xref: /csrg-svn/sys/vax/vax/rx50.c (revision 40912)
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  *
835045Skarels  * Redistribution and use in source and binary forms are permitted
935045Skarels  * provided that the above copyright notice and this paragraph are
1035045Skarels  * duplicated in all such forms and that any documentation,
1135045Skarels  * advertising materials, and other materials related to such
1235045Skarels  * distribution and use acknowledge that the software was developed
1335045Skarels  * by the University of California, Berkeley.  The name of the
1435045Skarels  * University may not be used to endorse or promote products derived
1535045Skarels  * from this software without specific prior written permission.
1635045Skarels  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1735045Skarels  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1835045Skarels  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1935045Skarels  *
20*40912Ssklower  *	@(#)rx50.c	7.3 (Berkeley) 04/12/90
2135045Skarels  */
2235045Skarels 
2335045Skarels #if VAX8200
2435045Skarels 
2535045Skarels /*
2635045Skarels  * Routines to handle the console RX50.
2735045Skarels  */
2835045Skarels 
2935045Skarels #include "param.h"
3035045Skarels #include "time.h"
3135045Skarels #include "kernel.h"
3235045Skarels #include "vmmac.h"
3335045Skarels #include "buf.h"
3435045Skarels #include "errno.h"
3535045Skarels #include "uio.h"
3635045Skarels 
3735045Skarels #include "cpu.h"
3835045Skarels #include "rx50reg.h"
3935045Skarels 
4035045Skarels struct	rx50device rx50device;
4135045Skarels 
4235045Skarels #define	rx50unit(dev)	minor(dev)
4335045Skarels 
4435045Skarels struct rx50state {
4535045Skarels 	short	rs_flags;	/* see below */
4635045Skarels 	short	rs_drive;	/* current drive number */
4735045Skarels 	u_int	rs_blkno;	/* current block number */
4835045Skarels } rx50state;
4935045Skarels 
5035045Skarels /* flags */
5135045Skarels #define	RS_0OPEN	0x01	/* drive 0 open -- must be first */
5235045Skarels #define	RS_1OPEN	0x02	/* drive 1 open -- must be second */
5335045Skarels #define	RS_BUSY		0x04	/* operation in progress */
5435045Skarels #define	RS_WANT		0x08	/* wakeup when done */
5535045Skarels #define	RS_DONE		0x20	/* I/O operation done */
5635045Skarels #define	RS_ERROR	0x40	/* error bit set at interrupt */
5735045Skarels 
5835045Skarels /*
5935045Skarels  * Open a console RX50.
6035045Skarels  */
6135045Skarels /*ARGSUSED*/
6235045Skarels rx50open(dev, flags)
6335045Skarels 	dev_t dev;
6435045Skarels 	int flags;
6535045Skarels {
6635045Skarels 	int unit;
6735045Skarels 
6835045Skarels 	/* only on 8200 (yet) */
6935045Skarels 	if (cpu != VAX_8200 || (unit = rx50unit(dev)) >= 2)
7035045Skarels 		return (ENXIO);
7135045Skarels 
7235045Skarels 	/* enforce exclusive access */
7335045Skarels 	if (rx50state.rs_flags & (1 << unit))
7435045Skarels 		return (EBUSY);
7535045Skarels 	rx50state.rs_flags |= 1 << unit;
7635045Skarels 	return (0);
7735045Skarels }
7835045Skarels 
7935045Skarels /*
8035045Skarels  * Close a console RX50.
8135045Skarels  */
8235045Skarels /*ARGSUSED*/
8335045Skarels rx50close(dev, flags)
8435045Skarels 	dev_t dev;
8535045Skarels 	int flags;
8635045Skarels {
8735045Skarels 
8835045Skarels 	rx50state.rs_flags &= ~(1 << dev);	/* atomic */
8935045Skarels }
9035045Skarels 
9135045Skarels /*
9237759Smckusick  * Perform a read (uio->uio_rw==UIO_READ) or write (uio->uio_rw==UIO_WRITE).
9335045Skarels  */
94*40912Ssklower rx50rw(dev, uio, flags)
9535045Skarels 	dev_t dev;
9635045Skarels 	register struct uio *uio;
9737759Smckusick 	int flags;
9835045Skarels {
9935045Skarels 	register struct rx50device *rxaddr;
10035045Skarels 	register struct rx50state *rs;
10135045Skarels 	register char *cp;
10235045Skarels 	register int error, i, t;
10335045Skarels 	char secbuf[512];
10435045Skarels 	static char driveselect[2] = { RXCMD_DRIVE0, RXCMD_DRIVE1 };
10535045Skarels 
10635045Skarels 	/* enforce whole-sector I/O */
10735045Skarels 	if ((uio->uio_offset & 511) || (uio->uio_resid & 511))
10835045Skarels 		return (EINVAL);
10935045Skarels 
11035045Skarels 	rs = &rx50state;
11135045Skarels 
11235045Skarels 	/* lock out others */
11335045Skarels 	i = spl4();
11435045Skarels 	while (rs->rs_flags & RS_BUSY) {
11535045Skarels 		rs->rs_flags |= RS_WANT;
11635045Skarels 		sleep((caddr_t) &rx50state, PZERO - 1);
11735045Skarels 	}
11835045Skarels 	rs->rs_flags |= RS_BUSY;
11935045Skarels 	rs->rs_drive = rx50unit(dev);
12035045Skarels 	splx(i);
12135045Skarels 
12235045Skarels 	rxaddr = &rx50device;
12335045Skarels 	error = 0;
12435045Skarels 
12535045Skarels 	while (uio->uio_resid) {
12635045Skarels 		rs->rs_blkno = uio->uio_offset >> 9;
12735045Skarels 		if (rs->rs_blkno >= RX50MAXSEC) {
12835045Skarels 			if (rs->rs_blkno > RX50MAXSEC)
12935045Skarels 				error = EINVAL;
13037759Smckusick 			else if (uio->uio_rw == UIO_WRITE)
13135045Skarels 				error = ENOSPC;
13235045Skarels 			/* else ``eof'' */
13335045Skarels 			break;
13435045Skarels 		}
13535045Skarels 		rs->rs_flags &= ~(RS_ERROR | RS_DONE);
13637759Smckusick 		if (uio->uio_rw == UIO_WRITE) {
13735045Skarels 			/* copy the data to the RX50 silo */
13837759Smckusick 			error = uiomove(secbuf, 512, uio);
13935045Skarels 			if (error)
14035045Skarels 				break;
14135045Skarels 			i = rxaddr->rxrda;
14235045Skarels 			for (cp = secbuf, i = 512; --i >= 0;)
14335045Skarels 				rxaddr->rxfdb = *cp++;
14435045Skarels 			i = RXCMD_WRITE;
14535045Skarels 		} else
14635045Skarels 			i = RXCMD_READ;
14735045Skarels 		rxaddr->rxcmd = i | driveselect[rs->rs_drive];
14835045Skarels 		i = rs->rs_blkno - ((t = rs->rs_blkno / RX50SEC) * RX50SEC);
14935045Skarels 		rxaddr->rxtrk = t == 79 ? 0 : t + 1;
15035045Skarels #ifdef notdef
15135045Skarels 		rxaddr->rxsec = "\1\3\5\7\11\1\3\5\7"[(2*t + i) % 5] + (i > 4);
15235045Skarels #else
15335045Skarels 		rxaddr->rxsec = RX50SKEW(i, t);
15435045Skarels #endif
15535045Skarels 		i = rxaddr->rxgo;	/* start it up */
15635045Skarels 		i = spl4();
15735045Skarels 		while ((rs->rs_flags & RS_DONE) == 0)
15835045Skarels 			sleep((caddr_t) &rs->rs_blkno, PRIBIO);
15935045Skarels 		splx(i);
16035045Skarels 		if (rs->rs_flags & RS_ERROR) {
16135045Skarels 			error = EIO;
16235045Skarels 			break;
16335045Skarels 		}
16437759Smckusick 		if (uio->uio_rw == UIO_READ) {
16535045Skarels 			/* copy the data out of the silo */
16635045Skarels 			i = rxaddr->rxrda;
16735045Skarels 			for (cp = secbuf, i = 512; --i >= 0;)
16835045Skarels 				*cp++ = rxaddr->rxedb;
16937759Smckusick 			error = uiomove(secbuf, 512, uio);
17035045Skarels 			if (error)
17135045Skarels 				break;
17235045Skarels 		}
17335045Skarels 	}
17435045Skarels 
17535045Skarels 	/* let others in */
17635045Skarels 	rs->rs_flags &= ~RS_BUSY;
17735045Skarels 	if (rs->rs_flags & RS_WANT)
17835045Skarels 		wakeup((caddr_t) rs);
17935045Skarels 
18035045Skarels 	return (error);
18135045Skarels }
18235045Skarels 
18335045Skarels rx50intr()
18435045Skarels {
18535045Skarels 	register struct rx50device *rxaddr = &rx50device;
18635045Skarels 	register struct rx50state *rs = &rx50state;
18735045Skarels 	int i;
18835045Skarels 
18935045Skarels #ifdef lint
19035045Skarels 	i = 0; i = i;
19135045Skarels #endif
19235045Skarels 
19335045Skarels 	/* ignore spurious interrupts */
19435045Skarels 	if ((rxaddr->rxcmd & RXCMD_DONE) == 0)
19535045Skarels 		return;
19635045Skarels 	if ((rs->rs_flags & RS_BUSY) == 0) {
19735045Skarels 		printf("stray rx50 interrupt ignored\n");
19835045Skarels 		return;
19935045Skarels 	}
20035045Skarels 	if (rxaddr->rxcmd & RXCMD_ERROR) {
20135045Skarels 		printf(
20235045Skarels 	"csa%d: hard error sn%d: cmd=%x trk=%x sec=%x csc=%x ict=%x ext=%x\n",
20335045Skarels 			rs->rs_drive + 1, rs->rs_blkno,
20435045Skarels 			rxaddr->rxcmd, rxaddr->rxtrk, rxaddr->rxsec,
20535045Skarels 			rxaddr->rxcsc, rxaddr->rxict, rxaddr->rxext);
20635045Skarels 		rxaddr->rxcmd = RXCMD_RESET;
20735045Skarels 		i = rxaddr->rxgo;
20835045Skarels 		rs->rs_flags |= RS_ERROR;
20935045Skarels 	}
21035045Skarels 	rs->rs_flags |= RS_DONE;
21135045Skarels 	wakeup((caddr_t) &rs->rs_blkno);
21235045Skarels }
21335045Skarels #endif
214