; refreshml.dsm ; L. Stewart, February 11, 1983 3:50 PM ; L. Stewart, February 14, 1983 12:25 PM, swab bug in refresh ; L. Stewart, February 16, 1983 10:26 PM, initial stack bug ; L. Stewart, February 18, 1983 9:46 AM, relocation ; L. Stewart, February 18, 1983 6:49 PM, boot switches & ref. bug. ; L. Stewart, February 24, 1983 1:48 PM, advice, bootSeal ; L. Stewart, February 24, 1983 1:48 PM, add monRelays..localNet SPACE SEGMENT C_GROUP GROUP SPACE, C_CODE, C_DATA ; DB 2 DUP(?) SPACE ENDS C_CODE SEGMENT $INCLUDE(Lark.d) ; numbers which affect relocation of this code ; stack initial value SPIN EQU 0DFF0H OffRefA EQU 0E010H OffRefB EQU 0E050H OffRefC EQU 0E090H OffRefD EQU 0E0D0H triploc EQU 004H trcsloc EQU 006H nmiploc EQU 008H nmcsloc EQU 00AH ; boot reasons ; interrupts of various sorts are of types 0 up through 255 cTRACE EQU 1 cNMI EQU 2 cWDTBoot EQU 0FFF8H cMainRet EQU 0FFF9H cTeleBoot EQU 0FFFAH cSSFAIL EQU 0FFFBH cMONRET EQU 0FFFCH cRUNERR EQU 0FFFDH cEXTINT EQU 0FFFEH cPwrOnBoot EQU 0FFFFH cRUNNING EQU 0FF00H C_DATA SEGMENT ; save area for machine state ; the arrangement of the following statics is known ; to remote debuggers, so don't change it frivilously _mState LABEL BYTE rax DW ? rbx DW ? rcx DW ? rdx DW ? rsp DW ? rbp DW ? rsi DW ? rdi DW ? rcs DW ? rds DW ? rss DW ? res DW ? rip DW ? rfl DW ? _bootReason DW 00H _rtcLow DW 00H _rtcHigh DW 00H _bootSwitches DW 00H _advice DW 00H _monRelays DW 00H _tlNet DW 00H _tlHost DW 00H _tlImHost DW 00H _localNet DW 00H ; above state known to remote debuggers _bootSeal DW 00H _lastIP DW ? ; single step use savea DW 0 _lastNMI DW ? C_DATA ENDS EXTRN _MonMain:NEAR EXTRN _PortStr:NEAR ASSUME CS:C_CODE, DS:C_DATA ; if code happens to execute into the monitor from lower ; addresses, a trap of type cRUNERR happens ; address = E000 NOP NOP NOP NOP NOP NOP NOP JMP runerr ; 3 bytes ; address = E00A JMP cstart ; 3 bytes ; address = E00D possnmi: JMP pnmib ; 3 bytes ; address = E010 RefA: NOP ; drain IFU NOP NOP NOP ; total 4 DW 006C7H ; 2 bytes DB 0C7H DB 006H DW nmiploc ; 2 bytes DW OffRefB NOP ; drain IFU NOP NOP NOP ; total 14 ADD _rtcLow,1 ; 5 bytes NOP ; drain IFU NOP NOP NOP ; total 23 ADC _rtcHigh,0 ; 5 bytes NOP ; drain IFU NOP NOP NOP ; total 32 MOV savea,AX ; 3 bytes NOP ; drain IFU NOP NOP NOP ; total 39 IN AL,pioc ; 2 bytes NOP ; drain IFU NOP NOP NOP ; total 45 TEST AL,1 ; 2 bytes NOP ; drain IFU NOP NOP NOP ; total 51 JZ possnmi ; 2 bytes wasntnmi: NOP ; drain IFU NOP NOP NOP ; total 57 MOV AX,savea ; 3 bytes NOP NOP NOP ; total 63 IRET RefB: NOP ; drain IFU NOP NOP NOP NOP ; total 5 DW 006C7H ; 2 bytes DB 0C7H DB 006H DW nmiploc DW OffRefC NOP ; drain IFU NOP NOP NOP NOP ; total 16 ADD _rtcLow,1 NOP ; drain IFU NOP NOP NOP NOP ; total 26 ADC _rtcHigh,0 NOP ; total 32 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; total 42 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; total 52 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; total 62 NOP IRET RefC: NOP ; drain IFU NOP NOP NOP NOP ; total 5 DW 006C7H ; 2 bytes DB 0C7H DB 006H DW nmiploc DW OffRefD NOP ; drain IFU NOP NOP NOP NOP ; total 16 ADD _rtcLow,1 NOP ; drain IFU NOP NOP NOP NOP ; total 26 ADC _rtcHigh,0 NOP ; total 32 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; total 42 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; total 52 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; total 62 NOP IRET RefD: NOP ; drain IFU NOP NOP NOP NOP ; total 5 DW 006C7H ; 2 bytes DB 0C7H DB 006H DW nmiploc DW OffRefA NOP ; drain IFU NOP NOP NOP NOP ; total 16 ADD _rtcLow,1 NOP ; drain IFU NOP NOP NOP NOP ; total 26 ADC _rtcHigh,0 NOP ; total 32 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; total 42 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; total 52 NOP NOP NOP NOP NOP NOP NOP NOP NOP NOP ; total 62 NOP IRET ; io device initialization strings ; The format of this stuff is ; port FF terminates the list ; first set up the 8255 and reset all its outputs _I8255 LABEL BYTE DB pioctl DB 1 DB 083H ; Port A, C[4..7] output, B, C[0..3] input, all mode 0 ; P1A (output) ; P1A7 ResAlogInt' 1 ; P1A6 Led' 1 ; P1A5 SlaveReset 1 ; P1A4 SlaveNMI 0 ; P1A3 KickWDT 0 ; P1A2 StopAudClock 0 ; P1A1 P1A1 0 ; P1A0 ResEncInt' 1 DB pioa DB 1 DB 0E1H ; P1B Ethernet host address switches (input) DB piob DB 1 DB 000H ; P1C (0-3 input, 4-7 output) ; P1C7 Unused 0 ; P1C6 Unused 0 ; P1C5 SwitchHS' 1 ; P1C4 ShuntA' 1 ; P1C3 P1C3 ; P1C2 BootMode ; P1C1 SynTSN ; P1C0 ManNMI DB pioc DB 1 DB 030H DB apioctl DB 1 DB 088H ; Port A, B, C0-3 Out, Port C4-7 In, mode 0 ; P2A (output) ; P2A7 Revert 1 ; P2A6 GoOffHook' 1 ; P2A5 CodecControlData 0 ; P2A4 CodecControlClock 0 ; P2A3 SenseSH 0 ; P2A2 SenseRI 0 ; P2A1 SenseSwitch 0 ; P2A0 SenseCode 0 DB apioa DB 1 DB 0C0H ; revert and off-hook relays OFF ; P2B (output) ; P2B7 SwDataStrobe3 0 ; P2B6 SwDataStrobe2 0 ; P2B5 SwDataStrobe1 0 ; P2B4 SwDataStrobe0 0 ; P2B3 SwAddr3 0 ; P2B2 SwAddr2 0 ; P2B1 SwAddr1 0 ; P2B0 SwAddr0 0 DB apiob DB 1 DB 000H ; P2C (0-3 output, 4-7 input) ; P2C7 DTMFCode3 ; P2C6 DTMFCode2 ; P2C5 DTMFCode1 ; P2C4 DTMFCode0 ; P2C3 EnableRing' 1 ; P2C2 SideTone' 1 ; P2C1 Unused 0 ; P2C0 SwData 0 DB apioc DB 1 DB 00CH ; EnableRing and SideTone OFF DB 0FFH _I8237 LABEL BYTE ; reset DMA controller DB dmamask DB 1 DB 00FH DB dmaclr DB 1 DB 000H ; Set up SLC controller only in cascade mode DB dmastat DB 1 DB 020H DB dmamode DB 1 DB 0C1H DB dmamask DB 1 DB 00DH DB 0FFH ; See Lark9513.txt for explanations _I9513 DB TimCtl DB 5 DB 0FFH DB 05FH DB 001H DB 0E0H DB 017H DB TimData DB 2 DB 0C0H DB 088H DB TimCtl DB 6 DB 0E9H ; set SLCHoldoff' high (was E1) DB 0E2H ; everyone else low DB 0E3H DB 0E4H DB 0E5H DB 001H ; SLCHoldoff DB TimData DB 30 ;new DB 062H ; mode L, toggle DB 0DBH ; active high edge gate N, F1 DB 059H ; delay 192/2 -7 DB 000H DB 02EH ; low for 46 DB 000H ;old ; DB 062H ; mode J ; DB 01BH ; DB 02EH ; DB 000H ; DB 092H ; DB 000H ; TSN ; new DB 062H ; Mode J, free run DB 01BH ; no gate, F1 DB 058H ; low for 88 DB 000H DB 008H ; high for 8 DB 000H ; old ; DB 062H ; mode L ; DB 0FBH ; DB 007H ; delay 7 ; DB 000H ; DB 008H ; high for 8 ; DB 000H ; Framesync DB 0A5H ; Mode R DB 0FBH ; active low edge gate N, F1 DB 005H ; delay 5 DB 000H DB 000H DB 000H ; 8274 ch. B baud rate, 1200 baud DB 062H ; Mode J, free run DB 01BH ; no gate, F1 DB 028H DB 000H DB 028H DB 000H ; Refresh generator ; Programmable timer, set up for toggling every 8 ticks of SynTSN ; It triggers nmi on the low to high transition of output DB 022H ; Mode D DB 014H DB 008H DB 000H DB 000H DB 000H DB TimCtl DB 2 DB 05FH DB 03FH DB 0FFH _I8274 DB sioctla DB 2 DB 018H ; channel reset DB 0F0H ; reset Tx underrun, error reset DB sioctlb DB 2 DB 018H ; channel reset DB 0F0H ; reset Tx underrun, error reset DB sioctla DB 14 DB 004H ; WR 4 next DB 04CH ; 16 x clock, 2 stop, no parity DB 001H ; WR 1 next ; select one of the next two lines ; DB 004H ; no interrupts, variable vector DB 01EH ; rx int all chars, variable vector, txint, no ext int DB 002H ; WR 2 next DB 014H ; 8088 mode, non-vector int. rx high pri., both int. DB 003H ; WR 3 next DB 0C0H ; 8 bits/rxchar DB 005H ; WR 5 next DB 060H ; 8 bits/txchar DB 006H ; WR 6 next DB 000H ; junk DB 007H ; WR 7 next DB 000H ; junk DB sioctlb DB 14 DB 004H ; WR 4 next DB 04CH ; 16 x clock, 2 stop, no parity DB 001H ; WR 1 next ; select one of the next two lines ; DB 004H ; no interrupts, variable vector DB 01EH ; rx int all chars, variable vector, txint, no ext int DB 002H ; WR 2 next DB 000H ; base vector DB 003H ; WR 3 next DB 0C0H ; 8 bits/rxchar DB 005H ; WR 5 next DB 060H ; 8 bits/txchar DB 006H ; WR 6 next DB 000H ; junk DB 007H ; WR 7 next DB 000H ; junk ; now enable 8274 DB sioctla DB 4 DB 003H DB 0C1H ; 8 bits/rxchar, rx enable DB 005H DB 068H ; 8 bits/txchar, tx enable DB sioctlb DB 4 DB 003H DB 0C1H ; 8 bits/rxchar, rx enable DB 005H DB 068H ; 8 bits/txchar, tx enable DB 0FFH ; set up 8259 ; Mask all interrupts _I8259 DB intctl DB 1 DB 01BH ; ICW1: level mode, single 8259, ICW4 needed DB intdata DB 3 DB 070H ; ICW2, base of vectors DB 001H ; ICW4, no nest, no buffer, no AEOI, 8088 DB 0FFH ; OCW1, mask off all interrupts ; end of string DB 0FFH ; jump targets for jumps at top of this file ; runerr may catch sequential execution into EPROM space runerr: PUSHF CLI PUSH CS MOV rbx,BX MOV BX,08000H ; fake PUSH IP PUSH BX MOV BX,cRUNERR JMP intcom ; NMI button pushed wasnmi: MOV rbx,BX MOV BX,cNMI JMP intcom ; possible NMI button push pnmib: ; if old, juggle stack MOV AX,1 XCHG AX,_lastNMI OR AL,AL JZ pnmic JMP wasntnmi pnmic: ; if we reach here, fix stack so IRET from refresh code ; "returns" to wasnmi, saving client state MOV AX,0F000H PUSH AX ; push flags for monitor execution XOR AX,AX PUSH AX ; push cs for wasnmi MOV AX,OFFSET wasnmi PUSH AX ; push ip for wasnmi JMP wasntnmi ; execution starts here on a system reset ; might be a WDTBoot, but we haven't checket yet cstart: MOV BX,cPwrOnBoot ; callable from C: CStart(reason) ; initializes _CStart: MOV AL,0FFH ; timer master reset OUT TimCtl,AL MOV AL,083H ; Port A, C4-7 Out, Port B, C0-3 In, mode 0 OUT pioctl,AL MOV AL,068H ; kick WDT, Alog reset OUT pioa,AL MOV AL,0E1H ; normal OUT pioa,AL MOV AL,000H ; input OUT piob,AL MOV AL,030H ; A and HS relays OFF OUT pioc,AL MOV AL,088H ; Port A, B, C0-3 Out, Port C4-7 In, mode 0 OUT apioctl,AL MOV AL,0C0H ; revert and off-hook relays OFF OUT apioa,AL MOV AL,000H ; crossbar OUT apiob,AL MOV AL,00CH ; EnableRing and SideTone OFF OUT apioc,AL ; all traps, etc. come here with different codes in BX _CRestart: MOV AX,SPIN MOV SP,AX ; CS better be 0 XOR AX,AX MOV SS,AX MOV ES,AX MOV DS,AX MOV BP,AX ; top of stack MOV _bootReason,BX CMP BX,cPwrOnBoot JNE callMon CALL _Setup ; might be a WDTBoot, so check it out MOV AX,_bootSeal CMP AX,0ABCDH JNE pob MOV BX,cWDTBoot MOV _bootReason,BX JMP callMon pob: MOV _advice,0 callMon: MOV AX,0ABCDH MOV _bootSeal,AX MOV BX,_bootReason CALL _MonMain ; ; if the monitor returns, start it again ; MOV BX,cMONRET JMP _CStart _StartM LABEL NEAR MOV _bootReason,cRUNNING CMP rsp,0300H JAE sok MOV rsp,03F0H sok: MOV AX,rip MOV _lastIP,AX ; save current ip XOR AX,AX ; zero segment regs MOV SS,AX MOV DS,AX MOV ES,AX MOV AX,rsp MOV SP,AX PUSH rfl XOR AX,AX ; zero CS PUSH AX PUSH rip MOV AX,rax MOV BX,rbx MOV CX,rcx MOV DX,rdx MOV SI,rsi MOV DI,rdi MOV BP,rbp IRET ; pops FL, CS, and IP intcom: MOV rax,AX MOV rcx,CX MOV rdx,DX MOV rsi,SI MOV rdi,DI MOV rbp,BP POP rip POP rcs POP rfl PUSH DS POP rds PUSH ES POP res MOV AX,SS MOV rss,AX MOV AX,SP MOV rsp,AX JMP _CRestart trace LABEL NEAR ; determine if interrupt happened first! ; if trace flag is off in the flags on the stack then reorder. MOV rax,AX MOV rbx,BX MOV rcx,CX MOV rdx,DX POP DX ; pop ip POP CX ; pop cs POP AX ; pop flags PUSH AX ; push them back ; note: asm bug, TEST AH,1 doesn't work! TEST AX,0100H ; tf set? JNZ trok ; if so, this is the trace trap XOR BX,BX ; otherwise PUSH BX ; push cs for this routine MOV BX,OFFSET trace ; push ip for this routine PUSH BX PUSH AX ; push original flags PUSH CX ; push original cs PUSH DX ; push original ip MOV AX,rax ; restore registers MOV BX,rbx MOV CX,rcx MOV DX,rdx IRET trok: PUSH CX ; push original cs PUSH DX ; push original ip MOV AX,rax ; restore registers MOV CX,rcx ; except BX MOV DX,rdx MOV BX,cTRACE JMP intcom ; All other interrupts UnkInt: ; in principle, CS contains the interrupt type and IP has ; whatever it takes to get control here. ; ; maybe the 8259 is confused ; ; PUSH AX ; MOV AL,020H ; 8259 eoi ; OUT intctl,AL ; POP AX ; MOV rbx,BX MOV BX,CS ; boot code is interrupt type DB 0EAH ; long jump to DW OFFSET intcom ; intcom DW 0 ; the monitor calls this to initialize the machine _Setup PROC NEAR ; ; set up all interrupts to point to UnkInt ; The idea is that the interrupt type is encoded in the CS:IP pair ; so that CS holds the type and IP holds UnkInt-16*CS ; temporary refresh, to keep things going temporarily MOV SI,0 MOV CX,128 CLD REP LODSW ; first fill in those in low memory MOV CX,6 MOV DI,000H MOV BX,000H MOV DX,OFFSET UnkInt SUB DX,000H CLD suih1: MOV AX,DX STOSW MOV AX,BX STOSW INC BX SUB DX,010H LOOP suih1 ; assert that an NMI is not in progress MOV _lastNMI,0 ; set up single step XOR AX,AX XOR BX,BX MOV [trcsloc+BX],AX MOV [nmcsloc+BX],AX MOV [triploc+BX],OFFSET trace MOV [nmiploc+BX],OFFSET RefA ; ; initialize IO devices ; CALL _InitIO ; set the rest of interrupts to point to UnkInt ; The idea is that the interrupt type is encoded in the CS:IP pair ; so that CS holds the type and IP holds UnkInt-16*CS MOV CX,250 MOV DI,018H MOV BX,006H MOV DX,OFFSET UnkInt SUB DX,060H CLD suih2: MOV AX,DX STOSW MOV AX,BX STOSW INC BX SUB DX,010H LOOP suih2 ; initialize save area MOV rip,0400H MOV rsp,0DFF0H XOR AX,AX MOV rcs,AX MOV res,AX MOV rds,AX MOV rss,AX MOV rfl,0F000H ; interrupts off RET _Setup ENDP _InitIO PROC NEAR MOV BX,OFFSET _I9513 CALL _PortStr MOV BX,OFFSET _I8255 CALL _PortStr MOV BX,OFFSET _I8237 CALL _PortStr MOV BX,OFFSET _I8274 CALL _PortStr MOV BX,OFFSET _I8259 CALL _PortStr RET _InitIO ENDP PUBLIC _mState PUBLIC _bootReason PUBLIC _rtcLow PUBLIC _rtcHigh PUBLIC _bootSwitches PUBLIC _advice PUBLIC _monRelays PUBLIC _tlNet PUBLIC _tlHost PUBLIC _tlImHost PUBLIC _localNet PUBLIC _CStart PUBLIC _CRestart PUBLIC _StartM PUBLIC _Setup PUBLIC _InitIO PUBLIC _lastIP PUBLIC _lastNMI C_CODE ENDS END