|
|
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.2 (Berkeley) 1/28/88
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: }
229:
230: rxstrategy(bp)
231: register struct buf *bp;
232: {
233: struct uba_device *ui;
234: register struct buf *dp;
235: struct rx_softc *sc;
236: int s, unit = RXUNIT(bp->b_dev);
237:
238: if (unit >= NRX)
239: goto bad;
240: ui = rxdinfo[unit];
241: if (ui == 0 || ui->ui_alive == 0)
242: goto bad;
243: sc = &rx_softc[unit];
244: if (bp->b_blkno < 0 || dbtob(bp->b_blkno) > RXSIZE)
245: goto bad;
246: if (sc->sc_flags & RXF_BAD) {
247: bp->b_error = EIO;
248: goto dbad;
249: }
250: s = spl5();
251: #ifdef RXDEBUG
252: printf("rxstrat: bp=0x%x, fl=0x%x, un=%d, bl=%d, cnt=%d\n",
253: bp, bp->b_flags, unit, bp->b_blkno, bp->b_bcount);
254: #endif
255: bp->b_cylin = bp->b_blkno; /* don't care to calculate trackno */
256: dp = &rxutab[unit];
257: disksort(dp, bp);
258: if (dp->b_active == 0) {
259: rxustart(ui);
260: bp = &ui->ui_mi->um_tab;
261: if (bp->b_actf && bp->b_active == 0)
262: rxstart(ui->ui_mi);
263: }
264: splx(s);
265: return;
266:
267: bad:
268: bp->b_error = ENXIO;
269: dbad:
270: bp->b_flags |= B_ERROR;
271: iodone(bp);
272: return;
273: }
274:
275: /*
276: * Unit start routine.
277: * Put this unit on the ready queue for the controller
278: */
279: rxustart(ui)
280: register struct uba_device *ui;
281: {
282: struct buf *dp = &rxutab[ui->ui_unit];
283: struct uba_ctlr *um = ui->ui_mi;
284:
285: dp->b_forw = NULL;
286: if (um->um_tab.b_actf == NULL)
287: um->um_tab.b_actf = dp;
288: else
289: um->um_tab.b_actl->b_forw = dp;
290: um->um_tab.b_actl = dp;
291: dp->b_active++;
292: }
293: /*
294: * Sector mapping routine.
295: * Two independent sets of choices are available:
296: *
297: * (a) The first logical sector may either be on track 1 or track 0.
298: * (b) The sectors on a track may either be taken in 2-for-1 interleaved
299: * fashion or directly.
300: * This gives a total of four possible mapping schemes.
301: *
302: * Physical tracks on the RX02 are numbered 0-76. Physical sectors on
303: * each track are numbered 1-26.
304: *
305: * When interleaving is used, sectors on the first logical track are
306: * taken in the order 1, 3, 5, ..., 25, 2, 4, 6, ..., 26. A skew of
307: * six sectors per track is also used (to allow time for the heads to
308: * move); hence, the sectors on the second logical track are taken in
309: * the order 7, 9, 11, ..., 25, 1, 3, 5, 8, 10, 12, ..., 26, 2, 4, 6;
310: * the third logical track starts with sector 13; and so on.
311: *
312: * When the mapping starts with track 1, track 0 is the last logical
313: * track, and this track is always handled directly (without inter-
314: * leaving), even when the rest of the disk is interleaved. (This is
315: * still compatible with DEC RT-11, which does not use track 0 at all.)
316: */
317: rxmap(bp, psector, ptrack)
318: struct buf *bp;
319: int *psector, *ptrack;
320: {
321: register int lt, ls, ptoff;
322: struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
323:
324: ls = (dbtob(bp->b_blkno) + (sc->sc_offset - sc->sc_resid)) / NBPS;
325: lt = ls / 26;
326: ls %= 26;
327: /*
328: * The "physical track offset" (ptoff) takes the
329: * starting physical track (0 or 1) and the desired
330: * interleaving into account. If lt+ptoff >= 77,
331: * then interleaving is not performed.
332: */
333: ptoff = 0;
334: if (sc->sc_flags & RXF_DIRECT)
335: ptoff = 77;
336: if (sc->sc_flags & RXF_TRKONE)
337: ptoff++;
338: if (lt + ptoff < 77)
339: ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26;
340: *ptrack = (lt + ptoff) % 77;
341: *psector = ls + 1;
342: }
343:
344: /*
345: * Controller start routine.
346: * Start a new transfer or continue a multisector
347: * transfer. If this is a new transfer (dp->b_active == 1)
348: * save the start address of the data buffer and the total
349: * byte count in the soft control structure. These are
350: * restored into the buffer structure when the transfer has
351: * been completed, before calling 'iodone'.
352: */
353: rxstart(um)
354: register struct uba_ctlr *um;
355: {
356: register struct rxdevice *rxaddr;
357: register struct rx_ctlr *rxc;
358: register struct rx_softc *sc;
359: struct buf *dp, *bp;
360: int unit, sector, track;
361:
362: if (um->um_tab.b_active)
363: return;
364: loop:
365: if ((dp = um->um_tab.b_actf) == NULL)
366: return;
367: if ((bp = dp->b_actf) == NULL) {
368: um->um_tab.b_actf = dp->b_forw;
369: goto loop;
370: }
371: um->um_tab.b_active++;
372: unit = RXUNIT(bp->b_dev);
373: sc = &rx_softc[unit];
374: if (sc->sc_flags & RXF_BAD) {
375: rxpurge(um);
376: return;
377: }
378: if (dp->b_active == 1) {
379: sc->sc_resid = bp->b_bcount;
380: sc->sc_uaddr = bp->b_un.b_addr;
381: sc->sc_bcnt = bp->b_bcount;
382: sc->sc_offset += sc->sc_bcnt;
383: dp->b_active++;
384: }
385: rxaddr = (struct rxdevice *)um->um_addr;
386: rxc = &rx_ctlr[um->um_ctlr];
387: bp->b_bcount = sc->sc_resid;
388: if (bp->b_bcount > NBPS)
389: bp->b_bcount = NBPS;
390: rxc->rxc_tocnt = 0;
391: #ifdef RXDEBUG
392: printf("rxstart: ");
393: #endif
394: if (rxaddr->rxcs == 0x800) {
395: /*
396: * 'Volume valid'? (check if the
397: * drive unit has been powered down)
398: */
399: rxaddr->rxcs = RX_INIT;
400: while((rxaddr->rxcs&RX_DONE) == 0)
401: ;
402: }
403: if (bp->b_flags & B_CTRL) { /* format */
404: rxc->rxc_state = RXS_FORMAT;
405: rxaddr->rxcs = RX_FORMAT | sc->sc_csbits;
406: while ((rxaddr->rxcs&RX_TREQ) == 0)
407: ;
408: rxaddr->rxdb = 'I';
409: return;
410: }
411: if (bp->b_flags & B_RDSTAT) { /* read drive status */
412: rxc->rxc_state = RXS_RDSTAT;
413: rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
414: return;
415: }
416:
417: if (bp->b_flags & B_READ) {
418: rxmap(bp, §or, &track); /* read */
419: #ifdef RXDEBUG
420: printf("read tr=%d, sc=%d", track, sector);
421: #endif
422: rxc->rxc_state = RXS_READ;
423: rxaddr->rxcs = RX_READ | sc->sc_csbits;
424: while ((rxaddr->rxcs&RX_TREQ) == 0)
425: ;
426: rxaddr->rxdb = (u_short)sector;
427: while ((rxaddr->rxcs&RX_TREQ) == 0)
428: ;
429: rxaddr->rxdb = (u_short)track;
430: } else {
431: #ifdef RXDEBUG
432: printf("write");
433: #endif
434: rxc->rxc_state = RXS_FILL; /* write */
435: um->um_cmd = RX_FILL;
436: (void) ubago(rxdinfo[unit]);
437: }
438: #ifdef RXDEBUG
439: printf("\n");
440: #endif
441: }
442:
443: rxdgo(um)
444: struct uba_ctlr *um;
445: {
446: register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr;
447: int ubinfo = um->um_ubinfo;
448: struct buf *bp = um->um_tab.b_actf->b_actf;
449: struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
450: struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr];
451:
452: rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits;
453: if (rxc->rxc_state != RXS_RDERR) {
454: while ((rxaddr->rxcs&RX_TREQ) == 0)
455: ;
456: rxaddr->rxdb = (u_short) bp->b_bcount >> 1;
457: }
458: while ((rxaddr->rxcs&RX_TREQ) == 0)
459: ;
460: rxaddr->rxdb = (u_short) ubinfo;
461: }
462:
463: rxintr(ctlr)
464: int ctlr;
465: {
466: int unit, sector, track;
467: struct uba_ctlr *um = rxminfo[ctlr];
468: register struct rxdevice *rxaddr;
469: register struct buf *bp, *dp;
470: register struct rx_softc *sc;
471: struct uba_device *ui;
472: struct rxerr *er;
473: struct rx_ctlr *rxc;
474:
475: if (!um->um_tab.b_active)
476: return;
477: dp = um->um_tab.b_actf;
478: if (!dp->b_active)
479: return;
480: bp = dp->b_actf;
481: unit = RXUNIT(bp->b_dev);
482: sc = &rx_softc[unit];
483: ui = rxdinfo[unit];
484: rxaddr = (struct rxdevice *)um->um_addr;
485: rxc = &rx_ctlr[um->um_ctlr];
486: rxc->rxc_tocnt = 0;
487: er = &rxerr[unit];
488: #ifdef RXDEBUG
489: printf("rxint: dev=%x, st=%d, cs=0x%x, db=0x%x\n",
490: bp->b_dev, rxc->rxc_state, rxaddr->rxcs, rxaddr->rxdb);
491: #endif
492: if ((rxaddr->rxcs & RX_ERR) &&
493: (rxc->rxc_state != RXS_RDSTAT) && (rxc->rxc_state != RXS_RDERR))
494: goto error;
495: switch (rxc->rxc_state) {
496:
497: /*
498: * Incomplete commands. Perform next step
499: * and return. Note that b_active is set on
500: * entrance and, therefore, also on exit.
501: */
502: case RXS_READ:
503: if (rxaddr->rxdb & RXES_DDMARK)
504: sc->sc_flags |= RXF_DDMK;
505: else
506: sc->sc_flags &= ~RXF_DDMK;
507: rxc->rxc_state = RXS_EMPTY;
508: um->um_cmd = RX_EMPTY;
509: (void) ubago(ui);
510: return;
511:
512: case RXS_FILL:
513: rxc->rxc_state = RXS_WRITE;
514: if (sc->sc_flags & RXF_USEWDDS) {
515: rxaddr->rxcs = RX_WDDS | sc->sc_csbits;
516: sc->sc_flags &= ~RXF_USEWDDS;
517: } else
518: rxaddr->rxcs = RX_WRITE | sc->sc_csbits;
519: rxmap(bp, §or, &track);
520: while ((rxaddr->rxcs&RX_TREQ) == 0)
521: ;
522: rxaddr->rxdb = sector;
523: while ((rxaddr->rxcs&RX_TREQ) == 0)
524: ;
525: rxaddr->rxdb = track;
526: return;
527:
528: /*
529: * Possibly completed command.
530: */
531: case RXS_RDSTAT:
532: if (bp->b_flags & B_RDSTAT) {
533: if ((rxaddr->rxdb&RXES_READY) == 0) {
534: bp->b_flags |= B_ERROR;
535: bp->b_error = ENODEV;
536: } else {
537: sc->sc_csbits |= rxaddr->rxdb&RXES_DBLDEN ?
538: RX_DDEN : RX_SDEN;
539: }
540: goto rdone;
541: }
542: if (rxaddr->rxdb&RXES_READY)
543: goto rderr;
544: bp->b_error = ENODEV;
545: bp->b_flags |= B_ERROR;
546: goto done;
547:
548: /*
549: * Command completed.
550: */
551: case RXS_EMPTY:
552: case RXS_WRITE:
553: goto done;
554:
555: case RXS_FORMAT:
556: goto rdone;
557:
558: case RXS_RDERR:
559: bp = savebp;
560: rxmap(bp, §or, &track);
561: printf("rx%d: hard error, trk %d psec %d ",
562: unit, track, sector);
563: printf("cs=%b, db=%b, err=", MASKREG(er->rxcs),
564: RXCS_BITS, MASKREG(er->rxdb), RXES_BITS);
565: printf("%x, %x, %x, %x\n", MASKREG(er->rxxt[0]),
566: MASKREG(er->rxxt[1]), MASKREG(er->rxxt[2]),
567: MASKREG(er->rxxt[3]));
568: goto done;
569:
570: default:
571: printf("rx%d: state %d (reset)\n", unit, rxc->rxc_state);
572: rxreset(um->um_ubanum);
573: return;
574: }
575: error:
576: /*
577: * In case of an error:
578: * (a) Give up now if a format (ioctl) was in progress, if a
579: * density error was detected, or if the drive went offline
580: * (b) Retry up to nine times if a CRC (data) error was detected,
581: * then give up if the error persists.
582: * (c) In all other cases, reinitialize the drive and try the
583: * operation once more before giving up.
584: */
585: if (rxc->rxc_state == RXS_FORMAT || (rxaddr->rxdb&RXES_DENERR))
586: goto giveup;
587: if (rxaddr->rxdb & RXES_CRCERR) {
588: if (++um->um_tab.b_errcnt >= 10)
589: goto giveup;
590: goto retry;
591: }
592: um->um_tab.b_errcnt += 9;
593: if (um->um_tab.b_errcnt >= 10)
594: goto giveup;
595: rxaddr->rxcs = RX_INIT;
596: /* no way to get an interrupt for "init done", so just wait */
597: while ((rxaddr->rxcs&RX_DONE) == 0)
598: ;
599: /* if someone opened the drive: give up */
600: if ((rxaddr->rxdb&RXES_READY) == 0)
601: goto giveup;
602: retry:
603: /*
604: * In case we already have UNIBUS resources, give
605: * them back since we reallocate things in rxstart.
606: */
607: if (um->um_ubinfo)
608: ubadone(um);
609: um->um_tab.b_active = 0;
610: rxstart(um);
611: return;
612:
613: giveup:
614: /*
615: * Hard I/O error --
616: * ALL errors are considered fatal and will abort the
617: * transfer and purge the i/o request queue
618: */
619: sc->sc_flags |= RXF_BAD;
620: sc->sc_resid = 0; /* make sure the transfer is terminated */
621: rxc->rxc_state = RXS_RDSTAT;
622: rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits;
623: return;
624:
625: rderr:
626: /*
627: * A hard error (other than not ready) has occurred.
628: * Read the extended error status information.
629: * Before doing this, save the current CS and DB register values,
630: * because the read error status operation may modify them.
631: * Insert buffer with request at the head of the queue.
632: */
633: bp->b_error = EIO;
634: bp->b_flags |= B_ERROR;
635: if (um->um_ubinfo)
636: ubadone(um);
637: savebp = bp;
638: er->rxcs = rxaddr->rxcs;
639: er->rxdb = rxaddr->rxdb;
640: bp = &erxbuf[unit];
641: bp->b_un.b_addr = (caddr_t)er->rxxt;
642: bp->b_bcount = sizeof (er->rxxt);
643: bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET);
644: if (dp->b_actf == NULL)
645: dp->b_actl = bp;
646: bp->b_forw = dp->b_actf;
647: dp->b_actf = bp;
648: rxc->rxc_state = RXS_RDERR;
649: um->um_cmd = RX_RDERR;
650: (void) ubago(ui);
651: return;
652:
653: done:
654: ubadone(um);
655: rdone:
656: um->um_tab.b_active = 0;
657: um->um_tab.b_errcnt = 0;
658: if ((sc->sc_resid -= NBPS) > 0) {
659: bp->b_un.b_addr += NBPS;
660: rxstart(um);
661: return;
662: }
663: bp->b_un.b_addr = sc->sc_uaddr;
664: bp->b_resid = 0;
665: bp->b_bcount = sc->sc_bcnt;
666: dp->b_actf = bp->av_forw;
667: iodone(bp);
668: sc->sc_offset = 0;
669: rxc->rxc_state = RXS_IDLE;
670: um->um_tab.b_actf = dp->b_forw;
671: dp->b_active = 0;
672: dp->b_errcnt = 0;
673: #ifdef RXDEBUG
674: printf(".. bp=%x, new=%x\n", bp, dp->b_actf);
675: #endif
676: /*
677: * If this unit has more work to do,
678: * start it up right away
679: */
680: if (dp->b_actf)
681: rxustart(ui);
682:
683: rxstart(um);
684: }
685:
686: /*ARGSUSED*/
687:
688: rxwatch()
689: {
690: register struct uba_device *ui;
691: register struct uba_ctlr *um;
692: register struct rx_softc *sc;
693: struct rx_ctlr *rxc;
694: int i, dopen = 0;
695:
696: for (i=0; i<NRX; i++) {
697: ui = rxdinfo[i];
698: if (ui == 0 || ui->ui_alive == 0)
699: continue;
700: sc = &rx_softc[i];
701: if ((sc->sc_open == 0) && (rxutab[i].b_active == 0)) {
702: sc->sc_csbits = 0;
703: continue;
704: }
705: dopen++;
706: um = ui->ui_mi;
707: rxc = &rx_ctlr[um->um_ctlr];
708: if (++rxc->rxc_tocnt >= RX_MAXTIMEOUT) {
709: rxc->rxc_tocnt = 0;
710: if (um->um_tab.b_active) {
711: printf("rx%d: timeout\n", i);/* for debugging */
712: rxintr(um->um_ctlr);
713: }
714: }
715: }
716: if (dopen)
717: timeout(rxwatch, (caddr_t)0, hz);
718: else
719: rxwstart = 0;
720: }
721:
722: rxreset(uban)
723: int uban;
724: {
725: register struct uba_ctlr *um;
726: register struct rxdevice *rxaddr;
727: register int ctlr;
728:
729: for (ctlr = 0; ctlr < NFX; ctlr++) {
730: if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban ||
731: um->um_alive == 0)
732: continue;
733: printf(" fx%d", ctlr);
734: if (um->um_ubinfo) {
735: printf("<%d>", UBAI_BDP(um->um_ubinfo));
736: um->um_ubinfo = 0;
737: }
738: rx_ctlr[ctlr].rxc_state = RXS_IDLE;
739: rxaddr = (struct rxdevice *)um->um_addr;
740: rxaddr->rxcs = RX_INIT;
741: while ((rxaddr->rxcs&RX_DONE) == 0)
742: ;
743: rxstart(um);
744: }
745: }
746:
747: rxread(dev, uio)
748: dev_t dev;
749: struct uio *uio;
750: {
751: int unit = RXUNIT(dev);
752: struct rx_softc *sc = &rx_softc[unit];
753:
754: if (uio->uio_offset + uio->uio_resid > RXSIZE)
755: return (ENXIO);
756: if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
757: return (ENXIO);
758: sc->sc_offset = uio->uio_offset % DEV_BSIZE;
759: return (physio(rxstrategy, &rrxbuf[unit], dev, B_READ, minphys, uio));
760: }
761:
762: rxwrite(dev, uio)
763: dev_t dev;
764: struct uio *uio;
765: {
766: int unit = RXUNIT(dev);
767: struct rx_softc *sc = &rx_softc[unit];
768:
769: if (uio->uio_offset + uio->uio_resid > RXSIZE)
770: return (ENXIO);
771: if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
772: return (ENXIO);
773: sc->sc_offset = uio->uio_offset % DEV_BSIZE;
774: return(physio(rxstrategy, &rrxbuf[unit], dev, B_WRITE, minphys, uio));
775: }
776:
777: /*
778: * Control routine:
779: * processes four kinds of requests:
780: *
781: * (1) Set density (i.e., format the diskette) according to
782: * that specified data parameter
783: * (2) Arrange for the next sector to be written with a deleted-
784: * data mark.
785: * (3) Report whether the last sector read had a deleted-data mark
786: * (4) Report the density of the diskette in the indicated drive
787: * (since the density it automatically determined by the driver,
788: * this is the only way to let an application program know the
789: * density)
790: *
791: * Requests relating to deleted-data marks can be handled right here.
792: * A "set density" (format) request, however, must additionally be
793: * processed through "rxstart", just like a read or write request.
794: */
795:
796: /*ARGSUSED3*/
797: rxioctl(dev, cmd, data, flag)
798: dev_t dev;
799: caddr_t data;
800: {
801: int unit = RXUNIT(dev);
802: struct rx_softc *sc = &rx_softc[unit];
803:
804: switch (cmd) {
805:
806: case RXIOC_FORMAT:
807: if ((flag&FWRITE) == 0)
808: return (EBADF);
809: if (sc->sc_open > 1)
810: return (EBUSY);
811: if (*(int *)data)
812: sc->sc_csbits |= RX_DDEN;
813: else
814: sc->sc_csbits &= ~RX_DDEN;
815: return (rxformat(dev));
816:
817: case RXIOC_WDDS:
818: sc->sc_flags |= RXF_USEWDDS;
819: return (0);
820:
821: case RXIOC_RDDSMK:
822: *(int *)data = sc->sc_flags & RXF_DDMK;
823: return (0);
824:
825: case RXIOC_GDENS:
826: *(int *)data = sc->sc_csbits & RX_DDEN;
827: return (0);
828: }
829: return (ENXIO);
830: }
831:
832: /*
833: * Initiate a format command.
834: */
835: rxformat(dev)
836: dev_t dev;
837: {
838: int unit = RXUNIT(dev);
839: struct buf *bp;
840: struct rx_softc *sc = &rx_softc[unit];
841: int error = 0;
842:
843: bp = &rrxbuf[unit];
844: bp->b_flags = B_BUSY | B_CTRL;
845: sc->sc_flags = RXF_FORMAT | RXF_LOCK;
846: bp->b_dev = dev;
847: bp->b_error = 0;
848: bp->b_blkno = 0;
849: rxstrategy(bp);
850: iowait(bp);
851: if (bp->b_flags & B_ERROR)
852: error = bp->b_error;
853: bp->b_flags &= ~B_BUSY;
854: sc->sc_flags &= ~RXF_LOCK;
855: return (error);
856: }
857:
858: /*
859: * A permanent hard error condition has occured,
860: * purge the buffer queue
861: */
862: rxpurge(um)
863: register struct uba_ctlr *um;
864: {
865: register struct buf *bp, *dp;
866:
867: dp = um->um_tab.b_actf;
868: while (dp->b_actf) {
869: dp->b_errcnt++;
870: bp = dp->b_actf;
871: bp->b_error = EIO;
872: bp->b_flags |= B_ERROR;
873: iodone(bp);
874: dp->b_actf = bp->av_forw;
875: }
876: }
877: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.