|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)flp.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #if VAX780
10: #include "param.h"
11: #include "systm.h"
12: #include "conf.h"
13: #include "dir.h"
14: #include "user.h"
15: #include "buf.h"
16: #include "uio.h"
17:
18: #include "cons.h"
19: #include "cpu.h"
20: #include "flp.h"
21: #include "mtpr.h"
22:
23: struct {
24: short fl_state; /* open and busy flags */
25: short fl_active; /* driver state flag */
26: struct buf *fl_buf; /* buffer we're using */
27: unsigned char *fl_xaddr; /* transfer address */
28: short fl_errcnt;
29: } fltab;
30:
31: /*ARGSUSED*/
32: flopen(dev, flag)
33: dev_t dev;
34: int flag;
35: {
36: struct buf *geteblk();
37:
38: if (cpu != VAX_780)
39: return (ENXIO);
40: if (fltab.fl_state != 0)
41: return (ENXIO);
42: fltab.fl_state = FL_OPEN;
43: fltab.fl_buf = geteblk(512);
44: fltab.fl_active = FL_IDLE;
45: return (0);
46: }
47:
48: /*ARGSUSED*/
49: flclose(dev, flag)
50: dev_t dev;
51: int flag;
52: {
53:
54: brelse(fltab.fl_buf);
55: fltab.fl_state = 0;
56: }
57:
58: floperation(rw, uio)
59: enum uio_rw rw;
60: struct uio *uio;
61: {
62: register struct buf *bp;
63: register int i;
64: int error;
65:
66: /*
67: * Assume one block read/written for each call -
68: * and enforce this by checking for block size of 128.
69: * Use the b_blkno field to address
70: * physical, 128-byte blocks (u.u_offset/128).
71: * This is checked for validity, and is further interpreted as:
72: *
73: * track# * (sectors/track) + sector #
74: */
75: if (uio->uio_resid == 0)
76: return (0);
77: (void) spl4();
78: while (fltab.fl_state & FL_BUSY)
79: sleep((caddr_t)&fltab, PRIBIO);
80: fltab.fl_state |= FL_BUSY;
81: (void) spl0();
82:
83: bp = fltab.fl_buf;
84: error = 0;
85: while ((i = imin(RXBYSEC, uio->uio_resid)) > 0) {
86: bp->b_blkno = uio->uio_offset>>7;
87: if (bp->b_blkno >= MAXSEC || (uio->uio_offset & 0177) != 0) {
88: error = ENXIO;
89: break;
90: }
91: if (rw == UIO_WRITE) {
92: error = uiomove(bp->b_un.b_addr, i, UIO_WRITE, uio);
93: if (error)
94: break;
95: }
96: bp->b_flags = rw == UIO_WRITE ? B_WRITE : B_READ;
97: (void) spl4();
98: flstart();
99: while ((bp->b_flags & B_DONE) == 0)
100: sleep((caddr_t)bp, PRIBIO);
101: (void) spl0();
102: if (bp->b_flags & B_ERROR) {
103: error = EIO;
104: break;
105: }
106: if (rw == UIO_READ) {
107: error = uiomove(bp->b_un.b_addr, i, UIO_READ, uio);
108: if (error)
109: break;
110: }
111: }
112: fltab.fl_state &= ~FL_BUSY;
113: wakeup((caddr_t)&fltab);
114: return (error);
115: }
116:
117: /*ARGSUSED*/
118: flread(dev, uio)
119: dev_t dev;
120: struct uio *uio;
121: {
122:
123: return (floperation(UIO_READ, uio));
124: }
125:
126: /*ARGSUSED*/
127: flwrite(dev, uio)
128: dev_t dev;
129: struct uio *uio;
130: {
131:
132: return (floperation(UIO_WRITE, uio));
133: }
134:
135: flstart()
136: {
137: register struct buf *bp;
138:
139: bp = fltab.fl_buf;
140: fltab.fl_active = FL_MAND;
141: fltab.fl_errcnt = 0;
142: fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr;
143: bp->b_resid = 0;
144: bp->b_bcount = RXBYSEC; /* always transfer a full sector */
145:
146: if ((mfpr(TXCS) & TXCS_RDY) == 0)
147: /* not ready to receive order */
148: return;
149: /*
150: * Wake up floppy LSI software with command
151: */
152: fltab.fl_active = FL_SEC;
153: if ((bp->b_flags&B_READ) == B_READ)
154: mtpr(TXDB, FL_RS);
155: else
156: mtpr(TXDB, FL_WS);
157: }
158:
159: /*
160: * See if we want to transmit something
161: * to the floppy - and do it
162: */
163: conxfl()
164: {
165: register int databyte;
166: register struct buf *bp;
167:
168: bp = fltab.fl_buf;
169: switch (fltab.fl_active) {
170:
171: case FL_MAND: /* send command */
172: if ((bp->b_flags&B_READ) == B_READ)
173: mtpr(TXDB,FL_RS);
174: else
175: mtpr(TXDB, FL_WS);
176: fltab.fl_active = FL_SEC;
177: break;
178:
179: case FL_SEC: /* send sector address */
180: databyte = (int)bp->b_blkno % RXSTRK + 1;
181: mtpr(TXDB, FL_DATA | databyte);
182: fltab.fl_active = FL_TRACK;
183: break;
184:
185: case FL_TRACK: /* send track address */
186: databyte = (int)bp->b_blkno / RXSTRK;
187: mtpr(TXDB , FL_DATA | databyte);
188: if ((bp->b_flags&B_READ) == B_READ)
189: /* prepare to receive complete */
190: fltab.fl_active = FL_COM;
191: else
192: /* prepare to send data */
193: fltab.fl_active = FL_DAX;
194: break;
195:
196: case FL_DAX:
197: databyte = *(fltab.fl_xaddr++);
198: mtpr(TXDB, FL_DATA | databyte);
199: if (--bp->b_bcount == 0)
200: fltab.fl_active = FL_COM;
201: break;
202:
203: case FL_CAN: /* give cancel order */
204: mtpr(TXDB, FL_CANCEL);
205: if (++fltab.fl_errcnt <= FLERRS) {
206: /* If error count permits, retry order */
207: fltab.fl_active = FL_MAND;
208: bp->b_bcount = RXBYSEC;
209: fltab.fl_xaddr = (unsigned char *) bp->b_un.b_addr;
210: } else {
211: /*
212: * We're really stupid today - call it an
213: * error and give up
214: */
215: bp->b_flags |= B_ERROR | B_DONE;
216: bp->b_resid = -RXBYSEC;
217: fltab.fl_active = FL_IDLE;
218: wakeup((caddr_t)bp);
219: }
220: }
221: }
222:
223: cnrfl(c)
224: int c;
225: {
226: register int datum;
227: register struct buf *bp;
228:
229: datum = c;
230: bp = fltab.fl_buf;
231: if (datum == FL_PERR) {
232: /*
233: * Got a protocol error - cancel the
234: * current function and try again if error count isn't
235: * too great. First, though, make sure that an actual
236: * transaction is in progress (so a spurious error from
237: * the LSI won't screw us up too much!
238: */
239: if (fltab.fl_active != FL_IDLE)
240: fltab.fl_active = FL_CAN;
241: } else switch(fltab.fl_active ) {
242:
243: case FL_DAR: /* expecting a datum */
244: if ((c&RXDB_ID) != FL_DATA)
245: goto error;
246: *(fltab.fl_xaddr++) = (c & RXDB_DATA);
247: if (--bp->b_bcount==0) {
248: fltab.fl_active = FL_IDLE;
249: bp->b_flags |= B_DONE;
250: wakeup((caddr_t)bp);
251: }
252: break;
253:
254: case FL_COM: /* expecting a "function complete" */
255: if ((c&RXDB_ID)!= FL_FFC || (c&FL_ERR) == FL_ERR){
256: error:
257: bp->b_flags |= B_ERROR | B_DONE;
258: bp->b_resid = -bp->b_bcount;
259: fltab.fl_active = FL_IDLE;
260: wakeup((caddr_t)bp);
261: } else if ((bp->b_flags&B_READ) == B_READ)
262: /* got function complete, now get data */
263: fltab.fl_active = FL_DAR;
264: else {
265: /* got function complete on write - finish up */
266: fltab.fl_active = FL_IDLE;
267: bp->b_flags |= B_DONE;
268: wakeup((caddr_t)bp);
269: }
270: break;
271: }
272: }
273: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.