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