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