NEAT: Fix EMS and implement Shadow RAM and top 128K of conventional memory on/off, closes #1375.
This commit is contained in:
@@ -37,6 +37,9 @@
|
||||
|
||||
#define EMS_MAXPAGE 4
|
||||
#define EMS_PGSIZE 16384
|
||||
#define EMS_PGMASK 16383
|
||||
|
||||
#define REG_MASK 0x0f
|
||||
|
||||
/* CS8221 82C211 controller registers. */
|
||||
#define REG_RA0 0x60 /* PROCCLK selector */
|
||||
@@ -194,37 +197,47 @@
|
||||
#define RB10_P0EXT 0xc0 /* page 0 extension */
|
||||
#define RB10_P0EXT_SH 6
|
||||
|
||||
#define REG_RB11 0x6f /* Miscellaneous */
|
||||
#define RB11_MASK 0xe6 /* 111R R11R */
|
||||
#define RB11_GA20 0x02 /* gate for A20 */
|
||||
#define RB11_RASTMO 0x04 /* enable RAS timeout counter */
|
||||
#define RB11_EMSLEN 0xe0 /* EMS memory chunk size */
|
||||
#define RB11_EMSLEN_SH 5
|
||||
#define REG_RB12 0x6f /* Miscellaneous */
|
||||
#define RB12_MASK 0xe6 /* 111R R11R */
|
||||
#define RB12_GA20 0x02 /* gate for A20 */
|
||||
#define RB12_RASTMO 0x04 /* enable RAS timeout counter */
|
||||
#define RB12_EMSLEN 0xe0 /* EMS memory chunk size */
|
||||
#define RB12_EMSLEN_SH 5
|
||||
|
||||
typedef struct emspage_t {
|
||||
int8_t enabled; /* 1=ENABLED */
|
||||
#define RAM_FLAG_EMS 0x08
|
||||
#define RAM_FLAG_ROMCS 0x04
|
||||
#define RAM_FLAG_SHREAD 0x02
|
||||
#define RAM_FLAG_SHWRITE 0x01
|
||||
#define RAM_FMASK_EMS 0x08
|
||||
#define RAM_FMASK_SHADOW 0x07
|
||||
|
||||
typedef struct ram_page_t {
|
||||
int8_t enabled; /* 1=ENABLED */
|
||||
char pad;
|
||||
uint16_t page; /* selected page in EMS block */
|
||||
uint32_t start; /* start of EMS in RAM */
|
||||
uint8_t *addr; /* start addr in EMS RAM */
|
||||
mem_mapping_t mapping; /* mapping entry for page */
|
||||
} emspage_t;
|
||||
uint32_t phys_base;
|
||||
uint32_t virt_base;
|
||||
mem_mapping_t mapping; /* mapping entry for page */
|
||||
} ram_page_t;
|
||||
|
||||
typedef struct neat_t {
|
||||
uint8_t regs[128]; /* all the CS8221 registers */
|
||||
uint8_t indx; /* programmed index into registers */
|
||||
uint8_t ram_flags[32];
|
||||
uint8_t regs[128]; /* all the CS8221 registers */
|
||||
uint8_t indx; /* programmed index into registers */
|
||||
|
||||
char pad;
|
||||
char pad;
|
||||
|
||||
uint16_t ems_base; /* configured base address */
|
||||
uint16_t ems_oldbase;
|
||||
uint32_t ems_frame; /* configured frame address */
|
||||
uint32_t ems_oldframe;
|
||||
uint16_t ems_size; /* EMS size in KB */
|
||||
uint16_t ems_pages; /* EMS size in pages */
|
||||
emspage_t ems[EMS_MAXPAGE]; /* EMS page registers */
|
||||
uint16_t ems_base; /* configured base address */
|
||||
uint32_t ems_frame; /* configured frame address */
|
||||
uint16_t ems_size; /* EMS size in KB */
|
||||
uint16_t ems_pages; /* EMS size in pages */
|
||||
|
||||
ram_page_t ems[EMS_MAXPAGE]; /* EMS page registers */
|
||||
ram_page_t shadow[32]; /* Shadow RAM pages */
|
||||
} neat_t;
|
||||
|
||||
static uint8_t defaults[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00,
|
||||
0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 };
|
||||
|
||||
#ifdef ENABLE_NEAT_LOG
|
||||
int neat_do_log = ENABLE_NEAT_LOG;
|
||||
|
||||
@@ -247,11 +260,11 @@ neat_log(const char *fmt, ...)
|
||||
static uint8_t
|
||||
ems_readb(uint32_t addr, void *priv)
|
||||
{
|
||||
neat_t *dev = (neat_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
ram_page_t *dev = (ram_page_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
/* Grab the data. */
|
||||
ret = *(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff));
|
||||
ret = *(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -260,11 +273,11 @@ ems_readb(uint32_t addr, void *priv)
|
||||
static uint16_t
|
||||
ems_readw(uint32_t addr, void *priv)
|
||||
{
|
||||
neat_t *dev = (neat_t *) priv;
|
||||
uint16_t ret = 0xffff;
|
||||
ram_page_t *dev = (ram_page_t *) priv;
|
||||
uint16_t ret = 0xffff;
|
||||
|
||||
/* Grab the data. */
|
||||
ret = *(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff));
|
||||
ret = *(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -273,40 +286,113 @@ ems_readw(uint32_t addr, void *priv)
|
||||
static void
|
||||
ems_writeb(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
neat_t *dev = (neat_t *) priv;
|
||||
ram_page_t *dev = (ram_page_t *) priv;
|
||||
|
||||
/* Write the data. */
|
||||
*(uint8_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val;
|
||||
*(uint8_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val;
|
||||
}
|
||||
|
||||
/* Write one word to paged RAM. */
|
||||
static void
|
||||
ems_writew(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
neat_t *dev = (neat_t *) priv;
|
||||
ram_page_t *dev = (ram_page_t *) priv;
|
||||
|
||||
/* Write the data. */
|
||||
*(uint16_t *) (dev->ems[(addr & 0xffff) >> 14].addr + (addr & 0x3fff)) = val;
|
||||
*(uint16_t *) &(ram[addr - dev->virt_base + dev->phys_base]) = val;
|
||||
}
|
||||
|
||||
static void
|
||||
neat_mem_update_state(neat_t *dev, uint32_t addr, uint32_t size, uint8_t new_flags, uint8_t mask)
|
||||
{
|
||||
if ((addr >= 0x00080000) && (addr < 0x00100000) &&
|
||||
((new_flags ^ dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE]) & mask)) {
|
||||
dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] &= ~mask;
|
||||
dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE] |= new_flags;
|
||||
|
||||
new_flags = dev->ram_flags[(addr - 0x00080000) / EMS_PGSIZE];
|
||||
|
||||
neat_log("neat_mem_update_state(): %08X-%08X: %02X\n", addr, addr + size - 1, new_flags);
|
||||
|
||||
if (new_flags & RAM_FLAG_EMS)
|
||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
else if (new_flags & RAM_FLAG_ROMCS)
|
||||
mem_set_mem_state(addr, size, MEM_READ_ROMCS | MEM_WRITE_ROMCS);
|
||||
else switch (new_flags & (RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE)) {
|
||||
case 0:
|
||||
mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
break;
|
||||
case 1:
|
||||
mem_set_mem_state(addr, size, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
case 2:
|
||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
|
||||
break;
|
||||
case 3:
|
||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flushmmucache_nopc();
|
||||
}
|
||||
|
||||
static void
|
||||
shadow_recalc(neat_t *dev)
|
||||
{
|
||||
for (uint8_t i = 8; i < 32; i++) {
|
||||
int romcs = 0;
|
||||
int write = 1;
|
||||
int shadow_reg = REG_RB3 + ((i - 8) >> 3);
|
||||
int shadow_bit = i & 7;
|
||||
int ram_flags;
|
||||
int read;
|
||||
|
||||
if (i > 16) {
|
||||
int rb1_romcs_bit = 7 - (i >> 2);
|
||||
int rb1_write_bit = rb1_romcs_bit + 4;
|
||||
|
||||
romcs = !(dev->regs[REG_RB1] & (1 << rb1_romcs_bit));
|
||||
write = !(dev->regs[REG_RB1] & (1 << rb1_write_bit));
|
||||
} else if (i <= 8)
|
||||
shadow_bit ^= 4;
|
||||
|
||||
read = dev->regs[shadow_reg] & (1 << shadow_bit);
|
||||
write = write && read;
|
||||
|
||||
ram_flags = romcs ? RAM_FLAG_ROMCS : 0x00;
|
||||
ram_flags |= read ? RAM_FLAG_SHREAD : 0x00;
|
||||
ram_flags |= write ? RAM_FLAG_SHWRITE : 0x00;
|
||||
|
||||
if ((ram_flags > 0x00) && !(ram_flags & RAM_FLAG_ROMCS))
|
||||
mem_mapping_set_addr(&(dev->shadow[i].mapping), dev->shadow[i].virt_base, EMS_PGSIZE);
|
||||
else
|
||||
mem_mapping_disable(&(dev->shadow[i].mapping));
|
||||
|
||||
neat_mem_update_state(dev, dev->shadow[i].virt_base, EMS_PGSIZE, ram_flags, RAM_FMASK_SHADOW);
|
||||
}
|
||||
}
|
||||
|
||||
/* Re-calculate the active-page physical address. */
|
||||
static void
|
||||
ems_recalc(neat_t *dev, emspage_t *ems)
|
||||
ems_recalc(neat_t *dev, ram_page_t *ems)
|
||||
{
|
||||
if (ems->page >= dev->ems_pages) {
|
||||
/* That page does not exist. */
|
||||
ems->enabled = 0;
|
||||
}
|
||||
uint32_t page = ems->phys_base / EMS_PGSIZE;
|
||||
|
||||
/* Pre-calculate the page address in EMS RAM. */
|
||||
ems->addr = ram + ems->start + (ems->page * EMS_PGSIZE);
|
||||
if ((dev->regs[REG_RB7] & RB7_EMSEN) && ems->enabled &&
|
||||
(page >= 0x40) && (page < (0x40 + dev->ems_pages))) {
|
||||
neat_log("ems_recalc(): %08X-%08X -> %08X-%08X\n",
|
||||
ems->virt_base, ems->virt_base + EMS_PGSIZE - 1,
|
||||
ems->phys_base, ems->phys_base + EMS_PGSIZE - 1);
|
||||
mem_mapping_set_addr(&ems->mapping, ems->virt_base, EMS_PGSIZE);
|
||||
|
||||
if (ems->enabled) {
|
||||
/* Update the EMS RAM address for this page. */
|
||||
mem_mapping_set_exec(&ems->mapping, ems->addr);
|
||||
mem_mapping_set_exec(&ems->mapping, ram + ems->phys_base);
|
||||
|
||||
/* Enable this page. */
|
||||
mem_mapping_enable(&ems->mapping);
|
||||
if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000))
|
||||
neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, RAM_FLAG_EMS, RAM_FMASK_EMS);
|
||||
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT EMS: page %d set to %08lx, %sabled)\n",
|
||||
@@ -315,15 +401,18 @@ ems_recalc(neat_t *dev, emspage_t *ems)
|
||||
} else {
|
||||
/* Disable this page. */
|
||||
mem_mapping_disable(&ems->mapping);
|
||||
|
||||
if ((ems->virt_base >= 0x00080000) && (ems->virt_base < 0x00100000))
|
||||
neat_mem_update_state(dev, ems->virt_base, EMS_PGSIZE, 0x00, RAM_FMASK_EMS);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ems_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
neat_t *dev = (neat_t *) priv;
|
||||
emspage_t *ems;
|
||||
int vpage;
|
||||
neat_t *dev = (neat_t *) priv;
|
||||
ram_page_t *ems;
|
||||
int vpage;
|
||||
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT: ems_write(%04x, %02x)\n", port, val);
|
||||
@@ -337,8 +426,7 @@ ems_write(uint16_t port, uint8_t val, void *priv)
|
||||
case 0x0008:
|
||||
case 0x0009:
|
||||
ems->enabled = !!(val & 0x80);
|
||||
ems->page &= 0x0180; /* clear lower bits */
|
||||
ems->page |= (val & 0x7f); /* add new bits */
|
||||
ems->phys_base = (ems->phys_base & 0xffe00000) | ((val & 0x7f) * EMS_PGSIZE);
|
||||
ems_recalc(dev, ems);
|
||||
break;
|
||||
default:
|
||||
@@ -358,7 +446,7 @@ ems_read(uint16_t port, void *priv)
|
||||
|
||||
switch (port & 0x000f) {
|
||||
case 0x0008: /* page number register */
|
||||
ret = dev->ems[vpage].page & 0x7f;
|
||||
ret = (dev->ems[vpage].phys_base / EMS_PGSIZE) & 0x7f;
|
||||
if (dev->ems[vpage].enabled)
|
||||
ret |= 0x80;
|
||||
break;
|
||||
@@ -373,68 +461,21 @@ ems_read(uint16_t port, void *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize the EMS module. */
|
||||
static void
|
||||
ems_init(neat_t *dev, int en)
|
||||
ems_update(neat_t *dev, int en)
|
||||
{
|
||||
uint8_t j;
|
||||
|
||||
/* Remove if needed. */
|
||||
if (!en) {
|
||||
if (dev->ems_base > 0)
|
||||
for (uint8_t i = 0; i < EMS_MAXPAGE; i++) {
|
||||
/* Disable for now. */
|
||||
mem_mapping_disable(&dev->ems[i].mapping);
|
||||
|
||||
/* Remove I/O handler. */
|
||||
io_removehandler(dev->ems_base + (i * EMS_PGSIZE), 2,
|
||||
ems_read, NULL, NULL, ems_write, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_NEAT_LOG
|
||||
neat_log("NEAT: EMS disabled\n");
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get configured I/O address. */
|
||||
j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH;
|
||||
dev->ems_base = 0x0208 + (0x10 * j);
|
||||
|
||||
/* Get configured frame address. */
|
||||
j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH;
|
||||
dev->ems_frame = 0xC0000 + (EMS_PGSIZE * j);
|
||||
|
||||
/*
|
||||
* For each supported page (we can have a maximum of 4),
|
||||
* create, initialize and disable the mappings, and set
|
||||
* up the I/O control handler.
|
||||
*/
|
||||
for (uint8_t i = 0; i < EMS_MAXPAGE; i++) {
|
||||
/* Create and initialize a page mapping. */
|
||||
mem_mapping_add(&dev->ems[i].mapping,
|
||||
dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE,
|
||||
ems_readb, ems_readw, NULL,
|
||||
ems_writeb, ems_writew, NULL,
|
||||
ram, MEM_MAPPING_EXTERNAL,
|
||||
dev);
|
||||
|
||||
/* Disable for now. */
|
||||
mem_mapping_disable(&dev->ems[i].mapping);
|
||||
|
||||
/* Set up an I/O port handler. */
|
||||
io_sethandler(dev->ems_base + (i * EMS_PGSIZE), 2,
|
||||
ems_read, NULL, NULL, ems_write, NULL, NULL, dev);
|
||||
io_handler(en, dev->ems_base + (i * EMS_PGSIZE), 2,
|
||||
ems_read, NULL, NULL, ems_write, NULL, NULL, dev);
|
||||
|
||||
/*
|
||||
* TODO: update the 'high_mem' mapping to reflect that we now
|
||||
* have NN MB less extended memory available..
|
||||
*/
|
||||
if (en)
|
||||
dev->ems[i].virt_base = dev->ems_frame + (i * EMS_PGSIZE);
|
||||
|
||||
ems_recalc(dev, &(dev->ems[i]));
|
||||
}
|
||||
|
||||
neat_log("NEAT: EMS enabled, I/O=%04xH, Frame=%05XH\n",
|
||||
dev->ems_base, dev->ems_frame);
|
||||
flushmmucache_nopc();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -442,6 +483,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
neat_t *dev = (neat_t *) priv;
|
||||
uint8_t xval;
|
||||
uint8_t j;
|
||||
uint8_t *reg;
|
||||
int i;
|
||||
|
||||
@@ -493,6 +535,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
case REG_RB1:
|
||||
val &= RB1_MASK;
|
||||
*reg = (*reg & ~RB1_MASK) | val;
|
||||
shadow_recalc(dev);
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
@@ -501,6 +544,10 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
case REG_RB2:
|
||||
val &= RB2_MASK;
|
||||
*reg = (*reg & ~RB2_MASK) | val;
|
||||
if (val & RB2_TOP128)
|
||||
neat_mem_update_state(dev, 0x00080000, 0x00020000, RAM_FLAG_SHREAD | RAM_FLAG_SHWRITE, RAM_FMASK_SHADOW);
|
||||
else
|
||||
neat_mem_update_state(dev, 0x00080000, 0x00020000, 0x00, RAM_FMASK_SHADOW);
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
@@ -509,6 +556,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
case REG_RB3:
|
||||
val &= RB3_MASK;
|
||||
*reg = (*reg & ~RB3_MASK) | val;
|
||||
shadow_recalc(dev);
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
@@ -517,6 +565,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
case REG_RB4:
|
||||
val &= RB4_MASK;
|
||||
*reg = (*reg & ~RB4_MASK) | val;
|
||||
shadow_recalc(dev);
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
@@ -525,6 +574,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
case REG_RB5:
|
||||
val &= RB5_MASK;
|
||||
*reg = (*reg & ~RB5_MASK) | val;
|
||||
shadow_recalc(dev);
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
@@ -544,10 +594,9 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
if (val & RB7_EMSEN)
|
||||
ems_init(dev, 1);
|
||||
else if (xval & RB7_EMSEN)
|
||||
ems_init(dev, 0);
|
||||
|
||||
if (xval & RB7_EMSEN)
|
||||
ems_update(dev, !!(val & RB7_EMSEN));
|
||||
|
||||
if (xval & RB7_UMAREL) {
|
||||
if (val & RB7_UMAREL)
|
||||
@@ -571,10 +620,19 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
if (dev->regs[REG_RB7] & RB7_EMSEN) {
|
||||
ems_init(dev, 0);
|
||||
ems_init(dev, 1);
|
||||
}
|
||||
|
||||
ems_update(dev, 0);
|
||||
|
||||
/* Get configured I/O address. */
|
||||
j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH;
|
||||
dev->ems_base = 0x0208 + (0x10 * j);
|
||||
|
||||
/* Get configured frame address. */
|
||||
j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH;
|
||||
dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j);
|
||||
|
||||
if (dev->regs[REG_RB7] & RB7_EMSEN)
|
||||
ems_update(dev, 1);
|
||||
break;
|
||||
|
||||
case REG_RB10:
|
||||
@@ -584,23 +642,29 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
|
||||
dev->ems[3].start = ((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21;
|
||||
dev->ems[2].start = ((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21;
|
||||
dev->ems[1].start = ((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21;
|
||||
dev->ems[0].start = ((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21;
|
||||
for (i = 0; i < EMS_MAXPAGE; i++)
|
||||
ems_recalc(dev, &dev->ems[i]);
|
||||
dev->ems[3].phys_base = (dev->ems[3].phys_base & 0x001fffff) |
|
||||
(((val & RB10_P3EXT) >> RB10_P3EXT_SH) << 21);
|
||||
dev->ems[2].phys_base = (dev->ems[2].phys_base & 0x001fffff) |
|
||||
(((val & RB10_P2EXT) >> RB10_P2EXT_SH) << 21);
|
||||
dev->ems[1].phys_base = (dev->ems[1].phys_base & 0x001fffff) |
|
||||
(((val & RB10_P1EXT) >> RB10_P1EXT_SH) << 21);
|
||||
dev->ems[0].phys_base = (dev->ems[0].phys_base & 0x001fffff) |
|
||||
(((val & RB10_P0EXT) >> RB10_P0EXT_SH) << 21);
|
||||
|
||||
if (dev->regs[REG_RB7] & RB7_EMSEN)
|
||||
for (i = 0; i < EMS_MAXPAGE; i++)
|
||||
ems_recalc(dev, &dev->ems[i]);
|
||||
break;
|
||||
|
||||
case REG_RB11:
|
||||
val &= RB11_MASK;
|
||||
*reg = (*reg & ~RB11_MASK) | val;
|
||||
case REG_RB12:
|
||||
val &= RB12_MASK;
|
||||
*reg = (*reg & ~RB12_MASK) | val;
|
||||
#if NEAT_DEBUG > 1
|
||||
neat_log("NEAT: RB11=%02x(%02x)\n", val, *reg);
|
||||
neat_log("NEAT: RB12=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
i = (val & RB11_EMSLEN) >> RB11_EMSLEN_SH;
|
||||
i = (val & RB12_EMSLEN) >> RB12_EMSLEN_SH;
|
||||
switch (i) {
|
||||
case 0: /* "less than 2MB" */
|
||||
case 0: /* "less than 1MB" */
|
||||
dev->ems_size = 512;
|
||||
break;
|
||||
|
||||
@@ -617,10 +681,18 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
}
|
||||
dev->ems_pages = (dev->ems_size << 10) / EMS_PGSIZE;
|
||||
|
||||
if (dev->regs[REG_RB7] & RB7_EMSEN)
|
||||
for (i = 0; i < EMS_MAXPAGE; i++)
|
||||
ems_recalc(dev, &dev->ems[i]);
|
||||
|
||||
if (dev->regs[REG_RB7] & RB7_EMSEN) {
|
||||
neat_log("NEAT: EMS %iKB (%i pages)\n",
|
||||
dev->ems_size, dev->ems_pages);
|
||||
}
|
||||
|
||||
mem_a20_key = val & RB12_GA20;
|
||||
mem_a20_recalc();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -629,6 +701,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -646,8 +719,10 @@ neat_read(uint16_t port, void *priv)
|
||||
break;
|
||||
|
||||
case 0x23:
|
||||
if ((dev->indx >= 0x60) && (dev->indx <= 0x6f))
|
||||
if ((dev->indx >= 0x60) && (dev->indx <= 0x6e))
|
||||
ret = dev->regs[dev->indx];
|
||||
else if (dev->indx == 0x6f)
|
||||
ret = (dev->regs[dev->indx] & 0xfd) | (mem_a20_key & 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -674,16 +749,50 @@ neat_init(UNUSED(const device_t *info))
|
||||
{
|
||||
neat_t *dev;
|
||||
uint8_t dram_mode = 0;
|
||||
uint8_t i;
|
||||
uint8_t j;
|
||||
|
||||
/* Create an instance. */
|
||||
dev = (neat_t *) malloc(sizeof(neat_t));
|
||||
memset(dev, 0x00, sizeof(neat_t));
|
||||
|
||||
/* Get configured I/O address. */
|
||||
j = (dev->regs[REG_RB9] & RB9_BASE) >> RB9_BASE_SH;
|
||||
dev->ems_base = 0x0208 + (0x10 * j);
|
||||
|
||||
/* Get configured frame address. */
|
||||
j = (dev->regs[REG_RB9] & RB9_FRAME) >> RB9_FRAME_SH;
|
||||
dev->ems_frame = 0xc0000 + (EMS_PGSIZE * j);
|
||||
|
||||
mem_mapping_disable(&ram_mid_mapping);
|
||||
|
||||
/*
|
||||
* For each supported page (we can have a maximum of 4),
|
||||
* create, initialize and disable the mappings, and set
|
||||
* up the I/O control handler.
|
||||
*/
|
||||
for (uint8_t i = 0; i < EMS_MAXPAGE; i++) {
|
||||
/* Create and initialize a page mapping. */
|
||||
mem_mapping_add(&dev->ems[i].mapping,
|
||||
dev->ems_frame + (EMS_PGSIZE * i), EMS_PGSIZE,
|
||||
ems_readb, ems_readw, NULL,
|
||||
ems_writeb, ems_writew, NULL,
|
||||
ram, MEM_MAPPING_INTERNAL,
|
||||
&(dev->ems[i]));
|
||||
|
||||
/* Disable for now. */
|
||||
mem_mapping_disable(&dev->ems[i].mapping);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 32; i++) {
|
||||
dev->shadow[i].virt_base = dev->shadow[i].phys_base =
|
||||
(i * EMS_PGSIZE) + 0x00080000;
|
||||
dev->shadow[i].enabled = 1;
|
||||
}
|
||||
|
||||
/* Initialize some of the registers to specific defaults. */
|
||||
for (i = REG_RA0; i <= REG_RB11; i++) {
|
||||
for (uint8_t i = REG_RA0; i <= REG_RB12; i++) {
|
||||
dev->indx = i;
|
||||
neat_write(0x0023, 0x00, dev);
|
||||
neat_write(0x0023, defaults[i & REG_MASK], dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user