MZ700 and MZ1500 updates
This commit is contained in:
BIN
software/FusionX/bin/k64fcpu
vendored
BIN
software/FusionX/bin/k64fcpu
vendored
Binary file not shown.
BIN
software/FusionX/bin/sharpbiter
vendored
BIN
software/FusionX/bin/sharpbiter
vendored
Binary file not shown.
BIN
software/FusionX/bin/z80ctrl
vendored
BIN
software/FusionX/bin/z80ctrl
vendored
Binary file not shown.
BIN
software/FusionX/modules/ttymzdrv.ko
vendored
BIN
software/FusionX/modules/ttymzdrv.ko
vendored
Binary file not shown.
BIN
software/FusionX/modules/z80drv.ko
vendored
BIN
software/FusionX/modules/z80drv.ko
vendored
Binary file not shown.
@@ -14,6 +14,7 @@
|
||||
// History: v1.0 Feb 2023 - Initial write of the Sharp MZ series hardware interface software.
|
||||
// v1.01 Mar 2023 - Bug fixes and additional ESC sequence processing.
|
||||
// v1.02 May 2023 - Updates to accommodate MZ-1500 host.
|
||||
// v1.2 Jul 2023 - Updates to MZ-1500 to display lower case chars and bug fixes.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
@@ -2505,26 +2506,26 @@ uint8_t mzInitMBHardware(void)
|
||||
READ_HARDWARE_INIT(1, MBADDR_SCLDSP); // Hardware scroll needs to be reset.
|
||||
|
||||
// Disable the hardware sound output.
|
||||
WRITE_HARDWARE(0, MBADDR_SUNDG, 0x00); // Sound could be enabled on start, disable it.
|
||||
WRITE_HARDWARE(1, MBADDR_SUNDG, 0x00); // Sound could be enabled on start, disable it.
|
||||
|
||||
#if (TARGET_HOST_MZ1500 == 1)
|
||||
for(idx=1; idx < 4; idx++)
|
||||
{
|
||||
WRITE_HARDWARE(0, IO_ADDR_E5, 0x00); // Select the PCG Bank.
|
||||
WRITE_HARDWARE_IO(1, IO_ADDR_E5, 0x00); // Select the PCG Bank.
|
||||
for(idx2=0xD000; idx2 < 0xF000; idx2++)
|
||||
{
|
||||
WRITE_HARDWARE(0, idx2, 0x00); // Zero the PCG memory in the bank.
|
||||
WRITE_HARDWARE(1, idx2, 0x00); // Zero the PCG memory in the bank.
|
||||
}
|
||||
}
|
||||
WRITE_HARDWARE(0, IO_ADDR_E6, 0x00); // Deselect the PCG Bank.
|
||||
WRITE_HARDWARE(0, IO_PCG_PRIO, 0x00); // Set text as priority.
|
||||
WRITE_HARDWARE_IO(1, IO_ADDR_E6, 0x00); // Deselect the PCG Bank.
|
||||
WRITE_HARDWARE_IO(1, IO_PCG_PRIO, 0x00); // Set text as priority.
|
||||
for(idx=0x11; idx < 0x90; idx+=0x11)
|
||||
{
|
||||
WRITE_HARDWARE(0, IO_PALETTE, idx); // Setup palettes.
|
||||
WRITE_HARDWARE_IO(1, IO_PALETTE, idx); // Setup palettes.
|
||||
}
|
||||
for(idx=0x9F; idx <- 0xFF; idx+=0x20)
|
||||
for(idx=0x9F; idx <= 0xFF; idx+=0x20)
|
||||
{
|
||||
WRITE_HARDWARE(0, IO_PSG_BOTH, idx); // Setup PSG.
|
||||
WRITE_HARDWARE_IO(1, IO_PSG_BOTH, idx); // Setup PSG.
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
28
software/FusionX/src/ttymz/sharpmz.h
vendored
28
software/FusionX/src/ttymz/sharpmz.h
vendored
@@ -14,6 +14,7 @@
|
||||
// History: v1.0 Feb 2023 - Initial write of the Sharp MZ series hardware interface software.
|
||||
// v1.01 Mar 2023 - Bug fixes and additional ESC sequence processing.
|
||||
// v1.02 May 2023 - Updates to accommodate MZ-1500 host.
|
||||
// v1.2 Jul 2023 - Fixed MZ-1500 ATB Display of lower case characters.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
@@ -369,6 +370,33 @@
|
||||
}
|
||||
#define READ_KEYB_INIT() READ_HARDWARE_IO_INIT(0, MBADDR_PIOB)
|
||||
#define READ_KEYB() READ_HARDWARE_IO()
|
||||
#elif (TARGET_HOST_MZ1500 ==1)
|
||||
#define ENABLE_VIDEO() {}
|
||||
#define DISABLE_VIDEO() {}
|
||||
#define WRITE_VRAM_CHAR(__addr__,__data__,__xlat__) if(__xlat__ == 1)\
|
||||
{\
|
||||
if(islower(__data__))\
|
||||
{\
|
||||
WRITE_HARDWARE(0,__addr__,(dispCodeMap[(int)(__data__)].dispCode & 0x7F));\
|
||||
READ_HARDWARE_INIT(0,(__addr__+0x800));\
|
||||
WRITE_HARDWARE(0,(__addr__+0x800),(READ_HARDWARE() | 0x80));\
|
||||
} else\
|
||||
{\
|
||||
WRITE_HARDWARE(0,__addr__,dispCodeMap[(int)(__data__)].dispCode);\
|
||||
READ_HARDWARE_INIT(0,(__addr__+0x800));\
|
||||
WRITE_HARDWARE(0,(__addr__+0x800),(READ_HARDWARE() & 0x7F));\
|
||||
}\
|
||||
} else\
|
||||
{\
|
||||
WRITE_HARDWARE(0,__addr__, __data__);\
|
||||
}
|
||||
#define WRITE_VRAM_ATTRIBUTE(__addr__,__data__) {\
|
||||
READ_HARDWARE_INIT(0,(__addr__));\
|
||||
WRITE_HARDWARE(0,__addr__,((READ_HARDWARE() & 0x80) | (__data__ & 0x7F)));\
|
||||
}
|
||||
#define WRITE_KEYB_STROBE(__data__) WRITE_HARDWARE(0, MBADDR_KEYPA, __data__)
|
||||
#define READ_KEYB_INIT() READ_HARDWARE_INIT(0, MBADDR_KEYPB)
|
||||
#define READ_KEYB() READ_HARDWARE()
|
||||
#else
|
||||
#define ENABLE_VIDEO() {}
|
||||
#define DISABLE_VIDEO() {}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
// being the TTY will continue to run within the mirrored framebuffer
|
||||
// and when reselected, refresh the hardware screen.
|
||||
// Apr 2023 - v1.1 Updated to include MZ-2000 mode.
|
||||
// Jul 2023 - v1.2 Updates and bug fixes.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
@@ -864,7 +865,7 @@ static int __init ttymz_init(void)
|
||||
mzInit();
|
||||
|
||||
// Sign on.
|
||||
sprintf(buf, "%s %s", DRIVER_DESCRIPTION, DRIVER_VERSION); mzWriteString(0, 0, buf, -1);
|
||||
sprintf(buf, "%s %s", DRIVER_TITLE, DRIVER_VERSION); mzWriteString(0, 0, buf, -1);
|
||||
sprintf(buf, "%s %s\n", DRIVER_COPYRIGHT, DRIVER_AUTHOR); mzWriteString(0, 1, buf, -1);
|
||||
|
||||
pr_info(DRIVER_DESCRIPTION " " DRIVER_VERSION "\n");
|
||||
|
||||
22
software/FusionX/src/ttymz/ttymz.h
vendored
22
software/FusionX/src/ttymz/ttymz.h
vendored
@@ -12,6 +12,7 @@
|
||||
//
|
||||
// History: Feb 2023 - v1.0 Initial write of the Sharp MZ tty driver software.
|
||||
// Apr 2023 - v1.1 Updated to include MZ-2000 mode.
|
||||
// Jul 2023 - v1.2 Updates and bug fixes.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
@@ -34,15 +35,28 @@
|
||||
|
||||
// Constants.
|
||||
#define DRIVER_LICENSE "GPL"
|
||||
#define DRIVER_AUTHOR "Philip D Smart"
|
||||
#define DRIVER_AUTHOR "P.D.Smart"
|
||||
#define DRIVER_DESCRIPTION "Sharp MZ TTY Driver"
|
||||
#define DRIVER_VERSION "v1.1"
|
||||
#define DRIVER_VERSION_DATE "Apr 2023"
|
||||
#define DRIVER_COPYRIGHT "(C) 2018-2023"
|
||||
#define DRIVER_VERSION "v1.2"
|
||||
#define DRIVER_VERSION_DATE "July 2023"
|
||||
#define DRIVER_COPYRIGHT "(C) 2018-23"
|
||||
#define DEVICE_NAME "ttymz"
|
||||
#define DRIVER_NAME "SharpMZ_tty"
|
||||
#define DEBUG_ENABLED 0 // 0 = disabled, 1 .. debug level.
|
||||
#define ARBITER_NAME "sharpbiter"
|
||||
#if (TARGET_HOST_MZ80A == 1)
|
||||
#define DRIVER_TITLE "Sharp MZ-80A TTY"
|
||||
#elif (TARGET_HOST_MZ700 == 1)
|
||||
#define DRIVER_TITLE "Sharp MZ-700 TTY"
|
||||
#elif (TARGET_HOST_MZ1500 == 1)
|
||||
#define DRIVER_TITLE "Sharp MZ-1500 TTY"
|
||||
#elif (TARGET_HOST_MZ2000 == 1)
|
||||
#define DRIVER_TITLE "Sharp MZ-2000 TTY"
|
||||
#elif (TARGET_HOST_PCW == 1)
|
||||
#define DRIVER_TITLE "Amstrad PCW-8XXX TTY"
|
||||
#else
|
||||
#define DRIVER_MODEL "not defined"
|
||||
#endif
|
||||
|
||||
// Fake UART values
|
||||
#define MCR_DTR 0x01
|
||||
|
||||
@@ -128,7 +128,7 @@ enum CTRL_COMMANDS {
|
||||
static t_Z80Ctrl *Z80Ctrl = NULL;
|
||||
static uint8_t *Z80RAM = NULL;
|
||||
static uint8_t *Z80ROM = NULL;
|
||||
static uint32_t *Z80PAGE[MEMORY_MODES];
|
||||
static uint32_t *Z80PAGE[MEMORY_MODES+MEMORY_SUB_MODES];
|
||||
static uint8_t memoryPage = 0;
|
||||
|
||||
// Method to obtain and return the output screen width.
|
||||
@@ -1038,7 +1038,7 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
// Loop through all the memory mapping pages, each page specifies a 64K mapping block, all memory accesses go through this map.
|
||||
for(idx=0; idx < MEMORY_MODES; idx++)
|
||||
for(idx=0; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
|
||||
{
|
||||
// Try and bind the page, if it doesnt exist, then the pointer will be NULL so it wont be used.
|
||||
Z80PAGE[idx] = (uint32_t *)mmap(0, ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + (0x1000*(idx+1))), PROT_READ | PROT_WRITE, MAP_SHARED, fdZ80, 0);
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
// a vanilla Z80 or customisations for hosts pulled in.
|
||||
// Apr 2023 - v1.4.1 Completed MZ2000 mode to work with arbiter and ttymz.
|
||||
// May 2023 - v1.5 Added MZ1500 modes.
|
||||
// Jul 2023 - v1.6 Updated MZ-700 code, adding sub-memory maps to increase page mapping
|
||||
// speed specifically to enable reliable tape read/write.
|
||||
//
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
@@ -478,12 +480,12 @@ static zuint8 z80_read(void *context, zuint16 address)
|
||||
Z_UNUSED(context)
|
||||
|
||||
// Only read if the address is in physical RAM.
|
||||
#if(TARGET_HOST_PCW == 0)
|
||||
if(isPhysical(address))
|
||||
#elif(TARGET_HOST_MZ1500 == 1)
|
||||
#if(TARGET_HOST_MZ1500 == 1)
|
||||
// MZ-1500 take into account PCG being active, always go to hardware when active. Cannot use the map because
|
||||
// this can change during PCG active mode and must be reflected when PCG is deactivated.
|
||||
if(isPhysicalHW(address) || (Z80Ctrl->pcgMode == 1 && address >= 0xD000))
|
||||
if(isPhysical(address) || (Z80Ctrl->pcgMode == 1 && address >= 0xD000))
|
||||
#elif(TARGET_HOST_PCW == 0)
|
||||
if(isPhysical(address))
|
||||
#else
|
||||
if(isPhysicalHW(address))
|
||||
#endif
|
||||
@@ -1267,10 +1269,10 @@ static int z80drv_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
}
|
||||
// Another one, as the memory bank page maps are allocated dynamically, need to send a size which indicates which memory block to map. This is done by the size of a memory map
|
||||
// added to it the map slot as 0x1000 per slot.
|
||||
else if(size >= ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + 0x1000) && size < ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + (MEMORY_MODES * 0x1000)))
|
||||
else if(size >= ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + 0x1000) && size < ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + ((MEMORY_MODES+MEMORY_SUB_MODES) * 0x1000)))
|
||||
{
|
||||
// Loop through all the memory page slots, if active and the size is in range, then map the memory to user space.
|
||||
for(idx=0; idx < MEMORY_MODES; idx++)
|
||||
for(idx=0; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
|
||||
{
|
||||
if(size >= ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + ((idx+1)*0x1000)) && size < ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + ((idx+2) * 0x1000)))
|
||||
{
|
||||
@@ -1665,6 +1667,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
|
||||
case 2:
|
||||
Z80Ctrl->cpuGovernorDelayROM = ROM_DELAY_X2;
|
||||
Z80Ctrl->cpuGovernorDelayRAM = RAM_DELAY_X2;
|
||||
pr_info("ROM:%d, RAM:%d\n", Z80Ctrl->cpuGovernorDelayROM, Z80Ctrl->cpuGovernorDelayRAM);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
@@ -2092,7 +2095,7 @@ static int __init ModuleInit(void)
|
||||
}
|
||||
// Default memory mode is 0, ie. Original. Additional modes may be used by drivers such as the tzpu driver.
|
||||
Z80Ctrl->memoryMode = 0;
|
||||
for(idx=0; idx < MEMORY_MODES; idx++)
|
||||
for(idx=0; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
|
||||
{
|
||||
(Z80Ctrl->page[idx]) = NULL;
|
||||
}
|
||||
@@ -2202,7 +2205,7 @@ static void __exit ModuleExit(void)
|
||||
}
|
||||
|
||||
// Return the memory used for the Z80 'virtual memory' and control variables.
|
||||
for(idx=0; idx < MEMORY_MODES; idx++)
|
||||
for(idx=0; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
|
||||
{
|
||||
if(Z80Ctrl->page[idx] != NULL)
|
||||
{
|
||||
|
||||
21
software/FusionX/src/z80drv/src/z80driver.h
vendored
21
software/FusionX/src/z80drv/src/z80driver.h
vendored
@@ -17,6 +17,8 @@
|
||||
// Feb 2023 - v1.2 Added RFS virtual driver.
|
||||
// Apr 2023 - v1.4.1 Completed MZ2000 mode to work with arbiter and ttymz.
|
||||
// May 2023 - v1.5 Added MZ1500 modes.
|
||||
// Jul 2023 - v1.6 Updated MZ-700 code, adding sub-memory maps to increase page mapping
|
||||
// speed specifically to enable reliable tape read/write.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
@@ -80,8 +82,8 @@
|
||||
#define DRIVER_LICENSE "GPL"
|
||||
#define DRIVER_AUTHOR "Philip D Smart"
|
||||
#define DRIVER_DESCRIPTION "Z80 CPU Emulator and Hardware Interface Driver"
|
||||
#define DRIVER_VERSION "v1.5"
|
||||
#define DRIVER_VERSION_DATE "May 2023"
|
||||
#define DRIVER_VERSION "v1.6"
|
||||
#define DRIVER_VERSION_DATE "July 2023"
|
||||
#define DRIVER_COPYRIGHT "(C) 2018-2023"
|
||||
#define Z80_VIRTUAL_ROM_SIZE (65536 * 32) // Sized to maximum Kernel contiguous allocation size, 2M which is 4x512K ROMS.
|
||||
#define Z80_VIRTUAL_RAM_SIZE (65536 * 32) // Sized to maximum Kernel contiguous allocation size, 2M.
|
||||
@@ -166,11 +168,11 @@
|
||||
#define INSTRUCTION_DELAY_ROM_112MHZ 8
|
||||
#define INSTRUCTION_DELAY_ROM_224MHZ 4
|
||||
#define INSTRUCTION_DELAY_ROM_448MHZ 1
|
||||
#define INSTRUCTION_DELAY_RAM_3_54MHZ 253
|
||||
#define INSTRUCTION_DELAY_RAM_7MHZ 126
|
||||
#define INSTRUCTION_DELAY_RAM_14MHZ 63
|
||||
#define INSTRUCTION_DELAY_RAM_28MHZ 32
|
||||
#define INSTRUCTION_DELAY_RAM_56MHZ 16
|
||||
#define INSTRUCTION_DELAY_RAM_3_54MHZ 240
|
||||
#define INSTRUCTION_DELAY_RAM_7MHZ 120
|
||||
#define INSTRUCTION_DELAY_RAM_14MHZ 60
|
||||
#define INSTRUCTION_DELAY_RAM_28MHZ 30
|
||||
#define INSTRUCTION_DELAY_RAM_56MHZ 15
|
||||
#define INSTRUCTION_DELAY_RAM_112MHZ 8
|
||||
#define INSTRUCTION_DELAY_RAM_224MHZ 4
|
||||
#define INSTRUCTION_DELAY_RAM_448MHZ 1
|
||||
@@ -599,6 +601,7 @@ enum Z80_INSTRUCTION_DELAY {
|
||||
// The memory page arrays dont check for allocation due to speed, it is assumed a memory mode page has been allocated and defined prior to the memoryMode
|
||||
// variable being set to that page.
|
||||
#define MEMORY_MODES 32 // Maximum number of different memory modes.
|
||||
#define MEMORY_SUB_MODES 6 // Number of possible alternate memory maps for a given memory mode.
|
||||
#define MEMORY_PAGE_SIZE 0x10000 // Total size of directly addressable memory.
|
||||
#define MEMORY_BLOCK_GRANULARITY 0x1 // Any change update MEMORY_BLOCK_SHIFT and mask in MEMORY_BLOCK_MASK
|
||||
#define MEMORY_BLOCK_SHIFT 0
|
||||
@@ -738,10 +741,10 @@ typedef struct {
|
||||
// 16bit Input Address -> map -> Pointer to 24bit memory address + type flag.
|
||||
// -> Pointer+<low bits of address> to 24bit memory address + type flag.
|
||||
//uint32_t page[MEMORY_BLOCK_SLOTS];
|
||||
uint32_t *page[MEMORY_MODES];
|
||||
uint32_t *page[MEMORY_MODES+MEMORY_SUB_MODES];
|
||||
uint32_t shadowPage[MEMORY_BLOCK_SLOTS]; // Shadow page is for manipulation and backup of an existing page.
|
||||
|
||||
// Current memory mode as used by active driver.
|
||||
// Current memory modes as used by an active driver.
|
||||
uint8_t memoryMode;
|
||||
|
||||
// I/O Page map.
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: May 2023 v1.0 - Initial write based on the MZ700 module.
|
||||
// Jul 2023 - v1.6 - Updated MZ-700 code, adding sub-memory maps to increase page mapping
|
||||
// speed specifically to enable reliable tape read/write. Code changes
|
||||
// reflected in MZ-1500 module. Addition of MZ-1R18 emulation.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
@@ -57,6 +60,10 @@
|
||||
// PCW control.
|
||||
typedef struct {
|
||||
uint8_t regCtrl; // Control register.
|
||||
uint8_t loDRAMen; // Lower bank 0000:0FFF DRAM enabled, else monitor.
|
||||
uint8_t hiDRAMen; // Higher bank D000:FFFF DRAM enabled, else memory mapped I/O.
|
||||
uint32_t *ramFileMem; // 64K RamFile memory.
|
||||
uint16_t ramFileAddr; // Address pointer of the MZ-1R18 64K Ram File Board memory.
|
||||
} t_MZ1500Ctrl;
|
||||
|
||||
// RFS Board control.
|
||||
@@ -71,10 +78,14 @@ static t_MZ1500Ctrl MZ1500Ctrl;
|
||||
void mz1500SetupMemory(enum Z80_MEMORY_PROFILE mode)
|
||||
{
|
||||
// Locals.
|
||||
uint8_t subMode;
|
||||
uint32_t idx;
|
||||
|
||||
// Setup defaults.
|
||||
MZ1500Ctrl.regCtrl = 0x00;
|
||||
MZ1500Ctrl.loDRAMen = 0; // Default is monitor ROM is enabled.
|
||||
MZ1500Ctrl.hiDRAMen = 0; // Default is memory mapped I/O enabled.
|
||||
Z80Ctrl->inhibitMode = 0;
|
||||
|
||||
// Setup default mode according to run mode, ie. Physical run or Virtual run.
|
||||
//
|
||||
@@ -145,9 +156,109 @@ void mz1500SetupMemory(enum Z80_MEMORY_PROFILE mode)
|
||||
}
|
||||
}
|
||||
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
|
||||
{
|
||||
if((idx&0x00ff) == 0xEA || (idx&0x00ff) == 0xEB)
|
||||
{
|
||||
Z80Ctrl->iopage[idx] = idx | IO_TYPE_VIRTUAL_HW;
|
||||
} else
|
||||
{
|
||||
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
|
||||
}
|
||||
}
|
||||
// Setup sub-memory pages to enable rapid switch according to memory bank commands.
|
||||
for(subMode=0; subMode < MEMORY_SUB_MODES; subMode++)
|
||||
{
|
||||
if(Z80Ctrl->page[MEMORY_MODES+subMode] == NULL)
|
||||
{
|
||||
#if(DEBUG_ENABLED & 0x01)
|
||||
if(Z80Ctrl->debug >=3) pr_info("Allocating memory sub page:%d\n", subMode);
|
||||
#endif
|
||||
(Z80Ctrl->page[MEMORY_MODES+subMode]) = (uint32_t *)kmalloc((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)), GFP_KERNEL);
|
||||
if ((Z80Ctrl->page[MEMORY_MODES+subMode]) == NULL)
|
||||
{
|
||||
pr_info("z80drv: failed to allocate memory sub mapping page:%d memory!", subMode);
|
||||
}
|
||||
}
|
||||
|
||||
// Duplicate current mode into the sub page prior to setting up specific config.
|
||||
memcpy((uint8_t *)Z80Ctrl->page[MEMORY_MODES+subMode], (uint8_t *)Z80Ctrl->page[0], MEMORY_BLOCK_SLOTS*sizeof(uint32_t));
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + subMode;
|
||||
|
||||
// MZ1500 memory mode switches.
|
||||
//
|
||||
// MZ-1500
|
||||
// |0000:0FFF|1000:CFFF|D000:FFFF
|
||||
// ------------------------------
|
||||
// OUT 0xE0 = |DRAM |DRAM |<last>
|
||||
// OUT 0xE1 = |<last> |DRAM |DRAM
|
||||
// OUT 0xE2 = |MONITOR |DRAM |<last>
|
||||
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE5 = |<last> |DRAM |PCG Enable
|
||||
// OUT 0xE6 = |<last> |DRAM |PCG Disable
|
||||
//
|
||||
// Sub-memory page maps:
|
||||
//
|
||||
// LOW BANK HIGH BANK PAGE MAP
|
||||
// DRAM 0
|
||||
// DRAM MEMORY MAP 1
|
||||
// Inhibit 2
|
||||
// DRAM 3
|
||||
// MONITOR MEMORY MAP 4
|
||||
// Inhibit 5
|
||||
//
|
||||
if(subMode >= 0 && subMode < 3)
|
||||
{
|
||||
// Enable lower 4K block as DRAM
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode >= 3 && subMode < 6)
|
||||
{
|
||||
// Enable lower 4K block as Monitor ROM
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode == 0 || subMode == 3)
|
||||
{
|
||||
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
// MZ-700 mode we only work in first 64K block.
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode == 1 || subMode == 4)
|
||||
{
|
||||
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
|
||||
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
|
||||
}
|
||||
for(idx=0xE000; idx < 0xE800; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
|
||||
}
|
||||
for(idx=0xE800; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode == 2 || subMode == 5)
|
||||
{
|
||||
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
|
||||
|
||||
// Enable refresh as using virtual RAM stops refresh of host DRAM.
|
||||
Z80Ctrl->refreshDRAM = 2;
|
||||
}
|
||||
@@ -195,6 +306,17 @@ void mz1500Init(uint8_t mode)
|
||||
// Reset memory paging to default.
|
||||
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
|
||||
|
||||
#if(DEBUG_ENABLED & 0x01)
|
||||
if(Z80Ctrl->debug >=3) pr_info("Allocating MZ-1R18 memory\n");
|
||||
#endif
|
||||
// Allocate memory for the MZ-1R18 64K Ram File board.
|
||||
MZ1500Ctrl.ramFileMem = (uint32_t *)kmalloc((65536 * sizeof(uint8_t)), GFP_KERNEL);
|
||||
if(MZ1500Ctrl.ramFileMem == NULL)
|
||||
{
|
||||
pr_info("z80drv: failed to allocate MZ-1R18 Ram File memory!");
|
||||
}
|
||||
MZ1500Ctrl.ramFileAddr = 0x0000;
|
||||
|
||||
// Initialise the virtual RAM from the HOST DRAM. This is to maintain compatibility as some applications (in my experience) have
|
||||
// bugs, which Im putting down to not initialising variables. The host DRAM is in a pattern of 0x00..0x00, 0xFF..0xFF repeating
|
||||
// when first powered on.
|
||||
@@ -248,17 +370,17 @@ void mz1500Remove(void)
|
||||
static inline void mz1500DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
|
||||
{
|
||||
// Locals.
|
||||
uint32_t idx;
|
||||
//uint32_t idx;
|
||||
|
||||
// Decoding memory address or I/O address?
|
||||
if(ioFlag == 0)
|
||||
{
|
||||
// #if(DEBUG_ENABLED & 1)
|
||||
// if(Z80Ctrl->debug >= 2)
|
||||
// {
|
||||
// pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
// }
|
||||
// #endif
|
||||
#if(DEBUG_ENABLED & 1)
|
||||
if(Z80Ctrl->debug >= 3)
|
||||
{
|
||||
pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
}
|
||||
#endif
|
||||
// Certain machines have memory mapped I/O, these need to be handled in-situ as some reads may change the memory map.
|
||||
// These updates are made whilst waiting for the CPLD to retrieve the requested byte.
|
||||
//
|
||||
@@ -285,92 +407,63 @@ static inline void mz1500DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint
|
||||
}
|
||||
} else
|
||||
{
|
||||
// #if(DEBUG_ENABLED & 1)
|
||||
// if(Z80Ctrl->debug >= 2)
|
||||
// {
|
||||
// pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
// }
|
||||
// #endif
|
||||
#if(DEBUG_ENABLED & 1)
|
||||
if(Z80Ctrl->debug >= 3)
|
||||
{
|
||||
pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Determine if this is a memory management port and update the memory page if required.
|
||||
switch(address & 0x00FF)
|
||||
// Check to see if the memory mode page has been allocated for requested mode, if it hasnt, we need to allocate and then define.
|
||||
if(((address&0xFF) - 0xE0) >= 0 && ((address&0xFF) - 0xE0) < 7)
|
||||
{
|
||||
// MZ1500 memory mode switch.
|
||||
//
|
||||
// MZ-1500
|
||||
// |0000:0FFF|1000:CFFF|D000:FFFF
|
||||
// ------------------------------
|
||||
// OUT 0xE0 = |DRAM | |
|
||||
// OUT 0xE1 = | | |DRAM
|
||||
// OUT 0xE2 = |MONITOR | |
|
||||
// OUT 0xE3 = | | |Memory Mapped I/O
|
||||
// OUT 0xE0 = |DRAM |DRAM |<last>
|
||||
// OUT 0xE1 = |<last> |DRAM |DRAM
|
||||
// OUT 0xE2 = |MONITOR |DRAM |<last>
|
||||
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE5 = | | |PCG Enable
|
||||
// OUT 0xE6 = | | |PCG Disable
|
||||
// OUT 0xE5 = |<last> |DRAM |PCG Enable
|
||||
// OUT 0xE6 = |<last> |DRAM |PCG Disable
|
||||
//
|
||||
// <return> = Return to the state prior to the complimentary command being invoked.
|
||||
// Enable lower 4K block as DRAM
|
||||
// Sub-memory page maps:
|
||||
//
|
||||
// LOW BANK HIGH BANK PAGE MAP
|
||||
// DRAM 0
|
||||
// DRAM MEMORY MAP 1
|
||||
// Inhibit 2
|
||||
// DRAM 3
|
||||
// MONITOR MEMORY MAP 4
|
||||
// Inhibit 5
|
||||
//
|
||||
// Determine if this is a memory management port and update the memory page if required.
|
||||
switch(address & 0x00FF)
|
||||
{
|
||||
case IO_ADDR_E0:
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
MZ1500Ctrl.loDRAMen = 1;
|
||||
break;
|
||||
|
||||
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
|
||||
case IO_ADDR_E1:
|
||||
if(!Z80Ctrl->inhibitMode)
|
||||
{
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
// MZ-1500 mode we only work in first 64K block.
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
}
|
||||
MZ1500Ctrl.hiDRAMen = 1;
|
||||
break;
|
||||
|
||||
// Enable MOnitor ROM in lower 4K block
|
||||
case IO_ADDR_E2:
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
MZ1500Ctrl.loDRAMen = 0;
|
||||
break;
|
||||
|
||||
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
|
||||
case IO_ADDR_E3:
|
||||
if(!Z80Ctrl->inhibitMode)
|
||||
{
|
||||
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
|
||||
}
|
||||
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
|
||||
}
|
||||
}
|
||||
MZ1500Ctrl.hiDRAMen = 0;
|
||||
break;
|
||||
|
||||
// Reset to power on condition memory map.
|
||||
case IO_ADDR_E4:
|
||||
// Lower 4K set to Monitor ROM.
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
if(!Z80Ctrl->inhibitMode)
|
||||
{
|
||||
// Upper 12K to hardware.
|
||||
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
|
||||
}
|
||||
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
|
||||
}
|
||||
}
|
||||
MZ1500Ctrl.loDRAMen = 0;
|
||||
MZ1500Ctrl.hiDRAMen = 0;
|
||||
Z80Ctrl->inhibitMode = 0;
|
||||
Z80Ctrl->pcgMode = 0;
|
||||
break;
|
||||
|
||||
// PCG Bank Switching.
|
||||
@@ -390,10 +483,44 @@ static inline void mz1500DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint
|
||||
Z80Ctrl->pcgMode = 0;
|
||||
break;
|
||||
|
||||
// Port is not a memory management port.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Setup memory mode based on flag state.
|
||||
if(Z80Ctrl->inhibitMode)
|
||||
{
|
||||
if(MZ1500Ctrl.loDRAMen)
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 2;
|
||||
else
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 5;
|
||||
} else
|
||||
if(MZ1500Ctrl.loDRAMen)
|
||||
{
|
||||
if(MZ1500Ctrl.hiDRAMen && !Z80Ctrl->pcgMode)
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 0;
|
||||
else
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 1;
|
||||
} else
|
||||
{
|
||||
if(MZ1500Ctrl.hiDRAMen && !Z80Ctrl->pcgMode)
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 3;
|
||||
else
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
|
||||
}
|
||||
Z80Ctrl->governorSkip = 0;
|
||||
} else
|
||||
if((address&0xff) >= 0xD8 && (address&0xff) < 0xDF)
|
||||
{
|
||||
// Do nothing for the Disk interface.
|
||||
} else
|
||||
if((address&0xff) >= 0xF4 && (address&0xff) < 0xF8)
|
||||
{
|
||||
Z80Ctrl->governorSkip = 0;
|
||||
} else
|
||||
{
|
||||
// Z80Ctrl->governorSkip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,8 +533,18 @@ static inline uint8_t mz1500Read(zuint16 address, uint8_t ioFlag)
|
||||
// I/O Operation?
|
||||
if(ioFlag)
|
||||
{
|
||||
switch(address)
|
||||
switch((address&0xff))
|
||||
{
|
||||
// MZ-1R18 Ram File Data Register.
|
||||
case 0xEA:
|
||||
data = MZ1500Ctrl.ramFileMem[MZ1500Ctrl.ramFileAddr];
|
||||
MZ1500Ctrl.ramFileAddr++;
|
||||
break;
|
||||
|
||||
// MZ-1R18 Ram File Control Register.
|
||||
case 0xEB:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -437,8 +574,19 @@ static inline void mz1500Write(zuint16 address, zuint8 data, uint8_t ioFlag)
|
||||
// I/O Operation?
|
||||
if(ioFlag)
|
||||
{
|
||||
switch(address)
|
||||
switch((address&0xff))
|
||||
{
|
||||
// MZ-1R18 Ram File Data Register.
|
||||
case 0xEA:
|
||||
MZ1500Ctrl.ramFileMem[MZ1500Ctrl.ramFileAddr] = data;
|
||||
MZ1500Ctrl.ramFileAddr++;
|
||||
break;
|
||||
|
||||
// MZ-1R18 Ram File Control Register.
|
||||
case 0xEB:
|
||||
MZ1500Ctrl.ramFileAddr = (address & 0xff00) | data;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Mar 2023 v1.0 - Initial write based on the RFS hardware module.
|
||||
// Apr 2023 v1.1 - Updates from the PCW/MZ2000 changes.
|
||||
// History: Mar 2023 - v1.0 - Initial write based on the RFS hardware module.
|
||||
// Apr 2023 - v1.1 - Updates from the PCW/MZ2000 changes.
|
||||
// Jul 2023 - v1.6 - Updated MZ-700 code, adding sub-memory maps to increase page mapping
|
||||
// speed specifically to enable reliable tape read/write. Addition of
|
||||
// MZ-1R18 emulation.
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
@@ -58,6 +61,10 @@
|
||||
// PCW control.
|
||||
typedef struct {
|
||||
uint8_t regCtrl; // Control register.
|
||||
uint8_t loDRAMen; // Lower bank 0000:0FFF DRAM enabled, else monitor.
|
||||
uint8_t hiDRAMen; // Higher bank D000:FFFF DRAM enabled, else memory mapped I/O.
|
||||
uint32_t *ramFileMem; // 64K RamFile memory.
|
||||
uint16_t ramFileAddr; // Address pointer of the MZ-1R18 64K Ram File Board memory.
|
||||
} t_MZ700Ctrl;
|
||||
|
||||
// RFS Board control.
|
||||
@@ -72,10 +79,14 @@ static t_MZ700Ctrl MZ700Ctrl;
|
||||
void mz700SetupMemory(enum Z80_MEMORY_PROFILE mode)
|
||||
{
|
||||
// Locals.
|
||||
uint8_t subMode;
|
||||
uint32_t idx;
|
||||
|
||||
// Setup defaults.
|
||||
MZ700Ctrl.regCtrl = 0x00;
|
||||
MZ700Ctrl.loDRAMen = 0; // Default is monitor ROM is enabled.
|
||||
MZ700Ctrl.hiDRAMen = 0; // Default is memory mapped I/O enabled.
|
||||
Z80Ctrl->inhibitMode = 0;
|
||||
|
||||
// Setup default mode according to run mode, ie. Physical run or Virtual run.
|
||||
//
|
||||
@@ -146,9 +157,109 @@ void mz700SetupMemory(enum Z80_MEMORY_PROFILE mode)
|
||||
}
|
||||
}
|
||||
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
|
||||
{
|
||||
if((idx&0x00ff) == 0xEA || (idx&0x00ff) == 0xEB)
|
||||
{
|
||||
Z80Ctrl->iopage[idx] = idx | IO_TYPE_VIRTUAL_HW;
|
||||
} else
|
||||
{
|
||||
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
|
||||
}
|
||||
}
|
||||
// Setup sub-memory pages to enable rapid switch according to memory bank commands.
|
||||
for(subMode=0; subMode < MEMORY_SUB_MODES; subMode++)
|
||||
{
|
||||
if(Z80Ctrl->page[MEMORY_MODES+subMode] == NULL)
|
||||
{
|
||||
#if(DEBUG_ENABLED & 0x01)
|
||||
if(Z80Ctrl->debug >=3) pr_info("Allocating memory sub page:%d\n", subMode);
|
||||
#endif
|
||||
(Z80Ctrl->page[MEMORY_MODES+subMode]) = (uint32_t *)kmalloc((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)), GFP_KERNEL);
|
||||
if ((Z80Ctrl->page[MEMORY_MODES+subMode]) == NULL)
|
||||
{
|
||||
pr_info("z80drv: failed to allocate memory sub mapping page:%d memory!", subMode);
|
||||
}
|
||||
}
|
||||
|
||||
// Duplicate current mode into the sub page prior to setting up specific config.
|
||||
memcpy((uint8_t *)Z80Ctrl->page[MEMORY_MODES+subMode], (uint8_t *)Z80Ctrl->page[0], MEMORY_BLOCK_SLOTS*sizeof(uint32_t));
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + subMode;
|
||||
|
||||
// MZ700 memory mode switch.
|
||||
//
|
||||
// MZ-700
|
||||
// |0000:0FFF|1000:CFFF|D000:FFFF
|
||||
// ------------------------------
|
||||
// OUT 0xE0 = |DRAM |DRAM |<last>
|
||||
// OUT 0xE1 = |<last> |DRAM |DRAM
|
||||
// OUT 0xE2 = |MONITOR |DRAM |<last>
|
||||
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE5 = |<last> |DRAM |Inhibit
|
||||
// OUT 0xE6 = |<last> |DRAM |<return to last>
|
||||
//
|
||||
// Sub-memory page maps:
|
||||
//
|
||||
// LOW BANK HIGH BANK PAGE MAP
|
||||
// DRAM 0
|
||||
// DRAM MEMORY MAP 1
|
||||
// Inhibit 2
|
||||
// DRAM 3
|
||||
// MONITOR MEMORY MAP 4
|
||||
// Inhibit 5
|
||||
//
|
||||
if(subMode >= 0 && subMode < 3)
|
||||
{
|
||||
// Enable lower 4K block as DRAM
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode >= 3 && subMode < 6)
|
||||
{
|
||||
// Enable lower 4K block as Monitor ROM
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode == 0 || subMode == 3)
|
||||
{
|
||||
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
// MZ-700 mode we only work in first 64K block.
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode == 1 || subMode == 4)
|
||||
{
|
||||
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
|
||||
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
|
||||
}
|
||||
for(idx=0xE000; idx < 0xE800; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
|
||||
}
|
||||
for(idx=0xE800; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode == 2 || subMode == 5)
|
||||
{
|
||||
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
|
||||
|
||||
// Enable refresh as using virtual RAM stops refresh of host DRAM.
|
||||
Z80Ctrl->refreshDRAM = 2;
|
||||
}
|
||||
@@ -196,6 +307,17 @@ void mz700Init(uint8_t mode)
|
||||
// Reset memory paging to default.
|
||||
SPI_SEND_32(0x00e4, 0x00 << 8 | CPLD_CMD_WRITEIO_ADDR);
|
||||
|
||||
#if(DEBUG_ENABLED & 0x01)
|
||||
if(Z80Ctrl->debug >=3) pr_info("Allocating MZ-1R18 memory\n");
|
||||
#endif
|
||||
// Allocate memory for the MZ-1R18 64K Ram File board.
|
||||
MZ700Ctrl.ramFileMem = (uint32_t *)kmalloc((65536 * sizeof(uint8_t)), GFP_KERNEL);
|
||||
if(MZ700Ctrl.ramFileMem == NULL)
|
||||
{
|
||||
pr_info("z80drv: failed to allocate MZ-1R18 Ram File memory!");
|
||||
}
|
||||
MZ700Ctrl.ramFileAddr = 0x0000;
|
||||
|
||||
// Initialise the virtual RAM from the HOST DRAM. This is to maintain compatibility as some applications (in my experience) have
|
||||
// bugs, which Im putting down to not initialising variables. The host DRAM is in a pattern of 0x00..0x00, 0xFF..0xFF repeating
|
||||
// when first powered on.
|
||||
@@ -267,17 +389,17 @@ void mz700Remove(void)
|
||||
static inline void mz700DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
|
||||
{
|
||||
// Locals.
|
||||
uint32_t idx;
|
||||
//uint32_t idx;
|
||||
|
||||
// Decoding memory address or I/O address?
|
||||
if(ioFlag == 0)
|
||||
{
|
||||
// #if(DEBUG_ENABLED & 1)
|
||||
// if(Z80Ctrl->debug >= 2)
|
||||
// {
|
||||
// pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
// }
|
||||
// #endif
|
||||
#if(DEBUG_ENABLED & 1)
|
||||
if(Z80Ctrl->debug >= 3)
|
||||
{
|
||||
pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
}
|
||||
#endif
|
||||
// Certain machines have memory mapped I/O, these need to be handled in-situ as some reads may change the memory map.
|
||||
// These updates are made whilst waiting for the CPLD to retrieve the requested byte.
|
||||
//
|
||||
@@ -304,117 +426,98 @@ static inline void mz700DecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8
|
||||
}
|
||||
} else
|
||||
{
|
||||
// #if(DEBUG_ENABLED & 1)
|
||||
// if(Z80Ctrl->debug >= 2)
|
||||
// {
|
||||
// pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
// }
|
||||
// #endif
|
||||
#if(DEBUG_ENABLED & 1)
|
||||
if(Z80Ctrl->debug >= 3)
|
||||
{
|
||||
pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Determine if this is a memory management port and update the memory page if required.
|
||||
switch(address & 0x00FF)
|
||||
// Check to see if the memory mode page has been allocated for requested mode, if it hasnt, we need to allocate and then define.
|
||||
if(((address&0xFF) - 0xE0) >= 0 && ((address&0xFF) - 0xE0) < 7)
|
||||
{
|
||||
// MZ700 memory mode switch.
|
||||
//
|
||||
// MZ-700
|
||||
// |0000:0FFF|1000:CFFF|D000:FFFF
|
||||
// ------------------------------
|
||||
// OUT 0xE0 = |DRAM | |
|
||||
// OUT 0xE1 = | | |DRAM
|
||||
// OUT 0xE2 = |MONITOR | |
|
||||
// OUT 0xE3 = | | |Memory Mapped I/O
|
||||
// OUT 0xE0 = |DRAM |DRAM |<last>
|
||||
// OUT 0xE1 = |<last> |DRAM |DRAM
|
||||
// OUT 0xE2 = |MONITOR |DRAM |<last>
|
||||
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE5 = | | |Inhibit
|
||||
// OUT 0xE6 = | | |<return>
|
||||
// OUT 0xE5 = |<last> |DRAM |Inhibit
|
||||
// OUT 0xE6 = |<last> |DRAM |<return to last>
|
||||
//
|
||||
// <return> = Return to the state prior to the complimentary command being invoked.
|
||||
// Enable lower 4K block as DRAM
|
||||
// Sub-memory page maps:
|
||||
//
|
||||
// LOW BANK HIGH BANK PAGE MAP
|
||||
// DRAM 0
|
||||
// DRAM MEMORY MAP 1
|
||||
// Inhibit 2
|
||||
// DRAM 3
|
||||
// MONITOR MEMORY MAP 4
|
||||
// Inhibit 5
|
||||
//
|
||||
// Determine if this is a memory management port and update the memory page if required.
|
||||
switch(address & 0x00FF)
|
||||
{
|
||||
case IO_ADDR_E0:
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
MZ700Ctrl.loDRAMen = 1;
|
||||
break;
|
||||
|
||||
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
|
||||
case IO_ADDR_E1:
|
||||
if(!Z80Ctrl->inhibitMode)
|
||||
{
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
// MZ-700 mode we only work in first 64K block.
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
}
|
||||
MZ700Ctrl.hiDRAMen = 1;
|
||||
break;
|
||||
|
||||
// Enable MOnitor ROM in lower 4K block
|
||||
case IO_ADDR_E2:
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
MZ700Ctrl.loDRAMen = 0;
|
||||
break;
|
||||
|
||||
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
|
||||
case IO_ADDR_E3:
|
||||
if(!Z80Ctrl->inhibitMode)
|
||||
{
|
||||
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
|
||||
}
|
||||
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
|
||||
}
|
||||
}
|
||||
MZ700Ctrl.hiDRAMen = 0;
|
||||
break;
|
||||
|
||||
// Reset to power on condition memory map.
|
||||
case IO_ADDR_E4:
|
||||
// Lower 4K set to Monitor ROM.
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
if(!Z80Ctrl->inhibitMode)
|
||||
{
|
||||
// Upper 12K to hardware.
|
||||
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
|
||||
}
|
||||
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
|
||||
case IO_ADDR_E5:
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
backupMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
|
||||
}
|
||||
Z80Ctrl->inhibitMode = 1;
|
||||
break;
|
||||
|
||||
// Restore D000-FFFF to its original state.
|
||||
case IO_ADDR_E6:
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
restoreMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
|
||||
}
|
||||
MZ700Ctrl.loDRAMen = 0;
|
||||
MZ700Ctrl.hiDRAMen = 0;
|
||||
Z80Ctrl->inhibitMode = 0;
|
||||
break;
|
||||
|
||||
case IO_ADDR_E5:
|
||||
Z80Ctrl->inhibitMode = 1;
|
||||
break;
|
||||
|
||||
case IO_ADDR_E6:
|
||||
Z80Ctrl->inhibitMode = 0;
|
||||
break;
|
||||
|
||||
// Port is not a memory management port.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Setup memory mode based on flag state.
|
||||
if(Z80Ctrl->inhibitMode)
|
||||
{
|
||||
if(MZ700Ctrl.loDRAMen)
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 2;
|
||||
else
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 5;
|
||||
} else
|
||||
if(MZ700Ctrl.loDRAMen)
|
||||
{
|
||||
if(MZ700Ctrl.hiDRAMen)
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 0;
|
||||
else
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 1;
|
||||
} else
|
||||
{
|
||||
if(MZ700Ctrl.hiDRAMen)
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 3;
|
||||
else
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,8 +530,18 @@ static inline uint8_t mz700Read(zuint16 address, uint8_t ioFlag)
|
||||
// I/O Operation?
|
||||
if(ioFlag)
|
||||
{
|
||||
switch(address)
|
||||
switch((address&0xff))
|
||||
{
|
||||
// MZ-1R18 Ram File Data Register.
|
||||
case 0xEA:
|
||||
data = MZ700Ctrl.ramFileMem[MZ700Ctrl.ramFileAddr];
|
||||
MZ700Ctrl.ramFileAddr++;
|
||||
break;
|
||||
|
||||
// MZ-1R18 Ram File Control Register.
|
||||
case 0xEB:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -458,8 +571,19 @@ static inline void mz700Write(zuint16 address, zuint8 data, uint8_t ioFlag)
|
||||
// I/O Operation?
|
||||
if(ioFlag)
|
||||
{
|
||||
switch(address)
|
||||
switch((address&0xff))
|
||||
{
|
||||
// MZ-1R18 Ram File Data Register.
|
||||
case 0xEA:
|
||||
MZ700Ctrl.ramFileMem[MZ700Ctrl.ramFileAddr] = data;
|
||||
MZ700Ctrl.ramFileAddr++;
|
||||
break;
|
||||
|
||||
// MZ-1R18 Ram File Control Register.
|
||||
case 0xEB:
|
||||
MZ700Ctrl.ramFileAddr = (address & 0xff00) | data;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
|
||||
// SD Drive constants.
|
||||
#define SD_DIR "/apps/FusionX/host/MZ-80A/RFS/"
|
||||
#define SD_CARD_FILENAME SD_DIR "SHARP_MZ80A_RFS_CPM_IMAGE_1.img"// SD Card Binary Image.
|
||||
#define SD_CARD_FILENAME SD_DIR "SHARP_MZ80A_RFS_CPM_IMAGE_1.img" // SD Card Binary Image.
|
||||
|
||||
// MMC/SD command (SPI mode)
|
||||
#define CMD0 0x40 + 0 // GO_IDLE_STATE
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
// Credits:
|
||||
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
|
||||
//
|
||||
// History: Feb 2023 v1.0 - Initial write based on the tranZPUter SW hardware.
|
||||
// Apr 2023 v1.1 - Updates & bug fixes.
|
||||
// History: Feb 2023 - v1.0 - Initial write based on the tranZPUter SW hardware.
|
||||
// Apr 2023 - v1.1 - Updates & bug fixes.
|
||||
// Jul 2023 - v1.6 - Updated MZ-700 code, adding sub-memory maps to increase page mapping
|
||||
// speed specifically to enable reliable tape read/write.
|
||||
|
||||
//
|
||||
// Notes: See Makefile to enable/disable conditional components
|
||||
//
|
||||
@@ -68,6 +71,8 @@ typedef struct {
|
||||
uint8_t regCpuInfo; // Internal FPGA CPU information register.
|
||||
uint8_t regCpldCfg; // Internal CPLD config register.
|
||||
uint8_t regCpldInfo; // Internal CPLD information register.
|
||||
uint8_t loDRAMen; // Lower bank 0000:0FFF DRAM enabled, else monitor.
|
||||
uint8_t hiDRAMen; // Higher bank D000:FFFF DRAM enabled, else memory mapped I/O.
|
||||
} t_TZPUCtrl;
|
||||
|
||||
// TZPU Board control.
|
||||
@@ -148,6 +153,8 @@ void tzpuSetupMemory(enum Z80_MEMORY_PROFILE mode)
|
||||
TZPUCtrl.regCpldInfo = (CPLD_VERSION << 4) | (CPLD_HAS_FPGA_VIDEO << 3) | HWMODE_MZ2000;
|
||||
#endif
|
||||
TZPUCtrl.regCpldCfg = 0x00; // Not used, as no CPLD available, but need to store/return value if addressed.
|
||||
TZPUCtrl.loDRAMen = 0; // Default is monitor ROM is enabled.
|
||||
TZPUCtrl.hiDRAMen = 0; // Default is memory mapped I/O enabled.
|
||||
|
||||
// Default memory mode, TZFS.
|
||||
Z80Ctrl->memoryMode = TZMM_TZFS;
|
||||
@@ -246,7 +253,7 @@ void tzpuRemove(void)
|
||||
uint32_t idx;
|
||||
|
||||
// Go through and clear all memory maps, leave the original page in slot 0.
|
||||
for(idx=1; idx < MEMORY_MODES; idx++)
|
||||
for(idx=1; idx < MEMORY_MODES+MEMORY_SUB_MODES; idx++)
|
||||
{
|
||||
if(Z80Ctrl->page[idx] != NULL)
|
||||
{
|
||||
@@ -267,17 +274,18 @@ void tzpuRemove(void)
|
||||
static inline void tzpuDecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
|
||||
{
|
||||
// Locals.
|
||||
uint32_t idx;
|
||||
//uint32_t idx;
|
||||
|
||||
// I/O or Memory?
|
||||
if(ioFlag == 0)
|
||||
{
|
||||
// #if(DEBUG_ENABLED & 1)
|
||||
// if(Z80Ctrl->debug >= 2)
|
||||
// {
|
||||
// pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
// }
|
||||
// #endif
|
||||
#if(DEBUG_ENABLED & 1)
|
||||
if(Z80Ctrl->debug >= 3)
|
||||
{
|
||||
pr_info("MEM:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Certain machines have memory mapped I/O, these need to be handled in-situ as some reads may change the memory map.
|
||||
// These updates are made whilst waiting for the CPLD to retrieve the requested byte.
|
||||
//
|
||||
@@ -305,117 +313,88 @@ static inline void tzpuDecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_
|
||||
} else
|
||||
// I/O Decoding.
|
||||
{
|
||||
// #if(DEBUG_ENABLED & 1)
|
||||
// if(Z80Ctrl->debug >= 2)
|
||||
// {
|
||||
// pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
// }
|
||||
// #endif
|
||||
#if(DEBUG_ENABLED & 1)
|
||||
if(Z80Ctrl->debug >= 3)
|
||||
{
|
||||
pr_info("IO:%04x,%02x,%d,%d\n", address, data, ioFlag, readFlag);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Determine if this is a memory management port and update the memory page if required.
|
||||
switch(address & 0x00FF)
|
||||
// Check to see if the memory mode page has been allocated for requested mode, if it hasnt, we need to allocate and then define.
|
||||
if(((address&0xFF) - 0xE0) >= 0 && ((address&0xFF) - 0xE0) < MEMORY_SUB_MODES)
|
||||
{
|
||||
// MZ700 memory mode switch.
|
||||
//
|
||||
// MZ-700
|
||||
// |0000:0FFF|1000:CFFF|D000:FFFF
|
||||
// ------------------------------
|
||||
// OUT 0xE0 = |DRAM | |
|
||||
// OUT 0xE1 = | | |DRAM
|
||||
// OUT 0xE2 = |MONITOR | |
|
||||
// OUT 0xE3 = | | |Memory Mapped I/O
|
||||
// OUT 0xE0 = |DRAM |DRAM |<last>
|
||||
// OUT 0xE1 = |<last> |DRAM |DRAM
|
||||
// OUT 0xE2 = |MONITOR |DRAM |<last>
|
||||
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE5 = | | |Inhibit
|
||||
// OUT 0xE6 = | | |<return>
|
||||
// OUT 0xE5 = |<last> |DRAM |Inhibit
|
||||
// OUT 0xE6 = |<last> |DRAM |<return to last>
|
||||
//
|
||||
// <return> = Return to the state prior to the complimentary command being invoked.
|
||||
// Enable lower 4K block as DRAM
|
||||
// Determine if this is a memory management port and update the memory page if required.
|
||||
switch(address & 0x00FF)
|
||||
{
|
||||
case IO_ADDR_E0:
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
TZPUCtrl.loDRAMen = 1;
|
||||
break;
|
||||
|
||||
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
|
||||
case IO_ADDR_E1:
|
||||
if(!Z80Ctrl->inhibitMode)
|
||||
{
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
// MZ-700 mode we only work in first 64K block.
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
}
|
||||
TZPUCtrl.hiDRAMen = 1;
|
||||
break;
|
||||
|
||||
// Enable MOnitor ROM in lower 4K block
|
||||
case IO_ADDR_E2:
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
TZPUCtrl.loDRAMen = 0;
|
||||
break;
|
||||
|
||||
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
|
||||
case IO_ADDR_E3:
|
||||
if(!Z80Ctrl->inhibitMode)
|
||||
{
|
||||
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
|
||||
}
|
||||
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
|
||||
}
|
||||
}
|
||||
TZPUCtrl.hiDRAMen = 0;
|
||||
break;
|
||||
|
||||
// Reset to power on condition memory map.
|
||||
case IO_ADDR_E4:
|
||||
// Lower 4K set to Monitor ROM.
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
|
||||
}
|
||||
if(!Z80Ctrl->inhibitMode)
|
||||
{
|
||||
// Upper 12K to hardware.
|
||||
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
|
||||
}
|
||||
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
|
||||
case IO_ADDR_E5:
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
backupMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
|
||||
}
|
||||
Z80Ctrl->inhibitMode = 1;
|
||||
break;
|
||||
|
||||
// Restore D000-FFFF to its original state.
|
||||
case IO_ADDR_E6:
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
restoreMemoryType(idx/MEMORY_BLOCK_GRANULARITY);
|
||||
}
|
||||
TZPUCtrl.loDRAMen = 0;
|
||||
TZPUCtrl.hiDRAMen = 0;
|
||||
Z80Ctrl->inhibitMode = 0;
|
||||
break;
|
||||
|
||||
case IO_ADDR_E5:
|
||||
Z80Ctrl->inhibitMode = 1;
|
||||
break;
|
||||
|
||||
case IO_ADDR_E6:
|
||||
Z80Ctrl->inhibitMode = 0;
|
||||
break;
|
||||
|
||||
// Port is not a memory management port.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Setup memory mode based on flag state.
|
||||
if(Z80Ctrl->inhibitMode)
|
||||
{
|
||||
if(TZPUCtrl.loDRAMen)
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 2;
|
||||
else
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 5;
|
||||
} else
|
||||
if(TZPUCtrl.loDRAMen)
|
||||
{
|
||||
if(TZPUCtrl.hiDRAMen)
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 0;
|
||||
else
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 1;
|
||||
} else
|
||||
{
|
||||
if(TZPUCtrl.hiDRAMen)
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 3;
|
||||
else
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,6 +472,7 @@ static inline uint8_t tzpuRead(zuint16 address, uint8_t ioFlag)
|
||||
static inline void tzpuWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
|
||||
{
|
||||
// Locals
|
||||
uint8_t subMode;
|
||||
uint32_t idx;
|
||||
|
||||
// The tranZPUter board, in order to autoboot and use valuable space for variables, allows writing into the User ROM
|
||||
@@ -925,6 +905,95 @@ static inline void tzpuWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
|
||||
}
|
||||
}
|
||||
// Memory map now created/switched.
|
||||
|
||||
// Allocate/populate the sub-memory maps for this mode. TZFS currently uses sub-memory modes for MZ-700 page banking.
|
||||
if(Z80Ctrl->memoryMode == TZMM_TZFS)
|
||||
{
|
||||
for(subMode=0; subMode < MEMORY_SUB_MODES; subMode++)
|
||||
{
|
||||
if(Z80Ctrl->page[MEMORY_MODES+subMode] == NULL)
|
||||
{
|
||||
#if(DEBUG_ENABLED & 0x01)
|
||||
if(Z80Ctrl->debug >=3) pr_info("Allocating memory sub page:%d\n", subMode);
|
||||
#endif
|
||||
pr_info("Allocating memory sub page:%d,%d\n", subMode, (MEMORY_BLOCK_SLOTS*sizeof(uint32_t)));
|
||||
(Z80Ctrl->page[MEMORY_MODES+subMode]) = (uint32_t *)kmalloc((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)), GFP_KERNEL);
|
||||
if ((Z80Ctrl->page[MEMORY_MODES+subMode]) == NULL)
|
||||
{
|
||||
pr_info("z80drv: failed to allocate memory sub mapping page:%d memory!", subMode);
|
||||
}
|
||||
}
|
||||
|
||||
// Duplicate current mode into the sub page prior to setting up specific config.
|
||||
memcpy((uint8_t *)Z80Ctrl->page[MEMORY_MODES+subMode], (uint8_t *)Z80Ctrl->page[(data & (MEMORY_MODES - 1))], MEMORY_BLOCK_SLOTS*sizeof(uint32_t));
|
||||
Z80Ctrl->memoryMode = MEMORY_MODES + subMode;
|
||||
TZPUCtrl.loDRAMen = 0;
|
||||
TZPUCtrl.hiDRAMen = 0;
|
||||
Z80Ctrl->inhibitMode = 0;
|
||||
|
||||
// MZ700 memory mode switch.
|
||||
//
|
||||
// MZ-700
|
||||
// |0000:0FFF|1000:CFFF|D000:FFFF
|
||||
// ------------------------------
|
||||
// OUT 0xE0 = |DRAM |DRAM |<last>
|
||||
// OUT 0xE1 = |<last> |DRAM |DRAM
|
||||
// OUT 0xE2 = |MONITOR |DRAM |<last>
|
||||
// OUT 0xE3 = |<last> |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE4 = |MONITOR |DRAM |Memory Mapped I/O
|
||||
// OUT 0xE5 = |<last> |DRAM |Inhibit
|
||||
// OUT 0xE6 = |<last> |DRAM |<return to last>
|
||||
//
|
||||
// Sub-memory page maps:
|
||||
//
|
||||
// LOW BANK HIGH BANK PAGE MAP
|
||||
// DRAM 0
|
||||
// DRAM MEMORY MAP 1
|
||||
// Inhibit 2
|
||||
// DRAM 3
|
||||
// MONITOR MEMORY MAP 4
|
||||
// Inhibit 5
|
||||
//
|
||||
if(subMode >= 0 && subMode < 3)
|
||||
{
|
||||
// Enable lower 4K block as DRAM
|
||||
for(idx=0x0000; idx < 0x1000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode == 0 || subMode == 3)
|
||||
{
|
||||
// Enable upper 12K block, including Video/Memory Mapped peripherals area, as DRAM.
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
// MZ-700 mode we only work in first 64K block.
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
|
||||
}
|
||||
}
|
||||
if(subMode == 1 || subMode == 4)
|
||||
{
|
||||
// Enable Video RAM and Memory mapped peripherals in upper 12K block.
|
||||
for(idx=0xD000; idx < 0xE000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
|
||||
}
|
||||
for(idx=0xE000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
|
||||
}
|
||||
}
|
||||
if(subMode == 2 || subMode == 5)
|
||||
{
|
||||
// Inhibit. Backup current page data in region 0xD000-0xFFFF and inhibit it.
|
||||
for(idx=0xD000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
|
||||
{
|
||||
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Z80Ctrl->memoryMode = (data & (MEMORY_MODES - 1));
|
||||
break;
|
||||
|
||||
case IO_TZ_SETXMHZ:
|
||||
|
||||
@@ -42,11 +42,15 @@ START: LD SP,STACK
|
||||
CALL ?CLER ; Clear 256 bytes from NAME 10F1h to 11F0h
|
||||
LD A,016H
|
||||
CALL PRNT
|
||||
IF KUMA = 1
|
||||
LD A,0CFH
|
||||
ELSE
|
||||
IF MODE80C = 0
|
||||
LD A,007H ; Black background, white characters. Bit 7 is clear as a write to bit 7 @ DFFFH selects 40Char mode.
|
||||
ELSE
|
||||
LD A,017H ; Blue background, white characters in colour mode. Bit 7 is set as a write to bit 7 @ DFFFH selects 80Char mode.
|
||||
ENDIF
|
||||
ENDIF
|
||||
LD HL,ARAM
|
||||
JR STRT1
|
||||
JP 1035H ; NMI routine.
|
||||
@@ -130,13 +134,19 @@ LOAD: CALL ?RDI
|
||||
JR C,ST1
|
||||
JP (HL)
|
||||
|
||||
|
||||
; LOADING
|
||||
MSG?2: DB 04CH, 0B7H, 0A1H, 09CH
|
||||
DB 0A6H, 0B0H, 097H, 020H
|
||||
DB 00DH
|
||||
|
||||
; SIGN ON BANNER
|
||||
MSG?3: DB "** MONITOR SA-1510 **", 0DH
|
||||
; SIGN ON BANNER - Different for Kuma 80 BIOS
|
||||
MSG?3: IF KUMA = 0
|
||||
DB "** MONITOR SA-1510 **", 0DH
|
||||
ELSE
|
||||
DB "*K",0A5H,0B3H,0A1H," MZ-80A M",0B7H,0B0H,0A6H
|
||||
DB 096H,0B7H,09DH,"*",00DH,"*",00DH
|
||||
ENDIF
|
||||
|
||||
; For 80 Character mode we need some space, so shorten the Check Sum Error message.
|
||||
;
|
||||
@@ -148,7 +158,7 @@ MSGE1: IF MODE80C = 0
|
||||
DB "CK SUM?", 0DH
|
||||
ENDIF
|
||||
|
||||
; Hook = 7 bytes.
|
||||
; Hook = 7 bytes using space taken from Check Sum message.
|
||||
HOOK: IF MODE80C = 1
|
||||
LD A,0FFH
|
||||
LD (SPAGE),A
|
||||
@@ -156,7 +166,11 @@ HOOK: IF MODE80C = 1
|
||||
ENDIF
|
||||
|
||||
; CR PAGE MODE1
|
||||
.CR: CALL .MANG
|
||||
.CR: IF KUMA = 1
|
||||
LD HL,(DSPXY)
|
||||
JP CURS2
|
||||
ELSE
|
||||
CALL .MANG
|
||||
RRCA
|
||||
JP NC,CURS2
|
||||
LD L,000H
|
||||
@@ -165,18 +179,43 @@ HOOK: IF MODE80C = 1
|
||||
JR Z,.CP1
|
||||
INC H
|
||||
JP CURS1
|
||||
ENDIF
|
||||
.CR1: IF KUMA = 1
|
||||
NEG
|
||||
LD (SPAGE),A
|
||||
ADD A,004H
|
||||
LD (KEYPF),A
|
||||
RET
|
||||
DB 00EH
|
||||
ENDIF
|
||||
|
||||
.CP1: LD (DSPXY),HL
|
||||
|
||||
; SCROLLER
|
||||
.SCROL: LD BC,SCRNSZ - COLW ; Scroll COLW -1 lines
|
||||
.SCROL: IF KUMA = 1
|
||||
LD BC, 0780H
|
||||
ELSE
|
||||
LD BC,SCRNSZ - COLW ; Scroll COLW -1 lines
|
||||
ENDIF
|
||||
LD DE,SCRN ; Start of the screen.
|
||||
IF KUMA = 1
|
||||
LD HL,0D050H
|
||||
ELSE
|
||||
LD HL,SCRN + COLW ; Start of screen + 1 line.
|
||||
ENDIF
|
||||
LDIR
|
||||
EX DE,HL
|
||||
IF KUMA = 1
|
||||
LD B, 050H
|
||||
ELSE
|
||||
LD B,COLW ; Clear last line at bottom of screen.
|
||||
ENDIF
|
||||
CALL ?CLER
|
||||
IF KUMA = 1
|
||||
JP ?RSTR
|
||||
ELSE
|
||||
LD BC,0001AH
|
||||
ENDIF
|
||||
LD DE,MANG
|
||||
LD HL,MANG + 1
|
||||
LDIR
|
||||
@@ -587,7 +626,30 @@ TIMIN: PUSH AF
|
||||
EI
|
||||
RET
|
||||
|
||||
.DSP03: EX DE,HL
|
||||
.DSP03: IF KUMA = 1
|
||||
LD A,(SPAGE)
|
||||
OR A
|
||||
LD A,027H
|
||||
RET Z
|
||||
ADD A,A
|
||||
INC A
|
||||
RET
|
||||
|
||||
L03A7: PUSH BC
|
||||
CALL .DSP03
|
||||
LD B,A
|
||||
LD A,L
|
||||
CP B
|
||||
POP BC
|
||||
RET
|
||||
|
||||
L03B0: CALL .DSP03
|
||||
LD L,A
|
||||
XOR A
|
||||
DEC H
|
||||
RET
|
||||
ELSE
|
||||
EX DE,HL
|
||||
LD (HL),001H
|
||||
INC HL
|
||||
LD (HL),000H
|
||||
@@ -603,6 +665,7 @@ TIMIN: PUSH AF
|
||||
RRCA
|
||||
EX DE,HL
|
||||
LD HL,(DSPXY)
|
||||
ENDIF
|
||||
RET
|
||||
|
||||
LD C,H
|
||||
@@ -1141,7 +1204,11 @@ L0743: DEC H
|
||||
?MODE: LD HL,KEYPF
|
||||
LD (HL),08AH
|
||||
LD (HL),007H
|
||||
IF KUMA = 1
|
||||
LD (HL),004H
|
||||
ELSE
|
||||
LD (HL),005H
|
||||
ENDIF
|
||||
LD (HL),001H
|
||||
RET
|
||||
|
||||
@@ -1270,7 +1337,11 @@ CHGPA: XOR A
|
||||
JR CHGPK1
|
||||
ENDIF
|
||||
CHGPK: LD A,0FFH
|
||||
CHGPK1: LD (SPAGE),A
|
||||
CHGPK1: IF KUMA = 1
|
||||
CALL .CR1
|
||||
ELSE
|
||||
LD (SPAGE),A
|
||||
ENDIF
|
||||
LD A,0C6H
|
||||
CALL ?DPCT
|
||||
CHGP1: JP GETL0
|
||||
@@ -1581,7 +1652,12 @@ REV2: JP ?RSTR
|
||||
.MANG: LD HL,MANG
|
||||
LD A,(SPAGE)
|
||||
OR A
|
||||
IF KUMA = 1
|
||||
JR NZ,.MANG1 ; (+018H)
|
||||
NOP
|
||||
ELSE
|
||||
JP NZ,.MANG2
|
||||
ENDIF
|
||||
LD A,(MGPNT)
|
||||
.MANG3: SUB 008H
|
||||
INC HL
|
||||
@@ -2407,14 +2483,24 @@ DLY12A: CALL DLY3
|
||||
CALL ?PONT
|
||||
LD (HL),B
|
||||
LD HL,(DSPXY)
|
||||
IF KUMA = 1
|
||||
CALL L03A7
|
||||
ELSE
|
||||
LD A,L
|
||||
DSP01: CP COLW - 1 ; End of line.
|
||||
ENDIF
|
||||
DSP01: IF KUMA = 0
|
||||
CP COLW - 1 ; End of line.
|
||||
ENDIF
|
||||
JR NZ,DSP04
|
||||
CALL .MANG
|
||||
JR C,DSP04
|
||||
LD A,(SPAGE)
|
||||
OR A
|
||||
IF KUMA
|
||||
JP NZ,CURSR
|
||||
ELSE
|
||||
JP NZ,.DSP03
|
||||
ENDIF
|
||||
EX DE,HL
|
||||
LD A,B
|
||||
CP 007H
|
||||
@@ -2535,8 +2621,12 @@ CURSU1: CALL MGP.D
|
||||
JR CURS3
|
||||
|
||||
CURSR: LD HL,(DSPXY)
|
||||
IF KUMA = 1
|
||||
CALL L03A7
|
||||
ELSE
|
||||
LD A,L
|
||||
CP COLW - 1 ; End of line
|
||||
ENDIF
|
||||
JR NC,CURS2
|
||||
INC L
|
||||
JR CURS3
|
||||
@@ -2555,8 +2645,12 @@ CURSL: LD HL,(DSPXY)
|
||||
JR Z,CURS5A
|
||||
DEC L
|
||||
JR CURS3
|
||||
CURS5A: LD L,COLW - 1 ; End of line
|
||||
CURS5A: IF KUMA = 1
|
||||
CALL L03B0
|
||||
ELSE
|
||||
LD L,COLW - 1 ; End of line
|
||||
DEC H
|
||||
ENDIF
|
||||
JP P,CURSU1
|
||||
LD H,000H
|
||||
LD (DSPXY),HL
|
||||
@@ -2643,6 +2737,16 @@ INST: CALL .MANG
|
||||
RRCA
|
||||
LD L,COLW - 1 ; End of line
|
||||
LD A,L
|
||||
IF KUMA = 1
|
||||
JR NC,INST1B
|
||||
LD A,028H
|
||||
ADD A,L
|
||||
LD L,A
|
||||
INST1B: CALL ?PNT1
|
||||
PUSH HL
|
||||
LD HL,(DSPXY)
|
||||
NOP
|
||||
ELSE
|
||||
JR NC,INST1A
|
||||
INC H
|
||||
INST1A: CALL ?PNT1
|
||||
@@ -2650,6 +2754,7 @@ INST1A: CALL ?PNT1
|
||||
LD HL,(DSPXY)
|
||||
JR NC,INST2
|
||||
LD A,(COLW*2)-1 ; 04FH
|
||||
ENDIF
|
||||
INST2: SUB L
|
||||
LD B,A
|
||||
POP DE
|
||||
@@ -2720,6 +2825,19 @@ ROLU1: CALL MGP.I
|
||||
PUSH HL
|
||||
POP BC
|
||||
LD DE,COLW
|
||||
IF KUMA = 1
|
||||
LD HL,(PAGETP)
|
||||
INC B
|
||||
LD A,(SPAGE)
|
||||
OR A
|
||||
JR Z,L0FCE ; (+008H)
|
||||
LD HL,0D000H
|
||||
LD E,050H
|
||||
JR L0FCE ; (+001H)
|
||||
L0FCD: ADD HL,DE
|
||||
L0FCE: DJNZ L0FCD ; (-003H)
|
||||
NOP
|
||||
ELSE
|
||||
LD HL,SCRN - COLW
|
||||
LD A,(SPAGE)
|
||||
OR A
|
||||
@@ -2730,6 +2848,7 @@ ROLU1: CALL MGP.I
|
||||
DEC B
|
||||
JP P,?PNT2
|
||||
LD B,000H
|
||||
ENDIF
|
||||
ADD HL,BC
|
||||
RES 3,H
|
||||
POP DE
|
||||
|
||||
Reference in New Issue
Block a user