Updates to support full memory in bank 4 of TZFS

This commit is contained in:
Philip Smart
2023-02-26 19:37:06 +00:00
parent e88777b04b
commit 09c9f0dadc
8 changed files with 213 additions and 82 deletions

View File

@@ -51,4 +51,4 @@ echo performance > /sys/devices//system/cpu/cpufreq/policy0/scaling_governor
echo 1200000 > /sys/devices//system/cpu/cpufreq/policy0/scaling_min_freq
# Done.
echo "FusionX loaded and configured in RFS mode."
echo "FusionX loaded and configured in TZFS mode."

View File

@@ -19,6 +19,7 @@
//
// History: Feb 2023 v1.0 - Source copied from zSoft and modified to run as a daemon, stripping
// out all low level control methods.
// v1.01 - Updates to make compatible with the TZFS changes.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -64,7 +65,7 @@ extern "C" {
#include "z80driver.h"
#include "tzpu.h"
#define VERSION "1.0"
#define VERSION "1.01"
#define AUTHOR "P.D.Smart"
#define COPYRIGHT "(c) 2018-23"
@@ -596,7 +597,7 @@ FRESULT loadZ80Memory(const char *src, uint32_t fileOffset, uint32_t addr, uint3
fr0 = (fseek(File, fileOffset, SEEK_SET) != -1) ? FR_OK : FR_DISK_ERR;
#if(DEBUG_ENABLED & 0x02)
if(Z80Ctrl->debug & 0x02) printf("Loading file(%s,%08lx,%08lx)\n", src, addr, size);
if(Z80Ctrl->debug >= 2) printf("Loading file(%s,%08lx,%08lx)\n", src, addr, size);
#endif
// If no errors in opening the file, proceed with reading and loading into memory.
@@ -2223,7 +2224,7 @@ uint8_t svcWriteCPMDrive(void)
if(!result)
{
#if(DEBUG_ENABLED & 0x02)
if(Z80Ctrl->debug & 0x02)
if(Z80Ctrl->debug >= 3)
{
printf("Writing offset=%08lx\n", fileOffset);
for(uint16_t idx=0; idx < TZSVC_SECTOR_SIZE; idx++)
@@ -2397,9 +2398,13 @@ FRESULT loadTZFS(char *biosFile, uint32_t loadAddr)
{
printf("Error: Failed to load page 3 of %s into tranZPUter memory.\n", MZ_ROM_TZFS);
}
if(!result && (result=loadZ80Memory((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_TZFS, 0x3800, MZ_BANKRAM_ADDR+0x30000, 0x1000, 0, TRANZPUTER) != FR_OK))
if(!result && (result=loadZ80Memory((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_TZFS, 0x3800, MZ_FULLRAM_START_ADDR+0x30000, MZ_FULLRAM_SIZE, 0, TRANZPUTER) != FR_OK))
{
printf("Error: Failed to load page 4 of %s into tranZPUter memory.\n", MZ_ROM_TZFS);
printf("Error: Failed to load page 4/1 of %s into tranZPUter memory.\n", MZ_ROM_TZFS);
}
if(!result && (result=loadZ80Memory((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_TZFS, 0x3800+MZ_FULLRAM_SIZE, MZ_BANKRAM_ADDR+0x30000, 0x1000, 0, TRANZPUTER) != FR_OK))
{
printf("Error: Failed to load page 4/2 of %s into tranZPUter memory.\n", MZ_ROM_TZFS);
}
return(result);
}
@@ -2431,7 +2436,7 @@ void loadTranZPUterDefaultROMS(uint8_t cpuConfig)
if(!result)
{
#if(DEBUG_ENABLED & 0x2)
if(Z80Ctrl->debug & 0x02) printf("Loading 1Z_013B\n");
if(Z80Ctrl->debug >= 2) printf("Loading 1Z_013B\n");
#endif
//result = loadBIOS(MZ_ROM_1Z_013B, MZ800, MZ_800_MROM_ADDR);
@@ -2446,7 +2451,7 @@ void loadTranZPUterDefaultROMS(uint8_t cpuConfig)
if(!result)
{
#if(DEBUG_ENABLED & 0x2)
if(Z80Ctrl->debug & 0x02) printf("Loading 9Z_504M\n");
if(Z80Ctrl->debug >= 2) printf("Loading 9Z_504M\n");
#endif
result = loadBIOS(MZ_ROM_9Z_504M, MZ_800_IPL_ADDR);
}
@@ -2455,7 +2460,7 @@ void loadTranZPUterDefaultROMS(uint8_t cpuConfig)
if(!result)
{
#if(DEBUG_ENABLED & 0x2)
if(Z80Ctrl->debug & 0x02) printf("Loading BASIC IOCS\n");
if(Z80Ctrl->debug >= 2) printf("Loading BASIC IOCS\n");
#endif
result = loadBIOS(MZ_ROM_800_IOCS, MZ_800_IOCS_ADDR);
}
@@ -2469,7 +2474,7 @@ void loadTranZPUterDefaultROMS(uint8_t cpuConfig)
case HW_MZ2000:
// Load up the IPL BIOS at least try even if the CGROM failed.
#if(DEBUG_ENABLED & 0x2)
if(Z80Ctrl->debug & 0x02) printf("Loading IPL\n");
if(Z80Ctrl->debug >= 2) printf("Loading IPL\n");
#endif
result = loadBIOS(MZ_ROM_MZ2000_IPL_TZPU, MZ_MROM_ADDR);
if(result != FR_OK)
@@ -2622,7 +2627,7 @@ void processServiceRequest(void)
// Load the 40 column version of the default host bios into memory.
case TZSVC_CMD_LOAD40ABIOS:
loadBIOS(MZ_ROM_SA1510_40C, MZ_MROM_ADDR);
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_SA1510_40C, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != HW_MZ80A)
@@ -2634,7 +2639,7 @@ void processServiceRequest(void)
// Load the 80 column version of the default host bios into memory.
case TZSVC_CMD_LOAD80ABIOS:
loadBIOS(MZ_ROM_SA1510_80C, MZ_MROM_ADDR);
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_SA1510_80C, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != HW_MZ80A)
@@ -2646,7 +2651,7 @@ void processServiceRequest(void)
// Load the 40 column MZ700 1Z-013A bios into memory for compatibility switch.
case TZSVC_CMD_LOAD700BIOS40:
loadBIOS(MZ_ROM_1Z_013A_40C, MZ_MROM_ADDR);
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_1Z_013A_40C, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != HW_MZ700)
@@ -2658,7 +2663,7 @@ void processServiceRequest(void)
// Load the 80 column MZ700 1Z-013A bios into memory for compatibility switch.
case TZSVC_CMD_LOAD700BIOS80:
loadBIOS(MZ_ROM_1Z_013A_80C, MZ_MROM_ADDR);
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_1Z_013A_80C, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != HW_MZ700)
@@ -2670,7 +2675,7 @@ void processServiceRequest(void)
// Load the MZ800 9Z-504M bios into memory for compatibility switch.
case TZSVC_CMD_LOAD800BIOS:
loadBIOS(MZ_ROM_9Z_504M, MZ_MROM_ADDR);
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_9Z_504M, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != HW_MZ800)
@@ -2682,7 +2687,7 @@ void processServiceRequest(void)
// Load the MZ-80B IPL ROM into memory for compatibility switch.
case TZSVC_CMD_LOAD80BIPL:
loadBIOS(MZ_ROM_MZ80B_IPL, MZ_MROM_ADDR);
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_MZ80B_IPL, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != HW_MZ80B)
@@ -2694,7 +2699,7 @@ void processServiceRequest(void)
// Load the MZ-2000 IPL ROM into memory for compatibility switch.
case TZSVC_CMD_LOAD2000IPL:
loadBIOS(MZ_ROM_MZ2000_IPL, MZ_MROM_ADDR);
loadBIOS((const char *)OS_BASE_DIR TZSVC_DEFAULT_TZFS_DIR "/" MZ_ROM_MZ2000_IPL, MZ_MROM_ADDR);
// Set the frequency of the CPU if we are emulating the hardware.
if(z80Control.hostType != HW_MZ2000)

View File

@@ -286,6 +286,10 @@
#define MZ_MROM_STACK_ADDR 0x01000 // Monitor ROM start stack address.
#define MZ_MROM_STACK_SIZE 0x000EF // Monitor ROM stack size.
#define MZ_UROM_ADDR 0x0E800 // User ROM start address.
#define MZ_FULLRAM_START_ADDR 0x01200 // Start of full memory area available for bank switching.
#define MZ_FULLRAM_SIZE 0xD000 - 0x1200 // Size of full memory area.
#define MZ_BANKRAM_ADDR 0x0F000 // Floppy API address which is used in TZFS as the paged RAM for additional functionality.
#define MZ_CMT_ADDR 0x010F0 // Address of the CMT (tape) header record.
#define MZ_CMT_DEFAULT_LOAD_ADDR 0x01200 // The default load address for a CMT, anything below this is normally illegal.

View File

@@ -127,6 +127,8 @@ 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 uint8_t memoryPage = 0;
// Method to obtain and return the output screen width.
//
@@ -211,6 +213,13 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryType, uint32_t
if(memoryType == 0)
return(-1);
// Make sure the memory page is valid if we are dumping them out.
if(memoryType == 3 && Z80PAGE[memoryPage] == NULL)
{
printf("Page %d is not allocated.\n", memoryPage);
return(-1);
}
// Reconfigure terminal to allow non-blocking key input.
//
set_conio_terminal_mode();
@@ -245,7 +254,10 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryType, uint32_t
{
case 16:
if(pnt+i < endAddr)
printf("%04X", memoryType == 1 ? (uint16_t)Z80RAM[pnt+i] : memoryType == 2 ? (uint16_t)Z80ROM[pnt+i] : memoryType == 3 ? (uint16_t)*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (pnt+i)) : (uint16_t)Z80Ctrl->iopage[pnt+i]);
printf("%04X", memoryType == 1 ? (uint16_t)Z80RAM[pnt+i] :
memoryType == 2 ? (uint16_t)Z80ROM[pnt+i] :
memoryType == 3 ? (uint16_t)*(*(Z80PAGE + memoryPage) + (pnt+i)) :
(uint16_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
@@ -253,7 +265,10 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryType, uint32_t
case 32:
if(pnt+i < endAddr)
printf("%08lX", memoryType == 1 ? (uint32_t)Z80RAM[pnt+i] : memoryType == 2 ? (uint32_t)Z80ROM[pnt+i] : memoryType == 3 ? (uint32_t)*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (pnt+i)) : (uint32_t)Z80Ctrl->iopage[pnt+i]);
printf("%08lX", memoryType == 1 ? (uint32_t)Z80RAM[pnt+i] :
memoryType == 2 ? (uint32_t)Z80ROM[pnt+i] :
memoryType == 3 ? (uint32_t)*(*(Z80PAGE + memoryPage) + (pnt+i)) :
(uint32_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
@@ -262,7 +277,10 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryType, uint32_t
case 8:
default:
if(pnt+i < endAddr)
printf("%02X", memoryType == 1 ? (uint8_t)Z80RAM[pnt+i] : memoryType == 2 ? (uint8_t)Z80ROM[pnt+i] : memoryType == 3 ? (uint8_t)*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (pnt+i)) : (uint8_t)Z80Ctrl->iopage[pnt+i]);
printf("%02X", memoryType == 1 ? (uint8_t)Z80RAM[pnt+i] :
memoryType == 2 ? (uint8_t)Z80ROM[pnt+i] :
memoryType == 3 ? (uint8_t)*(*(Z80PAGE + memoryPage) + (pnt+i)) :
(uint8_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
@@ -277,7 +295,9 @@ int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryType, uint32_t
// print single ascii char
for (i=0; i < displayWidth; i++)
{
c = memoryType == 1 ? (char)Z80RAM[pnt+i] : memoryType == 2 ? (char)Z80ROM[pnt+i] : memoryType == 3 ? (char)*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (pnt+i)) : (char)Z80Ctrl->iopage[pnt+i];
c = memoryType == 1 ? (char)Z80RAM[pnt+i] : memoryType == 2 ? (char)Z80ROM[pnt+i] :
memoryType == 3 ? (char)*(*(Z80PAGE + (uint32_t)memoryPage) + (pnt+i)) :
(char)Z80Ctrl->iopage[pnt+i];
if ((pnt+i < endAddr) && (c >= ' ') && (c <= '~'))
fputc((char)c, stdout);
else
@@ -721,10 +741,10 @@ void showArgs(char *progName, struct optparse *options)
printf(" # Load contents of binary file into memory at address. default = 0x000000.\n");
printf(" = LOADMEM --file <binary filename> --addr <24 bit addr> --type <0 - Host RAM, 1 = Virtual RAM, 2 = Virtual ROM> [--offset <offset> --len <length>]\n");
printf(" = SAVE --file <filename> --addr <24bit addr> --end <24bit addr> [--size <24bit>] --type <0 - Host RAM, 1 = Virtual RAM, 2 = Virtual ROM, 3 = PageTable, 4 = IOPageTable>\n");
printf(" = DUMP --addr <24bit addr> --end <24bit addr> [--size <24bit>] --type <0 - Host RAM, 1 = Virtual RAM, 2 = Virtual ROM, 3 = PageTable, 4 = IOPageTable>\n");
printf(" = DUMP --addr <24bit addr> --end <24bit addr> [--size <24bit>] --type <0 - Host RAM, 1 = Virtual RAM, 2 = Virtual ROM, 3 = MemoryPageTable, 4 = IOPageTable> [--memorypage <0..31>]\n");
printf(" = CPLDCMD --data <32bit command> # Send adhoc 32bit command to CPLD.\n");
#if(DEBUG_ENABLED != 0)
printf(" = DEBUG --level <level> # 0 = off, 1 = driver, 2 = k64f, 3 = both.\n");
printf(" = DEBUG --level <level> # 0 = off, 1..15 debug level, 15 is very verbose.\n");
#endif
printf(" = Z80TEST # Perform various debugging tests\n");
printf(" = SPITEST # Perform SPI testing\n");
@@ -741,6 +761,7 @@ int main(int argc, char *argv[])
char cmd[64] = { 0 };
char fileName[256] = { 0 };
char devName[32] = { 0 };
int idx;
int opt;
uint32_t hexData = 0;
long speedMultiplier = 1;
@@ -771,6 +792,7 @@ int main(int argc, char *argv[])
{"device", 'D', OPTPARSE_REQUIRED},
{"offset", 'O', OPTPARSE_REQUIRED},
{"len", 'L', OPTPARSE_REQUIRED},
{"memorypage", 'm', OPTPARSE_REQUIRED},
#if(DEBUG_ENABLED != 0)
{"level", 'l', OPTPARSE_REQUIRED},
#endif
@@ -847,9 +869,15 @@ int main(int argc, char *argv[])
memoryType = atoi(options.optarg);
break;
// Memory Page - which page, in the page table, to view.
case 'm':
memoryPage = atoi(options.optarg);
//printf("Memory Page:%02x\n", memoryPage);
break;
#if(DEBUG_ENABLED != 0)
// Debug level, 0 = off, 1 = driver, 2 = k64f, 3 = both.
case 'E':
// Debug level, 0 = off, 1..15 debug level, 15 is very verbose.
case 'l':
debugLevel = atoi(options.optarg);
break;
#endif
@@ -959,6 +987,13 @@ int main(int argc, char *argv[])
close(fdZ80);
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++)
{
// 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);
if(Z80PAGE[idx] == (void *)-1) Z80PAGE[idx] = NULL;
}
} else
{
printf("Failed to open the Z80 Driver, exiting...\n");
@@ -1029,7 +1064,7 @@ int main(int argc, char *argv[])
#if(DEBUG_ENABLED != 0)
if(strcasecmp(cmd, "DEBUG") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_DEBUG, debugLevel, 0, 0);
ctrlCmd(fdZ80, Z80_CMD_DEBUG, (long)debugLevel, 0, 0);
} else
#endif

View File

@@ -553,7 +553,7 @@ static zuint8 z80_read(void *context, zuint16 address)
Z80Ctrl->keyportHotKey = 0x01;
}
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
if(Z80Ctrl->debug >= 3)
{
pr_info("Read:%04x,%02x,%d\n", address, data, CPLD_Z80_INT());
}
@@ -601,7 +601,7 @@ static void z80_write(void *context, zuint16 address, zuint8 data)
writeVirtual(address, data, 0);
}
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
if(Z80Ctrl->debug >= 3)
{
pr_info("Write:%04x,%02x,%d\n", address, data, CPLD_Z80_INT());
}
@@ -663,10 +663,16 @@ static zuint8 z80_fetch_opcode(void *context, zuint16 address)
lookAhead(address, opcode, isVirtualROM((address+1)) ? readVirtualROM((address+1)) : readVirtualRAM((address+1)));
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
if(Z80Ctrl->debug >= 3)
{
if(address < 0xF036 || address > 0xF197)
pr_info("Fetch:%04x,%02x,%d\n", address, opcode, CPLD_Z80_INT());
// If max level, add delay so that the kernel log doesnt overflow.
if(Z80Ctrl->debug >= 15)
{
udelay(2000);
}
}
//if(address >= 0xE800) pr_info("Fetch:%04x,%02x\n", address, opcode);
#endif
@@ -712,7 +718,7 @@ static zuint8 z80_fetch(void *context, zuint16 address)
z80_int(&Z80CPU, CPLD_Z80_INT() != 0);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
if(Z80Ctrl->debug >= 4)
{
if(address < 0xF036 || address > 0xF197)
pr_info("FetchB:%04x,%02x,%d\n", address, data, CPLD_Z80_INT());
@@ -755,7 +761,7 @@ static zuint8 z80_in(void *context, zuint16 port)
}
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("z80_in:0x%x, 0x%x\n", port, value);
if(Z80Ctrl->debug >= 3) pr_info("z80_in:0x%x, 0x%x\n", port, value);
#endif
return(value);
}
@@ -794,7 +800,7 @@ static void z80_out(void *context, zuint16 port, zuint8 value)
}
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("z80_out:0x%x, 0x%x\n", port, value);
if(Z80Ctrl->debug >= 3) pr_info("z80_out:0x%x, 0x%x\n", port, value);
#endif
}
@@ -870,7 +876,7 @@ static void z80_reti(void *context)
if(CPLD_Z80_INT() != 0)
{
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
if(Z80Ctrl->debug >= 2)
{
pr_info("LOCKUP:%d\n", CPLD_Z80_INT());
}
@@ -878,7 +884,7 @@ static void z80_reti(void *context)
z80_int(&Z80CPU, false);
}
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("z80_reti\n");
if(Z80Ctrl->debug >= 3) pr_info("z80_reti\n");
#endif
}
static void z80_retn(void *context)
@@ -923,8 +929,6 @@ int thread_z80(void * thread_nr)
if(CPLD_RESET())
{
resetZ80();
//z80_instant_reset(&Z80CPU);
//setupMemory(Z80Ctrl->defaultPageMode);
// Wait for release before restarting CPU.
while(CPLD_RESET());
@@ -1028,6 +1032,7 @@ out:
static int z80drv_mmap(struct file *filp, struct vm_area_struct *vma)
{
// Locals.
int idx;
int ret = 0;
struct page *page = NULL;
unsigned long size = (unsigned long)(vma->vm_end - vma->vm_start);
@@ -1064,6 +1069,32 @@ static int z80drv_mmap(struct file *filp, struct vm_area_struct *vma)
goto out;
}
}
// 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)))
{
// 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++)
{
if(size >= ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + ((idx+1)*0x1000)) && size < ((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)) + ((idx+2) * 0x1000)))
{
// Map the memory if allocated and exit.
if(Z80Ctrl->page[idx] != NULL)
{
page = virt_to_page((unsigned long)Z80Ctrl->page[idx] + (vma->vm_pgoff << PAGE_SHIFT));
ret = remap_pfn_range(vma, vma->vm_start, page_to_pfn(page), size, vma->vm_page_prot);
if (ret != 0)
{
goto out;
}
} else
{
ret = -EINVAL;
goto out;
}
}
}
}
else
{
ret = -EINVAL;
@@ -1323,6 +1354,10 @@ void setupMemory(enum Z80_MEMORY_PROFILE mode)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_VRAM, idx);
@@ -1389,7 +1424,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
else
{
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("IOCTL - Command (%08x)\n", ioctlCmd.cmd);
if(Z80Ctrl->debug >=3) pr_info("IOCTL - Command (%08x)\n", ioctlCmd.cmd);
#endif
switch(ioctlCmd.cmd)
{
@@ -1402,7 +1437,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
z80_power(&Z80CPU, FALSE);
Z80_PC(Z80CPU) = 0;
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 stopped.\n");
if(Z80Ctrl->debug >= 3) pr_info("Z80 stopped.\n");
#endif
break;
@@ -1412,7 +1447,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
z80_power(&Z80CPU, TRUE);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 started.\n");
if(Z80Ctrl->debug >= 3) pr_info("Z80 started.\n");
#endif
break;
@@ -1420,7 +1455,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case IOCTL_CMD_Z80_PAUSE:
mutex_lock(&Z80RunModeMutex); Z80RunMode = Z80_PAUSE; mutex_unlock(&Z80RunModeMutex);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 paused.\n");
if(Z80Ctrl->debug >= 3) pr_info("Z80 paused.\n");
#endif
break;
@@ -1428,7 +1463,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case IOCTL_CMD_Z80_CONTINUE:
mutex_lock(&Z80RunModeMutex); Z80RunMode = Z80_CONTINUE; mutex_unlock(&Z80RunModeMutex);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 running.\n");
if(Z80Ctrl->debug >= 3) pr_info("Z80 running.\n");
#endif
break;
@@ -1443,7 +1478,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_lock(&Z80RunModeMutex); Z80RunMode = currentRunMode; mutex_unlock(&Z80RunModeMutex);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 Reset.\n");
if(Z80Ctrl->debug >= 3) pr_info("Z80 Reset.\n");
#endif
break;
@@ -1459,7 +1494,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_lock(&Z80RunModeMutex); Z80RunMode = currentRunMode; mutex_unlock(&Z80RunModeMutex);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 Set to use Host Memory.\n");
if(Z80Ctrl->debug >= 3) pr_info("Z80 Set to use Host Memory.\n");
#endif
break;
@@ -1478,7 +1513,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_lock(&Z80RunModeMutex); Z80RunMode = currentRunMode; mutex_unlock(&Z80RunModeMutex);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 Set to use Virtual Memory.\n");
if(Z80Ctrl->debug >= 3) pr_info("Z80 Set to use Virtual Memory.\n");
#endif
break;
@@ -1497,7 +1532,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_lock(&Z80RunModeMutex); Z80RunMode = currentRunMode; mutex_unlock(&Z80RunModeMutex);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 Host DRAM syncd with Virtual Memory.\n");
if(Z80Ctrl->debug >= 3) pr_info("Z80 Host DRAM syncd with Virtual Memory.\n");
#endif
break;
@@ -1706,6 +1741,7 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
// Method to turn on/off debug output.
case IOCTL_CMD_DEBUG:
Z80Ctrl->debug = ioctlCmd.debug.level;
pr_info("Debug level set to:%d\n", Z80Ctrl->debug);
break;
#endif
@@ -2014,6 +2050,11 @@ static int __init ModuleInit(void)
Z80_PC(Z80CPU) = 0;
z80_power(&Z80CPU, TRUE);
// Initialise Debug logic if compile time enabled.
#if(DEBUG_ENABLED != 0)
Z80Ctrl->debug = 0;
#endif
// Init done.
pr_info("Initialisation complete.\n");

View File

@@ -53,7 +53,7 @@
#define DEVICE_NAME "z80drv"
#define CLASS_NAME "mogu"
#define IO_PROCESSOR_NAME "k64fcpu" // Name of the I/O processor user space application.
#define DEBUG_ENABLED 1
#define DEBUG_ENABLED 0 // 0 = disabled, 1 = z80driver, 2 = k64fcpu, 3 = both.
// Memory and IO page types. Used to create a memory page which maps type of address space to real address space on host or virtual memory.
#define MEMORY_TYPE_VIRTUAL_MASK 0x00FFFFFF
@@ -71,6 +71,23 @@
#define IO_TYPE_PHYSICAL_HW 0x80000000
#define IO_TYPE_VIRTUAL_HW 0x40000000
//*********************************************************************************************
// Delay periods for the various hosts, which need adding to the primary opcode fetch in
// order to govern the virtual Z80 to a known speed. The timings are only used within
// virtual memory, if an opcode is being fetched from physical memory will self govern to the
// host speed.
// NB. As of v1.0 FusionX hardware, unless a method is forthcoming due to the low speed of the
// SSD202 CPU GPIO access (72MHz bus speed, 1x72MHz per bit, in theory 2.2M 32bit words per
// second, in practice 2MBytes per second! This is a shortcoming of the SSD202 CPU, others,
// such as the NXP K64FX512 Cortex-M4 has 32bit registers where a single access can write
// /read/toggle/clear 32bits and the bus is operating at 85MHz! If SigmaStar release an updated
// CPU, or another compatible system becomes available, v1.1 of the FusionX hardware will be
// created in order to allow full speed program execution within host memory.
// NBB: Actual Z80 transactions run at full speed, it is just the period from completion
// of 1 cycle to the next taking too much time in the SSD202 to setup. Workarounds using
// lookahead and queue techniques have been adopted to ensure I/O timing for things such as
// floppy drives functions as per the original host.
//*********************************************************************************************
// Approximate governor delays to regulate emulated CPU speed.
// MZ-700
@@ -184,23 +201,47 @@ enum Z80_INSTRUCTION_DELAY {
#endif
// MZ-80A - These values are dependent on the CPU Freq of the SSD202. Values are for 1.2GHz, in brackets for 1.0GHz
// The reason for having 2 sets of delays is due to original coding where ROM memory required less instructions
// than RAM. Also depending upon build slight differences need to be catered for, ie. when including debug logic
// there are extra instructions to process during the fetch cycle.
#if(TARGET_HOST_MZ80A == 1)
#define INSTRUCTION_DELAY_ROM_2MHZ 436 // (420)
#define INSTRUCTION_DELAY_ROM_4MHZ 218
#define INSTRUCTION_DELAY_ROM_8MHZ 109
#define INSTRUCTION_DELAY_ROM_16MHZ 54
#define INSTRUCTION_DELAY_ROM_32MHZ 27
#define INSTRUCTION_DELAY_ROM_64MHZ 14
#define INSTRUCTION_DELAY_ROM_128MHZ 7
#define INSTRUCTION_DELAY_ROM_256MHZ 3
#define INSTRUCTION_DELAY_RAM_2MHZ 420
#define INSTRUCTION_DELAY_RAM_4MHZ 210
#define INSTRUCTION_DELAY_RAM_8MHZ 105
#define INSTRUCTION_DELAY_RAM_16MHZ 52
#define INSTRUCTION_DELAY_RAM_32MHZ 26
#define INSTRUCTION_DELAY_RAM_64MHZ 13
#define INSTRUCTION_DELAY_RAM_128MHZ 7
#define INSTRUCTION_DELAY_RAM_256MHZ 0
#if(DEBUG_ENABLED > 0)
#define INSTRUCTION_DELAY_ROM_2MHZ 427 // (420)
#define INSTRUCTION_DELAY_ROM_4MHZ 218
#define INSTRUCTION_DELAY_ROM_8MHZ 109
#define INSTRUCTION_DELAY_ROM_16MHZ 54
#define INSTRUCTION_DELAY_ROM_32MHZ 27
#define INSTRUCTION_DELAY_ROM_64MHZ 14
#define INSTRUCTION_DELAY_ROM_128MHZ 7
#define INSTRUCTION_DELAY_ROM_256MHZ 3
#define INSTRUCTION_DELAY_RAM_2MHZ 425
#define INSTRUCTION_DELAY_RAM_4MHZ 212
#define INSTRUCTION_DELAY_RAM_8MHZ 106
#define INSTRUCTION_DELAY_RAM_16MHZ 53
#define INSTRUCTION_DELAY_RAM_32MHZ 26
#define INSTRUCTION_DELAY_RAM_64MHZ 13
#define INSTRUCTION_DELAY_RAM_128MHZ 7
#define INSTRUCTION_DELAY_RAM_256MHZ 0
#endif
#if(DEBUG_ENABLED == 0)
#define INSTRUCTION_DELAY_ROM_2MHZ 429 // (420)
#define INSTRUCTION_DELAY_ROM_4MHZ 218
#define INSTRUCTION_DELAY_ROM_8MHZ 109
#define INSTRUCTION_DELAY_ROM_16MHZ 54
#define INSTRUCTION_DELAY_ROM_32MHZ 27
#define INSTRUCTION_DELAY_ROM_64MHZ 14
#define INSTRUCTION_DELAY_ROM_128MHZ 7
#define INSTRUCTION_DELAY_ROM_256MHZ 3
#define INSTRUCTION_DELAY_RAM_2MHZ 425
#define INSTRUCTION_DELAY_RAM_4MHZ 210
#define INSTRUCTION_DELAY_RAM_8MHZ 105
#define INSTRUCTION_DELAY_RAM_16MHZ 52
#define INSTRUCTION_DELAY_RAM_32MHZ 26
#define INSTRUCTION_DELAY_RAM_64MHZ 13
#define INSTRUCTION_DELAY_RAM_128MHZ 7
#define INSTRUCTION_DELAY_RAM_256MHZ 0
#endif
#define INSTRUCTION_EQUIV_FREQ_2MHZ 2000000
#define INSTRUCTION_EQUIV_FREQ_4MHZ 4000000
#define INSTRUCTION_EQUIV_FREQ_8MHZ 8000000
@@ -210,6 +251,7 @@ enum Z80_INSTRUCTION_DELAY {
#define INSTRUCTION_EQUIV_FREQ_128MHZ 128000000
#define INSTRUCTION_EQUIV_FREQ_256MHZ 256000000
// Table of governor delays to be used to control run frequency,
enum Z80_INSTRUCTION_DELAY {
ROM_DELAY_NORMAL = INSTRUCTION_DELAY_ROM_2MHZ,
ROM_DELAY_X2 = INSTRUCTION_DELAY_ROM_4MHZ,
@@ -495,7 +537,7 @@ typedef struct {
// An I/O processor, running as a User Space daemon, can register to receive signals and events.
struct task_struct *ioTask;
#if(DEBUG_ENABLED == 1)
#if(DEBUG_ENABLED != 0)
// Debugging flag.
uint8_t debug;
#endif
@@ -520,7 +562,7 @@ struct virtual_device {
struct cpld_ctrl {
uint32_t cmd;
};
#if(DEBUG_ENABLED == 1)
#if(DEBUG_ENABLED != 0)
struct debug {
uint8_t level;
};
@@ -533,7 +575,7 @@ struct ioctlCmd {
struct speed speed;
struct virtual_device vdev;
struct cpld_ctrl cpld;
#if(DEBUG_ENABLED == 1)
#if(DEBUG_ENABLED != 0)
struct debug debug;
#endif
};

View File

@@ -185,7 +185,7 @@ void rfsSetupMemory(enum Z80_MEMORY_PROFILE mode)
// Setup the initial state of the latch up-counter, used to enable access to the programmable registers.
RFSCtrl.upCntr = ((RFSCtrl.regCtrl & 0x20) >> 2) | ((RFSCtrl.regCtrl & 0x10) >> 2) | ((RFSCtrl.regCtrl & 0x08) >> 2);
// Initialise the page pointers and memory to use physical RAM.
// Initialise the page pointers and memory to reflect an MZ-80A with an RFS board installed.
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0x0000 && idx < 0x1000)

View File

@@ -167,7 +167,7 @@ static inline uint8_t tzpuRead(zuint16 address, uint8_t ioFlag)
if(ioFlag)
{
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("Read IO:%02x\n", address);
if(Z80Ctrl->debug >= 3) pr_info("Read IO:%02x\n", address);
#endif
// Only the lower 8 bits of the I/O address are processed as the upper byte is not used in the Sharp models.
@@ -252,7 +252,7 @@ static inline void tzpuWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
if(Z80Ctrl->page[Z80Ctrl->memoryMode] == NULL)
{
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("Allocating memory page:%d\n", Z80Ctrl->memoryMode);
if(Z80Ctrl->debug >=3) pr_info("Allocating memory page:%d\n", Z80Ctrl->memoryMode);
#endif
(Z80Ctrl->page[Z80Ctrl->memoryMode]) = (uint32_t *)kmalloc((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)), GFP_KERNEL);
if ((Z80Ctrl->page[Z80Ctrl->memoryMode]) == NULL)
@@ -425,10 +425,14 @@ static inline void tzpuWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
else if(idx >= 0x1000 && idx < 0x1200)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1200 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK3_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
@@ -655,27 +659,27 @@ static inline void tzpuWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
case IO_TZ_SETXMHZ:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("SETXMHZ:%02x\n", data);
if(Z80Ctrl->debug >= 3) pr_info("SETXMHZ:%02x\n", data);
#endif
TZPUCtrl.clkSrc = 1;
break;
case IO_TZ_SET2MHZ:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("SET2MHZ:%02x\n", data);
if(Z80Ctrl->debug >= 3) pr_info("SET2MHZ:%02x\n", data);
#endif
TZPUCtrl.clkSrc = 0;
break;
case IO_TZ_CLKSELRD:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("CKSELRD:%02x\n", data);
if(Z80Ctrl->debug >= 3) pr_info("CKSELRD:%02x\n", data);
#endif
break;
case IO_TZ_SVCREQ:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("SVCREQ:%02x\n", data);
if(Z80Ctrl->debug >= 3) pr_info("SVCREQ:%02x\n", data);
#endif
// If a k64f process has registered, send it a service request signal.
@@ -696,32 +700,32 @@ static inline void tzpuWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
case IO_TZ_SYSREQ:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("SYSREQ:%02x\n", data);
if(Z80Ctrl->debug >= 3) pr_info("SYSREQ:%02x\n", data);
#endif
break;
case IO_TZ_CPLDCMD:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("CPLDCMD:%02x\n", data);
if(Z80Ctrl->debug >= 3) pr_info("CPLDCMD:%02x\n", data);
#endif
TZPUCtrl.regCmd = data;
break;
case IO_TZ_CPUINFO:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("CPUINFO:%02x\n", data);
if(Z80Ctrl->debug >= 3) pr_info("CPUINFO:%02x\n", data);
#endif
break;
case IO_TZ_CPLDCFG:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("CPLDCFG:%02x\n", data);
if(Z80Ctrl->debug >= 3) pr_info("CPLDCFG:%02x\n", data);
#endif
break;
case IO_TZ_CPLDINFO:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("CPLDINFO:%02x\n", data);
if(Z80Ctrl->debug >= 3) pr_info("CPLDINFO:%02x\n", data);
#endif
break;