xref: /original-bsd/sys/vax/vax/crl.c (revision 0fc6f013)
1 /*
2  * Copyright (c) 1982 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)crl.c	1.3 (Berkeley) 02/23/86
7  */
8 /*
9  * TO DO (tef  7/18/85):
10  *	1) change printf's to log() instead???
11  */
12 
13 #if VAX8600
14 #include "param.h"
15 #include "systm.h"
16 #include "conf.h"
17 #include "dir.h"
18 #include "user.h"
19 #include "buf.h"
20 #include "uio.h"
21 
22 #include "cons.h"
23 #include "cpu.h"
24 #include "crl.h"
25 #include "mtpr.h"
26 
27 struct {
28 	short	crl_state;		/* open and busy flags */
29 	short	crl_active;		/* driver state flag */
30 	struct	buf *crl_buf;		/* buffer we're using */
31 	ushort *crl_xaddr;		/* transfer address */
32 	short	crl_errcnt;
33 } crltab;
34 
35 struct {
36 	int	crl_cs;		/* saved controller status */
37 	int	crl_ds;		/* saved drive status */
38 } crlstat;
39 
40 /*ARGSUSED*/
41 crlopen(dev, flag)
42 	dev_t dev;
43 	int flag;
44 {
45 	struct buf *geteblk();
46 
47 	if (cpu != VAX_8600)
48 		return (ENXIO);
49 	if (crltab.crl_state != CRL_IDLE)
50 		return (EALREADY);
51 	crltab.crl_state = CRL_OPEN;
52 	crltab.crl_buf = geteblk(512);
53 	return (0);
54 }
55 
56 /*ARGSUSED*/
57 crlclose(dev, flag)
58 	dev_t dev;
59 	int flag;
60 {
61 
62 	brelse(crltab.crl_buf);
63 	crltab.crl_state = CRL_IDLE;
64 }
65 
66 crloperation(rw, uio)
67 	enum uio_rw rw;
68 	struct uio *uio;
69 {
70 	register struct buf *bp;
71 	register int i;
72 	register int s;
73 	int error;
74 
75 	if (uio->uio_resid == 0)
76 		return (0);
77 	s = spl4();
78 	while (crltab.crl_state & CRL_BUSY)
79 		sleep((caddr_t)&crltab, PRIBIO);
80 	crltab.crl_state |= CRL_BUSY;
81 	splx(s);
82 
83 	bp = crltab.crl_buf;
84 	error = 0;
85 	while ((i = imin(CRLBYSEC, uio->uio_resid)) > 0) {
86 		bp->b_blkno = uio->uio_offset>>9;
87 		if (bp->b_blkno >= MAXSEC || (uio->uio_offset & 0x1FF) != 0) {
88 			error = EIO;
89 			break;
90 		}
91 		if (rw == UIO_WRITE) {
92 			error = uiomove(bp->b_un.b_addr, i, UIO_WRITE, uio);
93 			if (error)
94 				break;
95 		}
96 		bp->b_flags = rw == UIO_WRITE ? B_WRITE : B_READ;
97 		s = spl4();
98 		crlstart();
99 		while ((bp->b_flags & B_DONE) == 0)
100 			sleep((caddr_t)bp, PRIBIO);
101 		splx(s);
102 		if (bp->b_flags & B_ERROR) {
103 			error = EIO;
104 			break;
105 		}
106 		if (rw == UIO_READ) {
107 			error = uiomove(bp->b_un.b_addr, i, UIO_READ, uio);
108 			if (error)
109 				break;
110 		}
111 	}
112 	crltab.crl_state &= ~CRL_BUSY;
113 	wakeup((caddr_t)&crltab);
114 	return (error);
115 }
116 
117 /*ARGSUSED*/
118 crlread(dev, uio)
119 	dev_t dev;
120 	struct uio *uio;
121 {
122 
123 	return (crloperation(UIO_READ, uio));
124 }
125 
126 /*ARGSUSED*/
127 crlwrite(dev, uio)
128 	dev_t dev;
129 	struct uio *uio;
130 {
131 
132 	return (crloperation(UIO_WRITE, uio));
133 }
134 
135 crlstart()
136 {
137 	register struct buf *bp;
138 
139 	bp = crltab.crl_buf;
140 	crltab.crl_errcnt = 0;
141 	crltab.crl_xaddr = (ushort *) bp->b_un.b_addr;
142 	bp->b_resid = 0;
143 
144 	if ((mfpr(STXCS) & STXCS_RDY) == 0)
145 		/* not ready to receive order */
146 		return;
147 	if ((bp->b_flags&(B_READ|B_WRITE)) == B_READ) {
148 		crltab.crl_active = CRL_F_READ;
149 		mtpr(STXCS, bp->b_blkno<<8 | STXCS_IE | CRL_F_READ);
150 	} else {
151 		crltab.crl_active = CRL_F_WRITE;
152 		mtpr(STXCS, bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE);
153 	}
154 #ifdef lint
155 	crlintr();
156 #endif
157 }
158 
159 crlintr()
160 {
161 	register struct buf *bp;
162 	int i;
163 
164 	bp = crltab.crl_buf;
165 	i = mfpr(STXCS);
166 	switch ((i>>24) & 0xFF) {
167 
168 	case CRL_S_XCMPLT:
169 		switch (crltab.crl_active) {
170 
171 		case CRL_F_RETSTS:
172 			crlstat.crl_ds = mfpr(STXDB);
173 			printf("crlcs=0x%b, crlds=0x%b\n", crlstat.crl_cs,
174 				CRLCS_BITS, crlstat.crl_ds, CRLDS_BITS);
175 			break;
176 
177 		case CRL_F_READ:
178 		case CRL_F_WRITE:
179 			bp->b_flags |= B_DONE;
180 		}
181 		crltab.crl_active = 0;
182 		wakeup((caddr_t)bp);
183 		break;
184 
185 	case CRL_S_XCONT:
186 		switch (crltab.crl_active) {
187 
188 		case CRL_F_WRITE:
189 			mtpr(STXDB, *crltab.crl_xaddr++);
190 			mtpr(STXCS, bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE);
191 			break;
192 
193 		case CRL_F_READ:
194 			*crltab.crl_xaddr++ = mfpr(STXDB);
195 			mtpr(STXCS, bp->b_blkno<<8 | STXCS_IE | CRL_F_READ);
196 		}
197 		break;
198 
199 	case CRL_S_ABORT:
200 		crltab.crl_active = CRL_F_RETSTS;
201 		mtpr(STXCS, STXCS_IE | CRL_F_RETSTS);
202 		bp->b_flags |= B_DONE|B_ERROR;
203 		break;
204 
205 	case CRL_S_RETSTS:
206 		crlstat.crl_cs = mfpr(STXDB);
207 		mtpr(STXCS, STXCS_IE | CRL_S_RETSTS);
208 		break;
209 
210 	case CRL_S_HNDSHK:
211 		printf("crl: hndshk error\n");	/* dump out some status too? */
212 		crltab.crl_active = 0;
213 		bp->b_flags |= B_DONE|B_ERROR;
214 		wakeup((caddr_t)bp);
215 		break;
216 
217 	case CRL_S_HWERR:
218 		printf("crl: hard error sn%d\n", bp->b_blkno);
219 		crltab.crl_active = CRL_F_ABORT;
220 		mtpr(STXCS, STXCS_IE | CRL_F_ABORT);
221 		break;
222 	}
223 }
224 #endif
225