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