Preparing web server for update to v1.15.4
This commit is contained in:
parent
0f06c3f039
commit
1d9a5ee0df
39 changed files with 7519 additions and 1387 deletions
|
|
@ -46,11 +46,13 @@ if (typeof module !== 'undefined') {
|
|||
*
|
||||
* The ChipSet component has the following component-specific (parmsChipSet) properties:
|
||||
*
|
||||
* model: "5150", "5160", "5170", etc (should correspond to a ChipSet.MODEL_* constant)
|
||||
* scaleTimers: true to divide timer cycle counts by the CPU's cycle multiplier (default is false)
|
||||
* sound: true to enable (experimental) sound support (default); false to disable
|
||||
* model: 5150, 5160 or 5170 (should correspond to a ChipSet.MODEL_* constant)
|
||||
* sw1: 8-character binary string representing the SW1 DIP switches (SW1[1-8])
|
||||
* sw2: 8-character binary string representing the SW2 DIP switches (SW2[1-8]) (MODEL_5150 only)
|
||||
* sound: true to enable (experimental) sound support (default); false to disable
|
||||
* scaleTimers: true to divide timer cycle counts by the CPU's cycle multiplier (default is false)
|
||||
* fdrives: 0-4 floppy drives (default is 2 if no sw1 value provided)
|
||||
* monitor: none|tv|color|mono (default is mono if no sw1 value provided)
|
||||
* rtcDate: optional RTC date to be used on resets; use the ISO 8601 format; eg: "2011-10-10T14:48:00"
|
||||
*
|
||||
* The conventions used for the sw1 and sw2 strings are that the left-most character represents DIP switch [1],
|
||||
|
|
@ -63,9 +65,9 @@ if (typeof module !== 'undefined') {
|
|||
*
|
||||
* SW1[1] (bit 0) "0xxxxxxx" (1): IPL, "1xxxxxxx" (0): No IPL
|
||||
* SW1[2] (bit 1) reserved
|
||||
* SW1[3,4] (bits 3-2) "xx11xxxx" (00): 16Kb, "xx10xxxx" (01): 32Kb, "xx01xxxx" (10): 48Kb, "xx00xxxx" (11): 64Kb
|
||||
* SW1[5,6] (bits 5-4) "xxxx11xx" (00): none, "xxxx10xx" (01): CGA40, "xxxx01xx" (10): CGA80, "xxxx00xx" (11): MDA80
|
||||
* SW1[7,8] (bits 7-6) "xxxxxx11" (00): 1 FD, "xxxxxx10" (01): 2 FD, "xxxxxx01" (10): 3 FD, "xxxxxx00" (11): 4 FD
|
||||
* SW1[3,4] (bits 3-2) "xx11xxxx" (00): 16Kb, "xx01xxxx" (01): 32Kb, "xx10xxxx" (10): 48Kb, "xx00xxxx" (11): 64Kb
|
||||
* SW1[5,6] (bits 5-4) "xxxx11xx" (00): none, "xxxx01xx" (01): tv, "xxxx10xx" (10): color, "xxxx00xx" (11): mono
|
||||
* SW1[7,8] (bits 7-6) "xxxxxx11" (00): 1 FD, "xxxxxx01" (01): 2 FD, "xxxxxx10" (10): 3 FD, "xxxxxx00" (11): 4 FD
|
||||
*
|
||||
* Note: FD refers to floppy drive, and IPL refers to an "Initial Program Load" floppy drive.
|
||||
*
|
||||
|
|
@ -149,14 +151,44 @@ function ChipSet(parmsChipSet)
|
|||
|
||||
this.model = parmsChipSet['model'];
|
||||
this.model = (this.model !== undefined? parseInt(this.model, 10) : ChipSet.MODEL_5150);
|
||||
|
||||
|
||||
/*
|
||||
* SW1 describes the number of floppy drives, the amount of base memory, the primary monitor type,
|
||||
* and (on the MODEL_5160) whether or not a coprocessor is installed. If no SW1 settings are provided,
|
||||
* we look for individual 'fdrives' and 'monitor' settings and build a default SW1 value.
|
||||
*
|
||||
* TODO: Get rid of reliance on SW1 for MODEL_5170 and later; omitting it now results in a BIOS warning:
|
||||
*
|
||||
* ' 162-System Options Not Set-(Run SETUP)'
|
||||
*
|
||||
* ' (RESUME = "F1" KEY)'
|
||||
*
|
||||
* The defaults below select max memory, monochrome monitor (EGA monitor for MODEL_5170), and two floppies.
|
||||
* Don't get too excited about "max memory" either: on a MODEL_5150, the max was 64Kb, and on a MODEL_5160,
|
||||
* the max was 256Kb. However, the RAM component is free to install as much base memory as it likes,
|
||||
* overriding the SW1 memory setting.
|
||||
*
|
||||
* Given that the ROM BIOS is hard-coded to load boot sectors @0000:7C00, the minimum amount of system RAM
|
||||
* required to boot is therefore 32Kb. Whether that's actually enough to run any or all versions of PC-DOS is
|
||||
* a separate question. FYI, with only 16Kb, the ROM BIOS will still try to boot, and fail miserably.
|
||||
*/
|
||||
this.sw1Init = this.parseSwitches(parmsChipSet['sw1'], ChipSet.PPI_SW.MEMORY.X4 | ChipSet.PPI_SW.MONITOR.MDA);
|
||||
|
||||
this.sw1Init = 0;
|
||||
var sw1 = parmsChipSet['sw1'];
|
||||
if (sw1) {
|
||||
this.sw1Init = this.parseSwitches(sw1, ChipSet.PPI_SW.MEMORY.X4 | ChipSet.PPI_SW.MONITOR.MONO);
|
||||
} else {
|
||||
var nDrives = parmsChipSet['fdrives'] || 2;
|
||||
if (nDrives) {
|
||||
this.sw1Init |= ChipSet.PPI_SW.FDRIVE.IPL;
|
||||
nDrives--;
|
||||
this.sw1Init |= ((nDrives & 0x3) << ChipSet.PPI_SW.FDRIVE.SHIFT);
|
||||
}
|
||||
var sMonitor = parmsChipSet['monitor'] || (this.model < ChipSet.MODEL_5170? "mono" : "ega");
|
||||
if (sMonitor && ChipSet.aMonitorSwitches[sMonitor] !== undefined) {
|
||||
this.sw1Init |= (ChipSet.aMonitorSwitches[sMonitor] << ChipSet.PPI_SW.MONITOR.SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SW2 describes the number of 32Kb blocks of I/O expansion RAM that's present in the system. The MODEL_5150 ROM BIOS
|
||||
* only checked/supported the first four switches, so the maximum amount of additional RAM specifiable was 15 * 32Kb,
|
||||
|
|
@ -168,11 +200,10 @@ function ChipSet(parmsChipSet)
|
|||
* supported on the motherboard) is the "size" parameter of the RAM component. NOTE: If you use the "size" parameter,
|
||||
* you will not be able to dynamically alter the memory configuration; the RAM component will ignore any changes to SW1.
|
||||
*/
|
||||
this.sw2Init = this.parseSwitches(parmsChipSet['sw2'], 0);
|
||||
this.sw2Init = this.parseSwitches(parmsChipSet['sw2'] || "11110000", 0);
|
||||
|
||||
/*
|
||||
* The SW1 memory switches specify a multiplier; the number of Kb that they multiply is model-dependent:
|
||||
* 16Kb on a MODEL_5150, 64Kb otherwise.
|
||||
* The SW1 memory setting is actually just a multiplier: it's multiplied by 16Kb on a MODEL_5150, 64Kb otherwise.
|
||||
*/
|
||||
this.kbSW = (this.model == ChipSet.MODEL_5150? 16 : 64);
|
||||
|
||||
|
|
@ -180,6 +211,7 @@ function ChipSet(parmsChipSet)
|
|||
if (this.model >= ChipSet.MODEL_5170) {
|
||||
this.cDMACs = this.cPICs = 2;
|
||||
}
|
||||
|
||||
this.fScaleTimers = parmsChipSet['scaleTimers'] || false;
|
||||
this.sRTCDate = parmsChipSet['rtcDate'];
|
||||
|
||||
|
|
@ -232,12 +264,24 @@ ChipSet.MODEL_5170 = 5170;
|
|||
*/
|
||||
ChipSet.MONITOR = {};
|
||||
ChipSet.MONITOR.NONE = 0;
|
||||
ChipSet.MONITOR.TV = 1; // TV (lower resolution; not currently supported)
|
||||
ChipSet.MONITOR.TV = 1; // Composite monitor (lower resolution; no support)
|
||||
ChipSet.MONITOR.COLOR = 2; // Color Display (5153)
|
||||
ChipSet.MONITOR.MONO = 3; // Monochrome Display (5151)
|
||||
ChipSet.MONITOR.EGACOLOR = 4; // Enhanced Color Display (5154) in High-Res Mode
|
||||
ChipSet.MONITOR.EGAEMULATION = 5; // Enhanced Color Display (5154) in Emulation Mode
|
||||
|
||||
/*
|
||||
* Lookup table for converting ChipSet "monitor" parameter into the corresponding SW1 switch bits
|
||||
* (they must be shifted left by ChipSet.PPI_SW.MONITOR.SHIFT before OR'ing them into sw1/sw1Init).
|
||||
*/
|
||||
ChipSet.aMonitorSwitches = {
|
||||
"none": 0x0,
|
||||
"tv": 0x1,
|
||||
"color":0x2,
|
||||
"mono": 0x3,
|
||||
"ega": 0x0
|
||||
};
|
||||
|
||||
/*
|
||||
* 8237A DMA Controller (DMAC) I/O ports
|
||||
*
|
||||
|
|
@ -385,6 +429,9 @@ ChipSet.PIC_HI.ICW4_MASTER = 0x04;
|
|||
ChipSet.PIC_HI.ICW4_BUFFERED = 0x08;
|
||||
ChipSet.PIC_HI.ICW4_FULLY_NESTED= 0x10;
|
||||
|
||||
/*
|
||||
* Definitions for Operation Command Words (OCW1, OCW2 and OCW3)
|
||||
*/
|
||||
ChipSet.PIC_HI.OCW1_IMR = 0xFF;
|
||||
|
||||
ChipSet.PIC_LO.OCW2 = 0x00; // bit 3 (PIC_LO.OCW3) and bit 4 (ChipSet.PIC_LO.ICW1) are clear in an OCW2 command byte
|
||||
|
|
@ -536,9 +583,9 @@ ChipSet.PPI_SW.MEMORY.X4 = 0x0C;
|
|||
ChipSet.PPI_SW.MEMORY.MASK = 0x0C;
|
||||
ChipSet.PPI_SW.MEMORY.SHIFT = 2;
|
||||
ChipSet.PPI_SW.MONITOR = {};
|
||||
ChipSet.PPI_SW.MONITOR.CGA40 = 0x10;
|
||||
ChipSet.PPI_SW.MONITOR.CGA80 = 0x20;
|
||||
ChipSet.PPI_SW.MONITOR.MDA = 0x30;
|
||||
ChipSet.PPI_SW.MONITOR.TV = 0x10;
|
||||
ChipSet.PPI_SW.MONITOR.COLOR = 0x20;
|
||||
ChipSet.PPI_SW.MONITOR.MONO = 0x30;
|
||||
ChipSet.PPI_SW.MONITOR.MASK = 0x30;
|
||||
ChipSet.PPI_SW.MONITOR.SHIFT = 4;
|
||||
ChipSet.PPI_SW.FDRIVE.ONE = 0x00; // 1 floppy drive attached (or 0 drives if PPI_SW.FDRIVE_IPL is not set -- MODEL_5150 only)
|
||||
|
|
@ -574,84 +621,85 @@ ChipSet.PPI_SW.FDRIVE.SHIFT = 6;
|
|||
* http://halicery.com/8042/8042_INTERN_TXT.htm
|
||||
* http://www.os2museum.com/wp/?p=589 ("IBM PC/AT 8042 Keyboard Controller Commands")
|
||||
*/
|
||||
ChipSet.KBC = {};
|
||||
ChipSet.KBC.DATA = { // this.b8042OutBuff (PPI_A on previous models, still referred to as "PORT A" by the MODEL_5170 BIOS)
|
||||
PORT: 0x60,
|
||||
SELF_TEST: { // result of ChipSet.KBC.CMD.SELF_TEST command (0xAA)
|
||||
OK: 0x55
|
||||
ChipSet.KBC = {
|
||||
DATA: { // this.b8042OutBuff (PPI_A on previous models, still referred to as "PORT A" by the MODEL_5170 BIOS)
|
||||
PORT: 0x60,
|
||||
CMD: { // this.b8042CmdData (KBD_DATA.CMD "data bytes" written to port 0x60, after writing a KBD_CMD byte to port 0x64)
|
||||
PC_COMPAT: 0x40, // generate IBM PC-compatible scan codes
|
||||
PC_MODE: 0x20,
|
||||
NO_CLOCK: 0x10, // disable keyboard by driving "clock" line low
|
||||
NO_INHIBIT: 0x08, // disable inhibit function
|
||||
SYS_FLAG: 0x04, // this value is propagated to ChipSet.KBC.STATUS.SYS_FLAG
|
||||
INT_ENABLE: 0x01 // generate an interrupt when the controller places data in the output buffer
|
||||
},
|
||||
SELF_TEST: { // result of ChipSet.KBC.CMD.SELF_TEST command (0xAA)
|
||||
OK: 0x55
|
||||
},
|
||||
INTF_TEST: { // result of ChipSet.KBC.CMD.INTF_TEST command (0xAB)
|
||||
OK: 0x00, // no error
|
||||
CLOCK_LO: 0x01, // keyboard clock line stuck low
|
||||
CLOCK_HI: 0x02, // keyboard clock line stuck high
|
||||
DATA_LO: 0x03, // keyboard data line stuck low
|
||||
DATA_HI: 0x04 // keyboard data line stuck high
|
||||
}
|
||||
},
|
||||
INTF_TEST: { // result of ChipSet.KBC.CMD.INTF_TEST command (0xAB)
|
||||
OK: 0x00, // no error
|
||||
CLOCK_LO: 0x01, // keyboard clock line stuck low
|
||||
CLOCK_HI: 0x02, // keyboard clock line stuck high
|
||||
DATA_LO: 0x03, // keyboard data line stuck low
|
||||
DATA_HI: 0x04 // keyboard data line stuck high
|
||||
INPORT: { // this.b8042InPort
|
||||
UNDEFINED: 0x0F, // undefined
|
||||
ENABLE_256KB: 0x10, // enable 2nd 256Kb of system board RAM
|
||||
MFG_OFF: 0x20, // manufacturing jumper not installed
|
||||
MONO: 0x40, // monochrome monitor is primary display
|
||||
KBD_ON: 0x80 // keyboard not inhibited
|
||||
},
|
||||
OUTPORT: { // this.b8042OutPort
|
||||
NO_RESET: 0x01, // set by default
|
||||
A20_ON: 0x02, // set by default
|
||||
OUTBUFF_FULL: 0x10, // output buffer full
|
||||
INBUFF_EMPTY: 0x20, // input buffer empty
|
||||
KBD_CLOCK: 0x40, // keyboard clock (output)
|
||||
KBD_DATA: 0x80 // keyboard data (output)
|
||||
},
|
||||
TESTPORT: { // generated "on the fly"
|
||||
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 KBD_RWREG)
|
||||
PORT: 0x61,
|
||||
CLK_TIMER2: 0x01, // set to enable clock to TIMER2
|
||||
SPK_TIMER2: 0x02, // set to connect output of TIMER2 to speaker
|
||||
DISABLE_CHK: 0x0C, // set these bits to disable I/O and RAM parity checks, clear them to enable checks
|
||||
REFRESH_BIT: 0x10, // indicates memory refresh
|
||||
IO_CHK: 0x40, // indicates I/O check
|
||||
PARITY_CHK: 0x80, // indicates RAM parity check
|
||||
PARITY_ERR: 0xC0
|
||||
},
|
||||
CMD: { // this.b8042InBuff (on write to port 0x64, interpret this as a CMD)
|
||||
PORT: 0x64,
|
||||
READ_CMD: 0x20,
|
||||
WRITE_CMD: 0x60, // followed by a command byte written to KBD_DATA.PORT (see KBD_DATA.CMD)
|
||||
SELF_TEST: 0xAA, // self-test (KBD_DATA.SELF_TEST_OK is placed in the output buffer if no errors)
|
||||
INTF_TEST: 0xAB, // interface test
|
||||
DIAG_DUMP: 0xAC, // diagnostic dump
|
||||
DISABLE_KBD: 0xAD, // disable keyboard
|
||||
ENABLE_KBD: 0xAE, // enable keyboard
|
||||
READ_INPORT: 0xC0, // read input port and place data in output buffer (use only if output buffer empty)
|
||||
READ_OUTPORT: 0xD0, // read output port and place data in output buffer (use only if output buffer empty)
|
||||
WRITE_OUTPORT: 0xD1, // next byte written to KBD_DATA.PORT (port 0x60) is placed in the output port (see KBD_DATA.OUTPUT)
|
||||
READ_TEST: 0xE0,
|
||||
PULSE_OUTPORT: 0xF0 // this is the 1st of 16 commands (0xF0-0xFF) that pulse bits 0-3 of the output port
|
||||
},
|
||||
STATUS: { // this.b8042Status (on read from port 0x64)
|
||||
PORT: 0x64,
|
||||
OUTBUFF_FULL: 0x01,
|
||||
INBUFF_FULL: 0x02, // set if the controller has received but not yet read data written to the input buffer (not normally set)
|
||||
SYS_FLAG: 0x04,
|
||||
CMD_FLAG: 0x08, // set on write to KBD_CMD (port 0x64), clear on write to KBD_DATA (port 0x60)
|
||||
NO_INHIBIT: 0x10,
|
||||
XMT_TIMEOUT: 0x20,
|
||||
RCV_TIMEOUT: 0x40,
|
||||
PARITY_ERR: 0x80, // last byte of data received had EVEN parity (ODD parity is normally expected)
|
||||
OUTBUFF_DELAY: 0x100
|
||||
}
|
||||
};
|
||||
ChipSet.KBC.DATA.CMD = { // this.b8042CmdData (KBD_DATA.CMD "data bytes" written to port 0x60, after writing a KBD_CMD byte to port 0x64)
|
||||
PC_COMPAT: 0x40, // generate IBM PC-compatible scan codes
|
||||
PC_MODE: 0x20,
|
||||
NO_CLOCK: 0x10, // disable keyboard by driving "clock" line low
|
||||
NO_INHIBIT: 0x08, // disable inhibit function
|
||||
SYS_FLAG: 0x04, // this value is propagated to ChipSet.KBC.STATUS.SYS_FLAG
|
||||
INT_ENABLE: 0x01 // generate an interrupt when the controller places data in the output buffer
|
||||
};
|
||||
ChipSet.KBC.INPORT = { // this.b8042InPort
|
||||
UNDEFINED: 0x0F, // undefined
|
||||
ENABLE_256KB: 0x10, // enable 2nd 256Kb of system board RAM
|
||||
MFG_OFF: 0x20, // manufacturing jumper not installed
|
||||
MONO: 0x40, // monochrome monitor is primary display
|
||||
KBD_ON: 0x80 // keyboard not inhibited
|
||||
};
|
||||
ChipSet.KBC.OUTPORT = { // this.b8042OutPort
|
||||
NO_RESET: 0x01, // set by default
|
||||
A20_ON: 0x02, // set by default
|
||||
OUTBUFF_FULL: 0x10, // output buffer full
|
||||
INBUFF_EMPTY: 0x20, // input buffer empty
|
||||
KBD_CLOCK: 0x40, // keyboard clock (output)
|
||||
KBD_DATA: 0x80 // keyboard data (output)
|
||||
};
|
||||
ChipSet.KBC.TESTPORT = { // generated "on the fly"
|
||||
KBD_CLOCK: 0x01, // keyboard clock (input)
|
||||
KBD_DATA: 0x02 // keyboard data (input)
|
||||
};
|
||||
ChipSet.KBC.RWREG = { // this.bPPIB (since CLK_TIMER2 and SPK_TIMER2 are in both PPI_B and KBD_RWREG)
|
||||
PORT: 0x61,
|
||||
CLK_TIMER2: 0x01, // set to enable clock to TIMER2
|
||||
SPK_TIMER2: 0x02, // set to connect output of TIMER2 to speaker
|
||||
DISABLE_CHK: 0x0C, // set these bits to disable I/O and RAM parity checks, clear them to enable checks
|
||||
REFRESH_BIT: 0x10, // indicates memory refresh
|
||||
IO_CHK: 0x40, // indicates I/O check
|
||||
PARITY_CHK: 0x80, // indicates RAM parity check
|
||||
PARITY_ERR: 0xC0
|
||||
};
|
||||
ChipSet.KBC.CMD = { // this.b8042InBuff (on write to port 0x64, interpret this as a CMD)
|
||||
PORT: 0x64,
|
||||
READ_CMD: 0x20,
|
||||
WRITE_CMD: 0x60, // followed by a command byte written to KBD_DATA.PORT (see KBD_DATA.CMD)
|
||||
SELF_TEST: 0xAA, // self-test (KBD_DATA.SELF_TEST_OK is placed in the output buffer if no errors)
|
||||
INTF_TEST: 0xAB, // interface test
|
||||
DIAG_DUMP: 0xAC, // diagnostic dump
|
||||
DISABLE_KBD: 0xAD, // disable keyboard
|
||||
ENABLE_KBD: 0xAE, // enable keyboard
|
||||
READ_INPORT: 0xC0, // read input port and place data in output buffer (use only if output buffer empty)
|
||||
READ_OUTPORT: 0xD0, // read output port and place data in output buffer (use only if output buffer empty)
|
||||
WRITE_OUTPORT: 0xD1, // next byte written to KBD_DATA.PORT (port 0x60) is placed in the output port (see KBD_DATA.OUTPUT)
|
||||
READ_TEST: 0xE0,
|
||||
PULSE_OUTPORT: 0xF0 // this is the 1st of 16 commands (0xF0-0xFF) that pulse bits 0-3 of the output port
|
||||
};
|
||||
ChipSet.KBC.STATUS = { // this.b8042Status (on read from port 0x64)
|
||||
PORT: 0x64,
|
||||
OUTBUFF_FULL: 0x01,
|
||||
INBUFF_FULL: 0x02, // set if the controller has received but not yet read data written to the input buffer (not normally set)
|
||||
SYS_FLAG: 0x04,
|
||||
CMD_FLAG: 0x08, // set on write to KBD_CMD (port 0x64), clear on write to KBD_DATA (port 0x60)
|
||||
NO_INHIBIT: 0x10,
|
||||
XMT_TIMEOUT: 0x20,
|
||||
RCV_TIMEOUT: 0x40,
|
||||
PARITY_ERR: 0x80, // last byte of data received had EVEN parity (ODD parity is normally expected)
|
||||
OUTBUFF_DELAY: 0x100
|
||||
};
|
||||
|
||||
/*
|
||||
* MC146818A RTC/CMOS Ports (MODEL_5170)
|
||||
|
|
@ -660,104 +708,104 @@ ChipSet.KBC.STATUS = { // this.b8042Status (on read from port 0x64)
|
|||
*
|
||||
* The ADDR port also controls NMI: write an address with bit 7 clear to enable NMI or set to disable NMI.
|
||||
*/
|
||||
ChipSet.CMOS = {};
|
||||
ChipSet.CMOS.ADDR = {}; // this.bCMOSAddr
|
||||
ChipSet.CMOS.ADDR.PORT = 0x70;
|
||||
ChipSet.CMOS.ADDR.RTC_SEC = 0x00;
|
||||
ChipSet.CMOS.ADDR.RTC_SEC_ALRM = 0x01;
|
||||
ChipSet.CMOS.ADDR.RTC_MIN = 0x02;
|
||||
ChipSet.CMOS.ADDR.RTC_MIN_ALRM = 0x03;
|
||||
ChipSet.CMOS.ADDR.RTC_HOUR = 0x04;
|
||||
ChipSet.CMOS.ADDR.RTC_HOUR_ALRM = 0x05;
|
||||
ChipSet.CMOS.ADDR.RTC_WEEK_DAY = 0x06;
|
||||
ChipSet.CMOS.ADDR.RTC_MONTH_DAY = 0x07;
|
||||
ChipSet.CMOS.ADDR.RTC_MONTH = 0x08;
|
||||
ChipSet.CMOS.ADDR.RTC_YEAR = 0x09;
|
||||
ChipSet.CMOS.ADDR.RTC_STATUSA = 0x0A;
|
||||
ChipSet.CMOS.ADDR.RTC_STATUSB = 0x0B;
|
||||
ChipSet.CMOS.ADDR.RTC_STATUSC = 0x0C;
|
||||
ChipSet.CMOS.ADDR.RTC_STATUSD = 0x0D;
|
||||
ChipSet.CMOS.ADDR.DIAG = 0x0E;
|
||||
ChipSet.CMOS.ADDR.SHUTDOWN = 0x0F;
|
||||
ChipSet.CMOS.ADDR.FDRIVE = 0x10;
|
||||
ChipSet.CMOS.ADDR.HDRIVE = 0x12;
|
||||
ChipSet.CMOS.ADDR.EQUIP = 0x14;
|
||||
ChipSet.CMOS.ADDR.BASEMEM_LO = 0x15;
|
||||
ChipSet.CMOS.ADDR.BASEMEM_HI = 0x16; // the BASEMEM values indicate the total Kb of base memory, up to 0x280 (640Kb)
|
||||
ChipSet.CMOS.ADDR.EXTMEM_LO = 0x17;
|
||||
ChipSet.CMOS.ADDR.EXTMEM_HI = 0x18; // the EXTMEM values indicate the total Kb of extended memory, up to 0x3C00 (15Mb)
|
||||
ChipSet.CMOS.ADDR.CHKSUM_HI = 0x2E;
|
||||
ChipSet.CMOS.ADDR.CHKSUM_LO = 0x2F; // CMOS bytes included in the checksum calculation: 0x10-0x2D
|
||||
ChipSet.CMOS.ADDR.EXTMEM2_LO = 0x30;
|
||||
ChipSet.CMOS.ADDR.EXTMEM2_HI = 0x31;
|
||||
ChipSet.CMOS.ADDR.CENTURY_DATE = 0x32; // BCD value for the current century (eg, 0x19 for 20th century, 0x20 for 21st century)
|
||||
ChipSet.CMOS.ADDR.BOOT_INFO = 0x33; // 0x80 if 128Kb expansion memory installed, 0x40 if Setup Utility wants an initial setup message
|
||||
ChipSet.CMOS.ADDR.MASK = 0x3F;
|
||||
ChipSet.CMOS.ADDR.TOTAL = 0x40;
|
||||
ChipSet.CMOS.ADDR.NMI_DISABLE = 0x80;
|
||||
|
||||
ChipSet.CMOS.DATA = {}; // this.abCMOSData
|
||||
ChipSet.CMOS.DATA.PORT = 0x71;
|
||||
|
||||
ChipSet.CMOS.STATUSA = {}; // abCMOSData[ChipSet.CMOS.ADDR.RTC_STATUSA]
|
||||
ChipSet.CMOS.STATUSA.UIP = 0x80; // bit 7: 1 indicates Update-In-Progress, 0 indicates date/time ready to read
|
||||
ChipSet.CMOS.STATUSA.DV = 0x70; // bits 6-4 (DV2-DV0) are programmed to 010 to select a 32.768Khz time base
|
||||
ChipSet.CMOS.STATUSA.RS = 0x0F; // bits 3-0 (RS3-RS0) are programmed to 0110 to select a 976.562us interrupt rate
|
||||
|
||||
ChipSet.CMOS.STATUSB = {}; // abCMOSData[ChipSet.CMOS.ADDR.RTC_STATUSB]
|
||||
ChipSet.CMOS.STATUSB.SET = 0x80; // bit 7: 1 to set any/all of the 14 time-bytes
|
||||
ChipSet.CMOS.STATUSB.PIE = 0x40; // bit 6: 1 for Periodic Interrupt Enable
|
||||
ChipSet.CMOS.STATUSB.AIE = 0x20; // bit 5: 1 for Alarm Interrupt Enable
|
||||
ChipSet.CMOS.STATUSB.UIE = 0x10; // bit 4: 1 for Update-Ended Interrupt Enable
|
||||
ChipSet.CMOS.STATUSB.SQWE = 0x08; // bit 3: 1 for Square Wave Enabled (as set by the STATUSA rate selection bits)
|
||||
ChipSet.CMOS.STATUSB.BINARY = 0x04; // bit 2: 1 for binary Date Mode, 0 for BCD Date Mode
|
||||
ChipSet.CMOS.STATUSB.HOUR24 = 0x02; // bit 1: 1 for 24-hour mode, 0 for 12-hour mode
|
||||
ChipSet.CMOS.STATUSB.DST = 0x01; // bit 0: 1 for Daylight Savings Time enabled
|
||||
|
||||
ChipSet.CMOS.STATUSC = {}; // abCMOSData[ChipSet.CMOS.ADDR.RTC_STATUSC] TODO: Does reading this register clear these interrupt conditions? (see F000:01C6 in the MODEL_5170 BIOS)
|
||||
ChipSet.CMOS.STATUSC.IRQF = 0x80; // bit 7
|
||||
ChipSet.CMOS.STATUSC.PF = 0x40; // bit 6: 1 indicates Periodic Interrupt
|
||||
ChipSet.CMOS.STATUSC.AF = 0x20; // bit 5: 1 indicates Alarm Interrupt
|
||||
ChipSet.CMOS.STATUSC.UF = 0x10; // bit 4: 1 indicates Update-Ended Interrupt
|
||||
ChipSet.CMOS.STATUSC.RESERVED = 0x0F;
|
||||
|
||||
ChipSet.CMOS.STATUSD = {}; // abCMOSData[ChipSet.CMOS.ADDR.RTC_STATUSD]
|
||||
ChipSet.CMOS.STATUSD.VRB = 0x80; // bit 7: 1 indicates Valid RAM Bit (0 implies power was and/or is lost)
|
||||
ChipSet.CMOS.STATUSD.RESERVED = 0x7F;
|
||||
|
||||
ChipSet.CMOS.DIAG = {}; // abCMOSData[ChipSet.CMOS.ADDR.DIAG]
|
||||
ChipSet.CMOS.DIAG.RTCFAIL = 0x80; // bit 7: 1 indicates RTC lost power
|
||||
ChipSet.CMOS.DIAG.CHKSUMFAIL = 0x40; // bit 6: 1 indicates bad CMOS checksum
|
||||
ChipSet.CMOS.DIAG.CONFIGFAIL = 0x20; // bit 5: 1 indicates bad CMOS configuration info
|
||||
ChipSet.CMOS.DIAG.MEMSIZEFAIL = 0x10; // bit 4: 1 indicates memory size miscompare
|
||||
ChipSet.CMOS.DIAG.HDRIVEFAIL = 0x08; // bit 3: 1 indicates hard drive controller or drive init failure
|
||||
ChipSet.CMOS.DIAG.TIMEFAIL = 0x04; // bit 2: 1 indicates time failure
|
||||
ChipSet.CMOS.DIAG.RESERVED = 0x03;
|
||||
|
||||
ChipSet.FDRIVE = { // abCMOSData[ChipSet.CMOS.ADDR.FDRIVE]
|
||||
D0_MASK: 0xF0, // Drive 0 type in high nibble
|
||||
D1_MASK: 0x0F, // Drive 1 type in lower nibble
|
||||
NONE: 0, // no drive
|
||||
DSDD: 1, // double-sided double-density drive (48 TPI, 40 tracks, 360Kb max)
|
||||
DSHD: 2 // double-sided high-density drive (96 TPI, 80 tracks, 1.2Mb max)
|
||||
};
|
||||
|
||||
ChipSet.CMOS.HDRIVE = { // abCMOSData[ChipSet.CMOS.ADDR.HDRIVE]
|
||||
D0_MASK: 0xF0, // Drive 0 type in high nibble
|
||||
D1_MASK: 0x0F // Drive 1 type in lower nibble
|
||||
ChipSet.CMOS = {
|
||||
ADDR: { // this.bCMOSAddr
|
||||
PORT: 0x70,
|
||||
RTC_SEC: 0x00,
|
||||
RTC_SEC_ALRM: 0x01,
|
||||
RTC_MIN: 0x02,
|
||||
RTC_MIN_ALRM: 0x03,
|
||||
RTC_HOUR: 0x04,
|
||||
RTC_HOUR_ALRM: 0x05,
|
||||
RTC_WEEK_DAY: 0x06,
|
||||
RTC_MONTH_DAY: 0x07,
|
||||
RTC_MONTH: 0x08,
|
||||
RTC_YEAR: 0x09,
|
||||
RTC_STATUSA: 0x0A,
|
||||
RTC_STATUSB: 0x0B,
|
||||
RTC_STATUSC: 0x0C,
|
||||
RTC_STATUSD: 0x0D,
|
||||
DIAG: 0x0E,
|
||||
SHUTDOWN: 0x0F,
|
||||
FDRIVE: 0x10,
|
||||
HDRIVE: 0x12,
|
||||
EQUIP: 0x14,
|
||||
BASEMEM_LO: 0x15,
|
||||
BASEMEM_HI: 0x16, // the BASEMEM values indicate the total Kb of base memory, up to 0x280 (640Kb)
|
||||
EXTMEM_LO: 0x17,
|
||||
EXTMEM_HI: 0x18, // the EXTMEM values indicate the total Kb of extended memory, up to 0x3C00 (15Mb)
|
||||
CHKSUM_HI: 0x2E,
|
||||
CHKSUM_LO: 0x2F, // CMOS bytes included in the checksum calculation: 0x10-0x2D
|
||||
EXTMEM2_LO: 0x30,
|
||||
EXTMEM2_HI: 0x31,
|
||||
CENTURY_DATE: 0x32, // BCD value for the current century (eg, 0x19 for 20th century, 0x20 for 21st century)
|
||||
BOOT_INFO: 0x33, // 0x80 if 128Kb expansion memory installed, 0x40 if Setup Utility wants an initial setup message
|
||||
MASK: 0x3F,
|
||||
TOTAL: 0x40,
|
||||
NMI_DISABLE: 0x80
|
||||
},
|
||||
DATA: { // this.abCMOSData
|
||||
PORT: 0x71
|
||||
},
|
||||
STATUSA: { // abCMOSData[ChipSet.CMOS.ADDR.RTC_STATUSA]
|
||||
UIP: 0x80, // bit 7: 1 indicates Update-In-Progress, 0 indicates date/time ready to read
|
||||
DV: 0x70, // bits 6-4 (DV2-DV0) are programmed to 010 to select a 32.768Khz time base
|
||||
RS: 0x0F // bits 3-0 (RS3-RS0) are programmed to 0110 to select a 976.562us interrupt rate
|
||||
},
|
||||
STATUSB: { // abCMOSData[ChipSet.CMOS.ADDR.RTC_STATUSB]
|
||||
SET: 0x80, // bit 7: 1 to set any/all of the 14 time-bytes
|
||||
PIE: 0x40, // bit 6: 1 for Periodic Interrupt Enable
|
||||
AIE: 0x20, // bit 5: 1 for Alarm Interrupt Enable
|
||||
UIE: 0x10, // bit 4: 1 for Update-Ended Interrupt Enable
|
||||
SQWE: 0x08, // bit 3: 1 for Square Wave Enabled (as set by the STATUSA rate selection bits)
|
||||
BINARY: 0x04, // bit 2: 1 for binary Date Mode, 0 for BCD Date Mode
|
||||
HOUR24: 0x02, // bit 1: 1 for 24-hour mode, 0 for 12-hour mode
|
||||
DST: 0x01 // bit 0: 1 for Daylight Savings Time enabled
|
||||
},
|
||||
STATUSC: { // abCMOSData[ChipSet.CMOS.ADDR.RTC_STATUSC] TODO: Does reading this register clear these interrupt conditions? (see F000:01C6 in the MODEL_5170 BIOS)
|
||||
IRQF: 0x80, // bit 7
|
||||
PF: 0x40, // bit 6: 1 indicates Periodic Interrupt
|
||||
AF: 0x20, // bit 5: 1 indicates Alarm Interrupt
|
||||
UF: 0x10, // bit 4: 1 indicates Update-Ended Interrupt
|
||||
RESERVED: 0x0F
|
||||
},
|
||||
STATUSD: { // abCMOSData[ChipSet.CMOS.ADDR.RTC_STATUSD]
|
||||
VRB: 0x80, // bit 7: 1 indicates Valid RAM Bit (0 implies power was and/or is lost)
|
||||
RESERVED: 0x7F
|
||||
},
|
||||
DIAG: { // abCMOSData[ChipSet.CMOS.ADDR.DIAG]
|
||||
RTCFAIL: 0x80, // bit 7: 1 indicates RTC lost power
|
||||
CHKSUMFAIL: 0x40, // bit 6: 1 indicates bad CMOS checksum
|
||||
CONFIGFAIL: 0x20, // bit 5: 1 indicates bad CMOS configuration info
|
||||
MEMSIZEFAIL: 0x10, // bit 4: 1 indicates memory size miscompare
|
||||
HDRIVEFAIL: 0x08, // bit 3: 1 indicates hard drive controller or drive init failure
|
||||
TIMEFAIL: 0x04, // bit 2: 1 indicates time failure
|
||||
RESERVED: 0x03
|
||||
},
|
||||
FDRIVE: { // abCMOSData[ChipSet.CMOS.ADDR.FDRIVE]
|
||||
D0_MASK: 0xF0, // Drive 0 type in high nibble
|
||||
D1_MASK: 0x0F, // Drive 1 type in lower nibble
|
||||
NONE: 0, // no drive
|
||||
DSDD: 1, // double-sided double-density drive (48 TPI, 40 tracks, 360Kb max)
|
||||
DSHD: 2 // double-sided high-density drive (96 TPI, 80 tracks, 1.2Mb max)
|
||||
},
|
||||
/*
|
||||
* HDRIVE types are defined by table in the HDC component, which uses setCMOSDriveType() to update the CMOS
|
||||
*/
|
||||
HDRIVE: { // abCMOSData[ChipSet.CMOS.ADDR.HDRIVE]
|
||||
D0_MASK: 0xF0, // Drive 0 type in high nibble
|
||||
D1_MASK: 0x0F // Drive 1 type in lower nibble
|
||||
},
|
||||
/*
|
||||
* The CMOS equipment flags use the same format as the older PPI equipment flags
|
||||
*/
|
||||
EQUIP: { // abCMOSData[ChipSet.CMOS.ADDR.EQUIP]
|
||||
MONITOR: ChipSet.PPI_SW.MONITOR, // PPI_SW.MONITOR.MASK == 0x30
|
||||
COPROC: ChipSet.PPI_SW.COPROC, // PPI_SW.COPROC == 0x02
|
||||
FDRIVE: ChipSet.PPI_SW.FDRIVE // PPI_SW.FDRIVE.IPL == 0x01 and PPI_SW.FDRIVE.MASK = 0xC0
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* The CMOS equipment flags use the same format as the older PPI equipment flags
|
||||
*/
|
||||
ChipSet.CMOS.EQUIP = {}; // abCMOSData[ChipSet.CMOS.ADDR.EQUIP]
|
||||
ChipSet.CMOS.EQUIP.MONITOR = ChipSet.PPI_SW.MONITOR; // PPI_SW.MONITOR.MASK == 0x30
|
||||
ChipSet.CMOS.EQUIP.COPROC = ChipSet.PPI_SW.COPROC; // PPI_SW.COPROC == 0x02
|
||||
ChipSet.CMOS.EQUIP.FDRIVE = ChipSet.PPI_SW.FDRIVE; // PPI_SW.FDRIVE.IPL == 0x01 and PPI_SW.FDRIVE.MASK = 0xC0
|
||||
|
||||
/*
|
||||
* Manufacturing Test Ports (MODEL_5170)
|
||||
*
|
||||
|
|
@ -772,29 +820,33 @@ ChipSet.CMOS.EQUIP.FDRIVE = ChipSet.PPI_SW.FDRIVE; // PPI_SW.FDRIVE
|
|||
* with manufacturing test ("MFG_TST") code which, if enabled, writes to other DMA page registers,
|
||||
* perhaps treating them as scratch registers.
|
||||
*/
|
||||
ChipSet.MFG = {}; // this.bMFGData
|
||||
ChipSet.MFG.PORT = 0x80;
|
||||
ChipSet.MFG = { // this.bMFGData
|
||||
PORT: 0x80
|
||||
};
|
||||
|
||||
/*
|
||||
* NMI Mask Register (MODEL_5150 and MODEL_5160 only)
|
||||
*/
|
||||
ChipSet.NMI = {}; // this.bNMI
|
||||
ChipSet.NMI.PORT = 0xA0;
|
||||
ChipSet.NMI.ENABLE = 0x80;
|
||||
ChipSet.NMI.DISABLE = 0x00;
|
||||
ChipSet.NMI = { // this.bNMI
|
||||
PORT: 0xA0,
|
||||
ENABLE: 0x80,
|
||||
DISABLE: 0x00
|
||||
};
|
||||
|
||||
/*
|
||||
* Coprocessor Control Registers (MODEL_5170)
|
||||
*/
|
||||
ChipSet.COPROC = {}; // TODO: Define a variable for this
|
||||
ChipSet.COPROC.PORT_CLEAR = 0xF0; // clear the coprocessor's "busy" state
|
||||
ChipSet.COPROC.PORT_RESET = 0xF1; // reset the coprocessor
|
||||
ChipSet.COPROC = { // TODO: Define a variable for this
|
||||
PORT_CLEAR: 0xF0, // clear the coprocessor's "busy" state
|
||||
PORT_RESET: 0xF1 // reset the coprocessor
|
||||
};
|
||||
|
||||
/*
|
||||
* ChipSet-related BIOS interrupts, functions, and other parameters
|
||||
*/
|
||||
ChipSet.BIOS = {};
|
||||
ChipSet.BIOS.RTC = 0x1A;
|
||||
ChipSet.BIOS = {
|
||||
RTC_INT: 0x1A
|
||||
};
|
||||
|
||||
/**
|
||||
* @this {ChipSet}
|
||||
|
|
@ -883,7 +935,7 @@ ChipSet.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
chipset.dumpCMOS();
|
||||
});
|
||||
}
|
||||
cpu.addInterruptNotify(ChipSet.BIOS.RTC, this, this.intBIOSRTC);
|
||||
cpu.addInterruptNotify(ChipSet.BIOS.RTC_INT, this, this.intBIOSRTC);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -897,8 +949,12 @@ ChipSet.prototype.initBus = function(cmp, bus, cpu, dbg)
|
|||
*/
|
||||
ChipSet.prototype.powerUp = function(data, fRepower)
|
||||
{
|
||||
if (!fRepower && data) {
|
||||
if (!this.restore(data)) return false;
|
||||
if (!fRepower) {
|
||||
if (!data) {
|
||||
this.reset();
|
||||
} else {
|
||||
if (!this.restore(data)) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
|
@ -923,8 +979,8 @@ ChipSet.prototype.powerDown = function(fSave)
|
|||
ChipSet.prototype.reset = function()
|
||||
{
|
||||
/*
|
||||
* We propagate the sw?Init values to sw? at reset; the user only gets
|
||||
* to tweak sw?Init, which we don't want to take effect until the next reset.
|
||||
* We propagate the sw1Init/sw2Init values to sw1/sw2 at reset; the user is only
|
||||
* allowed to tweak sw1Init/sw2Init, which doesn't take effect until the next reset.
|
||||
*/
|
||||
var i;
|
||||
this.sw1 = this.sw1Init;
|
||||
|
|
@ -963,7 +1019,7 @@ ChipSet.prototype.reset = function()
|
|||
this.bNMI = ChipSet.NMI.DISABLE;// tracks writes to the NMI Mask Register
|
||||
|
||||
/*
|
||||
* State introduced by the MODEL_5170
|
||||
* ChipSet state introduced by the MODEL_5170
|
||||
*/
|
||||
if (this.model >= ChipSet.MODEL_5170) {
|
||||
/*
|
||||
|
|
@ -988,17 +1044,25 @@ ChipSet.prototype.reset = function()
|
|||
if (this.getSWVideoMonitor() == ChipSet.MONITOR.MONO) this.b8042InPort |= ChipSet.KBC.INPORT.MONO;
|
||||
|
||||
this.b8042OutPort = ChipSet.KBC.OUTPORT.NO_RESET | ChipSet.KBC.OUTPORT.A20_ON;
|
||||
this.bCMOSAddr = 0; // NMI is enabled, since the ChipSet.CMOS.ADDR.NMI_DISABLE bit is not set in bCMOSAddr
|
||||
this.abCMOSData = new Array(ChipSet.CMOS.ADDR.TOTAL);
|
||||
this.initRTCDate(this.sRTCDate);
|
||||
this.initCMOSData();
|
||||
|
||||
/*
|
||||
* TODO: Data below here has not yet been added to the save/restore state; when we're done adding new data,
|
||||
* make sure it all gets added.
|
||||
*/
|
||||
|
||||
this.bMFGData = 0;
|
||||
this.abDMAPageSpare = new Array(7);
|
||||
|
||||
this.bCMOSAddr = 0; // NMI is enabled, since the ChipSet.CMOS.ADDR.NMI_DISABLE bit is not set in bCMOSAddr
|
||||
|
||||
/*
|
||||
* Now that we call reset() from the ChipSet constructor, enabling other components can to update
|
||||
* their CMOS information, we must not allow a reset() from powerUp() to toss that information, so
|
||||
* we allocate abCMOSData only if it hasn't already been allocated.
|
||||
*/
|
||||
if (!this.abCMOSData) this.abCMOSData = new Array(ChipSet.CMOS.ADDR.TOTAL);
|
||||
this.initRTCDate(this.sRTCDate);
|
||||
|
||||
/*
|
||||
* initCMOSData() will initialize a variety of "legacy" CMOS bytes, but it will NOT overwrite any memory
|
||||
* size or hard drive type information that might have been set, via addCMOSMemory() or setCMOSDriveType().
|
||||
*/
|
||||
this.initCMOSData();
|
||||
}
|
||||
|
||||
if (DEBUGGER && MAXDEBUG) {
|
||||
|
|
@ -1042,6 +1106,25 @@ ChipSet.prototype.initRTCDate = function(sDate)
|
|||
*/
|
||||
var date = sDate? new Date(sDate) : new Date();
|
||||
|
||||
/*
|
||||
* Example of a valid Date string:
|
||||
*
|
||||
* 2014-10-01T08:00:00-0700
|
||||
*
|
||||
* Example of an INVALID Date string:
|
||||
*
|
||||
* 2014-10-01T08:00:00PST
|
||||
*
|
||||
* In the second example, the Date object is invalid, but it wasn't obvious (to me) how to detect that.
|
||||
* So here's a test from StackOverflow (http://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript).
|
||||
*/
|
||||
if (Object.prototype.toString.call(date) !== "[object Date]" || isNaN(date.getTime())) {
|
||||
date = new Date();
|
||||
this.println("CMOS date invalid (" + sDate + "), using " + date);
|
||||
} else if (sDate) {
|
||||
this.println("CMOS date: " + date);
|
||||
}
|
||||
|
||||
this.abCMOSData[ChipSet.CMOS.ADDR.RTC_SEC] = date.getSeconds();
|
||||
this.abCMOSData[ChipSet.CMOS.ADDR.RTC_SEC_ALRM] = 0;
|
||||
this.abCMOSData[ChipSet.CMOS.ADDR.RTC_MIN] = date.getMinutes();
|
||||
|
|
@ -1171,7 +1254,7 @@ ChipSet.prototype.updateRTCDate = function()
|
|||
var nCyclesUpdate = this.cpu.getCycles(this.fScaleTimers);
|
||||
|
||||
/*
|
||||
* If nCyclesCMOSLastUpdate hasn't been properly set yet (ie, if this is our first updateRTCDate() call),
|
||||
* If nCyclesCMOSLastUpdate hasn't been set yet (ie, if this is our first updateRTCDate() call),
|
||||
* then do nothing except initialize nCyclesCMOSLastUpdate.
|
||||
*/
|
||||
if (this.nCyclesCMOSLastUpdate >= 0) {
|
||||
|
|
@ -1224,36 +1307,20 @@ ChipSet.prototype.updateRTCDate = function()
|
|||
ChipSet.prototype.initCMOSData = function()
|
||||
{
|
||||
/*
|
||||
* Make sure all the "checksummed" CMOS bytes get initialized (not just the handful we set below) to ensure
|
||||
* Make sure all the "checksummed" CMOS bytes are initialized (not just the handful we set below) to ensure
|
||||
* that the checksum will be valid.
|
||||
*/
|
||||
for (var iCMOS = ChipSet.CMOS.ADDR.DIAG; iCMOS < ChipSet.CMOS.ADDR.CHKSUM_HI; iCMOS++) {
|
||||
this.abCMOSData[iCMOS] = 0;
|
||||
if (this.abCMOSData[iCMOS] === undefined) this.abCMOSData[iCMOS] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We propagate all compatible "legacy" SW1 bits to the CMOS_EQUIP byte using the old SW masks, but any further
|
||||
* access to CMOS_ADDR.EQUIP should use the new CMOS_EQUIP flags (eg, CMOS_EQUIP.COPROC, CMOS_EQUIP.MONITOR.CGA80, etc).
|
||||
*
|
||||
* TODO: Consider more generic ChipSet parameters to specify equipment settings, so that newer models like MODEL_5170
|
||||
* don't have to rely on these legacy switch settings. In fact, switch settings should NEVER be required; we should be
|
||||
* setting defaults to automatically match the rest of the machine's hardware specification. However, that's probably
|
||||
* incomplete; for example, does the FDC component have a way of specifying the number of drives, and do we honor that?
|
||||
* I think not....
|
||||
*/
|
||||
this.abCMOSData[ChipSet.CMOS.ADDR.EQUIP] = this.sw1 & (ChipSet.PPI_SW.MONITOR.MASK | ChipSet.PPI_SW.COPROC | ChipSet.PPI_SW.FDRIVE.IPL | ChipSet.PPI_SW.FDRIVE.MASK);
|
||||
|
||||
this.abCMOSData[ChipSet.CMOS.ADDR.FDRIVE] = (this.getSWFloppyDriveType(0) << 4) | this.getSWFloppyDriveType(1);
|
||||
|
||||
/*
|
||||
* We allow both memory totals to start at zero now, and rely on the RAM component to call addCMOSMemory()
|
||||
* to update the total(s) as appropriate.
|
||||
*
|
||||
var wBaseMemKb = this.getSWMemorySize();
|
||||
this.abCMOSData[ChipSet.CMOS.ADDR.BASEMEM_LO] = wBaseMemKb & 0xff;
|
||||
this.abCMOSData[ChipSet.CMOS.ADDR.BASEMEM_HI] = wBaseMemKb >> 8;
|
||||
*/
|
||||
|
||||
/*
|
||||
* The final step is calculating the CMOS checksum, which we then store into the CMOS as a courtesy, so that the
|
||||
* user doesn't get unnecessary CMOS errors.
|
||||
|
|
@ -1285,7 +1352,7 @@ ChipSet.prototype.setCMOSByte = function(iCMOS, b)
|
|||
/**
|
||||
* addCMOSMemory(addr, size)
|
||||
*
|
||||
* This is ONLY for use by the RAM component, to dynamically update the CMOS memory configuration.
|
||||
* For use by the RAM component, to dynamically update the CMOS memory configuration.
|
||||
*
|
||||
* @this {ChipSet}
|
||||
* @param {number} addr (if 0, BASEMEM_LO/BASEMEM_HI is updated; if >= 0x100000, then EXTMEM_LO/EXTMEM_HI is updated)
|
||||
|
|
@ -1309,7 +1376,7 @@ ChipSet.prototype.addCMOSMemory = function(addr, size)
|
|||
/**
|
||||
* setCMOSDriveType(iDrive, bType)
|
||||
*
|
||||
* This is ONLY for use by the HDC component, to update the CMOS drive configuration to match HDC's internal configuration.
|
||||
* For use by the HDC component, to update the CMOS drive configuration to match HDC's internal configuration.
|
||||
*
|
||||
* TODO: Extend this to support FDC drive updates, so that FDC can eventually specify diskette drive types
|
||||
* (ie, DSDD or DSHD) in the same way that HDC does; currently, MODEL_5170 diskette drives always default to DSHD
|
||||
|
|
@ -1376,7 +1443,7 @@ ChipSet.prototype.save = function()
|
|||
if (this.model >= ChipSet.MODEL_5170) {
|
||||
state.set(5, [this.b8042Status, this.b8042InBuff, this.b8042CmdData,
|
||||
this.b8042OutBuff, this.b8042InPort, this.b8042OutPort]);
|
||||
state.set(6, [this.bCMOSAddr, this.abCMOSData, this.nCyclesCMOSLastUpdate]);
|
||||
state.set(6, [this.bMFGData, this.abDMAPageSpare, this.bCMOSAddr, this.abCMOSData, this.nCyclesCMOSLastUpdate]);
|
||||
}
|
||||
return state.data();
|
||||
};
|
||||
|
|
@ -1439,9 +1506,11 @@ ChipSet.prototype.restore = function(data)
|
|||
a = data[6];
|
||||
if (a) {
|
||||
Component.assert(this.model >= ChipSet.MODEL_5170);
|
||||
this.bCMOSAddr = a[0];
|
||||
this.abCMOSData = a[1];
|
||||
this.nCyclesCMOSLastUpdate = a[2];
|
||||
this.bMFGData = a[0];
|
||||
this.abDMAPageSpare = a[1];
|
||||
this.bCMOSAddr = a[2];
|
||||
this.abCMOSData = a[3];
|
||||
this.nCyclesCMOSLastUpdate = a[4];
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
|
@ -1914,13 +1983,10 @@ ChipSet.prototype.dumpCMOS = function()
|
|||
{
|
||||
if (DEBUGGER) {
|
||||
var sDump = "";
|
||||
for (var p in ChipSet.CMOS.ADDR) {
|
||||
var iCMOS = ChipSet.CMOS.ADDR[p];
|
||||
if (iCMOS >= 0 && iCMOS < ChipSet.CMOS.ADDR.MASK) {
|
||||
var b = (iCMOS <= ChipSet.CMOS.ADDR.RTC_STATUSD? this.getRTCByte(iCMOS) : this.abCMOSData[iCMOS]);
|
||||
if (sDump) sDump += '\n';
|
||||
sDump += str.pad(p + "(" + str.toHexByte(iCMOS) + "):", 19) + str.toHexByte(b);
|
||||
}
|
||||
for (var iCMOS = 0; iCMOS < ChipSet.CMOS.ADDR.TOTAL; iCMOS++) {
|
||||
var b = (iCMOS <= ChipSet.CMOS.ADDR.RTC_STATUSD? this.getRTCByte(iCMOS) : this.abCMOSData[iCMOS]);
|
||||
if (sDump) sDump += '\n';
|
||||
sDump += "CMOS[0x" + str.toHexByte(iCMOS) + "]: 0x" + str.toHexByte(b);
|
||||
}
|
||||
this.dbg.message(sDump);
|
||||
}
|
||||
|
|
@ -2137,8 +2203,8 @@ ChipSet.prototype.outDMAMode = function(iDMAC, port, bOut, addrFrom)
|
|||
* @param {number} bOut
|
||||
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
|
||||
*
|
||||
* Any write to this port simply resets the controller's "first/last flip-flop", which determines whether the even or odd byte
|
||||
* of a DMA address or count register will be accessed next.
|
||||
* Any write to this port simply resets the controller's "first/last flip-flop", which determines whether
|
||||
* the even or odd byte of a DMA address or count register will be accessed next.
|
||||
*/
|
||||
ChipSet.prototype.outDMAIndex = function(iDMAC, port, bOut, addrFrom)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1003,7 +1003,7 @@ if (DEBUGGER) {
|
|||
/*
|
||||
* DOS interrupts, for tracing DOS operations
|
||||
*/
|
||||
Debugger.INT_DOS_CALL = 0x21;
|
||||
Debugger.DOS_INT = 0x21;
|
||||
|
||||
Debugger.aDOSFuncDesc = {
|
||||
0x00: "terminate program",
|
||||
|
|
@ -1124,7 +1124,7 @@ if (DEBUGGER) {
|
|||
}
|
||||
}
|
||||
|
||||
this.cpu.addInterruptNotify(Debugger.INT_DOS_CALL, this, this.intDOSCall);
|
||||
this.cpu.addInterruptNotify(Debugger.DOS_INT, this, this.intDOSCall);
|
||||
|
||||
this.setReady();
|
||||
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ FDC.prototype.powerUp = function(data, fRepower)
|
|||
for (iDrive = 0; iDrive < this.nDrives; iDrive++) {
|
||||
var drive = this.aDrives[iDrive];
|
||||
drive.bType = this.chipset.getSWFloppyDriveType(iDrive);
|
||||
if (drive.bType == ChipSet.FDRIVE.DSHD) {
|
||||
if (drive.bType == ChipSet.CMOS.FDRIVE.DSHD) {
|
||||
drive.nCylinders = 80;
|
||||
}
|
||||
}
|
||||
|
|
@ -826,7 +826,7 @@ FDC.prototype.initDrive = function(drive, iDrive, data)
|
|||
* To simulate this, bCylinder is now treated as the "physical" cylinder (since that's how it's ALWAYS been used here),
|
||||
* and bCylinderSeek will now track (pun intended) the "logical" cylinder that's programmed via SEEK commands.
|
||||
*/
|
||||
drive.bType = ChipSet.FDRIVE.DSDD; // default; updated later once we have the actual ChipSet object
|
||||
drive.bType = ChipSet.CMOS.FDRIVE.DSDD; // default; updated later once we have the actual ChipSet object
|
||||
drive.bHead = data[i++];
|
||||
drive.bCylinderSeek = data[i++]; // the data[] slot where we used to store drive.nHeads (or -1)
|
||||
drive.bCylinder = data[i++];
|
||||
|
|
|
|||
|
|
@ -1050,7 +1050,7 @@ Keyboard.prototype.keyEvent = function(event, fDown)
|
|||
/*
|
||||
* HACK for simulating Ctrl-Break using Ctrl-Del (Mac) / Ctrl-Backspace (Windows)
|
||||
*/
|
||||
if (keyCode == Keyboard.KEYCODE.DELETE && (this.bitsShift & Keyboard.STATE.CTRL)) {
|
||||
if (keyCode == Keyboard.KEYCODE.DELETE && (this.bitsShift & (Keyboard.STATE.CTRL|Keyboard.STATE.ALT)) == Keyboard.STATE.CTRL) {
|
||||
keyCode = Keyboard.CHARCODE.CTRLBREAK;
|
||||
}
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -550,13 +550,13 @@
|
|||
<xsl:variable name="sw1">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@sw1"><xsl:value-of select="@sw1"/></xsl:when>
|
||||
<xsl:otherwise>11110011</xsl:otherwise>
|
||||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="sw2">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@sw2"><xsl:value-of select="@sw2"/></xsl:when>
|
||||
<xsl:otherwise>11110000</xsl:otherwise>
|
||||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="sound">
|
||||
|
|
@ -571,6 +571,18 @@
|
|||
<xsl:otherwise>false</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="fdrives">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@fdrives"><xsl:value-of select="@fdrives"/></xsl:when>
|
||||
<xsl:otherwise>0</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="monitor">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@monitor"><xsl:value-of select="@monitor"/></xsl:when>
|
||||
<xsl:otherwise/>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<xsl:variable name="rtcdate">
|
||||
<xsl:choose>
|
||||
<xsl:when test="@rtcdate"><xsl:value-of select="@rtcdate"/></xsl:when>
|
||||
|
|
@ -580,7 +592,7 @@
|
|||
<xsl:call-template name="component">
|
||||
<xsl:with-param name="machine" select="$machine"/>
|
||||
<xsl:with-param name="class">chipset</xsl:with-param>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',scaleTimers:<xsl:value-of select="$scaletimers"/>,sw1:'<xsl:value-of select="$sw1"/>',sw2:'<xsl:value-of select="$sw2"/>',sound:<xsl:value-of select="$sound"/>,rtcDate:'<xsl:value-of select="$rtcdate"/>'</xsl:with-param>
|
||||
<xsl:with-param name="parms">,model:'<xsl:value-of select="$model"/>',scaleTimers:<xsl:value-of select="$scaletimers"/>,sw1:'<xsl:value-of select="$sw1"/>',sw2:'<xsl:value-of select="$sw2"/>',sound:<xsl:value-of select="$sound"/>,fdrives:<xsl:value-of select="$fdrives"/>,monitor:'<xsl:value-of select="$monitor"/>',rtcDate:'<xsl:value-of select="$rtcdate"/>'</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue