- Recent changes in vax_watch.c changed the input parameter from a physical address to a register address within the watch chip. - vax630_sysdev.c called the older wtc_wr() with the new parameter, but the length argument has been removed. - The watch chip never starts as valid. Make it valid when the TODR is attached (i.e. reflecting a connected battery). - 64 bytes of bus addresses for the watch chip can sometimes be dispatched to wtc_rd() and wtc_wr(). Make sure that reasonable memory is always referenced for all potential accesses. - restore vax8200 to makefile which got lost in a prior merge.
558 lines
16 KiB
C
558 lines
16 KiB
C
/* vax4xx_stddev.c: KA4xx standard devices
|
|
|
|
Copyright (c) 2019, Matt Burke
|
|
This module incorporates code from SimH, Copyright (c) 1998-2008, Robert M Supnik
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
copy of this software and associated documentation files (the "Software"),
|
|
to deal in the Software without restriction, including without limitation
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
THE AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name(s) of the author(s) shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from the author(s).
|
|
|
|
rom bootstrap ROM (no registers)
|
|
nvr non-volatile ROM (no registers)
|
|
or option ROMs (no registers)
|
|
clk 100Hz and TODR clock
|
|
*/
|
|
|
|
#include "vax_defs.h"
|
|
|
|
#define UNIT_V_NODELAY (UNIT_V_UF + 0) /* ROM access equal to RAM access */
|
|
#define UNIT_NODELAY (1u << UNIT_V_NODELAY)
|
|
|
|
#define CLKCSR_IMP (CSR_IE) /* real-time clock */
|
|
#define CLKCSR_RW (CSR_IE)
|
|
#define CLK_DELAY 5000 /* 100 Hz */
|
|
#define TMXR_MULT 1 /* 100 Hz */
|
|
|
|
uint32 *rom = NULL; /* boot ROM */
|
|
uint32 *nvr = NULL; /* non-volatile mem */
|
|
int32 clk_csr = 0; /* control/status */
|
|
int32 clk_tps = 100; /* ticks/second */
|
|
int32 tmr_int = 0; /* interrupt */
|
|
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
|
|
int32 tmr_poll = CLK_DELAY; /* pgm timer poll */
|
|
|
|
t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
|
|
t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);
|
|
t_stat rom_reset (DEVICE *dptr);
|
|
t_stat rom_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
|
const char *rom_description (DEVICE *dptr);
|
|
t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw);
|
|
t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw);
|
|
t_stat nvr_reset (DEVICE *dptr);
|
|
t_stat nvr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
|
t_stat nvr_attach (UNIT *uptr, CONST char *cptr);
|
|
t_stat nvr_detach (UNIT *uptr);
|
|
const char *nvr_description (DEVICE *dptr);
|
|
t_stat or_reset (DEVICE *dptr);
|
|
t_stat or_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
|
const char *or_description (DEVICE *dptr);
|
|
t_stat clk_svc (UNIT *uptr);
|
|
t_stat clk_reset (DEVICE *dptr);
|
|
const char *clk_description (DEVICE *dptr);
|
|
|
|
extern int32 sysd_hlt_enb (void);
|
|
|
|
/* ROM data structures
|
|
|
|
rom_dev ROM device descriptor
|
|
rom_unit ROM units
|
|
rom_reg ROM register list
|
|
*/
|
|
|
|
UNIT rom_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK, ROMSIZE) };
|
|
|
|
REG rom_reg[] = {
|
|
{ NULL }
|
|
};
|
|
|
|
MTAB rom_mod[] = {
|
|
{ UNIT_NODELAY, UNIT_NODELAY, "fast access", "NODELAY", NULL, NULL, NULL, "Disable calibrated ROM access speed" },
|
|
{ UNIT_NODELAY, 0, "1usec calibrated access", "DELAY", NULL, NULL, NULL, "Enable calibrated ROM access speed" },
|
|
{ 0 }
|
|
};
|
|
|
|
DEVICE rom_dev = {
|
|
"ROM", &rom_unit, rom_reg, rom_mod,
|
|
1, 16, ROMAWIDTH, 4, 16, 32,
|
|
&rom_ex, &rom_dep, &rom_reset,
|
|
NULL, NULL, NULL,
|
|
NULL, 0, 0, NULL, NULL, NULL, &rom_help, NULL, NULL,
|
|
&rom_description
|
|
};
|
|
|
|
/* NVR data structures
|
|
|
|
nvr_dev NVR device descriptor
|
|
nvr_unit NVR units
|
|
nvr_reg NVR register list
|
|
*/
|
|
|
|
UNIT nvr_unit =
|
|
{ UDATA (NULL, UNIT_FIX+UNIT_BINK, NVRSIZE) };
|
|
|
|
REG nvr_reg[] = {
|
|
{ NULL }
|
|
};
|
|
|
|
DEVICE nvr_dev = {
|
|
"NVR", &nvr_unit, nvr_reg, NULL,
|
|
1, 16, NVRAWIDTH, 4, 16, 32,
|
|
&nvr_ex, &nvr_dep, &nvr_reset,
|
|
NULL, &nvr_attach, &nvr_detach,
|
|
NULL, 0, 0, NULL, NULL, NULL, &nvr_help, NULL, NULL,
|
|
&nvr_description
|
|
};
|
|
|
|
/* OR data structures
|
|
|
|
or_dev OR device descriptor
|
|
or_unit OR unit descriptor
|
|
or_reg OR register list
|
|
*/
|
|
|
|
UNIT or_unit[] = {
|
|
{ UDATA (NULL, UNIT_FIX+UNIT_RO+UNIT_BINK, ORSIZE) },
|
|
{ UDATA (NULL, UNIT_FIX+UNIT_RO+UNIT_BINK, ORSIZE) },
|
|
{ UDATA (NULL, UNIT_FIX+UNIT_RO+UNIT_BINK, ORSIZE) },
|
|
{ UDATA (NULL, UNIT_FIX+UNIT_RO+UNIT_BINK, ORSIZE) }
|
|
};
|
|
|
|
REG or_reg[] = {
|
|
{ NULL }
|
|
};
|
|
|
|
DEVICE or_dev = {
|
|
"OR", or_unit, or_reg, NULL,
|
|
OR_COUNT, 16, ORAWIDTH, 4, 16, 32,
|
|
NULL, NULL, &or_reset,
|
|
NULL, NULL, NULL,
|
|
NULL, 0, 0, NULL, NULL, NULL, &or_help, NULL, NULL,
|
|
&or_description
|
|
};
|
|
|
|
/* CLK data structures
|
|
|
|
clk_dev CLK device descriptor
|
|
clk_unit CLK unit descriptor
|
|
clk_reg CLK register list
|
|
*/
|
|
|
|
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), CLK_DELAY };
|
|
|
|
REG clk_reg[] = {
|
|
{ HRDATAD (CSR, clk_csr, 16, "control/status register") },
|
|
{ FLDATAD (INT, tmr_int, 0, "interrupt request") },
|
|
{ FLDATAD (IE, clk_csr, CSR_V_IE, "interrupt enable flag (CSR<6>)") },
|
|
{ DRDATAD (TIME, clk_unit.wait, 24, "initial poll interval"), REG_NZ + PV_LEFT },
|
|
{ DRDATAD (POLL, tmr_poll, 24, "calibrated poll interval"), REG_NZ + PV_LEFT + REG_HRO },
|
|
{ DRDATAD (TPS, clk_tps, 8, "ticks per second (100)"), REG_NZ + PV_LEFT },
|
|
#if defined (SIM_ASYNCH_IO)
|
|
{ DRDATAD (ASYNCH, sim_asynch_enabled, 1, "asynch I/O enabled flag"), PV_LEFT },
|
|
{ DRDATAD (LATENCY, sim_asynch_latency, 32, "desired asynch interrupt latency"), PV_LEFT },
|
|
{ DRDATAD (INST_LATENCY, sim_asynch_inst_latency, 32, "calibrated instruction latency"), PV_LEFT },
|
|
#endif
|
|
{ NULL }
|
|
};
|
|
|
|
DEVICE clk_dev = {
|
|
"CLK", &clk_unit, clk_reg, NULL,
|
|
1, 0, 0, 0, 0, 0,
|
|
NULL, NULL, &clk_reset,
|
|
NULL, NULL, NULL,
|
|
NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&clk_description
|
|
};
|
|
|
|
/* ROM: read only memory - stored in a buffered file
|
|
Register space access routines see ROM twice
|
|
|
|
ROM access has been 'regulated' to about 1Mhz to avoid issues
|
|
with testing the interval timers in self-test. Specifically,
|
|
the VAX boot ROM (ka4xx.bin) contains code which presumes that
|
|
the VAX runs at a particular slower speed when code is running
|
|
from ROM (which is not cached). These assumptions are built
|
|
into instruction based timing loops. As the host platform gets
|
|
much faster than the original VAX, the assumptions embedded in
|
|
these code loops are no longer valid.
|
|
|
|
Code has been added to the ROM implementation to limit CPU speed
|
|
to about 500K instructions per second. This heads off any future
|
|
issues with the embedded timing loops.
|
|
*/
|
|
|
|
int32 rom_rd (int32 pa)
|
|
{
|
|
int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2;
|
|
int32 val = rom[rg];
|
|
|
|
if (rom_unit.flags & UNIT_NODELAY)
|
|
return val;
|
|
|
|
return sim_rom_read_with_delay (val);
|
|
}
|
|
|
|
void rom_wr_B (int32 pa, int32 val)
|
|
{
|
|
int32 rg = ((pa - ROMBASE) & ROMAMASK) >> 2;
|
|
int32 sc = (pa & 3) << 3;
|
|
|
|
rom[rg] = ((val & 0xFF) << sc) | (rom[rg] & ~(0xFF << sc));
|
|
return;
|
|
}
|
|
|
|
/* ROM examine */
|
|
|
|
t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
|
|
{
|
|
uint32 addr = (uint32) exta;
|
|
|
|
if ((vptr == NULL) || (addr & 03))
|
|
return SCPE_ARG;
|
|
if (addr >= ROMSIZE)
|
|
return SCPE_NXM;
|
|
*vptr = rom[addr >> 2];
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* ROM deposit */
|
|
|
|
t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
|
|
{
|
|
uint32 addr = (uint32) exta;
|
|
|
|
if (addr & 03)
|
|
return SCPE_ARG;
|
|
if (addr >= ROMSIZE)
|
|
return SCPE_NXM;
|
|
rom[addr >> 2] = (uint32) val;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* ROM reset */
|
|
|
|
t_stat rom_reset (DEVICE *dptr)
|
|
{
|
|
if (rom == NULL)
|
|
rom = (uint32 *) calloc (ROMSIZE >> 2, sizeof (uint32));
|
|
if (rom == NULL)
|
|
return SCPE_MEM;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat rom_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
|
{
|
|
fprintf (st, "Read-only memory (ROM)\n\n");
|
|
fprintf (st, "The boot ROM consists of a single unit, simulating the 256KB boot ROM. It has\n");
|
|
fprintf (st, "no registers. The boot ROM is loaded with a binary byte stream using the \n");
|
|
fprintf (st, "LOAD -r command:\n\n");
|
|
fprintf (st, " LOAD -r KA410.BIN load ROM image KA410.BIN\n\n");
|
|
fprintf (st, "When the simulator starts running (via the BOOT command), if the ROM has\n");
|
|
fprintf (st, "not yet been loaded, an attempt will be made to automatically load the\n");
|
|
fprintf (st, "ROM image from the file ka410.bin in the current working directory.\n");
|
|
fprintf (st, "If that load attempt fails, then a copy of the missing ROM file is\n");
|
|
fprintf (st, "written to the current directory and the load attempt is retried.\n\n");
|
|
fprintf (st, "ROM accesses a use a calibrated delay that slows ROM-based execution to\n");
|
|
fprintf (st, "about 500K instructions per second. This delay is required to make the\n");
|
|
fprintf (st, "power-up self-test routines run correctly on very fast hosts.\n");
|
|
fprint_set_help (st, dptr);
|
|
return SCPE_OK;
|
|
}
|
|
|
|
const char *rom_description (DEVICE *dptr)
|
|
{
|
|
return "read-only memory";
|
|
}
|
|
|
|
/* NVR: non-volatile RAM - stored in a buffered file */
|
|
|
|
int32 nvr_rd (int32 pa)
|
|
{
|
|
int32 rg = (pa - NVRBASE) >> 2;
|
|
int32 val;
|
|
|
|
if (rg < 14) /* watch chip */
|
|
val = wtc_rd (rg);
|
|
else
|
|
val = nvr[rg];
|
|
return (val << 2);
|
|
}
|
|
|
|
void nvr_wr (int32 pa, int32 val, int32 lnt)
|
|
{
|
|
int32 rg = (pa - NVRBASE) >> 2;
|
|
val = val >> 2;
|
|
if (rg < 14) /* watch chip */
|
|
wtc_wr (rg, val);
|
|
else {
|
|
int32 sc = (pa & 3) << 3; /* merge */
|
|
int32 mask = 0xFF;
|
|
nvr[rg] = ((val & mask) << sc) | (nvr[rg] & ~(mask << sc));
|
|
}
|
|
}
|
|
|
|
/* NVR examine */
|
|
|
|
t_stat nvr_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw)
|
|
{
|
|
uint32 addr = (uint32) exta;
|
|
|
|
if ((vptr == NULL) || (addr & 03))
|
|
return SCPE_ARG;
|
|
if (addr >= NVRSIZE)
|
|
return SCPE_NXM;
|
|
*vptr = nvr[addr >> 2];
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* NVR deposit */
|
|
|
|
t_stat nvr_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw)
|
|
{
|
|
uint32 addr = (uint32) exta;
|
|
|
|
if (addr & 03)
|
|
return SCPE_ARG;
|
|
if (addr >= NVRSIZE)
|
|
return SCPE_NXM;
|
|
nvr[addr >> 2] = (uint32) val;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* NVR reset */
|
|
|
|
t_stat nvr_reset (DEVICE *dptr)
|
|
{
|
|
if (nvr == NULL) {
|
|
nvr = (uint32 *) calloc (NVRSIZE >> 2, sizeof (uint32));
|
|
nvr_unit.filebuf = nvr;
|
|
}
|
|
if (nvr == NULL)
|
|
return SCPE_MEM;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat nvr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
|
{
|
|
fprintf (st, "Non-volatile Memory (NVR)\n\n");
|
|
fprintf (st, "The NVR simulates %d bytes of battery-backed up memory.\n", NVRSIZE);
|
|
fprintf (st, "When the simulator starts, NVR is cleared to 0, and the battery-low indicator\n");
|
|
fprintf (st, "is set. Alternately, NVR can be attached to a file. This allows the NVR\n");
|
|
fprintf (st, "state to be preserved across simulator runs. Successfully attaching an NVR\n");
|
|
fprintf (st, "image clears the battery-low indicator.\n\n");
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* NVR attach */
|
|
|
|
t_stat nvr_attach (UNIT *uptr, CONST char *cptr)
|
|
{
|
|
t_stat r;
|
|
|
|
uptr->flags = uptr->flags | (UNIT_ATTABLE | UNIT_BUFABLE);
|
|
r = attach_unit (uptr, cptr);
|
|
if (r != SCPE_OK)
|
|
uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
|
|
else {
|
|
uptr->hwmark = (uint32) uptr->capac;
|
|
wtc_set_valid ();
|
|
}
|
|
return r;
|
|
}
|
|
|
|
/* NVR detach */
|
|
|
|
t_stat nvr_detach (UNIT *uptr)
|
|
{
|
|
t_stat r;
|
|
|
|
r = detach_unit (uptr);
|
|
if ((uptr->flags & UNIT_ATT) == 0) {
|
|
uptr->flags = uptr->flags & ~(UNIT_ATTABLE | UNIT_BUFABLE);
|
|
wtc_set_invalid ();
|
|
}
|
|
return r;
|
|
}
|
|
|
|
const char *nvr_description (DEVICE *dptr)
|
|
{
|
|
return "non-volatile memory";
|
|
}
|
|
|
|
/* OR routines
|
|
|
|
or_rd I/O page read
|
|
or_reset process reset
|
|
*/
|
|
|
|
int32 or_rd (int32 pa)
|
|
{
|
|
uint32 off = (pa - ORBASE); /* offset from start of option roms */
|
|
uint32 rn = ((off >> 18) & 0x3); /* rom number (0 - 3) */
|
|
UNIT *uptr = &or_dev.units[rn]; /* get unit */
|
|
uint8 *opr = (uint8*) uptr->filebuf;
|
|
int32 data = 0;
|
|
uint32 rg;
|
|
|
|
if ((uptr->flags & UNIT_ATT) && (opr != NULL)) {
|
|
switch (opr[0]) { /* number of ROM chips */
|
|
case 1:
|
|
rg = (off >> 2) & (uptr->capac - 1);
|
|
data = (0xFFFFFF00 | (opr[rg] & 0xFF));
|
|
return sim_rom_read_with_delay (data);
|
|
|
|
case 2:
|
|
rg = (off >> 1) & (uptr->capac - 1);
|
|
data = data | opr[rg++];
|
|
data = data | (opr[rg] << 8);
|
|
data = (0xFFFF0000 | data);
|
|
return sim_rom_read_with_delay (data);
|
|
|
|
case 4:
|
|
rg = off & (uptr->capac - 1);
|
|
data = data | opr[rg++];
|
|
data = data | (opr[rg++] << 8);
|
|
data = data | (opr[rg++] << 16);
|
|
data = data | (opr[rg++] << 24);
|
|
return sim_rom_read_with_delay (data);
|
|
}
|
|
}
|
|
return sim_rom_read_with_delay (0xFFFFFFFF);
|
|
}
|
|
|
|
t_stat or_reset (DEVICE *dptr)
|
|
{
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat or_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
|
{
|
|
fprintf (st, "Option ROMs (OR)\n\n");
|
|
fprintf (st, "The OR simulates the read only memory present on option boards.\n");
|
|
fprintf (st, "These ROMs contain the self-test code that is called by the main\n");
|
|
fprintf (st, "ROM during system power up. The system uses these ROMs to determine\n");
|
|
fprintf (st, "which option boards are present.\n");
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat or_map (uint32 index, uint8 *rom, t_addr size)
|
|
{
|
|
UNIT *uptr = &or_unit[index];
|
|
uptr->filebuf = (void *)rom;
|
|
uptr->capac = size;
|
|
uptr->flags |= UNIT_ATT;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
t_stat or_unmap (uint32 index)
|
|
{
|
|
UNIT *uptr = &or_unit[index];
|
|
uptr->filebuf = NULL;
|
|
uptr->capac = 0;
|
|
uptr->flags &= ~UNIT_ATT;
|
|
return SCPE_OK;
|
|
}
|
|
|
|
const char *or_description (DEVICE *dptr)
|
|
{
|
|
return "option ROMs";
|
|
}
|
|
|
|
/* Clock MxPR routines
|
|
|
|
iccs_rd/wr interval timer
|
|
*/
|
|
|
|
int32 iccs_rd (void)
|
|
{
|
|
return (clk_csr & CLKCSR_IMP);
|
|
}
|
|
|
|
void iccs_wr (int32 data)
|
|
{
|
|
if ((data & CSR_IE) == 0)
|
|
tmr_int = 0;
|
|
if (data & CSR_DONE)
|
|
sim_rtcn_tick_ack (20, TMR_CLK);
|
|
clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
|
|
return;
|
|
}
|
|
|
|
/* Clock routines
|
|
|
|
clk_svc process event (clock tick)
|
|
clk_reset process reset
|
|
clk_description return device description
|
|
*/
|
|
|
|
t_stat clk_svc (UNIT *uptr)
|
|
{
|
|
int32 t;
|
|
|
|
if (clk_csr & CSR_IE)
|
|
tmr_int = 1;
|
|
t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
|
|
sim_activate_after (uptr, 1000000/clk_tps); /* reactivate unit */
|
|
tmr_poll = t; /* set tmr poll */
|
|
tmxr_poll = t * TMXR_MULT; /* set mux poll */
|
|
AIO_SET_INTERRUPT_LATENCY(tmr_poll*clk_tps); /* set interrrupt latency */
|
|
return SCPE_OK;
|
|
}
|
|
|
|
/* Reset routine */
|
|
|
|
t_stat clk_reset (DEVICE *dptr)
|
|
{
|
|
int32 t;
|
|
|
|
clk_csr = 0;
|
|
tmr_int = 0;
|
|
t = sim_rtcn_init_unit (&clk_unit, clk_unit.wait, TMR_CLK);/* init 100Hz timer */
|
|
sim_activate_after (&clk_unit, 1000000/clk_tps); /* activate 100Hz unit */
|
|
tmr_poll = t; /* set tmr poll */
|
|
tmxr_poll = t * TMXR_MULT; /* set mux poll */
|
|
return SCPE_OK;
|
|
}
|
|
|
|
const char *clk_description (DEVICE *dptr)
|
|
{
|
|
return "100hz clock tick";
|
|
}
|
|
|
|
/* Dummy I/O space functions */
|
|
|
|
int32 ReadIO (uint32 pa, int32 lnt)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void WriteIO (uint32 pa, int32 val, int32 lnt)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int32 ReadIOU (uint32 pa, int32 lnt)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void WriteIOU (uint32 pa, int32 val, int32 lnt)
|
|
{
|
|
return;
|
|
}
|