xref: /csrg-svn/sys/vax/vax/rx50.c (revision 45811)
135045Skarels /*
235045Skarels  * Copyright (c) 1988 Regents of the University of California.
335045Skarels  * All rights reserved.
435045Skarels  *
535045Skarels  * This code is derived from software contributed to Berkeley by
635045Skarels  * Chris Torek.
735045Skarels  *
844541Sbostic  * %sccs.include.redist.c%
935045Skarels  *
10*45811Sbostic  *	@(#)rx50.c	7.5 (Berkeley) 12/16/90
1135045Skarels  */
1235045Skarels 
1335045Skarels #if VAX8200
1435045Skarels 
1535045Skarels /*
1635045Skarels  * Routines to handle the console RX50.
1735045Skarels  */
1835045Skarels 
19*45811Sbostic #include "sys/param.h"
20*45811Sbostic #include "sys/time.h"
21*45811Sbostic #include "sys/kernel.h"
22*45811Sbostic #include "sys/vmmac.h"
23*45811Sbostic #include "sys/buf.h"
24*45811Sbostic #include "sys/errno.h"
25*45811Sbostic #include "sys/uio.h"
2635045Skarels 
27*45811Sbostic #include "../include/cpu.h"
2835045Skarels #include "rx50reg.h"
2935045Skarels 
3035045Skarels struct	rx50device rx50device;
3135045Skarels 
3235045Skarels #define	rx50unit(dev)	minor(dev)
3335045Skarels 
3435045Skarels struct rx50state {
3535045Skarels 	short	rs_flags;	/* see below */
3635045Skarels 	short	rs_drive;	/* current drive number */
3735045Skarels 	u_int	rs_blkno;	/* current block number */
3835045Skarels } rx50state;
3935045Skarels 
4035045Skarels /* flags */
4135045Skarels #define	RS_0OPEN	0x01	/* drive 0 open -- must be first */
4235045Skarels #define	RS_1OPEN	0x02	/* drive 1 open -- must be second */
4335045Skarels #define	RS_BUSY		0x04	/* operation in progress */
4435045Skarels #define	RS_WANT		0x08	/* wakeup when done */
4535045Skarels #define	RS_DONE		0x20	/* I/O operation done */
4635045Skarels #define	RS_ERROR	0x40	/* error bit set at interrupt */
4735045Skarels 
4835045Skarels /*
4935045Skarels  * Open a console RX50.
5035045Skarels  */
5135045Skarels /*ARGSUSED*/
rx50open(dev,flags)5235045Skarels rx50open(dev, flags)
5335045Skarels 	dev_t dev;
5435045Skarels 	int flags;
5535045Skarels {
5635045Skarels 	int unit;
5735045Skarels 
5835045Skarels 	/* only on 8200 (yet) */
5935045Skarels 	if (cpu != VAX_8200 || (unit = rx50unit(dev)) >= 2)
6035045Skarels 		return (ENXIO);
6135045Skarels 
6235045Skarels 	/* enforce exclusive access */
6335045Skarels 	if (rx50state.rs_flags & (1 << unit))
6435045Skarels 		return (EBUSY);
6535045Skarels 	rx50state.rs_flags |= 1 << unit;
6635045Skarels 	return (0);
6735045Skarels }
6835045Skarels 
6935045Skarels /*
7035045Skarels  * Close a console RX50.
7135045Skarels  */
7235045Skarels /*ARGSUSED*/
rx50close(dev,flags)7335045Skarels rx50close(dev, flags)
7435045Skarels 	dev_t dev;
7535045Skarels 	int flags;
7635045Skarels {
7735045Skarels 
7835045Skarels 	rx50state.rs_flags &= ~(1 << dev);	/* atomic */
7935045Skarels }
8035045Skarels 
8135045Skarels /*
8237759Smckusick  * Perform a read (uio->uio_rw==UIO_READ) or write (uio->uio_rw==UIO_WRITE).
8335045Skarels  */
rx50rw(dev,uio,flags)8440912Ssklower rx50rw(dev, uio, flags)
8535045Skarels 	dev_t dev;
8635045Skarels 	register struct uio *uio;
8737759Smckusick 	int flags;
8835045Skarels {
8935045Skarels 	register struct rx50device *rxaddr;
9035045Skarels 	register struct rx50state *rs;
9135045Skarels 	register char *cp;
9235045Skarels 	register int error, i, t;
9335045Skarels 	char secbuf[512];
9435045Skarels 	static char driveselect[2] = { RXCMD_DRIVE0, RXCMD_DRIVE1 };
9535045Skarels 
9635045Skarels 	/* enforce whole-sector I/O */
9735045Skarels 	if ((uio->uio_offset & 511) || (uio->uio_resid & 511))
9835045Skarels 		return (EINVAL);
9935045Skarels 
10035045Skarels 	rs = &rx50state;
10135045Skarels 
10235045Skarels 	/* lock out others */
10335045Skarels 	i = spl4();
10435045Skarels 	while (rs->rs_flags & RS_BUSY) {
10535045Skarels 		rs->rs_flags |= RS_WANT;
10635045Skarels 		sleep((caddr_t) &rx50state, PZERO - 1);
10735045Skarels 	}
10835045Skarels 	rs->rs_flags |= RS_BUSY;
10935045Skarels 	rs->rs_drive = rx50unit(dev);
11035045Skarels 	splx(i);
11135045Skarels 
11235045Skarels 	rxaddr = &rx50device;
11335045Skarels 	error = 0;
11435045Skarels 
11535045Skarels 	while (uio->uio_resid) {
11635045Skarels 		rs->rs_blkno = uio->uio_offset >> 9;
11735045Skarels 		if (rs->rs_blkno >= RX50MAXSEC) {
11835045Skarels 			if (rs->rs_blkno > RX50MAXSEC)
11935045Skarels 				error = EINVAL;
12037759Smckusick 			else if (uio->uio_rw == UIO_WRITE)
12135045Skarels 				error = ENOSPC;
12235045Skarels 			/* else ``eof'' */
12335045Skarels 			break;
12435045Skarels 		}
12535045Skarels 		rs->rs_flags &= ~(RS_ERROR | RS_DONE);
12637759Smckusick 		if (uio->uio_rw == UIO_WRITE) {
12735045Skarels 			/* copy the data to the RX50 silo */
12837759Smckusick 			error = uiomove(secbuf, 512, uio);
12935045Skarels 			if (error)
13035045Skarels 				break;
13135045Skarels 			i = rxaddr->rxrda;
13235045Skarels 			for (cp = secbuf, i = 512; --i >= 0;)
13335045Skarels 				rxaddr->rxfdb = *cp++;
13435045Skarels 			i = RXCMD_WRITE;
13535045Skarels 		} else
13635045Skarels 			i = RXCMD_READ;
13735045Skarels 		rxaddr->rxcmd = i | driveselect[rs->rs_drive];
13835045Skarels 		i = rs->rs_blkno - ((t = rs->rs_blkno / RX50SEC) * RX50SEC);
13935045Skarels 		rxaddr->rxtrk = t == 79 ? 0 : t + 1;
14035045Skarels #ifdef notdef
14135045Skarels 		rxaddr->rxsec = "\1\3\5\7\11\1\3\5\7"[(2*t + i) % 5] + (i > 4);
14235045Skarels #else
14335045Skarels 		rxaddr->rxsec = RX50SKEW(i, t);
14435045Skarels #endif
14535045Skarels 		i = rxaddr->rxgo;	/* start it up */
14635045Skarels 		i = spl4();
14735045Skarels 		while ((rs->rs_flags & RS_DONE) == 0)
14835045Skarels 			sleep((caddr_t) &rs->rs_blkno, PRIBIO);
14935045Skarels 		splx(i);
15035045Skarels 		if (rs->rs_flags & RS_ERROR) {
15135045Skarels 			error = EIO;
15235045Skarels 			break;
15335045Skarels 		}
15437759Smckusick 		if (uio->uio_rw == UIO_READ) {
15535045Skarels 			/* copy the data out of the silo */
15635045Skarels 			i = rxaddr->rxrda;
15735045Skarels 			for (cp = secbuf, i = 512; --i >= 0;)
15835045Skarels 				*cp++ = rxaddr->rxedb;
15937759Smckusick 			error = uiomove(secbuf, 512, uio);
16035045Skarels 			if (error)
16135045Skarels 				break;
16235045Skarels 		}
16335045Skarels 	}
16435045Skarels 
16535045Skarels 	/* let others in */
16635045Skarels 	rs->rs_flags &= ~RS_BUSY;
16735045Skarels 	if (rs->rs_flags & RS_WANT)
16835045Skarels 		wakeup((caddr_t) rs);
16935045Skarels 
17035045Skarels 	return (error);
17135045Skarels }
17235045Skarels 
rx50intr()17335045Skarels rx50intr()
17435045Skarels {
17535045Skarels 	register struct rx50device *rxaddr = &rx50device;
17635045Skarels 	register struct rx50state *rs = &rx50state;
17735045Skarels 	int i;
17835045Skarels 
17935045Skarels #ifdef lint
18035045Skarels 	i = 0; i = i;
18135045Skarels #endif
18235045Skarels 
18335045Skarels 	/* ignore spurious interrupts */
18435045Skarels 	if ((rxaddr->rxcmd & RXCMD_DONE) == 0)
18535045Skarels 		return;
18635045Skarels 	if ((rs->rs_flags & RS_BUSY) == 0) {
18735045Skarels 		printf("stray rx50 interrupt ignored\n");
18835045Skarels 		return;
18935045Skarels 	}
19035045Skarels 	if (rxaddr->rxcmd & RXCMD_ERROR) {
19135045Skarels 		printf(
19235045Skarels 	"csa%d: hard error sn%d: cmd=%x trk=%x sec=%x csc=%x ict=%x ext=%x\n",
19335045Skarels 			rs->rs_drive + 1, rs->rs_blkno,
19435045Skarels 			rxaddr->rxcmd, rxaddr->rxtrk, rxaddr->rxsec,
19535045Skarels 			rxaddr->rxcsc, rxaddr->rxict, rxaddr->rxext);
19635045Skarels 		rxaddr->rxcmd = RXCMD_RESET;
19735045Skarels 		i = rxaddr->rxgo;
19835045Skarels 		rs->rs_flags |= RS_ERROR;
19935045Skarels 	}
20035045Skarels 	rs->rs_flags |= RS_DONE;
20135045Skarels 	wakeup((caddr_t) &rs->rs_blkno);
20235045Skarels }
20335045Skarels #endif
204