1 /* $NetBSD: cfl.c,v 1.9 2002/10/23 09:12:36 jdolecek 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 dev_type_open(cflopen); 92 dev_type_close(cflclose); 93 dev_type_read(cflrw); 94 95 const struct cdevsw cfl_cdevsw = { 96 cflopen, cflclose, cflrw, cflrw, noioctl, 97 nostop, notty, nopoll, nommap, nokqfilter, 98 }; 99 100 /*ARGSUSED*/ 101 int 102 cflopen(dev, flag, mode, p) 103 dev_t dev; 104 int flag, mode; 105 struct proc *p; 106 { 107 if (vax_cputype != VAX_780) 108 return (ENXIO); 109 if (cfltab.cfl_state != IDLE) 110 return (EALREADY); 111 cfltab.cfl_state = OPEN; 112 cfltab.cfl_buf = geteblk(512); 113 return (0); 114 } 115 116 /*ARGSUSED*/ 117 int 118 cflclose(dev, flag, mode, p) 119 dev_t dev; 120 int flag, mode; 121 struct proc *p; 122 { 123 int s; 124 s = splbio(); 125 brelse(cfltab.cfl_buf); 126 splx(s); 127 cfltab.cfl_state = IDLE; 128 return 0; 129 } 130 131 /*ARGSUSED*/ 132 int 133 cflrw(dev, uio, flag) 134 dev_t dev; 135 struct uio *uio; 136 int flag; 137 { 138 register struct buf *bp; 139 register int i; 140 register int s; 141 int error; 142 143 if (uio->uio_resid == 0) 144 return (0); 145 s = splconsmedia(); 146 while (cfltab.cfl_state == BUSY) 147 (void) tsleep(&cfltab, PRIBIO, "cflbusy", 0); 148 cfltab.cfl_state = BUSY; 149 splx(s); 150 151 bp = cfltab.cfl_buf; 152 error = 0; 153 while ((i = imin(CFL_BYTESPERSEC, uio->uio_resid)) > 0) { 154 bp->b_blkno = uio->uio_offset>>7; 155 if (bp->b_blkno >= CFL_MAXSEC || 156 (uio->uio_offset & 0x7F) != 0) { 157 error = EIO; 158 break; 159 } 160 if (uio->uio_rw == UIO_WRITE) { 161 error = uiomove(bp->b_data, i, uio); 162 if (error) 163 break; 164 } 165 if (uio->uio_rw == UIO_WRITE) { 166 bp->b_flags &= ~(B_READ|B_DONE); 167 bp->b_flags |= B_WRITE; 168 } else { 169 bp->b_flags &= ~(B_WRITE|B_DONE); 170 bp->b_flags |= B_READ; 171 } 172 s = splconsmedia(); 173 cflstart(); 174 while ((bp->b_flags & B_DONE) == 0) 175 (void) tsleep(bp, PRIBIO, "cflrw", 0); 176 splx(s); 177 if (bp->b_flags & B_ERROR) { 178 error = EIO; 179 break; 180 } 181 if (uio->uio_rw == UIO_READ) { 182 error = uiomove(bp->b_data, i, uio); 183 if (error) 184 break; 185 } 186 } 187 cfltab.cfl_state = OPEN; 188 wakeup((caddr_t)&cfltab); 189 return (error); 190 } 191 192 void 193 cflstart() 194 { 195 register struct buf *bp; 196 197 bp = cfltab.cfl_buf; 198 cfltab.cfl_errcnt = 0; 199 cfltab.cfl_xaddr = (unsigned char *) bp->b_data; 200 cfltab.cfl_active = CFL_START; 201 bp->b_resid = 0; 202 203 if ((mfpr(PR_TXCS) & GC_RDY) == 0) 204 /* not ready to receive order */ 205 return; 206 207 cfltab.cfl_active = CFL_SECTOR; 208 mtpr(bp->b_flags & B_READ ? FLOP_READSECT : FLOP_WRITSECT, PR_TXDB); 209 210 #ifdef lint 211 cflintr(); 212 #endif 213 } 214 215 void cfltint __P((int)); 216 217 void 218 cfltint(arg) 219 int arg; 220 { 221 register struct buf *bp = cfltab.cfl_buf; 222 223 switch (cfltab.cfl_active) { 224 case CFL_START:/* do a read */ 225 mtpr(bp->b_flags & B_READ ? FLOP_READSECT : FLOP_WRITSECT, 226 PR_TXDB); 227 cfltab.cfl_active = CFL_SECTOR; 228 break; 229 230 case CFL_SECTOR:/* send sector */ 231 mtpr(FLOP_DATA | (int)bp->b_blkno % (CFL_SECTORS + 1), PR_TXDB); 232 cfltab.cfl_active = CFL_TRACK; 233 break; 234 235 case CFL_TRACK: 236 mtpr(FLOP_DATA | (int)bp->b_blkno / CFL_SECTORS, PR_TXDB); 237 cfltab.cfl_active = CFL_NEXT; 238 break; 239 240 case CFL_NEXT: 241 mtpr(FLOP_DATA | *cfltab.cfl_xaddr++, PR_TXDB); 242 if (--bp->b_bcount == 0) 243 cfltab.cfl_active = CFL_FINISH; 244 break; 245 246 } 247 } 248 249 void cflrint __P((int)); 250 251 void 252 cflrint(int ch) 253 { 254 struct buf *bp = cfltab.cfl_buf; 255 int s; 256 257 switch (cfltab.cfl_active) { 258 case CFL_NEXT: 259 if ((bp->b_flags & B_READ) == B_READ) 260 cfltab.cfl_active = CFL_GETIN; 261 else { 262 cfltab.cfl_active = CFL_IDLE; 263 s = splbio(); 264 bp->b_flags |= B_DONE; 265 splx(s); 266 wakeup(bp); 267 } 268 break; 269 270 case CFL_GETIN: 271 *cfltab.cfl_xaddr++ = ch & 0377; 272 if (--bp->b_bcount==0) { 273 cfltab.cfl_active = CFL_IDLE; 274 s = splbio(); 275 bp->b_flags |= B_DONE; 276 splx(s); 277 wakeup(bp); 278 } 279 break; 280 } 281 } 282