// IfsInterruptInit.Bcpl -- IFS version of Interrupt initialization // Copyright Xerox Corporation 1979, 1980 // Last modified March 7, 1980 12:40 PM by Taft // - expand IST structure to save interruptXJmp and interruptXPC // Last modified February 20, 1980 3:03 PM by Wobber // - properly set stackBottom // Based on InterruptInit.Bcpl from Interrupt Package, // Last modified September 4, 1979 2:30 PM by Taft get "IfsXEmulator.decl" external [ // outgoing procedures InitializeInterrupt; FindInterruptMask // incoming procedures SysErr // incoming statics lvUserFinishProc // To clean up interrupt system // From Interrupt.Asm: interruptPrologue; interruptFinish interruptsActive; savedUserFinishProc ] //--------------------------------------------------------------- structure IST: // Corresponds to Interrupt.Asm //--------------------------------------------------------------- [ Prologue word 2 various word 9 // Old state saved here NewMask word // New interrupt mask Stack word // Stack pointer to use StackMin word // Stack bottom to use InitialPC word // Procedure to call StackBot word 0 // First stack location ] manifest [ interruptVector = #501 Active = #453 ecInterruptInUse = 2750 ecInterruptMaskZero = 2751 ecInterruptChanZero = 2752 ] //--------------------------------------------------------------- let InitializeInterrupt(region, length, mask, initialPc) = valof //--------------------------------------------------------------- [ // Trap all finishes and aborts to reset interrupt system if savedUserFinishProc eq -1 then [ savedUserFinishProc = @lvUserFinishProc @lvUserFinishProc = interruptFinish ] // Check validity of mask mask = MakeOneBit(mask) if (mask & @Active) ne 0 then SysErr(nil, ecInterruptInUse) // Install prologue, various stuff in IST for i = 0 to (size IST.Prologue/16)-1 do region!i = interruptPrologue!i region>>IST.NewMask = mask-1 region>>IST.InitialPC = initialPc region>>IST.Stack = region+length-4 // Minimal frame at top (region>>IST.Stack)!0 = region + (size IST.Prologue/16) (region>>IST.Stack)!stackBottom = lv (region>>IST.Stack)!stackBottom region>>IST.StackMin = (lv region>>IST.StackBot) // Discover interrupt channel number let i = 0 while ((1 lshift i) & mask) eq 0 do i = i+1 interruptVector!i = region //Enter this way @Active = @Active % mask //Let him at it interruptsActive = interruptsActive%mask resultis mask ] //--------------------------------------------------------------- and FindInterruptMask(mask) = valof //--------------------------------------------------------------- // Find legal channel of next lowest priority [ mask = MakeOneBit(mask) while mask ne #100000 do [ if (mask&@Active) eq 0 then resultis mask mask = mask lshift 1 ] resultis 0 ] //--------------------------------------------------------------- and MakeOneBit(mask) = valof //--------------------------------------------------------------- //From mask, make legal one-bit mask sensing only highest order bit [ if mask eq 0 then SysErr(nil, ecInterruptMaskZero) let i = 0 while (mask𘚠) eq 0 do [ mask = mask lshift 1 i = i+1 ] mask = (#100000 rshift i) if mask eq #100000 then SysErr(nil, ecInterruptChanZero) resultis mask ]