|
|
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.