|
|
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: * @(#)rx.c 7.4 (Berkeley) 4/3/90
7: */
8:
9: #include "rx.h"
10: #if NFX > 0
11: /*
12: * RX02 floppy disk device driver
13: *
14: */
15:
16: /*
17: * TODO:
18: * - clean up the code for multisector transfers using
19: * a 'transfer in progress' flag
20: * - Test Deleted Data read/write
21: * - Test error handling/reporting and 'volume valid' stuff
22: *
23: * Note: If the drive subsystem is
24: * powered off at boot time, the controller won't interrupt!
25: */
26:
27: #include "machine/pte.h"
28:
29: #include "param.h"
30: #include "buf.h"
31: #include "systm.h"
32: #include "conf.h"
33: #include "errno.h"
34: #include "time.h"
35: #include "kernel.h"
36: #include "uio.h"
37: #include "file.h"
38:
39: #include "../vax/cpu.h"
40: #include "../vax/nexus.h"
41:
42: #include "ubavar.h"
43: #include "ubareg.h"
44: #include "rxreg.h"
45:
46: #define b_cylin b_resid
47:
48: /* per-controller data */
49: struct rx_ctlr {
50: int rxc_state; /* controller state */
51: #define RXS_READ 1 /* read started */
52: #define RXS_EMPTY 2 /* empty started */
53: #define RXS_FILL 3 /* fill started */
54: #define RXS_WRITE 4 /* write started */
55: #define RXS_FORMAT 5 /* format started */
56: #define RXS_RDSTAT 6 /* status read started */
57: #define RXS_RDERR 7 /* error read started */
58: #define RXS_IDLE 8 /* device is idle */
59: u_short rxc_rxcs; /* extended error status */
60: u_short rxc_rxdb;
61: u_short rxc_rxxt[4];
62: int rxc_tocnt; /* for watchdog routine */
63: #define RX_MAXTIMEOUT 30 /* # seconds to wait before giving up */
64: } rx_ctlr[NFX];
65:
66: /* per-drive buffers */
67: struct buf rrxbuf[NRX]; /* buffers for raw I/O */
68: struct buf erxbuf[NRX]; /* buffers for reading error status */
69: struct buf rxutab[NRX]; /* per drive buffers */
70:
71: /* per-drive data */
72: struct rx_softc {
73: int sc_flags; /* drive status flags */
74: #define RXF_DIRECT 0x01 /* if set: use direct sector mapping */
75: #define RXF_TRKONE 0x02 /* if set: start mapping on track 1 */
76: #define RXF_DBLDEN 0x04 /* use double density */
77: #define RXF_DEVTYPE 0x07 /* mapping flags */
78: #define RXF_LOCK 0x10 /* exclusive use */
79: #define RXF_DDMK 0x20 /* deleted-data mark detected */
80: #define RXF_USEWDDS 0x40 /* write deleted-data sector */
81: #define RXF_FORMAT 0x80 /* format in progress */
82: #define RXF_BAD 0x100 /* drive bad, cannot be used */
83: int sc_csbits; /* constant bits for CS register */
84: int sc_open; /* count number of opens */
85: int sc_offset; /* raw mode kludge to avoid restricting */
86: /* single sector transfers to start on */
87: /* DEV_BSIZE boundaries */
88: /*
89: * The rest of this structure is used to
90: * store temporaries while simulating multi
91: * sector transfers
92: */
93: caddr_t sc_uaddr; /* unibus base address */
94: long sc_bcnt; /* total transfer count */
95: long sc_resid; /* no. of bytes left to transfer */
96: } rx_softc[NRX];
97:
98: struct rxerr {
99: short rxcs;
100: short rxdb;
101: short rxxt[4]; /* error code dump from controller */
102: } rxerr[NRX];
103: /* End of per-drive data */
104:
105: struct uba_device *rxdinfo[NRX];
106: struct uba_ctlr *rxminfo[NFX];
107:
108: struct buf *savebp;
109:
110: int rxprobe(), rxslave(), rxattach(), rxdgo(), rxintr(), rxwatch(), rxphys();
111: u_short rxstd[] = { 0177170, 0177150, 0 };
112: struct uba_driver fxdriver =
113: { rxprobe, rxslave, rxattach, rxdgo, rxstd, "rx", rxdinfo, "fx", rxminfo };
114:
115: int rxwstart;
116: #define RXUNIT(dev) (minor(dev)>>3)
117: #define MASKREG(reg) (reg&0xffff)
118:
119: /* constants related to floppy data capacity */
120: #define RXSECS 2002 /* # sectors on a floppy */
121: #define DDSTATE (sc->sc_csbits&RX_DDEN)
122: #define NBPS (DDSTATE ? 256 : 128) /* # bytes per sector */
123: #define RXSIZE (DDSTATE ? 512512 : 256256) /* # bytes per disk */
124: #define SECMASK (DDSTATE ? 0xff : 0x7f) /* shifted-out bits of offset */
125:
126: #define B_CTRL 0x80000000 /* control (format) request */
127: #define B_RDSTAT 0x40000000 /* read drive status (open) */
128:
129: /*ARGSUSED*/
130: rxprobe (reg)
131: caddr_t reg;
132: {
133: register int br, cvec; /* value-result */
134: struct rxdevice *rxaddr = (struct rxdevice *)reg;
135:
136: #ifdef lint
137: br = 0; cvec = br; br = cvec;
138: rxintr(0);
139: #endif lint
140: rxaddr->rxcs = RX_INTR;
141: DELAY(10);
142: rxaddr->rxcs = 0;
143: return (sizeof (*rxaddr));
144: }
145:
146: /*ARGSUSED*/
147: rxslave(ui, reg)
148: struct uba_device *ui;
149: caddr_t reg;
150: {
151: return (ui->ui_slave == 0 || ui->ui_slave == 1);
152: }
153:
154: /*ARGSUSED*/
155: rxattach(ui)
156: struct uba_device *ui;
157: {
158:
159: }
160:
161: /*ARGSUSED1*/
162: rxopen(dev, flag)
163: dev_t dev;
164: {
165: register int unit = RXUNIT(dev);
166: register struct rx_softc *sc;
167: register struct uba_device *ui;
168: struct rx_ctlr *rxc;
169:
170: if (unit >= NRX || (ui = rxdinfo[unit]) == 0 || ui->ui_alive == 0)
171: return (ENXIO);
172: sc = &rx_softc[unit];
173: if (sc->sc_open == 0 && sc->sc_csbits == 0) {
174: struct buf *bp = &erxbuf[unit];
175: /*
176: * lock the device while an open
177: * is in progress
178: */
179: sc->sc_flags = (minor(dev) & RXF_DEVTYPE) | RXF_LOCK;
180: sc->sc_csbits = RX_INTR;
181: sc->sc_csbits |= ui->ui_slave == 0 ? RX_DRV0 : RX_DRV1;
182:
183: bp->b_dev = dev;
184: bp->b_flags = B_RDSTAT | B_BUSY;
185: bp->b_error = 0;
186: bp->b_blkno = 0;
187: sc->sc_offset = 0;
188: sc->sc_resid = 0;
189: /*
190: * read device status to determine if
191: * a floppy is present in the drive and
192: * what density it is
193: */
194: rxstrategy(bp);
195: iowait(bp);
196: if (bp->b_flags & B_ERROR) {
197: sc->sc_csbits = 0;
198: sc->sc_flags &= ~RXF_LOCK;
199: return (bp->b_error);
200: }
201: if (rxwstart++ == 0) {
202: rxc = &rx_ctlr[ui->ui_mi->um_ctlr];
203: rxc->rxc_tocnt = 0;
204: timeout(rxwatch, (caddr_t)0, hz); /* start watchdog */
205: }
206: #ifdef RXDEBUG
207: printf("rxopen: csbits=0x%x\n", sc->sc_csbits);
208: #endif
209: sc->sc_flags &= ~RXF_LOCK;
210: } else {
211: if (sc->sc_flags & RXF_LOCK)
212: return(EBUSY);
213: }
214: sc->sc_open = 1;
215: return (0);
216: }
217:
218: /*ARGSUSED1*/
219: rxclose(dev, flag)
220: dev_t dev;
221: {
222: register struct rx_softc *sc = &rx_softc[RXUNIT(dev)];
223:
224: sc->sc_open = 0;
225: #ifdef RXDEBUG
226: printf("rxclose: dev=0x%x, sc_open=%d\n", dev, sc->sc_open);
227: #endif
228: return (0);
229: }
230:
231: rxstrategy(bp)
232: register struct buf *bp;
233: {
234: struct uba_device *ui;
235: register struct buf *dp;
236: struct rx_softc *sc;
237: int s, unit = RXUNIT(bp->b_dev);
238:
239: if (unit >= NRX)
240: goto bad;
241: ui = rxdinfo[unit];
242: if (ui == 0 || ui->ui_alive == 0)
243: goto bad;
244: sc = &rx_softc[unit];
245: if (bp->b_blkno < 0 || dbtob(bp->b_blkno) > RXSIZE)
246: goto bad;
247: if (sc->sc_flags & RXF_BAD) {
248: bp->b_error = EIO;
249: goto dbad;
250: }
251: s = spl5();
252: #ifdef RXDEBUG
253: printf("rxstrat: bp=0x%x, fl=0x%x, un=%d, bl=%d, cnt=%d\n",
254: bp, bp->b_flags, unit, bp->b_blkno, bp->b_bcount);
255: #endif
256: bp->b_cylin = bp->b_blkno; /* don't care to calculate trackno */
257: dp = &rxutab[unit];
258: disksort(dp, bp);
259: if (dp->b_active == 0) {
260: rxustart(ui);
261: bp = &ui->ui_mi->um_tab;
262: if (bp->b_actf && bp->b_active == 0)
263: rxstart(ui->ui_mi);
264: }
265: splx(s);
266: return;
267:
268: bad:
269: bp->b_error = ENXIO;
270: dbad:
271: bp->b_flags |= B_ERROR;
272: iodone(bp);
273: return;
274: }
275:
276: /*
277: * Unit start routine.
278: * Put this unit on the ready queue for the controller
279: */
280: rxustart(ui)
281: register struct uba_device *ui;
282: {
283: struct buf *dp = &rxutab[ui->ui_unit];
284: struct uba_ctlr *um = ui->ui_mi;
285:
286: dp->b_forw = NULL;
287: if (um->um_tab.b_actf == NULL)
288: um->um_tab.b_actf = dp;
289: else
290: um->um_tab.b_actl->b_forw = dp;
291: um->um_tab.b_actl = dp;
292: dp->b_active++;
293: }
294: /*
295: * Sector mapping routine.
296: * Two independent sets of choices are available:
297: *
298: * (a) The first logical sector may either be on track 1 or track 0.
299: * (b) The sectors on a track may either be taken in 2-for-1 interleaved
300: * fashion or directly.
301: * This gives a total of four possible mapping schemes.
302: *
303: * Physical tracks on the RX02 are numbered 0-76. Physical sectors on
304: * each track are numbered 1-26.
305: *
306: * When interleaving is used, sectors on the first logical track are
307: * taken in the order 1, 3, 5, ..., 25, 2, 4, 6, ..., 26. A skew of
308: * six sectors per track is also used (to allow time for the heads to
309: * move); hence, the sectors on the second logical track are taken in
310: * the order 7, 9, 11, ..., 25, 1, 3, 5, 8, 10, 12, ..., 26, 2, 4, 6;
311: * the third logical track starts with sector 13; and so on.
312: *
313: * When the mapping starts with track 1, track 0 is the last logical
314: * track, and this track is always handled directly (without inter-
315: * leaving), even when the rest of the disk is interleaved. (This is
316: * still compatible with DEC RT-11, which does not use track 0 at all.)
317: */
318: rxmap(bp, psector, ptrack)
319: struct buf *bp;
320: int *psector, *ptrack;
321: {
322: register int lt, ls, ptoff;
323: struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
324:
325: ls = (dbtob(bp->b_blkno) + (sc->sc_offset - sc->sc_resid)) / NBPS;
326: lt = ls / 26;
327: ls %= 26;
328: /*
329: * The "physical track offset" (ptoff) takes the
330: * starting physical track (0 or 1) and the desired
331: * interleaving into account. If lt+ptoff >= 77,
332: * then interleaving is not performed.
333: */
334: ptoff = 0;
335: if (sc->sc_flags & RXF_DIRECT)
336: ptoff = 77;
337: if (sc->sc_flags & RXF_TRKONE)
338: ptoff++;
339: if (lt + ptoff < 77)
340: ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26;
341: *ptrack = (lt + ptoff) % 77;
342: *psector = ls + 1;
343: }
344:
345: /*
346: * Controller start routine.
347: * Start a new transfer or continue a multisector
348: * transfer. If this is a new transfer (dp->b_active == 1)
349: * save the start address of the data buffer and the total
350: * byte count in the soft control structure. These are
351: * restored into the buffer structure when the transfer has
352: * been completed, before calling 'iodone'.
353: */
354: rxstart(um)
355: register struct uba_ctlr *um;
356: {
357: register struct rxdevice *rxaddr;
358: register struct rx_ctlr *rxc;
359: register struct rx_softc *sc;
360: struct buf *dp, *bp;
361: int unit, sector, track;
362:
363: if (um->um_tab.b_active)
364: return;
365: loop:
366: if ((dp = um->um_tab.b_actf) == NULL)
367: return;
368: if ((bp = dp->b_actf) == NULL) {
369: um->um_tab.b_actf = dp->b_forw;
370: goto loop;
371: }
372: um->um_tab.b_active++;
373: unit = RXUNIT(bp->b_dev);
374: sc = &rx_softc[unit];
375: if (sc->sc_flags & RXF_BAD) {
376: rxpurge(um);
377: return;
378: }
379: if (dp->b_active == 1) {
380: sc->sc_resid = bp->b_bcount;
381: sc->sc_uaddr = bp->b_un.b_addr;
382: sc->sc_bcnt = bp->b_bcount;
383: sc->sc_offset += sc->sc_bcnt;
384: dp->b_active++;
385: }
386: rxaddr = (struct rxdevice *)um->um_addr;
387: rxc = &rx_ctlr[um->um_ctlr];
388: bp->b_bcount = sc->sc_resid;
389: if (bp->b_bcount > NBPS)
390: bp->b_bcount = NBPS;
391: rxc->rxc_tocnt = 0;
392: #ifdef RXDEBUG
393: printf("rxstart: ");
394: #endif
395: if (rxaddr->rxcs == 0x800) {
396: /*
397: * 'Volume valid'? (check if the
398: * drive unit has been powered down)
399: */
400: rxaddr->rxcs = RX_INIT;
401: while((rxaddr->rxcs&RX_DONE) == 0)
402: ;
403: }
404: if (bp->b_flags & B_CTRL) { /* format */
405: rxc->rxc_state = RXS_FORMAT;
406: rxaddr->rxcs = RX_FORMAT | sc->sc_csbits;
407: while ((rxaddr->rxcs&RX_TREQ) == 0)
408: ;
409: rxaddr->rxdb = 'I';
410: return;
411: }
412: if (bp->b_flags & B_RDSTAT) { /* read drive status */
413: rxc->rxc_state = RXS_RDSTAT;
414: rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
415: return;
416: }
417:
418: if (bp->b_flags & B_READ) {
419: rxmap(bp, §or, &track); /* read */
420: #ifdef RXDEBUG
421: printf("read tr=%d, sc=%d", track, sector);
422: #endif
423: rxc->rxc_state = RXS_READ;
424: rxaddr->rxcs = RX_READ | sc->sc_csbits;
425: while ((rxaddr->rxcs&RX_TREQ) == 0)
426: ;
427: rxaddr->rxdb = (u_short)sector;
428: while ((rxaddr->rxcs&RX_TREQ) == 0)
429: ;
430: rxaddr->rxdb = (u_short)track;
431: } else {
432: #ifdef RXDEBUG
433: printf("write");
434: #endif
435: rxc->rxc_state = RXS_FILL; /* write */
436: um->um_cmd = RX_FILL;
437: (void) ubago(rxdinfo[unit]);
438: }
439: #ifdef RXDEBUG
440: printf("\n");
441: #endif
442: }
443:
444: rxdgo(um)
445: struct uba_ctlr *um;
446: {
447: register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr;
448: int ubinfo = um->um_ubinfo;
449: struct buf *bp = um->um_tab.b_actf->b_actf;
450: struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
451: struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr];
452:
453: rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits;
454: if (rxc->rxc_state != RXS_RDERR) {
455: while ((rxaddr->rxcs&RX_TREQ) == 0)
456: ;
457: rxaddr->rxdb = (u_short) bp->b_bcount >> 1;
458: }
459: while ((rxaddr->rxcs&RX_TREQ) == 0)
460: ;
461: rxaddr->rxdb = (u_short) ubinfo;
462: }
463:
464: rxintr(ctlr)
465: int ctlr;
466: {
467: int unit, sector, track;
468: struct uba_ctlr *um = rxminfo[ctlr];
469: register struct rxdevice *rxaddr;
470: register struct buf *bp, *dp;
471: register struct rx_softc *sc;
472: struct uba_device *ui;
473: struct rxerr *er;
474: struct rx_ctlr *rxc;
475:
476: if (!um->um_tab.b_active)
477: return;
478: dp = um->um_tab.b_actf;
479: if (!dp->b_active)
480: return;
481: bp = dp->b_actf;
482: unit = RXUNIT(bp->b_dev);
483: sc = &rx_softc[unit];
484: ui = rxdinfo[unit];
485: rxaddr = (struct rxdevice *)um->um_addr;
486: rxc = &rx_ctlr[um->um_ctlr];
487: rxc->rxc_tocnt = 0;
488: er = &rxerr[unit];
489: #ifdef RXDEBUG
490: printf("rxint: dev=%x, st=%d, cs=0x%x, db=0x%x\n",
491: bp->b_dev, rxc->rxc_state, rxaddr->rxcs, rxaddr->rxdb);
492: #endif
493: if ((rxaddr->rxcs & RX_ERR) &&
494: (rxc->rxc_state != RXS_RDSTAT) && (rxc->rxc_state != RXS_RDERR))
495: goto error;
496: switch (rxc->rxc_state) {
497:
498: /*
499: * Incomplete commands. Perform next step
500: * and return. Note that b_active is set on
501: * entrance and, therefore, also on exit.
502: */
503: case RXS_READ:
504: if (rxaddr->rxdb & RXES_DDMARK)
505: sc->sc_flags |= RXF_DDMK;
506: else
507: sc->sc_flags &= ~RXF_DDMK;
508: rxc->rxc_state = RXS_EMPTY;
509: um->um_cmd = RX_EMPTY;
510: (void) ubago(ui);
511: return;
512:
513: case RXS_FILL:
514: rxc->rxc_state = RXS_WRITE;
515: if (sc->sc_flags & RXF_USEWDDS) {
516: rxaddr->rxcs = RX_WDDS | sc->sc_csbits;
517: sc->sc_flags &= ~RXF_USEWDDS;
518: } else
519: rxaddr->rxcs = RX_WRITE | sc->sc_csbits;
520: rxmap(bp, §or, &track);
521: while ((rxaddr->rxcs&RX_TREQ) == 0)
522: ;
523: rxaddr->rxdb = sector;
524: while ((rxaddr->rxcs&RX_TREQ) == 0)
525: ;
526: rxaddr->rxdb = track;
527: return;
528:
529: /*
530: * Possibly completed command.
531: */
532: case RXS_RDSTAT:
533: if (bp->b_flags & B_RDSTAT) {
534: if ((rxaddr->rxdb&RXES_READY) == 0) {
535: bp->b_flags |= B_ERROR;
536: bp->b_error = ENODEV;
537: } else {
538: sc->sc_csbits |= rxaddr->rxdb&RXES_DBLDEN ?
539: RX_DDEN : RX_SDEN;
540: }
541: goto rdone;
542: }
543: if (rxaddr->rxdb&RXES_READY)
544: goto rderr;
545: bp->b_error = ENODEV;
546: bp->b_flags |= B_ERROR;
547: goto done;
548:
549: /*
550: * Command completed.
551: */
552: case RXS_EMPTY:
553: case RXS_WRITE:
554: goto done;
555:
556: case RXS_FORMAT:
557: goto rdone;
558:
559: case RXS_RDERR:
560: bp = savebp;
561: rxmap(bp, §or, &track);
562: printf("rx%d: hard error, trk %d psec %d ",
563: unit, track, sector);
564: printf("cs=%b, db=%b, err=", MASKREG(er->rxcs),
565: RXCS_BITS, MASKREG(er->rxdb), RXES_BITS);
566: printf("%x, %x, %x, %x\n", MASKREG(er->rxxt[0]),
567: MASKREG(er->rxxt[1]), MASKREG(er->rxxt[2]),
568: MASKREG(er->rxxt[3]));
569: goto done;
570:
571: default:
572: printf("rx%d: state %d (reset)\n", unit, rxc->rxc_state);
573: rxreset(um->um_ubanum);
574: return;
575: }
576: error:
577: /*
578: * In case of an error:
579: * (a) Give up now if a format (ioctl) was in progress, if a
580: * density error was detected, or if the drive went offline
581: * (b) Retry up to nine times if a CRC (data) error was detected,
582: * then give up if the error persists.
583: * (c) In all other cases, reinitialize the drive and try the
584: * operation once more before giving up.
585: */
586: if (rxc->rxc_state == RXS_FORMAT || (rxaddr->rxdb&RXES_DENERR))
587: goto giveup;
588: if (rxaddr->rxdb & RXES_CRCERR) {
589: if (++um->um_tab.b_errcnt >= 10)
590: goto giveup;
591: goto retry;
592: }
593: um->um_tab.b_errcnt += 9;
594: if (um->um_tab.b_errcnt >= 10)
595: goto giveup;
596: rxaddr->rxcs = RX_INIT;
597: /* no way to get an interrupt for "init done", so just wait */
598: while ((rxaddr->rxcs&RX_DONE) == 0)
599: ;
600: /* if someone opened the drive: give up */
601: if ((rxaddr->rxdb&RXES_READY) == 0)
602: goto giveup;
603: retry:
604: /*
605: * In case we already have UNIBUS resources, give
606: * them back since we reallocate things in rxstart.
607: */
608: if (um->um_ubinfo)
609: ubadone(um);
610: um->um_tab.b_active = 0;
611: rxstart(um);
612: return;
613:
614: giveup:
615: /*
616: * Hard I/O error --
617: * ALL errors are considered fatal and will abort the
618: * transfer and purge the i/o request queue
619: */
620: sc->sc_flags |= RXF_BAD;
621: sc->sc_resid = 0; /* make sure the transfer is terminated */
622: rxc->rxc_state = RXS_RDSTAT;
623: rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
624: return;
625:
626: rderr:
627: /*
628: * A hard error (other than not ready) has occurred.
629: * Read the extended error status information.
630: * Before doing this, save the current CS and DB register values,
631: * because the read error status operation may modify them.
632: * Insert buffer with request at the head of the queue.
633: */
634: bp->b_error = EIO;
635: bp->b_flags |= B_ERROR;
636: if (um->um_ubinfo)
637: ubadone(um);
638: savebp = bp;
639: er->rxcs = rxaddr->rxcs;
640: er->rxdb = rxaddr->rxdb;
641: bp = &erxbuf[unit];
642: bp->b_un.b_addr = (caddr_t)er->rxxt;
643: bp->b_bcount = sizeof (er->rxxt);
644: bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET);
645: if (dp->b_actf == NULL)
646: dp->b_actl = bp;
647: bp->b_forw = dp->b_actf;
648: dp->b_actf = bp;
649: rxc->rxc_state = RXS_RDERR;
650: um->um_cmd = RX_RDERR;
651: (void) ubago(ui);
652: return;
653:
654: done:
655: ubadone(um);
656: rdone:
657: um->um_tab.b_active = 0;
658: um->um_tab.b_errcnt = 0;
659: if ((sc->sc_resid -= NBPS) > 0) {
660: bp->b_un.b_addr += NBPS;
661: rxstart(um);
662: return;
663: }
664: bp->b_un.b_addr = sc->sc_uaddr;
665: bp->b_resid = 0;
666: bp->b_bcount = sc->sc_bcnt;
667: dp->b_actf = bp->av_forw;
668: iodone(bp);
669: sc->sc_offset = 0;
670: rxc->rxc_state = RXS_IDLE;
671: um->um_tab.b_actf = dp->b_forw;
672: dp->b_active = 0;
673: dp->b_errcnt = 0;
674: #ifdef RXDEBUG
675: printf(".. bp=%x, new=%x\n", bp, dp->b_actf);
676: #endif
677: /*
678: * If this unit has more work to do,
679: * start it up right away
680: */
681: if (dp->b_actf)
682: rxustart(ui);
683:
684: rxstart(um);
685: }
686:
687: /*ARGSUSED*/
688:
689: rxwatch()
690: {
691: register struct uba_device *ui;
692: register struct uba_ctlr *um;
693: register struct rx_softc *sc;
694: struct rx_ctlr *rxc;
695: int i, dopen = 0;
696:
697: for (i=0; i<NRX; i++) {
698: ui = rxdinfo[i];
699: if (ui == 0 || ui->ui_alive == 0)
700: continue;
701: sc = &rx_softc[i];
702: if ((sc->sc_open == 0) && (rxutab[i].b_active == 0)) {
703: sc->sc_csbits = 0;
704: continue;
705: }
706: dopen++;
707: um = ui->ui_mi;
708: rxc = &rx_ctlr[um->um_ctlr];
709: if (++rxc->rxc_tocnt >= RX_MAXTIMEOUT) {
710: rxc->rxc_tocnt = 0;
711: if (um->um_tab.b_active) {
712: printf("rx%d: timeout\n", i);/* for debugging */
713: rxintr(um->um_ctlr);
714: }
715: }
716: }
717: if (dopen)
718: timeout(rxwatch, (caddr_t)0, hz);
719: else
720: rxwstart = 0;
721: }
722:
723: rxreset(uban)
724: int uban;
725: {
726: register struct uba_ctlr *um;
727: register struct rxdevice *rxaddr;
728: register int ctlr;
729:
730: for (ctlr = 0; ctlr < NFX; ctlr++) {
731: if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban ||
732: um->um_alive == 0)
733: continue;
734: printf(" fx%d", ctlr);
735: if (um->um_ubinfo) {
736: printf("<%d>", UBAI_BDP(um->um_ubinfo));
737: um->um_ubinfo = 0;
738: }
739: rx_ctlr[ctlr].rxc_state = RXS_IDLE;
740: rxaddr = (struct rxdevice *)um->um_addr;
741: rxaddr->rxcs = RX_INIT;
742: while ((rxaddr->rxcs&RX_DONE) == 0)
743: ;
744: rxstart(um);
745: }
746: }
747:
748: rxread(dev, uio)
749: dev_t dev;
750: struct uio *uio;
751: {
752: int unit = RXUNIT(dev);
753: struct rx_softc *sc = &rx_softc[unit];
754:
755: if (uio->uio_offset + uio->uio_resid > RXSIZE)
756: return (ENXIO);
757: if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
758: return (ENXIO);
759: sc->sc_offset = uio->uio_offset % DEV_BSIZE;
760: return (physio(rxstrategy, &rrxbuf[unit], dev, B_READ, minphys, uio));
761: }
762:
763: rxwrite(dev, uio)
764: dev_t dev;
765: struct uio *uio;
766: {
767: int unit = RXUNIT(dev);
768: struct rx_softc *sc = &rx_softc[unit];
769:
770: if (uio->uio_offset + uio->uio_resid > RXSIZE)
771: return (ENXIO);
772: if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
773: return (ENXIO);
774: sc->sc_offset = uio->uio_offset % DEV_BSIZE;
775: return(physio(rxstrategy, &rrxbuf[unit], dev, B_WRITE, minphys, uio));
776: }
777:
778: /*
779: * Control routine:
780: * processes four kinds of requests:
781: *
782: * (1) Set density (i.e., format the diskette) according to
783: * that specified data parameter
784: * (2) Arrange for the next sector to be written with a deleted-
785: * data mark.
786: * (3) Report whether the last sector read had a deleted-data mark
787: * (4) Report the density of the diskette in the indicated drive
788: * (since the density it automatically determined by the driver,
789: * this is the only way to let an application program know the
790: * density)
791: *
792: * Requests relating to deleted-data marks can be handled right here.
793: * A "set density" (format) request, however, must additionally be
794: * processed through "rxstart", just like a read or write request.
795: */
796:
797: /*ARGSUSED3*/
798: rxioctl(dev, cmd, data, flag)
799: dev_t dev;
800: caddr_t data;
801: {
802: int unit = RXUNIT(dev);
803: struct rx_softc *sc = &rx_softc[unit];
804:
805: switch (cmd) {
806:
807: case RXIOC_FORMAT:
808: if ((flag&FWRITE) == 0)
809: return (EBADF);
810: if (sc->sc_open > 1)
811: return (EBUSY);
812: if (*(int *)data)
813: sc->sc_csbits |= RX_DDEN;
814: else
815: sc->sc_csbits &= ~RX_DDEN;
816: return (rxformat(dev));
817:
818: case RXIOC_WDDS:
819: sc->sc_flags |= RXF_USEWDDS;
820: return (0);
821:
822: case RXIOC_RDDSMK:
823: *(int *)data = sc->sc_flags & RXF_DDMK;
824: return (0);
825:
826: case RXIOC_GDENS:
827: *(int *)data = sc->sc_csbits & RX_DDEN;
828: return (0);
829: }
830: return (ENXIO);
831: }
832:
833: /*
834: * Initiate a format command.
835: */
836: rxformat(dev)
837: dev_t dev;
838: {
839: int unit = RXUNIT(dev);
840: struct buf *bp;
841: struct rx_softc *sc = &rx_softc[unit];
842: int error = 0;
843:
844: bp = &rrxbuf[unit];
845: bp->b_flags = B_BUSY | B_CTRL;
846: sc->sc_flags = RXF_FORMAT | RXF_LOCK;
847: bp->b_dev = dev;
848: bp->b_error = 0;
849: bp->b_blkno = 0;
850: rxstrategy(bp);
851: iowait(bp);
852: if (bp->b_flags & B_ERROR)
853: error = bp->b_error;
854: bp->b_flags &= ~B_BUSY;
855: sc->sc_flags &= ~RXF_LOCK;
856: return (error);
857: }
858:
859: /*
860: * A permanent hard error condition has occured,
861: * purge the buffer queue
862: */
863: rxpurge(um)
864: register struct uba_ctlr *um;
865: {
866: register struct buf *bp, *dp;
867:
868: dp = um->um_tab.b_actf;
869: while (dp->b_actf) {
870: dp->b_errcnt++;
871: bp = dp->b_actf;
872: bp->b_error = EIO;
873: bp->b_flags |= B_ERROR;
874: iodone(bp);
875: dp->b_actf = bp->av_forw;
876: }
877: }
878: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.