|
|
1.1 root 1: /* $Header: /x/usr/src/sys/coh/RCS/bio.c,v 1.1 91/11/08 12:46:39 hal Exp $ */
2: /* (lgl-
3: * The information contained herein is a trade secret of Mark Williams
4: * Company, and is confidential information. It is provided under a
5: * license agreement, and may be copied or disclosed only under the
6: * terms of that agreement. Any reproduction or disclosure of this
7: * material without the express written authorization of Mark Williams
8: * Company or persuant to the license agreement is unlawful.
9: *
10: * COHERENT Version 2.3.37
11: * Copyright (c) 1982, 1983, 1984.
12: * An unpublished work by Mark Williams Company, Chicago.
13: * All rights reserved.
14: -lgl) */
15: /*
16: * Coherent.
17: * Buffered I/O.
18: *
19: * $Log: bio.c,v $
20: * Revision 1.1 91/11/08 12:46:39 hal
21: * Used in COH 3.2.0
22: *
23: * Revision 1.1 88/03/24 16:13:29 src
24: * Initial revision
25: *
26: * 87/11/25 Allan Cornish /usr/src/sys/coh/bio.c
27: * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
28: *
29: * 87/11/05 Allan Cornish /usr/src/sys/coh/bio.c
30: * New seg struct now used to allow extended addressing.
31: *
32: * 87/01/05 Allan Cornish /usr/src/sys/coh/bio.c
33: * ioreq() now only wakes &stimer if the swap timer is active.
34: *
35: * 86/12/12 Allan Cornish /usr/src/sys/coh/bio.c
36: * Added 3rd arg to dpoll() to specify blocking poll if non-zero.
37: *
38: * 86/11/19 Allan Cornish /usr/src/sys/coh/bio.c
39: * Added dpoll() routine to perform device polls [System V.3 compatible].
40: *
41: * 86/07/24 Allan Cornish /usr/src/sys/coh/bio.c
42: * Added check in devinit() for null dp->d_conp->c_load function pointer.
43: */
44: #include <sys/coherent.h>
45: #include <sys/buf.h>
46: #include <sys/con.h>
47: #include <errno.h>
48: #include <sys/io.h>
49: #include <sys/proc.h>
50: #include <sys/sched.h>
51: #include <sys/seg.h>
52: #include <sys/stat.h>
53: #include <sys/uproc.h>
54:
55: /*
56: * Initialise buffer headers.
57: */
58: bufinit()
59: {
60: register BUF *bp;
61: faddr_t f;
62: paddr_t p;
63:
64: FP_SEL(f) = sds;
65: FP_OFF(f) = 0;
66: p = blockp;
67: FP_OFF(f) = blockp - vtop(f);
68:
69: bufl = kalloc(NBUF * sizeof(BUF));
70: if (bufl == NULL)
71: panic("bufinit: no space for BUF's");
72:
73: for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
74: bp->b_dev = NODEV;
75: bp->b_faddr = f;
76: bp->b_paddr = p;
77: FP_OFF(f) += BSIZE;
78: p += BSIZE;
79: }
80: }
81:
82: /*
83: * Synchronise the buffer cache.
84: */
85: bsync()
86: {
87: register BUF *bp;
88:
89: for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
90: if ((bp->b_flag&BFMOD) == 0)
91: continue;
92: lock(bp->b_gate);
93: if ((bp->b_flag&BFMOD) != 0)
94: bwrite(bp, 1);
95: unlock(bp->b_gate);
96: }
97: }
98:
99: /*
100: * Synchronise all block for a particular device in the buffer cache
101: * and invalidate all references.
102: */
103: bflush(dev)
104: register dev_t dev;
105: {
106: register BUF *bp;
107:
108: for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
109: if (bp->b_dev != dev)
110: continue;
111: lock(bp->b_gate);
112: if (bp->b_dev == dev) {
113: if ((bp->b_flag&BFMOD) != 0)
114: bwrite(bp, 1);
115: bp->b_dev = NODEV;
116: }
117: unlock(bp->b_gate);
118: }
119: }
120:
121: /*
122: * Return a buffer containing the given block from the given device.
123: * If `f' is not set, the read is asynchronous and no buffer is returned.
124: */
125: BUF *
126: bread(dev, bno, f)
127: dev_t dev;
128: daddr_t bno;
129: register int f;
130: {
131: register BUF *bp;
132: register int s;
133:
134: bp = bclaim(dev, bno);
135: if ((bp->b_flag&BFNTP) != 0) {
136: if (f != 0)
137: bp->b_flag &= ~BFASY;
138: else {
139: bp->b_flag |= BFASY;
140: bumap(bp);
141: }
142: bp->b_req = BREAD;
143: bp->b_count = BSIZE;
144: s = sphi();
145: dblock(dev, bp);
146: if (f == 0) {
147: spl(s);
148: return (NULL);
149: }
150: while ((bp->b_flag&BFNTP) != 0)
151: sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
152: spl(s);
153: if ((bp->b_flag&BFERR) != 0) {
154: u.u_error = bp->b_err ? bp->b_err : EIO;
155: brelease(bp);
156: return (NULL);
157: }
158: if (bp->b_resid == BSIZE) {
159: brelease(bp);
160: return (NULL);
161: }
162: }
163: if (f == 0) {
164: brelease(bp);
165: return (NULL);
166: }
167: u.u_block++;
168: return (bp);
169: }
170:
171: /*
172: * If the requested buffer is in the buffer cache, return a pointer to
173: * it. If not, pick an empty buffer, set it up and return it.
174: */
175: BUF *
176: bclaim(dev, bno)
177: dev_t dev;
178: daddr_t bno;
179: {
180: register BUF *bp;
181: register BUF *bp1;
182: register unsigned seqn;
183: register int s;
184:
185: again:
186: bp1 = NULL;
187: seqn = 0;
188: for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
189: if (bp->b_bno == bno && bp->b_dev == dev) {
190: lock(bp->b_gate);
191: if (bp->b_bno != bno || bp->b_dev != dev) {
192: unlock(bp->b_gate);
193: goto again;
194: }
195: if ((bp->b_flag&BFERR) != 0)
196: bp->b_flag |= BFNTP;
197: bsmap(bp);
198: return (bp);
199: }
200: if (locked(bp->b_gate) == 0) {
201: if (bufseqn-bp->b_seqn >= seqn) {
202: bp1 = bp;
203: seqn = bufseqn - bp->b_seqn;
204: }
205: }
206: }
207: if (bp1 == NULL) {
208: s = sphi();
209: for (bp=&bufl[NBUF-1]; bp >= bufl; --bp) {
210: if (locked(bp->b_gate) == 0) {
211: if (bufseqn-bp->b_seqn >= seqn) {
212: bp1 = bp;
213: seqn = bufseqn - bp->b_seqn;
214: }
215: }
216: }
217: if (bp1 == NULL) {
218: bufneed = 1;
219: sleep((char *)&bufneed, CVBLKIO, IVBLKIO, SVBLKIO);
220: spl(s);
221: goto again;
222: }
223: spl(s);
224: }
225: bp = bp1;
226: lock(bp->b_gate);
227: if ((bp->b_flag&BFMOD) != 0) {
228: bwrite(bp, 0);
229: goto again;
230: }
231: bp->b_flag = BFNTP;
232: bp->b_dev = dev;
233: bp->b_bno = bno;
234: bsmap(bp);
235: return (bp);
236: }
237:
238: /*
239: * Write the given buffer out. If `f' is set, the write is synchronous,
240: * otherwise asynchronous. This routine must be called with the buffer
241: * gate locked.
242: */
243: bwrite(bp, f)
244: register BUF *bp;
245: {
246: register int s;
247:
248: if (f != 0)
249: bp->b_flag &= ~BFASY;
250: else {
251: bp->b_flag |= BFASY;
252: bumap(bp);
253: }
254: bp->b_flag |= BFNTP;
255: bp->b_req = BWRITE;
256: bp->b_count = BSIZE;
257: s = sphi();
258: dblock(bp->b_dev, bp);
259: if (f == 0) {
260: spl(s);
261: return;
262: }
263: while ((bp->b_flag&BFNTP) != 0)
264: sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
265: spl(s);
266: }
267:
268: /*
269: * This is called by the driver when I/O has completed on a buffer.
270: */
271: bdone(bp)
272: register BUF *bp;
273: {
274: if (bp->b_req == BWRITE)
275: bp->b_flag &= ~BFMOD;
276: if (bp->b_req == BREAD) {
277: if ((bp->b_flag&BFERR) != 0)
278: bp->b_dev = NODEV;
279: }
280: if ((bp->b_flag&BFASY) != 0) {
281: bp->b_flag &= ~BFASY;
282: brelease(bp);
283: }
284: bp->b_flag &= ~BFNTP;
285: wakeup((char *)bp);
286: }
287:
288: /*
289: * Release the given buffer.
290: */
291: brelease(bp)
292: register BUF *bp;
293: {
294: if ((bp->b_flag&BFERR) == 0)
295: bp->b_seqn = bufseqn++;
296: else {
297: bp->b_flag &= ~BFERR;
298: bp->b_dev = NODEV;
299: }
300: bp->b_flag &= ~BFNTP;
301: bumap(bp);
302: unlock(bp->b_gate);
303: if (bufneed != 0) {
304: bufneed = 0;
305: wakeup((char *)&bufneed);
306: }
307: }
308:
309: /*
310: * Map the given buffer.
311: */
312: bsmap(bp)
313: register BUF *bp;
314: {
315: bsave(bp->b_map);
316: bp->b_flag |= BFMAP;
317: bmapv(bconv(bp->b_paddr));
318: }
319:
320: /*
321: * Unmap the given buffer.
322: */
323: bumap(bp)
324: register BUF *bp;
325: {
326: if ((bp->b_flag&BFMAP) == 0)
327: return;
328: bp->b_flag &= ~BFMAP;
329: brest(bp->b_map);
330: }
331:
332: /*
333: * Read data from the I/O segment into kernel space.
334: */
335: ioread(iop, v, n)
336: register IO *iop;
337: register char *v;
338: register unsigned n;
339: {
340: switch (iop->io_seg) {
341: case IOSYS:
342: iop->io_base += kkcopy(iop->io_base, v, n);
343: break;
344: case IOUSR:
345: iop->io_base += ukcopy(iop->io_base, v, n);
346: break;
347: case IOPHY:
348: iop->io_phys += pkcopy(iop->io_phys, v, n);
349: break;
350: }
351: iop->io_ioc -= n;
352: }
353:
354: /*
355: * Write data from kernel space to the I/O segment.
356: */
357: iowrite(iop, v, n)
358: register IO *iop;
359: register char *v;
360: register unsigned n;
361: {
362: switch (iop->io_seg) {
363: case IOSYS:
364: iop->io_base += kkcopy(v, iop->io_base, n);
365: break;
366: case IOUSR:
367: iop->io_base += kucopy(v, iop->io_base, n);
368: break;
369: case IOPHY:
370: iop->io_phys += kpcopy(v, iop->io_phys, n);
371: break;
372: }
373: iop->io_ioc -= n;
374: }
375:
376: /*
377: * Get a character from the I/O segment.
378: */
379: iogetc(iop)
380: register IO *iop;
381: {
382: register int c;
383:
384: if (iop->io_ioc == 0)
385: return (-1);
386: --iop->io_ioc;
387: if (iop->io_seg == IOSYS)
388: c = *iop->io_base++ & 0377;
389: else {
390: c = getubd(iop->io_base++);
391: if (u.u_error)
392: return (-1);
393: }
394: return (c);
395: }
396:
397: /*
398: * Put a character using the I/O segment.
399: */
400: ioputc(c, iop)
401: register IO *iop;
402: {
403: if (iop->io_ioc == 0)
404: return (-1);
405: --iop->io_ioc;
406: if (iop->io_seg == IOSYS)
407: *iop->io_base++ = c;
408: else {
409: putubd(iop->io_base++, c);
410: if (u.u_error)
411: return (-1);
412: }
413: return (c);
414: }
415:
416: /*
417: * Given a buffer pointer, an I/O structure, a device, request type, and
418: * a flags word, check the I/O structure and perform the I/O request.
419: */
420: ioreq(bp, iop, dev, req, f)
421: register BUF *bp;
422: register IO *iop;
423: dev_t dev;
424: {
425: register SEG *sp;
426: register int n;
427: register int s;
428: register CON *cp;
429: dold_t dold;
430:
431: if ((cp=drvmap(dev, &dold)) == NULL)
432: return;
433: lock(bp->b_gate);
434: n = cp->c_flag; /* n should do something with that flag */
435: drest(dold);
436: sp = NULL;
437: if (iop != NULL) {
438: if ((f&BFBLK) != 0) {
439: if (blocko(iop->io_seek) != 0) {
440: u.u_error = EIO;
441: goto out;
442: }
443: }
444: if ((f&BFIOC) != 0) {
445: if ((sp=iomapvp(iop, bp)) == NULL) {
446: u.u_error = EIO;
447: goto out;
448: }
449: }
450: }
451: bp->b_flag = f|BFNTP;
452: bp->b_req = req;
453: bp->b_dev = dev;
454: if (iop != NULL) {
455: bp->b_bno = blockn(iop->io_seek);
456: bp->b_count = iop->io_ioc;
457: }
458: if (sp != NULL) {
459: bp->b_faddr = ptov( bp->b_paddr, (fsize_t) bp->b_count );
460: sp->s_lrefc++;
461: }
462: s = sphi();
463: dblock(dev, bp);
464: while ((bp->b_flag&BFNTP) != 0)
465: sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO);
466: spl(s);
467: if (sp != NULL) {
468: vrelse( bp->b_faddr );
469: sp->s_lrefc--;
470: }
471: if (stimer.t_last != 0)
472: wakeup((char *)&stimer);
473: if ((bp->b_flag&BFERR) != 0) {
474: u.u_error = bp->b_err ? bp->b_err : EIO;
475: goto out;
476: }
477: if (iop != NULL) {
478: n = iop->io_ioc - bp->b_resid;
479: iop->io_seek += n;
480: iop->io_ioc -= n;
481: }
482: out:
483: unlock(bp->b_gate);
484: }
485:
486: /*
487: * Given an I/O structure and a buffer header, see if the addresses
488: * in the I/O structure are valid and set up the buffer header.
489: */
490: SEG *
491: iomapvp(iop, bp)
492: register IO *iop;
493: register BUF *bp;
494: {
495: register SR *srp;
496: register SEG *sp;
497: register vaddr_t b;
498:
499: if (iop->io_seg != IOUSR)
500: panic("Raw I/O from non user");
501: for (srp=u.u_segl; srp<&u.u_segl[NUSEG]; srp++) {
502: if ((sp=srp->sr_segp) == NULL)
503: continue;
504: if ((srp->sr_flag&SRFDATA) == 0)
505: continue;
506: /* Yet another bug in the 8000 C compiler
507: if ((long)(b=iop->io_base) < (long)srp->sr_base)
508: */
509: if ((b=iop->io_base) < srp->sr_base)
510: continue;
511: if ((long)b+iop->io_ioc > (long)srp->sr_base + sp->s_size)
512: continue;
513: bp->b_paddr = sp->s_paddr + (vaddr_t) (b - srp->sr_base);
514: return (sp);
515: }
516: return (NULL);
517: }
518:
519: /*
520: * Initialise devices.
521: */
522: devinit()
523: {
524: register DRV *dp;
525: register int mind;
526:
527: for ( dp = drvl, mind = 0; mind < drvn; mind++, dp++ ) {
528: if ((dp->d_conp != NULL) && (dp->d_conp->c_load != NULL)) {
529: (*dp->d_conp->c_load)();
530: }
531: }
532: }
533:
534: /*
535: * Open a device.
536: */
537: dopen(dev, m, f)
538: register dev_t dev;
539: {
540: register CON *cp;
541: dold_t dold;
542:
543: if ((cp=drvmap(dev, &dold)) == NULL)
544: return;
545: if ((cp->c_flag&f) == 0) {
546: u.u_error = ENXIO;
547: return;
548: }
549: (*cp->c_open)(dev, m);
550: drest(dold);
551: }
552:
553: /*
554: * Close a device.
555: */
556: dclose(dev)
557: register dev_t dev;
558: {
559: register CON *cp;
560: dold_t dold;
561:
562: if ((cp=drvmap(dev, &dold)) == NULL)
563: return;
564: (*cp->c_close)(dev);
565: drest(dold);
566: }
567:
568: /*
569: * Call the block entry point of a device.
570: */
571: dblock(dev, bp)
572: dev_t dev;
573: BUF *bp;
574: {
575: register CON *cp;
576: dold_t dold;
577:
578: if ((cp=drvmap(dev, &dold)) == NULL)
579: return;
580: (*cp->c_block)(bp);
581: drest(dold);
582: }
583:
584: /*
585: * Read from a device.
586: */
587: dread(dev, iop)
588: register dev_t dev;
589: register IO *iop;
590: {
591: register CON *cp;
592: dold_t dold;
593:
594: if ((cp=drvmap(dev, &dold)) == NULL)
595: return;
596: (*cp->c_read)(dev, iop);
597: drest(dold);
598: }
599:
600: /*
601: * Write to a device.
602: */
603: dwrite(dev, iop)
604: register dev_t dev;
605: register IO *iop;
606: {
607: register CON *cp;
608: dold_t dold;
609:
610: if ((cp=drvmap(dev, &dold)) == NULL)
611: return;
612: (*cp->c_write)(dev, iop);
613: drest(dold);
614: }
615:
616: /*
617: * Call the ioctl function for a device.
618: */
619: dioctl(dev, com, vec)
620: register dev_t dev;
621: union ioctl *vec;
622: {
623: register CON *cp;
624: dold_t dold;
625:
626: if ((cp=drvmap(dev, &dold)) == NULL)
627: return;
628: (*cp->c_ioctl)(dev, com, vec);
629: drest(dold);
630: }
631:
632: /*
633: * Call the powerfail entry point of a device.
634: */
635: dpower(dev)
636: register dev_t dev;
637: {
638: register CON *cp;
639: dold_t dold;
640:
641: if ((cp=drvmap(dev, &dold)) == NULL)
642: return;
643: (*cp->c_power)(dev);
644: drest(dold);
645: }
646:
647: /*
648: * Call the timeout entry point of a device.
649: */
650: dtime(dev)
651: register dev_t dev;
652: {
653: register CON *cp;
654: dold_t dold;
655:
656: if ((cp=drvmap(dev, &dold)) == NULL)
657: return;
658: (*cp->c_timer)(dev);
659: drest(dold);
660: }
661:
662: /*
663: * Poll a device.
664: */
665: dpoll(dev, ev, msec)
666: register dev_t dev;
667: int ev;
668: int msec;
669: {
670: register CON *cp;
671: dold_t dold;
672:
673: if ((cp=drvmap(dev, &dold)) == NULL)
674: return POLLNVAL;
675:
676: if ( cp->c_flag & DFPOL )
677: ev = (*cp->c_poll)(dev, ev, msec);
678: else
679: ev = POLLNVAL;
680:
681: drest(dold);
682: return ev;
683: }
684:
685: /*
686: * Given a device, return the flags word.
687: */
688: dflag(dev)
689: dev_t dev;
690: {
691: register CON *cp;
692: register int f;
693: dold_t dold;
694:
695: if ((cp=drvmap(dev, &dold)) == NULL)
696: return (DFERR);
697: f = cp->c_flag;
698: drest(dold);
699: return (f);
700: }
701:
702: /*
703: * Given a device, and a pointer to a driver map save area, save the
704: * current map in the driver map save area and map in the new device,
705: * returning a pointer to the configuration entry for that device.
706: */
707: CON *
708: drvmap(dev, doldp)
709: dev_t dev;
710: dold_t *doldp;
711: {
712: register DRV *dp;
713: register unsigned m;
714:
715: if ((m=major(dev)) >= drvn) {
716: u.u_error = ENXIO;
717: return (NULL);
718: }
719: dp = &drvl[m];
720: if (locked(dp->d_gate)) {
721: u.u_error = ENXIO;
722: return (NULL);
723: }
724: if (dp->d_conp == NULL) {
725: u.u_error = ENXIO;
726: return (NULL);
727: }
728: dsave(*doldp);
729: if (dp->d_map != 0)
730: dmapv(dp->d_map);
731: return (dp->d_conp);
732: }
733:
734: /*
735: * Non existant device.
736: */
737: nonedev()
738: {
739: u.u_error = ENXIO;
740: }
741:
742: /*
743: * Null device.
744: */
745: nulldev()
746: {
747: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.