Renamed the Paradise WD90C11 Standalone to Paradise WD90C11-LR and made it use the correct BIOS;
Added the Paradise PVGA1A (standalone) and the Paradise WD90C30-LR, both with configurable video memory; Added the Toshiba T3100e.
This commit is contained in:
721
src/machine/m_at_t3100e.c
Normal file
721
src/machine/m_at_t3100e.c
Normal file
@@ -0,0 +1,721 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../mouse.h"
|
||||
#include "../mem.h"
|
||||
#include "../device.h"
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../floppy/fdd.h"
|
||||
#include "../video/vid_t3100e.h"
|
||||
|
||||
#include "machine.h"
|
||||
#include "m_at_t3100e.h"
|
||||
|
||||
/* The Toshiba 3100e is a 286-based portable.
|
||||
*
|
||||
* To bring up the BIOS setup screen hold down the 'Fn' key on booting
|
||||
*
|
||||
* Memory management
|
||||
* ~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Motherboard memory is divided into:
|
||||
* - Conventional memory: Either 512k or 640k
|
||||
* - Upper memory: Either 512k or 384k, depending on amount of
|
||||
* conventional memory. Upper memory can be
|
||||
* used either as EMS or XMS.
|
||||
* - High memory: 0-4Mb, depending on RAM installed. The BIOS
|
||||
* setup screen allows some or all of this to be
|
||||
* used as EMS; the remainder is XMS.
|
||||
*
|
||||
* Additional memory (either EMS or XMS) can also be provided by ISA
|
||||
* expansion cards.
|
||||
*
|
||||
* Under test in PCEM, the BIOS will boot with up to 65368Kb of memory in
|
||||
* total (16Mb less 16k). However it will give an error with RAM sizes
|
||||
* above 8Mb, if any of the high memory is allocated as EMS, because the
|
||||
* builtin EMS page registers can only access up to 8Mb.
|
||||
*
|
||||
* Memory is controlled by writes to I/O port 8084h:
|
||||
* Bit 7: Always 0 }
|
||||
* Bit 6: Always 1 } These bits select which motherboard function to
|
||||
* Bit 5: Always 0 } access.
|
||||
* Bit 4: Set to treat upper RAM as XMS
|
||||
* Bit 3: Enable external RAM boards?
|
||||
* Bit 2: Set for 640k conventional memory, clear for 512k
|
||||
* Bit 1: Enable RAM beyond 1Mb.
|
||||
* Bit 0: Enable EMS.
|
||||
*
|
||||
* The last value written to this port is saved at 0040:0093h, and in
|
||||
* CMOS memory at offset 0x37. If the top bit of the CMOS byte is set,
|
||||
* then high memory is being provided by an add-on card rather than the
|
||||
* mainboard; accordingly, the BIOS will not allow high memory to be
|
||||
* used as EMS.
|
||||
*
|
||||
* EMS is controlled by 16 page registers:
|
||||
*
|
||||
* Page mapped at 0xD000 0xD400 0xD800 0xDC00
|
||||
* ------------------------------------------------------
|
||||
* Pages 0x00-0x7F 0x208 0x4208 0x8208 0xc208
|
||||
* Pages 0x80-0xFF 0x218 0x4218 0x8218 0xc218
|
||||
* Pages 0x100-0x17F 0x258 0x4258 0x8258 0xc258
|
||||
* Pages 0x180-0x1FF 0x268 0x4268 0x8268 0xc268
|
||||
*
|
||||
* The value written has bit 7 set to enable EMS, reset to disable it.
|
||||
*
|
||||
* So: OUT 0x208, 0x80 will page in the first 16k page at 0xD0000.
|
||||
* OUT 0x208, 0x00 will page out EMS, leaving nothing at 0xD0000.
|
||||
* OUT 0x4208, 0x80 will page in the first 16k page at 0xD4000.
|
||||
* OUT 0x218, 0x80 will page in the 129th 16k page at 0xD0000.
|
||||
*
|
||||
* etc.
|
||||
*
|
||||
* To use EMS from DOS, you will need the Toshiba EMS driver (TOSHEMM.ZIP).
|
||||
* This supports the above system, plus further ranges of ports at
|
||||
* 0x_2A8, 0x_2B8, 0x_2C8.
|
||||
*
|
||||
*/
|
||||
|
||||
static const int t3100e_log = 0;
|
||||
|
||||
extern uint8_t *ram; /* Physical RAM */
|
||||
|
||||
/* Features not implemented:
|
||||
* > Four video fonts.
|
||||
* > BIOS-controlled mapping of serial ports to IRQs.
|
||||
* > Custom keyboard controller. This has a number of extra commands in the
|
||||
* 0xB0-0xBC range, for such things as turbo on/off, and switching the
|
||||
* keyboard between AT and PS/2 modes. Currently I have only implemented
|
||||
* command 0xBB, so that self-test completes successfully. Commands include:
|
||||
*
|
||||
* 0xB0: Turbo on
|
||||
* 0xB1: Turbo off
|
||||
* 0xB2: Internal display on?
|
||||
* 0xB3: Internal display off?
|
||||
* 0xB5: Get settings byte (bottom bit is colour / mono setting)
|
||||
* 0xB6: Set settings byte
|
||||
* 0xB7: Behave as 101-key PS/2 keyboard
|
||||
* 0xB8: Behave as 84-key AT keyboard
|
||||
* 0xBB: Return a byte, bit 2 is Fn key state, other bits unknown.
|
||||
*
|
||||
* The other main I/O port needed to POST is:
|
||||
* 0x8084: System control.
|
||||
* Top 3 bits give command, bottom 5 bits give parameters.
|
||||
* 000 => set serial port IRQ / addresses
|
||||
* bit 4: IRQ5 serial port base: 1 => 0x338, 0 => 0x3E8
|
||||
* bits 3, 2, 0 specify serial IRQs for COM1, COM2, COM3:
|
||||
* 00 0 => 4, 3, 5
|
||||
* 00 1 => 4, 5, 3
|
||||
* 01 0 => 3, 4, 5
|
||||
* 01 1 => 3, 5, 4
|
||||
* 10 0 => 4, -, 3
|
||||
* 10 1 => 3, -, 4
|
||||
* 010 => set memory mappings
|
||||
* bit 4 set if upper RAM is XMS
|
||||
* bit 3 enable add-on memory boards beyond 5Mb?
|
||||
* bit 2 set for 640k sysram, clear for 512k sysram
|
||||
* bit 1 enable mainboard XMS
|
||||
* bit 0 enable mainboard EMS
|
||||
* 100 => set parallel mode / LCD settings
|
||||
* bit 4 set for bidirectional parallel port
|
||||
* bit 3 set to disable internal CGA
|
||||
* bit 2 set for single-pixel LCD font
|
||||
* bits 0,1 for display font
|
||||
*/
|
||||
|
||||
void at_init();
|
||||
|
||||
/* The T3100e motherboard can (and does) dynamically reassign RAM between
|
||||
* conventional, XMS and EMS. This translates to monkeying with the mappings.
|
||||
*/
|
||||
|
||||
extern mem_mapping_t base_mapping;
|
||||
|
||||
extern mem_mapping_t ram_low_mapping; /* This is to switch conventional RAM
|
||||
* between 512k and 640k */
|
||||
|
||||
extern mem_mapping_t ram_mid_mapping; /* This will not be used */
|
||||
|
||||
extern mem_mapping_t ram_high_mapping; /* This is RAM beyond 1Mb if any */
|
||||
|
||||
extern uint8_t *ram;
|
||||
|
||||
static unsigned t3100e_ems_page_reg[] =
|
||||
{
|
||||
0x208, 0x4208, 0x8208, 0xc208, /* The first four map the first 2Mb */
|
||||
/* of RAM into the page frame */
|
||||
0x218, 0x4218, 0x8218, 0xc218, /* The next four map the next 2Mb */
|
||||
/* of RAM */
|
||||
0x258, 0x4258, 0x8258, 0xc258, /* and so on. */
|
||||
0x268, 0x4268, 0x8268, 0xc268,
|
||||
};
|
||||
|
||||
struct t3100e_ems_regs
|
||||
{
|
||||
uint8_t page[16];
|
||||
mem_mapping_t mapping[4];
|
||||
uint32_t page_exec[4]; /* Physical location of memory pages */
|
||||
uint32_t upper_base; /* Start of upper RAM */
|
||||
uint8_t upper_pages; /* Pages of EMS available from upper RAM */
|
||||
uint8_t upper_is_ems; /* Upper RAM is EMS? */
|
||||
mem_mapping_t upper_mapping;
|
||||
uint8_t notify; /* Notification from keyboard controller */
|
||||
uint8_t turbo; /* 0 for 6MHz, else full speed */
|
||||
uint8_t mono; /* Emulates PC/AT 'mono' motherboard switch */
|
||||
/* Bit 0 is 0 for colour, 1 for mono */
|
||||
} t3100e_ems;
|
||||
|
||||
void t3100e_ems_out(uint16_t addr, uint8_t val, void *p);
|
||||
|
||||
|
||||
/* Given a memory address (which ought to be in the page frame at 0xD0000),
|
||||
* which page does it relate to? */
|
||||
static int addr_to_page(uint32_t addr)
|
||||
{
|
||||
if ((addr & 0xF0000) == 0xD0000)
|
||||
{
|
||||
return ((addr >> 14) & 3);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* And vice versa: Given a page slot, which memory address does it
|
||||
* correspond to? */
|
||||
static uint32_t page_to_addr(int pg)
|
||||
{
|
||||
return 0xD0000 + ((pg & 3) * 16384);
|
||||
}
|
||||
|
||||
/* Given an EMS page ID, return its physical address in RAM. */
|
||||
uint32_t t3100e_ems_execaddr(struct t3100e_ems_regs *regs,
|
||||
int pg, uint16_t val)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (!(val & 0x80)) return 0; /* Bit 7 reset => not mapped */
|
||||
|
||||
val &= 0x7F;
|
||||
val += (0x80 * (pg >> 2)); /* The high bits of the register bank */
|
||||
/* are used to extend val to allow up */
|
||||
/* to 8Mb of EMS to be accessed */
|
||||
|
||||
/* Is it in the upper memory range? */
|
||||
if (regs->upper_is_ems)
|
||||
{
|
||||
if (val < regs->upper_pages)
|
||||
{
|
||||
addr = regs->upper_base + 0x4000 * val;
|
||||
return addr;
|
||||
}
|
||||
val -= regs->upper_pages;
|
||||
}
|
||||
/* Otherwise work down from the top of high RAM (so, the more EMS,
|
||||
* the less XMS) */
|
||||
if ((val * 0x4000) + 0x100000 >= (mem_size * 1024))
|
||||
{
|
||||
return 0; /* Not enough high RAM for this page */
|
||||
}
|
||||
/* High RAM found */
|
||||
addr = (mem_size * 1024) - 0x4000 * (val + 1);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
/* The registers governing the EMS ports are in rather a nonintuitive order */
|
||||
static int port_to_page(uint16_t addr)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case 0x208: return 0;
|
||||
case 0x4208: return 1;
|
||||
case 0x8208: return 2;
|
||||
case 0xC208: return 3;
|
||||
case 0x218: return 4;
|
||||
case 0x4218: return 5;
|
||||
case 0x8218: return 6;
|
||||
case 0xC218: return 7;
|
||||
case 0x258: return 8;
|
||||
case 0x4258: return 9;
|
||||
case 0x8258: return 10;
|
||||
case 0xC258: return 11;
|
||||
case 0x268: return 12;
|
||||
case 0x4268: return 13;
|
||||
case 0x8268: return 14;
|
||||
case 0xC268: return 15;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Used to dump the memory mapping table, for debugging
|
||||
void dump_mappings()
|
||||
{
|
||||
mem_mapping_t *mm = base_mapping.next;
|
||||
|
||||
if (!t3100e_log) return;
|
||||
while (mm)
|
||||
{
|
||||
const char *name = "";
|
||||
uint32_t offset = (uint32_t)(mm->exec - ram);
|
||||
|
||||
if (mm == &ram_low_mapping ) name = "LOW ";
|
||||
if (mm == &ram_mid_mapping ) name = "MID ";
|
||||
if (mm == &ram_high_mapping) name = "HIGH";
|
||||
if (mm == &t3100e_ems.upper_mapping) name = "UPPR";
|
||||
if (mm == &t3100e_ems.mapping[0])
|
||||
{
|
||||
name = "EMS0";
|
||||
offset = t3100e_ems.page_exec[0];
|
||||
}
|
||||
if (mm == &t3100e_ems.mapping[1])
|
||||
{
|
||||
name = "EMS1";
|
||||
offset = t3100e_ems.page_exec[1];
|
||||
}
|
||||
if (mm == &t3100e_ems.mapping[2])
|
||||
{
|
||||
name = "EMS2";
|
||||
offset = t3100e_ems.page_exec[2];
|
||||
}
|
||||
if (mm == &t3100e_ems.mapping[3])
|
||||
{
|
||||
name = "EMS3";
|
||||
offset = t3100e_ems.page_exec[3];
|
||||
}
|
||||
|
||||
pclog(" %p | base=%05x size=%05x %c @ %06x %s\n", mm,
|
||||
mm->base, mm->size, mm->enable ? 'Y' : 'N',
|
||||
offset, name);
|
||||
|
||||
mm = mm->next;
|
||||
}
|
||||
}*/
|
||||
|
||||
void t3100e_map_ram(uint8_t val)
|
||||
{
|
||||
int n;
|
||||
int32_t upper_len;
|
||||
|
||||
if (t3100e_log)
|
||||
{
|
||||
pclog("OUT 0x8084, %02x [ set memory mapping :", val | 0x40);
|
||||
if (val & 1) pclog("ENABLE_EMS ");
|
||||
if (val & 2) pclog("ENABLE_XMS ");
|
||||
if (val & 4) pclog("640K ");
|
||||
if (val & 8) pclog("X8X ");
|
||||
if (val & 16) pclog("UPPER_IS_XMS ");
|
||||
pclog("\n");
|
||||
}
|
||||
/* Bit 2 controls size of conventional memory */
|
||||
if (val & 4)
|
||||
{
|
||||
t3100e_ems.upper_base = 0xA0000;
|
||||
t3100e_ems.upper_pages = 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
t3100e_ems.upper_base = 0x80000;
|
||||
t3100e_ems.upper_pages = 32;
|
||||
}
|
||||
upper_len = t3100e_ems.upper_pages * 16384;
|
||||
|
||||
mem_mapping_set_addr(&ram_low_mapping, 0, t3100e_ems.upper_base);
|
||||
/* Bit 0 set if upper RAM is EMS */
|
||||
t3100e_ems.upper_is_ems = (val & 1);
|
||||
|
||||
/* Bit 1 set if high RAM is enabled */
|
||||
if (val & 2)
|
||||
{
|
||||
mem_mapping_enable(&ram_high_mapping);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_mapping_disable(&ram_high_mapping);
|
||||
}
|
||||
|
||||
/* Bit 4 set if upper RAM is mapped to high memory
|
||||
* (and bit 1 set if XMS enabled) */
|
||||
if ((val & 0x12) == 0x12)
|
||||
{
|
||||
mem_mapping_set_addr(&t3100e_ems.upper_mapping,
|
||||
mem_size * 1024,
|
||||
upper_len);
|
||||
mem_mapping_enable(&t3100e_ems.upper_mapping);
|
||||
mem_mapping_set_exec(&t3100e_ems.upper_mapping, ram + t3100e_ems.upper_base);
|
||||
}
|
||||
else
|
||||
{
|
||||
mem_mapping_disable(&t3100e_ems.upper_mapping);
|
||||
}
|
||||
/* Recalculate EMS mappings */
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
t3100e_ems_out(t3100e_ems_page_reg[n], t3100e_ems.page[n],
|
||||
&t3100e_ems);
|
||||
}
|
||||
|
||||
//dump_mappings();
|
||||
}
|
||||
|
||||
|
||||
void t3100e_notify_set(uint8_t value)
|
||||
{
|
||||
t3100e_ems.notify = value;
|
||||
}
|
||||
|
||||
void t3100e_mono_set(uint8_t value)
|
||||
{
|
||||
t3100e_ems.mono = value;
|
||||
}
|
||||
|
||||
uint8_t t3100e_mono_get(void)
|
||||
{
|
||||
return t3100e_ems.mono;
|
||||
}
|
||||
|
||||
void t3100e_turbo_set(uint8_t value)
|
||||
{
|
||||
t3100e_ems.turbo = value;
|
||||
if (!value)
|
||||
{
|
||||
int c = cpu;
|
||||
cpu = 0; /* 286/6 */
|
||||
cpu_set();
|
||||
cpu = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_set();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t t3100e_sys_in(uint16_t addr, void *p)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p;
|
||||
|
||||
/* The low 4 bits always seem to be 0x0C. The high 4 are a
|
||||
* notification sent by the keyboard controller when it detects
|
||||
* an [Fn] key combination */
|
||||
if (t3100e_log) pclog("IN 0x8084\n");
|
||||
return 0x0C | (regs->notify << 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Handle writes to the T3100e system control port at 0x8084 */
|
||||
void t3100e_sys_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
// struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p;
|
||||
|
||||
switch (val & 0xE0)
|
||||
{
|
||||
case 0x00: /* Set serial port IRQs. Not implemented */
|
||||
if (t3100e_log) pclog("OUT 0x8084, %02x [ set serial port IRQs]\n", val);
|
||||
break;
|
||||
case 0x40: /* Set RAM mappings. */
|
||||
t3100e_map_ram(val & 0x1F);
|
||||
break;
|
||||
|
||||
case 0x80: /* Set video options. */
|
||||
t3100e_video_options_set(val & 0x1F); break;
|
||||
|
||||
/* Other options not implemented. */
|
||||
default: if (t3100e_log) pclog("OUT 0x8084, %02x\n", val); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t t3100e_config_get(void)
|
||||
{
|
||||
/* The byte returned:
|
||||
Bit 7: Set if internal plasma display enabled
|
||||
Bit 6: Set if running at 6MHz, clear at full speed
|
||||
Bit 5: Always 1?
|
||||
Bit 4: Set if the FD2MB jumper is present (internal floppy is ?tri-mode)
|
||||
Bit 3: Clear if the FD2 jumper is present (two internal floppies)
|
||||
Bit 2: Set if the internal drive is A:, clear if B:
|
||||
Bit 1: Set if the parallel port is configured as a floppy connector
|
||||
for the second drive.
|
||||
Bit 0: Set if the F2HD jumper is present (internal floppy is 720k)
|
||||
*/
|
||||
uint8_t value = 0x28; /* Start with bits 5 and 3 set. */
|
||||
|
||||
int type_a = fdd_get_type(0);
|
||||
int type_b = fdd_get_type(1);
|
||||
int prt_switch; /* External drive type: 0=> none, 1=>A, 2=>B */
|
||||
|
||||
/* Get display setting */
|
||||
if (t3100e_display_get()) value |= 0x80;
|
||||
if (!t3100e_ems.turbo) value |= 0x40;
|
||||
|
||||
/* Try to determine the floppy types.*/
|
||||
|
||||
prt_switch = (type_b ? 2 : 0);
|
||||
switch(type_a)
|
||||
{
|
||||
/* Since a T3100e cannot have an internal 5.25" drive, mark 5.25" A: drive as
|
||||
* being external, and set the internal type based on type_b. */
|
||||
case 1: /* 360k */
|
||||
case 2: /* 1.2Mb */
|
||||
case 3: /* 1.2Mb RPMx2*/
|
||||
prt_switch = 1; /* External drive is A: */
|
||||
switch (type_b)
|
||||
{
|
||||
case 1: /* 360k */
|
||||
case 4: value |= 1; break; /* 720k */
|
||||
case 6: value |= 0x10; break; /* Tri-mode */
|
||||
/* All others will be treated as 1.4M */
|
||||
}
|
||||
break;
|
||||
case 4: value |= 0x01; /* 720k */
|
||||
if (type_a == type_b)
|
||||
{
|
||||
value &= (~8); /* Two internal drives */
|
||||
prt_switch = 0; /* No external drive */
|
||||
}
|
||||
break;
|
||||
case 5: /* 1.4M */
|
||||
case 7: /* 2.8M */
|
||||
if (type_a == type_b)
|
||||
{
|
||||
value &= (~8); /* Two internal drives */
|
||||
prt_switch = 0; /* No external drive */
|
||||
}
|
||||
break;
|
||||
case 6: /* 3-mode */
|
||||
value |= 0x10;
|
||||
if (type_a == type_b)
|
||||
{
|
||||
value &= (~8); /* Two internal drives */
|
||||
prt_switch = 0; /* No external drive */
|
||||
}
|
||||
break;
|
||||
} /* End switch */
|
||||
switch (prt_switch)
|
||||
{
|
||||
case 0: value |= 4; break; /* No external floppy */
|
||||
case 1: value |= 2; break; /* External floppy is A: */
|
||||
case 2: value |= 6; break; /* External floppy is B: */
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/* Read EMS page register */
|
||||
uint8_t t3100e_ems_in(uint16_t addr, void *p)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p;
|
||||
|
||||
return regs->page[port_to_page(addr)];
|
||||
|
||||
}
|
||||
|
||||
/* Write EMS page register */
|
||||
void t3100e_ems_out(uint16_t addr, uint8_t val, void *p)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p;
|
||||
int pg = port_to_page(addr);
|
||||
|
||||
regs->page_exec[pg & 3] = t3100e_ems_execaddr(regs, pg, val);
|
||||
if (t3100e_log) pclog("EMS: page %d %02x -> %02x [%06x]\n",
|
||||
pg, regs->page[pg], val, regs->page_exec[pg & 3]);
|
||||
regs->page[pg] = val;
|
||||
|
||||
pg &= 3;
|
||||
/* Bit 7 set if page is enabled, reset if page is disabled */
|
||||
if (regs->page_exec[pg])
|
||||
{
|
||||
if (t3100e_log) pclog("Enabling EMS RAM at %05x\n",
|
||||
page_to_addr(pg));
|
||||
mem_mapping_enable(®s->mapping[pg]);
|
||||
mem_mapping_set_exec(®s->mapping[pg], ram + regs->page_exec[pg]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t3100e_log) pclog("Disabling EMS RAM at %05x\n",
|
||||
page_to_addr(pg));
|
||||
mem_mapping_disable(®s->mapping[pg]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read RAM in the EMS page frame */
|
||||
static uint8_t ems_read_ram(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return 0xFF;
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
return ram[addr];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint16_t ems_read_ramw(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return 0xFF;
|
||||
//pclog("ems_read_ramw addr=%05x ", addr);
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
//pclog("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]);
|
||||
return *(uint16_t *)&ram[addr];
|
||||
}
|
||||
|
||||
|
||||
static uint32_t ems_read_raml(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return 0xFF;
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
return *(uint32_t *)&ram[addr];
|
||||
}
|
||||
|
||||
/* Write RAM in the EMS page frame */
|
||||
static void ems_write_ram(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return;
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
static void ems_write_ramw(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return;
|
||||
//pclog("ems_write_ramw addr=%05x ", addr);
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
//pclog("-> %06x val=%04x\n", addr, val);
|
||||
|
||||
*(uint16_t *)&ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
static void ems_write_raml(uint32_t addr, uint32_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
int pg = addr_to_page(addr);
|
||||
|
||||
if (pg < 0) return;
|
||||
addr = regs->page_exec[pg] + (addr & 0x3FFF);
|
||||
*(uint32_t *)&ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read RAM in the upper area. This is basically what the 'remapped'
|
||||
* mapping in mem.c does, except that the upper area can move around */
|
||||
static uint8_t upper_read_ram(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
return ram[addr];
|
||||
}
|
||||
|
||||
static uint16_t upper_read_ramw(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
return *(uint16_t *)&ram[addr];
|
||||
}
|
||||
|
||||
static uint32_t upper_read_raml(uint32_t addr, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
return *(uint32_t *)&ram[addr];
|
||||
}
|
||||
|
||||
|
||||
static void upper_write_ram(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
static void upper_write_ramw(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
*(uint16_t *)&ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void upper_write_raml(uint32_t addr, uint32_t val, void *priv)
|
||||
{
|
||||
struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)priv;
|
||||
|
||||
addr = (addr - (1024 * mem_size)) + regs->upper_base;
|
||||
*(uint32_t *)&ram[addr] = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void machine_at_t3100e_init(machine_t *model)
|
||||
{
|
||||
int pg;
|
||||
|
||||
memset(&t3100e_ems, 0, sizeof(t3100e_ems));
|
||||
|
||||
machine_at_ide_init(model);
|
||||
/* Hook up system control port */
|
||||
io_sethandler(0x8084, 0x0001,
|
||||
t3100e_sys_in, NULL, NULL,
|
||||
t3100e_sys_out, NULL, NULL, &t3100e_ems);
|
||||
|
||||
/* Start monitoring all 16 EMS registers */
|
||||
for (pg = 0; pg < 16; pg++)
|
||||
{
|
||||
io_sethandler(t3100e_ems_page_reg[pg], 0x0001,
|
||||
t3100e_ems_in, NULL, NULL,
|
||||
t3100e_ems_out, NULL, NULL, &t3100e_ems);
|
||||
}
|
||||
|
||||
/* Map the EMS page frame */
|
||||
for (pg = 0; pg < 4; pg++)
|
||||
{
|
||||
if (t3100e_log) pclog("Adding memory map at %x for page %d\n", page_to_addr(pg), pg);
|
||||
mem_mapping_add(&t3100e_ems.mapping[pg],
|
||||
page_to_addr(pg), 16384,
|
||||
ems_read_ram, ems_read_ramw, ems_read_raml,
|
||||
ems_write_ram, ems_write_ramw, ems_write_raml,
|
||||
NULL, MEM_MAPPING_EXTERNAL,
|
||||
&t3100e_ems);
|
||||
/* Start them all off disabled */
|
||||
mem_mapping_disable(&t3100e_ems.mapping[pg]);
|
||||
}
|
||||
/* Mapping for upper RAM when in use as XMS*/
|
||||
mem_mapping_add(&t3100e_ems.upper_mapping, mem_size * 1024, 384 * 1024,
|
||||
upper_read_ram, upper_read_ramw, upper_read_raml,
|
||||
upper_write_ram, upper_write_ramw, upper_write_raml,
|
||||
NULL, MEM_MAPPING_INTERNAL, &t3100e_ems);
|
||||
mem_mapping_disable(&t3100e_ems.upper_mapping);
|
||||
|
||||
device_add(&t3100e_device);
|
||||
}
|
||||
7
src/machine/m_at_t3100e.h
Normal file
7
src/machine/m_at_t3100e.h
Normal file
@@ -0,0 +1,7 @@
|
||||
void t3100e_notify_set(uint8_t value);
|
||||
void t3100e_display_set(uint8_t value);
|
||||
uint8_t t3100e_display_get();
|
||||
uint8_t t3100e_config_get();
|
||||
void t3100e_turbo_set(uint8_t value);
|
||||
uint8_t t3100e_mono_get();
|
||||
void t3100e_mono_set(uint8_t value);
|
||||
@@ -100,6 +100,8 @@ extern void machine_at_ide_init(machine_t *);
|
||||
extern void machine_at_top_remap_init(machine_t *);
|
||||
extern void machine_at_ide_top_remap_init(machine_t *);
|
||||
|
||||
extern void machine_at_t3100e_init(machine_t *);
|
||||
|
||||
extern void machine_at_p54tp4xe_init(machine_t *);
|
||||
extern void machine_at_endeavor_init(machine_t *);
|
||||
extern void machine_at_zappa_init(machine_t *);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
* NOTES: OpenAT wip for 286-class machine with open BIOS.
|
||||
* PS2_M80-486 wip, pending receipt of TRM's for machine.
|
||||
*
|
||||
* Version: @(#)machine_table.c 1.0.8 2017/12/29
|
||||
* Version: @(#)machine_table.c 1.0.9 2017/12/31
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
@@ -72,8 +72,9 @@ machine_t machines[] = {
|
||||
{ "[286 ISA] IBM XT Model 286", ROM_IBMXT286, "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_top_remap_init, NULL, nvr_at_close },
|
||||
{ "[286 ISA] Samsung SPC-4200P", ROM_SPC4200P, "spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 127, machine_at_scat_init, NULL, nvr_at_close },
|
||||
#ifdef WALTJE
|
||||
{ "[286 ISA] OpenAT 286", ROM_OPENAT, "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 4096, 128, 127, machine_at_init, NULL, nvr_at_close },
|
||||
{ "[286 ISA] OpenAT 286", ROM_OPENAT, "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 0, MACHINE_ISA | MACHINE_AT, 512, 4096, 128, 127, machine_at_init, NULL, nvr_at_close },
|
||||
#endif
|
||||
{ "[286 ISA] Toshiba 3100e", ROM_T3100E, "t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL, nvr_at_close },
|
||||
|
||||
{ "[286 MCA] IBM PS/2 model 50", ROM_IBMPS2_M50, "ibmps2_m50", {{"", cpus_ps2_m30_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, 1, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC_PS2, 1, 16, 1, 63, machine_ps2_model_50_init, NULL, nvr_at_close },
|
||||
|
||||
|
||||
Reference in New Issue
Block a user