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