xref: /original-bsd/sys/vax/vax/crl.c (revision 42c7e7a1)
1 /*-
2  * Copyright (c) 1982, 1986 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)crl.c	7.5 (Berkeley) 05/09/91
8  */
9 
10 /*
11  * TO DO (tef  7/18/85):
12  *	1) change printf's to log() instead???
13  */
14 
15 #if VAX8600
16 #include "sys/param.h"
17 #include "sys/systm.h"
18 #include "sys/conf.h"
19 #include "sys/user.h"
20 #include "sys/buf.h"
21 
22 #include "cons.h"
23 #include "../include/cpu.h"
24 #include "crl.h"
25 #include "../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 /*ARGSUSED*/
67 crlrw(dev, uio, flag)
68 	dev_t dev;
69 	struct uio *uio;
70 	int flag;
71 {
72 	register struct buf *bp;
73 	register int i;
74 	register int s;
75 	int error;
76 
77 	if (uio->uio_resid == 0)
78 		return (0);
79 	s = spl4();
80 	while (crltab.crl_state & CRL_BUSY)
81 		sleep((caddr_t)&crltab, PRIBIO);
82 	crltab.crl_state |= CRL_BUSY;
83 	splx(s);
84 
85 	bp = crltab.crl_buf;
86 	error = 0;
87 	while ((i = imin(CRLBYSEC, uio->uio_resid)) > 0) {
88 		bp->b_blkno = uio->uio_offset>>9;
89 		if (bp->b_blkno >= MAXSEC || (uio->uio_offset & 0x1FF) != 0) {
90 			error = EIO;
91 			break;
92 		}
93 		if (uio->uio_rw == UIO_WRITE) {
94 			error = uiomove(bp->b_un.b_addr, i, uio);
95 			if (error)
96 				break;
97 		}
98 		bp->b_flags = uio->uio_rw == UIO_WRITE ? B_WRITE : B_READ;
99 		s = spl4();
100 		crlstart();
101 		while ((bp->b_flags & B_DONE) == 0)
102 			sleep((caddr_t)bp, PRIBIO);
103 		splx(s);
104 		if (bp->b_flags & B_ERROR) {
105 			error = EIO;
106 			break;
107 		}
108 		if (uio->uio_rw == UIO_READ) {
109 			error = uiomove(bp->b_un.b_addr, i, uio);
110 			if (error)
111 				break;
112 		}
113 	}
114 	crltab.crl_state &= ~CRL_BUSY;
115 	wakeup((caddr_t)&crltab);
116 	return (error);
117 }
118 
119 crlstart()
120 {
121 	register struct buf *bp;
122 
123 	bp = crltab.crl_buf;
124 	crltab.crl_errcnt = 0;
125 	crltab.crl_xaddr = (ushort *) bp->b_un.b_addr;
126 	bp->b_resid = 0;
127 
128 	if ((mfpr(STXCS) & STXCS_RDY) == 0)
129 		/* not ready to receive order */
130 		return;
131 	if ((bp->b_flags&(B_READ|B_WRITE)) == B_READ) {
132 		crltab.crl_active = CRL_F_READ;
133 		mtpr(STXCS, bp->b_blkno<<8 | STXCS_IE | CRL_F_READ);
134 	} else {
135 		crltab.crl_active = CRL_F_WRITE;
136 		mtpr(STXCS, bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE);
137 	}
138 #ifdef lint
139 	crlintr();
140 #endif
141 }
142 
143 crlintr()
144 {
145 	register struct buf *bp;
146 	int i;
147 
148 	bp = crltab.crl_buf;
149 	i = mfpr(STXCS);
150 	switch ((i>>24) & 0xFF) {
151 
152 	case CRL_S_XCMPLT:
153 		switch (crltab.crl_active) {
154 
155 		case CRL_F_RETSTS:
156 			crlstat.crl_ds = mfpr(STXDB);
157 			printf("crlcs=0x%b, crlds=0x%b\n", crlstat.crl_cs,
158 				CRLCS_BITS, crlstat.crl_ds, CRLDS_BITS);
159 			break;
160 
161 		case CRL_F_READ:
162 		case CRL_F_WRITE:
163 			bp->b_flags |= B_DONE;
164 		}
165 		crltab.crl_active = 0;
166 		wakeup((caddr_t)bp);
167 		break;
168 
169 	case CRL_S_XCONT:
170 		switch (crltab.crl_active) {
171 
172 		case CRL_F_WRITE:
173 			mtpr(STXDB, *crltab.crl_xaddr++);
174 			mtpr(STXCS, bp->b_blkno<<8 | STXCS_IE | CRL_F_WRITE);
175 			break;
176 
177 		case CRL_F_READ:
178 			*crltab.crl_xaddr++ = mfpr(STXDB);
179 			mtpr(STXCS, bp->b_blkno<<8 | STXCS_IE | CRL_F_READ);
180 		}
181 		break;
182 
183 	case CRL_S_ABORT:
184 		crltab.crl_active = CRL_F_RETSTS;
185 		mtpr(STXCS, STXCS_IE | CRL_F_RETSTS);
186 		bp->b_flags |= B_DONE|B_ERROR;
187 		break;
188 
189 	case CRL_S_RETSTS:
190 		crlstat.crl_cs = mfpr(STXDB);
191 		mtpr(STXCS, STXCS_IE | CRL_S_RETSTS);
192 		break;
193 
194 	case CRL_S_HNDSHK:
195 		printf("crl: hndshk error\n");	/* dump out some status too? */
196 		crltab.crl_active = 0;
197 		bp->b_flags |= B_DONE|B_ERROR;
198 		wakeup((caddr_t)bp);
199 		break;
200 
201 	case CRL_S_HWERR:
202 		printf("crl: hard error sn%d\n", bp->b_blkno);
203 		crltab.crl_active = CRL_F_ABORT;
204 		mtpr(STXCS, STXCS_IE | CRL_F_ABORT);
205 		break;
206 	}
207 }
208 #endif
209