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