$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