|
|
1.1 root 1: /* $Header: /kernel/kersrc/ldrv/RCS/ldmain.c,v 1.1 92/07/17 15:27:53 bin Exp Locker: bin $ */
2: /*
3: * The information contained herein is a trade secret of INETCO
4: * Systems, and is confidential information. It is provided under
5: * a license agreement, and may be copied or disclosed only under
6: * the terms of that agreement. Any reproduction or disclosure of
7: * this material without the express written authorization of
8: * INETCO Systems or persuant to the license agreement is unlawful.
9: *
10: * Copyright (c) 1987
11: * An unpublished work by INETCO Systems, Ltd.
12: * All rights reserved.
13: */
14:
15: /*
16: * Loadable Driver - Process Handler.
17: *
18: * $Log: ldmain.c,v $
19: * Revision 1.1 92/07/17 15:27:53 bin
20: * Initial revision
21: *
22: * Revision 1.2 89/03/31 16:19:36 src
23: * Bug: Did not cancel either attached timed functions or deferred functions
24: * during an unload. As a result, if a driver did not explicitly do
25: * this, then unloading the driver could cause a system panic.
26: * Fix: Now cancels the functions. (ABC)
27: *
28: * Revision 1.1 88/03/24 08:30:44 src
29: * Initial revision
30: *
31: * 87/12/03 Allan Cornish /usr/src/sys/ldrv/ldmain.c
32: * Initial version.
33: */
34: #include <sys/coherent.h>
35: #include <sys/proc.h>
36: #include <sys/sched.h>
37: #include <sys/con.h>
38: #include <sys/seg.h>
39: #include <sys/stat.h>
40: #include <sys/uproc.h>
41:
42: extern CON con;
43:
44: extern saddr_t ldrvsel[NDRV];
45: extern saddr_t ldrvics[16];
46: extern void (*ldrvipc[16])();
47: extern CON * ldrvcon[NDRV];
48: extern CON ldrvpsy;
49: extern saddr_t ucs;
50:
51: /*
52: * Local variable - keeps track of the number of opens.
53: * The loadable driver can't terminate until after the last close.
54: * Openf is the loadable driver open routine.
55: * Closef points to the driver's close routine.
56: * The configuration table entries are taken over
57: */
58: static int nopen = 0;
59: static void (*openf)() = NULL;
60: static void (*closef)() = NULL;
61:
62: main()
63: {
64: register int mind = con.c_mind;
65: register int level;
66: extern void myopen();
67: extern void myclose();
68: extern void Kdefend();
69:
70: /*
71: * Loadable devices must identify the desired major device.
72: */
73: if ( (mind == 0) || (mind >= drvn) ) {
74: printf("ldrv:%d: bad dev\n", mind );
75: uexit( 1 );
76: }
77:
78: /*
79: * Loadable devices must use a unique [not in use] major device.
80: */
81: if ( (drvl[mind].d_conp != NULL) || (ldrvcon[mind] != NULL) ) {
82: printf("ldrv:%d: dev bsy\n", mind );
83: uexit( 0 );
84: }
85:
86: /*
87: * Intercept driver open/close requests.
88: * This allows the driver process to terminate after the last close,
89: * if one or more signals have been received.
90: */
91: openf = con.c_open;
92: closef = con.c_close;
93: con.c_open = myopen;
94: con.c_close = myclose;
95:
96: /*
97: * Install the loadable driver pseudo device interface.
98: * The O/S will call the pseudo-device, which will call us.
99: * Record our driver configuration and code segment.
100: */
101: drvl[mind].d_conp = &ldrvpsy;
102: ldrvcon[mind] = &con;
103: ldrvsel[mind] = ucs;
104:
105: /*
106: * Load the device driver.
107: */
108: if ( con.c_load != NULL )
109: (*con.c_load)( makedev(mind,0) );
110:
111: /*
112: * Sleep until a kill signal has arrived, and no device is open.
113: */
114: do {
115: sleep( (char *)&nopen, CVSWAP, IVSWAP, SVSWAP );
116:
117: } while ( ((SELF->p_ssig & 0x0100) == 0) || (nopen != 0) );
118:
119: /*
120: * Unload the device driver.
121: */
122: if ( con.c_uload != NULL )
123: (*con.c_uload)( makedev(mind,0) );
124:
125: /*
126: * Erase references to our kernel process.
127: */
128: drvl[mind].d_conp = NULL;
129: ldrvcon[mind] = NULL;
130: ldrvsel[mind] = 0;
131:
132: /*
133: * Scan looking for attached interrupts.
134: * NOTE: This is to prevent dangling interrupt vectors.
135: */
136: for ( level = 0; level < 16; level++ ) {
137:
138: /*
139: * Interrupt is not attached to us.
140: */
141: if ( ldrvics[level] != ucs )
142: continue;
143:
144: /*
145: * Disable interrupt.
146: */
147: clrivec( level );
148:
149: /*
150: * Release loadable driver interrupt.
151: */
152: ldrvics[level] = 0;
153: ldrvipc[level] = NULL;
154: }
155:
156: /*
157: * Service deferred functions BEFORE scanning for timed functions.
158: * This is in case a deferred function schedules a timed function.
159: */
160: kcall( Kdefend );
161:
162: /*
163: * Scan for attached timed functions which have to be terminated.
164: */
165: for ( level = 0; level < nel(timq); level++ ) {
166: register TIM * tp;
167:
168: /*
169: * Access a specific timing queue.
170: */
171: for ( tp = timq[level]; tp != NULL; ) {
172:
173: /*
174: * Timed function is in our loadable driver.
175: * Restart search at start of timing queue.
176: */
177: if ( FP_SEL(tp->t_ldrv) == getcs() ) {
178: timeout( tp, 0, NULL, 0 );
179: tp = timq[ level ];
180: }
181:
182: /*
183: * Not one of our timed functions.
184: * Advance to next function in queue.
185: */
186: else
187: tp = tp->t_next;
188: }
189: }
190:
191: /*
192: * Terminate with extreme prejudice.
193: */
194: uexit( 0 );
195: }
196:
197: static void
198: myopen( dev, mode )
199: dev_t dev;
200: int mode;
201: {
202: /*
203: * Invoke the true open routine for the loadable driver.
204: */
205: if ( openf != NULL )
206: (*openf)(dev, mode );
207:
208: /*
209: * Adjust reference count if open succeeded.
210: */
211: if ( u.u_error == 0 )
212: nopen++;
213: }
214:
215: static void
216: myclose( dev )
217: dev_t dev;
218: {
219: /*
220: * Invoke the true close routine for the loadable driver.
221: */
222: if ( closef != NULL )
223: (*closef)( dev );
224:
225: /*
226: * Wakeup driver process after last close.
227: * This allows it to terminate if appropriate.
228: */
229: if ( --nopen == 0 )
230: wakeup( (char*) &nopen );
231: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.