Skip to content

Commit 5490631

Browse files
committed
INT 10h video mode fix, PIT test use 16 bit counter
1 parent 43acad4 commit 5490631

File tree

1 file changed

+82
-62
lines changed

1 file changed

+82
-62
lines changed

src/GLABIOS.ASM

Lines changed: 82 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,11 +1500,12 @@ BIOS_TOP ENDP
15001500

15011501
BYTES_HERE POWER_ON ; 5 BYTES HERE
15021502

1503+
15031504
ASSUME CS:_BIOS, DS:NOTHING, ES:NOTHING, SS:NOTHING
15041505
;----------------------------------------------------------------------------;
15051506
; F000:E05B: Beginning of boot execution
15061507
;----------------------------------------------------------------------------;
1507-
; Loosely follow these publicly-available specs for BIOS POST operations:
1508+
; Loosely follow these specs for BIOS POST operations:
15081509
;
15091510
; http://minuszerodegrees.net/5160/post/5160%20-%20POST%20-%20Detailed%20breakdown.htm
15101511
; http://minuszerodegrees.net/5150/post/5150%20-%20POST%20-%20Detailed%20breakdown.htm
@@ -1531,22 +1532,15 @@ POWER_ON PROC NEAR
15311532
CLI ; disable CPU interrupts
15321533
CLD ; clear direction flag
15331534

1534-
;----------------------------------------------------------------------------;
1535-
; Disable non-maskable interrupts (NMIs) from reaching the CPU.
1536-
;----------------------------------------------------------------------------;
1537-
DISABLE_NMI:
1538-
XOR AX, AX
1539-
OUT NMI_R0, AL ; write AL = 0 to NMI register port
1540-
15411535
;----------------------------------------------------------------------------;
15421536
; POST Hardware/System Tests
15431537
;----------------------------------------------------------------------------;
15441538

15451539
POST_CPU_TEST:
15461540
;----------------------------------------------------------------------------;
1547-
; 1 - A "very thorough" test of the CPU Registers
1541+
; [1] Test and clear all CPU Registers
15481542
;----------------------------------------------------------------------------;
1549-
; Check and clear all registers
1543+
; Check and set all registers to 0.
15501544
;
15511545
; On Failure: 1 long beep and 2 short beeps
15521546
;----------------------------------------------------------------------------;
@@ -1566,11 +1560,17 @@ CPU_REG_TEST:
15661560
MOV BL, 21H ; on Failure: 2 short and 1 long beep
15671561
JNZ HALT_ERROR
15681562
XOR AX, AX ; otherwise repeat with AX = 0
1569-
JNZ HALT_ERROR ; if ZF was not set, you're in trouble
1563+
JNZ HALT_ERROR ; if ZF was not set, it's not good
15701564
TEST DX, DX ; if zero it was second pass
15711565
JNZ CPU_REG_TEST ; Loop again to zero all registers
15721566
CPU_REG_PASS:
15731567

1568+
;----------------------------------------------------------------------------;
1569+
; Disable non-maskable interrupts (NMIs)
1570+
;----------------------------------------------------------------------------;
1571+
DISABLE_NMI:
1572+
OUT NMI_R0, AL ; write AL = 0 to NMI register port
1573+
15741574
;----------------------------------------------------------------------------;
15751575
; [1B] A brief test of flags and CPU instructions
15761576
;----------------------------------------------------------------------------;
@@ -1666,6 +1666,7 @@ RESET_PPI:
16661666
;----------------------------------------------------------------------------;
16671667
; [8] Checksum (8 bit) the main ROM to ensure it is not corrupt
16681668
;----------------------------------------------------------------------------;
1669+
; Input: AH = 0, DX = 0F000h
16691670
; On Failure: 2 long beep and 2 short beeps
16701671
;----------------------------------------------------------------------------;
16711672
JWB CHECKSUM_OK ; skip on warm boot
@@ -1674,11 +1675,11 @@ CHECKSUM_ROM:
16741675
MOV DS, DX ; DS to 0F000h BIOS segment
16751676
MOV SI, OFFSET BIOS_TOP ; offset to top of BIOS ROM
16761677
MOV CH, 10H ; checksum 8KB (in 2 byte words)
1677-
XOR BX, BX ; BL = accumulator for sum
1678+
CWD ; DL = accumulator for sum, DH = 0
16781679
CHECKSUM:
16791680
LODSW ; next two bytes into AL and AH
1680-
ADD BL, AL
1681-
ADD BL, AH ; ZF if sum is 0
1681+
ADD DL, AL
1682+
ADD DL, AH ; ZF if sum is 0
16821683
LOOP CHECKSUM ; loop through entire ROM
16831684
MOV BL, 22H ; on failure, 2 short and 2 long beeps
16841685
JNZ HALT_ERROR ; if sum not 0, fail
@@ -1692,17 +1693,6 @@ INIT_DMA1:
16921693
MOV AL, 00000100B ; Set Controller Disable bit
16931694
OUT DMA_CMD, AL ; write to DMA Command Register
16941695

1695-
;----------------------------------------------------------------------------;
1696-
; [9B] 8253 PIT Programmable Interval Timer Initialization Channel 1
1697-
;----------------------------------------------------------------------------;
1698-
; Counter 1 - DRAM Refresh
1699-
;----------------------------------------------------------------------------;
1700-
INIT_PIT1:
1701-
MOV AL, 01010100B ; Control Word: Counter 1
1702-
; Format: R/W low byte
1703-
; Mode: 2 Rate Gen, BCD: 0
1704-
OUT PIT_CTRL, AL ; set Counter mode
1705-
17061696
IF POST_TEST_PIT_1 EQ 1
17071697
;----------------------------------------------------------------------------;
17081698
; [10] Test Channel #1 on 8253 timer chip.
@@ -1711,21 +1701,40 @@ INIT_PIT1:
17111701
; If the test fails, beep failure code
17121702
;
17131703
; Test that all data lines are working by reading counter and checking
1714-
; that all bits from counter go both high and low. The result should
1715-
; be the opposite of the starting value.
1704+
; that all bits from counter go both high and low.
17161705
;----------------------------------------------------------------------------;
1717-
MOV AL, 0
1718-
MOV DX, 0FFH ; high byte is all 0's, low is all 1's
1719-
OUT PIT_CH1, AL
1706+
; Use 16-bit mode to test low three address lines using high byte of counter.
1707+
; This avoids a situation where the read counter code is a binary multiple
1708+
; of the counter causing a bit to not be observed as changing.
1709+
;
1710+
; Control Word Counter 1 (port 43H) - System Timer:
1711+
; 01 - SC: Select Counter 1
1712+
; 11 - RW: Read/Write 2xR/2xW
1713+
; 010 - M: Mode 2, Rate Gen
1714+
; 0 - BCD: 0
1715+
;
1716+
MOV AL, 01110100B ; Control Word: Counter 1
1717+
; Format: R/W low/high byte
1718+
; Mode: 2 Rate Gen, BCD: 0
1719+
OUT PIT_CTRL, AL ; set Counter mode
1720+
MOV DX, LOW PIT_CH1 ; DX = PIT channel 1
1721+
OUT DX, AL ; set low byte (any value)
1722+
MOV SI, 0FFH SHL 3 ; look at bits 10-3 for 1 check
1723+
MOV DI, NOT 0FFH SHL 3 ; look at bits 10-3 for 0 check
1724+
OUT DX, AL ; set high byte (any value)
17201725
INIT_PIT1_TEST:
1726+
CMP SI, 0FFFFH ; have all bits flipped to 1?
1727+
JNZ INIT_PIT1_TEST_READ
1728+
TEST DI, DI ; have all bits flipped to 0?
1729+
JZ INIT_PIT1_TEST_DONE
1730+
INIT_PIT1_TEST_READ:
17211731
MOV AL, 01000000b ; latch Counter 1 command
17221732
OUT PIT_CTRL, AL ; write command to CTC
1723-
CMP DX, NOT 0FFH ; have all bits flipped?
1724-
JZ INIT_PIT1_TEST_DONE
1725-
IO_DELAY_SHORT ; I/O delay
1726-
IN AL, PIT_CH1 ; read timer counter
1727-
AND DL, AL ; clear all lines received on low byte
1728-
OR DH, AL ; set all lines received on high byte
1733+
IN AL, DX ; read timer LSB
1734+
XCHG AH, AL ; save LSB
1735+
IN AL, DX ; read timer MSB
1736+
AND DI, AX ; clear all lines received as 0
1737+
OR SI, AX ; set all lines received as 1
17291738
LOOP INIT_PIT1_TEST ; loop until timeout
17301739
MOV BL, 32H ; beep pattern (3 short, 2 long)
17311740
HALT_ERROR:
@@ -1739,6 +1748,17 @@ HALT_ERROR:
17391748

17401749
INIT_PIT1_TEST_DONE:
17411750

1751+
;----------------------------------------------------------------------------;
1752+
; [9B] 8253 PIT Programmable Interval Timer Initialization Channel 1
1753+
;----------------------------------------------------------------------------;
1754+
; Counter 1 - DRAM Refresh
1755+
;----------------------------------------------------------------------------;
1756+
INIT_PIT1:
1757+
MOV AL, 01010100B ; Control Word: Counter 1
1758+
; Format: R/W low byte
1759+
; Mode: 2 Rate Gen, BCD: 0
1760+
OUT PIT_CTRL, AL ; set Counter mode
1761+
17421762
;----------------------------------------------------------------------------;
17431763
; [12] Reset, Clear and test DMA Offset and Block Size Registers
17441764
;----------------------------------------------------------------------------;
@@ -1750,7 +1770,7 @@ INIT_PIT1_TEST_DONE:
17501770
IF POST_TEST_DMA EQ 1
17511771
MOV BH, 8 ; test 8 ports
17521772
XOR DX, DX ; starting at port 00H
1753-
CALL_NS WB_TEST ; ZF if pass, NZ if failed
1773+
CALL_NS WB_TEST ; ZF and CX = 0 if pass, NZ if failed
17541774
MOV BL, 42H ; beep pattern (4 short, 2 long)
17551775
JNZ HALT_ERROR
17561776
DMA_PASS:
@@ -1765,9 +1785,8 @@ DMA_PASS:
17651785
;----------------------------------------------------------------------------;
17661786
MOV AL, 0FFH ; Memory refresh counter (16-bit) is 0FFFFH
17671787
OUT DMA_0_C, AL ; write low order bits
1768-
IO_DELAY_SHORT
1788+
NOP ; very short I/O delay
17691789
OUT DMA_0_C, AL ; write high order bits
1770-
;IO_DELAY_SHORT ; necessary?
17711790

17721791
;----------------------------------------------------------------------------;
17731792
; [13] Set Mode DMA Channel 0
@@ -1780,25 +1799,21 @@ DMA_PASS:
17801799
;----------------------------------------------------------------------------;
17811800
MOV AL, 01011000B ; see above
17821801
OUT DMA_MODE, AL ; write to DMA Mode Register
1783-
IO_DELAY_SHORT
17841802

17851803
;----------------------------------------------------------------------------;
17861804
; [13B] 8253 Timer set channel #1 for DMA/DRAM refresh
17871805
;----------------------------------------------------------------------------;
17881806
MOV AL, 18 ; divisor: 1.19318 MHz / 18 = 66,287.7 Hz
17891807
OUT PIT_CH1, AL ; refresh DRAM every 2ms
1790-
;IO_DELAY_SHORT
17911808
ENDIF
17921809

17931810
;----------------------------------------------------------------------------;
17941811
; [13C] Enable DMA and clear mask register on Channels 0-3
17951812
;----------------------------------------------------------------------------;
17961813
MOV AL, 0 ; Set Controller Enable bit
17971814
OUT DMA_CMD, AL ; write to DMA Command Register
1798-
IO_DELAY_SHORT ; necessary?
1799-
1815+
MOV CL, 3 ; Set mode on Channels 1-3 for [13D]
18001816
OUT DMA_MASK, AL ; clear mask (enable) on all channels
1801-
;IO_DELAY_SHORT
18021817

18031818
;----------------------------------------------------------------------------;
18041819
; [13D] Set default Mode for DMA Channels 1-3
@@ -1808,9 +1823,10 @@ DMA_PASS:
18081823
; 0 ; No Auto-initialization
18091824
; 00 ; type: Verify
18101825
; xx ; Channels 1-3
1826+
;
1827+
; Input: CL = 3 from [13C], CH = 0 from CALL_NS in [12]
18111828
;----------------------------------------------------------------------------;
18121829
MOV AL, 01000001B ; AL = 01000001
1813-
MOV CL, 3 ; Set mode on Channels 1-3
18141830
DMA_SETUP_CH:
18151831
OUT DMA_MODE, AL ; write to DMA Mode Register
18161832
INC AX ; next channel
@@ -1848,14 +1864,16 @@ DMA_SETUP_CH:
18481864
; On failure:
18491865
; - Read/Write Error: 1 short, 3 long beeps
18501866
; - Parity Error: 1 short, 4 long beeps
1867+
;
1868+
; Input: CX = 0 from [13D]
18511869
;----------------------------------------------------------------------------;
18521870
ASSUME DS:_BDA_ABS, ES:_IVT
18531871
BASE_RAM_TEST:
18541872
IN AL, PPI_B ; AL = PB0 flags
18551873
OR AL, MASK PBIO OR MASK PBPC ; disable RAM parity and I/O ch. flags
18561874
OUT PPI_B, AL
1857-
XOR AX, AX ; DS and ES = IVT segment 0000
1858-
MOV DS, AX
1875+
XCHG AX, CX ; AX = 0 = MEM_CHECK pattern and
1876+
MOV DS, AX ; DS and ES = IVT segment 0000
18591877
MOV ES, AX
18601878
MOV SI, OFFSET WARM_FLAG_ABS ; preserve warm boot flag
18611879
MOV DX, WORD PTR[SI] ; save warm boot flag
@@ -1875,8 +1893,7 @@ HALT_BEEP_1:
18751893
BASE_RAM_ZERO:
18761894
MOV AX, RAM_TEST ; test pattern
18771895
CALL_NS MEM_CHECK ; write and verify test pattern
1878-
JNZ BASE_RAM_ERROR
1879-
XOR AX, AX ; zero
1896+
JNZ BASE_RAM_ERROR ; ZF and AX = 0 if okay
18801897
CALL_NS MEM_CHECK ; write and verify zeros
18811898
JNZ BASE_RAM_ERROR
18821899
MOV WORD PTR[SI], DX ; restore warm boot flag
@@ -1904,8 +1921,7 @@ BASE_RAM_TEST_DONE:
19041921
ASSUME SS:_BOOT_STACK
19051922
MOV AX, SEG STACK_TOP ; SP to temp boot stack 0030:0100
19061923
MOV SS, AX
1907-
MOV AX, OFFSET STACK_TOP
1908-
MOV SP, AX
1924+
MOV SP, OFFSET STACK_TOP
19091925

19101926
;----------------------------------------------------------------------------;
19111927
; [19] 8259A PIC Interrupt controller Initialization
@@ -1938,7 +1954,7 @@ BASE_RAM_TEST_DONE:
19381954
INC DX ; DX = PIC Port 1
19391955
MOV AL, 00001000B ; ICW2 - Port 1
19401956
OUT DX, AL
1941-
NOP ; short delay
1957+
MOV BH, 1 ; short delay and test 1 port for [22]
19421958
MOV AL, 00001001B ; ICW4 - Port 1
19431959
OUT DX, AL
19441960

@@ -1948,14 +1964,13 @@ BASE_RAM_TEST_DONE:
19481964
;----------------------------------------------------------------------------;
19491965
; - Read and write registers (IMR) and verify result
19501966
;----------------------------------------------------------------------------;
1951-
MOV BH, 1 ; test 1 port
19521967
CALL WB_TEST ; walking bit test of PIC IMR register
19531968
MOV BL, 52H ; beep error 5 short, 2 long
19541969
JZ PIC_REG_PASS
19551970
PIC_INT_FAIL:
19561971
JMP SHORT HALT_BEEP_1
19571972
PIC_REG_PASS:
1958-
DEC DX ; DX = Port 1 (21h)
1973+
DEC DX ; DX = Port 1 (0021h)
19591974
ELSE
19601975
NOP
19611976
ENDIF ; IF POST_TEST_PIC_REG EQ 1
@@ -1981,7 +1996,7 @@ PIC_VECT_TMP_LOOP:
19811996
; - Mask all interrupts and ensure none are received
19821997
;
19831998
MOV DI, OFFSET INT_LAST_ABS
1984-
MOV [DI], DH ; clear last interrupt flag
1999+
MOV [DI], DH ; clear last interrupt flag (DH = 0)
19852000
STI ; enable interrupts
19862001
IO_DELAY ; wait for it...
19872002
CLI
@@ -1994,9 +2009,11 @@ PIC_VECT_TMP_LOOP:
19942009
JZ PIC_INT_PASS
19952010
JMP SHORT HALT_BEEP_1
19962011
ENDIF ; IF POST_TEST_PIC_REG EQ 1
1997-
19982012
ENDIF ; IF POST_TEST_PIC_INT EQ 1
19992013

2014+
MOV AL, 11111110B ; OCW1 - unmask timer
2015+
OUT DX, AL ; write IMR to PIC
2016+
20002017
PIC_INT_PASS:
20012018

20022019
;----------------------------------------------------------------------------;
@@ -2263,12 +2280,12 @@ VID_MODE_OK:
22632280
; Clear screen and reset the video display.
22642281
;
22652282
RESET_VIDEO:
2266-
XOR AH, AH ; AH = 0 - Set Video Mode in AL
2283+
CBW ; AH = 0 - Set Video Mode in AL
22672284
INT 10H
22682285
RESET_VIDEO_DONE:
22692286

22702287
;----------------------------------------------------------------------------;
2271-
; Hello Computer (just use the keyboard)
2288+
; Hello Computer ("just use the keyboard")
22722289
;----------------------------------------------------------------------------;
22732290
HELLO_WORLD:
22742291
PRINTLN_SZ VER_BANNER ; display banner
@@ -2292,7 +2309,7 @@ HELLO_WORLD:
22922309
PRINT_SZ VER ; display version
22932310
PRINT_SZ REL_DATE ; display build date
22942311
POP DX ; restore previous cursor
2295-
MOV AH, 2 ; reset cursor position
2312+
MOV AH, 2 ; reset cursor position
22962313
INT 10H ; row = DH, column = DL
22972314
ELSE
22982315
PRINT_SZ VER ; display version
@@ -3799,7 +3816,7 @@ MEM_ADDR_TEST ENDP
37993816
;
38003817
; Clobbers AX, CX, DI
38013818
;
3802-
; ZF if okay, NZ if fail
3819+
; ZF and AX = 0 if okay, NZ if fail
38033820
;----------------------------------------------------------------------------;
38043821
MEM_TEST PROC
38053822
MOV AX, RAM_TEST ; test pattern
@@ -3813,7 +3830,7 @@ MEM_TEST PROC
38133830
; AX = pattern to write
38143831
; ES = segment for test
38153832
;
3816-
; ZF if okay, NZ if fail
3833+
; ZF and AX = 0 if okay, NZ if fail
38173834
;----------------------------------------------------------------------------;
38183835
MEM_CHECK:
38193836
MOV CX, 02000H ; loop 2000H WORDs
@@ -3823,6 +3840,7 @@ MEM_TEST_VERIFY:
38233840
MOV CH, 20H ; restart loop 2000H
38243841
XOR DI, DI ; start at offset 0
38253842
REPZ SCASW ; loop until CX = 0 OR WORD is not AX
3843+
XCHG AX, CX ; AX = 0 if success
38263844
RET
38273845
MEM_TEST ENDP
38283846

@@ -6015,6 +6033,7 @@ INT_10_IS_CGA80 PROC
60156033
INT_10_IS_CGA80_DONE:
60166034
POP DS
60176035
POP AX
6036+
INT_10_0_RET:
60186037
RET
60196038
INT_10_IS_CGA80 ENDP
60206039

@@ -6083,7 +6102,7 @@ INT_1D ENDP
60836102
;----------------------------------------------------------------------------;
60846103
INT_10_0 PROC
60856104
CMP AL, 7 ; is new video page > 7?
6086-
JA INT_10_DONE ; if so, not valid, return
6105+
JA INT_10_0_RET ; if so, not valid, return
60876106
PUSH AX
60886107
PUSH BX
60896108
PUSH DX
@@ -7835,6 +7854,7 @@ OUT_SZ ENDP
78357854
; BH = number of sequential ports to test
78367855
; Output:
78377856
; NZ if failed
7857+
; CX = 0 if success
78387858
;
78397859
; Adapted from:
78407860
; https://barrgroup.com/embedded-systems/how-to/memory-test-suite-c

0 commit comments

Comments
 (0)