|
|
1.1 root 1: /* $Header: /src386/kernel/coh.386/RCS/bio.c,v 1.8 93/06/14 13:34:10 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.8 93/06/14 13:34:10 bin
21: * Hal: kernel 78 update
22: *
23: * Revision 1.9 93/04/14 10:06:14 root
24: * r75
25: *
26: * Revision 1.7 92/10/06 23:48:44 root
27: * Ker #64
28: *
29: * Revision 1.6 92/07/27 18:15:08 hal
30: * Kernel #59
31: *
32: * Revision 1.2 92/01/06 11:58:35 hal
33: * Compile with cc.mwc.
34: *
35: * Revision 1.1 88/03/24 16:13:29 src
36: * Initial revision
37: *
38: * 87/11/05 Allan Cornish /usr/src/sys/coh/bio.c
39: * New seg struct now used to allow extended addressing.
40: *
41: * 87/01/05 Allan Cornish /usr/src/sys/coh/bio.c
42: * ioreq() now only wakes &stimer if the swap timer is active.
43: *
44: * 86/12/12 Allan Cornish /usr/src/sys/coh/bio.c
45: * Added 3rd arg to dpoll() to specify blocking poll if non-zero.
46: *
47: * 86/11/19 Allan Cornish /usr/src/sys/coh/bio.c
48: * Added dpoll() routine to perform device polls [System V.3 compatible].
49: *
50: * 86/07/24 Allan Cornish /usr/src/sys/coh/bio.c
51: * Added check in devinit() for null dp->d_conp->c_load function pointer.
52: */
53: #include <sys/coherent.h>
54: #include <sys/buf.h>
55: #include <sys/con.h>
56: #include <errno.h>
57: #include <sys/io.h>
58: #include <sys/proc.h>
59: #include <sys/sched.h>
60: #include <sys/seg.h>
61: #include <sys/stat.h>
62:
63: /*
64: * NIGEL: Whatever a "dold_t" was, there is no such thing now. Strip them
65: * out sometime soon.
66: */
67: typedef unsigned char dold_t;
68:
69: static BUF **hasharray; /* pointer to hash buckets */
70: static BUF *firstbuf; /* pointer to first in LRU chain */
71: static BUF *lastbuf; /* pointer to last in LRU chain */
72:
73: /*
74: * The following hashing algorithm is used by bclaim().
75: */
76: #define HASH(device, blockno) ((device * 257) + blockno)
77:
78: #if BDEBUG
79: #include <sys/bufdebug.h>
80:
81: static BUFDEBUG bufdebug; /* actual counters used in profiling */
82:
83: /*
84: * Perform buffer cache debugging ioctl's.
85: * These will not stay in the production release!
86: */
87: bufioctl(cmd, vec)
88: BUFDEBUG *vec;
89: {
90: switch (cmd) {
91: case BDINIT: /* clear (init) all counters */
92: kclear(&bufdebug, sizeof(bufdebug));
93: bufdebug.nbuf = NBUF;
94: bufdebug.version = BDVERSION;
95: break;
96: case BDGETVAL: /* return current counters to user */
97: kucopy(&bufdebug, vec, sizeof(bufdebug));
98: break;
99: default:
100: SET_U_ERROR(EINVAL, "bufioctl()");
101: }
102: }
103: #endif
104:
105: /*
106: * Allocate and initialize buffer headers.
107: */
108: bufinit()
109: {
110: register BUF *bp;
111: paddr_t p;
112: caddr_t v;
113: int i;
114:
115: p = MAPIO(blockp.sr_segp->s_vmem, 0);
116: v = blockp.sr_base;
117:
118: if (NBUF < 32)
119: panic("NBUF not set correctly");
120: if (NHASH < 32)
121: panic("NHASH not set correctly");
122:
123: bufl = kalloc(NBUF * sizeof(BUF));
124: hasharray = kalloc(NHASH * sizeof(BUF *));
125: if (bufl == BNULL || hasharray == BNULL)
126: panic("bufinit: insufficient memory for %d buffers", NBUF);
127:
128: for (i = 0; i < NHASH; ++i)
129: hasharray[i] = BNULL;
130:
131: /*
132: * initialize the buffer header array with the physical and
133: * virtual addresses of the buffers, NULL values for the
134: * hash chain pointers, and pointers to the successor and
135: * predecessor of the current node.
136: */
137: firstbuf = &bufl[0];
138: for (bp = lastbuf = &bufl[NBUF-1]; bp >= bufl; --bp) {
139: bp->b_dev = NODEV;
140: bp->b_paddr = p;
141: bp->b_vaddr = v;
142: bp->b_hashf = BNULL;
143: bp->b_hashb = BNULL;
144: bp->b_LRUf = bp + 1; /* next entry in chain */
145: bp->b_LRUb = bp - 1; /* prev entry in chain */
146: p += BSIZE;
147: v += BSIZE;
148: }
149: /*
150: * the first and last headers are special cases.
151: */
152: bufl[0].b_LRUb = BNULL; /* no predecessor */
153: bufl[NBUF-1].b_LRUf = BNULL; /* no successor */
154: }
155:
156: /*
157: * Synchronise the buffer cache.
158: */
159: bsync()
160: {
161: register BUF *bp;
162:
163: #if BDEBUG
164: ++bufdebug.bsync;
165: #endif
166: for (bp = &bufl[NBUF-1]; bp >= bufl; --bp) {
167: if ((bp->b_flag&BFMOD) == 0)
168: continue;
169: lock(bp->b_gate);
170: if (bp->b_flag&BFMOD)
171: bwrite(bp, 1);
172: unlock(bp->b_gate);
173: }
174: }
175:
176: /*
177: * Synchronise all block for a particular device in the buffer cache
178: * and invalidate all references.
179: */
180: bflush(dev)
181: register dev_t dev;
182: {
183: register BUF *bp;
184:
185: #if BDEBUG
186: ++bufdebug.bflush;
187: #endif
188: for (bp = &bufl[NBUF-1]; bp >= bufl; --bp) {
189: if (bp->b_dev != dev)
190: continue;
191: lock(bp->b_gate);
192: if (bp->b_dev == dev) {
193: if (bp->b_flag&BFMOD)
194: bwrite(bp, 1);
195: bp->b_dev = NODEV;
196: }
197: unlock(bp->b_gate);
198: }
199: }
200:
201: /*
202: * Return a buffer containing the given block from the given device.
203: * If `sync' is not set, the read is asynchronous and no buffer is returned.
204: */
205: BUF *
206: bread(dev, bno, sync)
207: dev_t dev;
208: daddr_t bno;
209: register int sync;
210: {
211: register BUF *bp;
212: register int s;
213:
214: #if BDEBUG
215: ++bufdebug.bread;
216: #endif
217: bp = bclaim(dev, bno);
218: if (bp->b_flag&BFNTP) {
219: if (sync)
220: bp->b_flag &= ~BFASY;
221: else {
222: bp->b_flag |= BFASY;
223: bumap(bp);
224: }
225: bp->b_req = BREAD;
226: bp->b_count = BSIZE;
227: /*
228: * NIGEL: It is my sincere hope that whoever put this sphi () here (and in the
229: * corresponding places lower down) was simply having a bad day and that there
230: * is no real reason for this. Delete this comment and the bad code as soon as
231: * we have determined that it isn't really important. Look for the sign of the
232: * good and bad magicians below...
233: *
234: * BAD MAGIC s = sphi();
235: */
236: dblock(dev, bp);
237: if (!sync) {
238: /* BAD MAGIC spl(s); */
239: return (NULL);
240: }
241: /*
242: * If buffer is not valid, wait for it.
243: */
244:
245: s = sphi (); /* GOOD MAGIC */
246: while (bp->b_flag&BFNTP) {
247: x_sleep((char *)bp, pridisk, slpriNoSig, "bpwait");
248: /* If buffer is not valid, wait for it. */
249: }
250: spl(s);
251: if (bp->b_flag&BFERR) {
252: SET_U_ERROR(bp->b_err ? bp->b_err : EIO, "bread()");
253: brelease(bp);
254: return (NULL);
255: }
256: if (bp->b_resid == BSIZE) {
257: brelease(bp);
258: return (NULL);
259: }
260: }
261: if (!sync) {
262: brelease(bp);
263: return (NULL);
264: }
265: u.u_block++;
266: return (bp);
267: }
268:
269: /*
270: * Perform an LRU chain update by unlinking the specified buffer
271: * from it present location in the LRU chain and inserting it
272: * at the head of the chain, as pointed to by "firstbuf". Handle
273: * updating "lastbuf" if current buffer is the last buffer on the chain.
274: */
275: static
276: LRUupdate(bp)
277: register BUF *bp;
278: {
279: if (bp != firstbuf) {
280: if (bp == lastbuf)
281: lastbuf = bp->b_LRUb;
282: if (bp->b_LRUb != BNULL)
283: bp->b_LRUb->b_LRUf = bp->b_LRUf;
284: if (bp->b_LRUf != BNULL)
285: bp->b_LRUf->b_LRUb = bp->b_LRUb;
286: bp->b_LRUb = BNULL;
287: bp->b_LRUf = firstbuf;
288: firstbuf->b_LRUb = bp;
289: firstbuf = bp;
290: }
291: }
292:
293: /*
294: * If the requested buffer header is in the hash chain, delete it.
295: */
296: static
297: HASHdelete(bp)
298: register BUF *bp;
299: {
300: if (bp->b_hashb == BNULL) { /* we're first in the chain */
301: hasharray[bp->b_hashval] = bp->b_hashf;
302: if (bp->b_hashf != BNULL)
303: bp->b_hashf->b_hashb = BNULL;
304: } else {
305: bp->b_hashb->b_hashf = bp->b_hashf;
306: if (bp->b_hashf != BNULL)
307: bp->b_hashf->b_hashb = bp->b_hashb;
308: }
309: bp->b_hashf = BNULL;
310: bp->b_hashb = BNULL;
311: }
312:
313: /*
314: * Insert the current buffer at the head of the appropriate hash chain.
315: */
316: static
317: HASHinsert(bp)
318: register BUF *bp;
319: {
320: if (bp->b_hashf != BNULL || bp->b_hashb != BNULL)
321: panic("HASHinsert");
322: bp->b_hashf = hasharray[bp->b_hashval];
323: if (bp->b_hashf != BNULL)
324: bp->b_hashf->b_hashb = bp;
325: hasharray[bp->b_hashval] = bp;
326: }
327:
328: /*
329: * If the requested buffer is in the buffer cache, return a pointer to
330: * it. If not, pick an empty buffer, set it up and return it.
331: */
332: BUF *
333: bclaim(dev, bno)
334: dev_t dev;
335: register daddr_t bno;
336: {
337: register BUF *bp;
338: register int s;
339: unsigned long hashval;
340: static GATE bufgate; /* better than sphi()/spl() */
341:
342: #if BDEBUG
343: ++bufdebug.bclaim;
344: #endif
345: hashval = HASH(dev, bno) % NHASH; /* select a hash bucket */
346:
347: again:
348: lock(bufgate); /* avoid pointer updates */
349:
350: for (bp = hasharray[hashval]; bp != BNULL; bp = bp->b_hashf) {
351: #if BDEBUG
352: ++bufdebug.compares;
353: #endif
354: if (bp->b_bno == bno && bp->b_dev == dev) {
355: lock(bp->b_gate);
356: if (bp->b_bno != bno || bp->b_dev != dev) {
357: #if BDEBUG
358: ++bufdebug.fails;
359: #endif
360: unlock(bp->b_gate);
361: unlock(bufgate);
362: goto again;
363: }
364: #if BDEBUG
365: ++bufdebug.hits;
366: #endif
367: /*
368: * Now that we have located the buffer in the cache,
369: * unlink it from its current location in the
370: * LRU chain and move it to the front.
371: */
372: LRUupdate(bp);
373:
374: /*
375: * If the buffer had an I/O error, mark it as
376: * invalid. Unlock the buffer gate and return
377: * the buffer to the requestor.
378: */
379: if (bp->b_flag&BFERR)
380: bp->b_flag |= BFNTP;
381: unlock(bufgate);
382: bsmap(bp);
383: return (bp);
384: }
385: }
386: unlock(bufgate);
387: #if BDEBUG
388: ++bufdebug.misses;
389: #endif
390:
391: /*
392: * The requested buffer is not resident in our cache. Locate the
393: * oldest (least recently used) available buffer. If it's dirty,
394: * queue up an asynchronous write for it and continue searching
395: * for the next old candidate. Once a candidate is found, move it
396: * to the front of the LRU chain, update the hash pointers, mark
397: * the buffer as invalid, unlock our buffer gate and return the
398: * buffer to the requestor.
399: */
400: for (;;) { /* loop until successful */
401: lock(bufgate);
402: for (bp = lastbuf; bp != BNULL; bp = bp->b_LRUb) {
403: if (locked(bp->b_gate))
404: continue; /* not available */
405: s = sphi();
406: if (locked(bp->b_gate)) {
407: spl(s);
408: continue; /* they snuck in ;-) */
409: }
410: lock(bp->b_gate);
411: spl(s);
412: if (bp->b_flag&BFMOD)
413: bwrite(bp, 0); /* flush dirty buffer */
414: else {
415: /*
416: * Update the hash chain for this old
417: * buffer. Unlink it from it's old location
418: * fixing up any references. Also, update
419: * the LRU chain to move the buffer to the head.
420: */
421: HASHdelete(bp);
422: LRUupdate(bp);
423:
424: bp->b_flag = BFNTP;
425: bp->b_dev = dev;
426: bp->b_bno = bno;
427: bp->b_hashval = hashval;
428:
429: HASHinsert(bp);
430: unlock(bufgate);
431: bsmap(bp);
432: return (bp);
433: }
434: }
435: unlock(bufgate);
436: #if BDEBUG
437: ++bufdebug.needbuf;
438: #endif
439: s = sphi();
440: bufneed = 1;
441: x_sleep((char *)&bufneed, pridisk, slpriNoSig, "bufneed");
442: /* There are no buffers available. */
443: spl(s);
444: } /* forever */
445: }
446:
447: /*
448: * Write the given buffer out. If `sync' is set, the write is synchronous,
449: * otherwise asynchronous. This routine must be called with the buffer
450: * gate locked.
451: */
452: bwrite(bp, sync)
453: register BUF *bp;
454: {
455: register int s;
456:
457: #if BDEBUG
458: ++bufdebug.bwrite;
459: #endif
460: if (sync)
461: bp->b_flag &= ~BFASY;
462: else {
463: bp->b_flag |= BFASY;
464: bumap(bp);
465: }
466: bp->b_flag |= BFNTP;
467: bp->b_req = BWRITE;
468: bp->b_count = BSIZE;
469: /* BAD MAGIC s = sphi(); */
470: dblock(bp->b_dev, bp);
471: if (!sync) {
472: /* BAD MAGIC spl(s); */
473: return;
474: }
475: s = sphi (); /* GOOD MAGIC */
476: while (bp->b_flag&BFNTP) {
477: x_sleep((char *)bp, pridisk, slpriNoSig, "bwrite");
478: /* Waiting for a buffer write to finish. */
479: }
480: spl(s);
481: }
482:
483: /*
484: * This is called by the driver when I/O has completed on a buffer.
485: */
486: bdone(bp)
487: register BUF *bp;
488: {
489: #if BDEBUG
490: ++bufdebug.bdone;
491: #endif
492: if (bp->b_req == BWRITE)
493: bp->b_flag &= ~BFMOD;
494: if (bp->b_req == BREAD) {
495: if (bp->b_flag&BFERR)
496: bp->b_dev = NODEV;
497: }
498: if (bp->b_flag&BFASY) {
499: bp->b_flag &= ~BFASY;
500: brelease(bp);
501: }
502: bp->b_flag &= ~BFNTP;
503: dwakeup((char *)bp);
504: }
505:
506: /*
507: * Release the given buffer.
508: */
509: brelease(bp)
510: register BUF *bp;
511: {
512: #if BDEBUG
513: ++bufdebug.brelease;
514: #endif
515: if (bp->b_flag&BFERR) {
516: bp->b_flag &= ~BFERR;
517: bp->b_dev = NODEV;
518: }
519: bp->b_flag &= ~BFNTP;
520: bumap(bp);
521: unlock(bp->b_gate);
522: if (bufneed) {
523: bufneed = 0;
524: wakeup((char *)&bufneed);
525: }
526: }
527:
528: /*
529: * Map the given buffer.
530: */
531: bsmap(bp)
532: register BUF *bp;
533: {
534: bsave(bp->b_map);
535: bp->b_flag |= BFMAP;
536: bmapv(bconv(bp->b_paddr));
537: }
538:
539: /*
540: * Unmap the given buffer.
541: */
542: bumap(bp)
543: register BUF *bp;
544: {
545: if ((bp->b_flag&BFMAP) == 0)
546: return;
547: bp->b_flag &= ~BFMAP;
548: brest(bp->b_map);
549: }
550:
551: /*
552: * Read data from the I/O segment into kernel space.
553: *
554: * "v" is the destination virtual address.
555: * "n" is the number of bytes to read.
556: */
557: ioread(iop, v, n)
558: register IO *iop;
559: register char *v;
560: register unsigned n;
561: {
562: #if BDEBUG
563: ++bufdebug.ioread;
564: #endif
565: switch (iop->io_seg) {
566: case IOSYS:
567: #if BDEBUG
568: ++bufdebug.iosys;
569: #endif
570: iop->io.vbase += kkcopy(iop->io.vbase, v, n);
571: break;
572: case IOUSR:
573: #if BDEBUG
574: ++bufdebug.iousr;
575: #endif
576: iop->io.vbase += ukcopy(iop->io.vbase, v, n);
577: break;
578: case IOPHY:
579: #if BDEBUG
580: ++bufdebug.iophy;
581: #endif
582: dmain(n, iop->io.pbase, v);
583: iop->io.pbase += n;
584: break;
585: }
586: iop->io_ioc -= n;
587: }
588:
589: /*
590: * Write data from kernel space to the I/O segment.
591: */
592: iowrite(iop, v, n)
593: register IO *iop;
594: register char *v;
595: register unsigned n;
596: {
597: #if BDEBUG
598: ++bufdebug.iowrite;
599: #endif
600: switch (iop->io_seg) {
601: case IOSYS:
602: #if BDEBUG
603: ++bufdebug.iosys;
604: #endif
605: iop->io.vbase += kkcopy(v, iop->io.vbase, n);
606: break;
607: case IOUSR:
608: #if BDEBUG
609: ++bufdebug.iousr;
610: #endif
611: iop->io.vbase += kucopy(v, iop->io.vbase, n);
612: break;
613: case IOPHY:
614: #if BDEBUG
615: ++bufdebug.iophy;
616: #endif
617: dmaout(n, iop->io.pbase, v);
618: iop->io.pbase += n;
619: break;
620: }
621: iop->io_ioc -= n;
622: }
623:
624: /*
625: * Get a character from the I/O segment.
626: */
627: iogetc(iop)
628: register IO *iop;
629: {
630: register int c;
631:
632: #if BDEBUG
633: ++bufdebug.iogetc;
634: #endif
635: if (iop->io_ioc == 0)
636: return (-1);
637: --iop->io_ioc;
638: if (iop->io_seg == IOSYS)
639: c = *(char*) iop->io.vbase++ & 0377;
640: else {
641: c = getubd(iop->io.vbase++);
642: if (u.u_error)
643: return (-1);
644: }
645: return (c);
646: }
647:
648: /*
649: * Put a character using the I/O segment.
650: */
651: ioputc(c, iop)
652: register IO *iop;
653: {
654: #if BDEBUG
655: ++bufdebug.ioputc;
656: #endif
657: if (iop->io_ioc == 0)
658: return (-1);
659: --iop->io_ioc;
660: if (iop->io_seg == IOSYS)
661: * (char *)iop->io.vbase++ = c;
662: else {
663: putubd(iop->io.vbase++, c);
664: if (u.u_error)
665: return (-1);
666: }
667: return (c);
668: }
669:
670: /*
671: * Given a buffer pointer, an I/O structure, a device, request type, and
672: * a flags word, check the I/O structure and perform the I/O request.
673: */
674: ioreq(bp, iop, dev, req, f)
675: register BUF *bp;
676: register IO *iop;
677: dev_t dev;
678: {
679: register int n;
680: register int s;
681: register CON *cp;
682: dold_t dold;
683:
684: #if BDEBUG
685: ++bufdebug.ioreq;
686: #endif
687: if ((cp=drvmap(dev, &dold)) == NULL)
688: return;
689: lock(bp->b_gate);
690: n = cp->c_flag; /* n should do something with that flag */
691: drest(dold);
692: if (iop) {
693: if (f&BFBLK) {
694: if (blocko(iop->io_seek)) {
695: SET_U_ERROR(EIO, "ioreq()");
696: goto out;
697: }
698: }
699: if (f&BFIOC) {
700: if (!iomapvp(iop, bp)) {
701: SET_U_ERROR(EIO, "ioreq()");
702: goto out;
703: }
704: }
705: }
706: bp->b_flag = f|BFNTP;
707: bp->b_req = req;
708: bp->b_dev = dev;
709: if (iop) {
710: bp->b_bno = blockn(iop->io_seek);
711: bp->b_count = iop->io_ioc;
712: }
713: /*BAD MAGIC s = sphi(); */
714: dblock(dev, bp);
715: s = sphi (); /* GOOD MAGIC */
716: while (bp->b_flag&BFNTP) {
717: x_sleep((char *)bp, pridisk, slpriNoSig, "ioreq");
718: /* Ask norm what this sleep means. */
719: }
720: spl(s);
721: if (stimer.t_last)
722: wakeup((char *)&stimer);
723: if (bp->b_flag&BFERR) {
724: SET_U_ERROR(bp->b_err ? bp->b_err : EIO, "ioreq()");
725: goto out;
726: }
727: if (iop) {
728: n = iop->io_ioc - bp->b_resid;
729: iop->io_seek += n;
730: iop->io_ioc -= n;
731: }
732: out:
733: unlock(bp->b_gate);
734: }
735:
736: /*
737: * Given an I/O structure and a buffer header, see if the addresses
738: * in the I/O structure are valid and set up the buffer header.
739: *
740: * Search the u area segment table for a data segment containing
741: * iop->io.vbase. If one is found, put the corresponding system
742: * global address into bp->b_paddr and return the corresponding
743: * SEG pointer, else return NULL.
744: */
745: SEG *
746: iomapvp(iop, bp)
747: register IO *iop;
748: register BUF *bp;
749: {
750: register SR *srp;
751: register SEG *sp;
752: register caddr_t iobase, base;
753: unsigned ioc;
754: int i;
755:
756: if (iop->io_seg != IOUSR)
757: panic("Raw I/O from non user");
758:
759: iobase = iop->io.vbase;
760: ioc = iop->io_ioc;
761:
762: for (srp = u.u_segl; srp < &u.u_segl[NUSEG]; srp++) {
763: if ((sp = srp->sr_segp) == NULL)
764: continue;
765: if ((srp->sr_flag&SRFDATA) == 0)
766: continue;
767: /*
768: * The following calculation is because the system represents
769: * the 'base' of a stack as its upper limit (because it is the
770: * upper limit that is fixed).
771: */
772: base = srp->sr_base;
773: if (srp==&u.u_segl[SISTACK])
774: base -= srp->sr_size;
775:
776: if (iobase < base)
777: continue;
778: if (iobase + ioc > base + sp->s_size)
779: continue;
780: bp->b_paddr = MAPIO(sp->s_vmem, iobase - base);
781: return sp;
782: }
783:
784: /* Is the io area in question contained in a shared memory segment? */
785: if (srp = accShm(iobase, ioc)) {
786: sp = srp->sr_segp;
787: base = srp->sr_base;
788: bp->b_paddr = MAPIO(sp->s_vmem, iobase - base);
789: return sp;
790: }
791:
792: return 0;
793: }
794:
795: /*
796: * Initialise devices.
797: * Mark all initialized devices as loaded.
798: */
799: devinit()
800: {
801: register DRV *dp;
802: register int mind;
803:
804: for ( dp = drvl, mind = 0; mind < drvn; mind++, dp++ ) {
805: if (dp->d_conp && dp->d_conp->c_load) {
806: (*dp->d_conp->c_load)();
807: dev_loaded |= (1<<mind);
808: }
809: }
810:
811: /*
812: * Inform STREAMS that it is time to set up shop.
813: */
814:
815: STREAMS_INIT ();
816: }
817:
818: /*
819: * Open a device.
820: *
821: * NIGEL: In order to make it at all possible to support the System V DDI/DDK
822: * calling conventions for driver entry points, it is necessary for this code
823: * to pass the *type* of open being made to the underlying device (which is
824: * passed in the 'f' parameter below).
825: */
826: dopen(dev, m, f)
827: register dev_t dev;
828: {
829: register CON *cp;
830: dold_t dold;
831:
832: if ((cp=drvmap(dev, &dold)) == NULL)
833: return;
834: if ((cp->c_flag&f) == 0) {
835: SET_U_ERROR(ENXIO, "dopen()");
836: return;
837: }
838: (*cp->c_open)(dev, m, f); /* NIGEL */
839: drest(dold);
840: }
841:
842: /*
843: * Close a device.
844: *
845: * NIGEL: In order to be able to support the System V DDI/DDK calling
846: * conventions for driver entry points, this function has to be altered to
847: * accept a file-mode and character/block mode parameter. Note that the
848: * Coherent 4.0 driver kit documentation says that the driver close entry
849: * point is passed the same parameters as the open entry. After this mod,
850: * this will be true for the first time.
851: */
852: dclose(dev, mode, typ)
853: register dev_t dev;
854: {
855: register CON *cp;
856: dold_t dold;
857:
858: if ((cp=drvmap(dev, &dold)) == NULL)
859: return;
860: (*cp->c_close)(dev, mode, typ); /* NIGEL */
861: drest(dold);
862: }
863:
864: /*
865: * Call the block entry point of a device.
866: */
867: dblock(dev, bp)
868: dev_t dev;
869: BUF *bp;
870: {
871: register CON *cp;
872: dold_t dold;
873:
874: if ((cp=drvmap(dev, &dold)) == NULL)
875: return;
876: (*cp->c_block)(bp);
877: drest(dold);
878: }
879:
880: /*
881: * Read from a device.
882: */
883: dread(dev, iop)
884: register dev_t dev;
885: register IO *iop;
886: {
887: register CON *cp;
888: dold_t dold;
889:
890: if ((cp=drvmap(dev, &dold)) == NULL)
891: return;
892: (*cp->c_read)(dev, iop);
893: drest(dold);
894: }
895:
896: /*
897: * Write to a device.
898: */
899: dwrite(dev, iop)
900: register dev_t dev;
901: register IO *iop;
902: {
903: register CON *cp;
904: dold_t dold;
905:
906: if ((cp=drvmap(dev, &dold)) == NULL)
907: return;
908: (*cp->c_write)(dev, iop);
909: drest(dold);
910: }
911:
912: /*
913: * Call the ioctl function for a device.
914: *
915: * NIGEL: In order to support the System V DDI/DDK calling conventions for
916: * device driver entry points, this function needs to pass a "mode" parameter
917: * indicating the open mode of the file. There are only two calls to this
918: * function, for uioctl () and in the /dev/tty driver, "io.386/ct.c" which is
919: * passing its arguments back here (ie, a layered open). The "ct.c" call has
920: * not been changed.
921: */
922: dioctl(dev, com, vec, mode)
923: register dev_t dev;
924: union ioctl *vec;
925: {
926: register CON *cp;
927: dold_t dold;
928:
929: if ((cp=drvmap(dev, &dold)) == NULL)
930: return;
931: if (XMODE_286)
932: tioc(dev, com, vec, cp->c_ioctl);
933: else
934: (*cp->c_ioctl)(dev, com, vec, mode); /* NIGEL */
935: drest(dold);
936: }
937:
938: /*
939: * Call the powerfail entry point of a device.
940: */
941: dpower(dev)
942: register dev_t dev;
943: {
944: register CON *cp;
945: dold_t dold;
946:
947: if ((cp=drvmap(dev, &dold)) == NULL)
948: return;
949: (*cp->c_power)(dev);
950: drest(dold);
951: }
952:
953: /*
954: * Call the timeout entry point of a device.
955: */
956: dtime(dev)
957: register dev_t dev;
958: {
959: register CON *cp;
960: dold_t dold;
961:
962: if ((cp=drvmap(dev, &dold)) == NULL)
963: return;
964: (*cp->c_timer)(dev);
965: drest(dold);
966: }
967:
968: /*
969: * Poll a device.
970: */
971: dpoll(dev, ev, msec)
972: register dev_t dev;
973: int ev;
974: int msec;
975: {
976: register CON *cp;
977: dold_t dold;
978:
979: if ((cp=drvmap(dev, &dold)) == NULL)
980: return POLLNVAL;
981:
982: if ( cp->c_flag & DFPOL )
983: ev = (*cp->c_poll)(dev, ev, msec);
984: else
985: ev = POLLNVAL;
986:
987: drest(dold);
988: return ev;
989: }
990:
991: /*
992: * Given a device, and a pointer to a driver map save area, save the
993: * current map in the driver map save area and map in the new device,
994: * returning a pointer to the configuration entry for that device.
995: *
996: * NIGEL: This function is the only code that references drvl [] directly
997: * other than the bogus code that manages the load and unload entry points,
998: * which we will also need to "enhance". What we add to this code is a range
999: * check so that it no longer can index off the end of drvl [], and in the
1000: * case that we would go off the end of drvl [] we vector instead to the
1001: * STREAMS system and ask it to return a kludged-up "CON *". The mapping
1002: * code referred to above is for the i286 and does nothing whatsoever, so
1003: * all this function really does as it stands is a table lookup.
1004: */
1005: CON *
1006: drvmap(dev, doldp)
1007: dev_t dev;
1008: dold_t *doldp;
1009: {
1010: register DRV *dp;
1011: register unsigned m;
1012:
1013: if ((m=major(dev)) >= drvn) {
1014: CON * conp;
1015:
1016: /*
1017: * NIGEL: If STREAMS is disabled or there is no device
1018: * corresponding to this (external) major number, flag ENXIO.
1019: */
1020:
1021: if ((conp = STREAMS_GETCON (dev)) != NULL)
1022: return conp;
1023:
1024: SET_U_ERROR(ENXIO, "drvmap()");
1025: return (NULL);
1026: }
1027: dp = &drvl[m];
1028: if (locked(dp->d_gate)) {
1029: SET_U_ERROR(ENXIO, "drvmap()");
1030: return (NULL);
1031: }
1032: if (dp->d_conp == NULL) {
1033: SET_U_ERROR(ENXIO, "drvmap()");
1034: return (NULL);
1035: }
1036: dsave(*doldp);
1037: #ifndef _I386
1038: if (dp->d_map)
1039: dmapv(dp->d_map);
1040: #endif
1041: return (dp->d_conp);
1042: }
1043:
1044: /*
1045: * Non existant device.
1046: */
1047: nonedev()
1048: {
1049: SET_U_ERROR(ENXIO, "nonedev()");
1050: }
1051:
1052: /*
1053: * Null device.
1054: */
1055: nulldev()
1056: {
1057: }
1058:
1059: #if 0
1060: /* debugging utility. given a system global addr (e.g. iop->io.pbase),
1061: return the first int at the address */
1062: grabDB(paddr)
1063: {
1064: int ret;
1065: int work = workAlloc();
1066: cseg_t * base = sysmem.u.pbase + btocrd(paddr);
1067:
1068: ptable1_v[work] = *base | SEG_SRW;
1069: mmuupd();
1070: ret = *(int*)(ctob(work)+(paddr&(NBPC-1)));
1071: workFree(work);
1072: return ret;
1073: }
1074: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.