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 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 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 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 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 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 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