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