; cmonml.dsm
; L. Stewart, September 24, 1982 10:30 AM
; clkxx -> cmkxx , September 10, 1982 11:42 AM
; L. Stewart, December 3, 1982 3:02 PM, new initial I/O setup code
; L. Stewart, January 21, 1983 1:04 PM, initial I/O fixup
SPACE SEGMENT
C←GROUP GROUP SPACE, C←CODE, C←DATA
; DB 2 DUP(?)
SPACE ENDS
C←CODE SEGMENT
$INCLUDE(Lark.d)
; stack initial value
SPIN EQU 0DFF0H
deiploc EQU 000H
decsloc EQU 002H
triploc EQU 004H
trcsloc EQU 006H
nmiploc EQU 008H
nmcsloc EQU 00AH
bkiploc EQU 00CH
bkcsloc EQU 00EH
oviploc EQU 010H
ovcsloc EQU 012H
; boot reasons
cDIVERR EQU 0
cTRACE EQU 1
cNMI EQU 2
cBREAK EQU 3
cOVERR EQU 4
cEXTINT EQU 254
cRESET EQU 255
C←DATA SEGMENT
←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 ?
←lip DW ? ; single step use
←cmklo DW 00H
←cmkhi DW 00H
←refa DW ?
←refb DW ?
←refc DW ?
←refd DW ?
←savea DW ?
←saveb DW ?
←lnmi DW ?
←eitype DW ?
C←DATA ENDS
EXTRN ←main:NEAR
EXTRN ←portstr:NEAR
ASSUME CS:C←CODE, DS:C←DATA
←cstart:
MOV AL,0FFH
OUT TimCtl,AL
MOV AL,083H ; Port A, C4-7 Out, Port B, C0-3 In, mode 0
OUT pioctl,AL
MOV AL,068H
OUT pioa,AL
MOV AL,0E1H
OUT pioa,AL
MOV AL,030H ; A and HS relays OFF
OUT pioc,AL
MOV AL,000H
OUT piob,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
XOR BX,BX
cmmt:
IN AL,pioc
TEST AL,4
JNZ cmst
IN AL,piob
MOV [BX+0AA55H],AL
MOV AL,[BX+0AA55H]
MOV [BX+055AAH],AL
MOV AL,[BX+055AAH]
JMP cmmt
cmst:
MOV BX,cRESET
←crestart:
MOV AX,SPIN
MOV SP,AX
MOV AX,CS
MOV SS,AX
MOV ES,AX
MOV DS,AX
CALL ←main
JMP DWORD PTR JHUNK
JHUNK DW 00H
DW 0FFFFH
; set timer, address of timer in BX, interval in CX
; call is settmr(interval, &timer)
; interval is in 1000ths of a second
←settmr PROC NEAR
ADD CX,←cmklo
MOV WORD PTR [BX],CX
RET
←settmr ENDP
; has timer expired? Address of timer in BX
; returns BX=1 if so, BX=0 if not
; call is if (tmrexp(&timer)) { ... }
←tmrexp PROC NEAR
MOV AX,WORD PTR [BX]
XOR BX,BX
CMP AX,←cmklo ; expired will leave sign bit set
JS teret
RET
teret:
INC BX
RET
←tmrexp ENDP
; Enable interrupts
←inton PROC NEAR
STI
RET
←inton ENDP
; Disable interrupts
←intoff PROC NEAR
CLI
RET
←intoff ENDP
wasnmi:
MOV rbx,BX
MOV BX,cNMI
JMP intcom
possnmi: ; if old, juggle stack
MOV AX,1
XCHG AX,←lnmi
OR AL,AL
JNZ wasntnmi
; if we reach here, fix stack so IRET returns to secret place!
MOV BX,0F000H
PUSH BX ; push flags
XOR BX,BX
PUSH BX ; push cs for this routine
MOV BX,OFFSET wasnmi
PUSH BX ; push ip for this routine
JMP wasntnmi
; Refresh Interrupt
RefA:
MOV ←savea,AX ; 3 bytes
MOV ←saveb,BX ; 4 bytes
XOR BX,BX ; 2 bytes
MOV AX,←refb ; 3 bytes
MOV [nmiploc+BX],AX ; 4 bytes
MOV AX,←cmklo ; 3 bytes
ADD AX,1 ; 3 bytes
MOV ←cmklo,AX ; 3 bytes
MOV AX,←cmkhi ; 3 bytes
ADC AX,0 ; 3 bytes
MOV ←cmkhi,AX ; 3 bytes
IN AL,pioc ; 2 bytes check for NMI
TEST AL,1 ; 2 bytes
JZ possnmi ; 2 bytes
wasntnmi:
MOV AX,←savea ; 3 bytes
MOV BX,←saveb ; 3 bytes
; total 46, we need 18 more, counting IRET
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
IRET
RefB:
MOV ←savea,AX ; 3 bytes
MOV ←saveb,BX ; 4 bytes
XOR BX,BX ; 2 bytes
MOV AX,←refc ; 3 bytes
MOV [nmiploc+BX],AX ; 4 bytes
MOV AX,←cmklo ; 3 bytes
ADD AX,1 ; 3 bytes
MOV ←cmklo,AX ; 3 bytes
MOV AX,←cmkhi ; 3 bytes
ADC AX,0 ; 3 bytes
MOV ←cmkhi,AX ; 3 bytes
MOV AX,←savea ; 3 bytes
MOV BX,←saveb ; 3 bytes
; total 40, we need 24 more, counting IRET
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
IRET
RefC:
MOV ←savea,AX ; 3 bytes
MOV ←saveb,BX ; 4 bytes
XOR BX,BX ; 2 bytes
MOV AX,←refd ; 3 bytes
MOV [nmiploc+BX],AX ; 4 bytes
MOV AX,←cmklo ; 3 bytes
ADD AX,1 ; 3 bytes
MOV ←cmklo,AX ; 3 bytes
MOV AX,←cmkhi ; 3 bytes
ADC AX,0 ; 3 bytes
MOV ←cmkhi,AX ; 3 bytes
MOV AX,←savea ; 3 bytes
MOV BX,←saveb ; 3 bytes
; total 50, we need 24 more, counting IRET
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
IRET
RefD:
MOV ←savea,AX ; 3 bytes
MOV ←saveb,BX ; 4 bytes
XOR BX,BX ; 2 bytes
MOV AX,←refa ; 3 bytes
MOV [nmiploc+BX],AX ; 4 bytes
MOV AX,←cmklo ; 3 bytes
ADD AX,1 ; 3 bytes
MOV ←cmklo,AX ; 3 bytes
MOV AX,←cmkhi ; 3 bytes
ADC AX,0 ; 3 bytes
MOV ←cmkhi,AX ; 3 bytes
MOV AX,←savea ; 3 bytes
MOV BX,←saveb ; 3 bytes
; total 50, we need 24 more, counting IRET
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
IRET
; initialize interrupt vectors
←intinit PROC NEAR
MOV AX,OFFSET RefA
MOV ←refa,AX
MOV AX,OFFSET RefB
MOV ←refb,AX
MOV AX,OFFSET RefC
MOV ←refc,AX
MOV AX,OFFSET RefD
MOV ←refd,AX
XOR BX,BX
XOR AX,AX
MOV [nmcsloc+BX],AX
MOV AX,←refa
MOV [nmiploc+BX],AX
RET
←intinit ENDP
; The format of this stuff is <port address><byte count><bytes>
; 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
DB pioa
DB 1
DB 0E1H
DB piob
DB 1
DB 000H
DB pioc
DB 1
DB 030H
DB apioctl
DB 1
DB 088H ; Port A, B, C0-3 Out, Port C4-7 In, mode 0
DB apioa
DB 1
DB 0C0H ; revert and off-hook relays 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
DB 01BH
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
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
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
DB intdata
DB 3
DB 070H
DB 001H
DB 0FFH
; end of string
DB 0FFH
←startm LABEL NEAR
CMP rsp,020H
JAE sok
MOV rsp,01F0H
sok:
MOV AX,rip
MOV ←lip,AX ; save current ip
MOV AX,rss
MOV SS,AX
MOV AX,rsp
MOV SP,AX
PUSH rfl
PUSH rcs
PUSH rip
MOV BX,rbx
MOV CX,rcx
MOV DX,rdx
MOV SI,rsi
MOV DI,rdi
MOV BP,rbp
MOV AX,rax
PUSH res
PUSH rds
POP DS
POP ES
IRET
brkpt LABEL NEAR
MOV rbx,BX
MOV BX,cBREAK
intcom:
MOV rax,AX
MOV rcx,CX
MOV rdx,DX
MOV rsi,SI
MOV rdi,DI
MOV rbp,BP
PUSH DS
POP rds
PUSH ES
POP res
POP rip
POP rcs
POP rfl
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
cmov LABEL NEAR
MOV rbx,BX
MOV BX,cOVERR
JMP intcom
cmde LABEL NEAR
MOV rbx,BX
MOV BX,cDIVERR
JMP intcom
; All other interrupts
UnkInt:
; in principle, CS contains the interrupt type and IP has
; whatever it takes to get control here.
PUSH BX
MOV BX,CS
MOV ←eitype,BX
POP BX
MOV AL,020H ; 8259 eoi
OUT intctl,AL
MOV rbx,BX
MOV BX,cEXTINT
DB 0EAH ; long jump to
DW OFFSET intcom ; intcom
DW 0
←setup PROC NEAR
CALL ←intinit
MOV BX,OFFSET ←I8255
CALL ←portstr
MOV BX,OFFSET ←I9513
CALL ←portstr
MOV BX,OFFSET ←I8237
CALL ←portstr
MOV BX,OFFSET ←I8274
CALL ←portstr
MOV BX,OFFSET ←I8259
CALL ←portstr
; now set up single step and breakpoint
XOR AX,AX
XOR BX,BX
MOV ←lnmi,AX
MOV [trcsloc+BX],AX
MOV [bkcsloc+BX],AX
MOV [decsloc+BX],AX
MOV [ovcsloc+BX],AX
MOV [triploc+BX],OFFSET trace
MOV [bkiploc+BX],OFFSET brkpt
MOV [deiploc+BX],OFFSET cmde
MOV [oviploc+BX],OFFSET cmov
; 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
MOV CX,251
MOV DI,014H
MOV BX,5
MOV DX,OFFSET UnkInt
SUB DX,050H
CLD
suih:
MOV AX,DX
STOSW
MOV AX,BX
STOSW
INC BX
SUB DX,010H
LOOP suih
; initialize save area
MOV rip,0200H
MOV rsp,01F0H
XOR AX,AX
MOV rcs,AX
MOV res,AX
MOV rds,AX
MOV rss,AX
MOV rfl,0F000H ; interrupts off
RET
←setup ENDP
PUBLIC ←settmr
PUBLIC ←tmrexp
; PUBLIC ←inton
; PUBLIC ←intoff
PUBLIC ←cmklo
PUBLIC ←cmkhi
PUBLIC ←mstate
PUBLIC ←startm
PUBLIC ←setup
PUBLIC ←lip
PUBLIC ←lnmi
PUBLIC ←eitype
C←CODE ENDS
END