diff options
author | 2012-08-21 10:41:19 +0000 | |
---|---|---|
committer | 2012-08-21 10:41:19 +0000 | |
commit | 7285b359d259b2ae0fdf85096571c386ec8c991a (patch) | |
tree | a027aff57f1a255f9ec6cfd3b68cabe4b6683998 /src/mess/machine/coco_vhd.c | |
parent | 67c425e90757876a6716b7867df30c0149912e74 (diff) |
Merge of MESS sources (no whatsnew)
Diffstat (limited to 'src/mess/machine/coco_vhd.c')
-rw-r--r-- | src/mess/machine/coco_vhd.c | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/src/mess/machine/coco_vhd.c b/src/mess/machine/coco_vhd.c new file mode 100644 index 00000000000..fe4ade801b0 --- /dev/null +++ b/src/mess/machine/coco_vhd.c @@ -0,0 +1,280 @@ +/*************************************************************************** + + coco_vhd.c + + Color Computer Virtual Hard Drives + +**************************************************************************** + + Technical specs on the Virtual Hard Disk interface + + Address Description + ------- ----------- + FF80 Logical record number (high byte) + FF81 Logical record number (middle byte) + FF82 Logical record number (low byte) + FF83 Command/status register + FF84 Buffer address (high byte) + FF85 Buffer address (low byte) + + Set the other registers, and then issue a command to FF83 as follows: + + 0 = read 256-byte sector at LRN + 1 = write 256-byte sector at LRN + 2 = flush write cache (Closes and then opens the image file) + + Error values: + + 0 = no error + -1 = power-on state (before the first command is received) + -2 = invalid command + 2 = VHD image does not exist + 4 = Unable to open VHD image file + 5 = access denied (may not be able to write to VHD image) + + IMPORTANT: The I/O buffer must NOT cross an 8K MMU bank boundary. + + ***************************************************************************/ + +#include "emu.h" +#include "coco_vhd.h" +#include "includes/coco.h" +#include "machine/ram.h" + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define VERBOSE 1 + +#define VHDSTATUS_OK 0x00 +#define VHDSTATUS_NO_VHD_ATTACHED 0x02 +#define VHDSTATUS_ACCESS_DENIED 0x05 +#define VHDSTATUS_UNKNOWN_COMMAND 0xFE +#define VHDSTATUS_POWER_ON_STATE 0xFF + +#define VHDCMD_READ 0 +#define VHDCMD_WRITE 1 +#define VHDCMD_FLUSH 2 + + +/*************************************************************************** + CORE IMPLEMENTATION +***************************************************************************/ + +const device_type COCO_VHD = &device_creator<coco_vhd_image_device>; + +//------------------------------------------------- +// coco_vhd_image_device - constructor +//------------------------------------------------- + +coco_vhd_image_device::coco_vhd_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, COCO_VHD, "Virtual Hard Disk", tag, owner, clock), + device_image_interface(mconfig, *this) +{ + +} + +//------------------------------------------------- +// coco_vhd_image_device - destructor +//------------------------------------------------- + +coco_vhd_image_device::~coco_vhd_image_device() +{ +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void coco_vhd_image_device::device_config_complete() +{ + // set brief and instance name + update_names(); +} + + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void coco_vhd_image_device::device_start() +{ + m_status = VHDSTATUS_NO_VHD_ATTACHED; + m_cpu = machine().device<cpu_device>(MAINCPU_TAG); + m_cpu_space = m_cpu->space(AS_PROGRAM); +} + + + +//------------------------------------------------- +// call_load +//------------------------------------------------- + +bool coco_vhd_image_device::call_load() +{ + m_status = VHDSTATUS_POWER_ON_STATE; + m_logical_record_number = 0; + m_buffer_address = 0; + return IMAGE_INIT_PASS; +} + + + +//------------------------------------------------- +// coco_vhd_readwrite +//------------------------------------------------- + +void coco_vhd_image_device::coco_vhd_readwrite(UINT8 data) +{ + int result, i; + UINT32 bytes_to_read; + UINT32 bytes_to_write; + UINT64 seek_position; + UINT64 total_size; + char buffer[1024]; + + /* access the image */ + if (!exists()) + { + m_status = VHDSTATUS_NO_VHD_ATTACHED; + return; + } + + /* perform the seek */ + seek_position = ((UINT64) 256) * m_logical_record_number; + total_size = length(); + result = fseek(MIN(seek_position, total_size), SEEK_SET); + if (result < 0) + { + m_status = VHDSTATUS_ACCESS_DENIED; + return; + } + + /* expand the disk, if necessary */ + if (data == VHDCMD_WRITE) + { + while(total_size < seek_position) + { + memset(buffer, 0, sizeof(buffer)); + + bytes_to_write = (UINT32) MIN(seek_position - total_size, (UINT64) sizeof(buffer)); + result = fwrite(buffer, bytes_to_write); + if (result != bytes_to_write) + { + m_status = VHDSTATUS_ACCESS_DENIED; + return; + } + + total_size += bytes_to_write; + } + } + + switch(data) + { + case VHDCMD_READ: /* Read sector */ + memset(buffer, 0, 256); + if (total_size > seek_position) + { + bytes_to_read = (UINT32) MIN((UINT64) 256, total_size - seek_position); + result = fread(buffer, bytes_to_read); + if (result != bytes_to_read) + { + m_status = VHDSTATUS_ACCESS_DENIED; + return; + } + } + + /* write the bytes to memory */ + for (i = 0; i < 256; i++) + m_cpu_space->write_byte(m_buffer_address + i, buffer[i]); + + m_status = VHDSTATUS_OK; + break; + + case VHDCMD_WRITE: /* Write Sector */ + /* read the bytes from memory */ + for (i = 0; i < 256; i++) + buffer[i] = m_cpu_space->read_byte(m_buffer_address + i); + + /* and write to disk */ + result = fwrite(buffer, 256); + if (result != 256) + { + m_status = VHDSTATUS_ACCESS_DENIED; + return; + } + + m_status = VHDSTATUS_OK; + break; + + case VHDCMD_FLUSH: /* Flush file cache */ + m_status = VHDSTATUS_OK; + break; + + default: + m_status = VHDSTATUS_UNKNOWN_COMMAND; + break; + } +} + + + +UINT8 coco_vhd_image_device::read(offs_t offset) +{ + UINT8 result = 0; + + switch(offset) + { + case 0xff83 - 0xff80: + if (VERBOSE) + logerror("vhd: Status read: %d\n", m_status); + result = m_status; + break; + } + return result; +} + + + +void coco_vhd_image_device::write(offs_t offset, UINT8 data) +{ + int pos; + + switch(offset) + { + case 0xff80 - 0xff80: + case 0xff81 - 0xff80: + case 0xff82 - 0xff80: + pos = ((0xff82 - 0xff80) - offset) * 8; + m_logical_record_number &= ~(0xFF << pos); + m_logical_record_number += data << pos; + if (VERBOSE) + logerror("vhd: LRN write: %6.6X\n", m_logical_record_number); + break; + + case 0xff83 - 0xff80: + coco_vhd_readwrite(data); + if (VERBOSE) + logerror("vhd: Command: %d\n", data); + break; + + case 0xff84 - 0xff80: + m_buffer_address &= 0xFFFF00FF; + m_buffer_address += data << 8; + if (VERBOSE) + logerror("vhd: BA write: %X (%2.2X..)\n", m_buffer_address, data); + break; + + case 0xff85 - 0xff80: + m_buffer_address &= 0xFFFFFF00; + m_buffer_address += data; + if (VERBOSE) + logerror("vhd: BA write: %X (..%2.2X)\n", m_buffer_address, data); + break; + } +} |