$MOD186 $PAGELENGTH (72) $PAGEWIDTH (136) ;Copyright (C) 1984, 1985 by Xerox Corporation. All rights reserved. ;-- This program implements the mesa processor handler and mesa client task. ;-- stored as [Iris]<WMicro>Dove>MesaUpDn.asm ; ;-- last edited by: ;-- RTK 24-Feb-87 12:15:46 ;Add 16 Bit IO Operations ;-- RTK 6-Jan-87 14:29:27 :Add readIOPBus - writeOptBus ;-- JPM 2-Oct-85 8:38:44 :Test for display size. ;-- JPM 13-Aug-85 16:43:05 :Add ReadPCType. ;-- JPM 12-Aug-85 9:16:42 :Change IOPEInRAM alignment to WORD. ;-- JPM 3-Aug-85 8:11:16 :Convert for new ReadEEProm macro ;-- JPM 30-Jul-85 12:27:35 :Fix bugs in DownNotify ;-- JPM 26-Jul-85 12:45:40 :Opie redesign conversion ;-- JPM 17-Jun-85 16:40:30 :Implemented PerformBoot (using opieReentry) ;-- KEK 23-May-85 17:27:49 :added explicit Enable after ThisTaskServices. ;-- JPM 5-Dec-84 17:36:34 :Made init proc NEAR; changed to RAM macros ;-- JPM 29-Nov-84 13:14:35 :Halt/start Mesa processor during task init ;-- JPM 26-Oct-84 11:15:02 :Added IN instrs. to clear Mesa interrupt ;-- JPM 18-Oct-84 12:05:52 :Fixed bug in command check ;-- JPM 17-Oct-84 13:30:18 :Added more commands, made jump table ;-- JPM 4-Oct-84 13:51:43 :Added commands, PCE notify ;-- JPM 28-Sep-84 15:30:34 :Made separate proc to initialize tasks ;-- JPM 23-Jul-84 13:06:37 :Creation NAME MesaUpDn ;-------------------------------------------------------------------------------- ; $NOLIST $INCLUDE (IOPDefs.asm) $INCLUDE (HardDefs.asm) $INCLUDE (MesaDefs.asm) $INCLUDE (ROMEEP.asm) $INCLUDE (RAMEEP.asm) $INCLUDE (OpieDefs.asm) $INCLUDE (IOPMacro.asm) $LIST EXTRN MesaProcessorHandlerID: ABS EXTRN mesaProcessorInterrupt: ABS EXTRN DisplayHandlerID: ABS ;******************************************************************************** IOPELocalRAM SEGMENT AT 0 EXTRN IOROpieSegmentAddress: WORD ; we take short cut EXTRN VMMFirstPage: WORD, VMMSizeInPages: WORD EXTRN firstRealPageInVM: WORD, lastRealPageInVM: WORD EXTRN countRealPagesInVM: WORD EXTRN firstDisplayBankPage: WORD, countDisplayBankPages: WORD EXTRN opieReentry: WORD IOPELocalRAM ENDS ;******************************************************************************** MesaProcessorIOR SEGMENT COMMON EXTRN mesaProcessorTask: TaskContextBlock EXTRN mesaClientTask: TaskContextBlock EXTRN notifiersLockMask: WORD EXTRN upNotifyBits: WORD EXTRN downNotifyBits: WORD EXTRN wordsForDownNotify: ABS EXTRN mesaProcessorCommand: BYTE EXTRN mesaProcessorData: WORD EXTRN mesaClientCondition: Condition EXTRN mesaClientMask: WORD MesaProcessorIOR ENDS ;******************************************************************************** MesaProcessorSTK SEGMENT COMMON EXTRN MesaProcessorStack: WORD EXTRN MesaClientStack: WORD MesaProcessorSTK ENDS ;******************************************************************************** OpieIOR SEGMENT COMMON EXTRN workNotifierCondition: Condition EXTRN workNotifierBitsPtr: WORD EXTRN timeOfDay: TimeOfDayFormat OpieIOR ENDS ;-------------------------------------------------------------------------------- DisplayIOR SEGMENT COMMON EXTRN numberQuadWords: WORD DisplayIOR ENDS ;-------------------------------------------------------------------------------- ; ; ;******************************************************************************** IOPEInRAM SEGMENT WORD PUBLIC ASSUME CS:IOPEInRAM PUBLIC MesaProcessorInit MesaProcessorInit PROC FAR %InitializeTask (MesaProcessorHandlerID,OFFSET mesaProcessorTask,MesaProcessorStart,OFFSET MesaProcessorStack) ; initialize down-notify task %InitializeTask (MesaProcessorHandlerID,OFFSET mesaClientTask,MesaClientStart,OFFSET MesaClientStack) ; initialize up-notify task RET MesaProcessorInit ENDP ;-------------------------------------------------------------------------------- MesaProcessorStart: ; initialization for interrupt watcher (down-notify task) ASSUME DS:MesaProcessorIOR MOV AX, haltMesa ; halt the OUT WriteCSReg, AX ; Mesa processor %GetLockMask ; acquire software lock mask for notifiers MOV notifiersLockMask, AX ; and store away MOV BX, OFFSET downNotifyBits MOV CX, wordsForDownNotify ZeroDownNotifyBits: MOV WORD PTR [BX], 0 ADD BX, 2 LOOP ZeroDownNotifyBits %LoadOpieSegment (ES,AX) ; get direct access to Opie ASSUME ES:OpieIOR IN AX, ClrMesaIntr ; clear Mesa interrupt ; initialization complete, now attach this task to MesaProcessorInterrupt %ThisTaskServices (MesaProcessorInterrupt,RecoveryNoOp) %DisableInterruptsTillNextWait ; don't allow interrupt %Enable(MesaProcessorInterrupt) MOV AX, noHaltMesa ; start the OUT WriteCSReg, AX ; Mesa processor MesaProcessorWait: ; task waits for MesaProcessorInterrupt, picks up locked data, ORs into workNotifierBits and ; notifies system-level task to do individual notifies ; it also does a command from Mesa if requested %WaitForInterrupt (noTimeout) ; (MesaProcessorInterrupt) IN AX, ClrMesaIntr ; clear Mesa interrupt MOV BL, mesaProcessorCommand; load command ADD BL, BL ; make word offset JZ DownNotify ; if no command, go to down notify XOR BH, BH ; clear high half of BX CMP BX, 2*lastCommand ; check for valid command JG ResetCommand ; if not valid, reset MOV BX, CS:CommandTable[BX-2] ; load command routine addr JMP BX ; execute command routine CommandTable DW OFFSET ReadGMT ; cmd=readGMTtoData DW OFFSET WriteGMT ; cmd=writeGMTfromData DW OFFSET ReadHostID ; cmd=readHostIDtoData DW OFFSET ReadVMMapDesc ; cmd=readVMMapDesctoData DW OFFSET ReadRealMemDesc ; cmd=readRealMemDesctoData DW OFFSET ReadDisplayDesc ; cmd=readDisplayDesctoData DW OFFSET ReadKeyboardType ; cmd=readKeyboardTypetoData DW OFFSET ReadPCType ; cmd=readPCTypetoData DW OFFSET PerformBoot ; cmd=bootButton DW OFFSET ReadIOP ; cmd=readIOPBus DW OFFSET WriteIOP ; cmd=writeIOPBus DW OFFSET ReadOpt ; cmd=readOptBus DW OFFSET WriteOpt ; cmd=writeOptBus DW OFFSET IORead16 ; cmd=ioread16 DW OFFSET IOWrite16 ; cmd=iowrite16 ResetCommand: MOV mesaProcessorCommand, noCommand ; reset command DownNotify: MOV BX, OFFSET downNotifyBits MOV DI, workNotifierBitsPtr MOV CX, wordsForDownNotify MOV BP, Null DownNotifyLoop: XOR AX, AX ; prepare to do locked exchange of downNotifyBits with 0 CMP DS:[BX], AX ; any bits set? JE DownNotifyLoopEnd ; if not, jump around MOV BP, CX ; save CX (also makes BP > Null) %MesaLockedOut (XCHG,BX,AX,notifiersLockMask) ; do exchange MOV CX, BP ; restore CX OR ES:[DI], AX ; set bits for work notify DownNotifyLoopEnd: ADD BX, 2 ; increment source and ADD DI, 2 ; destination ptrs LOOP DownNotifyLoop ; loop through all words CMP BP, Null ; any exchanges happen? JE MesaProcessorWait ; if not, go back and wait %NotifyHandlerCondition (opieHandlerID,OFFSET workNotifierCondition) ; notify system-level task JMP MesaProcessorWait ; go back and wait ;-- command procs ReadGMT: MOV AX, timeOfDay.lowWord ; pick up both words MOV mesaProcessorData, AX ; of GMT MOV AX, timeOfDay.highWord ; and store them MOV mesaProcessorData+2, AX ; in mesaProcessorData JMP ResetCommand WriteGMT: MOV AX, mesaProcessorData ; pick up first 2 words MOV timeOfDay.lowWord, AX ; of mesaProcessorData MOV AX, mesaProcessorData+2 ; and store them MOV timeOfDay.highWord, AX ; in GMT JMP ResetCommand ReadHostID: MOV DX, ReadHostProm ; load 1st I/O addr of host prom MOV BX, OFFSET mesaProcessorData ; and addr of mesaProcessorData MOV CX, sizeHostID ; set up loop count ReadHostIDLoop: IN AL, DX ; read byte of host prom MOV DS:[BX], AL ; and store it INC BX ; increment data addr ADD DX, 2 ; and I/O addr LOOP ReadHostIDLoop ; loop JMP ResetCommand ReadVMMapDesc: MOV AX, IOPELocalRAM ; switch to MOV ES, AX ; local RAM segment ASSUME ES:IOPELocalRAM MOV AX, VMMFirstPage ; get VMM first page MOV mesaProcessorData, AX ; and store in mesaProcessorData MOV AX, VMMSizeInPages ; get VMM size MOV mesaProcessorData+2, AX ; and store in mesaProcessorData MOV ES, IOROpieSegmentAddress ; restore ES ASSUME ES:OpieIOR JMP ResetCommand ReadRealMemDesc: MOV AX, IOPELocalRAM ; switch to MOV ES, AX ; local RAM segment ASSUME ES:IOPELocalRAM MOV AX, firstRealPageInVM ; get first real page MOV mesaProcessorData, AX ; and store in mesaProcessorData MOV AX, lastRealPageInVM ; get last real page MOV mesaProcessorData+2, AX ; and store in mesaProcessorData MOV AX, countRealPagesInVM ; get real page count MOV mesaProcessorData+4, AX ; and store in mesaProcessorData MOV ES, IOROpieSegmentAddress ; restore ES ASSUME ES:OpieIOR JMP ResetCommand ReadDisplayDesc: %EstablishHandlerAccess (displayHandlerID) ASSUME ES:DisplayIOR MOV AX, numberQuadWords ; get display size Test15InchBW: CMP AX, 13 ; value for 15" b/w JNE Test19InchBW MOV AX, 1 ; display present, b/w, small JMP SHORT GoodDisplayDesc Test19InchBW: CMP AX, 18 ; value for 19" b/w JNE GetEEPromDisplayInfo MOV AX, 5 ; display present, b/w, large JMP SHORT GoodDisplayDesc GetEEPromDisplayInfo: %ReadEEProm (eePromDispType,1) ; read word from EEProm JNC GoodDisplayDesc ; (if not good read, MOV AX, 0 ; assume no display) GoodDisplayDesc: MOV mesaProcessorData, AX ; store in mesaProcessorData MOV AX, IOPELocalRAM ; switch to MOV ES, AX ; local RAM segment ASSUME ES:IOPELocalRAM MOV AX, firstDisplayBankPage ; get first display page MOV mesaProcessorData+2, AX ; and store in mesaProcessorData MOV AX, countDisplayBankPages ; get display page count MOV mesaProcessorData+4, AX ; and store in mesaProcessorData MOV ES, IOROpieSegmentAddress ; restore ES ASSUME ES:OpieIOR JMP ResetCommand ReadKeyboardType: %ReadEEProm (eePromKBType,1) ; read word from EEProm JNC GoodKeyboardType ; (if not good read, MOV AX, 1 ; use American) GoodKeyboardType: MOV mesaProcessorData, AX ; and store in mesaProcessorData JMP ResetCommand ReadPCType: %ReadEEProm (eePromPCEMemSize,1) ; read word from EEProm JNC GoodPCType ; (if not good read, MOV AX, 0 ; use null) GoodPCType: MOV mesaProcessorData, AX ; and store in mesaProcessorData JMP ResetCommand PerformBoot: MOV AX, IOPELocalRAM ; jump to Opie's MOV ES, AX ; reentry point (addr in JMP DWORD PTR ES:opieReentry ; local RAM) ReadIOP: MOV BP, mesaProcessorData ; get the IOP offset MOV BX, ES ; save ES MOV ES, mesaProcessorData+2 ; get the IOP segment MOV AL, ES:[BP] ; get a byte MOV AH,0 MOV mesaProcessorData+4, AX ; store the byte MOV ES, BX ; restore ES JMP ResetCommand WriteIOP: MOV BP, mesaProcessorData ; get the IOP offset MOV BX, ES ; save ES MOV ES, mesaProcessorData+2 ; get the IOP segment MOV AX, mesaProcessorData+4 ; get the byte MOV ES:[BP], AL ; write the byte MOV ES, BX ; restore ES JMP ResetCommand ReadOpt: MOV DX, mesaProcessorData ; get the IO address IN AL, DX ; get a byte MOV AH,0 MOV mesaProcessorData+4, AX ; store the byte JMP ResetCommand WriteOpt: MOV DX, mesaProcessorData ; get the IO addres MOV AX, mesaProcessorData+4 ; get the byte OUT DX, AL ; write the byte JMP ResetCommand IORead16: MOV DX, mesaProcessorData ; get IO address IN AX, DX ; get the word MOV mesaProcessorData+4, AX ; store the word JMP ResetCommand IOWrite16: MOV DX, mesaProcessorData ; get IO address MOV AX, mesaProcessorData+4 ; get the word OUT DX, AX ; write the word JMP ResetCommand ;-------------------------------------------------------------------------------- ; interrupt error recovery proc RecoveryNoOp PROC FAR RET ; no interrupt recovery (should not be needed, because task is always ready RecoveryNoOp ENDP ; for interrupt and does not use watch dog timeout) ;-------------------------------------------------------------------------------- MesaClientStart: ; initialization for up-notify task MOV upNotifyBits, 0 ; reset upNotifyBits MOV mesaClientMask, 0 ; and local source MesaClientWait: ; main task waits for condition notify, picks up local bits, ; ORs into locked data, and interrupts the Mesa processor %WaitForCondition (OFFSET mesaClientCondition,noTimeout) XOR AX, AX ; prepare to exchange local data with 0 XCHG mesaClientMask, AX ; do exchange %MesaLockedOut (OR,OFFSET upNotifyBits,AX,notifiersLockMask) ; OR into locked data MOV AX, noInterruptMesa ; interrupt the Mesa processor OUT WriteCSReg, AX ; by resetting bit in CS reg. MOV AX, interruptMesa ; then setting it OUT WriteCSReg, AX ; (bit is latched for Mesa) JMP MesaClientWait ; loop IOPEInRAM ENDS END