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