1 /* $NetBSD: cfl.c,v 1.24 2017/05/22 16:39:40 ragge Exp $ */
2 /*-
3 * Copyright (c) 1982, 1986 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * @(#)crl.c 7.5 (Berkeley) 5/9/91
31 */
32
33 /*-
34 * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
57 * @(#)crl.c 7.5 (Berkeley) 5/9/91
58 */
59
60 /*
61 * Console floppy driver for 11/780.
62 * XXX - Does not work. (Not completed)
63 * Included here if someone wants to finish it.
64 */
65
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(0, "$NetBSD: cfl.c,v 1.24 2017/05/22 16:39:40 ragge Exp $");
68
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/conf.h>
72 #include <sys/cpu.h>
73 #include <sys/proc.h>
74 #include <sys/buf.h>
75
76 #include <machine/sid.h>
77 #include <machine/scb.h>
78
79 #include <vax/vax/gencons.h>
80
81 #define CFL_TRACKS 77
82 #define CFL_SECTORS 26
83 #define CFL_BYTESPERSEC 128
84 #define CFL_MAXSEC (CFL_TRACKS * CFL_SECTORS)
85
86 #define FLOP_READSECT 0x900
87 #define FLOP_WRITSECT 0x901
88 #define FLOP_DATA 0x100
89 #define FLOP_COMPLETE 0x200
90
91 struct {
92 short cfl_state; /* open and busy flags */
93 short cfl_active; /* driver state flag */
94 struct buf *cfl_buf; /* buffer we're using */
95 unsigned char *cfl_xaddr; /* transfer address */
96 short cfl_errcnt;
97 } cfltab;
98
99 #define IDLE 0
100 #define OPEN 1
101 #define BUSY 2
102
103 #define CFL_IDLE 0
104 #define CFL_START 1
105 #define CFL_SECTOR 2
106 #define CFL_DATA 3
107 #define CFL_TRACK 4
108 #define CFL_NEXT 5
109 #define CFL_FINISH 6
110 #define CFL_GETIN 7
111
112 static void cflstart(void);
113
114 static dev_type_open(cflopen);
115 static dev_type_close(cflclose);
116 static dev_type_read(cflrw);
117
118 const struct cdevsw cfl_cdevsw = {
119 .d_open = cflopen,
120 .d_close = cflclose,
121 .d_read = cflrw,
122 .d_write = cflrw,
123 .d_ioctl = noioctl,
124 .d_stop = nostop,
125 .d_tty = notty,
126 .d_poll = nopoll,
127 .d_mmap = nommap,
128 .d_kqfilter = nokqfilter,
129 .d_discard = nodiscard,
130 .d_flag = 0
131 };
132
133 /*ARGSUSED*/
134 int
cflopen(dev_t dev,int flag,int mode,struct lwp * l)135 cflopen(dev_t dev, int flag, int mode, struct lwp *l)
136 {
137 if (vax_cputype != VAX_780)
138 return (ENXIO);
139 if (cfltab.cfl_state != IDLE)
140 return (EALREADY);
141 cfltab.cfl_state = OPEN;
142 cfltab.cfl_buf = geteblk(512);
143 return (0);
144 }
145
146 /*ARGSUSED*/
147 int
cflclose(dev_t dev,int flag,int mode,struct lwp * l)148 cflclose(dev_t dev, int flag, int mode, struct lwp *l)
149 {
150 int s;
151 s = splbio();
152 brelse(cfltab.cfl_buf, 0);
153 splx(s);
154 cfltab.cfl_state = IDLE;
155 return 0;
156 }
157
158 /*ARGSUSED*/
159 int
cflrw(dev_t dev,struct uio * uio,int flag)160 cflrw(dev_t dev, struct uio *uio, int flag)
161 {
162 struct buf *bp;
163 int i;
164 int s;
165 int error;
166
167 if (uio->uio_resid == 0)
168 return (0);
169 s = splconsmedia();
170 while (cfltab.cfl_state == BUSY)
171 (void) tsleep(&cfltab, PRIBIO, "cflbusy", 0);
172 cfltab.cfl_state = BUSY;
173 splx(s);
174
175 bp = cfltab.cfl_buf;
176 error = 0;
177 while ((i = imin(CFL_BYTESPERSEC, uio->uio_resid)) > 0) {
178 bp->b_blkno = uio->uio_offset>>7;
179 if (bp->b_blkno >= CFL_MAXSEC ||
180 (uio->uio_offset & 0x7F) != 0) {
181 error = EIO;
182 break;
183 }
184 if (uio->uio_rw == UIO_WRITE) {
185 error = uiomove(bp->b_data, i, uio);
186 if (error)
187 break;
188 }
189 if (uio->uio_rw == UIO_WRITE) {
190 bp->b_oflags &= ~(BO_DONE);
191 bp->b_flags &= ~(B_READ);
192 bp->b_flags |= B_WRITE;
193 } else {
194 bp->b_oflags &= ~(BO_DONE);
195 bp->b_flags &= ~(B_WRITE);
196 bp->b_flags |= B_READ;
197 }
198 s = splconsmedia();
199 cflstart();
200 biowait(bp);
201 splx(s);
202 if (bp->b_error != 0) {
203 error = bp->b_error;
204 break;
205 }
206 if (uio->uio_rw == UIO_READ) {
207 error = uiomove(bp->b_data, i, uio);
208 if (error)
209 break;
210 }
211 }
212 cfltab.cfl_state = OPEN;
213 wakeup((void *)&cfltab);
214 return (error);
215 }
216
217 void
cflstart(void)218 cflstart(void)
219 {
220 struct buf *bp;
221
222 bp = cfltab.cfl_buf;
223 cfltab.cfl_errcnt = 0;
224 cfltab.cfl_xaddr = (unsigned char *) bp->b_data;
225 cfltab.cfl_active = CFL_START;
226 bp->b_resid = 0;
227
228 if ((mfpr(PR_TXCS) & GC_RDY) == 0)
229 /* not ready to receive order */
230 return;
231
232 cfltab.cfl_active = CFL_SECTOR;
233 mtpr(bp->b_flags & B_READ ? FLOP_READSECT : FLOP_WRITSECT, PR_TXDB);
234
235 #ifdef lint
236 cflintr();
237 #endif
238 }
239
240 void cfltint(int);
241
242 void
cfltint(int arg)243 cfltint(int arg)
244 {
245 struct buf *bp = cfltab.cfl_buf;
246
247 switch (cfltab.cfl_active) {
248 case CFL_START:/* do a read */
249 mtpr(bp->b_flags & B_READ ? FLOP_READSECT : FLOP_WRITSECT,
250 PR_TXDB);
251 cfltab.cfl_active = CFL_SECTOR;
252 break;
253
254 case CFL_SECTOR:/* send sector */
255 mtpr(FLOP_DATA | (int)bp->b_blkno % (CFL_SECTORS + 1), PR_TXDB);
256 cfltab.cfl_active = CFL_TRACK;
257 break;
258
259 case CFL_TRACK:
260 mtpr(FLOP_DATA | (int)bp->b_blkno / CFL_SECTORS, PR_TXDB);
261 cfltab.cfl_active = CFL_NEXT;
262 break;
263
264 case CFL_NEXT:
265 mtpr(FLOP_DATA | *cfltab.cfl_xaddr++, PR_TXDB);
266 if (--bp->b_bcount == 0)
267 cfltab.cfl_active = CFL_FINISH;
268 break;
269
270 }
271 }
272
273 void cflrint(int);
274
275 void
cflrint(int ch)276 cflrint(int ch)
277 {
278 struct buf *bp = cfltab.cfl_buf;
279
280 switch (cfltab.cfl_active) {
281 case CFL_NEXT:
282 if ((bp->b_flags & B_READ) == B_READ)
283 cfltab.cfl_active = CFL_GETIN;
284 else {
285 cfltab.cfl_active = CFL_IDLE;
286 mutex_enter(bp->b_objlock);
287 bp->b_oflags |= BO_DONE;
288 cv_broadcast(&bp->b_done);
289 mutex_exit(bp->b_objlock);
290 }
291 break;
292
293 case CFL_GETIN:
294 *cfltab.cfl_xaddr++ = ch & 0377;
295 if (--bp->b_bcount==0) {
296 cfltab.cfl_active = CFL_IDLE;
297 mutex_enter(bp->b_objlock);
298 bp->b_oflags |= BO_DONE;
299 cv_broadcast(&bp->b_done);
300 mutex_exit(bp->b_objlock);
301 }
302 break;
303 }
304 }
305