diff options
Diffstat (limited to 'src/devices/bus/isa/omti8621.cpp')
-rw-r--r-- | src/devices/bus/isa/omti8621.cpp | 1391 |
1 files changed, 1391 insertions, 0 deletions
diff --git a/src/devices/bus/isa/omti8621.cpp b/src/devices/bus/isa/omti8621.cpp new file mode 100644 index 00000000000..9f86243a90a --- /dev/null +++ b/src/devices/bus/isa/omti8621.cpp @@ -0,0 +1,1391 @@ +// license:BSD-3-Clause +// copyright-holders:Hans Ostermeyer, R. Belmont +/* + * omti8621.c - SMS OMTI 8621 disk controller (for Apollo DN3x00) + * + * Created on: August 30, 2010 + * Author: Hans Ostermeyer + * + * Converted to ISA device by R. Belmont + * + * see also: + * * http://www.bitsavers.org/pdf/sms/pc/OMTI_AT_Controller_Series_Jan87.pdf + */ + +#define VERBOSE 0 + +static int verbose = VERBOSE; + +#include "omti8621.h" +#include "image.h" +#include "formats/pc_dsk.h" +#include "formats/naslite_dsk.h" +#include "formats/apollo_dsk.h" + +#define LOG(x) { logerror ("%s: ", cpu_context(this)); logerror x; logerror ("\n"); } +#define LOG1(x) { if (verbose > 0) LOG(x)} +#define LOG2(x) { if (verbose > 1) LOG(x)} +#define LOG3(x) { if (verbose > 2) LOG(x)} + +#define OMTI_DISK_SECTOR_SIZE 1056 + +#define OMTI_DISK_TYPE_155_MB 0x607 // Micropolis 1355 (170 MB Dtype = 607) +#define OMTI_DISK_TYPE_348_MB 0x604 // Maxtor EXT-4380-E (380 MB Dtype = 604) +#define OMTI_DISK_TYPE_DEFAULT OMTI_DISK_TYPE_348_MB // new disks will have this type (and size) + +#define OMTI_MAX_BLOCK_COUNT 32 + +#define OMTI_DISK0_TAG "omti_disk0" +#define OMTI_DISK1_TAG "omti_disk1" + +#define OMTI_FDC_TAG "omti_fdc" + +#define OMTI_CPU_REGION "omti_cpu" +#define OMTI_BIOS_REGION "omti_bios" + +// forward declaration of image class +extern const device_type OMTI_DISK; + +class omti_disk_image_device : public device_t, + public device_image_interface +{ +public: + // construction/destruction + omti_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // image-level overrides + virtual iodevice_t image_type() const { return IO_HARDDISK; } + + virtual bool is_readable() const { return 1; } + virtual bool is_writeable() const { return 1; } + virtual bool is_creatable() const { return 1; } + virtual bool must_be_loaded() const { return 0; } + virtual bool is_reset_on_load() const { return 0; } + virtual const char *image_interface() const { return NULL; } + virtual const char *file_extensions() const { return "awd"; } + virtual const option_guide *create_option_guide() const { return NULL; } + + virtual bool call_create(int format_type, option_resolution *format_options); +protected: + // device-level overrides + virtual void device_config_complete(); + virtual void device_start(); + virtual void device_reset(); + + void omti_disk_config(UINT16 disk_type); +public: + UINT16 m_type; + UINT16 m_cylinders; + UINT16 m_heads; + UINT16 m_sectors; + UINT32 m_sectorbytes; + UINT32 m_sector_count; + + device_image_interface *m_image; + + // configuration data + UINT8 m_config_data[10]; + + // ESDI defect list data + UINT8 m_esdi_defect_list[256]; +}; + +/* + * I/O register offsets + */ + +#define OMTI_PORT_DATA_IN 0x00 /* read, 8-bit */ +#define OMTI_PORT_DATA_OUT 0x00 /* write, 8-bit */ +#define OMTI_PORT_STATUS 0x01 /* read, 8-bit */ +#define OMTI_PORT_RESET 0x01 /* write, 8-bit */ +#define OMTI_PORT_CONFIG 0x02 /* read, 8-bit */ +#define OMTI_PORT_SELECT 0x02 /* write, 8-bit */ +#define OMTI_PORT_MASK 0x03 /* write only, 8-bit */ + +// port status + +#define OMTI_STATUS_REQ 0x01 // Request (1 = request transfer of data via data in/out register) +#define OMTI_STATUS_IO 0x02 // In/Out (1 = direction of transfer is from controller to host) +#define OMTI_STATUS_CD 0x04 // Command/Data ( 1 = byte transfered is command or status byte) +#define OMTI_STATUS_BUSY 0x08 // Busy (0 = controller is idle, 1 = controller selected) +#define OMTI_STATUS_DREQ 0x10 // Data Request (0 = no DMA request, 1 = DMA cycle requested) +#define OMTI_STATUS_IREQ 0x20 // Interrupt Request (0 = no interrupt, 1 = command complete) +#define OMTI_STATUS_NU6 0x40 // not used +#define OMTI_STATUS_NU7 0x80 // not used + +#define OMTI_CONFIG_W23 0x01 // jumper W23 +#define OMTI_CONFIG_W22 0x02 // jumper W22 +#define OMTI_CONFIG_W21 0x04 // jumper W21 +#define OMTI_CONFIG_W20 0x08 // jumper W20 + +#define OMTI_MASK_DMAE 0x01 // DMA enable +#define OMTI_MASK_INTE 0x02 // Interrupt enable + +#define OMTI_COMMAND_STATUS_ERROR 0x02 // error bit +#define OMTI_COMMAND_STATUS_LUN 0x20 // drive 0 is 0 + +#define OMTI_SENSE_CODE_NO_ERROR 0x00 +#define OMTI_SENSE_CODE_DRIVE_NOT_READY 0x04 +#define OMTI_SENSE_CODE_ADDRESS_VALID 0x80 +#define OMTI_SENSE_CODE_SECTOR_NOT_FOUND 0x14 +#define OMTI_SENSE_CODE_ECC_ERROR 0x11 +#define OMTI_SENSE_CODE_BAD_TRACK 0x19 +#define OMTI_SENSE_CODE_ALTERNATE_TRACK 0x1C +#define OMTI_SENSE_CODE_INVALID_COMMAND 0x20 +#define OMTI_SENSE_CODE_ILLEGAL_ADDRESS 0x21 + +enum { + OMTI_STATE_RESET, + OMTI_STATE_IDLE, + OMTI_STATE_SELECTION, + OMTI_STATE_COMMAND, + OMTI_STATE_DATA, + OMTI_STATE_STATUS +}; + +// OMTI commands + +#define OMTI_CMD_TEST_DRIVE_READY 0x00 +#define OMTI_CMD_RECALIBRATE 0x01 + +#define OMTI_CMD_REQUEST_SENSE 0x03 +#define OMTI_CMD_FORMAT_DRIVEUNIT 0x04 +#define OMTI_CMD_READ_VERIFY 0x05 +#define OMTI_CMD_FORMAT_TRACK 0x06 +#define OMTI_CMD_FORMAT_BAD_TRACK 0x07 +#define OMTI_CMD_READ 0x08 + +#define OMTI_CMD_WRITE 0x0a +#define OMTI_CMD_SEEK 0x0b + +#define OMTI_CMD_READ_SECTOR_BUFFER 0x0e +#define OMTI_CMD_WRITE_SECTOR_BUFFER 0x0f + +#define OMTI_CMD_ASSIGN_ALTERNATE_TRACK 0x11 + +#define OMTI_CMD_READ_DATA_TO_BUFFER 0x1e +#define OMTI_CMD_WRITE_DATA_FROM_BUFFER 0x1f +#define OMTI_CMD_COPY 0x20 + +#define OMTI_CMD_READ_ESDI_DEFECT_LIST 0x37 + +#define OMTI_CMD_RAM_DIAGNOSTICS 0xe0 +#define OMTI_CMD_CONTROLLER_INT_DIAGNOSTIC 0xe4 +#define OMTI_CMD_READ_LONG 0xe5 +#define OMTI_CMD_WRITE_LONG 0xe6 + +#define OMTI_CMD_READ_CONFIGURATION 0xec +#define OMTI_CMD_INVALID_COMMAND 0xff + +/*************************************************************************** + cpu_context - return a string describing the current CPU context + ***************************************************************************/ + +static const char *cpu_context(const device_t *device) { + static char statebuf[64]; /* string buffer containing state description */ + + device_t *cpu = device->machine().firstcpu; + + /* if we have an executing CPU, output data */ + if (cpu != NULL) { + osd_ticks_t t = osd_ticks(); + int s = t / osd_ticks_per_second(); + int ms = (t % osd_ticks_per_second()) / 1000; + + sprintf(statebuf, "%d.%03d %s pc=%08x - %s", s, ms, cpu->tag(), + cpu->safe_pcbase(), device->tag()); + } else { + strcpy(statebuf, "(no context)"); + } + return statebuf; +} + +static SLOT_INTERFACE_START( pc_hd_floppies ) + SLOT_INTERFACE( "525hd", FLOPPY_525_HD ) + SLOT_INTERFACE( "35hd", FLOPPY_35_HD ) + SLOT_INTERFACE( "525dd", FLOPPY_525_DD ) + SLOT_INTERFACE( "35dd", FLOPPY_35_DD ) +SLOT_INTERFACE_END + +MACHINE_CONFIG_FRAGMENT( omti_disk ) + MCFG_DEVICE_ADD(OMTI_DISK0_TAG, OMTI_DISK, 0) + MCFG_DEVICE_ADD(OMTI_DISK1_TAG, OMTI_DISK, 0) + + MCFG_PC_FDC_AT_ADD(OMTI_FDC_TAG) + MCFG_PC_FDC_INTRQ_CALLBACK(WRITELINE(omti8621_device, fdc_irq_w)) + MCFG_PC_FDC_DRQ_CALLBACK(WRITELINE(omti8621_device, fdc_drq_w)) + MCFG_FLOPPY_DRIVE_ADD(OMTI_FDC_TAG":0", pc_hd_floppies, "525hd", omti8621_device::floppy_formats) +// Apollo workstations never have more then 1 floppy drive +// MCFG_FLOPPY_DRIVE_ADD(OMTI_FDC_TAG":1", pc_hd_floppies, "525hd", omti8621_device::floppy_formats) +MACHINE_CONFIG_END + +FLOPPY_FORMATS_MEMBER( omti8621_device::floppy_formats ) + FLOPPY_APOLLO_FORMAT, + FLOPPY_PC_FORMAT, + FLOPPY_NASLITE_FORMAT +FLOPPY_FORMATS_END + +// this card has two EPROMs: a program for the on-board Z8 CPU, +// and a PC BIOS to make the card bootable on a PC. +// we have the Z8 program, we still need the PC BIOS. +ROM_START( omti8621 ) + ROM_REGION(0x4000, OMTI_CPU_REGION, 0) // disassembles fine as Z8 code + ROM_LOAD( "omti_8621_102640-b.bin", 0x000000, 0x004000, CRC(e6f20dbb) SHA1(cf1990ad72eac6b296485410f5fa3309a0d6d078) ) + +#if 1 + // OMTI 8621 boards for Apollo workstations never use a BIOS ROM + // They don't even have a socket for the BIOS ROM + ROM_REGION(0x1000, OMTI_BIOS_REGION, 0) + ROM_LOAD_OPTIONAL("omti_bios", 0x0000, 0x1000, NO_DUMP) +#endif +ROM_END + +static INPUT_PORTS_START( omti_port ) + PORT_START("IO_BASE") + PORT_DIPNAME( 0x07, 0x04, "ESDI I/O base") + PORT_DIPSETTING( 0x00, "0320h" ) + PORT_DIPSETTING( 0x01, "0324h" ) + PORT_DIPSETTING( 0x02, "0328h" ) + PORT_DIPSETTING( 0x03, "032Ch" ) + PORT_DIPSETTING( 0x04, "01A0h" ) + PORT_DIPSETTING( 0x05, "01A4h" ) + PORT_DIPSETTING( 0x06, "01A8h" ) + PORT_DIPSETTING( 0x07, "01ACh" ) + PORT_DIPNAME( 0x08, 0x00, "Floppy I/O base") + PORT_DIPSETTING( 0x00, "03F0h" ) + PORT_DIPSETTING( 0x01, "0370h" ) + + PORT_START("BIOS_OPTS") + PORT_DIPNAME( 0x01, 0x00, "BIOS control") + PORT_DIPSETTING( 0x00, "Disabled" ) + PORT_DIPSETTING( 0x01, "Enabled" ) + PORT_DIPNAME( 0x02, 0x00, "BIOS base") + PORT_DIPSETTING( 0x00, "C8000h" ) + PORT_DIPSETTING( 0x01, "CA000h" ) +INPUT_PORTS_END + +machine_config_constructor omti8621_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( omti_disk ); +} + +const rom_entry *omti8621_device::device_rom_region() const +{ + return ROM_NAME( omti8621 ); +} + +ioport_constructor omti8621_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( omti_port ); +} + +/*------------------------------------------------- + device start callback +-------------------------------------------------*/ + +void omti8621_device::device_start() +{ + LOG2(("device_start")); + + set_isa_device(); + + m_installed = false; + + sector_buffer.resize(OMTI_DISK_SECTOR_SIZE*OMTI_MAX_BLOCK_COUNT); + + m_timer = timer_alloc(0, NULL); + + our_disks[0] = subdevice<omti_disk_image_device>(OMTI_DISK0_TAG); + our_disks[1] = subdevice<omti_disk_image_device>(OMTI_DISK1_TAG); +} + +/*------------------------------------------------- + device reset callback +-------------------------------------------------*/ + +void omti8621_device::device_reset() +{ + static const int io_bases[8] = { 0x320, 0x324, 0x328, 0x32c, 0x1a0, 0x1a4, 0x1a8, 0x1ac }; + + LOG2(("device_reset")); + + // you can't read I/O ports in device_start() even if they're required_ioport<> in your class! + if (!m_installed) + { + int esdi_base = io_bases[m_iobase->read() & 7]; + + // install the ESDI ports + m_isa->install16_device(esdi_base, esdi_base + 7, 0, 0, read16_delegate(FUNC(omti8621_device::read), this), write16_delegate(FUNC(omti8621_device::write), this)); + + // and the onboard AT FDC ports + if (m_iobase->read() & 8) + { + m_isa->install_device(0x0370, 0x0377, *m_fdc, &pc_fdc_interface::map); + } + else + { + m_isa->install_device(0x03f0, 0x03f7, *m_fdc, &pc_fdc_interface::map); + } + + m_isa->set_dma_channel(2, this, TRUE); + + m_installed = true; + } + + set_jumper(our_disks[0]->m_type); + + // should go from reset to idle after 100 us + // state->omti_state = OMTI_STATE_RESET; + omti_state = OMTI_STATE_IDLE; + + status_port = OMTI_STATUS_NU6 | OMTI_STATUS_NU7; + config_port = ~jumper; + mask_port = 0; + + // default the sector data buffer with model and status information + // (i.e. set sector data buffer for cmd=0x0e READ SECTOR BUFFER) + + memset(§or_buffer[0], 0, OMTI_DISK_SECTOR_SIZE); + memcpy(§or_buffer[0], "8621VB.4060487xx", 0x10); + sector_buffer[0x10] = 0; // ROM Checksum error + sector_buffer[0x11] = 0; // Processor Register error + sector_buffer[0x12] = 0; // Buffer RAM error + sector_buffer[0x13] = 0; // Sequencer Register File error + sector_buffer[0x14] = 0xc0; // 32K buffer size + // TODO: add missing Default values for LUN 0, 1 and 3 + + command_length = 0; + command_index = 0; + command_status = 0; + + data_index = 0; + data_length = 0; + + clear_sense_data(); + + diskaddr_ecc_error = 0; + diskaddr_format_bad_track = 0; + alternate_track_address[0] = 0; + alternate_track_address[1] = 0; +} + +const device_type ISA16_OMTI8621 = &device_creator<omti8621_device>; + +omti8621_device::omti8621_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, ISA16_OMTI8621, "OMTI 8621 ESDI/floppy controller", tag, owner, clock, "omti8621", __FILE__), + device_isa16_card_interface(mconfig, *this), + m_fdc(*this, OMTI_FDC_TAG), + m_iobase(*this, "IO_BASE"), + m_biosopts(*this, "BIOS_OPTS") +{ +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void omti8621_device::device_config_complete() +{ +} + +/*------------------------------------------------- + set_interrupt - update the IRQ state + -------------------------------------------------*/ + +void omti8621_device::set_interrupt(enum line_state line_state) +{ + LOG2(("set_interrupt: status_port=%x, line_state %d", status_port, line_state)); + m_isa->irq14_w(line_state); +} + +void omti8621_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + set_interrupt(ASSERT_LINE); +} + +/*************************************************************************** + clear_sense_data - clear the sense data + ***************************************************************************/ + +void omti8621_device::clear_sense_data() { + LOG2(("clear_sense_data")); + memset(sense_data, 0, sizeof(sense_data)); +} + +/*************************************************************************** + set_sense_data - set the sense data from code and command descriptor block + ***************************************************************************/ + +void omti8621_device::set_sense_data(UINT8 code, const UINT8 * cdb) { + LOG2(("set_sense_data code=%x", code)); + sense_data[0]=code; + sense_data[1]=cdb[1]; + sense_data[2]=cdb[2]; + sense_data[3]=cdb[3]; +} + +/*************************************************************************** + set_configuration_data - set the configuration data for drive lun + ***************************************************************************/ + +void omti8621_device::set_configuration_data(UINT8 lun) { + LOG2(("set_configuration_data lun=%x", lun)); + + // initialize the configuration data + omti_disk_image_device *disk = our_disks[lun]; + + disk->m_config_data[0] = (disk->m_cylinders - 1) >> 8; // Number of Cylinders (MSB) + disk->m_config_data[1] = (disk->m_cylinders - 1) & 0xff; // Number of Cylinders (LSB) (-1) + disk->m_config_data[2] = disk->m_heads - 1; // Number of Heads (-1) + disk->m_config_data[3] = disk->m_sectors - 1; // Number of Sectors (-1) + disk->m_config_data[4] = 0x02; // Drive Configuration Word (MSB) + disk->m_config_data[5] = 0x44; // Drive Configuration Word (LSB) + disk->m_config_data[6] = 0x00; // ISG AFTER INDEX + disk->m_config_data[7] = 0x00; // PLO SYN Field (ID) + disk->m_config_data[8] = 0x00; // PLO SYN Field (DATA) + disk->m_config_data[9] = 0x00; // ISG AFTER SECTOR +} + +/*************************************************************************** + get_lun - get logical unit number from a command descriptor block (in bit 5) + ***************************************************************************/ + +UINT8 omti8621_device::get_lun(const UINT8 * cdb) +{ + return (cdb[1] & 0x20) >> 5; +} + +/*************************************************************************** + check_disk_address - check disk address, set sense data and return true for no error + ***************************************************************************/ + +UINT8 omti8621_device::check_disk_address(const UINT8 *cdb) +{ + UINT8 sense_code = OMTI_SENSE_CODE_NO_ERROR; + UINT8 lun = get_lun(cdb); + UINT16 head = cdb[1] & 0x1f; + UINT16 sector = cdb[2] & 0x3f; + UINT32 cylinder = cdb[3] + ((cdb[2] & 0xc0) << 2) + ((cdb[1] & 0x80) << 3); + UINT8 block_count = cdb[4]; + omti_disk_image_device *disk = our_disks[lun]; + + UINT32 disk_track = cylinder * disk->m_heads + head; + UINT32 disk_addr = (disk_track * disk->m_sectors) + sector; + + if (block_count > OMTI_MAX_BLOCK_COUNT) { + LOG(("########### check_disk_address: unexpected block count %x", block_count)); + sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID; + } + + if (lun > OMTI_MAX_LUN) { + sense_code = OMTI_SENSE_CODE_DRIVE_NOT_READY; + } else if (!disk->m_image->exists()) { + sense_code = OMTI_SENSE_CODE_DRIVE_NOT_READY; + } else if (sector >= OMTI_MAX_BLOCK_COUNT) { + sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID; + } else if (head >= disk->m_heads) { + sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID; + } else if (cylinder >= disk->m_cylinders) { + sense_code = OMTI_SENSE_CODE_ILLEGAL_ADDRESS | OMTI_SENSE_CODE_ADDRESS_VALID; + } else if ( disk_track == diskaddr_format_bad_track && disk_track != 0) { + sense_code = OMTI_SENSE_CODE_BAD_TRACK; + } else if (disk_addr == diskaddr_ecc_error && disk_addr != 0) { + sense_code = OMTI_SENSE_CODE_ECC_ERROR; + } else if (disk_track == alternate_track_address[1] && disk_track != 0) { + sense_code = OMTI_SENSE_CODE_ALTERNATE_TRACK; + } + + if (sense_code == OMTI_SENSE_CODE_NO_ERROR) { + clear_sense_data(); + } else { + command_status |= OMTI_COMMAND_STATUS_ERROR; + set_sense_data(sense_code, cdb); + } + return sense_code == OMTI_SENSE_CODE_NO_ERROR; +} + +/*************************************************************************** + get_disk_track - get disk track from a command descriptor block + ***************************************************************************/ + +UINT32 omti8621_device::get_disk_track(const UINT8 * cdb) { + UINT8 lun = get_lun(cdb); + UINT16 head = cdb[1] & 0x1f; + UINT32 cylinder = cdb[3] + ((cdb[2] & 0xc0) << 2) + ((cdb[1] & 0x80) << 3); + return cylinder * our_disks[lun]->m_heads + head; +} + +/*************************************************************************** + get_disk_address - get disk address from a command descriptor block + ***************************************************************************/ + +UINT32 omti8621_device::get_disk_address(const UINT8 * cdb) { + UINT8 lun = get_lun(cdb); + UINT16 sector = cdb[2] & 0x3f; + return get_disk_track(cdb) * our_disks[lun]->m_sectors + sector; +} + +/*************************************************************************** + set_data_transfer - setup for data transfer from/to data + ***************************************************************************/ + +void omti8621_device::set_data_transfer(UINT8 *data, UINT16 length) +{ + // set controller for read data transfer + omti_state = OMTI_STATE_DATA; + status_port |= OMTI_STATUS_REQ | OMTI_STATUS_IO | OMTI_STATUS_BUSY; + status_port &= ~OMTI_STATUS_CD; + + data_buffer = data; + data_length = length; + data_index = 0; +} + +/*************************************************************************** + read_sectors_from_disk - read sectors starting at diskaddr into sector_buffer + ***************************************************************************/ + +void omti8621_device::read_sectors_from_disk(INT32 diskaddr, UINT8 count, UINT8 lun) +{ + UINT8 *data_buffer = §or_buffer[0]; + device_image_interface *image = our_disks[lun]->m_image; + + while (count-- > 0) { + LOG2(("read_sectors_from_disk lun=%d diskaddr=%x", lun, diskaddr)); + + image->fseek( diskaddr * OMTI_DISK_SECTOR_SIZE, SEEK_SET); + image->fread( data_buffer, OMTI_DISK_SECTOR_SIZE); + + diskaddr++; + data_buffer += OMTI_DISK_SECTOR_SIZE; + } +} + +/*************************************************************************** + write_sectors_to_disk - write sectors starting at diskaddr from sector_buffer + ***************************************************************************/ + +void omti8621_device::write_sectors_to_disk(INT32 diskaddr, UINT8 count, UINT8 lun) +{ + UINT8 *data_buffer = §or_buffer[0]; + device_image_interface *image = our_disks[lun]->m_image; + + while (count-- > 0) { + LOG2(("write_sectors_to_disk lun=%d diskaddr=%x", lun, diskaddr)); + + image->fseek( diskaddr * OMTI_DISK_SECTOR_SIZE, SEEK_SET); + image->fwrite( data_buffer, OMTI_DISK_SECTOR_SIZE); + + if (diskaddr == diskaddr_ecc_error) { + // reset previous ECC error + diskaddr_ecc_error = 0; + } + + diskaddr++; + data_buffer += OMTI_DISK_SECTOR_SIZE; + } +} + +/*************************************************************************** + copy_sectors - copy sectors + ***************************************************************************/ + +void omti8621_device::copy_sectors(INT32 dst_addr, INT32 src_addr, UINT8 count, UINT8 lun) +{ + device_image_interface *image = our_disks[lun]->m_image; + + LOG2(("copy_sectors lun=%d src_addr=%x dst_addr=%x count=%x", lun, src_addr, dst_addr, count)); + + while (count-- > 0) { + image->fseek( src_addr * OMTI_DISK_SECTOR_SIZE, SEEK_SET); + image->fread( §or_buffer[0], OMTI_DISK_SECTOR_SIZE); + + image->fseek( dst_addr * OMTI_DISK_SECTOR_SIZE, SEEK_SET); + image->fwrite( §or_buffer[0], OMTI_DISK_SECTOR_SIZE); + + if (dst_addr == diskaddr_ecc_error) { + // reset previous ECC error + diskaddr_ecc_error = 0; + } + + src_addr++; + dst_addr++; + } +} + +/*************************************************************************** + format track - format a track + ***************************************************************************/ + +void omti8621_device::format_track(const UINT8 * cdb) +{ + UINT8 lun = get_lun(cdb); + UINT32 disk_addr = get_disk_address(cdb); + UINT32 disk_track = get_disk_track(cdb); + + if (diskaddr_ecc_error == disk_addr) { + // reset previous ECC error + diskaddr_ecc_error = 0; + } + + if (diskaddr_format_bad_track == disk_track) { + // reset previous bad track formatting + diskaddr_format_bad_track = 0; + } + + if (alternate_track_address[0] == disk_track) { + // reset source of alternate track address + alternate_track_address[0] = 0; + } + + if (alternate_track_address[1] == disk_track) { + // reset alternate track address + alternate_track_address[1] = 0; + } + + if (check_disk_address(cdb) ) { + if ((cdb[5] & 0x40) == 0) { + memset(§or_buffer[0], 0x6C, OMTI_DISK_SECTOR_SIZE * our_disks[lun]->m_sectors); + } + write_sectors_to_disk(disk_addr, our_disks[lun]->m_sectors, lun); + } + +} + +/*************************************************************************** + set_esdi_defect_list - setup the (emty) ESDI defect list + ***************************************************************************/ + +void omti8621_device::set_esdi_defect_list(UINT8 lun, UINT8 head) +{ + omti_disk_image_device *disk = our_disks[lun]; + + memset(disk->m_esdi_defect_list, 0, sizeof(disk->m_esdi_defect_list)); + disk->m_esdi_defect_list[0] = 1; // month + disk->m_esdi_defect_list[1] = 1; // day + disk->m_esdi_defect_list[2] = 90; // year + disk->m_esdi_defect_list[3] = head; + memset(disk->m_esdi_defect_list+6, 0xff, 5); // end of defect list +} + +/*************************************************************************** + log_command - log command from a command descriptor block + ***************************************************************************/ + +void omti8621_device::log_command(const UINT8 cdb[], const UINT16 cdb_length) +{ + if (verbose > 0) { + int i; + logerror("%s: OMTI command ", cpu_context(this)); + switch (cdb[0]) { + case OMTI_CMD_TEST_DRIVE_READY: // 0x00 + logerror("Test Drive Ready"); + break; + case OMTI_CMD_RECALIBRATE: // 0x01 + logerror("Recalibrate"); + break; + case OMTI_CMD_REQUEST_SENSE: // 0x03 + logerror("Request Sense"); + break; + case OMTI_CMD_READ_VERIFY: // 0x05 + logerror("Read Verify"); + break; + case OMTI_CMD_FORMAT_TRACK: // 0x06 + logerror("Format Track"); + break; + case OMTI_CMD_FORMAT_BAD_TRACK: // 0x07 + logerror("Format Bad Track"); + break; + case OMTI_CMD_READ: // 0x08 + logerror("Read"); + break; + case OMTI_CMD_WRITE: // 0x0A + logerror("Write"); + break; + case OMTI_CMD_SEEK: // 0x0B + logerror("Seek"); + break; + case OMTI_CMD_READ_SECTOR_BUFFER: // 0x0E + logerror("Read Sector Buffer"); + break; + case OMTI_CMD_WRITE_SECTOR_BUFFER: // 0x0F + logerror("Write Sector Buffer"); + break; + case OMTI_CMD_ASSIGN_ALTERNATE_TRACK: // 0x11 + logerror("Assign Alternate Track"); + break; + case OMTI_CMD_READ_DATA_TO_BUFFER: // 0x1E + logerror("Read Data to Buffer"); + break; + case OMTI_CMD_WRITE_DATA_FROM_BUFFER: // 0x1F + logerror("Write Data from Buffer"); + break; + case OMTI_CMD_COPY: // 0x20 + logerror("Copy"); + break; + case OMTI_CMD_READ_ESDI_DEFECT_LIST: // 0x37 + logerror("Read ESDI Defect List"); + break; + case OMTI_CMD_RAM_DIAGNOSTICS: // 0xE0 + logerror("RAM. Diagnostic"); + break; + case OMTI_CMD_CONTROLLER_INT_DIAGNOSTIC: // 0xE4 + logerror("Controller Int. Diagnostic"); + break; + case OMTI_CMD_READ_LONG: // 0xE5 + logerror("Read Long"); + break; + case OMTI_CMD_WRITE_LONG: // 0xE6 + logerror("Write Long"); + break; + case OMTI_CMD_READ_CONFIGURATION: // 0xEC + logerror("Read Configuration"); + break; + case OMTI_CMD_INVALID_COMMAND: // 0xFF + logerror("Invalid Command"); + break; + default: + logerror("!!! Unexpected Command !!!"); + } +// logerror(" (%02x, length=%02x)", cdb[0], cdb_length); + for (i = 0; i < cdb_length; i++) { + logerror(" %02x", cdb[i]); + } + + switch (cdb[0]) { + case OMTI_CMD_READ_VERIFY: // 0x05 + case OMTI_CMD_READ: // 0x08 + case OMTI_CMD_WRITE: // 0x0a + case OMTI_CMD_SEEK: // 0x0b + case OMTI_CMD_READ_DATA_TO_BUFFER: // 0x1E + case OMTI_CMD_WRITE_DATA_FROM_BUFFER: // 0x1F + case OMTI_CMD_COPY: // 0x20 + logerror(" (diskaddr=%x count=%x)", get_disk_address(cdb), cdb[4]); + break; + } + logerror("\n"); + } +} + +/*************************************************************************** + log_data - log data in the common data buffer + ***************************************************************************/ + +void omti8621_device::log_data() +{ + if (verbose > 0) { + int i; + logerror("%s: OMTI data (length=%02x)", cpu_context(this), + data_length); + for (i = 0; i < data_length && i < OMTI_DISK_SECTOR_SIZE; i++) { + logerror(" %02x", data_buffer[i]); + } + + if (i < data_length) { + logerror(" ..."); + } + logerror("\n"); + } +} + +/*************************************************************************** + do_command + ***************************************************************************/ + +void omti8621_device::do_command(const UINT8 cdb[], const UINT16 cdb_length) +{ + UINT8 lun = get_lun(cdb); + omti_disk_image_device *disk = our_disks[lun]; + int command_duration = 0; // ms + + log_command( cdb, cdb_length); + + // default to read status and status is successful completion + omti_state = OMTI_STATE_STATUS; + status_port |= OMTI_STATUS_IO | OMTI_STATUS_CD; + command_status = lun ? OMTI_COMMAND_STATUS_LUN : 0; + + if (mask_port & OMTI_MASK_INTE) { + set_interrupt(CLEAR_LINE); + } + + if (!disk->m_image->exists()) { + command_status |= OMTI_COMMAND_STATUS_ERROR; // no such drive + } + + switch (cdb[0]) { + case OMTI_CMD_TEST_DRIVE_READY: // 0x00 + if (!disk->m_image->exists()) + { + set_sense_data(OMTI_SENSE_CODE_DRIVE_NOT_READY, cdb); + } + break; + + case OMTI_CMD_RECALIBRATE: // 0x01 + break; + + case OMTI_CMD_REQUEST_SENSE: // 0x03 + set_data_transfer(sense_data, sizeof(sense_data)); + break; + + case OMTI_CMD_READ_VERIFY: // 0x05 + check_disk_address(cdb); + break; + + case OMTI_CMD_FORMAT_TRACK: // 0x06 + format_track(cdb); + break; + + case OMTI_CMD_FORMAT_BAD_TRACK: // 0x07 + diskaddr_format_bad_track = get_disk_address(cdb); + break; + + case OMTI_CMD_READ: // 0x08 + if (check_disk_address(cdb)) { + // read data from controller + read_sectors_from_disk(get_disk_address(cdb), cdb[4], lun); + set_data_transfer(§or_buffer[0], OMTI_DISK_SECTOR_SIZE*cdb[4]); + } + break; + + case OMTI_CMD_WRITE: // 0x0A + log_data(); + if (check_disk_address(cdb)) { + write_sectors_to_disk(get_disk_address(cdb), cdb[4], lun); + } + break; + + case OMTI_CMD_SEEK: // 0x0B + check_disk_address(cdb); + break; + + case OMTI_CMD_READ_SECTOR_BUFFER: // 0x0E + set_data_transfer(§or_buffer[0], OMTI_DISK_SECTOR_SIZE*cdb[4]); + break; + + case OMTI_CMD_WRITE_SECTOR_BUFFER: // 0x0F + log_data(); + break; + + case OMTI_CMD_COPY: // 0x20 + if (check_disk_address(cdb) && check_disk_address(cdb+4)) { + // copy sectors + copy_sectors (get_disk_address(cdb+4), get_disk_address(cdb), cdb[4], lun); + } + break; + + case OMTI_CMD_READ_ESDI_DEFECT_LIST: // 0x37 + set_esdi_defect_list(get_lun(cdb), cdb[1] & 0x1f); + set_data_transfer(disk->m_esdi_defect_list, sizeof(disk->m_esdi_defect_list)); + break; + +#if 0 // this command seems unused by Domain/OS, and it's unclear what the intent of the code is (it makes some versions of GCC quite unhappy) + case OMTI_CMD_ASSIGN_ALTERNATE_TRACK: // 0x11 + log_data(); + alternate_track_address[0] = get_disk_track(cdb); + alternate_track_address[1] = get_disk_track(alternate_track_buffer-1); + break; +#endif + + case OMTI_CMD_READ_DATA_TO_BUFFER: // 0x1E + if (check_disk_address(cdb)) { + // read data from controller + read_sectors_from_disk (get_disk_address(cdb), cdb[4], lun); + // Domain/OS doesn't expect zero access time + command_duration += 1; // 1 ms is enough, average time would be 30 ms) + } + break; + + case OMTI_CMD_WRITE_DATA_FROM_BUFFER: // 0x1F + log_data(); + if (check_disk_address(cdb)) { + write_sectors_to_disk(get_disk_address(cdb), cdb[4], lun); + } + break; + + case OMTI_CMD_RAM_DIAGNOSTICS: // 0xE0 + break; + + case OMTI_CMD_CONTROLLER_INT_DIAGNOSTIC: // 0xE4 + break; + + case OMTI_CMD_READ_LONG: // 0xE5 + if (check_disk_address(cdb)) { + // read data from controller + read_sectors_from_disk(get_disk_address(cdb), cdb[4], lun); + set_data_transfer(§or_buffer[0], OMTI_DISK_SECTOR_SIZE+6); + } + break; + + case OMTI_CMD_WRITE_LONG: // 0xE6 + log_data(); + if (check_disk_address(cdb)) { + UINT32 diskaddr = get_disk_address(cdb); + write_sectors_to_disk(diskaddr, cdb[4], lun); + // this will spoil the ECC code + diskaddr_ecc_error = diskaddr; + } + break; + + case OMTI_CMD_READ_CONFIGURATION: // 0xEC + set_configuration_data(get_lun(cdb)); + set_data_transfer(disk->m_config_data, sizeof(disk->m_config_data)); + break; + + case OMTI_CMD_INVALID_COMMAND: // 0xFF + set_sense_data(OMTI_SENSE_CODE_INVALID_COMMAND, cdb); + command_status |= OMTI_COMMAND_STATUS_ERROR; + break; + + default: + LOG(("do_command: UNEXPECTED command %02x",cdb[0])); + set_sense_data(OMTI_SENSE_CODE_INVALID_COMMAND, cdb); + command_status |= OMTI_COMMAND_STATUS_ERROR; + break; + } + + if (mask_port & OMTI_MASK_INTE) { +// if (omti_state != OMTI_STATE_STATUS) { +// LOG(("do_command: UNEXPECTED omti_state %02x",omti_state)); +// } + status_port |= OMTI_STATUS_IREQ; + if (command_duration == 0) + { + set_interrupt(ASSERT_LINE); + } + else + { + // FIXME: should delay omti_state and status_port as well + m_timer->adjust(attotime::from_msec(command_duration), 0); + } + } +} + +/*************************************************************************** + get_command_length + ***************************************************************************/ + +UINT8 omti8621_device::get_command_length(UINT8 command_byte) +{ + return command_byte == OMTI_CMD_COPY ? 10 : 6; +} + +/*************************************************************************** + get_data + ***************************************************************************/ + +UINT16 omti8621_device::get_data() +{ + UINT16 data = 0xff; + if (data_index < data_length) { + data = data_buffer[data_index++]; + data |= data_buffer[data_index++] << 8; + if (data_index >= data_length) { + omti_state = OMTI_STATE_STATUS; + status_port |= OMTI_STATUS_IO | OMTI_STATUS_CD; + log_data(); + } + } else { + LOG(("UNEXPECTED reading OMTI 8621 data (buffer length exceeded)")); + } + return data; +} + +/*************************************************************************** + set_data + ***************************************************************************/ + +void omti8621_device::set_data(UINT16 data) +{ + if (data_index < data_length) { + data_buffer[data_index++] = data & 0xff; + data_buffer[data_index++] = data >> 8; + if (data_index >= data_length) { + do_command(command_buffer, command_index); + } + } else { + LOG(("UNEXPECTED writing OMTI 8621 data (buffer length exceeded)")); + } +} + +/*************************************************************************** + OMTI8621 Disk Controller-AT Registers +***************************************************************************/ + +WRITE16_MEMBER(omti8621_device::write) +{ + switch (mem_mask) + { + case 0x00ff: + write8(space, offset*2, data, mem_mask); + break; + + case 0xff00: + write8(space, offset*2+1, data>>8, mem_mask>>8); + break; + + default: + set_data(data); + break; + } +} + +WRITE8_MEMBER(omti8621_device::write8) +{ + switch (offset) + { + case OMTI_PORT_DATA_OUT: // 0x00 + switch (omti_state) { + case OMTI_STATE_COMMAND: + LOG2(("writing OMTI 8621 Command Register at offset %02x = %02x", offset, data)); + if (command_index == 0) { + command_length = get_command_length(data); + } + + if (command_index < command_length) { + command_buffer[command_index++] = data; + } else { + LOG(("UNEXPECTED writing OMTI 8621 Data Register at offset %02x = %02x (command length exceeded)", offset, data)); + } + + if (command_index == command_length) { + switch (command_buffer[0]) { + case OMTI_CMD_WRITE: // 0x0A + // TODO: check diskaddr + // Fall through + case OMTI_CMD_WRITE_SECTOR_BUFFER: // 0x0F + set_data_transfer(§or_buffer[0], + OMTI_DISK_SECTOR_SIZE * command_buffer[4]); + status_port &= ~OMTI_STATUS_IO; + break; + + case OMTI_CMD_ASSIGN_ALTERNATE_TRACK: // 0x11 + set_data_transfer(alternate_track_buffer, sizeof(alternate_track_buffer)); + status_port &= ~OMTI_STATUS_IO; + break; + + case OMTI_CMD_WRITE_LONG: // 0xE6 + // TODO: check diskaddr + set_data_transfer(§or_buffer[0], + (OMTI_DISK_SECTOR_SIZE +6) * command_buffer[4]); + status_port &= ~OMTI_STATUS_IO; + break; + + default: + do_command(command_buffer, command_index); + break; + } + } + break; + + case OMTI_STATE_DATA: + LOG(("UNEXPECTED: writing OMTI 8621 Data Register at offset %02x = %02x", offset, data)); + break; + + default: + LOG(("UNEXPECTED writing OMTI 8621 Data Register at offset %02x = %02x (omti state = %02x)", offset, data, omti_state)); + break; + } + break; + + case OMTI_PORT_RESET: // 0x01 + LOG2(("writing OMTI 8621 Reset Register at offset %02x = %02x", offset, data)); + device_reset(); + break; + + case OMTI_PORT_SELECT: // 0x02 + LOG2(("writing OMTI 8621 Select Register at offset %02x = %02x (omti state = %02x)", offset, data, omti_state)); + omti_state = OMTI_STATE_COMMAND; + + status_port |= OMTI_STATUS_BUSY | OMTI_STATUS_REQ | OMTI_STATUS_CD; + status_port &= ~OMTI_STATUS_IO; + + command_status = 0; + command_index = 0; + break; + + case OMTI_PORT_MASK: // 0x03 + LOG2(("writing OMTI 8621 Mask Register at offset %02x = %02x", offset, data)); + mask_port = data; + + if ((data & OMTI_MASK_INTE) == 0) { + status_port &= ~OMTI_STATUS_IREQ; + set_interrupt(CLEAR_LINE); + } + + if ((data & OMTI_MASK_DMAE) == 0) { + status_port &= ~OMTI_STATUS_DREQ; + } + break; + + default: + LOG(("UNEXPECTED writing OMTI 8621 Register at offset %02x = %02x", offset, data)); + break; + } +} + +READ16_MEMBER(omti8621_device::read) +{ + switch (mem_mask) + { + case 0x00ff: + return read8(space, offset*2, mem_mask); + case 0xff00: + return read8(space, offset*2+1, mem_mask >> 8) << 8; + default: + return get_data(); + } +} + +READ8_MEMBER(omti8621_device::read8) +{ + UINT8 data = 0xff; + static UINT8 last_data = 0xff; + + switch (offset) { + case OMTI_PORT_DATA_IN: // 0x00 + if (status_port & OMTI_STATUS_CD) + { + data = command_status; + switch (omti_state) + { + case OMTI_STATE_COMMAND: + LOG2(("reading OMTI 8621 Data Status Register 1 at offset %02x = %02x (omti state = %02x)", offset, data, omti_state)); + break; + case OMTI_STATE_STATUS: + omti_state = OMTI_STATE_IDLE; + status_port &= ~(OMTI_STATUS_BUSY | OMTI_STATUS_CD | OMTI_STATUS_IO | OMTI_STATUS_REQ); + LOG2(("reading OMTI 8621 Data Status Register 2 at offset %02x = %02x", offset, data)); + break; + default: + LOG(("UNEXPECTED reading OMTI 8621 Data Status Register 3 at offset %02x = %02x (omti state = %02x)", offset, data, omti_state)); + break; + } + } + else + { + LOG(("UNEXPECTED reading OMTI 8621 Data Register 4 at offset %02x = %02x (status bit C/D = 0)", offset, data)); + } + break; + + case OMTI_PORT_STATUS: // 0x01 + data = status_port; + // omit excessive logging + if (data != last_data) + { + LOG2(("reading OMTI 8621 Status Register 5 at offset %02x = %02x", offset, data)); +// last_data = data; + } + break; + + case OMTI_PORT_CONFIG: // 0x02 + data = config_port; + LOG2(("reading OMTI 8621 Configuration Register at offset %02x = %02x", offset, data)); + break; + + case OMTI_PORT_MASK: // 0x03 + data = mask_port ; + // win.dex will update the mask register with read-modify-write + // LOG2(("reading OMTI 8621 Mask Register at offset %02x = %02x (UNEXPECTED!)", offset, data)); + break; + + default: + LOG(("UNEXPECTED reading OMTI 8621 Register at offset %02x = %02x", offset, data)); + break; + } + + return data; +} + +void omti8621_device::set_verbose(int on_off) +{ + verbose = on_off == 0 ? 0 : VERBOSE > 1 ? VERBOSE : 1; +} + +/*************************************************************************** + get_sector - get sector diskaddr of logical unit lun into data_buffer + ***************************************************************************/ + +// FIXME: this will work, but is not supported by MESS +#if 0 // APOLLO_XXL +UINT32 omti8621_device::get_sector(INT32 diskaddr, UINT8 *data_buffer, UINT32 length, UINT8 lun) +{ + omti_disk_image_device *disk = omti8621_device_1->our_disks[lun]; + + if (disk == NULL || disk->m_image == NULL || !disk->m_image->exists()) + { + return 0; + } + else + { +// LOG1(("omti8621_get_sector %x on lun %d", diskaddr, lun)); + + // restrict length to size of 1 sector (i.e. 1024 Byte) + length = length < OMTI_DISK_SECTOR_SIZE ? length : OMTI_DISK_SECTOR_SIZE; + + disk->m_image->fseek(diskaddr * OMTI_DISK_SECTOR_SIZE, SEEK_SET); + disk->m_image->fread(data_buffer, length); + + return length; + } +} +#endif + +/*************************************************************************** + omti_set_jumper - set OMI jumpers + ***************************************************************************/ + +void omti8621_device::set_jumper(UINT16 disk_type) +{ + LOG1(("set_jumper: disk type=%x", disk_type)); + + switch (disk_type) + { + case OMTI_DISK_TYPE_348_MB: // Maxtor 380 MB (348-MB FA formatted) + jumper = OMTI_CONFIG_W22 | OMTI_CONFIG_W23; + break; + + case OMTI_DISK_TYPE_155_MB: // Micropolis 170 MB (155-MB formatted) + default: + jumper = OMTI_CONFIG_W20; + break; + } +} + +// FDC uses the standard IRQ 6 / DMA 2, doesn't appear to be configurable +WRITE_LINE_MEMBER( omti8621_device::fdc_irq_w ) +{ + m_isa->irq6_w(state ? ASSERT_LINE : CLEAR_LINE); +} + +WRITE_LINE_MEMBER( omti8621_device::fdc_drq_w ) +{ + m_isa->drq2_w(state ? ASSERT_LINE : CLEAR_LINE); +} + +UINT8 omti8621_device::dack_r(int line) +{ + return m_fdc->dma_r(); +} + +void omti8621_device::dack_w(int line, UINT8 data) +{ + return m_fdc->dma_w(data); +} + +void omti8621_device::eop_w(int state) +{ + m_fdc->tc_w(state == ASSERT_LINE); +} + +//########################################################################## + +// device type definition +const device_type OMTI_DISK = &device_creator<omti_disk_image_device>; + +omti_disk_image_device::omti_disk_image_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, OMTI_DISK, "OMTI8621 ESDI disk", tag, owner, clock, "omti_disk_image", __FILE__), + device_image_interface(mconfig, *this) +{ +} + +void omti_disk_image_device::device_config_complete() +{ + update_names(OMTI_DISK, "disk", "disk"); +} + + +/*************************************************************************** + omti_disk_config - configure disk parameters + ***************************************************************************/ + +void omti_disk_image_device::omti_disk_config(UINT16 disk_type) +{ + LOG1(("omti_disk_config: configuring disk with type %x", disk_type)); + + switch (disk_type) + { + case OMTI_DISK_TYPE_348_MB: // Maxtor 380 MB (348-MB FA formatted) + m_cylinders = 1223; + m_heads = 15; + m_sectors = 18; + break; + + case OMTI_DISK_TYPE_155_MB: // Micropolis 170 MB (155-MB formatted) + default: + m_cylinders = 1023; + m_heads = 8; + m_sectors = 18; + break; + } + + m_type = disk_type; + m_sectorbytes = OMTI_DISK_SECTOR_SIZE; + m_sector_count = m_cylinders * m_heads * m_sectors; +} + +/*------------------------------------------------- + device start callback +-------------------------------------------------*/ + +void omti_disk_image_device::device_start() +{ + m_image = this; + + if (m_image->image_core_file() == NULL) + { + LOG1(("device_start_omti_disk: no disk")); + } + else + { + LOG1(("device_start_omti_disk: with disk image %s",m_image->basename() )); + } + + // default disk type + omti_disk_config(OMTI_DISK_TYPE_DEFAULT); +} + +/*------------------------------------------------- + device reset callback +-------------------------------------------------*/ + +void omti_disk_image_device::device_reset() +{ + LOG1(("device_reset_omti_disk")); + + if (exists() && fseek(0, SEEK_END) == 0) + { + UINT32 disk_size = (UINT32)(ftell() / OMTI_DISK_SECTOR_SIZE); + UINT16 disk_type = disk_size >= 300000 ? OMTI_DISK_TYPE_348_MB : OMTI_DISK_TYPE_155_MB; + if (disk_type != m_type) { + LOG1(("device_reset_omti_disk: disk size=%d blocks, disk type=%x", disk_size, disk_type )); + omti_disk_config(disk_type); + } + } +} + +/*------------------------------------------------- + disk image create callback +-------------------------------------------------*/ + +bool omti_disk_image_device::call_create(int format_type, option_resolution *format_options) +{ + LOG(("device_create_omti_disk: creating OMTI Disk with %d blocks", m_sector_count)); + + int x; + unsigned char sectordata[OMTI_DISK_SECTOR_SIZE]; // empty block data + + + memset(sectordata, 0x55, sizeof(sectordata)); + for (x = 0; x < m_sector_count; x++) + { + if (fwrite(sectordata, OMTI_DISK_SECTOR_SIZE) + < OMTI_DISK_SECTOR_SIZE) + { + return IMAGE_INIT_FAIL; + } + } + return IMAGE_INIT_PASS; +} |