- An 8251 USART next the 8255 PPI. Apparently it is used for the keyboard interfacing
- BIOS size 16 KiB, two 2764 EPROMs
- All numeric values are in hexadecimal
JMP F000:E05B
JMP C0D1
- C0D1:
- DS=0000
- SS=0000
- SP=0040 ; stack at 0000:0040
- OUT 3D0,00 ; Disable video?
- SI=C07D ; pointer to the table with the initial values for I/O ports - 25 values:
- OUT 71,00 ; Set USART to command mode: configure sync operation
- OUT 71,00 ; Write two dummy sync characters
- OUT 71,00
- OUT 71,40 ; Issue reset command
- OUT 71,4E ; Write mode instruction: 1 stop bit, no parity, 8 bits, divide clock by 16
- OUT 71,11 ; Write command instruction: Set Error Reset - ER, bit 4, and Transmit Enable - TE, bit 0
- OUT 83,00 ; DMA channel 1 page register
- OUT A0,00 ; Disable NMIs
- OUT B8,01 ; ??
- OUT 63,99 ; PPI control register - control word: group A&B: mode 0; port A - input, port B - output; port C - input
- OUT 61,B5 ; PPI port B: clear kbd/enable SW1, disable kbd clock, disable I/O check, disable parity check, read memory size from port C; turn off speaker, enable PIT channel 2 (speaker)
- OUT 08,04 ; DMA initialization...
- OUT 0D,03 ;
- OUT 00,00 ;
- OUT 00,00 ;
- OUT 01,FF ;
- OUT 01,FF ;
- OUT 02,00 ;
- OUT 02,00 ;
- OUT 03,00 ;
- OUT 03,00 ;
- OUT 04,00 ;
- OUT 04,00 ;
- OUT 05,00 ;
- OUT 05,00 ;
- OUT 06,00 ;
- OUT 06,00 ;
- OUT 07,00 ;
- OUT 07,00 ;
- OUT 0B,5B ;
- OUT 08,00 ;
- OUT 0A,00 ;
- OUT 43,54 ; PIT initialization...
- OUT 41,12 ;
- OUT 0B,41 ; DMA - enable memory refresh?!
- OUT 0B,42 ;
- OUT 0B,43 ;
- DI=C0E9 ; return address
- JMP C2C5 ; set I/O ports
- C0E9: ; Test first 64 KiB of RAM
- OUT 213,01 ; ??
- BX=[0472] ; BX - soft reset flag
- SI=C138
- ES=0000
- DL=54
- IF BX=1234 JMP C108 ; jump on soft reset
- DX=8080
- AX=5555 ; memory test pattern?
- C108:
- DI=AX ; save AX to DI
- IN AL,61
- OR AL,30 ; Disable I/O channel check, disable memory parity check
- OUT 61,AL
- OUT 61,AL ; I/O delay?!
- AND AL,CF ; Enable I/O channel check, enable memory parity check
- OUT 61,AL
- AX=DI ; restore AX (5555 for cold boot, 0000 for warm boot)
- DI=0000
- CX=8000
- REP STOSW ; first 64KiB of RAM: cold boot - initialize RAM with the pattern ; warm boot - clear RAM
- Compare initialized memory with the pattern / 0000 if doesn't match JMP C136
- Apparently repeat again with AAAA pattern for cold boot
- IN AL,62 ; Read PPI Port C
- AND AL,C0 ; Isolate I/O check and parity flags
- JMP SI ; SI = C138
- C138:
- JZ C143 ; Jump if no memory errors
- DX=E389
- SI=C13A
- JMP C2DC ; something to do with memory errors?!
- C13A:
- [0472]=BX ; restore soft reset flag after memory test
- DX=A000
- DI=0000
- C14C: ; Test/size the rest of RAM
- DX=DX-1000
- ES=DX
- AH=DH
- AL=AH
- AL=!AL
- ES:[DI]=AX
- IF AH != 00 JMP C14C
- DX=1000
- BX=0040
- C166:
- ES=DX
- AH=DH ; 10?
- AL=AH
- AL=!AL
- CX=8000
- SUB AX,ES:[DI]
- JNZ C184
- REP STOSW
- ADD DX,1000
- ADD BX,40
- CMP AH,A0
- JNZ C166
- C184:
- MOV [0413],BX - store memory size to BDA
- SI=C0C8 ; pointer to the table with the values for I/O ports - 4 values:
- OUT 20,13 ; PIC initialization
- OUT 21,08
- OUT 21,09
- OUT 21,FF
- CALL C2C4 ; set I/O ports
- SP=0080
- CX=0020 - number of vectors to initialize - INT 0 - INT 19
- SI,FF21 - interrupt vectors, offsets only - this is the top of the table, 20 word entries
- INT 00 = F000:F862, INT 01 = F000:F862, INT 02 = F000:E2C3, INT 03 = F000:F862
- INT 04 = F000:F862, INT 05 = F000:D03A, INT 06 = F000:F862, INT 07 = F000:F862
- INT 08 = F000:D2E4, INT 09 = F000:F862, INT 0A = F000:F862, INT 0B = F000:F862
- INT 0C = F000:F862, INT 0D = F000:F862, INT 0E = F000:C84D, INT 0F = F000:F862
- INT 10 = F000:D53E, INT 11 = F000:F84D, INT 12 = F000:F841, INT 13 = F000:C443
- INT 14 = F000:D0E6, INT 15 = F000:FF53, INT 16 = F000:CA6F, INT 17 = F000:CF56
- INT 18 = F000:C0D1, INT 19 = F000:C38C, INT 1A = F000:D26E, INT 1B = F000:FF53
- INT 1C = F000:FF53, INT 1D = F000:D328, INT 1E = F000:C42A, INT 1F = F000:0000
- C197: ; Initialize Interrupt vector table
- PUSH CS
- MOV AX,CS:[SI]
- DEC SI
- DEC SI
- PUSH AX
- LOOPW C197
- C1A0:
- SP=0400
- CALL C372 ; read switches to AL and AH
- AH = 00
- [0410]=AX ; store to BDA / equipment list
- CALL DF62 ; initialize video controller
- if warm boot jump to C1BC
- C1B6:
- MOV SI,C046 ; 'POWER ON TEST'
- CALL C2B5 ; print string
- C1BC:
- DI=C000
- DX=C800
- CALL C319 ; extension ROM scan - video controllers only (C000-C800)
- CALL CEC8 ; initialize keyboard and enable keyboard interrupt
- if warm boot jump to C1D3
- CALL C23E ; RAM test continued?!
- C1D3:
- CALL C29F ; Configure PIT channel 0 and enable timer interrupt
- DI=C800
- DX=F600
- CALL C319 ; extension ROM scan - the rest of upper memeory (C800-F600)
- CALL C29F ; Configure PIT channel 0 and enable timer interrupt (in case extension ROMs disabled it?!)
- CALL C28C ; Enable FDC interrupt and reset FDC
- JAE C1ED ; jump if FDC initialized successfully?
- SI=C2B0 ; 'DISKETTE ERROR'
- CALL C2B0 ; set error flag [0412]=FF, and print error message
- C1ED:
- IN AL,21
- AND AL,FC ; clear bits 1 and 0, unmask IRQ1 and IRQ0
- OUT 21,AL
- INC BYTE PTR [0412] ; increment error flag, will set ZF on error?
- PUSHF
- DX=C002
- JZ C200 ; jump on error
- DX=8001
- C200:
- CALL C2DB ; beep, pattern depends on errors
- POPF
- JNZ C21C ; jump if no error
- TEST BYTE PTR [0410],01 ; Equipment word, IPL installed?
- JZ C21C ; yes IPL
- SI=C058 ; 'PRESS F1 KEY'
- CALL C2B5 ; print string
- C213:
- MOV AH,00
- INT 16 ; wait for key
- CMP AH,3B ; F1?
- JNZ C213 ; nope
- C21C:
- CALL CFE2 ; initialize LPT ports
- ROR AL,1 ; shift LPT bits for equipment word?
- ROR AL,1
- PUSH AX
- CALL D203 ; initialize COM ports, also enabled USART tx/rx...
- POP SI
- ROL AL,1
- OR AX,SI
- MOV [0411],AL ; update LPT and COM port count in BDA equipment word
- CALL C367 ; reset I/O check and parity NMIs
- OUT A0,80 ; enable NMIs
- SI=C070 ; 'WAITING...'
- CALL C2B5 ; print string
- INT 19 ; call IPL loader
- C28C:
- IN AL,21
- AND AL,BF - clear bit 6 - umask IRQ 6
- OUT 21,AL
- AX=0000
- DL=00
- INT 13
- JB C29E ; jump if CF == 1
- DEC AH
- INT 13
- C29E:
- RET
- OUT 43,36
- OUT 40,00
- OUT 40,00
- IN AL,21
- AND AL,FE ; clear bit 0 - unmask IRQ 0
- OUT 21,AL
C2B0 - Set error flag [0412]=FF, and print zero zero-terminated string pointed by CS:SI to the screen
- POP DI
- Inputs
- SI - pointer to the table with the initial values for I/O ports:
- First byte - number of ports to set
- Followed by pairs of bytes: value to write and port number
- DI - return address
- SI - pointer to the table with the initial values for I/O ports:
- IN AL,61
- OR AL,30
- OUT 61,AL
- AND AL,CF
- OUT 61,AL
- RET
- C372:
- AH=00
- CALL C37B
- C377:
- OUT 61,BD ; previous value was B5, so setting bit 3, probably enables the other half of switches?
- C37B:
- IN AL,62 ; read PPI Port C
- AND AL,0F ; get switches
- OR AL,AH ; set bits in AL according to AH bit mask
- MOV CL,04
- ROL AL,CL ; rotate
- MOV AH,AL
- RET
CEC8:
PUSH AX
PUSH CX
MOV AX,001E ; Pointer to the beginning of the keyboard buffer in the BIOS Data Area
MOV [041A],AX ; Keyboard buffer head
MOV [041C],AX ; Keyboard buffer tail
MOV [0480],AX ; Keyboard buffer start offset
MOV WORD PTR [0482],003E ; Keyboard buffer end offset
MOV AL,40
OUT 61,AL ; Enable keyboard clock
MOV AL,00
OUT 60,AL ; Send 0 to the keyboard?! What does it do? Resets the keyboard? Runs diagnostics?
CEE4:
IN AL,71 ; Read USART status register
AND AL,04 ; Isolate TxEMPTY bit
JZ CEE4 ; Wait until TxEMPTY is set
MOV AL,05
OUT AL,71 ; Set Receive Enable, bit 2 and Transmit Enable, bit 0
MOV BYTE PTR [046B],00 ; This location is unused on a typical PC/XT, but it appears to be used as some kind of flag here
IN AL,21 ; Read interrupt mask from PIC to AL
AND AL,FD ; Reset bit 1 - unmask IRQ1
OUT 21,AL ; Write new interrupt mask to PIC
STI
MOV CX,0000 ; Timeout counter
MOV AH,03 ; High byte of timeout counter
CEFF:
TEST BYTE PTR [046B],02 ; Check if IRQ1 have happened
JNZ CF0E ; Bit 1 is set, exit the loop
LOOPW CEFF
DEC AH
JNZ CEFF
JMP CF20 ; Jump if timeout waiting for bit 1
CLI
IN AL,71 ; Read USART status register
AND AL,38 ; Check Error bits
JNZ CF20 ; Jump if USART error bits set
IN AL,60 ; Read the keyboard. What are we expecting to get here? Keyboard diagnostics / POST status?
MOV [04EE],AL ; Store in the BIOS Data Area, note 04EE is not typically used on PC/XT
AND AL,F0 ; Isolate top 4 bits
CMP AL,A0 ; Check bits 7 and 5
JZ CF2D ; Jump if bits 7 and 5 are not set
CF20:
PUSH SI
MOV SI,CF3E ; "Keyboard Error"
CALL E05E ; Print zero-terminated string pointed by CS:SI on the screen
POP SI
MOV BYTE PTR [0412],FF ; 0412 is IBM PCjr infrared keyboard error count... Perhaps indicates keyboard error here?!
MOV AL,C0
OUT 61,AL ; Clear keyboard shift regiser, enable keyboard clock
MOV AL,40
OUT 61,AL ; Enable keyboard, enable keyboard clock
MOV WORD PTR [0024],CB32 ; Set IRQ1 handler offset to CB32 (originally it is pointing to the default interrupt handler)
POP CX
POP AX
RET
- OUT 71,05 ; why here? USART - transmit enable, receive enable
- F862:
- PUSH AX
- PUSH DS
- MOV BYTE PTR [046B],FF - indicate an unknown unhandled interrupt?
- OUT 20,0B ; PIC OCW3 - read in-service register
- IN AL,20 ; get IRQ number
- CMP AL,00 ; unknown interrupt?
- JZ F887 ; exit
- MOV AH,AL ; save vector to AH
- MOV [046B],AL ; Last spurious IRQ number
- IN AL,21
- OR AL,AH
- OUT 21,AL ; clear interrupt
- OUT 20,20 ; signal end of interrupt to PIC
- F887:
- POP DS
- POP AX
- RET