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