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*/
crlopen(dev,flag)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*/
crlclose(dev,flag)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*/
crlrw(dev,uio,flag)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
crlstart()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
crlintr()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