Updated PIT nomenclature, added more DeskPro 386 ROM notes

This commit is contained in:
Jeff Parsons 2015-04-15 10:59:57 -07:00 committed by jeffpar
commit 9b1de72137
5 changed files with 594 additions and 548 deletions

File diff suppressed because it is too large Load diff

View file

@ -185,228 +185,3 @@ Turns out this is because the A20 line has been disabled.
-------------------------------------------------------------------------------------------------
Let's look at a complete run:
EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000304
ESP=00000000 EBP=00000000 ESI=00000000 EDI=00000000
SS=0000 DS=0000 ES=0000 FS=0000 GS=0000 PS=00000002 V0 D0 I0 T0 S0 Z0 A0 P0 C0
F000:FFF0 EA05F900F0 JMP F000:F905
I want to catch writes to the top-left corner of the screen, so I set a write breakpoint:
bw b800:0
which reports:
write breakpoint added to memory block 000B8000
breakpoint enabled: B800:0000 (write)
and then we're off:
running
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x00) @F000:F907
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x01) @F000:F926
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x02) @F000:F93C
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x03) @F000:F942
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x04) @F000:F946
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x05) @F000:F95F
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x06) @F000:F978
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x08) @F000:F9AA
notice: PIC0(0x20): unsupported OCW2 automatic EOI command: 0x00
stopped (149 ops, 622 cycles, 92 ms, 6761 hz)
EAX=0000F000 EBX=00000000 ECX=00000008 EDX=00000020
ESP=00000000 EBP=00000000 ESI=0000F8E7 EDI=00000000
SS=0000 DS=F000 ES=0000 FS=0000 GS=0304 PS=00000046 V0 D0 I0 T0 S0 Z1 A0 P1 C0
F000:F9ED E6A0 OUT A0,AL
running
notice: PIC1(0xA0): unsupported OCW2 automatic EOI command: 0x00
stopped (150 ops, 5 cycles, 19 ms, 263 hz)
EAX=0000F000 EBX=00000000 ECX=00000008 EDX=00000020
ESP=00000000 EBP=00000000 ESI=0000F8E7 EDI=00000000
SS=0000 DS=F000 ES=0000 FS=0000 GS=0304 PS=00000046 V0 D0 I0 T0 S0 Z1 A0 P1 C0
F000:F9EF B009 MOV AL,09
running
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x09) @F000:F9F1
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x0F) @F000:BAAA
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x10) @F000:BAFB
bus.outPort(0x004B,unknown,0x12) @F000:BAFF
bus.outPort(0x004B,unknown,0x42) @F000:BB03
bus.outPort(0x004B,unknown,0x92) @F000:BB07
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x11) @F000:BB29
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x12) @F000:BB70
breakpoint hit: B800:0000 (write)
stopped (413 ops, 959 cycles, 80 ms, 11988 hz)
EAX=00000720 EBX=0000BA77 ECX=00001FFF EDX=000003D8
ESP=00000000 EBP=0000BB78 ESI=0000F0C6 EDI=00000002
SS=0000 DS=F000 ES=B800 FS=0000 GS=0304 PS=00000046 V0 D0 I0 T0 S0 Z1 A0 P1 C0
F000:9C05 F3 REPZ
F000:9C06 AB STOSW
This is where screen memory is first initialized ("blanked").
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x13) @F000:BB90
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x14) @F000:BBB8
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x15) @F000:BBD8
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x17) @F000:BC08
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x18) @F000:BC14
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x40) @F000:B552
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x2F) @0018:87B4
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x41) @F000:B572
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x42) @F000:B599
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x43) @F000:B5C4
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x44) @F000:B5D2
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x45) @F000:B600
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x43) @F000:B5C4
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x44) @F000:B5D2
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x45) @F000:B600
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x46) @F000:B61C
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x19) @F000:BC2C
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x30) @F000:A8B0
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x31) @F000:A905
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x32) @F000:A91D
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x33) @F000:A93B
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x34) @F000:A953
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x36) @F000:A991
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x38) @F000:A99C
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x39) @F000:A9BC
bus.inPort(0x03BC,unknown) @F000:A9CA
bus.outPort(0x03BC,unknown,0x00) @F000:A9CD
bus.inPort(0x03BC,unknown) @F000:A9D0
bus.inPort(0x0378,unknown) @F000:A9CA
bus.outPort(0x0378,unknown,0x00) @F000:A9CD
bus.inPort(0x0378,unknown) @F000:A9D0
bus.inPort(0x0278,unknown) @F000:A9CA
bus.outPort(0x0278,unknown,0x00) @F000:A9CD
bus.inPort(0x0278,unknown) @F000:A9D0
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x3A) @F000:A9DE
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x3B) @F000:A9FB
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x52) @F000:AA41
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x53) @F000:AA54
bus.outPort(0x03B9,unknown,0x30) @F000:9BE7
write breakpoint added to memory block 000B8000
write breakpoint added to memory block 000B8000
breakpoint hit: B800:0000 (write)
stopped (1340834 ops, 3291994 cycles, 821 ms, 4009737 hz)
EAX=00000720 EBX=00000720 ECX=00003FFF EDX=0000B800
ESP=000000D0 EBP=FFFF2230 ESI=00000CBA EDI=00000002
SS=0030 DS=0000 ES=B800 FS=0000 GS=0304 PS=00000246 V0 D0 I1 T0 S0 Z1 A0 P1 C0
C000:0E93 F3 REPZ
C000:0E94 AB STOSW
Now the video card's own BIOS is doing the same thing, followed by more of the same:
write breakpoint added to memory block 000B8000
write breakpoint added to memory block 000B8000
breakpoint hit: B800:0000 (write)
stopped (1384492 ops, 79242 cycles, 52 ms, 1523885 hz)
EAX=00000720 EBX=00000720 ECX=00003FFF EDX=0000B800
ESP=000000C8 EBP=FFFF2230 ESI=00000C3A EDI=00000002
SS=0030 DS=0000 ES=B800 FS=0000 GS=0304 PS=00000246 V0 D0 I1 T0 S0 Z1 A0 P1 C0
C000:0E93 F3 REPZ
C000:0E94 AB STOSW
running
breakpoint hit: B800:0000 (write)
stopped (1476959 ops, 347538 cycles, 67 ms, 5187134 hz)
EAX=00000FDB EBX=00000FDB ECX=00000050 EDX=000003DA
ESP=000000CC EBP=FFFF00E2 ESI=00000000 EDI=00000002
SS=0030 DS=0000 ES=B800 FS=0000 GS=0304 PS=00000246 V0 D0 I1 T0 S0 Z1 A0 P1 C0
C000:18D7 FB STI
running
write breakpoint added to memory block 000B8000
write breakpoint added to memory block 000B8000
breakpoint hit: B800:0000 (write)
stopped (2824784 ops, 4644466 cycles, 528 ms, 8796337 hz)
EAX=00000720 EBX=00000720 ECX=00003FFF EDX=0000B800
ESP=000000C8 EBP=FFFF2230 ESI=00000CBA EDI=00000002
SS=0030 DS=0000 ES=B800 FS=0000 GS=0304 PS=00000246 V0 D0 I1 T0 S0 Z1 A0 P1 C0
C000:0E93 F3 REPZ
C000:0E94 AB STOSW
running
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x8C) @F000:D05C
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x1A) @F000:BC79
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x50) @F000:AA76
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x51) @F000:AA7F
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x52) @F000:AA9C
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x1B) @F000:BC80
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x1C) @F000:BC87
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x90) @F000:CC53
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x91) @F000:CC85
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x1D) @F000:BC8E
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x93) @F000:CC8A
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x94) @F000:CD06
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x95) @F000:CD3C
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x96) @F000:CD6A
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x2D) @F000:BC95
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x0D) @F000:E107
bus.outPort(0x004B,unknown,0x12) @F000:E10B
bus.outPort(0x0048,unknown,0x22) @F000:E112
bus.outPort(0x004B,unknown,0x00) @F000:E139
bus.inPort(0x0048,unknown) @F000:E13B
bus.inPort(0x0048,unknown) @F000:E13E
bus.outPort(0x004B,unknown,0x12) @F000:E11A
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x0E) @F000:E11E
bus.outPort(0x004B,unknown,0x92) @F000:E122
bus.outPort(0x004A,unknown,0x22) @F000:E129
bus.outPort(0x004B,unknown,0x80) @F000:E139
bus.inPort(0x004A,unknown) @F000:E13B
bus.inPort(0x004A,unknown) @F000:E13E
bus.outPort(0x004B,unknown,0x92) @F000:E131
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x1E) @F000:BC9C
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x80) @F000:CFDF
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x81) @F000:CFF7
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x82) @F000:D011
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x84) @F000:D02D
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x1F) @F000:BCA3
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x75) @F000:F74D
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x76) @F000:F761
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x77) @0030:F772
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x78) @0030:F790
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x00) @F000:F907
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x07) @F000:F986
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x08) @F000:F9AA
notice: PIC0(0x20): unsupported OCW2 automatic EOI command: 0x00
stopped (19729382 ops, 81457037 cycles, 7165 ms, 11368742 hz)
EAX=0000F000 EBX=00000006 ECX=00000008 EDX=00000020
ESP=00000000 EBP=00000000 ESI=0000F8E7 EDI=00000000
SS=0000 DS=F000 ES=0000 FS=0000 GS=0000 PS=00000046 V0 D0 I0 T0 S0 Z1 A0 P1 C0
F000:F9ED E6A0 OUT A0,AL
running
notice: PIC1(0xA0): unsupported OCW2 automatic EOI command: 0x00
stopped (19729383 ops, 5 cycles, 20 ms, 250 hz)
EAX=0000F000 EBX=00000006 ECX=00000008 EDX=00000020
ESP=00000000 EBP=00000000 ESI=0000F8E7 EDI=00000000
SS=0000 DS=F000 ES=0000 FS=0000 GS=0000 PS=00000046 V0 D0 I0 T0 S0 Z1 A0 P1 C0
F000:F9EF B009 MOV AL,09
We're back in the Compaq BIOS, the video card appears to be fully initialized now, so perhaps the next
write to video memory will be the first memory test results.
And in fact, it is. But the "bw b800:0" command doesn't work, because the memory test results are being
performed in protected-mode, and there is no segment 0xB800 mapped to video memory at that point.
So the write breakpoint must be specified as "bw %b8000" instead. Now we catch it:
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x09) @F000:F9F1
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x79) @F000:F7CD
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x7B) @F000:F814
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x20) @F000:BCAA
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x60) @F000:D6E6
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x61) @F000:D704
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x18) @0030:870A
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x18) @0030:8715
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x62) @0030:D719
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x63) @0030:D761
chipset.outPort(0x0084,DMA.SPARE0.PAGE,0x70) @0030:DB38
breakpoint hit: %000B8000 (write)
stopped (19736120 ops, 23810 cycles, 165 ms, 144303 hz)
EAX=00000000 EBX=0000000A ECX=0000000A EDX=00000730
ESP=000000D0 EBP=00000080 ESI=00000095 EDI=00008002
SS=0028[00000300,FFFF] DS=0018[0001C000,FFFF] ES=0040[000B0000,FFFF]
CS=0030[000F0000,FFFF] FS=0000[00000000,FFFF] GS=0304[00003040,FFFF]
LD=0000[00000000,0000] GD=[0001C000,005F] ID=[000FF821,0007] TR=0000 A20=ON
CR0=0000FFF1 CR2=00000000 CR3=00000000 PS=00000082 V0 D0 I0 T0 S1 Z0 A0 P0 C0
0030:80DA F3 REPZ
0030:80DB A5 MOVSW
x8509: Memory test of top 128Kb of top 16Mb?
xdb33:

View file

@ -540,24 +540,37 @@ ChipSet.IRQ = {
/*
* 8253 Programmable Interval Timer (PIT) I/O ports
*
* Although technically, a PIT provides 3 "counters" rather than 3 "timers", we have
* adopted IBM's TechRef nomenclature, which refers to the PIT's counters as TIMER0,
* TIMER1, and TIMER2. For machines with a second PIT (eg, the DeskPro 386), we refer
* to those additional counters as TIMER3, TIMER4, and TIMER5.
*
* In addition, if there's a need to refer to a specfic PIT, use PIT0 for the first PIT
* and PIT1 for the second. This mirrors how we refer to multiple DMA controllers
* (eg, DMA0 and DMA1) and multiple PICs (eg, PIC0 and PIC1).
*
* This differs from Compaq's nomenclature, which used "Timer 1" to refer to the first
* PIT, and "Timer 2" for the second PIT, and then referred to "Counter 0", "Counter 1",
* and "Counter 2" within each PIT.
*/
ChipSet.TIMER0 = {
INDEX: 0,
PORT: 0x40 // used for time-of-day (prior to MODEL_5170)
ChipSet.PIT0 = {
PORT: 0x40,
TIMER0: 0, // used for time-of-day (prior to MODEL_5170)
TIMER1: 1, // used for memory refresh
TIMER2: 2 // used for speaker tone generation
};
ChipSet.TIMER1 = {
INDEX: 1,
PORT: 0x41 // used for memory refresh
ChipSet.PIT1 = {
PORT: 0x48, // MODEL_DESKPRO386 only
TIMER3: 0, // used for fail-safe clock
TIMER4: 1, // N/A
TIMER5: 2 // used for refresher request extend/speed control
};
ChipSet.TIMER2 = {
INDEX: 2,
PORT: 0x42 // used for speaker tone generation
};
ChipSet.TIMER_CTRL = {
PORT: 0x43, // write-only control register (use the Read-Back command to get status)
ChipSet.PIT_CTRL = {
PORT1: 0x43, // write-only control register (use the Read-Back command to get status)
PORT2: 0x4B, // write-only control register (use the Read-Back command to get status)
BCD: 0x01,
MODE: 0x0E,
MODE0: 0x00, // interrupt on Terminal Count (TC)
@ -734,7 +747,7 @@ ChipSet.KBC = {
KBD_CLOCK: 0x01, // keyboard clock (input)
KBD_DATA: 0x02 // keyboard data (input)
},
RWREG: { // this.bPPIB (since CLK_TIMER2 and SPK_TIMER2 are in both PPI_B and KBC.RWREG)
RWREG: { // this.bPPIB (since CLK_TIMER2 and SPK_TIMER2 are in both PPI_B and RWREG)
PORT: 0x61,
CLK_TIMER2: 0x01, // set to enable clock to TIMER2 (R/W)
SPK_TIMER2: 0x02, // set to connect output of TIMER2 to speaker (R/W)
@ -1097,7 +1110,7 @@ ChipSet.prototype.reset = function(fHard)
this.updateSwitchDesc();
/*
* DMA Controller initialization
* DMA (Direct Memory Access) Controller initialization
*/
this.aDMACs = new Array(this.cDMACs);
for (i = 0; i < this.cDMACs; i++) {
@ -1105,7 +1118,7 @@ ChipSet.prototype.reset = function(fHard)
}
/*
* PIC initialization
* PIC (Programmable Interupt Controller) initialization
*/
this.aPICs = new Array(this.cPICs);
this.initPIC(ChipSet.PIC0.INDEX, ChipSet.PIC0.PORT_LO);
@ -1114,10 +1127,16 @@ ChipSet.prototype.reset = function(fHard)
}
/*
* Timer initialization
* PIT (Programmable Interval Timer) initialization
*
* Although the DeskPro 386 refers to the timers in the first PIT as "Timer 1, Counter 0",
* "Timer 1, Counter 1" and "Timer 1, Counter 2", we're sticking with IBM's nomenclature:
* TIMER0, TIMER1 and TIMER2. Which means that we refer to the "counters" in the second PIT
* as TIMER3, TIMER4 and TIMER5; that numbering also matches their indexes in the aTimers array.
*/
this.bTimerCtrl = null; // tracks writes to port 0x43
this.aTimers = new Array(3);
this.bPIT1Ctrl = null; // tracks writes to port 0x43
this.bPIT2Ctrl = null; // tracks writes to port 0x4B (MODEL_DESKPRO386 only)
this.aTimers = new Array(this.model == ChipSet.MODEL_DESKPRO386? 6 : 3);
for (i = 0; i < this.aTimers.length; i++) {
this.initTimer(i);
}
@ -1706,7 +1725,7 @@ ChipSet.prototype.save = function()
state.set(0, [this.sw1Init, this.sw2Init, this.sw1, this.sw2]);
state.set(1, [this.saveDMAControllers()]);
state.set(2, [this.savePICs()]);
state.set(3, [this.bTimerCtrl, this.saveTimers()]);
state.set(3, [this.bPIT1Ctrl, this.saveTimers(), this.bPIT2Ctrl]);
state.set(4, [this.bPPIA, this.bPPIB, this.bPPIC, this.bPPICtrl, this.bNMI]);
if (this.model >= ChipSet.MODEL_5170) {
state.set(5, [this.b8042Status, this.b8042InBuff, this.b8042CmdData,
@ -1745,7 +1764,8 @@ ChipSet.prototype.restore = function(data)
}
a = data[3];
this.bTimerCtrl = a[0];
this.bPIT1Ctrl = a[0];
this.bPIT2Ctrl = a[2];
for (i = 0; i < this.aTimers.length; i++) {
this.initTimer(i, a[1][i]);
}
@ -2358,11 +2378,12 @@ ChipSet.prototype.inDMAChannelAddr = function(iDMAC, iChannel, port, addrFrom)
}
controller.bIndex ^= 0x1;
/*
* Technically, aTimers[ChipSet.TIMER1.INDEX].fOut is what drives DMA requests for DMA channel 0 (ChipSet.DMA_REFRESH),
* Technically, aTimers[1].fOut is what drives DMA requests for DMA channel 0 (ChipSet.DMA_REFRESH),
* every 15us, once the BIOS has initialized the channel's "mode" with MODE_SINGLE, INCREMENT, AUTOINIT, and XFER_READ (0x58)
* and initialized TIMER1 appropriately.
*
* However, we don't need to be that particular. Simply simulate an ever-increasing address after every read of the full DMA channel 0 address.
* However, we don't need to be that particular. Simply simulate an ever-increasing address after every read of the full
* DMA channel 0 address.
*/
if (!iDMAC && iChannel == ChipSet.DMA_REFRESH && !controller.bIndex) {
channel.addrCurrent[0]++;
@ -2418,9 +2439,9 @@ ChipSet.prototype.inDMAChannelCount = function(iDMAC, iChannel, port, addrFrom)
}
controller.bIndex ^= 0x1;
/*
* Technically, aTimers[ChipSet.TIMER1.INDEX].fOut is what drives DMA requests for DMA channel 0 (ChipSet.DMA_REFRESH),
* every 15us, once the BIOS has initialized the channel's "mode" with MODE_SINGLE, INCREMENT, AUTOINIT, and XFER_READ (0x58)
* and initialized TIMER1 appropriately.
* Technically, aTimers[1].fOut is what drives DMA requests for DMA channel 0 (ChipSet.DMA_REFRESH),
* every 15us, once the BIOS has initialized the channel's "mode" with MODE_SINGLE, INCREMENT, AUTOINIT,
* and XFER_READ (0x58) and initialized TIMER1 appropriately.
*
* However, we don't need to be that particular. Simply simulate an ever-decreasing count after every read of the full DMA channel 0 count.
*/
@ -3122,7 +3143,6 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
*/
if (bOCW2 & ChipSet.PIC_LO.OCW2_SET_ROTAUTO) {
this.notice("PIC" + iPIC + '(' + str.toHexByte(pic.port) + "): unsupported OCW2 rotate command: " + str.toHexByte(bOut));
this.cpu.stopCPU();
}
}
else if (bOCW2 == ChipSet.PIC_LO.OCW2_SET_PRI) {
@ -3136,7 +3156,6 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
* TODO: Remaining commands to support: ChipSet.PIC_LO.OCW2_SET_ROTAUTO and ChipSet.PIC_LO.OCW2_CLR_ROTAUTO
*/
this.notice("PIC" + iPIC + '(' + str.toHexByte(pic.port) + "): unsupported OCW2 automatic EOI command: " + str.toHexByte(bOut));
this.cpu.stopCPU();
}
} else {
/*
@ -3147,7 +3166,6 @@ ChipSet.prototype.outPICLo = function(iPIC, bOut, addrFrom)
*/
if (bOut & (ChipSet.PIC_LO.OCW3_POLL_CMD | ChipSet.PIC_LO.OCW3_SMM_CMD)) {
this.notice("PIC" + iPIC + '(' + str.toHexByte(pic.port) + "): unsupported OCW3 command: " + str.toHexByte(bOut));
this.cpu.stopCPU();
}
pic.bOCW3 = bOut;
}
@ -3413,11 +3431,12 @@ ChipSet.prototype.getIRRVector = function(iPIC)
* inTimer(iTimer, addrFrom)
*
* @this {ChipSet}
* @param {number} iTimer (ports 0x40, 0x41, 0x42)
* @param {number} iTimer
* @param {number} port (0x40, 0x41, 0x42, etc)
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
* @return {number} simulated port value
*/
ChipSet.prototype.inTimer = function(iTimer, addrFrom)
ChipSet.prototype.inTimer = function(iTimer, port, addrFrom)
{
var b;
var timer = this.aTimers[iTimer];
@ -3428,13 +3447,13 @@ ChipSet.prototype.inTimer = function(iTimer, addrFrom)
this.updateTimer(iTimer);
b = timer.countCurrent[timer.countIndex++];
if (this.messageEnabled(Messages.TIMER | Messages.PORT)) {
this.printMessageIO(ChipSet.TIMER0.PORT + iTimer, null, addrFrom, "TIMER" + iTimer, b, true);
this.printMessageIO(port, null, addrFrom, "TIMER" + iTimer, b, true);
}
return b;
};
/**
* outTimer(iTimer, bOut, addrFrom)
* outTimer(iTimer, port, bOut, addrFrom)
*
* We now rely EXCLUSIVELY on setBurstCycles() to address situations where quick timer interrupt turn-around
* is expected; eg, by the ROM BIOS POST when it sets TIMER0 to a low test count (0x16); since we typically
@ -3446,14 +3465,15 @@ ChipSet.prototype.inTimer = function(iTimer, addrFrom)
* OK with that.
*
* @this {ChipSet}
* @param {number} iTimer (ports 0x40, 0x41, 0x42)
* @param {number} iTimer
* @param {number} port (0x40, 0x41, 0x42, etc)
* @param {number} bOut
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
*/
ChipSet.prototype.outTimer = function(iTimer, bOut, addrFrom)
ChipSet.prototype.outTimer = function(iTimer, port, bOut, addrFrom)
{
if (this.messageEnabled(Messages.TIMER | Messages.PORT)) {
this.printMessageIO(ChipSet.TIMER0.PORT + iTimer, bOut, addrFrom, "TIMER" + iTimer, null, true);
this.printMessageIO(port, bOut, addrFrom, "TIMER" + iTimer, null, true);
}
var timer = this.aTimers[iTimer];
if (timer.countIndex == timer.countBytes) this.resetTimerIndex(iTimer);
@ -3463,7 +3483,7 @@ ChipSet.prototype.outTimer = function(iTimer, bOut, addrFrom)
* In general, writing a new count to a timer that's already counting isn't supposed to affect the current
* count, with the notable exceptions of MODE0 and MODE4.
*/
if (!timer.fCounting || timer.mode == ChipSet.TIMER_CTRL.MODE0 || timer.mode == ChipSet.TIMER_CTRL.MODE4) {
if (!timer.fCounting || timer.mode == ChipSet.PIT_CTRL.MODE0 || timer.mode == ChipSet.PIT_CTRL.MODE4) {
timer.fLatched = false;
timer.countCurrent[0] = timer.countStart[0] = timer.countInit[0];
timer.countCurrent[1] = timer.countStart[1] = timer.countInit[1];
@ -3476,67 +3496,65 @@ ChipSet.prototype.outTimer = function(iTimer, bOut, addrFrom)
* on the original PC is that an interrupt is requested only when the corresponding "OUT" transitions from
* "low" to "high".
*/
timer.fOUT = (timer.mode != ChipSet.TIMER_CTRL.MODE0);
timer.fOUT = (timer.mode != ChipSet.PIT_CTRL.MODE0);
if (iTimer == ChipSet.TIMER0.INDEX) {
if (iTimer == ChipSet.PIT0.TIMER0) {
/*
* TODO: Determine if there are situations/modes where I should NOT automatically clear IRQ0 on behalf of TIMER0.
*/
this.clearIRR(ChipSet.IRQ.TIMER0);
var countInit = this.getTimerInit(ChipSet.TIMER0.INDEX);
var countInit = this.getTimerInit(ChipSet.PIT0.TIMER0);
var nCyclesRemain = (countInit * this.nTicksDivisor) | 0;
if (timer.mode == ChipSet.TIMER_CTRL.MODE3) nCyclesRemain >>= 1;
if (timer.mode == ChipSet.PIT_CTRL.MODE3) nCyclesRemain >>= 1;
this.cpu.setBurstCycles(nCyclesRemain);
}
}
if (iTimer == ChipSet.TIMER2.INDEX) {
this.setSpeaker();
}
if (iTimer == ChipSet.PIT0.TIMER2) this.setSpeaker();
}
};
/**
* inTimerCtrl(port, addrFrom)
* inPIT1Ctrl(port, addrFrom)
*
* @this {ChipSet}
* @param {number} port (0x43)
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
* @return {number|null} simulated port value
*/
ChipSet.prototype.inTimerCtrl = function(port, addrFrom)
ChipSet.prototype.inPIT1Ctrl = function(port, addrFrom)
{
this.printMessageIO(port, null, addrFrom, "TIMER_CTRL", null, Messages.TIMER);
if (DEBUG) this.printMessage("TIMER_CTRL: Read-Back command not supported (yet)", Messages.TIMER);
this.printMessageIO(port, null, addrFrom, "PIT1_CTRL", null, Messages.TIMER);
if (DEBUG) this.printMessage("PIT1_CTRL: Read-Back command not supported (yet)", Messages.TIMER);
return null;
};
/**
* outTimerCtrl(port, bOut, addrFrom)
* outPIT1Ctrl(port, bOut, addrFrom)
*
* @this {ChipSet}
* @param {number} port (0x43)
* @param {number} bOut
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
*/
ChipSet.prototype.outTimerCtrl = function(port, bOut, addrFrom)
ChipSet.prototype.outPIT1Ctrl = function(port, bOut, addrFrom)
{
this.bTimerCtrl = bOut;
this.printMessageIO(port, bOut, addrFrom, "TIMER_CTRL", null, Messages.TIMER);
this.bPIT1Ctrl = bOut;
this.printMessageIO(port, bOut, addrFrom, "PIT1_CTRL", null, Messages.TIMER);
/*
* Extract the SC (Select Counter) bits
*/
var iTimer = (bOut & ChipSet.TIMER_CTRL.SC) >> 6;
var iTimer = (bOut & ChipSet.PIT_CTRL.SC) >> 6;
if (iTimer == 0x3) {
if (DEBUG) this.printMessage("TIMER_CTRL: Read-Back command not supported (yet)", Messages.TIMER);
if (DEBUG) this.printMessage("PIT1_CTRL: Read-Back command not supported (yet)", Messages.TIMER);
return;
}
/*
* Extract the BCD, MODE, and RW bits, which we simply store as-is (see setTimerMode)
*/
var bcd = (bOut & ChipSet.TIMER_CTRL.BCD);
var mode = (bOut & ChipSet.TIMER_CTRL.MODE);
var rw = (bOut & ChipSet.TIMER_CTRL.RW);
var bcd = (bOut & ChipSet.PIT_CTRL.BCD);
var mode = (bOut & ChipSet.PIT_CTRL.MODE);
var rw = (bOut & ChipSet.PIT_CTRL.RW);
if (!rw) {
this.latchTimer(iTimer);
} else {
@ -3559,7 +3577,7 @@ ChipSet.prototype.outTimerCtrl = function(port, bOut, addrFrom)
*
* TODO: Determine if there are situations/modes where I should NOT automatically clear IRQ0 on behalf of TIMER0.
*/
if (iTimer == ChipSet.TIMER0.INDEX) this.clearIRR(ChipSet.IRQ.TIMER0);
if (iTimer == ChipSet.PIT0.TIMER0) this.clearIRR(ChipSet.IRQ.TIMER0);
/*
* Another TIMER0 HACK: The "CASSETTE DATA WRAP TEST" @F000:E51E occasionally reports an error when the second of
@ -3572,7 +3590,7 @@ ChipSet.prototype.outTimerCtrl = function(port, bOut, addrFrom)
* FWIW, I believe the cassette hardware was discontinued after MODEL_5150, and even if the test fails, it's non-fatal;
* the ROM BIOS displays an error (131) and moves on.
*/
if (iTimer == ChipSet.TIMER2.INDEX) {
if (iTimer == ChipSet.PIT0.TIMER2) {
var pic = this.aPICs[0];
if (pic.bIMR == 0xff && this.bPPIB == (ChipSet.PPI_B.CLK_TIMER2 | ChipSet.PPI_B.ENABLE_SW2 | ChipSet.PPI_B.CASS_MOTOR_OFF | ChipSet.PPI_B.CLK_KBD)) {
var timer = this.aTimers[0];
@ -3637,10 +3655,10 @@ ChipSet.prototype.getTimerCycleLimit = function(iTimer, nCycles)
this.assert(ticksElapsed >= 0);
var countStart = this.getTimerStart(iTimer);
var count = countStart - ticksElapsed;
if (timer.mode == ChipSet.TIMER_CTRL.MODE3) count -= ticksElapsed;
if (timer.mode == ChipSet.PIT_CTRL.MODE3) count -= ticksElapsed;
this.assert(count > 0);
var nCyclesRemain = (count * this.nTicksDivisor) | 0;
if (timer.mode == ChipSet.TIMER_CTRL.MODE3) nCyclesRemain >>= 1;
if (timer.mode == ChipSet.PIT_CTRL.MODE3) nCyclesRemain >>= 1;
if (nCycles > nCyclesRemain) nCycles = nCyclesRemain;
}
return nCycles;
@ -3709,8 +3727,8 @@ ChipSet.prototype.setTimerMode = function(iTimer, bcd, mode, rw)
ChipSet.prototype.resetTimerIndex = function(iTimer)
{
var timer = this.aTimers[iTimer];
timer.countIndex = (timer.rw == ChipSet.TIMER_CTRL.RW_MSB? 1 : 0);
timer.countBytes = (timer.rw == ChipSet.TIMER_CTRL.RW_BOTH? 2 : 1);
timer.countIndex = (timer.rw == ChipSet.PIT_CTRL.RW_MSB? 1 : 0);
timer.countBytes = (timer.rw == ChipSet.PIT_CTRL.RW_BOTH? 2 : 1);
};
/**
@ -3741,7 +3759,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
* Every timer's counting state is gated by its own fCounting flag; TIMER2 is further gated by PPI_B's
* CLK_TIMER2 bit.
*/
if (timer.fCounting && (iTimer != ChipSet.TIMER2.INDEX || (this.bPPIB & ChipSet.PPI_B.CLK_TIMER2))) {
if (timer.fCounting && (iTimer != ChipSet.PIT0.TIMER2 || (this.bPPIB & ChipSet.PPI_B.CLK_TIMER2))) {
/*
* We determine the current timer count based on how many instruction cycles have elapsed since we started
* the timer. Timers are supposed to be "ticking" at a rate of 1193181.8181 times per second, which is
@ -3800,7 +3818,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
* neither too slowly nor too quickly. As a result, I've had to add some corresponding trickery
* in outTimer() to force interrupt simulation immediately after a low initial count (0x16) has been set.
*/
if (timer.mode == ChipSet.TIMER_CTRL.MODE0) {
if (timer.mode == ChipSet.PIT_CTRL.MODE0) {
if (count <= 0) count = 0;
if (DEBUG && this.messageEnabled(Messages.TIMER)) {
this.printMessage("updateTimer(" + iTimer + "): MODE0 timer count=" + count, true);
@ -3832,7 +3850,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
* is "illegal", whatever that means.
*/
else
if (timer.mode == ChipSet.TIMER_CTRL.MODE2) {
if (timer.mode == ChipSet.PIT_CTRL.MODE2) {
timer.fOUT = (count != 1); // yes, this line does seem rather pointless....
if (count <= 0) {
count = countInit + count;
@ -3866,7 +3884,7 @@ ChipSet.prototype.updateTimer = function(iTimer, fCycleReset)
* to be "high" for (N + 1) / 2 ticks and "low" for (N - 1) / 2 ticks.
*/
else
if (timer.mode == ChipSet.TIMER_CTRL.MODE3) {
if (timer.mode == ChipSet.PIT_CTRL.MODE3) {
count -= ticksElapsed;
if (count <= 0) {
timer.fOUT = !timer.fOUT;
@ -4047,7 +4065,7 @@ ChipSet.prototype.inPPIC = function(port, addrFrom)
}
if (this.bPPIB & ChipSet.PPI_B.CLK_TIMER2) {
var timer = this.updateTimer(ChipSet.TIMER2.INDEX);
var timer = this.updateTimer(ChipSet.PIT0.TIMER2);
if (timer.fOUT) {
if (this.bPPIB & ChipSet.PPI_B.SPK_TIMER2)
b |= ChipSet.PPI_C.TIMER2_OUT;
@ -4857,7 +4875,7 @@ ChipSet.prototype.setSpeaker = function(fOn)
} else {
fOn = this.fSpeaker && this.cpu && this.cpu.isRunning();
}
var freq = Math.round(ChipSet.TIMER_TICKS_PER_SEC / this.getTimerInit(ChipSet.TIMER2.INDEX));
var freq = Math.round(ChipSet.TIMER_TICKS_PER_SEC / this.getTimerInit(ChipSet.PIT0.TIMER2));
/*
* Treat frequencies outside the normal hearing range (below 20hz or above 20Khz) as a clever attempt
* to turn sound off; we have to explicitly turn the sound off in those cases, to prevent the Audio API
@ -4970,10 +4988,10 @@ ChipSet.aPortInput = {
0x08: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAStatus(ChipSet.DMA0.INDEX, port, addrFrom); },
0x20: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICLo(ChipSet.PIC0.INDEX, addrFrom); },
0x21: /** @this {ChipSet} */ function(port, addrFrom) { return this.inPICHi(ChipSet.PIC0.INDEX, addrFrom); },
0x40: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER0.INDEX, addrFrom); },
0x41: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER1.INDEX, addrFrom); },
0x42: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.TIMER2.INDEX, addrFrom); },
0x43: ChipSet.prototype.inTimerCtrl,
0x40: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.PIT0.TIMER0, port, addrFrom); },
0x41: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.PIT0.TIMER1, port, addrFrom); },
0x42: /** @this {ChipSet} */ function(port, addrFrom) { return this.inTimer(ChipSet.PIT0.TIMER2, port, addrFrom); },
0x43: ChipSet.prototype.inPIT1Ctrl,
0x81: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageReg(ChipSet.DMA0.INDEX, 2, port, addrFrom); },
0x82: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageReg(ChipSet.DMA0.INDEX, 3, port, addrFrom); },
0x83: /** @this {ChipSet} */ function(port, addrFrom) { return this.inDMAPageReg(ChipSet.DMA0.INDEX, 1, port, addrFrom); },
@ -5038,10 +5056,10 @@ ChipSet.aPortOutput = {
0x0D: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAMasterClear(ChipSet.DMA0.INDEX, port, bOut, addrFrom); },
0x20: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICLo(ChipSet.PIC0.INDEX, bOut, addrFrom); },
0x21: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outPICHi(ChipSet.PIC0.INDEX, bOut, addrFrom); },
0x40: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER0.INDEX, bOut, addrFrom); },
0x41: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER1.INDEX, bOut, addrFrom); },
0x42: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.TIMER2.INDEX, bOut, addrFrom); },
0x43: ChipSet.prototype.outTimerCtrl,
0x40: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.PIT0.TIMER0, port, bOut, addrFrom); },
0x41: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.PIT0.TIMER1, port, bOut, addrFrom); },
0x42: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outTimer(ChipSet.PIT0.TIMER2, port, bOut, addrFrom); },
0x43: ChipSet.prototype.outPIT1Ctrl,
0x81: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageReg(ChipSet.DMA0.INDEX, 2, port, bOut, addrFrom); },
0x82: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageReg(ChipSet.DMA0.INDEX, 3, port, bOut, addrFrom); },
0x83: /** @this {ChipSet} */ function(port, bOut, addrFrom) { this.outDMAPageReg(ChipSet.DMA0.INDEX, 1, port, bOut, addrFrom); },

View file

@ -498,6 +498,18 @@ Memory.prototype = {
/**
* readNone(off)
*
* Previously, this always returned 0x00, but the initial memory probe by the Compaq DeskPro 386 ROM BIOS
* writes 0x0000 to the first word of every 64Kb block in the nearly 16Mb address space it supports, and so
* it would initially think that LOTS of RAM existed, only to be disappointed later when it performed a more
* exhaustive memory test, and generating error messages in the process.
*
* TODO: Determine if we should have separate readByteNone(), readShortNone() and readLongNone() functions
* to return 0xff, 0xffff and 0xffffffff|0, respectively. This seems sufficient, as it seems unlikely
* that a system would require nonexistent memory locations to have all bits set.
*
* Also, I'm reluctant to address that potential issue by simply returning -1, because to date, the Memory
* component has always provided return values that are properly masked, and some callers may depend on that.
*
* @this {Memory}
* @param {number} off
* @return {number}
@ -506,7 +518,7 @@ Memory.prototype = {
if (DEBUGGER && this.dbg.messageEnabled(Messages.MEM) /* && !off */) {
this.dbg.message("attempt to read invalid block %" + str.toHex(this.addr) + " from " + this.dbg.hexOffset(this.cpu.getIP(), this.cpu.getCS()));
}
return 0;
return 0xff;
},
/**
* writeNone(off, v)

View file

@ -211,7 +211,13 @@ RAM.prototype.reset = function()
if (MAXDEBUG) this.status("ROM BIOS memory test has been disabled");
this.bus.setShortDirect(ROM.BIOS.RESET_FLAG, ROM.BIOS.RESET_FLAG_WARMBOOT);
}
if (this.chipset) this.chipset.addCMOSMemory(this.addrRAM, this.sizeRAM);
/*
* Don't add the "ramCPQ" memory to the CMOS total, because addCMOSMemory() will add it to the extended
* memory total, which will just confuse the Compaq BIOS.
*/
if (!COMPAQ386 || this.idComponent != "ramCPQ") {
if (this.chipset) this.chipset.addCMOSMemory(this.addrRAM, this.sizeRAM);
}
} else {
Component.error("No RAM allocated");
}