|
|
1.1 root 1: /*
2: * This file contains the entry points into the STREAMS system called by the
3: * Coherent kernel.
4: */
5:
6: #define _DDI_DKI 1
7: #define _SYSV3 1
8:
9: #include <kernel/ddi_cpu.h>
10: #include <kernel/ddi_glob.h>
11: #include <sys/confinfo.h>
12: #include <sys/types.h>
13: #include <sys/cmn_err.h>
14: #include <stdlib.h>
15:
16: #ifdef __MSDOS__
17: #include <sys/_con.h>
18: #else
19: #include <sys/con.h>
20: #endif
21:
22:
23: /*
24: * Refer to memory allocated by "space.c" file from tunable parameters.
25: */
26:
27: extern size_t _streams_size;
28: extern uchar_t _streams_heap [];
29:
30:
31: __EXTERN_C_BEGIN__
32:
33: int INTR_INIT __PROTO ((void));
34: int DDI_GLOB_INIT __PROTO ((void));
35: int KMEM_INIT __PROTO ((_VOID * _addr, size_t _size));
36: int LOCK_TESTS __PROTO ((int _negative));
37:
38: __EXTERN_C_END__
39:
40:
41: #if __BORLANDC__
42:
43: void SETIVEC __PROTO ((int _num));
44: void CLRIVEC __PROTO ((int _num));
45:
46: #elif __COHERENT__
47:
48: void setivec __PROTO ((int _num, intthunk_t _thunk));
49: void clrivec __PROTO ((int _num));
50:
51: #define SETIVEC(num) setivec (inttab [num].int_vector, \
52: inttab [num].int_thunk)
53:
54: #define CLRIVEC(num) clrivec (inttab [num].int_vector)
55:
56: #else /* if ! __COHERENT */
57:
58: #error How do I set up interrupts?
59:
60: #endif /* ! __COHERENT__ */
61:
62:
63: /*
64: * Global start/exit state. We use this so that if an exit or halt routine
65: * panics (which may cause a retry of the shutdown process) we can try again.
66: */
67:
68: static int _exitlevel;
69: static int _intlevel;
70: static int _haltlevel;
71:
72:
73: /*
74: * Since we don't have a real trap-handler, I have factored out the deferred-
75: * function check to here.
76: *
77: * Entered with interrupts disabled. This routine must be able to enable
78: * interrupts without causing excess stack growth. Note that if we have
79: * interrupt prologue and epilogue code in assembly language, a rather
80: * different loop structure might work out simpler.
81: */
82:
83: #if __USE_PROTO__
84: __LOCAL__ int (RUN_INT_DEFER) (defer_t * deferp)
85: #else
86: __LOCAL__ int
87: RUN_INT_DEFER __ARGS ((deferp))
88: defer_t * deferp;
89: #endif
90: {
91: int recheck = 0;
92: int idx;
93:
94: /*
95: * If we detected a non-empty global defer table, try and lock the
96: * table before processing the deferred routines. Only try once; if
97: * the table is busy, then someone else must be dealing with it.
98: */
99:
100: if (ATOMIC_FETCH_AND_STORE_UCHAR (deferp->df_rlock, 1) != 0)
101: return 1;
102:
103: while ((idx = ATOMIC_FETCH_UCHAR (deferp->df_read)) !=
104: ATOMIC_FETCH_UCHAR (deferp->df_write)) {
105: __CHEAP_ENABLE_INTS ();
106:
107: (* deferp->df_tab [idx ++]) ();
108:
109: if (idx == ATOMIC_FETCH_UCHAR (deferp->df_max))
110: idx = 0;
111:
112: ATOMIC_STORE_UCHAR (deferp->df_read, idx);
113:
114: recheck = 1;
115:
116: __CHEAP_DISABLE_INTS ();
117: }
118:
119: /*
120: * Release the lock on the global defer table.
121: */
122:
123: ATOMIC_STORE_UCHAR (deferp->df_rlock, 0);
124:
125: return recheck;
126: }
127:
128: #ifdef __MSDOS__
129:
130: #include <dos.h>
131:
132: void CHECK_DEFER (void) {
133: while (RUN_INT_DEFER (& ddi_global_data ()->dg_defint) ||
134: RUN_INT_DEFER (& ddi_cpu_data ()->dc_defint))
135: (* (char __far *) MK_FP (0xB800, 6)) ++;
136:
137: /*
138: * For breaking out of bad situations... hold right shift.
139: */
140:
141: if ((* (char __far *) MK_FP (0x40, 0x17) & 1) != 0)
142: cmn_err (CE_PANIC, "Emergency abort!");
143:
144: }
145: #endif
146:
147: #ifdef __COHERENT__
148:
149: #if __USE_PROTO__
150: void (STREAMS_SCHEDULER) (void)
151: #else
152: void
153: STREAMS_SCHEDULER __ARGS (())
154: #endif
155: {
156: __CHEAP_DISABLE_INTS ();
157:
158: while (RUN_INT_DEFER (& ddi_global_data ()->dg_defint) ||
159: RUN_INT_DEFER (& ddi_cpu_data ()->dc_defint))
160: ; /* DO NOTHING */
161:
162: __CHEAP_ENABLE_INTS ();
163: }
164: #endif /* ! defined (__COHERENT__) */
165:
166:
167: /*
168: * Shut things down, in the right order.
169: */
170:
171: #if __USE_PROTO__
172: void (STREAMS_EXIT) (void)
173: #else
174: void
175: STREAMS_EXIT __ARGS (())
176: #endif
177: {
178: spltimeout ();
179: ddi_cpu_data ()->dc_int_level = 0;
180:
181: while (_exitlevel > 0)
182: (* exittab [-- _exitlevel]) ();
183:
184: /*
185: * Turn off interrupts.
186: */
187:
188: while (_intlevel > 0)
189: CLRIVEC (-- _intlevel);
190:
191: while (_haltlevel > 0)
192: (* halttab [-- _haltlevel]) ();
193: }
194:
195:
196: /*
197: * Get an old Coherent "CON" entry.
198: */
199:
200: #if __USE_PROTO__
201: CON * (STREAMS_GETCON) (o_dev_t dev)
202: #else
203: CON *
204: STREAMS_GETCON __ARGS ((dev))
205: o_dev_t dev;
206: #endif
207: {
208: int omajor = (dev >> 8) & 0xFF;
209:
210: return (omajor > _maxmajor || _major [omajor] == NODEV) ? NULL :
211: & cdevsw [_major [omajor]].cdev_con;
212: }
213:
214:
215: /*
216: * Start things up, in the right order. If we can't proceed, panic.
217: */
218:
219: #if __USE_PROTO__
220: void (STREAMS_INIT) (void)
221: #else
222: void
223: STREAMS_INIT __ARGS (())
224: #endif
225: {
226: int i;
227:
228: /*
229: * We call upon INTR_INIT () to ensure that we can call spl... ()
230: * functions safely. For some environments, this needs to take note of
231: * the existing interrupt masks.
232: */
233:
234: while (INTR_INIT ())
235: cmn_err (CE_PANIC, "Initial DDI/DKI setup failed");
236:
237: #ifdef __MSDOS__
238: /*
239: * Arrange for the exit routines to be called eventually.
240: */
241:
242: atexit (STREAMS_EXIT);
243: #endif
244:
245: /*
246: * Bootstrap the heap allocator. The allocation routines may need
247: * locking (which needs an allocator), but we depend on KMEM_INIT ()
248: * to deal with that.
249: */
250:
251: while (KMEM_INIT (_streams_heap, _streams_size) != 0)
252: cmn_err (CE_PANIC, "Unable to initalise STREAMS heap");
253:
254: /*
255: * Other global initialization which can proceed now we have an
256: * allocation system active.
257: */
258:
259: while (DDI_GLOB_INIT ())
260: cmn_err (CE_PANIC, "Unable to set up DDI/DKI global data");
261:
262: /*
263: * After the defer tables have been set up, we can call LOCK_TESTS (),
264: * which we couldn't before because the ..._DEALLOC () calls that the
265: * tests perform at the end require defer-table support.
266: */
267:
268: if (LOCK_TESTS (0))
269: cmn_err (CE_PANIC, "Lock primitives not functional");
270:
271: /*
272: * Call the configured init routines for the system. According to the
273: * specification of init (D2DK), this happens before interrupts are
274: * enabled and before there is any real process context for us to
275: * be able to sleep.
276: */
277:
278: for (i = 0 ; i < ninit ; i ++)
279: (* inittab [i]) ();
280:
281: _exitlevel = nexit;
282:
283:
284: /*
285: * Now we can configure the interrupts for the system.
286: */
287:
288: for (_intlevel = 0 ; _intlevel < nintr ; _intlevel ++)
289: SETIVEC (_intlevel);
290:
291: splbase ();
292:
293:
294: /*
295: * And finally, we can call the start routines.
296: */
297:
298: for (i = 0 ; i < nstart ; i ++)
299: (* starttab [i]) ();
300:
301: }
302:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.