:TITLE[Initialize]; % Ed Fiala 13 March 1984: Absolutely locate BootEmulators so that Midas won't have to load PILOT1SYMBOLS during booting; move page 0 resident subrs to Fault.mc. Ed Fiala 3 October 1983: change init for prPsbIndexMask for Klamath. Tom Rich 15 October 1982: condition SCB handshake on ESSMode, to exclude PathFinderMode. Zero low byte of CDC9730 DTab. Tom Henning 20 September 1982: delete SCB handshake for Tor, key it on WithCDC9730. Ed Fiala 14 September 1982: Parameterize RefreshPeriod. Tom Rich September 8, 1982: WithTor => WithUIB and WithEOM. Ed Fiala 24 May 1982: Make SCB handshake work for Tor also. Ed Fiala 17 May 1982: fix DTab comments. Ed Fiala 14 May 1982: Fix DevFound bug for multitask devices. Ed Fiala 6 May 1982: Absorb prTime, NWW, RS232Image init from Timer.Mc. Ed Fiala 28 April 1982: Absorb ESS configuration edits from Tom Rich. Ed Fiala 21 April 1982: add display of no. 'good' pages from Initial, new 10 mb Ethernet DTab entries; delete old 10 mb Ethernet DTab entries, WithRDC, WithUTVFC; increase viewing delay; default init for vCrystal; conditionals on DTab entries; device init changes from AMesa system; preserve refresh sequence from Initial and use normal refresh during LoadRAM calls; eliminate InitPage2, initpc, contemp, rlink0; speed up PNIP. Ed Fiala 19 February 1982: delete unused MP code defs, removed ErrorCnt, ErrorCountx, initr0-3; changed StartDeviceInit and NPages MP codes with delay so they can be seen. Ed Fiala 17 December 1981: change PilotMDS and xfMX init for new Pilot. % RV[xCNT,20]; *Used everywhere RV[DevIndex,21]; *Used in DeviceInit RV[Assigned,23]; *Used in DeviceInit RV[rbuf0,24]; *Used in DeviceInit RV[rbuf1,25]; *Used in DeviceInit MC[NextDiskAddr,237]; RV[BootDiskAddr,37]; *Machine initialization begins here; start here from any task. SoftStart: xCNT _ HiA[Task0StartLoc], At[SoftStartLoc]; OnPage[InitPage]; xCNT _ (xCNT) or (LoA[Task0StartLoc]), GoTo[InitNotify]; Qtask: xCNT _ LoA[Qloc], At[Task0StartLoc]; *Quiesce tasks 15b to 1 xCNT _ (xCNT) or (HiA[Qloc,15]); DevIndex _ IP[DevIndex]C; StkP _ DevIndex; DevIndex _ LoA[QretLoc]; DevIndex _ (DevIndex) or (HiA[QretLoc]); InitNotify: Qloop: APCTask&APC _ xCNT; initRET: Return; *goes to Qx *Notify comes here. Leave task's TPC pointing at Qxy. Qx: APCTask&APC _ Stack, Call[PFExit], At[Qloc]; *BadWakeup is on a non-overlaid page so that it will remain intact after *initialization has completed. Wakeup from a device that isn't reset *properly comes here. BadWakeup: SetFault, GoTo[.]; Qret: LU _ LdF[xCNT,0,3], At[QretLoc]; *xCNT points to this location xCNT _ (xCNT) - (10000C), GoTo[Qloop,ALU#0]; *Zap devices. T _ RTemp1 _ 177400C; RTemp _ 300C; ZapDloop1: Output[RTemp]; *send 300 to register 0 of all devices T _ RTemp1 _ (RTemp1) + (20C); GoTo[ZapDloop1,ALU<0]; T _ RTemp1 _ 177400C; RTemp _ 0C; ZapDloop2: Output[RTemp]; *send 0 to register 0 of all devices T _ RTemp1 _ (RTemp1) + (20C); GoTo[ZapDloop2,ALU<0]; *During the Pilot1 LoadRAM, xfTemp1 was a state variable for inline refresh. *Put xfTemp1 back into Refr for regular refresh. This avoids having some *RAMs go unrefreshed for a longer than normal period. T _ (xfTemp1) and not (17C); xfTemp1 _ IP[Refr]C; StkP _ xfTemp1; Stack _ T; xfTemp1 _ IP[NWW]C; StkP _ xfTemp1; T _ Stack _ 0C; xfTemp1 _ IP[RSImage]C; StkP _ xfTemp1; Stack _ RS232 _ T; xfTemp1 _ IP[prTime]C; StkP _ xfTemp1; Stack _ 3C; *xfTemp1 odd for normal refresh on the LoadRAM calls during device init. *Also need RTemp1 even (to believe starting address) and ZapDloop2 above *leaves it even. xfTemp1 _ 1C; xCNT _ HiA[TimerInitLoc,16]; xCNT _ (xCNT) or (LoA[TimerInitLoc]), Call[InitNotify]; %Init location 7777b to be "PFetch4[PCB,IBuf,4], GoToExternal[MesaRefillLoc];" = 0 164614 011004. LoadRAM can't write 7777b. Unfortunately, the Boot program from the EPROM leaves the machine number in location 7777b and the software uses ReadRAM to obtain this number, so it can't be used for code. However, leave this code (which is untested) in as a comment in case we can do it later. % % xBuf1 _ HiA[7777]; xBuf1 _ (xBuf1) or (LoA[7777]); T _ 0C; *Data 2 xBuf _ HiA[164614]; *Data 0 xBuf _ (xBuf) or (LoA[164614]); LU _ xBuf; *This mi may be useless APCTask&APC _ xBuf1; WriteCS0&2; xBuf _ HiA[011004]; *Data 1 xBuf _ (xBuf) or (LoA[011004]); LU _ xBuf; *This mi may be useless APCTask&APC _ xBuf1; WriteCS1; % *Before initializing and starting devices, set up the RM locations that *must be valid. RegInit1: R400 _ 400C; AllOnes _ (Zero) - 1; RZero _ Zero; LoadPage[PNIPPage]; T _ StartDeviceInit, CallP[PNIP]; *Wait ~0.4 seconds for user to view StartDeviceInit 0104. Outer loop *repeats 32k times, so wait ~ 32k*123 cycles. xBuf _ 0C, Call[MPWait]; xBuf _ (xBuf) + 1, GoTo[MPWait,R>=0]; *Default vCrystal to 120b (80d), appropriate with a 40 mHz processor crystal. *If the Dolphin has a UTVFC, then DisplayInit.Mc will correct the value in *vCrystal for 44.5 mHz or 50 mHz crystals. xBuf _ IP[vCrystal]C; StkP _ xBuf; Stack _ 120C; :IF[IFE[RefreshPeriod,5000,0,1]]; ******************** Set[RefPerShift,IFE[RefreshPeriod,2400,1,IFE[RefreshPeriod,1200,2]]]; Stack _ LSh[Stack,RefPerShift]; :ENDIF; ********************************************** *Get next disk address from reg 237 and save in reg 37. xCNT _ NextDiskAddr; StkP _ xCNT; T _ Stack; BootDiskAddr _ T, GoTo[DeviceInit]; *Delay subroutine executes 121d (=7+2*(56+1)) cycles before returning. MPWaita: xBuf1 _ 70C, Skip; MPWait: xBuf1 _ 70C; xBuf1 _ (xBuf1) - 1, GoTo[.,R>=0]; Return; ClockOutPattern: StkP _ xCNT; xCNT _ 17C; *go through the slot table backwards COP1: DevIndex _ 3C; *DevIndex used for loop count COP2: T _ (Stack) xor (1C); *complement bit DevIndex _ (DevIndex) - 1, GenSRClock; *send bit Stack _ RCy[Stack,1], GoTo[COP2,ALU>=0]; *get next bit xCNT _ (xCNT) - 1; *all slot table entries done? Stack&-1, GoTo[COP1,ALU>=0]; *get next word Return; GetCon: APCTask&APC _ DevIndex; ReadCS; T _ CSData, Return, DispTable[1,1,0]; *Force even placement :IF[ESSMode]; ****************************************** *uib constants for communicating successful boot to SCB Set[uibTASKL,LShift[uibTask,4]]; MC[BootOKLeft,LShift[25,10]]; MC[TurnOnVideoLeft,LShift[24,10]]; MC[BootDLeft,LShift[30,10]]; MC[RightAllOnes,377]; *right side for above commands MC[MESAregBusy,2000]; *if this bit is on the Mesa Command Register is busy MC[uibRegAddr,Add[uibTASKL,2]]; MC[uibMESAregAddrC,Add[uibTASKL,3]]; *RTemp and prPsbIndexMask are available scratch registers SendMessageToSCB: prPsbIndexMask _ (prPsbIndexMask) or (RightAllOnes); T _ uibRegAddr; *check Mesa register Status Input[RTemp]; LU _ (RTemp) and (MESAregBusy); T _ uibMESAregAddrC, GoTo[SendMessageToSCB,ALU#0]; Output[prPsbIndexMask]; *send command to Mesa register prPsbIndexMask _ prPsbIndexMask, Return; *evade output gotcha :ENDIF; ************************************************ %Find and initialize all I/O devices: The idea is to use RM 40-57 as a "slot table" with one entry per potential I/O controller. First the table is filled with dummy controller addresses, and these are clocked out to the controllers. Then, each controller is interrogated for it's Device ID, and these names are put in the table. Then, for each slot, the device ID is looked up in a table (in IMX) of potential devices, and if a match is found, the entry from the device table is put into the slot table. A device table entry consists of the uPC value of the device's initialization routine (12 bits), and the task number for the controller. When all slots have been looked up, the task numbers are clocked out to the controllers, and the associated initialization routines are called in turn. To add a new controller to the system, simply add both a device table entry here and its driver microcode. Note that each entry should be CONDITIONAL upon having suitable microcode at the device's starting address to avoid a wild branch. A system with a DTAB entry but no driver microcode won't run on a Dolphin which has the device. NOTE: ORDER OF BOARDS IN CHASIS IS IMPORTANT. There are some problems: 1) The table is overlying RM 40-57 and DisplayInit.Mc may call LoadRAM. When the old LoadRAM is called, xBuf-xBuf3 (RM 44-47) and RTemp (RM 52) will be smashed and RTemp1 (RM 53) must be even. This means that the UTVFC must be in chasis slots 0 to 3 or table entries not yet handled will be smashed. For the new LoadRAM, yBuf-yBuf2 (50-52) will be smashed, so the UTVFC must be in chasis slots 0 to 7. For both old and new LoadRAM, there must be fewer than 13b controller mounted or RTemp1 might not be even (this could be fixed easily). 2) The Ethernet software/StartIO microcode require that the "first board" be assigned to the primary ethernet task (i.e., xoTask/xiTask or enxTask) and that the "second board" be assigned to the second task (enxTask2) and the third board to the third task (enxTask3), etc. This is necessary because gateway software "knows" through a parameter file that board 1 is on network X, board 2 on network Y, etc. To achieve this, the "first board" must be mounted nearest the processor and must be assigned the highest task number; second board next nearest and next highest task number; etc. 3) The two MIOC controllers want the task numbers assigned in the opposite way from the Ethernet controllers. % *First, a macro to allow nice formatting of the device table entries... Macro[DTab,IFE[#4,0,,IMData[LH[#1] RH[LShift[#2,4],#3] At[DTabLoc]] Set[DTabLoc,Add[DTabLoc,1]]]]; Set[DTabBase,Add[InitBase,100]]; Set[DTabLoc,DTabBase]; *DTab[5400,FDinit,FDtask,1]; *IFDC (floppy disk--not supported) *Since DES and FP boards have no init microcode, assemble unconditionally. DTab[12000,0,0,1]; *DES board DTab[127000,0,0,1]; *FP board DTab[127400,cdcInitLoc,cdcTask,WithCDC]; *Color display DTab[5000,uibInitLoc,uibTask,WithUIB]; DTab[7000,eomHiTaskInitLoc,eomHiTask,WithEOM]; DTab[7400,eomLoTaskInitLoc,eomLoTask,WithEOM]; DTab[4000,eimInitLoc,eimTask,WithEIM]; DTab[4400,vdInitLoc,vdTask,WithCDC9730]; DTab[10000,ioInitLoc,ioTask1,WithMIOC]; *1st MIOC DTab[10000,ioInitLoc,ioTask2,WithMIOC]; *2nd MIOC DTab[3400,xwInInitLoc,xiTask,With3MB]; *1st 3mb Ethernet input DTab[3000,xwOutInitLoc,xoTask,With3MB]; *1st 3mb Ethernet output DTab[3400,xwInInitLoc,xiTask2,With3MB]; *2nd 3mb Ethernet input DTab[3000,xwOutInitLoc2,xoTask2,With3MB]; *2nd 3mb Ethernet output DTab[12400,enxInitLoc,enxTask,With10MB]; *1st 10mb Ethernet DTab[12400,enxInitLoc2,enxTask2,With10MB]; *2nd 10mb Ethernet DTab[12400,enxInitLoc3,enxTask3,With10MB]; *3rd 10mb Ethernet DTab[1400,rdcInitLoc,rdcTask,WithRDC]; *SA4000 DTab[2400,rdcInitLoc,rdcTask,WithRDC]; *SA4000 kludge DTab[1000,DisplayInitLoc,DisplayTask,WithUTVFC]; *UTVFC ID = 1000b DTab[0,0,0,1]; *Final DTab entry must be Zero OnPage[InitPage]; DeviceInit: xCNT _ 57C; xCNT _ T _ (StkP _ xCNT) + 1, Call[.+1]; *StkP = 57b, xCNT = T = 60b here; write 60-77 into RM 40-57 (StkP counts *mod 20b, so StkP+1 when StkP .eq. 57b is 40b). LU _ (xCNT) xor (77C); Stack&+1 _ T, Skip[ALU=0]; xCNT _ T _ (xCNT) + 1, Return; *Send dummy controller addresses to devices; wind up with (n lsh 14b) + 3 in *RM (40b+n). Assigned _ 0C; *Bit mask of assigned tasks xCNT _ 57C, Call[ClockOutPattern]; *StkP = 57b here; read controller ID's from register 0 of all devices. xCNT _ T _ 177400C, Call[devRET]; *Allow xCNT & T to be written Input[Stack]; xCNT _ T _ (xCNT) + (20C), Skip[R>=0]; *Advance to next device devRET: Return; *Loop *StkP is now back at 40b since it wraps around the last time it was bumped. *Have 3000b, 3400b, 1055b, 1417b, etc. followed by 177777b for all undefined *slots. Look up each slot table entry in the device table. Scan devices *nearest the CPU first. xCNT _ 17C; DI4x: DevIndex _ HiA[DTabBase]; *Base of device table in control store DevIndex _ (DevIndex) or (LoA[DTabBase]); DI4y: T _ 0C, Call[GetCon]; *Get a device ID from the device table *Compare with the slot table entry (high byte) LU _ (LHMask[Stack]) xor T; *Check for end of table (Zero entry) LU _ T, GoTo[DevFound,ALU=0]; DevIndex _ (DevIndex) + 1, GoTo[DI4y,ALU#0]; *End of table reached without match--set slot's task to 17 (unused) Stack _ 17C; DI4z: xCNT _ (xCNT) - 1; *check for all slots processed Stack&+1, DblGoTo[DI4x,DI5,ALU>=0]; *set to next slot DevFound: T _ (SStkP&NStkP) xor (377C); rbuf0 _ T; T _ 1C, Call[GetCon]; rbuf1 _ T; *device table entry contains task assignment rbuf1 _ LSh[rbuf1,4]; *10:13b _ task number about to be assigned CycleControl _ rbuf1; T _ WFA[AllOnes]; LU _ (Assigned) and T; Assigned _ (Assigned) or T, Skip[ALU=0]; *Keep looking, task already assigned DevIndex _ (DevIndex) + 1, GoTo[DI4y]; T _ CSData; *Recover task assignment Stack _ T; *Replace slot table entry with device table entry *Write 177400 + 20b*task into RM 20b*task; this addresses the CSB for the *device automatically. StkP _ rbuf1; T _ (rbuf1) or (177400C); Stack _ T; StkP _ rbuf0, GoTo[DI4z]; *Clock out new controller ID's DI5: xCNT _ 57C, Call[ClockOutPattern]; %Here the table has task and uPC for existing controllers and 170000b for non-existent or undefined controllers. NOTE: StkP is 57b, so entries are handled in the order 57, 56, ..., 41. % *Call all the Init routines xCNT _ 17C; *Come here from DisplayInit DI5a: Call[devRET]; *do Call to set up TPC for loop below DI6: xCNT _ (xCNT) - 1, GoTo[BootEmulators,R<0]; LU _ LdF[Stack,4,14]; *check for Init PC = 0 (no initialization required) *Skip to call init routine for controller. APCTask&APC _ Stack&-1, Skip[ALU#0]; Nop; Return; %Initialize Mesa registers except StkP and FFault; LoadRAM will jump to InitEndLoc (in MesaOP3.Mc) which will setup these two registers and jump to Xfer which sets up CODE, GLOBAL, etc. % MC[PilotMDS,0]; BootEmulators: *Absolutely place for Pilot.midas command file. prCurrentPsb _ 0C, At[BootEmulatorsLoc]; :IF[ESSMode]; ****************************************** prPsbIndexMask _ BootOKLeft, Call[SendMessageToSCB]; *Assert boot is successful prPsbIndexMask _ TurnOnVideoLeft, Call[SendMessageToSCB]; *Turn on the UI prPsbIndexMask _ BootDLeft, Call[SendMessageToSCB]; *Until bootD in othello :ENDIF; ************************************************ prPsbIndexMask _ HiA[17770]; prPsbIndexMask _ (prPsbIndexMask) or (LoA[17770]), Task; MemStat _ Normal; xfWDC _ 1C, Task; MDS _ 0C; xfGFIWord _ 0C, Task; xfXTSReg _ 0C; xfBrkByte _ 40400C; *2001b rcy 2 xfMX _ HiA[1002], Task; xfMX _ (xfMX) or (LoA[1002]); *NWW, RSImage, and RS232 were zeroed by Timer.Mc initialization. *Show count of 'good' pages from Initial. xBuf _ IP[xPageCount]C, Task; StkP _ xBuf; LoadPage[PNIPPage]; T _ Stack, CallP[PNIP]; *Delay before overlaying control store because io microcode may not be *finished initializing yet and will be overwritten. xBuf _ 0C, Call[MPWaita]; xBuf _ (xBuf) + 1, GoTo[MPWaita,R>=0]; RTemp _ IP[FFault]C; StkP _ RTemp; T _ GLOBALhi _ PilotMDS; T _ GLOBALhi _ (LSh[GLOBALhi,10]) or T; LOCALhi _ T; xfTemp1 _ 1C; *Odd (normal tasking) RTemp1 _ 0C; *Even (believe starting address), .ge. 0 (resume Mesa) MDShi _ T, LoadPageExternal[LRJPage]; LOCAL _ 0C, GoToExternal[LRJContinue]; :END[Initialize];e6(1795)\f2