Added TZFS device driver and K64F CPU

This commit is contained in:
Philip Smart
2023-02-22 14:53:46 +00:00
parent 652bdd81eb
commit a3cfebc7f9
12 changed files with 5148 additions and 194 deletions

5
.gitignore vendored
View File

@@ -341,6 +341,7 @@ software/FusionX/src/driver/Z80
software/FusionX/src/driver/Z80/
software/FusionX/src/driver/Z80.c.old
software/FusionX/src/driver/z80ctrl
software/FusionX/src/driver/k64fcpu
software/FusionX/src/driver/Z80.rc.in
software/FusionX/src/hello
software/FusionX/src/spitools
@@ -1681,3 +1682,7 @@ software/FusionX/src/driver/MZ80A/z80vhw_rfs.c.bad
software/FusionX/disk
software/FusionX/roms
software/linux/project/FusionX/
software/FusionX/src/driver/MZ80A/k64fcpu.c.hld
software/linux/buildroot/.config.old
software/linux/kernel/scripts/kconfig/.mconf.cmd

View File

@@ -33,10 +33,10 @@ insmod z80drv.ko
sleep 1
# Load the original RFS ROM images.
${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/MROM_256_${SCREENWIDTH}c.bin --addr 0x000000
${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/USER_ROM_256_${SCREENWIDTH}c.bin --addr 0x80000
${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/USER_ROM_II_256_${SCREENWIDTH}c.bin --addr 0x100000
${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/USER_ROM_III_256_${SCREENWIDTH}c.bin --addr 0x180000
${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/MROM_256_${SCREENWIDTH}c.bin --addr 0x000000 --type 1
${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/USER_ROM_256_${SCREENWIDTH}c.bin --addr 0x80000 --type 1
${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/USER_ROM_II_256_${SCREENWIDTH}c.bin --addr 0x100000 --type 1
${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/rom/USER_ROM_III_256_${SCREENWIDTH}c.bin --addr 0x180000 --type 1
# Add the RFS Virtual Hardware to the driver.
${FUSIONXDIR}/bin/z80ctrl --adddev --device rfs

View File

@@ -0,0 +1,54 @@
#!/bin/sh
FUSIONXDIR=/apps/FusionX
# Setup screen width, used to load correct Monitor ROM image.
SCREENWIDTH=40
if [[ "$#" -ne 0 ]]; then
if [[ "$1" -eq 80 ]]; then
SCREENWIDTH=80
fi
fi
echo "Screen width set to: ${SCREENWIDTH}"
# Detach CPU 1 from scheduler and IRQ's as it will be dedicated to the z80drv.
for f in `ps -eaf |grep -v kthread_z80 | awk '{print $1}'`
do
taskset -pc 0 $f >/dev/null 2>/dev/null
done
# Detach IRQ's
for I in $(ls /proc/irq)
do
if [[ -d "/proc/irq/$I" ]]
then
echo 0 > /proc/irq/$I/smp_affinity_list 2>/dev/null
fi
done
# Load the Z80 driver. Small pause to ensure the driver is fully loaded and initialsed prior to loading ROM images.
cd ${FUSIONXDIR}/modules
rmmod z80drv 2>/dev/null
insmod z80drv.ko
sleep 1
# Load the original Monitor and TZFS ROM images. This is done in the K64F daemon but can be manually enabled.
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/monitor_${SCREENWIDTH}c_sa1510.rom --addr 0x000000 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/tzfs.rom --offset 0x000000 --len 0x001800 --addr 0x00E800 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/tzfs.rom --offset 0x001800 --len 0x001000 --addr 0x01F000 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/tzfs.rom --offset 0x002800 --len 0x001000 --addr 0x02F000 --type 1
#${FUSIONXDIR}/bin/z80ctrl --loadrom --file ${FUSIONXDIR}/roms/tzfs.rom --offset 0x003800 --len 0x001000 --addr 0x03F000 --type 1
# Add the TZPU Virtual Hardware to the driver.
${FUSIONXDIR}/bin/z80ctrl --adddev --device tzpu
# Start the K64F Virtual CPU Emulation.
${FUSIONXDIR}/bin/k64fcpu &
# Ensure the system is set for performance mode with max frequency.
# NB: Enabling this prior to starting the Z80 results in a kernel error.
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."

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,738 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: tzpu.h
// Created: May 2020
// Author(s): Philip Smart
// Description: The TranZPUter library.
// This file is copied from the original zSoft tranZPUter library header file and
// modified for the FusionX tranZPUter SW driver. It is used by the Z80 driver and the
// user space daemon.
// Hardware references have been removed as the K64F is a virtual process rather
// than a physical MPU.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: May 2020 - Initial write of the TranZPUter software.
// Jul 2020 - Updates to accommodate v2.1 of the tranZPUter board.
// Sep 2020 - Updates to accommodate v2.2 of the tranZPUter board.
// May 2021 - Changes to use 512K-1Mbyte Z80 Static RAM, build time configurable.
// Feb 2023 - Adaptation of zSoft tranzputer.h for the FusionX tranZPUter SW driver.
//
// Notes: See Makefile to enable/disable conditional components
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file is free software: you can redistribute it and#or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef TZPU_H
#define TZPU_H
#ifdef __cplusplus
extern "C" {
#endif
// Configurable constants.
//
#define REFRESH_BYTE_COUNT 8 // This constant controls the number of bytes read/written to the z80 bus before a refresh cycle is needed.
#define RFSH_BYTE_CNT 256 // Number of bytes we can write before needing a full refresh for the DRAM.
#define HOST_MON_TEST_VECTOR 0x4 // Address in the host monitor to test to identify host type.
#define OS_BASE_DIR "/apps/FusionX/disk/MZ-80A/" // Linux base directory where all the files are stored. On a real tranZPUter this would be the SD card root dir.
#define TZFS_AUTOBOOT_FLAG OS_BASE_DIR "/TZFSBOOT.FLG" // Filename used as a flag, if this file exists in the base directory then TZFS is booted automatically.
#define TZ_MAX_Z80_MEM 0x100000 // Maximum Z80 memory available on the tranZPUter board.
// tranZPUter Memory Modes - select one of the 32 possible memory models using these constants.
//
#define TZMM_ORIG 0x00 // Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
#define TZMM_BOOT 0x01 // Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
#define TZMM_TZFS 0x02 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
#define TZMM_TZFS2 0x03 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
#define TZMM_TZFS3 0x04 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
#define TZMM_TZFS4 0x05 // TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
#define TZMM_CPM 0x06 // CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
#define TZMM_CPM2 0x07 // CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
// Special case for 0000:003F (interrupt vectors) which resides in block 4, F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
#define TZMM_COMPAT 0x08 // Original mode but with main DRAM in Bank 0 to allow bootstrapping of programs from other machines such as the MZ700.
#define TZMM_HOSTACCESS 0x09 // Mode to allow code running in Bank 0, address E800:FFFF to access host memory. Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
#define TZMM_MZ700_0 0x0a // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
#define TZMM_MZ700_1 0x0b // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
#define TZMM_MZ700_2 0x0c // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
#define TZMM_MZ700_3 0x0d // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
#define TZMM_MZ700_4 0x0e // MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
#define TZMM_MZ800 0x0f // MZ800 Mode - Host is an MZ-800 and mode provides for MZ-700/MZ-800 decoding per original machine.
#define TZMM_MZ2000 0x10 // MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
#define TZMM_FPGA 0x15 // Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
#define TZMM_TZPUM 0x16 // Everything is on mainboard, no access to tranZPUter memory.
#define TZMM_TZPU 0x17 // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory. K64F drives A18-A16 allowing full access to RAM.
//#define TZMM_TZPU0 0x18 // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
//#define TZMM_TZPU1 0x19 // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
//#define TZMM_TZPU2 0x1A // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
//#define TZMM_TZPU3 0x1B // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
//#define TZMM_TZPU4 0x1C // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
//#define TZMM_TZPU5 0x1D // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
//#define TZMM_TZPU6 0x1E // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
//#define TZMM_TZPU7 0x1F // Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.
// IO addresses on the tranZPUter or mainboard.
//
#define IO_TZ_CTRLLATCH 0x60 // Control latch which specifies the Memory Model/mode.
#define IO_TZ_SETXMHZ 0x62 // Switch to alternate CPU frequency provided by K64F.
#define IO_TZ_SET2MHZ 0x64 // Switch to system CPU frequency.
#define IO_TZ_CLKSELRD 0x66 // Read the status of the clock select, ie. which clock is connected to the CPU.
#define IO_TZ_SVCREQ 0x68 // Service request from the Z80 to be provided by the K64F.
#define IO_TZ_SYSREQ 0x6A // System request from the Z80 to be provided by the K64F.
#define IO_TZ_CPLDCMD 0x6B // Version 2.1 CPLD command register.
#define IO_TZ_CPLDSTATUS 0x6B // Version 2.1 CPLD status register.
#define IO_TZ_CPUCFG 0x6C // Version 2.2 CPU configuration register.
#define IO_TZ_CPUSTATUS 0x6C // Version 2.2 CPU runtime status register.
#define IO_TZ_CPUINFO 0x6D // Version 2.2 CPU information register.
#define IO_TZ_CPLDCFG 0x6E // Version 2.1 CPLD configuration register.
#define IO_TZ_CPLDINFO 0x6F // Version 2.1 CPLD version information register.
#define IO_TZ_PALSLCTOFF 0xA3 // set the palette slot Off position to be adjusted.
#define IO_TZ_PALSLCTON 0xA4 // set the palette slot On position to be adjusted.
#define IO_TZ_PALSETRED 0xA5 // set the red palette value according to the PALETTE_PARAM_SEL address.
#define IO_TZ_PALSETGREEN 0xA6 // set the green palette value according to the PALETTE_PARAM_SEL address.
#define IO_TZ_PALSETBLUE 0xA7 // set the blue palette value according to the PALETTE_PARAM_SEL address.
#define IO_TZ_OSDMNU_SZX 0xA8 // Get OSD Menu Horizontal Size (X).
#define IO_TZ_OSDMNU_SZY 0xA9 // Get OSD Menu Vertical Size (Y).
#define IO_TZ_OSDHDR_SZX 0xAA // Get OSD Status Header Horizontal Size (X).
#define IO_TZ_OSDHDR_SZY 0xAB // Get OSD Status Header Vertical Size (Y).
#define IO_TZ_OSDFTR_SZX 0xAC // Get OSD Status Footer Horizontal Size (X).
#define IO_TZ_OSDFTR_SZY 0xAD // Get OSD Status Footer Vertical Size (Y).
#define IO_TZ_PALETTE 0xB0 // Sets the palette. The Video Module supports 4 bit per colour output but there is only enough RAM for 1 bit per colour so the pallette is used to change the colours output.
// Bits [7:0] defines the pallete number. This indexes a lookup table which contains the required 4bit output per 1bit input.
#define IO_TZ_GPUPARAM 0xB2 // Set parameters. Store parameters in a long word to be used by the graphics command processor.
// The parameter word is 128 bit and each write to the parameter word shifts left by 8 bits and adds the new byte at bits 7:0.
#define IO_TZ_GPUCMD 0xB3 // Set the graphics processor unit commands.
// Bits [5:0] - 0 = Reset parameters.
// 1 = Clear to val. Start Location (16 bit), End Location (16 bit), Red Filter, Green Filter, Blue Filter
#define IO_TZ_VMCTRL 0xB8 // Video Module control register. [2:0] - 000 (default) = MZ80A, 001 = MZ-700, 010 = MZ800, 011 = MZ80B, 100 = MZ80K, 101 = MZ80C, 110 = MZ1200, 111 = MZ2000. [3] = 0 - 40 col, 1 - 80 col.
#define IO_TZ_VMGRMODE 0xB9 // Video Module graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
#define IO_TZ_VMREDMASK 0xBA // Video Module Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMGREENMASK 0xBB // Video Module Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMBLUEMASK 0xBC // Video Module Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
#define IO_TZ_VMPAGE 0xBD // Video Module memory page register. [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. Bits [1:0] = page, 00 = off, 01 = Red, 10 = Green, 11 = Blue. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.
#define IO_TZ_VMVGATTR 0xBE // Select VGA Border colour and attributes. Bit 2 = Red, 1 = Green, 0 = Blue, 4:3 = VGA Mode, 00 = Off, 01 = 640x480, 10 = 800x600, 11 = 50Hz Internal
#define IO_TZ_VMVGAMODE 0xBF // Select VGA Output mode, ie. Internal, 640x480 etc. Bits [3:0] specify required mode. Undefined default to internal standard frequency.
#define IO_TZ_GDGWF 0xCC // MZ-800 write format register
#define IO_TZ_GDGRF 0xCD // MZ-800 read format register
#define IO_TZ_GDCMD 0xCE // MZ-800 CRTC Mode register
#define IO_TZ_GDCCTRL 0xCF // MZ-800 CRTC control register
#define IO_TZ_MMIO0 0xE0 // MZ-700/MZ-800 Memory management selection ports.
#define IO_TZ_MMIO1 0xE1 // ""
#define IO_TZ_MMIO2 0xE2 // ""
#define IO_TZ_MMIO3 0xE3 // ""
#define IO_TZ_MMIO4 0xE4 // ""
#define IO_TZ_MMIO5 0xE5 // ""
#define IO_TZ_MMIO6 0xE6 // ""
#define IO_TZ_MMIO7 0xE7 // MZ-700/MZ-800 Memory management selection ports.
#define IO_TZ_PPIA 0xE0 // MZ80B/MZ2000 8255 PPI Port A
#define IO_TZ_PPIB 0xE1 // MZ80B/MZ2000 8255 PPI Port B
#define IO_TZ_PPIC 0xE2 // MZ80B/MZ2000 8255 PPI Port C
#define IO_TZ_PPICTL 0xE3 // MZ80B/MZ2000 8255 PPI Control Register
#define IO_TZ_PIT0 0xE4 // MZ80B/MZ2000 8253 PIT Timer 0
#define IO_TZ_PIT1 0xE5 // MZ80B/MZ2000 8253 PIT Timer 1
#define IO_TZ_PIT2 0xE6 // MZ80B/MZ2000 8253 PIT Timer 2
#define IO_TZ_PITCTL 0xE7 // MZ80B/MZ2000 8253 PIT Control Register
#define IO_TZ_PIOA 0xE8 // MZ80B/MZ2000 Z80 PIO Port A
#define IO_TZ_PIOCTLA 0xE9 // MZ80B/MZ2000 Z80 PIO Port A Control Register
#define IO_TZ_PIOB 0xEA // MZ80B/MZ2000 Z80 PIO Port B
#define IO_TZ_PIOCTLB 0xEB // MZ80B/MZ2000 Z80 PIO Port B Control Register
#define IO_TZ_SYSCTRL 0xF0 // System board control register. [2:0] - 000 MZ80A Mode, 2MHz CPU/Bus, 001 MZ80B Mode, 4MHz CPU/Bus, 010 MZ700 Mode, 3.54MHz CPU/Bus.
#define IO_TZ_GRAMMODE 0xF4 // MZ80B Graphics mode. Bit 0 = 0, Write to Graphics RAM I, Bit 0 = 1, Write to Graphics RAM II. Bit 1 = 1, blend Graphics RAM I output on display, Bit 2 = 1, blend Graphics RAM II output on display.
//#define IO_TZ_GRAMOPT 0xF4 // MZ80B/MZ2000 GRAM configuration option.
#define IO_TZ_CRTGRPHPRIO 0xF5 // MZ2000 Graphics priority register, character or a graphics colour has front display priority.
#define IO_TZ_CRTGRPHSEL 0xF6 // MZ2000 Graphics output select on CRT or external CRT
#define IO_TZ_GRAMCOLRSEL 0xF7 // MZ2000 Graphics RAM colour bank select.
// Addresses on the tranZPUter board.
//
#define SRAM_BANK0_ADDR 0x00000 // Address of the 1st 64K RAM bank in the SRAM chip.
#define SRAM_BANK1_ADDR 0x10000 // ""
#define SRAM_BANK2_ADDR 0x20000 // ""
#define SRAM_BANK3_ADDR 0x30000 // ""
#define SRAM_BANK4_ADDR 0x40000 // ""
#define SRAM_BANK5_ADDR 0x50000 // ""
#define SRAM_BANK6_ADDR 0x60000 // ""
#define SRAM_BANK7_ADDR 0x70000 // ""
#define SRAM_BANK8_ADDR 0x80000 // ""
#define SRAM_BANK9_ADDR 0x90000 // ""
#define SRAM_BANKA_ADDR 0xA0000 // ""
#define SRAM_BANKB_ADDR 0xB0000 // ""
#define SRAM_BANKC_ADDR 0xC0000 // ""
#define SRAM_BANKD_ADDR 0xD0000 // ""
#define SRAM_BANKE_ADDR 0xE0000 // ""
#define SRAM_BANKF_ADDR 0xF0000 // Address of the 16th 64K RAM bank in the SRAM chip.
// IO register constants.
//
#define CPUMODE_SET_Z80 0x00 // Set the CPU to the hard Z80.
#define CPUMODE_SET_T80 0x01 // Set the CPU to the soft T80.
#define CPUMODE_SET_ZPU_EVO 0x02 // Set the CPU to the soft ZPU Evolution.
#define CPUMODE_SET_EMU_MZ 0x04 //
#define CPUMODE_SET_BBB 0x08 // Place holder for a future soft CPU.
#define CPUMODE_SET_CCC 0x10 // Place holder for a future soft CPU.
#define CPUMODE_SET_DDD 0x20 // Place holder for a future soft CPU.
#define CPUMODE_IS_Z80 0x00 // Status value to indicate if the hard Z80 available.
#define CPUMODE_IS_T80 0x01 // Status value to indicate if the soft T80 available.
#define CPUMODE_IS_ZPU_EVO 0x02 // Status value to indicate if the soft ZPU Evolution available.
#define CPUMODE_IS_EMU_MZ 0x04 // Status value to indicate if the Sharp MZ Series Emulation is available.
#define CPUMODE_IS_BBB 0x08 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_IS_CCC 0x10 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_IS_DDD 0x20 // Place holder to indicate if a future soft CPU is available.
#define CPUMODE_CLK_EN 0x40 // Toggle the soft CPU clock, 1 = enable, 0 = disable.
#define CPUMODE_RESET_CPU 0x80 // Reset the soft CPU. Active high, when high the CPU is held in RESET, when low the CPU runs.
#define CPUMODE_IS_SOFT_AVAIL 0x040 // Marker to indicate if the underlying FPGA can support soft CPU's.
#define CPUMODE_IS_SOFT_MASK 0x03F // Mask to filter out the Soft CPU availability flags.
// CPLD Configuration constants.
#define HWMODE_MZ80K 0x00 // Hardware mode = MZ80K
#define HWMODE_MZ80C 0x01 // Hardware mode = MZ80C
#define HWMODE_MZ1200 0x02 // Hardware mode = MZ1200
#define HWMODE_MZ80A 0x03 // Hardware mode = MZ80A
#define HWMODE_MZ700 0x04 // Hardware mode = MZ700
#define HWMODE_MZ800 0x05 // Hardware mode = MZ800
#define HWMODE_MZ80B 0x06 // Hardware mode = MZ80B
#define HWMODE_MZ2000 0x07 // Hardware mode = MZ2000
#define MODE_VIDEO_MODULE_ENABLED 0x08 // Hardware enable (bit 3 = 1) or disable of the Video Module on the newer version, the one below will be removed.
#define MODE_VIDEO_MODULE_DISABLED 0x00 // Hardware enable (bit 3 = 0) or disable of the Video Module.
#define MODE_PRESERVE_CONFIG 0x80 // Preserve hardware configuration on RESET.
#define CPLD_HAS_FPGA_VIDEO 0x00 // Flag to indicate if this device supports enhanced video.
#define CPLD_VERSION 0x01 // Version of the CPLD which is being emulated. Version 1 was the original version.
// CPLD Command Instruction constants.
#define CPLD_RESET_HOST 1 // CPLD level command to reset the host system.
#define CPLD_HOLD_HOST_BUS 2 // CPLD command to hold the host bus.
#define CPLD_RELEASE_HOST_BUS 3 // CPLD command to release the host bus.
// Video Module control bits.
#define SYSMODE_MZ80A 0x00 // System board mode MZ80A, 2MHz CPU/Bus.
#define SYSMODE_MZ80B 0x01 // System board mode MZ80B, 4MHz CPU/Bus.
#define SYSMODE_MZ700 0x02 // System board mode MZ700, 3.54MHz CPU/Bus.
#define VMMODE_MASK 0xF0 // Mask to mask out video mode.
#define VMMODE_MZ80K 0x00 // Video mode = MZ80K
#define VMMODE_MZ80C 0x01 // Video mode = MZ80C
#define VMMODE_MZ1200 0x02 // Video mode = MZ1200
#define VMMODE_MZ80A 0x03 // Video mode = MZ80A
#define VMMODE_MZ700 0x04 // Video mode = MZ700
#define VMMODE_MZ800 0x05 // Video mode = MZ800
#define VMMODE_MZ1500 0x06 // Video mode = MZ1500
#define VMMODE_MZ80B 0x07 // Video mode = MZ80B
#define VMMODE_MZ2000 0x08 // Video mode = MZ2000
#define VMMODE_MZ2200 0x09 // Video mode = MZ2200
#define VMMODE_MZ2500 0x0A // Video mode = MZ2500
#define VMMODE_80CHAR 0x10 // Enable 80 character display.
#define VMMODE_80CHAR_MASK 0xEF // Mask to filter out display width control bit.
#define VMMODE_COLOUR 0x20 // Enable colour display.
#define VMMODE_COLOUR_MASK 0xDF // Mask to filter out colour control bit.
#define VMMODE_PCGRAM 0x40 // Enable PCG RAM.
#define VMMODE_VGA_MASK 0xF0 // Mask to filter out the VGA output mode bits.
#define VMMODE_VGA_OFF 0x00 // Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
#define VMMODE_VGA_INT 0x00 // Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
#define VMMODE_VGA_INT50 0x01 // Set VGA mode off, external monitor is driven by standard internal 50Hz signals.
#define VMMODE_VGA_640x480 0x02 // Set external monitor to VGA 640x480 @ 60Hz mode.
#define VMMODE_VGA_800x600 0x03 // Set external monitor to VGA 800x600 @ 60Hz mode.
// VGA mode border control constants.
//
#define VMBORDER_BLACK 0x00 // VGA has a black border.
#define VMBORDER_BLUE 0x01 // VGA has a blue border.
#define VMBORDER_RED 0x02 // VGA has a red border.
#define VMBORDER_PURPLE 0x03 // VGA has a purple border.
#define VMBORDER_GREEN 0x04 // VGA has a green border.
#define VMBORDER_CYAN 0x05 // VGA has a cyan border.
#define VMBORDER_YELLOW 0x06 // VGA has a yellow border.
#define VMBORDER_WHITE 0x07 // VGA has a white border.
#define VMBORDER_MASK 0xF8 // Mask to filter out current border setting.
// Sharp MZ colour attributes.
#define VMATTR_FG_BLACK 0x00 // Foreground black character attribute.
#define VMATTR_FG_BLUE 0x10 // Foreground blue character attribute.
#define VMATTR_FG_RED 0x20 // Foreground red character attribute.
#define VMATTR_FG_PURPLE 0x30 // Foreground purple character attribute.
#define VMATTR_FG_GREEN 0x40 // Foreground green character attribute.
#define VMATTR_FG_CYAN 0x50 // Foreground cyan character attribute.
#define VMATTR_FG_YELLOW 0x60 // Foreground yellow character attribute.
#define VMATTR_FG_WHITE 0x70 // Foreground white character attribute.
#define VMATTR_FG_MASKOUT 0x8F // Mask to filter out foreground attribute.
#define VMATTR_FG_MASKIN 0x70 // Mask to filter out foreground attribute.
#define VMATTR_BG_BLACK 0x00 // Background black character attribute.
#define VMATTR_BG_BLUE 0x01 // Background blue character attribute.
#define VMATTR_BG_RED 0x02 // Background red character attribute.
#define VMATTR_BG_PURPLE 0x03 // Background purple character attribute.
#define VMATTR_BG_GREEN 0x04 // Background green character attribute.
#define VMATTR_BG_CYAN 0x05 // Background cyan character attribute.
#define VMATTR_BG_YELLOW 0x06 // Background yellow character attribute.
#define VMATTR_BG_WHITE 0x07 // Background white character attribute.
#define VMATTR_BG_MASKOUT 0xF8 // Mask to filter out background attribute.
#define VMATTR_BG_MASKIN 0x07 // Mask to filter out background attribute.
// Sharp MZ constants.
//
#define MZ_MROM_ADDR 0x00000 // Monitor ROM start address.
#define MZ_800_MROM_ADDR 0x70000 // MZ-800 Monitor ROM address.
#define MZ_800_CGROM_ADDR 0x71000 // MZ-800 CGROM address during reset when it is loaded into the PCG.
#define MZ_800_IPL_ADDR 0x7E000 // Address of the 9Z_504M IPL BIOS.
#define MZ_800_IOCS_ADDR 0x7F400 // Address of the MZ-800 common IOCS bios.
#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_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.
#define MZ_VID_RAM_ADDR 0x0D000 // Start of Video RAM
#define MZ_VID_RAM_SIZE 2048 // Size of Video RAM.
#define MZ_VID_MAX_COL 40 // Maximum column for the host display
#define MZ_VID_MAX_ROW 25 // Maximum row for the host display
#define MZ_VID_DFLT_BYTE 0x00 // Default character (SPACE) for video RAM.
#define MZ_ATTR_RAM_ADDR 0xD800 // On machines with the upgrade, the start of the Attribute RAM.
#define MZ_ATTR_RAM_SIZE 2048 // Size of the attribute RAM.
#define MZ_ATTR_DFLT_BYTE 0x07 // Default colour (White on Black) for the attribute.
#define MZ_SCROL_BASE 0xE200 // Base address of the hardware scroll registers.
#define MZ_SCROL_END 0xE2FF // End address of the hardware scroll registers.
#define MZ_MEMORY_SWAP 0xE00C // Address when read swaps the memory from 0000-0FFF -> C000-CFFF
#define MZ_MEMORY_RESET 0xE010 // Address when read resets the memory to the default location 0000-0FFF.
#define MZ_CRT_NORMAL 0xE014 // Address when read sets the CRT to normal display mode.
#define MZ_CRT_INVERSE 0xE018 // Address when read sets the CRT to inverted display mode.
#define MZ_80A_CPU_FREQ 2000000 // CPU Speed of the Sharp MZ-80A
#define MZ_700_CPU_FREQ 3580000 // CPU Speed of the Sharp MZ-700
#define MZ_80B_CPU_FREQ 4000000 // CPU Speed of the Sharp MZ-80B
#define MZ_2000_CPU_FREQ 4000000 // CPU Speed of the Sharp MZ-2000
#define MZ_800_CPU_FREQ 3580000 // CPU Speed of the Sharp MZ-800
// Service request constants.
//
#define TZSVC_CMD_STRUCT_ADDR_TZFS 0x0ED80 // Address of the command structure within TZFS - exists in 64K Block 0.
#define TZSVC_CMD_STRUCT_ADDR_CPM 0x4F560 // Address of the command structure within CP/M - exists in 64K Block 4.
#define TZSVC_CMD_STRUCT_ADDR_MZ700 0x6FD80 // Address of the command structure within MZ700 compatible programs - exists in 64K Block 6.
#define TZSVC_CMD_STRUCT_ADDR_ZOS 0x11FD80 // 0x7FD80 // Address of the command structure for zOS use, exists in shared memory rather than FPGA. Spans top of block 6 and all of block 7.
#define TZSVC_CMD_STRUCT_ADDR_MZ2000_NST 0x6FD80 // Address of the command structure within MZ2000 compatible programs during normal state - exists in 64K Block 1.
#define TZSVC_CMD_STRUCT_ADDR_MZ2000_IPL 0x07D80 // Address of the command structure within MZ2000 compatible programs during IPL state - exists in 64K Block 0.
#define TZSVC_CMD_STRUCT_SIZE 0x280 // Size of the inter z80/K64 service command memory.
#define TZSVC_CMD_SIZE (sizeof(t_svcControl)-TZSVC_SECTOR_SIZE)
#define TZVC_MAX_CMPCT_DIRENT_BLOCK TZSVC_SECTOR_SIZE/TZSVC_CMPHDR_SIZE // Maximum number of directory entries per sector.
#define TZSVC_MAX_DIR_ENTRIES 255 // Maximum number of files in one directory, any more than this will be ignored.
#define TZSVC_CMPHDR_SIZE 32 // Compacted header size, contains everything except the comment field, padded out to 32bytes.
#define MZF_FILLER_LEN 8 // Filler to pad a compacted header entry to a power of 2 length.
#define TZVC_MAX_DIRENT_BLOCK TZSVC_SECTOR_SIZE/MZF_HEADER_SIZE // Maximum number of directory entries per sector.
#define TZSVC_CMD_READDIR 0x01 // Service command to open a directory and return the first block of entries.
#define TZSVC_CMD_NEXTDIR 0x02 // Service command to return the next block of an open directory.
#define TZSVC_CMD_READFILE 0x03 // Service command to open a file and return the first block.
#define TZSVC_CMD_NEXTREADFILE 0x04 // Service command to return the next block of an open file.
#define TZSVC_CMD_WRITEFILE 0x05 // Service command to create a file and save the first block.
#define TZSVC_CMD_NEXTWRITEFILE 0x06 // Service command to write the next block to the open file.
#define TZSVC_CMD_CLOSE 0x07 // Service command to close any open file or directory.
#define TZSVC_CMD_LOADFILE 0x08 // Service command to load a file directly into tranZPUter memory.
#define TZSVC_CMD_SAVEFILE 0x09 // Service command to save a file directly from tranZPUter memory.
#define TZSVC_CMD_ERASEFILE 0x0a // Service command to erase a file on the SD card.
#define TZSVC_CMD_CHANGEDIR 0x0b // Service command to change active directory on the SD card.
#define TZSVC_CMD_LOAD40ABIOS 0x20 // Service command requesting that the 40 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD80ABIOS 0x21 // Service command requesting that the 80 column version of the SA1510 BIOS is loaded.
#define TZSVC_CMD_LOAD700BIOS40 0x22 // Service command requesting that the MZ700 1Z-013A 40 column BIOS is loaded.
#define TZSVC_CMD_LOAD700BIOS80 0x23 // Service command requesting that the MZ700 1Z-013A 80 column patched BIOS is loaded.
#define TZSVC_CMD_LOAD80BIPL 0x24 // Service command requesting the MZ-80B IPL is loaded.
#define TZSVC_CMD_LOAD800BIOS 0x25 // Service command requesting that the MZ800 9Z-504M BIOS is loaded.
#define TZSVC_CMD_LOAD2000IPL 0x26 // Service command requesting the MZ-2000 IPL is loaded.
#define TZSVC_CMD_LOADTZFS 0x2F // Service command requesting the loading of TZFS. This service is for machines which normally dont have a monitor BIOS. ie. MZ-80B/MZ-2000 and manually request TZFS.
#define TZSVC_CMD_LOADBDOS 0x30 // Service command to reload CPM BDOS+CCP.
#define TZSVC_CMD_ADDSDDRIVE 0x31 // Service command to attach a CPM disk to a drive number.
#define TZSVC_CMD_READSDDRIVE 0x32 // Service command to read an attached SD file as a CPM disk drive.
#define TZSVC_CMD_WRITESDDRIVE 0x33 // Service command to write to a CPM disk drive which is an attached SD file.
#define TZSVC_CMD_CPU_BASEFREQ 0x40 // Service command to switch to the mainboard frequency.
#define TZSVC_CMD_CPU_ALTFREQ 0x41 // Service command to switch to the alternate frequency provided by the K64F.
#define TZSVC_CMD_CPU_CHGFREQ 0x42 // Service command to set the alternate frequency in hertz.
#define TZSVC_CMD_CPU_SETZ80 0x50 // Service command to switch to the external Z80 hard cpu.
#define TZSVC_CMD_CPU_SETT80 0x51 // Service command to switch to the internal T80 soft cpu.
#define TZSVC_CMD_CPU_SETZPUEVO 0x52 // Service command to switch to the internal ZPU Evolution cpu.
#define TZSVC_CMD_EMU_SETMZ80K 0x53 // Service command to switch to the internal Sharp MZ Series Emulation of the MZ80K.
#define TZSVC_CMD_EMU_SETMZ80C 0x54 // "" "" "" MZ80C.
#define TZSVC_CMD_EMU_SETMZ1200 0x55 // "" "" "" MZ1200.
#define TZSVC_CMD_EMU_SETMZ80A 0x56 // "" "" "" MZ80A.
#define TZSVC_CMD_EMU_SETMZ700 0x57 // "" "" "" MZ700.
#define TZSVC_CMD_EMU_SETMZ800 0x58 // "" "" "" MZ800.
#define TZSVC_CMD_EMU_SETMZ1500 0x59 // "" "" "" MZ1500.
#define TZSVC_CMD_EMU_SETMZ80B 0x5A // "" "" "" MZ80B.
#define TZSVC_CMD_EMU_SETMZ2000 0x5B // "" "" "" MZ2000.
#define TZSVC_CMD_EMU_SETMZ2200 0x5C // "" "" "" MZ2200.
#define TZSVC_CMD_EMU_SETMZ2500 0x5D // "" "" "" MZ2500.
#define TZSVC_CMD_SD_DISKINIT 0x60 // Service command to initialise and provide raw access to the underlying SD card.
#define TZSVC_CMD_SD_READSECTOR 0x61 // Service command to provide raw read access to the underlying SD card.
#define TZSVC_CMD_SD_WRITESECTOR 0x62 // Service command to provide raw write access to the underlying SD card.
#define TZSVC_CMD_EXIT 0x7F // Service command to terminate TZFS and restart the machine in original mode.
#define TZSVC_DEFAULT_TZFS_DIR "TZFS" // Default directory where TZFS files are stored.
#define TZSVC_DEFAULT_CPM_DIR "CPM" // Default directory where CPM files are stored.
#define TZSVC_DEFAULT_MZF_DIR "MZF" // Default directory where MZF files are stored.
#define TZSVC_DEFAULT_CAS_DIR "CAS" // Default directory where BASIC CASsette files are stored.
#define TZSVC_DEFAULT_BAS_DIR "BAS" // Default directory where BASIC text files are stored.
#define TZSVC_DEFAULT_MZF_EXT "MZF" // Default file extension for MZF files.
#define TZSVC_DEFAULT_CAS_EXT "CAS" // Default file extension for CASsette files.
#define TZSVC_DEFAULT_BAS_EXT "BAS" // Default file extension for BASic script files stored in readable text.
#define TZSVC_DEFAULT_WILDCARD "*" // Default wildcard file matching.
#define TZSVC_RESULT_OFFSET 0x01 // Offset into structure of the result byte.
#define TZSVC_DIRNAME_SIZE 20 // Limit is size of FAT32 directory name.
#define TZSVC_WILDCARD_SIZE 20 // Very basic pattern matching so small size.
#define TZSVC_FILENAME_SIZE MZF_FILENAME_LEN // Length of a Sharp MZF filename.
#define TZSVC_LONG_FNAME_SIZE (sizeof(t_svcCmpDirEnt) - 1) // Length of a standard filename to fit inside a directory entry.
#define TZSVC_LONG_FMT_FNAME_SIZE 20 // Length of a standard filename formatted in a directory listing.
#define TZSVC_SECTOR_SIZE 512 // SD Card sector buffer size.
#define TZSVC_STATUS_OK 0x00 // Flag to indicate the K64F processing completed successfully.
#define TZSVC_STATUS_FILE_ERROR 0x01 // Flag to indicate a file or directory error.
#define TZSVC_STATUS_BAD_CMD 0x02 // Flag to indicate a bad service command was requested.
#define TZSVC_STATUS_BAD_REQ 0x03 // Flag to indicate a bad request was made, the service status request flag was not set.
#define TZSVC_STATUS_REQUEST 0xFE // Flag to indicate Z80 has posted a request.
#define TZSVC_STATUS_PROCESSING 0xFF // Flag to indicate the K64F is processing a command.
#define TZSVC_OPEN 0x00 // Service request to open a directory or file.
#define TZSVC_NEXT 0x01 // Service request to return the next directory block or file block or write the next file block.
#define TZSVC_CLOSE 0x02 // Service request to close open dir/file.
// ROM file paths.
#define MZ_ROM_SP1002 "SP1002.rom" // Original MZ-80K ROM
#define MZ_ROM_SA1510_40C "SA1510.rom" // Original 40 character Monitor ROM.
#define MZ_ROM_SA1510_80C "SA1510-8.rom" // Original Monitor ROM patched for 80 character screen mode.
#define MZ_ROM_1Z_013A_40C "1Z-013A.rom" // Original 40 character Monitor ROM for the Sharp MZ700.
#define MZ_ROM_1Z_013A_80C "1Z-013A-8.rom" // Original Monitor ROM patched for the Sharp MZ700 patched for 80 column mode.
#define MZ_ROM_1Z_013A_KM_40C "1Z-013A-KM.rom" // Original 40 character Monitor ROM for the Sharp MZ700 with keyboard remapped for the MZ80A.
#define MZ_ROM_1Z_013A_KM_80C "1Z-013A-KM-8.rom" // Original Monitor ROM patched for the Sharp MZ700 with keyboard remapped for the MZ80A and patched for 80 column mode.
#define MZ_ROM_1Z_013A_2000 "1Z-013A-2000.rom" // Original 40 character Monitor ROM for the Sharp MZ700 modified to run on an MZ-2000.
#define MZ_ROM_9Z_504M_COMBINED "MZ800_IPL.rom" // Original MZ-800 BIOS which comprises the 1Z_013B BIOS, 9Z_504M IPL, CGROM and IOCS.
#define MZ_ROM_9Z_504M "MZ800_9Z_504M.rom" // Modified MZ-800 9Z_504M IPL to contain a select TZFS option.
#define MZ_ROM_1Z_013B "MZ800_1Z_013B.rom" // Original MZ-800 1Z_013B MZ-700 compatible BIOS.
#define MZ_ROM_800_CGROM "MZ800_CGROM.ori" // Original MZ-800 Character Generator ROM.
#define MZ_ROM_800_IOCS "MZ800_IOCS.rom" // Original MZ-800 common IOCS bios.
#define MZ_ROM_MZ80B_IPL "MZ80B_IPL.rom" // Original IPL ROM for the Sharp MZ-80B.
#define MZ_ROM_MZ2000_IPL "MZ2000_IPL.rom" // Original IPL ROM for the Sharp MZ-2000.
#define MZ_ROM_MZ2000_IPL_TZPU "MZ2000_IPL_TZPU.rom" // Modified IPL ROM for the tranZPUter running on the Sharp MZ-2000.
#define MZ_ROM_MZ2000_CGROM "MZ2000_CGROM.rom" // MZ-2000 CGROM.
#define MZ_ROM_TZFS "tzfs.rom" // tranZPUter Filing System ROM.
// CP/M constants.
//
#define CPM_MAX_DRIVES 16 // Maximum number of drives in CP/M.
#define CPM_SD_DRIVES_DIR TZSVC_DEFAULT_CPM_DIR "/SDC16M/RAW" // Default directory where CPM SD disk drive images are stored.
#define CPM_DRIVE_TMPL "CPMDSK%02u.RAW" // Template for CPM disk drives stored on the SD card.
#define CPM_SECTORS_PER_TRACK 32 // Number of sectors in a track on the virtual CPM disk.
#define CPM_TRACKS_PER_DISK 1024 // Number of tracks on a disk.
// Constants for the Sharp MZ80A MZF file format.
#define MZF_HEADER_SIZE 128 // Size of the MZF header.
#define MZF_ATTRIBUTE 0x00 // Code Type, 01 = Machine Code.
#define MZF_FILENAME 0x01 // Title/Name (17 bytes).
#define MZF_FILENAME_LEN 17 // Length of the filename, it is not NULL terminated, generally a CR can be taken as terminator but not guaranteed.
#define MZF_FILESIZE 0x12 // Size of program.
#define MZF_LOADADDR 0x14 // Load address of program.
#define MZF_EXECADDR 0x16 // Exec address of program.
#define MZF_COMMENT 0x18 // Comment, used for details of the file or startup code.
#define MZF_COMMENT_LEN 104 // Length of the comment field.
#define CMT_TYPE_OBJCD 0x001 // MZF contains a binary object.
#define CMT_TYPE_BTX1CD 0x002 // MZF contains a BASIC program.
#define CMT_TYPE_BTX2CD 0x005 // MZF contains a BASIC program.
#define CMT_TYPE_TZOBJCD0 0x0F8 // MZF contains a TZFS binary object for page 0.
#define CMT_TYPE_TZOBJCD1 0x0F9
#define CMT_TYPE_TZOBJCD2 0x0FA
#define CMT_TYPE_TZOBJCD3 0x0FB
#define CMT_TYPE_TZOBJCD4 0x0FC
#define CMT_TYPE_TZOBJCD5 0x0FD
#define CMT_TYPE_TZOBJCD6 0x0FE
#define CMT_TYPE_TZOBJCD7 0x0FF // MZF contains a TZFS binary object for page 7.
// Constants for other handled file formats.
//
#define CAS_HEADER_SIZE 256 // Size of the CASsette header.
// Possible targets the K64F can read from/write to.
enum TARGETS {
MAINBOARD = 0,
TRANZPUTER = 1
};
// Possible machine hardware types the tranZPUter is functioning within.
//
enum MACHINE_HW_TYPES {
HW_MZ80K = HWMODE_MZ80K, // Host hardware = MZ-80K.
HW_MZ80C = HWMODE_MZ80C, // Host hardware = MZ-80C.
HW_MZ1200 = HWMODE_MZ1200, // Host hardware = MZ-1200.
HW_MZ80A = HWMODE_MZ80A, // Host hardware = MZ-80A.
HW_MZ700 = HWMODE_MZ700, // Host hardware = MZ-700.
HW_MZ800 = HWMODE_MZ800, // Host hardware = MZ-800.
HW_MZ80B = HWMODE_MZ80B, // Host hardware = MZ-80B.
HW_MZ2000 = HWMODE_MZ2000, // Host hardware = MZ-2000.
HW_UNKNOWN = 0xFF // Host hardware unknown, fault or CPLD misconfiguration.
};
// Groups to which the machines belong. This is a lineage route of the Sharp machines.
//
enum MACHINE_GROUP {
GROUP_MZ80K = 0, // Machines in the MZ80K group, ie. MZ80K/C/1200/80A
GROUP_MZ700 = 1, // Machines in the MZ700 group, ie. MZ700/800/1500
GROUP_MZ80B = 2 // Machines in the MZ80B group, ie. MZ80B/2000/2200/2500
};
// Types of file which have handlers and can be processed.
//
enum FILE_TYPE {
MZF = 0, // Sharp MZF tape image files.
MZFHDR = 1, // Sharp MZF Header from file only.
CAS = 2, // BASIC CASsette image files.
BAS = 3, // BASic ASCII text script files.
ALL = 10, // All files to be considered.
ALLFMT = 11 // Special case for directory listings, all files but truncated and formatted.
};
// File function return code (FRESULT) - From FatFS.
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
// Following are only required for the user space daemon which emulates the Cortex-M4 on the tranZPUter SW
#ifndef __KERNEL_DRIVER__
// Structure to define a Sharp MZ80A MZF directory structure. This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images.
//
typedef struct __attribute__((__packed__)) {
uint8_t attr; // MZF attribute describing the file.
uint8_t fileName[MZF_FILENAME_LEN]; // Each directory entry is the size of an MZF filename.
uint16_t fileSize; // Size of file.
uint16_t loadAddr; // Load address for the file.
uint16_t execAddr; // Execution address where the Z80 starts processing.
uint8_t comment[MZF_COMMENT_LEN]; // Text comment field but often contains a startup machine code program.
} t_svcDirEnt;
// Structure to define a compacted Sharp MZ80A MZF directory structure (no comment) for use in directory listings.
// This header appears at the beginning of every Sharp MZ80A tape (and more recently archived/emulator) images.
//
typedef struct __attribute__((__packed__)) {
uint8_t attr; // MZF attribute describing the file.
uint8_t fileName[MZF_FILENAME_LEN]; // Each directory entry is the size of an MZF filename.
uint16_t fileSize; // Size of file.
uint16_t loadAddr; // Load address for the file.
uint16_t execAddr; // Execution address where the Z80 starts processing.
uint8_t filler[MZF_FILLER_LEN]; // Filler to pad to a power of 2 length.
} t_svcCmpDirEnt;
// Structure to hold the map betwen an SD filename and the Sharp file it contains. The file is an MZF format file with a 128 byte header
// and this header contains the name understood on the Sharp MZ80A.
//
typedef struct __attribute__((__packed__)) {
uint8_t *sdFileName; // Name of file on the SD card.
t_svcCmpDirEnt mzfHeader; // Compact Sharp header data of this file.
} t_sharpToSDMap;
// Structure to define the control information for a CP/M disk drive.
//
typedef struct {
uint8_t *fileName; // FQFN of the CPM disk image file.
uint32_t lastTrack; // Track of last successful operation.
uint32_t lastSector; // Sector of last successful operation.
FILE *File; // Opened file handle of the CPM disk image.
} t_cpmDrive;
// Structure to define which CP/M drives are added to the system, mapping a number from CP/M into a record containing the details of the file on the SD card.
//
typedef struct {
t_cpmDrive *drive[CPM_MAX_DRIVES]; // 1:1 map of CP/M drive number to an actual file on the SD card.
} t_cpmDriveMap;
// Structure to hold a map of an entire directory of files on the SD card and their associated Sharp MZ0A filename.
typedef struct __attribute__((__packed__)) {
uint8_t valid; // Is this mapping valid?
uint8_t entries; // Number of entries in cache.
uint8_t type; // Type of file being cached.
char directory[TZSVC_DIRNAME_SIZE]; // Directory this mapping is associated with.
union {
t_sharpToSDMap *mzfFile[TZSVC_MAX_DIR_ENTRIES]; // File mapping of SD file to its Sharp MZ80A name.
uint8_t *sdFileName[TZSVC_MAX_DIR_ENTRIES]; // No mapping for SD filenames, just the file name.
};
} t_dirMap;
// Structure to maintain all MZ700 hardware control information in order to emulate the machine.
//
typedef struct {
uint32_t config; // Compacted control register, 31:19 = reserved, 18 = Inhibit mode, 17 = Upper D000:FFFF is RAM (=1), 16 = Lower 0000:0FFF is RAM (=1), 15:8 = old memory mode, 7:0 = current memory mode.
//uint8_t memoryMode; // The memory mode the MZ700 is currently running under, this is determined by the memory control commands from the MZ700.
//uint8_t lockMemoryMode; // The preserved memory mode when entering the locked state.
//uint8_t inhibit; // The inhibit flag, blocks the upper 0xD000:0xFFFF region from being accessed, affects the memoryMode temporarily.
//uint8_t update; // Update flag, indicates to the ISR that a memory mode update is needed.
//uint8_t b0000; // Block 0000:0FFF mode.
//uint8_t bD000; // Block D000:FFFF mode.
} t_mz700;
// Structure to maintain all MZ-80B hardware control information in order to emulate the machine as near as possible.
typedef struct {
uint32_t config; // Compacted control register, 31:19 = reserved, 18 = Inhibit mode, 17 = Upper D000:FFFF is RAM (=1), 16 = Lower 0000:0FFF is RAM (=1), 15:8 = old memory mode, 7:0 = current memory mode.
} t_mz80b;
// Structure to maintain all the control and management variables of the Z80 and underlying hardware so that the state of run is well known by any called method.
//
typedef struct {
#if !defined(__APP__) || defined(__TZFLUPD__)
uint32_t svcControlAddr; // Address of the service control record within the Z80 static RAM bank.
uint8_t refreshAddr; // Refresh address for times when the K64F must issue refresh cycles on the Z80 bus.
uint8_t disableRefresh; // Disable refresh if the mainboard DRAM isnt being used.
enum MACHINE_HW_TYPES hostType; // The underlying host machine, 0 = Sharp MZ-80A, 1 = MZ-700, 2 = MZ-80B
uint8_t iplMode; // Flag to indicate if the host is in IPL (boot) or run mode. Applicable on the MZ-2000/MZ-80B only.
uint8_t blockResetActions; // Flag to request reset actions are blocked on the next detected reset. This is useful on startup or when loading a monitor ROM set different to the default.
t_mz700 mz700; // MZ700 emulation control to detect IO commands and adjust the memory map accordingly.
t_mz80b mz80b; // MZ-80B emulation control to detect IO commands and adjust the memory map and I/O forwarding accordingly.
uint8_t resetEvent; // A Z80_RESET event occurred, probably user pressing RESET button.
uint32_t freqMultiplier; // Multipler to be applied to CPU frequency.
int fdZ80; // Handle to the Z80 kernel.
#endif
} t_z80Control;
// Structure to maintain higher level OS control and management variables typically used for TZFS and CPM.
//
typedef struct {
uint8_t tzAutoBoot; // Autoboot the tranZPUter into TZFS mode.
t_dirMap dirMap; // Directory map of SD filenames to Sharp MZ80A filenames.
t_cpmDriveMap cpmDriveMap; // Map of file number to an open SD disk file to be used as a CPM drive.
uint8_t *lastFile; // Last file loaded - typically used for CPM to reload itself.
} t_osControl;
// Structure to contain inter CPU communications memory for command service processing and results.
// Typically the z80 places a command into the structure in it's memory space and asserts an I/O request,
// the K64F detects the request and reads the lower portion of the struct from z80 memory space,
// determines the command and then either reads the remainder or writes to the remainder. This struct
// exists in both the z80 and K64F domains and data is sync'd between them as needed.
//
typedef struct __attribute__((__packed__)) {
uint8_t cmd; // Command request.
uint8_t result; // Result code. 0xFE - set by Z80, command available, 0xFE - set by K64F, command ack and processing. 0x00-0xF0 = cmd complete and result of processing.
union {
uint8_t dirSector; // Virtual directory sector number.
uint8_t fileSector; // Sector within open file to read/write.
uint8_t vDriveNo; // Virtual or physical SD card drive number.
};
union {
struct {
uint16_t trackNo; // For virtual drives with track and sector this is the track number
uint16_t sectorNo; // For virtual drives with track and sector this is the sector number. NB For LBA access, this is 32bit and overwrites fileNo/fileType which arent used during raw SD access.
};
uint32_t sectorLBA; // For LBA access, this is 32bit and used during raw SD access.
struct {
uint8_t memTarget; // Target memory for operation, 0 = tranZPUter, 1 = mainboard.
uint8_t spare1; // Unused variable.
uint16_t spare2; // Unused variable.
};
};
uint8_t fileNo; // File number of a file within the last directory listing to open/update.
uint8_t fileType; // Type of file being processed.
union {
uint16_t loadAddr; // Load address for ROM/File images which need to be dynamic.
uint16_t saveAddr; // Save address for ROM/File images which need to be dynamic.
uint16_t cpuFreq; // CPU Frequency in KHz - used for setting of the alternate CPU clock frequency.
};
union {
uint16_t loadSize; // Size for ROM/File to be loaded.
uint16_t saveSize; // Size for ROM/File to be saved.
};
uint8_t directory[TZSVC_DIRNAME_SIZE]; // Directory in which to look for a file. If no directory is given default to MZF.
uint8_t filename[TZSVC_FILENAME_SIZE]; // File to open or create.
uint8_t wildcard[TZSVC_WILDCARD_SIZE]; // A basic wildcard pattern match filter to be applied to a directory search.
uint8_t sector[TZSVC_SECTOR_SIZE]; // Sector buffer generally for disk read/write.
} t_svcControl;
// Structure to define all the directory entries which are packed into a single SD sector which is used between the Z80<->K64F.
//
typedef struct __attribute__((__packed__)) {
t_svcDirEnt dirEnt[TZVC_MAX_DIRENT_BLOCK]; // Fixed number of directory entries per sector/block.
} t_svcDirBlock;
// Structure to hold compacted directory entries which are packed into a single SD sector which is used between the Z80<->K64F.
//
typedef struct __attribute__((__packed__)) {
t_svcCmpDirEnt dirEnt[TZVC_MAX_CMPCT_DIRENT_BLOCK];// Fixed number of compacted directory entries per sector/block.
} t_svcCmpDirBlock;
// Mapping table from Sharp MZ80A Ascii to real Ascii.
//
typedef struct {
uint8_t asciiCode;
} t_asciiMap;
// Mapping table from Ascii to Sharp MZ display code.
//
typedef struct {
uint8_t dispCode;
} t_dispCodeMap;
// Prototypes.
//
void reqResetZ80(uint8_t);
void startZ80(uint8_t memoryMode);
void stopZ80(uint8_t memoryMode);
uint32_t setZ80CPUFrequency(float, uint8_t);
uint8_t copyFromZ80(uint8_t *, uint32_t, uint32_t, enum TARGETS);
uint8_t copyToZ80(uint32_t, uint8_t *, uint32_t, enum TARGETS);
uint8_t writeZ80Memory(uint32_t, uint8_t, enum TARGETS);
uint8_t readZ80Memory(uint32_t);
void fillZ80Memory(uint32_t, uint32_t, uint8_t, enum TARGETS);
FRESULT loadZ80Memory(const char *, uint32_t, uint32_t, uint32_t, uint32_t *, enum TARGETS);
FRESULT saveZ80Memory(const char *, uint32_t, uint32_t, t_svcDirEnt *, enum TARGETS);
FRESULT loadMZFZ80Memory(const char *, uint32_t, uint32_t *, uint8_t, enum TARGETS);
int memoryDump(uint32_t memaddr, uint32_t memsize, uint8_t memoryType, uint32_t memwidth, uint32_t dispaddr, uint8_t dispwidth);
// Getter/Setter methods!
void convertSharpFilenameToAscii(char *, char *, uint8_t);
void convertToFAT32FileNameFormat(char *);
// tranZPUter OS i/f methods.
uint8_t setZ80SvcStatus(uint8_t);
void svcSetDefaults(enum FILE_TYPE);
uint8_t svcReadDir(uint8_t, enum FILE_TYPE);
uint8_t svcFindFile(char *, char *, uint8_t, enum FILE_TYPE);
uint8_t svcReadDirCache(uint8_t, enum FILE_TYPE);
uint8_t svcFindFileCache(char *, char *, uint8_t, enum FILE_TYPE);
uint8_t svcCacheDir(const char *, enum FILE_TYPE, uint8_t);
uint8_t svcReadFile(uint8_t, enum FILE_TYPE);
uint8_t svcWriteFile(uint8_t, enum FILE_TYPE);
uint8_t svcLoadFile(enum FILE_TYPE);
uint8_t svcSaveFile(enum FILE_TYPE);
uint8_t svcEraseFile(enum FILE_TYPE);
uint8_t svcAddCPMDrive(void);
uint8_t svcReadCPMDrive(void);
uint8_t svcWriteCPMDrive(void);
uint32_t getServiceAddr(void);
void processServiceRequest(void);
uint8_t loadBIOS(const char *, uint32_t);
FRESULT loadTZFS(char *, uint32_t);
void loadTranZPUterDefaultROMS(uint8_t);
uint8_t testTZFSAutoBoot(void);
#endif // __KERNEL_DRIVER__
#ifdef __cplusplus
}
#endif
#endif // TZPU_H

View File

@@ -116,7 +116,10 @@ enum CTRL_COMMANDS {
Z80_CMD_DEL_DEVICE = 11,
CPLD_CMD_SEND_CMD = 12,
CPLD_CMD_SPI_TEST = 13,
CPLD_CMD_PRL_TEST = 14
CPLD_CMD_PRL_TEST = 14,
#if(DEBUG_ENABLED != 0)
Z80_CMD_DEBUG = 15,
#endif
};
@@ -242,7 +245,7 @@ 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[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)*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (pnt+i)) : (uint16_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
@@ -250,7 +253,7 @@ 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[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)*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (pnt+i)) : (uint32_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
@@ -259,7 +262,7 @@ 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[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)*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (pnt+i)) : (uint8_t)Z80Ctrl->iopage[pnt+i]);
else
printf(" ");
i++;
@@ -274,7 +277,7 @@ 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[pnt+i] : (char)Z80Ctrl->iopage[pnt+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];
if ((pnt+i < endAddr) && (c >= ' ') && (c <= '~'))
fputc((char)c, stdout);
else
@@ -320,47 +323,57 @@ memoryDumpExit:
// Method to load a program or data file into the Z80 memory. First load into Virtual memory and then trigger a sync to bring Host RAM in line.
//
int z80load(int fdZ80, char *fileName, uint32_t romLoadAddr, uint8_t useROM)
int z80load(int fdZ80, char *fileName, uint32_t memLoadAddr, long fileOffset, long fileLen, uint8_t memoryType, uint8_t isMZF)
{
// Locals.
struct ioctlCmd ioctlCmd;
int result = 0;
long fileSize;
t_svcDirEnt mzfHeader;
FILE *ptr;
// Open the file and read directly into the Virtual memory via the share.
FILE *ptr;
ptr = fopen(fileName, "rb");
if(ptr)
// Sanity check.
if(isMZF == 0 && (fileOffset == -1 && fileLen != -1 || fileOffset != -1 && fileLen == -1))
{
// Get size of file for sanity checks.
fseek(ptr, 0, SEEK_END);
fileSize = ftell(ptr);
fseek(ptr, 0, SEEK_SET);
printf("Error: Both --offset and --len are required, dont specify to use entire file.\n");
result = 1;
}
if(result == 0)
{
// Open the file and read directly into the Virtual memory via the share.
ptr = fopen(fileName, "rb");
if(ptr)
{
// Get size of file for sanity checks.
fseek(ptr, 0, SEEK_END);
fileSize = ftell(ptr);
fseek(ptr, 0, SEEK_SET);
// Sanity checks.
if(useROM)
{
if((romLoadAddr+fileSize) > Z80_VIRTUAL_ROM_SIZE)
// Sanity checks.
if(isMZF == 0)
{
printf("Error: Binary ROM file out of ROM bounds (Size=%ld, Load=%08x)\n", fileSize, romLoadAddr);
result = 1;
}
} else
{
// First the header.
fread((uint8_t *)&mzfHeader, MZF_HEADER_SIZE, 1, ptr);
if((mzfHeader.loadAddr + mzfHeader.fileSize) > Z80_VIRTUAL_RAM_SIZE)
fileSize = (fileLen == -1 ? fileSize : fileLen);
if((memoryType == 1 && (memLoadAddr+fileSize) > Z80_VIRTUAL_RAM_SIZE) || (memoryType == 2 && (memLoadAddr+fileSize) > Z80_VIRTUAL_ROM_SIZE))
{
printf("Error: Binary file out of memory bounds (Size=%ld, Load=%08x)\n", fileSize, memLoadAddr);
result = 1;
}
} else
{
printf("Error: MZF file out of RAM bounds (Size=%ld, Load=%08x)\n", fileSize, romLoadAddr);
result = 1;
// First the header.
fread((uint8_t *)&mzfHeader, MZF_HEADER_SIZE, 1, ptr);
if((mzfHeader.loadAddr + mzfHeader.fileSize) > Z80_VIRTUAL_RAM_SIZE)
{
printf("Error: MZF file out of RAM bounds (Size=%ld, Load=%08x)\n", fileSize, memLoadAddr);
result = 1;
}
}
}
}
else
{
printf("Couldnt open file:%s\n", fileName);
result = 1;
else
{
printf("Couldnt open file:%s\n", fileName);
result = 1;
}
}
// No file errors, read contents into Z80 memory.
@@ -371,11 +384,35 @@ int z80load(int fdZ80, char *fileName, uint32_t romLoadAddr, uint8_t useROM)
ioctlCmd.cmd = IOCTL_CMD_Z80_PAUSE;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
if(useROM)
if(isMZF == 0)
{
// Position file if offset provided.
if(fileOffset != -1) fseek(ptr, fileOffset, SEEK_SET);
// Now read in the data.
fread(&Z80ROM[romLoadAddr], fileSize, 1, ptr);
printf("Loaded %s, Size:%08x, Addr:%08x\n", fileName, fileSize, romLoadAddr);
switch(memoryType)
{
case 0:
break;
case 2:
fread(&Z80ROM[memLoadAddr], fileSize, 1, ptr);
break;
case 3:
fread(&Z80Ctrl->page[memLoadAddr], fileSize, 1, ptr);
break;
case 4:
fread(&Z80Ctrl->iopage[memLoadAddr], fileSize, 1, ptr);
break;
case 1:
default:
fread(&Z80RAM[memLoadAddr], fileSize, 1, ptr);
break;
}
printf("Loaded %s, Size:%08x, Addr:%08x, memoryType:%d\n", fileName, fileSize, memLoadAddr, memoryType);
}
else
{
@@ -423,7 +460,7 @@ int z80load(int fdZ80, char *fileName, uint32_t romLoadAddr, uint8_t useROM)
// Method to save FusionX memory to a local file.
//
int z80save(int fdZ80, char *fileName, long addr, long size, long memoryType)
int z80save(int fdZ80, char *fileName, long addr, long size, uint8_t memoryType)
{
// Locals.
struct ioctlCmd ioctlCmd;
@@ -447,6 +484,7 @@ int z80save(int fdZ80, char *fileName, long addr, long size, long memoryType)
case 2:
fwrite(&Z80ROM[addr], size, 1, ptr);
break;
case 3:
fwrite(&Z80Ctrl->page[addr], size, 1, ptr);
@@ -584,6 +622,14 @@ int ctrlCmd(int fdZ80, enum CTRL_COMMANDS cmd, long param1, long param2, long pa
ioctlCmd.cmd = IOCTL_CMD_USE_VIRTUAL_RAM;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
#if(DEBUG_ENABLED != 0)
case Z80_CMD_DEBUG:
// Send command to enable/disable debugging output.
ioctlCmd.cmd = IOCTL_CMD_DEBUG;
ioctlCmd.debug.level = (uint8_t)param1;
ioctl(fdZ80, IOCTL_CMD_SEND, &ioctlCmd);
break;
#endif
case Z80_CMD_MEMORY_TEST:
// Send command to test the SPI.
ioctlCmd.cmd = IOCTL_CMD_Z80_MEMTEST;
@@ -672,10 +718,14 @@ void showArgs(char *progName, struct optparse *options)
printf(" = DELDEV --device <RFS, TZPU> # Remove a virtual device from the Z80 configuration.\n");
printf(" = SPEED --mult <1, 2, 4, 8, 16, 32, 64, 128> # In Virtual RAM mode, set CPU speed to base clock x factor.\n");
printf(" = LOADMZF --file <mzf filename> # Load MZF file into RAM.\n");
printf(" = LOADROM --file <binary filename> --addr <24 bit addr> # Load contents of binary file into ROM at address. default = 0x000000.\n");
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(" = 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");
#endif
printf(" = Z80TEST # Perform various debugging tests\n");
printf(" = SPITEST # Perform SPI testing\n");
printf(" = PRLTEST # Perform Parallel Bus testing\n");
@@ -696,9 +746,14 @@ int main(int argc, char *argv[])
long speedMultiplier = 1;
long startAddr = 0x0000;
long endAddr = 0x1000;
int memoryType = 0;
long fileOffset = -1;
long fileLen = -1;
#if(DEBUG_ENABLED != 0)
int debugLevel = 0;
#endif
int helpFlag = 0;
int verboseFlag = 0;
uint8_t memoryType = 0;
// Define parameters to be processed.
struct optparse options;
@@ -714,6 +769,11 @@ int main(int argc, char *argv[])
{"end", 'e', OPTPARSE_REQUIRED},
{"size", 's', OPTPARSE_REQUIRED},
{"device", 'D', OPTPARSE_REQUIRED},
{"offset", 'O', OPTPARSE_REQUIRED},
{"len", 'L', OPTPARSE_REQUIRED},
#if(DEBUG_ENABLED != 0)
{"level", 'l', OPTPARSE_REQUIRED},
#endif
{"verbose", 'v', OPTPARSE_NONE},
{"save", '0', OPTPARSE_NONE},
{"dump", '1', OPTPARSE_NONE},
@@ -726,6 +786,7 @@ int main(int argc, char *argv[])
{"continue", '8', OPTPARSE_NONE},
{"speed", '9', OPTPARSE_NONE},
{"cpldcmd", '+', OPTPARSE_NONE},
{"debug", 'x', OPTPARSE_NONE},
{"adddev", '-', OPTPARSE_NONE},
{"deldev", ':', OPTPARSE_NONE},
{0}
@@ -768,11 +829,30 @@ int main(int argc, char *argv[])
endAddr = startAddr + strtol(options.optarg, NULL, 0);
//printf("End Addr:%04x\n", endAddr);
break;
// File offset.
case 'O':
fileOffset = strtol(options.optarg, NULL, 0);
//printf("File Offset:%04x\n", fileOffset);
break;
// Length.
case 'L':
fileLen = strtol(options.optarg, NULL, 0);
//printf("File Len:%04x\n", fileLen);
break;
// Memory type flag, 0 = host, 1 = virtual RAM, 2 = virtual ROM, 3 = page table, 4 = iopage table.
case 'T':
memoryType = atoi(options.optarg);
break;
#if(DEBUG_ENABLED != 0)
// Debug level, 0 = off, 1 = driver, 2 = k64f, 3 = both.
case 'E':
debugLevel = atoi(options.optarg);
break;
#endif
// Filename.
case 'f':
@@ -800,7 +880,7 @@ int main(int argc, char *argv[])
strcpy(cmd, "LOADMZF");
break;
case '3':
strcpy(cmd, "LOADROM");
strcpy(cmd, "LOADMEM");
break;
case '4':
strcpy(cmd, "RESET");
@@ -828,6 +908,12 @@ int main(int argc, char *argv[])
break;
case ':':
strcpy(cmd, "DELDEV");
break;
#if(DEBUG_ENABLED != 0)
case 'x':
strcpy(cmd, "DEBUG");
break;
#endif
// Verbose mode.
case 'v':
@@ -882,11 +968,11 @@ int main(int argc, char *argv[])
// Basic string to method mapping. Started off with just 1 or two but has grown, may need a table!
if(strcasecmp(cmd, "LOADMZF") == 0)
{
z80load(fdZ80, fileName, 0, 0);
z80load(fdZ80, fileName, 0, -1, -1, 1, 1);
} else
if(strcasecmp(cmd, "LOADROM") == 0)
if(strcasecmp(cmd, "LOADMEM") == 0)
{
z80load(fdZ80, fileName, startAddr, 1);
z80load(fdZ80, fileName, startAddr, fileOffset, fileLen, memoryType, 0);
} else
if(strcasecmp(cmd, "RESET") == 0)
{
@@ -940,6 +1026,12 @@ int main(int argc, char *argv[])
{
ctrlCmd(fdZ80, CPLD_CMD_SEND_CMD, hexData, 0, 0);
} else
#if(DEBUG_ENABLED != 0)
if(strcasecmp(cmd, "DEBUG") == 0)
{
ctrlCmd(fdZ80, Z80_CMD_DEBUG, debugLevel, 0, 0);
} else
#endif
// Test methods, if the code is built-in to the driver.
if(strcasecmp(cmd, "Z80TEST") == 0)

View File

@@ -29,6 +29,12 @@
// in host memory at full speed.
// Feb 2023 - v1.2 Added MZ-80A Rom Filing System device driver. This allows the FusionX
// hosted in an MZ-80A to run the original RFS Monitor and software.
// Feb 2023 - v11.3 Added tranZPUter SW device driver. This allows the FusionX hosted
// in any supported host to run TZFS and the updated applications
// such as CP/M, SA-5510 Basic, MS-Basic etc. Adding this device driver
// prepares the ground to add the SOM GPU as the Video emulation of
// the Sharp machines.
//
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -132,6 +138,10 @@ static inline void decodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t io
rfsDecodeMemoryMapSetup(address, data, ioFlag, readFlag);
} else
#endif
if(Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_TZPU)
{
rfsDecodeMemoryMapSetup(address, data, ioFlag, readFlag);
} else
{
// Decoding memory address or I/O address?
if(ioFlag == 0)
@@ -332,7 +342,7 @@ static inline void decodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t io
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
}
}
z80_instant_reset(&Z80CPU);
resetZ80();
}
break;
@@ -386,9 +396,9 @@ static inline void decodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t io
return;
}
// Method to decode address and invoke virtual hardware to handle accordingly.
// Method to decode address and invoke virtual RAM, ROM or hardware to handle accordingly.
//
static inline zuint8 readVirtualHW(zuint16 address, uint8_t ioFlag)
static inline zuint8 readVirtual(zuint16 address, uint8_t ioFlag)
{
// Locals.
//
@@ -400,20 +410,27 @@ static inline zuint8 readVirtualHW(zuint16 address, uint8_t ioFlag)
// RFS only has memory mapped registers.
if((Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_RFS) && ioFlag == 0)
{
data = rfsRead(address);
}
data = rfsRead(address, ioFlag);
} else
#endif
if((Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_TZPU) && (ioFlag == 0 || isVirtualDevice(address, VIRTUAL_DEVICE_TZPU)))
if((Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_TZPU))
{
data = tzpuRead(address);
data = tzpuRead(address, ioFlag);
}
else if(isVirtualMemory(address))
{
// Retrieve data from virtual memory.
data = isVirtualROM(address) ? readVirtualROM(address) : readVirtualRAM(address);
}
return(data);
}
// Method to decode address and invoke virtual hardware to handle accordingly.
// Method to decode address and invoke virtual ROM, RAM or hardware to handle accordingly.
//
static inline void writeVirtualHW(zuint16 address, zuint8 data, uint8_t ioFlag)
static inline void writeVirtual(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals.
@@ -423,12 +440,19 @@ static inline void writeVirtualHW(zuint16 address, zuint8 data, uint8_t ioFlag)
// RFS only has memory mapped registers.
if((Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_RFS) && ioFlag == 0)
{
rfsWrite(address, data);
}
rfsWrite(address, data, ioFlag);
} else
#endif
if((Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_TZPU) && (ioFlag == 0 || isVirtualDevice(address, VIRTUAL_DEVICE_TZPU)))
if((Z80Ctrl->virtualDeviceBitMap & VIRTUAL_DEVICE_TZPU))
{
tzpuWrite(address, data);
tzpuWrite(address, data, ioFlag);
}
else if(isVirtualRAM(address))
{
// Update virtual memory.
writeVirtualRAM(address, data);
}
return;
@@ -513,15 +537,10 @@ static zuint8 z80_read(void *context, zuint16 address)
// Pause until the Last T-State is detected.
//while(CPLD_LAST_TSTATE() == 0);
}
else if(isVirtualHW(address))
else if(isVirtual(address))
{
// Decode the address and if virtual logic exists, invoke it.
data = readVirtualHW(address, 0);
}
else if(isVirtualMemory(address))
{
// Retrieve data from virtual memory.
data = isVirtualROM(address) ? readVirtualROM(address) : readVirtualRAM(address);
// Decode the address and if virtual RAM, ROM or logic exists, invoke it.
data = readVirtual(address, 0);
}
// Keyport data? Store.
@@ -533,6 +552,12 @@ static zuint8 z80_read(void *context, zuint16 address)
{
Z80Ctrl->keyportHotKey = 0x01;
}
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
{
pr_info("Read:%04x,%02x,%d\n", address, data, CPLD_Z80_INT());
}
#endif
return(data);
}
@@ -566,17 +591,22 @@ static void z80_write(void *context, zuint16 address, zuint8 data)
// Pause until the Last T-State is detected.
//while(CPLD_LAST_TSTATE() == 0);
}
else if(isVirtualHW(address))
// Virtual ROM, technically isnt writable, but some devices such as the TZPU use RAM as ROM and mask it
// according to operating mode.
// Virtual Hardware is driver dependent, common method called to write to ROM/HW.
// Virtual RAM is generally a direct write but any driver may change the action.
else if(isVirtual(address))
{
// Decode the address and if virtual logic exists, invoke and write to it.
writeVirtualHW(address, data, 0);
// Decode the address and process.
writeVirtual(address, data, 0);
}
else if(isVirtualRAM(address))
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
{
// Update virtual memory.
writeVirtualRAM(address, data);
pr_info("Write:%04x,%02x,%d\n", address, data, CPLD_Z80_INT());
}
// Cannot write to virtual ROM so no logic.
#endif
return;
}
// Primary Opcode fetch method. This method is called each time a single or multi-byte opcode is
@@ -628,12 +658,18 @@ static zuint8 z80_fetch_opcode(void *context, zuint16 address)
for(idx=0; idx < Z80Ctrl->cpuGovernorDelayRAM; idx++);
}
}
//if(address < 0x9e0 || address > 0xA00)
//if(address >= 0xE800 && address < 0xF000)
//pr_info("Fetch:%04x(%08x):%02x\n", address, getPageAddr(address, MEMORY_TYPE_VIRTUAL_MASK), opcode);
// Check if this operation is I/O or known memory I/O so we can look ahead to optimise sending request to CPLD.
lookAhead(address, opcode, isVirtualROM((address+1)) ? readVirtualROM((address+1)) : readVirtualRAM((address+1)));
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
{
if(address < 0xF036 || address > 0xF197)
pr_info("Fetch:%04x,%02x,%d\n", address, opcode, CPLD_Z80_INT());
}
//if(address >= 0xE800) pr_info("Fetch:%04x,%02x\n", address, opcode);
#endif
return(opcode);
}
@@ -669,9 +705,19 @@ static zuint8 z80_fetch(void *context, zuint16 address)
}
// Check for interrupts.
if(CPLD_Z80_NMI() != 0) z80_nmi(&Z80CPU);
if(CPLD_Z80_NMI() != 0)
{
z80_nmi(&Z80CPU);
}
z80_int(&Z80CPU, CPLD_Z80_INT() != 0);
//if(CPLD_Z80_INT() != 0) pr_info("Interrupt High\n");
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
{
if(address < 0xF036 || address > 0xF197)
pr_info("FetchB:%04x,%02x,%d\n", address, data, CPLD_Z80_INT());
}
#endif
return(data);
}
@@ -705,9 +751,12 @@ static zuint8 z80_in(void *context, zuint16 port)
if(isVirtualIO(port))
{
// Virtual I/O - call the handler.
value = readVirtualHW(port, 1);
value = readVirtual(port, 1);
}
//pr_info("z80_in:0x%x, 0x%x\n", port, value);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("z80_in:0x%x, 0x%x\n", port, value);
#endif
return(value);
}
@@ -741,9 +790,12 @@ static void z80_out(void *context, zuint16 port, zuint8 value)
if(isVirtualIO(port))
{
// Decode the address and if virtual logic exists, invoke and write to it.
writeVirtualHW(port, value, 1);
writeVirtual(port, value, 1);
}
//pr_info("z80_out:0x%x, 0x%x\n", port, value);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("z80_out:0x%x, 0x%x\n", port, value);
#endif
}
// NOP - No Operation method. This instruction is used for timing, padding out an application or during
@@ -760,7 +812,6 @@ static zuint8 z80_nop(void *context, zuint16 address)
// If autorefresh is not enabled, send a single refresh request.
if(Z80Ctrl->refreshDRAM == 0)
SPI_SEND8(CPLD_CMD_REFRESH);
pr_info("NOP");
}
return 0x00;
}
@@ -816,7 +867,19 @@ static void z80_ldra(void *context)
static void z80_reti(void *context)
{
Z_UNUSED(context)
pr_info("z80_reti\n");
if(CPLD_Z80_INT() != 0)
{
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01)
{
pr_info("LOCKUP:%d\n", CPLD_Z80_INT());
}
#endif
z80_int(&Z80CPU, false);
}
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("z80_reti\n");
#endif
}
static void z80_retn(void *context)
{
@@ -859,8 +922,9 @@ int thread_z80(void * thread_nr)
// Reset pressed?
if(CPLD_RESET())
{
z80_instant_reset(&Z80CPU);
setupMemory(Z80Ctrl->defaultPageMode);
resetZ80();
//z80_instant_reset(&Z80CPU);
//setupMemory(Z80Ctrl->defaultPageMode);
// Wait for release before restarting CPU.
while(CPLD_RESET());
@@ -905,8 +969,18 @@ int thread_z80(void * thread_nr)
static int z80drv_release(struct inode *inodep, struct file *filep)
{
// Locals.
struct task_struct *task = get_current();
mutex_unlock(&Z80DRV_MUTEX);
// Is this the K64F de-registering?
if(Z80Ctrl->ioTask == task)
{
Z80Ctrl->ioTask = NULL;
pr_info("I/O processor stopped.\n");
} else
{
// Free up the mutex preventing more than one control process taking control at the same time.
mutex_unlock(&Z80DRV_MUTEX);
}
//pr_info("z80drv: Device successfully closed\n");
return(0);
@@ -920,16 +994,28 @@ static int z80drv_open(struct inode *inodep, struct file *filep)
{
// Locals.
int ret = 0;
struct task_struct *task = get_current();
// I/O Processor?
if(Z80Ctrl->ioTask == NULL && strcmp(task->comm, IO_PROCESSOR_NAME) == 0)
{
Z80Ctrl->ioTask = task;
pr_info("Registering I/O Processor:%s\n", Z80Ctrl->ioTask->comm);
} else
if(Z80Ctrl->ioTask != NULL && strcmp(task->comm, IO_PROCESSOR_NAME) == 0)
{
pr_info("I/O Processor already registered, PID:%d\n", Z80Ctrl->ioTask->pid);
ret = -EBUSY;
goto out;
} else
if(!mutex_trylock(&Z80DRV_MUTEX))
{
pr_alert("z80drv: device busy!\n");
pr_alert("z80drv: Device busy!\n");
ret = -EBUSY;
goto out;
}
//pr_info("z80drv: Device successfully opened\n");
//pr_info("z80drv: Device opened\n");
out:
return(ret);
}
@@ -1129,13 +1215,27 @@ void setupMemory(enum Z80_MEMORY_PROFILE mode)
// Locals.
uint32_t idx;
// Check to see if the memory mode page has been allocated for current mode.
if(Z80Ctrl->page[Z80Ctrl->memoryMode] == NULL)
{
pr_info("Allocating memory page:%d\n", Z80Ctrl->memoryMode);
(Z80Ctrl->page[Z80Ctrl->memoryMode]) = (uint32_t *)kmalloc((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)), GFP_KERNEL);
if ((Z80Ctrl->page[Z80Ctrl->memoryMode]) == NULL)
{
pr_info("z80drv: failed to allocate memory mapping page:%d memory!", Z80Ctrl->memoryMode);
Z80Ctrl->page[Z80Ctrl->memoryMode] = Z80Ctrl->page[0];
}
}
// Setup default mode according to run mode, ie. Physical run or Virtual run.
//
if(mode == USE_PHYSICAL_RAM)
{
#if(TARGET_HOST_MZ700 == 1)
#endif
#if(TARGET_HOST_MZ2000 == 1)
// Initialise the page pointers and memory to use physical RAM.
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x8000)
{
@@ -1158,7 +1258,7 @@ void setupMemory(enum Z80_MEMORY_PROFILE mode)
#endif
#if(TARGET_HOST_MZ80A == 1)
// Initialise the page pointers and memory to use physical RAM.
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x1000)
{
@@ -1185,7 +1285,7 @@ void setupMemory(enum Z80_MEMORY_PROFILE mode)
}
}
#endif
for(idx=0x0000; idx < 0x10000; idx++)
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
@@ -1197,7 +1297,7 @@ void setupMemory(enum Z80_MEMORY_PROFILE mode)
#if(TARGET_HOST_MZ2000 == 1)
// Initialise the page pointers and memory to use virtual RAM.
// MZ-2000 comes up in IPL mode where lower 32K is ROM and upper 32K is RAM remapped from 0x0000.
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x8000)
{
@@ -1208,7 +1308,7 @@ void setupMemory(enum Z80_MEMORY_PROFILE mode)
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (Z80Ctrl->lowMemorySwap ? idx - 0x8000 : idx));
}
}
for(idx=0x0000; idx < 0x10000; idx++)
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
@@ -1217,34 +1317,30 @@ void setupMemory(enum Z80_MEMORY_PROFILE mode)
#endif
#if(TARGET_HOST_MZ80A == 1)
// Initialise the page pointers and memory to use virtual RAM.
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
for(idx=0x0000; idx < MEMORY_PAGE_SIZE; idx+=MEMORY_BLOCK_GRANULARITY)
{
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, idx);
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_VRAM, idx);
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, idx);
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_PHYSICAL_HW, idx);
}
else if(idx >= 0xE800 && idx < 0xF000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_HW, idx);
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_HW, idx);
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_ROM, idx);
}
else
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, idx);
setMemoryType((idx/MEMORY_BLOCK_GRANULARITY), MEMORY_TYPE_VIRTUAL_ROM, idx);
}
}
for(idx=0x0000; idx < 0x10000; idx++)
for(idx=0x0000; idx < IO_PAGE_SIZE; idx++)
{
Z80Ctrl->iopage[idx] = idx | IO_TYPE_PHYSICAL_HW;
}
@@ -1292,7 +1388,9 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
pr_info("IOCTL - Couldnt retrieve command!\n");
else
{
//pr_info("IOCTL - Command (%08x)\n", ioctlCmd.cmd);
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("IOCTL - Command (%08x)\n", ioctlCmd.cmd);
#endif
switch(ioctlCmd.cmd)
{
// Command to stop the Z80 CPU and power off.
@@ -1303,7 +1401,9 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
z80_power(&Z80CPU, FALSE);
Z80_PC(Z80CPU) = 0;
pr_info("Z80 stopped.\n");
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 stopped.\n");
#endif
break;
// Command to power on and start the Z80 CPU.
@@ -1311,19 +1411,25 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_lock(&Z80RunModeMutex); Z80RunMode = Z80_RUNNING; mutex_unlock(&Z80RunModeMutex);
z80_power(&Z80CPU, TRUE);
pr_info("Z80 started.\n");
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 started.\n");
#endif
break;
// Command to pause the Z80.
case IOCTL_CMD_Z80_PAUSE:
mutex_lock(&Z80RunModeMutex); Z80RunMode = Z80_PAUSE; mutex_unlock(&Z80RunModeMutex);
pr_info("Z80 paused.\n");
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 paused.\n");
#endif
break;
// Command to release a paused Z80.
case IOCTL_CMD_Z80_CONTINUE:
mutex_lock(&Z80RunModeMutex); Z80RunMode = Z80_CONTINUE; mutex_unlock(&Z80RunModeMutex);
pr_info("Z80 running.\n");
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 running.\n");
#endif
break;
// Command to perform a CPU reset.
@@ -1333,10 +1439,12 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
do { mutex_lock(&Z80RunModeMutex); nextRunMode = Z80RunMode ; mutex_unlock(&Z80RunModeMutex);
} while(nextRunMode == Z80_STOP);
z80_instant_reset(&Z80CPU);
setupMemory(Z80Ctrl->defaultPageMode);
resetZ80();
mutex_lock(&Z80RunModeMutex); Z80RunMode = currentRunMode; mutex_unlock(&Z80RunModeMutex);
pr_info("Z80 Reset.\n");
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 Reset.\n");
#endif
break;
// Command to setup the page table to use host memory and physical hardware.
@@ -1347,11 +1455,12 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
} while(nextRunMode == Z80_STOP);
Z80Ctrl->defaultPageMode = USE_PHYSICAL_RAM;
setupMemory(Z80Ctrl->defaultPageMode);
z80_instant_reset(&Z80CPU);
resetZ80();
mutex_lock(&Z80RunModeMutex); Z80RunMode = currentRunMode; mutex_unlock(&Z80RunModeMutex);
pr_info("Z80 Set to use Host Memory.\n");
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 Set to use Host Memory.\n");
#endif
break;
// Command to setup the page table to use virtual memory, only physical hardware is accessed on the host.
@@ -1362,10 +1471,15 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
} while(nextRunMode == Z80_STOP);
Z80Ctrl->defaultPageMode = USE_VIRTUAL_RAM;
setupMemory(Z80Ctrl->defaultPageMode);
z80_instant_reset(&Z80CPU);
resetZ80();
//setupMemory(Z80Ctrl->defaultPageMode);
// z80_instant_reset(&Z80CPU);
mutex_lock(&Z80RunModeMutex); Z80RunMode = currentRunMode; mutex_unlock(&Z80RunModeMutex);
pr_info("Z80 Set to use Virtual Memory.\n");
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 Set to use Virtual Memory.\n");
#endif
break;
// Command to synchronise virtual memory to host DRAM.
@@ -1382,7 +1496,9 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
}
mutex_lock(&Z80RunModeMutex); Z80RunMode = currentRunMode; mutex_unlock(&Z80RunModeMutex);
pr_info("Z80 Host DRAM syncd with Virtual Memory.\n");
#if(DEBUG_ENABLED & 1)
if(Z80Ctrl->debug & 0x01) pr_info("Z80 Host DRAM syncd with Virtual Memory.\n");
#endif
break;
// Command to dump out host memory.
@@ -1586,6 +1702,13 @@ static long int z80drv_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_lock(&Z80RunModeMutex); Z80RunMode = currentRunMode; mutex_unlock(&Z80RunModeMutex);
break;
#if(DEBUG_ENABLED & 1)
// Method to turn on/off debug output.
case IOCTL_CMD_DEBUG:
Z80Ctrl->debug = ioctlCmd.debug.level;
break;
#endif
// Command to run a series of SOM to CPLD SPI tests.
case IOCTL_CMD_SPI_TEST:
// Stop the CPU prior to SPI testing.
@@ -1692,7 +1815,7 @@ static int __init ModuleInit(void)
// Get device Major number.
major = register_chrdev(0, DEVICE_NAME, &z80drv_fops);
if (major < 0) {
pr_info("z80drv: fail to register major number!");
pr_info("z80drv: fail to register major number!\n");
ret = major;
goto initExit;
}
@@ -1700,7 +1823,7 @@ static int __init ModuleInit(void)
class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(class)){
unregister_chrdev(major, DEVICE_NAME);
pr_info("z80drv: failed to register device class");
pr_info("z80drv: failed to register device class\n");
ret = PTR_ERR(class);
goto initExit;
}
@@ -1717,21 +1840,36 @@ static int __init ModuleInit(void)
Z80Ctrl = (t_Z80Ctrl *)kmalloc(sizeof(t_Z80Ctrl), GFP_KERNEL);
if (Z80Ctrl == NULL)
{
pr_info("z80drv: failed to allocate ctrl memory!");
pr_info("z80drv: failed to allocate ctrl memory!\n");
ret = -ENOMEM;
goto initExit;
}
Z80Ctrl->ram= (uint8_t *)kmalloc(Z80_VIRTUAL_RAM_SIZE, GFP_KERNEL);
if (Z80Ctrl->ram == NULL)
{
pr_info("z80drv: failed to allocate RAM memory!");
pr_info("z80drv: failed to allocate RAM memory!\n");
ret = -ENOMEM;
goto initExit;
}
Z80Ctrl->rom= (uint8_t *)kmalloc(Z80_VIRTUAL_ROM_SIZE, GFP_KERNEL);
if (Z80Ctrl->rom == NULL)
{
pr_info("z80drv: failed to allocate ROM memory!");
pr_info("z80drv: failed to allocate ROM memory!\n");
ret = -ENOMEM;
goto initExit;
}
// 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++)
{
(Z80Ctrl->page[idx]) = NULL;
}
// Allocate standard memory mode mapping page.
(Z80Ctrl->page[Z80Ctrl->memoryMode]) = (uint32_t *)kmalloc((MEMORY_BLOCK_SLOTS*sizeof(uint32_t)), GFP_KERNEL);
if ((Z80Ctrl->page[Z80Ctrl->memoryMode]) == NULL)
{
pr_info("z80drv: failed to allocate default memory mapping page memory!\n");
ret = -ENOMEM;
goto initExit;
}
@@ -1856,6 +1994,9 @@ static int __init ModuleInit(void)
// Setup memory profile to use internal virtual RAM (SOM kernel RAM rather than HOST DRAM).
setupMemory(Z80Ctrl->defaultPageMode);
// Initialise control handles.
Z80Ctrl->ioTask = NULL;
// Initialse run control.
mutex_init(&Z80RunModeMutex);
mutex_lock(&Z80RunModeMutex); Z80RunMode = Z80_STOP; mutex_unlock(&Z80RunModeMutex);
@@ -1877,7 +2018,7 @@ static int __init ModuleInit(void)
pr_info("Initialisation complete.\n");
// Create thread to run the Z80 cpu.
kthread_z80 = kthread_create(thread_z80, &threadId_z80, "kthread_z80");
kthread_z80 = kthread_create(thread_z80, &threadId_z80, "z80");
if(kthread_z80 != NULL)
{
pr_info("kthread - Thread Z80 was created, waking...!\n");
@@ -1900,10 +2041,28 @@ initExit:
// the device from the /dev directory.
static void __exit ModuleExit(void)
{
// Locals.
uint32_t idx;
int result;
// Stop the internal threads.
kthread_stop(kthread_z80);
result = kthread_stop(kthread_z80);
if(result != 0)
{
pr_info("Failed to stop Z80 thread, reason:%d\n", result);
}
// Return the memory used for the Z80 'virtual memory' and control variables.
for(idx=0; idx < MEMORY_MODES; idx++)
{
if(Z80Ctrl->page[idx] != NULL)
{
kfree(Z80Ctrl->page[idx]);
Z80Ctrl->page[idx] = NULL;
}
}
kfree(Z80Ctrl->ram); Z80Ctrl->ram = NULL;
kfree(Z80Ctrl->rom); Z80Ctrl->rom = NULL;
kfree(Z80Ctrl);
// Nothing to be done for the hardware.

View File

@@ -39,7 +39,7 @@
#define DRIVER_LICENSE "GPL"
#define DRIVER_AUTHOR "Philip D Smart"
#define DRIVER_DESCRIPTION "Z80 CPU Emulator and Hardware Interface Driver"
#define DRIVER_VERSION "v1.2"
#define DRIVER_VERSION "v1.3"
#define DRIVER_VERSION_DATE "Feb 2023"
#define DRIVER_COPYRIGHT "(C) 2018-2023"
#define TARGET_HOST_MZ700 0 // Target compilation for an MZ700
@@ -52,6 +52,8 @@
#define MAX_VIRTUAL_DEVICES 5 // Maximum number of allowed virtual devices.
#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
// 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
@@ -64,7 +66,8 @@
#define MEMORY_TYPE_PHYSICAL_HW 0x10000000
#define MEMORY_TYPE_VIRTUAL_RAM 0x08000000
#define MEMORY_TYPE_VIRTUAL_ROM 0x04000000
#define MEMORY_TYPE_VIRTUAL_HW 0x02000000
#define MEMORY_TYPE_VIRTUAL_RAM_RO 0x02000000
#define MEMORY_TYPE_VIRTUAL_HW 0x01000000
#define IO_TYPE_PHYSICAL_HW 0x80000000
#define IO_TYPE_VIRTUAL_HW 0x40000000
@@ -88,6 +91,14 @@
#define INSTRUCTION_DELAY_RAM_112MHZ 8
#define INSTRUCTION_DELAY_RAM_224MHZ 4
#define INSTRUCTION_DELAY_RAM_448MHZ 1
#define INSTRUCTION_EQUIV_FREQ_3_54MHZ 3540000
#define INSTRUCTION_EQUIV_FREQ_7MHZ 7000000
#define INSTRUCTION_EQUIV_FREQ_14MHZ 14000000
#define INSTRUCTION_EQUIV_FREQ_28MHZ 28000000
#define INSTRUCTION_EQUIV_FREQ_56MHZ 56000000
#define INSTRUCTION_EQUIV_FREQ_112MHZ 112000000
#define INSTRUCTION_EQUIV_FREQ_224MHZ 224000000
#define INSTRUCTION_EQUIV_FREQ_448MHZ 448000000
enum Z80_INSTRUCTION_DELAY {
ROM_DELAY_NORMAL = INSTRUCTION_DELAY_ROM_3_54MHZ,
@@ -106,6 +117,14 @@ enum Z80_INSTRUCTION_DELAY {
RAM_DELAY_X32 = INSTRUCTION_DELAY_RAM_112MHZ,
RAM_DELAY_X64 = INSTRUCTION_DELAY_RAM_224MHZ,
RAM_DELAY_X128 = INSTRUCTION_DELAY_RAM_448MHZ
CPU_FREQUENCY_NORMAL = INSTRUCTION_EQUIV_FREQ_3_54MHZ,
CPU_FREQUENCY_X2 = INSTRUCTION_EQUIV_FREQ_7MHZ,
CPU_FREQUENCY_X4 = INSTRUCTION_EQUIV_FREQ_14MHZ,
CPU_FREQUENCY_X8 = INSTRUCTION_EQUIV_FREQ_28MHZ,
CPU_FREQUENCY_X16 = INSTRUCTION_EQUIV_FREQ_56MHZ,
CPU_FREQUENCY_X32 = INSTRUCTION_EQUIV_FREQ_112MHZ,
CPU_FREQUENCY_X64 = INSTRUCTION_EQUIV_FREQ_224MHZ,
CPU_FREQUENCY_X128 = INSTRUCTION_EQUIV_FREQ_448MHZ,
};
#endif
@@ -127,6 +146,14 @@ enum Z80_INSTRUCTION_DELAY {
#define INSTRUCTION_DELAY_RAM_128MHZ 7
#define INSTRUCTION_DELAY_RAM_256MHZ 3
#define INSTRUCTION_DELAY_RAM_512MHZ 1
#define INSTRUCTION_EQUIV_FREQ_4MHZ 4000000
#define INSTRUCTION_EQUIV_FREQ_8MHZ 8000000
#define INSTRUCTION_EQUIV_FREQ_16MHZ 16000000
#define INSTRUCTION_EQUIV_FREQ_32MHZ 32000000
#define INSTRUCTION_EQUIV_FREQ_64MHZ 64000000
#define INSTRUCTION_EQUIV_FREQ_128MHZ 128000000
#define INSTRUCTION_EQUIV_FREQ_256MHZ 256000000
#define INSTRUCTION_EQUIV_FREQ_512MHZ 512000000
enum Z80_INSTRUCTION_DELAY {
ROM_DELAY_NORMAL = INSTRUCTION_DELAY_ROM_4MHZ,
@@ -145,6 +172,14 @@ enum Z80_INSTRUCTION_DELAY {
RAM_DELAY_X32 = INSTRUCTION_DELAY_RAM_128MHZ,
RAM_DELAY_X64 = INSTRUCTION_DELAY_RAM_256MHZ,
RAM_DELAY_X128 = INSTRUCTION_DELAY_RAM_512MHZ,
CPU_FREQUENCY_NORMAL = INSTRUCTION_EQUIV_FREQ_4MHZ,
CPU_FREQUENCY_X2 = INSTRUCTION_EQUIV_FREQ_8MHZ,
CPU_FREQUENCY_X4 = INSTRUCTION_EQUIV_FREQ_16MHZ,
CPU_FREQUENCY_X8 = INSTRUCTION_EQUIV_FREQ_32MHZ,
CPU_FREQUENCY_X16 = INSTRUCTION_EQUIV_FREQ_64MHZ,
CPU_FREQUENCY_X32 = INSTRUCTION_EQUIV_FREQ_128MHZ,
CPU_FREQUENCY_X64 = INSTRUCTION_EQUIV_FREQ_256MHZ,
CPU_FREQUENCY_X128 = INSTRUCTION_EQUIV_FREQ_512MHZ,
};
#endif
@@ -165,7 +200,15 @@ enum Z80_INSTRUCTION_DELAY {
#define INSTRUCTION_DELAY_RAM_32MHZ 26
#define INSTRUCTION_DELAY_RAM_64MHZ 13
#define INSTRUCTION_DELAY_RAM_128MHZ 7
#define INSTRUCTION_DELAY_RAM_256MHZ 3
#define INSTRUCTION_DELAY_RAM_256MHZ 0
#define INSTRUCTION_EQUIV_FREQ_2MHZ 2000000
#define INSTRUCTION_EQUIV_FREQ_4MHZ 4000000
#define INSTRUCTION_EQUIV_FREQ_8MHZ 8000000
#define INSTRUCTION_EQUIV_FREQ_16MHZ 16000000
#define INSTRUCTION_EQUIV_FREQ_32MHZ 32000000
#define INSTRUCTION_EQUIV_FREQ_64MHZ 64000000
#define INSTRUCTION_EQUIV_FREQ_128MHZ 128000000
#define INSTRUCTION_EQUIV_FREQ_256MHZ 256000000
enum Z80_INSTRUCTION_DELAY {
ROM_DELAY_NORMAL = INSTRUCTION_DELAY_ROM_2MHZ,
@@ -184,6 +227,14 @@ enum Z80_INSTRUCTION_DELAY {
RAM_DELAY_X32 = INSTRUCTION_DELAY_RAM_64MHZ,
RAM_DELAY_X64 = INSTRUCTION_DELAY_RAM_128MHZ,
RAM_DELAY_X128 = INSTRUCTION_DELAY_RAM_256MHZ,
CPU_FREQUENCY_NORMAL = INSTRUCTION_EQUIV_FREQ_2MHZ,
CPU_FREQUENCY_X2 = INSTRUCTION_EQUIV_FREQ_4MHZ,
CPU_FREQUENCY_X4 = INSTRUCTION_EQUIV_FREQ_8MHZ,
CPU_FREQUENCY_X8 = INSTRUCTION_EQUIV_FREQ_16MHZ,
CPU_FREQUENCY_X16 = INSTRUCTION_EQUIV_FREQ_32MHZ,
CPU_FREQUENCY_X32 = INSTRUCTION_EQUIV_FREQ_64MHZ,
CPU_FREQUENCY_X64 = INSTRUCTION_EQUIV_FREQ_128MHZ,
CPU_FREQUENCY_X128 = INSTRUCTION_EQUIV_FREQ_256MHZ,
};
#endif
@@ -203,11 +254,10 @@ enum Z80_INSTRUCTION_DELAY {
#define IOCTL_CMD_SEND _IOW('c', 'c', int32_t *)
#define IOCTL_CMD_SETPC _IOW('p', 'p', int32_t *)
#define IOCTL_CMD_SYNC_TO_HOST_RAM 'V'
#define IOCTL_CMD_DEBUG 'd'
#define IOCTL_CMD_SPI_TEST '1'
#define IOCTL_CMD_PRL_TEST '2'
#define IOCTL_CMD_Z80_MEMTEST '3'
// Chip Select map MZ80K-MZ700.
//
@@ -261,38 +311,75 @@ enum Z80_INSTRUCTION_DELAY {
// * = MZ-800 host only.
// Macros to lookup and test to see if a given memory block or IO byte is of a given type. Also macros to read/write to the memory block and IO byte.
#define MEMORY_BLOCK_GRANULARITY 0x800
#define MEMORY_BLOCK_SLOTS (0x10000 / MEMORY_BLOCK_GRANULARITY)
#define MEMORY_BLOCK_MASK (0x10000 - MEMORY_BLOCK_GRANULARITY)
#define MEMORY_BLOCK_SHIFT 11
#define getPageData(a) (Z80Ctrl->page[(a & 0xF800) >> MEMORY_BLOCK_SHIFT])
#define getIOPageData(a) (Z80Ctrl->iopage[(a & 0xFFFF])
// 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_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
#define MEMORY_BLOCK_SLOTS (MEMORY_PAGE_SIZE / MEMORY_BLOCK_GRANULARITY)
#define MEMORY_BLOCK_MASK (MEMORY_PAGE_SIZE - MEMORY_BLOCK_GRANULARITY)
#define IO_PAGE_SIZE 0x10000 // Total size of directly addressable I/O.
#define IO_BLOCK_GRANULARITY 0x1 // Any change update MEMORY_BLOCK_SHIFT and mask in MEMORY_BLOCK_MASK
#define IO_BLOCK_SHIFT 0
#define IO_BLOCK_SLOTS (IO_PAGE_SIZE / IO_BLOCK_GRANULARITY)
#define IO_BLOCK_MASK (IO_PAGE_SIZE - IO_BLOCK_GRANULARITY)
//#define getPageData(a) (Z80Ctrl->page[(a & 0xFFFF) >> MEMORY_BLOCK_SHIFT])
//#define getIOPageData(a) (Z80Ctrl->iopage[(a & 0xFFFF])
#define getPageData(a) (*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + ((a & MEMORY_BLOCK_MASK) >> MEMORY_BLOCK_SHIFT)))
#define getIOPageData(a) (Z80Ctrl->iopage[(a & IO_BLOCK_MASK])
#define getPageType(a, mask) (getPageData(a) & mask)
#define getPageAddr(a, mask) ((getPageData(a) & mask) + (a & (MEMORY_BLOCK_GRANULARITY-1)))
#define getIOPageType(a, mask) (getIOPageData(a) & mask)
#define getIOPageAddr(a, mask) (getIOPageData(a) & mask)
#define realAddress(a) (Z80Ctrl->page[getPageAddr(a, MEMORY_TYPE_REAL_MASK)])
#define realPort(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_MASK)
//#define realAddress(a) (Z80Ctrl->page[getPageAddr(a, MEMORY_TYPE_REAL_MASK)])
#define realAddress(a) (*(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (getPageAddr(a, MEMORY_TYPE_REAL_MASK))))
#define realPort(a) (Z80Ctrl->iopage[a & IO_BLOCK_MASK] & IO_TYPE_MASK)
#define isPhysicalRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_RAM))
#define isPhysicalVRAM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_VRAM))
#define isPhysicalROM(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_ROM))
#define isPhysicalMemory(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM))])
#define isPhysicalHW(a) (getPageType(a, MEMORY_TYPE_PHYSICAL_HW))
#define isPhysical(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_PHYSICAL_ROM | MEMORY_TYPE_PHYSICAL_RAM | MEMORY_TYPE_PHYSICAL_VRAM)))
#define isPhysicalIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_PHYSICAL_HW)
#define isVirtualRAM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_RAM))
#define isPhysicalIO(a) (Z80Ctrl->iopage[a & IO_BLOCK_MASK] & IO_TYPE_PHYSICAL_HW)
#define isVirtualRAM(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_RAM | MEMORY_TYPE_VIRTUAL_RAM_RO)))
#define isVirtualRO(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_RAM_RO))
#define isVirtualRW(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_RAM))
#define isVirtualROM(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_ROM))
#define isVirtualMemory(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_RAM)))
#define isVirtualMemory(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_RAM | MEMORY_TYPE_VIRTUAL_RAM_RO)))
#define isVirtualHW(a) (getPageType(a, MEMORY_TYPE_VIRTUAL_HW))
#define isVirtualIO(a) (Z80Ctrl->iopage[a & 0xFFFF] & IO_TYPE_VIRTUAL_HW)
#define isVirtualDevice(a, d) (Z80Ctrl->iopage[a & 0xFFFF] & d)
#define isVirtualIO(a) (Z80Ctrl->iopage[a & IO_BLOCK_MASK] & IO_TYPE_VIRTUAL_HW)
#define isVirtual(a) (getPageType(a, (MEMORY_TYPE_VIRTUAL_ROM | MEMORY_TYPE_VIRTUAL_RAM | MEMORY_TYPE_VIRTUAL_RAM_RO | MEMORY_TYPE_VIRTUAL_HW)))
#define isVirtualDevice(a, d) (Z80Ctrl->iopage[a & IO_BLOCK_MASK] & d)
#define isHW(a) (getPageType(a, (MEMORY_TYPE_PHYSICAL_HW | MEMORY_TYPE_VIRTUAL_HW)))
#define readVirtualRAM(a) (Z80Ctrl->ram[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ])
#define readVirtualROM(a) (Z80Ctrl->rom[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ])
#define writeVirtualRAM(a, d) { Z80Ctrl->ram[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ] = d; }
#define setMemoryType(_block_,_type_,_addr_) { Z80Ctrl->page[_block_] = _type_ | _addr_; }
#define backupMemoryType(_block_) { Z80Ctrl->shadowPage[_block_] = Z80Ctrl->page[_block_]; }
#define restoreMemoryType(_block_) { Z80Ctrl->page[_block_] = Z80Ctrl->shadowPage[_block_]; }
#define writeVirtualROM(a, d) { Z80Ctrl->rom[ getPageAddr(a, MEMORY_TYPE_VIRTUAL_MASK) ] = d; }
//#define setMemoryType(_block_,_type_,_addr_) { Z80Ctrl->page[_block_] = _type_ | _addr_; }
#define setMemoryType(_block_,_type_,_addr_) { *(*(Z80Ctrl->page + Z80Ctrl->memoryMode) +_block_) = _type_ | _addr_; }
#define backupMemoryType(_block_) { Z80Ctrl->shadowPage[_block_] = *(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (_block_)); }
//#define restoreMemoryType(_block_) { Z80Ctrl->page[_block_] = Z80Ctrl->shadowPage[_block_]; }
#define restoreMemoryType(_block_) { *(*(Z80Ctrl->page + Z80Ctrl->memoryMode) + (_block_)) = Z80Ctrl->shadowPage[_block_]; }
#define sendSignal(_signal_) { struct siginfo sigInfo;\
if(Z80Ctrl->ioTask != NULL)\
{\
memset(&sigInfo, 0, sizeof(struct siginfo));\
sigInfo.si_signo = _signal_;\
sigInfo.si_code = SI_QUEUE;\
sigInfo.si_int = 1;\
if(send_sig_info(_signal_, &sigInfo, Z80Ctrl->ioTask) < 0)\
{\
pr_info("Error: Failed to send Request to I/O Processor:%d, %s\n", _signal_, Z80Ctrl->ioTask->comm);\
}\
}\
}
#define resetZ80() {\
sendSignal(SIGUSR1); \
setupMemory(Z80Ctrl->defaultPageMode);\
z80_instant_reset(&Z80CPU);\
}
#define IO_ADDR_E0 0xE0
#define IO_ADDR_E1 0xE1
@@ -343,7 +430,7 @@ typedef struct {
// Page pointer map.
//
// Each pointer points to a byte or block of bytes in the Z80 Memory frame, 64K Real + Banked.
// This is currently set at a block of size 0x800 per memory pointer for the MZ-700.
// This is currently set at a block of size 0x1 per memory pointer for the MZ-700.
// The LSB of the pointer is a direct memory index to a byte or block of bytes, the upper byte of the pointer indicates type of memory space.
// 0x80<FFFFFF> - physical host RAM
// 0x40<FFFFFF> - physical host ROM
@@ -354,8 +441,12 @@ typedef struct {
// 0x02<FFFFFF> - virtual host hardware
// 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 shadowPage[MEMORY_BLOCK_SLOTS];
//uint32_t page[MEMORY_BLOCK_SLOTS];
uint32_t *page[MEMORY_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.
uint8_t memoryMode;
// I/O Page map.
//
@@ -380,13 +471,13 @@ typedef struct {
uint8_t ioReadAhead;
uint8_t ioWriteAhead;
#if(TARGET_HOST_MZ2000 == 1)
#if(TARGET_HOST_MZ2000 == 1)
uint8_t lowMemorySwap;
#endif
#if(TARGET_HOST_MZ80A == 1)
#endif
#if(TARGET_HOST_MZ80A == 1)
// MZ-80A can relocate the lower 4K ROM by swapping RAM at 0xC000.
uint8_t memSwitch;
#endif
#endif
// Keyboard strobe and data. Required to detect hotkey press.
uint8_t keyportStrobe;
@@ -400,36 +491,52 @@ typedef struct {
// is quicker than RAM (both are in the same kernel memory) as a pointer calculation needs to be made.
uint32_t cpuGovernorDelayROM;
uint32_t cpuGovernorDelayRAM;
// 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)
// Debugging flag.
uint8_t debug;
#endif
} t_Z80Ctrl;
// IOCTL structure for passing data from user space to driver to perform commands.
//
struct z80_addr {
uint32_t start;
uint32_t end;
uint32_t size;
uint32_t start;
uint32_t end;
uint32_t size;
};
struct z80_ctrl {
uint16_t pc;
uint16_t pc;
};
struct speed {
uint32_t speedMultiplier;
uint32_t speedMultiplier;
};
struct virtual_device {
enum VIRTUAL_DEVICE device;
};
struct cpld_ctrl {
uint32_t cmd;
uint32_t cmd;
};
#if(DEBUG_ENABLED == 1)
struct debug {
uint8_t level;
};
#endif
struct ioctlCmd {
int32_t cmd;
union {
struct z80_addr addr;
struct z80_ctrl z80;
struct speed speed;
struct virtual_device vdev;
struct cpld_ctrl cpld;
};
int32_t cmd;
union {
struct z80_addr addr;
struct z80_ctrl z80;
struct speed speed;
struct virtual_device vdev;
struct cpld_ctrl cpld;
#if(DEBUG_ENABLED == 1)
struct debug debug;
#endif
};
};
// Prototypes.

View File

@@ -166,8 +166,6 @@ void rfsSetupMemory(enum Z80_MEMORY_PROFILE mode)
// is controlled by the REG_BANK1 (MROM) and REG_BANK2 (UROM) registers with the upper UROM registers provided in REG_CTRL.
// So on initial setup, map the MROM page to point to the Z80 ROM area 0x00000 which is the base of the first 512K Flash ROM (virtual).
pr_info("RFS Memory Setup complete.\n");
// Setup defaults.
RFSCtrl.regBank1 = 0x00;
RFSCtrl.regBank2 = 0x00;
@@ -202,6 +200,7 @@ void rfsSetupMemory(enum Z80_MEMORY_PROFILE mode)
}
// No I/O Ports on the RFS board.
pr_info("RFS Memory Setup complete.\n");
}
// Perform any setup operations, such as variable initialisation, to enable use of this module.
@@ -561,7 +560,7 @@ void rfsSDCard(void)
}
// Method to read from either the memory mapped registers if enabled else the ROM.
static inline uint8_t rfsRead(zuint16 address)
static inline uint8_t rfsRead(zuint16 address, uint8_t ioFlag)
{
// Locals.
uint8_t data = 0xFF;
@@ -570,14 +569,14 @@ static inline uint8_t rfsRead(zuint16 address)
// Any access to the control region increments the enable counter till it reaches terminal count and enables writes to the registers. When the counter
// gets to 15 the registers are enabled and the EPROM, in the control region, is disabled.
if(address >= BNKCTRLRST && RFSCtrl.upCntr < 15)
if((address >= BNKCTRLRST && address <= BNKCTRL) && RFSCtrl.upCntr < 15)
{
RFSCtrl.upCntr++;
}
// Address in control region and register bank enabled?
//
if(RFSCtrl.upCntr >= 15 && address >= BNKCTRLRST)
if(RFSCtrl.upCntr >= 15 && (address >= BNKCTRLRST && address <= BNKCTRL))
{
switch(address)
{
@@ -616,7 +615,7 @@ static inline uint8_t rfsRead(zuint16 address)
} else
{
// Return the contents of the ROM at given address.
data = readVirtualROM(address);
data = isVirtualROM(address) ? readVirtualROM(address) : readVirtualRAM(address);
}
//pr_info("RFS-Read:%04x, Data:%02x, BK1:%02x, BK2:%02x, CTRL:%02x, MROM:%08x, UROM:%08x\n", address, data, RFSCtrl.regBank1, RFSCtrl.regBank2, RFSCtrl.regCtrl, RFSCtrl.mromAddr, RFSCtrl.uromAddr);
@@ -624,7 +623,7 @@ static inline uint8_t rfsRead(zuint16 address)
}
// Method to handle writes to the RFS board. Generally the RFS board.
static inline void rfsWrite(zuint16 address, zuint8 data)
static inline void rfsWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals.
uint32_t idx;
@@ -633,14 +632,14 @@ static inline void rfsWrite(zuint16 address, zuint8 data)
// Any access to the control region increments the enable counter till it reaches terminal count and enables writes to the registers. When the counter
// gets to 15 the registers are enabled and the EPROM, in the control region, is disabled.
if(address >= BNKCTRLRST && RFSCtrl.upCntr < 15)
if((address >= BNKCTRLRST && address <= BNKCTRL) && RFSCtrl.upCntr < 15)
{
RFSCtrl.upCntr++;
}
// Address in control region and register bank enabled?
//
if(RFSCtrl.upCntr >= 15 && address >= BNKCTRLRST)
if(RFSCtrl.upCntr >= 15 && (address >= BNKCTRLRST && address <= BNKCTRL))
{
switch(address)
{
@@ -708,6 +707,10 @@ static inline void rfsWrite(zuint16 address, zuint8 data)
}
break;
}
} else
{
// Any unprocessed write is commited to RAM.
writeVirtualRAM(address, data);
}
//pr_info("RFS-Write:%04x, Data:%02x, BK1:%02x, BK2:%02x, CTRL:%02x, MROM:%08x, UROM:%08x\n", address, data, RFSCtrl.regBank1, RFSCtrl.regBank2, RFSCtrl.regCtrl, RFSCtrl.mromAddr, RFSCtrl.uromAddr);
return;

View File

@@ -6,14 +6,17 @@
// Description: Z80 Virtual Hardware Driver - tranZPUter SW
// This file contains the methods used to emulate the first tranZPUter Software series
// the tranZPUter SW which used a Cortex-M4 to enhance the host machine and provide
// an upgraded monitor, the tzfs (tranZPUter Filing System).
// an upgraded monitor, the tzfs (tranZPUter Filing System). As the original hardware
// use an independent processor to provide services to the Z80, this driver is made up
// of two parts, 1) the Z80, ie. this driver, 2) a user space daemon which fulfils the
// role of the independent processor.
//
// These drivers are intended to be instantiated inline to reduce overhead of a call
// and as such, they are included like header files rather than C linked object files.
// Credits:
// Copyright: (c) 2019-2023 Philip Smart <philip.smart@net2net.org>
//
// History: Feb 2023 - Initial write based on the RFS hardware.
// History: Feb 2023 v1.0 - Initial write based on the tranZPUter SW hardware.
//
// Notes: See Makefile to enable/disable conditional components
//
@@ -53,19 +56,69 @@
#include <infinity2m/gpio.h>
#include <infinity2m/registers.h>
#include "tzpu.h"
// TZPU Board registers.
typedef struct {
uint8_t clkSrc; // Source of clock, host - 0, secondary - 1
uint8_t regCmd; // Internal command register of the CPLD.
uint8_t regCmdStatus; // Internal command status register of the CPLD.
uint8_t regCpuCfg; // Internal FPGA CPU config register.
uint8_t regCpuInfo; // Internal FPGA CPU information register.
uint8_t regCpldCfg; // Internal CPLD config register.
uint8_t regCpldInfo; // Internal CPLD information register.
} t_TZPUCtrl;
// TZPU Board control.
static t_TZPUCtrl TZPUCtrl;
//-------------------------------------------------------------------------------------------------------------------------------
//
//
//-------------------------------------------------------------------------------------------------------------------------------
// Method to setup the memory page config to reflect installation of a tranZPUter SW Board.
void tzpuSetupMemory(enum Z80_MEMORY_PROFILE mode)
{
}
// Memory Modes: 0 - Default, normal Sharp MZ80A operating mode, all memory and IO (except tranZPUter control IO block) are on the mainboard
// 1 - As 0 except User ROM is mapped to tranZPUter RAM.
// 2 - TZFS, Monitor ROM 0000-0FFF, Main DRAM 0x1000-0xD000, User/Floppy ROM E800-FFFF are in tranZPUter memory. Two small holes of 2 bytes at F3FE and F7FE exist
// for the Floppy disk controller, the fdc uses the rom as a wait detection by toggling the ROM lines according to WAIT, the Z80 at 2MHz hasnt enough ooomph to read WAIT and action it.
// NB: Main DRAM will not be refreshed so cannot be used to store data in this mode.
// 3 - TZFS, Monitor ROM 0000-0FFF, Main RAM area 0x1000-0xD000, User ROM 0xE800-EFFF are in tranZPUter memory block 0, Floppy ROM F000-FFFF are in tranZPUter memory block 1.
// NB: Main DRAM will not be refreshed so cannot be used to store data in this mode.
// 4 - TZFS, Monitor ROM 0000-0FFF, Main RAM area 0x1000-0xD000, User ROM 0xE800-EFFF are in tranZPUter memory block 0, Floppy ROM F000-FFFF are in tranZPUter memory block 2.
// NB: Main DRAM will not be refreshed so cannot be used to store data in this mode.
// 5 - TZFS, Monitor ROM 0000-0FFF, Main RAM area 0x1000-0xD000, User ROM 0xE800-EFFF are in tranZPUter memory block 0, Floppy ROM F000-FFFF are in tranZPUter memory block 3.
// NB: Main DRAM will not be refreshed so cannot be used to store data in this mode.
// 6 - CPM, all memory on the tranZPUter board, 64K block 4 selected.
// Special case for F3FE:F3FF & F7FE:F7FF (floppy disk paging vectors) which resides on the mainboard.
// 7 - CPM, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5 selected, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
// Special case for 0000:00FF (interrupt vectors) which resides in block 4 and CPM vectors and two small holes of 2 bytes at F3FE and F7FE exist for the Floppy disk controller, the fdc
// uses the rom as a wait detection by toggling the ROM lines according to WAIT, the Z80 at 2MHz hasnt enough ooomph to read WAIT and action it.
// 8 - Monitor ROM (0000:0FFF) on mainboard, Main RAM (1000:CFFF) in tranZPUter bank 0 and video, memory mapped I/O, User/Floppy ROM on mainboard.
// NB: Main DRAM will not be refreshed so cannot be used to store data in this mode.
// 9 - Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
// 10 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
// 11 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
// 12 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
// 13 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
// 14 - MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
// 15 - MZ800 Mode - Running on MZ800 hardware, configuration set according to MZ700/MZ800 mode.
// 16 - MZ2000 Mode - Running on MZ2000 hardware, configuration set according to the MZ2000 runtime configuration registers.
// 21 - Access the FPGA memory by passing through the full 24bit Z80 address, typically from the K64F.
// 22 - Access to the host mainboard 64K address space only.
// 23 - Access all memory and IO on the tranZPUter board with the K64F addressing the full 512K-1MB RAM.
// 24 - All memory and IO are on the tranZPUter board, 64K block 0 selected.
// 25 - All memory and IO are on the tranZPUter board, 64K block 1 selected.
// 26 - All memory and IO are on the tranZPUter board, 64K block 2 selected.
// 27 - All memory and IO are on the tranZPUter board, 64K block 3 selected.
// 28 - All memory and IO are on the tranZPUter board, 64K block 4 selected.
// 29 - All memory and IO are on the tranZPUter board, 64K block 5 selected.
// 30 - All memory and IO are on the tranZPUter board, 64K block 6 selected.
// 31 - All memory and IO are on the tranZPUter board, 64K block 7 selected.
// Perform any setup operations, such as variable initialisation, to enable use of this module.
void tzpuInit(void)
{
pr_info("Enabling TZPU driver.\n");
}
// Method to decode an address and make any system memory map changes as required.
@@ -73,19 +126,678 @@ void tzpuInit(void)
static inline void tzpuDecodeMemoryMapSetup(zuint16 address, zuint8 data, uint8_t ioFlag, uint8_t readFlag)
{
// Locals.
// I/O or Memory?
if(ioFlag == 0)
{
// Memory map switch.
if(readFlag == 0)
{
} else
{
}
} else
// I/O Decoding.
{
// Only lower 8 bits recognised in the tzpu.
switch(address & 0xFF)
{
default:
break;
}
}
}
// Method to read from the tranZPUter SW memory or I/O ports.
static inline uint8_t tzpuRead(zuint16 address)
static inline uint8_t tzpuRead(zuint16 address, uint8_t ioFlag)
{
// Locals.
uint8_t data = 0x00;
// The tranZPUter board, in order to autoboot and use valuable space for variables, allows writing into the User ROM
// space above 0xEBFF. 0xE800 is used to detect if a ROM is installed and cannot be written.
if(ioFlag == 0 && isVirtualRAM(address))
{
// Retrieve data from virtual memory.
data = readVirtualRAM(address);
} else
if(ioFlag)
{
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) 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.
//
switch(address & 0x00FF)
{
case IO_TZ_CTRLLATCH:
data = Z80Ctrl->memoryMode;
break;
case IO_TZ_SETXMHZ:
break;
case IO_TZ_SET2MHZ:
break;
case IO_TZ_CLKSELRD:
data = TZPUCtrl.clkSrc;
break;
case IO_TZ_SVCREQ:
break;
case IO_TZ_SYSREQ:
break;
case IO_TZ_CPLDSTATUS:
data = TZPUCtrl.regCmdStatus;
break;
case IO_TZ_CPUSTATUS:
data = TZPUCtrl.regCpuCfg;
break;
case IO_TZ_CPUINFO:
data = TZPUCtrl.regCpuInfo;
break;
case IO_TZ_CPLDCFG:
data = TZPUCtrl.regCpldCfg;
break;
case IO_TZ_CPLDINFO:
data = TZPUCtrl.regCpldInfo;
break;
default:
break;
}
}
return(data);
}
// Method to write to the tranZPUter SW memory or I/O ports.
static inline void tzpuWrite(zuint16 address, zuint8 data)
static inline void tzpuWrite(zuint16 address, zuint8 data, uint8_t ioFlag)
{
// Locals
uint32_t idx;
// The tranZPUter board, in order to autoboot and use valuable space for variables, allows writing into the User ROM
// space above 0xE800. 0xE800 is used to detect if a ROM is installed and cannot be written.
if(ioFlag == 0)
{
// Virtual ROM in range 0xEC00:0xEFFF is Read/Write.
if(isVirtualRW(address))
{
//if(address >= 0xE800) pr_info("Write:%04x,%02x\n", address, data);
writeVirtualRAM(address, data);
}
} else
if(ioFlag)
{
// Only the lower 8 bits of the I/O address are processed as the upper byte is not used in the Sharp models.
//
switch(address & 0x00FF)
{
case IO_TZ_CTRLLATCH:
//pr_info("CTRLLATCH:%02x\n", data);
// Check to see if the memory mode page has been allocated for requested mode, if it hasnt, we need to allocate and then define.
Z80Ctrl->memoryMode = (data & (MEMORY_MODES - 1));
if(Z80Ctrl->page[Z80Ctrl->memoryMode] == NULL)
{
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) 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)
{
pr_info("z80drv: failed to allocate memory mapping page:%d memory!", Z80Ctrl->memoryMode);
Z80Ctrl->page[Z80Ctrl->memoryMode] = Z80Ctrl->page[0];
}
// A lot of the memory maps below are identical, minor changes such as RAM bank. This is a direct conversion of the VHDL code from the CPLD.
//
for(idx=0x0000; idx < 0x10000; idx+=MEMORY_BLOCK_GRANULARITY)
{
switch(Z80Ctrl->memoryMode)
{
// Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
case TZMM_ORIG:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE800 && idx < 0xEC00)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xEC00 && idx < 0xF000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
break;
// Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
case TZMM_BOOT:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE800 && idx < 0xEC00)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xEC00 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
break;
// TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
case TZMM_TZFS:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx == 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE801 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
break;
// TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
case TZMM_TZFS2:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE800 && idx < 0xEC00)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xEC00 && idx < 0xF000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK1_ADDR+idx));
}
break;
// TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
case TZMM_TZFS3:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx == 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE801 && idx < 0xF000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK2_ADDR+idx));
}
break;
// TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
case TZMM_TZFS4:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx == 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE801 && idx < 0xF000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK3_ADDR+idx));
}
break;
// CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
case TZMM_CPM:
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK4_ADDR+idx));
break;
// CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
// Special case for 0000:003F (interrupt vectors) which resides in block 4, F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
case TZMM_CPM2:
if(idx >= 0 && idx < 0x40)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK4_ADDR+idx));
}
else if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK5_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK5_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE800 && idx < 0xEC00)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK5_ADDR+idx));
}
else if(idx >= 0xEC00 && idx < 0xF000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK5_ADDR+idx));
}
else if(idx >= 0xF000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK4_ADDR+idx));
}
break;
// Original mode but with main DRAM in Bank 0 to allow bootstrapping of programs from other machines such as the MZ700.
case TZMM_COMPAT:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE800 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
break;
// Mode to allow code running in Bank 0, address E800:FFFF to access host memory. Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory.
case TZMM_HOSTACCESS:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE800 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
break;
// MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
case TZMM_MZ700_0:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK6_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0xE000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_VRAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE000 && idx < 0xE800)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_PHYSICAL_HW, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xE800 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM_RO, (SRAM_BANK0_ADDR+idx));
}
break;
// MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
case TZMM_MZ700_1:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK6_ADDR+idx));
}
break;
// MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
case TZMM_MZ700_2:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK6_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK6_ADDR+idx));
}
break;
// MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
case TZMM_MZ700_3:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, (SRAM_BANK0_ADDR+idx));
}
break;
// MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
case TZMM_MZ700_4:
if(idx >= 0 && idx < 0x1000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK6_ADDR+idx));
}
else if(idx >= 0x1000 && idx < 0xD000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_VIRTUAL_RAM, (SRAM_BANK0_ADDR+idx));
}
else if(idx >= 0xD000 && idx < 0x10000)
{
setMemoryType(idx/MEMORY_BLOCK_GRANULARITY, MEMORY_TYPE_INHIBIT, (SRAM_BANK0_ADDR+idx));
}
break;
// MZ800 Mode - Host is an MZ-800 and mode provides for MZ-700/MZ-800 decoding per original machine.
case TZMM_MZ800:
// MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
case TZMM_MZ2000:
// Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
case TZMM_FPGA:
// Everything is on mainboard, no access to tranZPUter memory.
case TZMM_TZPUM:
// Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory. K64F drives A18-A16 allowing full access to RAM.
case TZMM_TZPU:
default:
pr_info("Memory Mode(%d) not available.\n", data);
break;
}
}
}
// Memory map now created/switched.
break;
case IO_TZ_SETXMHZ:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) 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);
#endif
TZPUCtrl.clkSrc = 0;
break;
case IO_TZ_CLKSELRD:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) 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);
#endif
// If a k64f process has registered, send it a service request signal.
sendSignal(SIGIO);
// A strange race state exists with CP/M and interrupts during disk requests. If no delay is
// given for read/write requests, the interrupt line will eventually lockup active and the Z80
// enters an interrupt loop. Strange because the Z80 interrupt line is a buffered signal from the
// host motherboard to the SOM via CPLD without latches. The 8253 timer generates the interrupt
// but the ISR resets it. My guess is memory corruption due to a race state, more time is needed
// debugging but in the meantime, a 2ms delay ensures the read/write completes prior to next
// request.
if(Z80Ctrl->ram[0x4f560] == 0x32 || Z80Ctrl->ram[0x4f560] == 0x33)
{
udelay(2000);
}
break;
case IO_TZ_SYSREQ:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) 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);
#endif
TZPUCtrl.regCmd = data;
break;
case IO_TZ_CPUINFO:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) 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);
#endif
break;
case IO_TZ_CPLDINFO:
#if(DEBUG_ENABLED & 0x01)
if(Z80Ctrl->debug & 0x01) pr_info("CPLDINFO:%02x\n", data);
#endif
break;
default:
pr_info("PORT:%02x\n", data);
break;
}
}
return;
}
// Method to setup the memory page config to reflect installation of a tranZPUter SW Board. This sets up the default
// as the memory map changes according to selection and handled in-situ.
void tzpuSetupMemory(enum Z80_MEMORY_PROFILE mode)
{
// Locals.
uint32_t idx;
// The tranZPUter SW uses a CPLD to set a 4K Z80 memory range window into a 512K-1MB linear RAM block. The actual map required
// at any one time is governed by the Memory Config register at I/O port 0x60.
// This method sets the initial state, which is a normal Sharp operating mode, all memory and IO (except tranZPUter
// control IO block) are on the mainboard.
// Setup defaults.
TZPUCtrl.clkSrc = 0x00; // Clock defaults to host.
TZPUCtrl.regCmd = 0x00; // Default for the CPLD Command.
TZPUCtrl.regCmdStatus = 0x00; // Default for the CPLD Command Status.
TZPUCtrl.regCpuCfg = 0x00; // Not used, as no FPGA available, but need to store/return value if addressed.
TZPUCtrl.regCpuInfo = 0x00; // Not used, as no FPGA available, but need to store/return value if addressed.
// Setup the CPLD status value, this is used by the host for configuration of tzfs.
#if(TARGET_HOST_MZ80A == 1)
TZPUCtrl.regCpldInfo = (CPLD_VERSION << 4) | (CPLD_HAS_FPGA_VIDEO << 3) | HWMODE_MZ80A;
#endif
#if(TARGET_HOST_MZ700 == 1)
TZPUCtrl.regCpldInfo = (CPLD_VERSION << 4) | (CPLD_HAS_FPGA_VIDEO << 3) | HWMODE_MZ700;
#endif
#if(TARGET_HOST_MZ2000 == 1)
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.
// Go through and clear all memory maps, valid for startup and reset.
for(idx=0; idx < MEMORY_MODES; idx++)
{
if(Z80Ctrl->page[idx] != NULL)
{
kfree(Z80Ctrl->page[idx]);
Z80Ctrl->page[idx] = NULL;
}
}
// Setup all initial TZFS memory modes
tzpuWrite(IO_TZ_CTRLLATCH, TZMM_ORIG, 1);
tzpuWrite(IO_TZ_CTRLLATCH, TZMM_TZFS, 1);
tzpuWrite(IO_TZ_CTRLLATCH, TZMM_TZFS2, 1);
tzpuWrite(IO_TZ_CTRLLATCH, TZMM_TZFS3, 1);
tzpuWrite(IO_TZ_CTRLLATCH, TZMM_TZFS4, 1);
Z80Ctrl->memoryMode = 0x02; // Default memory mode, MZ-80A.
// I/O Ports on the tranZPUter SW board. All hosts have the same ports for the tzpu board.
for(idx=0x0000; idx < 0x10000; idx+=0x0100)
{
Z80Ctrl->iopage[idx+IO_TZ_CTRLLATCH] = IO_TZ_CTRLLATCH | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_SETXMHZ] = IO_TZ_SETXMHZ | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_SET2MHZ] = IO_TZ_SET2MHZ | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_CLKSELRD] = IO_TZ_CLKSELRD | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_SVCREQ] = IO_TZ_SVCREQ | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_SYSREQ] = IO_TZ_SYSREQ | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_CPLDCMD] = IO_TZ_CPLDCMD | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_CPLDSTATUS] = IO_TZ_CPLDSTATUS | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_CPUCFG] = IO_TZ_CPUCFG | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_CPUSTATUS] = IO_TZ_CPUSTATUS | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_CPUINFO] = IO_TZ_CPUINFO | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_CPLDCFG] = IO_TZ_CPLDCFG | IO_TYPE_VIRTUAL_HW;
Z80Ctrl->iopage[idx+IO_TZ_CPLDINFO] = IO_TZ_CPLDINFO | IO_TYPE_VIRTUAL_HW;
}
pr_info("TZPU Memory Setup complete.\n");
}

View File

@@ -4,7 +4,7 @@ MODEL := MZ80A
KERNEL := $(PWD)/../../../linux/kernel
FUSIONX := $(PWD)/../..
CROSS := arm-linux-gnueabihf-
ccflags-y += -O2 -I${src}/Zeta/API -I${src}/Z80/API -I${KERNEL}/drivers/sstar/include -I${KERNEL}/drivers/sstar/include/infinity2m -I${KERNEL}/drivers/sstar/gpio/infinity2m
ccflags-y += -O2 -I${src}/Zeta/API -I${src}/Z80/API -I${KERNEL}/drivers/sstar/include -I${KERNEL}/drivers/sstar/include/infinity2m -I${KERNEL}/drivers/sstar/gpio/infinity2m -D__KERNEL_DRIVER__
CTRLINC += -IZeta/API -IZ80/API
obj-m += z80drv.o
@@ -16,9 +16,14 @@ z80drv-objs += ../../../linux/kernel/drivers/sstar/gpio/infinity2m/padmux_tables
all:
@echo "Build driver for host: $(MODEL)"
@echo ""
@echo "Build K64F Daemon for host: $(MODEL)"
$(CROSS)gcc $(CTRLINC) $(MODEL)/k64fcpu.c -o k64fcpu
@echo ""
@echo "Build driver for host: $(MODEL)"
make -C $(KERNEL) ARCH=arm CROSS_COMPILE=$(CROSS) M="$(PWD)" modules
@echo ""
@echo "Build z80ctrl tool for host: $(MODEL)"
$(CROSS)gcc $(CTRLINC) $(MODEL)/z80ctrl.c -o z80ctrl
install:

View File

@@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Buildroot 2020.05-g1e61fe54a-dirty Configuration
# Buildroot 2020.05-00004-g652bdd81e-dirty Configuration
#
BR2_HAVE_DOT_CONFIG=y
BR2_HOST_GCC_AT_LEAST_4_9=y
@@ -2033,7 +2033,7 @@ BR2_PACKAGE_NCURSES_ADDITIONAL_TERMINFO=""
# BR2_PACKAGE_ONIGURUMA is not set
# BR2_PACKAGE_PCRE is not set
# BR2_PACKAGE_PCRE2 is not set
# BR2_PACKAGE_POPT is not set
BR2_PACKAGE_POPT=y
# BR2_PACKAGE_READLINE is not set
# BR2_PACKAGE_SLANG is not set
# BR2_PACKAGE_TCLAP is not set
@@ -2295,7 +2295,7 @@ BR2_PACKAGE_PPPD_OVERWRITE_RESOLV_CONF=y
# BR2_PACKAGE_RP_PPPOE is not set
# BR2_PACKAGE_RPCBIND is not set
# BR2_PACKAGE_RSH_REDONE is not set
# BR2_PACKAGE_RSYNC is not set
BR2_PACKAGE_RSYNC=y
# BR2_PACKAGE_RTORRENT is not set
# BR2_PACKAGE_RTPTOOLS is not set
# BR2_PACKAGE_RYGEL is not set