diff --git a/src/emu/bus/ieee488/hardbox.c b/src/emu/bus/ieee488/hardbox.c index 6b799543c9b..5c4f9b19760 100644 --- a/src/emu/bus/ieee488/hardbox.c +++ b/src/emu/bus/ieee488/hardbox.c @@ -43,11 +43,6 @@ #include "hardbox.h" -#include "cpu/z80/z80.h" -#include "machine/i8251.h" -#include "machine/i8255.h" -#include "imagedev/harddriv.h" -#include "includes/corvushd.h" @@ -58,6 +53,7 @@ #define Z80_TAG "z80" #define I8255_0_TAG "ic17" #define I8255_1_TAG "ic16" +#define CORVUS_HDC_TAG "corvus" @@ -126,7 +122,7 @@ static ADDRESS_MAP_START( hardbox_io, AS_IO, 8, hardbox_device ) ADDRESS_MAP_GLOBAL_MASK(0xff) AM_RANGE(0x10, 0x13) AM_DEVREADWRITE(I8255_0_TAG, i8255_device, read, write) AM_RANGE(0x14, 0x17) AM_DEVREADWRITE(I8255_1_TAG, i8255_device, read, write) - AM_RANGE(0x18, 0x18) AM_READWRITE_LEGACY(corvus_hdc_data_r, corvus_hdc_data_w) + AM_RANGE(0x18, 0x18) AM_DEVREADWRITE(CORVUS_HDC_TAG, corvus_hdc_t, read, write) ADDRESS_MAP_END @@ -247,7 +243,7 @@ READ8_MEMBER( hardbox_device::ppi1_pc_r ) */ - UINT8 status = corvus_hdc_status_r(space, 0); + UINT8 status = m_hdc->status_r(space, 0); UINT8 data = 0; data |= (status & CONTROLLER_BUSY) ? 0 : 0x10; @@ -302,6 +298,8 @@ static MACHINE_CONFIG_FRAGMENT( hardbox ) // devices MCFG_I8255A_ADD(I8255_0_TAG, ppi0_intf) MCFG_I8255A_ADD(I8255_1_TAG, ppi1_intf) + + MCFG_DEVICE_ADD(CORVUS_HDC_TAG, CORVUS_HDC, 0) MCFG_HARDDISK_ADD("harddisk1") MCFG_HARDDISK_ADD("harddisk2") MCFG_HARDDISK_ADD("harddisk3") @@ -365,7 +363,8 @@ ioport_constructor hardbox_device::device_input_ports() const hardbox_device::hardbox_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, HARDBOX, "HardBox", tag, owner, clock, "hardbox", __FILE__), device_ieee488_interface(mconfig, *this), - m_maincpu(*this, Z80_TAG) + m_maincpu(*this, Z80_TAG), + m_hdc(*this, CORVUS_HDC_TAG) { } @@ -376,7 +375,6 @@ hardbox_device::hardbox_device(const machine_config &mconfig, const char *tag, d void hardbox_device::device_start() { - corvus_hdc_init(this); } diff --git a/src/emu/bus/ieee488/hardbox.h b/src/emu/bus/ieee488/hardbox.h index 4f705085ec0..4c798448632 100644 --- a/src/emu/bus/ieee488/hardbox.h +++ b/src/emu/bus/ieee488/hardbox.h @@ -15,6 +15,11 @@ #define __PET_HARDBOX__ #include "ieee488.h" +#include "cpu/z80/z80.h" +#include "machine/i8251.h" +#include "machine/i8255.h" +#include "imagedev/harddriv.h" +#include "includes/corvushd.h" @@ -62,6 +67,7 @@ private: }; required_device m_maincpu; + required_device m_hdc; int m_ifc; // Tracks previous state of IEEE-488 IFC line }; diff --git a/src/emu/bus/ieee488/softbox.c b/src/emu/bus/ieee488/softbox.c index f2d419e2e9a..d169022133c 100644 --- a/src/emu/bus/ieee488/softbox.c +++ b/src/emu/bus/ieee488/softbox.c @@ -18,12 +18,6 @@ #include "softbox.h" -#include "bus/rs232/rs232.h" -#include "cpu/z80/z80.h" -#include "imagedev/harddriv.h" -#include "includes/corvushd.h" -#include "machine/i8251.h" -#include "machine/i8255.h" //************************************************************************** @@ -36,6 +30,7 @@ #define I8255_1_TAG "ic16" #define COM8116_TAG "ic14" #define RS232_TAG "rs232" +#define CORVUS_HDC_TAG "corvus" @@ -93,7 +88,7 @@ static ADDRESS_MAP_START( softbox_io, AS_IO, 8, softbox_device ) AM_RANGE(0x0c, 0x0c) AM_WRITE(dbrg_w) AM_RANGE(0x10, 0x13) AM_DEVREADWRITE(I8255_0_TAG, i8255_device, read, write) AM_RANGE(0x14, 0x17) AM_DEVREADWRITE(I8255_1_TAG, i8255_device, read, write) - AM_RANGE(0x18, 0x18) AM_READWRITE_LEGACY(corvus_hdc_data_r, corvus_hdc_data_w) + AM_RANGE(0x18, 0x18) AM_DEVREADWRITE(CORVUS_HDC_TAG, corvus_hdc_t, read, write) ADDRESS_MAP_END @@ -202,7 +197,7 @@ READ8_MEMBER( softbox_device::ppi1_pc_r ) */ - UINT8 status = corvus_hdc_status_r(space, 0); + UINT8 status = m_hdc->status_r(space, 0); UINT8 data = 0; data |= (status & CONTROLLER_BUSY) ? 0 : 0x10; @@ -282,6 +277,7 @@ static MACHINE_CONFIG_FRAGMENT( softbox ) MCFG_COM8116_FR_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_rxc)) MCFG_COM8116_FT_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_txc)) + MCFG_DEVICE_ADD(CORVUS_HDC_TAG, CORVUS_HDC, 0) MCFG_HARDDISK_ADD("harddisk1") MCFG_HARDDISK_ADD("harddisk2") MCFG_HARDDISK_ADD("harddisk3") @@ -345,7 +341,8 @@ softbox_device::softbox_device(const machine_config &mconfig, const char *tag, d : device_t(mconfig, SOFTBOX, "PET SoftBox", tag, owner, clock, "pet_softbox", __FILE__), device_ieee488_interface(mconfig, *this), m_maincpu(*this, Z80_TAG), - m_dbrg(*this, COM8116_TAG) + m_dbrg(*this, COM8116_TAG), + m_hdc(*this, CORVUS_HDC_TAG) { } @@ -356,7 +353,6 @@ softbox_device::softbox_device(const machine_config &mconfig, const char *tag, d void softbox_device::device_start() { - corvus_hdc_init(this); } diff --git a/src/emu/bus/ieee488/softbox.h b/src/emu/bus/ieee488/softbox.h index 9edc2f8adcb..f5f4902b81c 100644 --- a/src/emu/bus/ieee488/softbox.h +++ b/src/emu/bus/ieee488/softbox.h @@ -15,7 +15,13 @@ #define __PET_SOFTBOX__ #include "ieee488.h" +#include "bus/rs232/rs232.h" +#include "cpu/z80/z80.h" +#include "imagedev/harddriv.h" +#include "includes/corvushd.h" #include "machine/com8116.h" +#include "machine/i8251.h" +#include "machine/i8255.h" @@ -65,6 +71,7 @@ private: required_device m_maincpu; required_device m_dbrg; + required_device m_hdc; int m_ifc; // Tracks previous state of IEEE-488 IFC line }; diff --git a/src/mess/drivers/softbox.c b/src/mess/drivers/softbox.c index a92bd7f317a..747f2a570c5 100644 --- a/src/mess/drivers/softbox.c +++ b/src/mess/drivers/softbox.c @@ -138,7 +138,7 @@ static ADDRESS_MAP_START( softbox_io, AS_IO, 8, softbox_state ) AM_RANGE(0x0c, 0x0c) AM_WRITE(dbrg_w) AM_RANGE(0x10, 0x13) AM_DEVREADWRITE(I8255_0_TAG, i8255_device, read, write) AM_RANGE(0x14, 0x17) AM_DEVREADWRITE(I8255_1_TAG, i8255_device, read, write) - AM_RANGE(0x18, 0x18) AM_READWRITE_LEGACY(corvus_hdc_data_r, corvus_hdc_data_w) + AM_RANGE(0x18, 0x18) AM_DEVREADWRITE(CORVUS_HDC_TAG, corvus_hdc_t, read, write) ADDRESS_MAP_END @@ -276,7 +276,7 @@ READ8_MEMBER( softbox_state::ppi1_pc_r ) */ - UINT8 status = corvus_hdc_status_r(space, 0); + UINT8 status = m_hdc->status_r(space, 0); UINT8 data = 0; data |= (status & CONTROLLER_BUSY) ? 0 : 0x10; @@ -339,7 +339,6 @@ DEVICE_INPUT_DEFAULTS_END void softbox_state::machine_start() { - corvus_hdc_init(machine()); } @@ -414,6 +413,8 @@ static MACHINE_CONFIG_START( softbox, softbox_state ) MCFG_COM8116_FT_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_txc)) MCFG_CBM_IEEE488_ADD("c8050") + + MCFG_DEVICE_ADD(CORVUS_HDC_TAG, CORVUS_HDC, 0) MCFG_HARDDISK_ADD("harddisk1") MCFG_HARDDISK_ADD("harddisk2") MCFG_HARDDISK_ADD("harddisk3") diff --git a/src/mess/includes/corvushd.h b/src/mess/includes/corvushd.h index 5456fc56c09..09e3fcaf25c 100644 --- a/src/mess/includes/corvushd.h +++ b/src/mess/includes/corvushd.h @@ -13,6 +13,9 @@ #ifndef CORVUSHD_H_ #define CORVUSHD_H_ +#include "emu.h" +#include "imagedev/harddriv.h" +#include // // Controller Commands @@ -171,17 +174,330 @@ #define CONTROLLER_BUSY 0x80 // Set = Busy, Clear = Ready #define CONTROLLER_DIRECTION 0x40 // Set = Controller->Host, Clear = Host->Controller +#define MAX_COMMAND_SIZE 4096 // The maximum size of a command packet (the controller only has 5K of RAM...) -/*----------- defined in machine/corvushd.c -----------*/ +class corvus_hdc_t : public device_t +{ +public: + // construction/destruction + corvus_hdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -// -// Prototypes -// -UINT8 corvus_hdc_init( running_machine &machine ); -UINT8 corvus_hdc_init( device_t *device ); -DECLARE_READ8_HANDLER ( corvus_hdc_status_r ); -DECLARE_READ8_HANDLER ( corvus_hdc_data_r ); -DECLARE_WRITE8_HANDLER ( corvus_hdc_data_w ); + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); + DECLARE_READ8_MEMBER( status_r ); +protected: + // device-level overrides + virtual void device_start(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + +private: + enum + { + TIMER_TIMEOUT, + TIMER_COMMAND + }; + + // Sector addressing scheme for Rev B/H drives used in various commands (Called a DADR in the docs) + struct dadr_t { + UINT8 address_msn_and_drive;// Most significant nibble: Most signficant nibble of sector address, Least significant nibble: Drive # + UINT8 address_lsb; // Least significant byte of sector address + UINT8 address_mid; // Middle byte of sector address + }; + + UINT8 m_status; // Controller status byte (DIRECTION + BUSY/READY) + bool m_prep_mode; // Whether the controller is in Prep Mode or not + // Physical drive info + UINT8 m_sectors_per_track; // Number of sectors per track for this drive + UINT8 m_tracks_per_cylinder;// Number of tracks per cylinder (heads) + UINT16 m_cylinders_per_drive;// Number of cylinders per drive + // Command Processing + UINT16 m_offset; // Current offset into raw_data buffer + bool m_awaiting_modifier; // We've received a two-byte command and we're waiting for the mod + UINT16 m_recv_bytes; // Number of bytes expected to be received from Host + UINT16 m_xmit_bytes; // Number of bytes expected to be transmitted to host + // Timing-related values + UINT16 m_last_cylinder; // Last cylinder accessed - for calculating seek times + UINT32 m_delay; // Delay in microseconds for callback + emu_timer *m_timeout_timer; // Four-second timer for timeouts + emu_timer *m_cmd_timer; + bool m_invalid_command_flag; // I hate this, but it saves a lot more tests + + // + // Union below represents both an input and output buffer and interpretations of it + // + union { + // + // Raw Buffer + // + UINT8 raw_data[MAX_COMMAND_SIZE]; + // + // Basic interpretation of code and modifier + // + struct { + UINT8 code; // First byte of data is the code (command) + UINT8 modifier; // Second byte of data is the modifier + } command; + // + // Basic response code + // + struct { + UINT8 status; // Status code returned by the command executed + } single_byte_response; + // + // Read sector command + // + struct { + UINT8 code; // Command code + dadr_t dadr; // Encoded drive and sector to read + } read_sector_command; + // + // 128-byte Read Sector response + // + struct { + UINT8 status; // Status code returned by command executed + UINT8 data[128]; // Data returned from read + } read_128_response; + // + // 256-byte Read Sector response + // + struct { + UINT8 status; // Status code returned by command executed + UINT8 data[256]; // Data returned from read + } read_256_reponse; + // + // 512-byte Read Sector response + // + struct { + UINT8 status; // Status code returned by command executed + UINT8 data[512]; // Data returned by read + } read_512_response; + // + // Write 128-byte sector command + // + struct { + UINT8 code; // Command code + dadr_t dadr; // Encoded drive and sector to write + UINT8 data[128]; // Data to be written + } write_128_command; + // + // Write 256-byte sector command + // + struct { + UINT8 code; // Command code + dadr_t dadr; // Encoded drive and sector to write + UINT8 data[256]; // Data to be written + } write_256_command; + // + // Write 512-byte sector command + // + struct { + UINT8 code; // Command Code + dadr_t dadr; // Encoded drive and sector to write + UINT8 data[512]; // Data to be written + } write_512_command; + // + // Semaphore Lock command + // + struct { + UINT8 code; // Command code + UINT8 modifier; // Command code modifier + UINT8 name[8]; // Semaphore name + } lock_semaphore_command; + // + // Semaphore Unlock command + // + struct { + UINT8 code; // Command code + UINT8 modifier; // Command code modifier + UINT8 name[8]; // Semaphore name + } unlock_semaphore_command; + // + // Semaphore Lock/Unlock response + // + struct { + UINT8 status; // Disk access status + UINT8 result; // Semaphore action status + UINT8 unused[10]; // Unused + } semaphore_locking_response; + // + // Initialize Semaphore table command + // + struct { + UINT8 code; // Command code + UINT8 modifier; // Command code modifier + UINT8 unused[3]; // Unused + } init_semaphore_command; + // + // Semaphore Status command + // + struct { + UINT8 code; // Command code + UINT8 modifier; // Command code modifier + UINT8 zero_three; // Don't ask me... + UINT8 unused[2]; // Unused + } semaphore_status_command; + // + // Semaphore Status response + // + struct { + UINT8 status; // Disk access status + UINT8 table[256]; // Contents of the semaphore table + } semaphore_status_response; + // + // Get Drive Parameters command (0x10) + // + struct { + UINT8 code; // Command code + UINT8 drive; // Drive number (starts at 1) + } get_drive_parameters_command; + // + // Get Drive Parameters command response + // + struct { + UINT8 status; // Status code returned by command executed + UINT8 firmware[33]; // Firmware message + UINT8 rom_version; // ROM Version + struct { + UINT8 sectors_per_track; // Sectors/Track + UINT8 tracks_per_cylinder; // Tracks/Cylinder (heads) + struct { + UINT8 lsb; + UINT8 msb; + } cylinders_per_drive; // Byte-flipped Cylinders/Drive + } track_info; + struct { + UINT8 lsb; // Least significant byte + UINT8 midb; // Middle byte + UINT8 msb; // Most significant byte + } capacity; // 24-bit value, byte-flipped (lsb..msb) + UINT8 unused[16]; + UINT8 interleave; // Interleave factor + struct { + UINT8 mux_parameters[12]; + UINT8 pipe_name_table_ptr[2]; // Pointer to table of 64 entries, 8 bytes each (table of names) + UINT8 pipe_ptr_table_ptr[2]; // Pointer to table of 64 entries, 8 bytes each. See pp. 29 - Mass Storage GTI + UINT8 pipe_area_size[2]; // Size of pipe area (lsb, msb) + struct { + UINT8 track_offset[2]; + } vdo_table[7]; // Virtual drive table + UINT8 lsi11_vdo_table[8]; + UINT8 lsi11_spare_table[8]; + } table_info; + UINT8 drive_number; // Physical drive number + struct { + UINT8 lsb; // Least + UINT8 midb; // Middle + UINT8 msb; // Most + } physical_capacity; // Physical capacity of drive + } drive_param_response; + // + // 2-byte Boot command (0x14) + // + struct { + UINT8 code; // Command code + UINT8 boot_block; // Which boot block to read (0-7) + } old_boot_command; + // + // Read Firmware command (Prep Mode 0x32) + // + struct { + UINT8 code; // Command Code + UINT8 encoded_h_s;// Encoded Head (bits 7-5) / Sector (bits 4-0) + } read_firmware_command; + // + // Write Firmware command (Prep Mode 0x33) + // + struct { + UINT8 code; // Command Code + UINT8 encoded_h_s; // Encoded Head (bits 7-5) / Sector (bits 4-0) + UINT8 data[512]; // Data to be written + } write_firmware_command; + // + // Format Drive command (Prep Mode 0x01) + // + // Note that the following is a BLATANT ASSUMPTION. Technically, the Format Drive command + // uses a variable-length buffer for the pattern. Unfortunately, the docs don't explain how to determine the + // length of the buffer passed. I assume it's a timeout; however, the docs happen to say that + // all Corvus diagnostic programs send 513 bytes total, including the command, so I'm going with that. + // + struct { + UINT8 code; // Command Code + UINT8 pattern[512]; // Pattern to be written + } format_drive_revbh_command; + } m_buffer; + + // Structure of Block #1, the Disk Parameter Block + struct disk_parameter_block_t { + struct { + UINT8 lsb; + UINT8 msb; + } spared_track[8]; // Spared track table (0xffff indicates end) + UINT8 interleave; // Interleave factor + UINT8 reserved; + struct { + UINT8 track_offset[2]; // Virtual drive offsets (lsb, msb) 0xffff indicates unused + } vdo_table[7]; + UINT8 lsi11_vdo_table[8]; + UINT8 lsi11_spare_table[8]; + UINT8 reserved2[432]; + struct { + UINT8 lsb; + UINT8 msb; + } revh_spare_table[16]; + }; + + // Structure of Block #3, the Constellation Parameter Block + struct constellation_parameter_block_t { + UINT8 mux_parameters[12]; + UINT8 pipe_name_table_ptr[2]; + UINT8 pipe_ptr_table_ptr[2]; + UINT8 pipe_area_size[2]; + UINT8 reserved[470]; + UINT8 software_protection[12]; + UINT8 serial_number[12]; + }; + + // Structure of Block #7, the Semaphore Table Block + struct semaphore_table_block_t { + union { + UINT8 semaphore_table[256]; // Table consists of 256 bytes + struct { + UINT8 semaphore_name[8]; // Each semaphore name is 8 bytes + } semaphore_entry[32]; // 32 Entries + } semaphore_block; + UINT8 unused[256]; // Remaining half of block is unused + }; + + // Command size structure (number of bytes to xmit and recv for each command) + struct corvus_cmd_t { + UINT16 recv_bytes; // Number of bytes from host for this command + UINT16 xmit_bytes; // Number of bytes to return to host + }; + + void dump_buffer(UINT8 *buffer, UINT16 length); + bool parse_hdc_command(UINT8 data); + UINT8 corvus_write_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len); + UINT8 corvus_write_logical_sector(dadr_t *dadr, UINT8 *buffer, int len); + UINT8 corvus_read_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len); + UINT8 corvus_read_logical_sector(dadr_t *dadr, UINT8 *buffer, int len); + UINT8 corvus_lock_semaphore(UINT8 *name); + UINT8 corvus_unlock_semaphore(UINT8 *name); + UINT8 corvus_init_semaphore_table(); + UINT8 corvus_get_drive_parameters(UINT8 drv); + UINT8 corvus_read_boot_block(UINT8 block); + UINT8 corvus_read_firmware_block(UINT8 head, UINT8 sector); + UINT8 corvus_write_firmware_block(UINT8 head, UINT8 sector, UINT8 *buffer); + UINT8 corvus_format_drive(UINT8 *pattern, UINT16 len); + hard_disk_file *corvus_hdc_file(int id); + void corvus_process_command_packet(bool local_invalid_command_flag); + + corvus_cmd_t corvus_cmd[0xf5][0xc1]; // Command sizes and their return sizes + corvus_cmd_t corvus_prep_cmd[0x82]; // Prep Command sizes and their return sizes +}; + + +// device type definition +extern const device_type CORVUS_HDC; #endif /* CORVUSHD_H_ */ diff --git a/src/mess/includes/softbox.h b/src/mess/includes/softbox.h index 13546f2b3ce..d259a92f9c8 100644 --- a/src/mess/includes/softbox.h +++ b/src/mess/includes/softbox.h @@ -21,6 +21,7 @@ #define I8255_1_TAG "ic16" #define COM8116_TAG "ic14" #define RS232_TAG "rs232" +#define CORVUS_HDC_TAG "corvus" class softbox_state : public driver_device { @@ -29,12 +30,14 @@ public: : driver_device(mconfig, type, tag), m_maincpu(*this, Z80_TAG), m_dbrg(*this, COM8116_TAG), - m_ieee(*this, IEEE488_TAG) + m_ieee(*this, IEEE488_TAG), + m_hdc(*this, CORVUS_HDC_TAG) { } required_device m_maincpu; required_device m_dbrg; required_device m_ieee; + required_device m_hdc; virtual void machine_start(); virtual void device_reset_after_children(); diff --git a/src/mess/machine/concept_exp.c b/src/mess/machine/concept_exp.c index 8b22a61b865..5c9f506d380 100644 --- a/src/mess/machine/concept_exp.c +++ b/src/mess/machine/concept_exp.c @@ -18,7 +18,6 @@ #include "formats/basicdsk.h" // HDC controller -#include "includes/corvushd.h" #include "imagedev/harddriv.h" //************************************************************************** @@ -123,7 +122,8 @@ concept_fdc_device::concept_fdc_device(const machine_config &mconfig, const char concept_hdc_device::concept_hdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, CONCEPT_HDC, "Corvus Concept HDC controller", tag, owner, clock, "concept_hdc", __FILE__), - concept_exp_card_device( mconfig, *this ) + concept_exp_card_device( mconfig, *this ), + m_hdc(*this, "hdc") { } @@ -343,7 +343,6 @@ machine_config_constructor concept_fdc_device::device_mconfig_additions() const void concept_hdc_device::device_start() { - corvus_hdc_init(machine()); } @@ -358,10 +357,10 @@ READ8_MEMBER(concept_hdc_device::reg_r) switch (offset) { case 0: // HDC Data Register - return corvus_hdc_data_r(space, offset); + return m_hdc->read(space, offset); case 1: // HDC Status Register - return corvus_hdc_status_r(space, offset); + return m_hdc->status_r(space, offset); } return 0; @@ -373,7 +372,7 @@ WRITE8_MEMBER(concept_hdc_device::reg_w) switch (offset) { case 0: // HDC Data Register - corvus_hdc_data_w(space, offset, data); + m_hdc->write(space, offset, data); break; } } @@ -388,6 +387,7 @@ READ8_MEMBER(concept_hdc_device::rom_r) static MACHINE_CONFIG_FRAGMENT( hdc ) + MCFG_DEVICE_ADD("hdc", CORVUS_HDC, 0) MCFG_HARDDISK_ADD( "harddisk1" ) MACHINE_CONFIG_END diff --git a/src/mess/machine/concept_exp.h b/src/mess/machine/concept_exp.h index 697492d664a..d6a459b3cb7 100644 --- a/src/mess/machine/concept_exp.h +++ b/src/mess/machine/concept_exp.h @@ -3,6 +3,7 @@ #include "emu.h" #include "machine/wd17xx.h" +#include "includes/corvushd.h" // FIXME: Concept expansion ports should just use the Apple II Bus device! // The code below is outdated and inaccurate! @@ -110,6 +111,7 @@ public: virtual machine_config_constructor device_mconfig_additions() const; protected: + required_device m_hdc; }; diff --git a/src/mess/machine/corvushd.c b/src/mess/machine/corvushd.c index 1d196cade20..5cea873fc1c 100644 --- a/src/mess/machine/corvushd.c +++ b/src/mess/machine/corvushd.c @@ -68,6 +68,25 @@ #include +const device_type CORVUS_HDC = &device_creator; + +corvus_hdc_t::corvus_hdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, CORVUS_HDC, "Corvus Flat Cable HDC", tag, owner, clock, "corvus_hdc", __FILE__), + m_status(0), + m_prep_mode(false), + m_sectors_per_track(0), + m_tracks_per_cylinder(0), + m_cylinders_per_drive(0), + m_offset(0), + m_awaiting_modifier(false), + m_recv_bytes(0), + m_xmit_bytes(0), + m_last_cylinder(0), + m_delay(0), + m_invalid_command_flag(false) +{ +} + #define VERBOSE 0 #define VERBOSE_RESPONSES 0 #define VERSION 1 @@ -83,302 +102,6 @@ #define LOG(x) do { if (VERBOSE) logerror x; } while (0) #define LOG_BUFFER(p,s) do { if (VERBOSE) dump_buffer(p,s); } while (0) -// -// Structures -// - -// Sector addressing scheme for Rev B/H drives used in various commands (Called a DADR in the docs) -struct dadr_t { - UINT8 address_msn_and_drive;// Most significant nibble: Most signficant nibble of sector address, Least significant nibble: Drive # - UINT8 address_lsb; // Least significant byte of sector address - UINT8 address_mid; // Middle byte of sector address -}; - -// Controller structure -struct corvus_hdc_t { - device_t *root_device; - UINT8 status; // Controller status byte (DIRECTION + BUSY/READY) - char prep_mode; // Whether the controller is in Prep Mode or not - // Physical drive info - UINT8 sectors_per_track; // Number of sectors per track for this drive - UINT8 tracks_per_cylinder;// Number of tracks per cylinder (heads) - UINT16 cylinders_per_drive;// Number of cylinders per drive - // Command Processing - UINT16 offset; // Current offset into raw_data buffer - char awaiting_modifier; // We've received a two-byte command and we're waiting for the mod - UINT16 recv_bytes; // Number of bytes expected to be received from Host - UINT16 xmit_bytes; // Number of bytes expected to be transmitted to host - // Timing-related values - UINT16 last_cylinder; // Last cylinder accessed - for calculating seek times - UINT32 delay; // Delay in microseconds for callback - emu_timer *timeout_timer; // Four-second timer for timeouts - UINT8 invalid_command_flag; // I hate this, but it saves a lot more tests - - // - // Union below represents both an input and output buffer and interpretations of it - // - union { - // - // Raw Buffer - // - UINT8 raw_data[MAX_COMMAND_SIZE]; - // - // Basic interpretation of code and modifier - // - struct { - UINT8 code; // First byte of data is the code (command) - UINT8 modifier; // Second byte of data is the modifier - } command; - // - // Basic response code - // - struct { - UINT8 status; // Status code returned by the command executed - } single_byte_response; - // - // Read sector command - // - struct { - UINT8 code; // Command code - dadr_t dadr; // Encoded drive and sector to read - } read_sector_command; - // - // 128-byte Read Sector response - // - struct { - UINT8 status; // Status code returned by command executed - UINT8 data[128]; // Data returned from read - } read_128_response; - // - // 256-byte Read Sector response - // - struct { - UINT8 status; // Status code returned by command executed - UINT8 data[256]; // Data returned from read - } read_256_reponse; - // - // 512-byte Read Sector response - // - struct { - UINT8 status; // Status code returned by command executed - UINT8 data[512]; // Data returned by read - } read_512_response; - // - // Write 128-byte sector command - // - struct { - UINT8 code; // Command code - dadr_t dadr; // Encoded drive and sector to write - UINT8 data[128]; // Data to be written - } write_128_command; - // - // Write 256-byte sector command - // - struct { - UINT8 code; // Command code - dadr_t dadr; // Encoded drive and sector to write - UINT8 data[256]; // Data to be written - } write_256_command; - // - // Write 512-byte sector command - // - struct { - UINT8 code; // Command Code - dadr_t dadr; // Encoded drive and sector to write - UINT8 data[512]; // Data to be written - } write_512_command; - // - // Semaphore Lock command - // - struct { - UINT8 code; // Command code - UINT8 modifier; // Command code modifier - UINT8 name[8]; // Semaphore name - } lock_semaphore_command; - // - // Semaphore Unlock command - // - struct { - UINT8 code; // Command code - UINT8 modifier; // Command code modifier - UINT8 name[8]; // Semaphore name - } unlock_semaphore_command; - // - // Semaphore Lock/Unlock response - // - struct { - UINT8 status; // Disk access status - UINT8 result; // Semaphore action status - UINT8 unused[10]; // Unused - } semaphore_locking_response; - // - // Initialize Semaphore table command - // - struct { - UINT8 code; // Command code - UINT8 modifier; // Command code modifier - UINT8 unused[3]; // Unused - } init_semaphore_command; - // - // Semaphore Status command - // - struct { - UINT8 code; // Command code - UINT8 modifier; // Command code modifier - UINT8 zero_three; // Don't ask me... - UINT8 unused[2]; // Unused - } semaphore_status_command; - // - // Semaphore Status response - // - struct { - UINT8 status; // Disk access status - UINT8 table[256]; // Contents of the semaphore table - } semaphore_status_response; - // - // Get Drive Parameters command (0x10) - // - struct { - UINT8 code; // Command code - UINT8 drive; // Drive number (starts at 1) - } get_drive_parameters_command; - // - // Get Drive Parameters command response - // - struct { - UINT8 status; // Status code returned by command executed - UINT8 firmware[33]; // Firmware message - UINT8 rom_version; // ROM Version - struct { - UINT8 sectors_per_track; // Sectors/Track - UINT8 tracks_per_cylinder; // Tracks/Cylinder (heads) - struct { - UINT8 lsb; - UINT8 msb; - } cylinders_per_drive; // Byte-flipped Cylinders/Drive - } track_info; - struct { - UINT8 lsb; // Least significant byte - UINT8 midb; // Middle byte - UINT8 msb; // Most significant byte - } capacity; // 24-bit value, byte-flipped (lsb..msb) - UINT8 unused[16]; - UINT8 interleave; // Interleave factor - struct { - UINT8 mux_parameters[12]; - UINT8 pipe_name_table_ptr[2]; // Pointer to table of 64 entries, 8 bytes each (table of names) - UINT8 pipe_ptr_table_ptr[2]; // Pointer to table of 64 entries, 8 bytes each. See pp. 29 - Mass Storage GTI - UINT8 pipe_area_size[2]; // Size of pipe area (lsb, msb) - struct { - UINT8 track_offset[2]; - } vdo_table[7]; // Virtual drive table - UINT8 lsi11_vdo_table[8]; - UINT8 lsi11_spare_table[8]; - } table_info; - UINT8 drive_number; // Physical drive number - struct { - UINT8 lsb; // Least - UINT8 midb; // Middle - UINT8 msb; // Most - } physical_capacity; // Physical capacity of drive - } drive_param_response; - // - // 2-byte Boot command (0x14) - // - struct { - UINT8 code; // Command code - UINT8 boot_block; // Which boot block to read (0-7) - } old_boot_command; - // - // Read Firmware command (Prep Mode 0x32) - // - struct { - UINT8 code; // Command Code - UINT8 encoded_h_s;// Encoded Head (bits 7-5) / Sector (bits 4-0) - } read_firmware_command; - // - // Write Firmware command (Prep Mode 0x33) - // - struct { - UINT8 code; // Command Code - UINT8 encoded_h_s; // Encoded Head (bits 7-5) / Sector (bits 4-0) - UINT8 data[512]; // Data to be written - } write_firmware_command; - // - // Format Drive command (Prep Mode 0x01) - // - // Note that the following is a BLATANT ASSUMPTION. Technically, the Format Drive command - // uses a variable-length buffer for the pattern. Unfortunately, the docs don't explain how to determine the - // length of the buffer passed. I assume it's a timeout; however, the docs happen to say that - // all Corvus diagnostic programs send 513 bytes total, including the command, so I'm going with that. - // - struct { - UINT8 code; // Command Code - UINT8 pattern[512]; // Pattern to be written - } format_drive_revbh_command; - } buffer; -}; - -// Structure of Block #1, the Disk Parameter Block -struct disk_parameter_block_t { - struct { - UINT8 lsb; - UINT8 msb; - } spared_track[8]; // Spared track table (0xffff indicates end) - UINT8 interleave; // Interleave factor - UINT8 reserved; - struct { - UINT8 track_offset[2]; // Virtual drive offsets (lsb, msb) 0xffff indicates unused - } vdo_table[7]; - UINT8 lsi11_vdo_table[8]; - UINT8 lsi11_spare_table[8]; - UINT8 reserved2[432]; - struct { - UINT8 lsb; - UINT8 msb; - } revh_spare_table[16]; -}; - -// Structure of Block #3, the Constellation Parameter Block -struct constellation_parameter_block_t { - UINT8 mux_parameters[12]; - UINT8 pipe_name_table_ptr[2]; - UINT8 pipe_ptr_table_ptr[2]; - UINT8 pipe_area_size[2]; - UINT8 reserved[470]; - UINT8 software_protection[12]; - UINT8 serial_number[12]; -}; - -// Structure of Block #7, the Semaphore Table Block -struct semaphore_table_block_t { - union { - UINT8 semaphore_table[256]; // Table consists of 256 bytes - struct { - UINT8 semaphore_name[8]; // Each semaphore name is 8 bytes - } semaphore_entry[32]; // 32 Entries - } semaphore_block; - UINT8 unused[256]; // Remaining half of block is unused -}; - -// Command size structure (number of bytes to xmit and recv for each command) -struct corvus_cmd_t { - UINT16 recv_bytes; // Number of bytes from host for this command - UINT16 xmit_bytes; // Number of bytes to return to host -}; - -// -// Prototypes -// -static hard_disk_file *corvus_hdc_file(running_machine &machine, int id); -static TIMER_CALLBACK(corvus_hdc_callback); - -// -// Globals -// -static corvus_hdc_t corvus_hdc; // The controller itself -static corvus_cmd_t corvus_cmd[0xf5][0xc1]; // Command sizes and their return sizes -static corvus_cmd_t corvus_prep_cmd[0x82]; // Prep Command sizes and their return sizes @@ -394,7 +117,7 @@ static corvus_cmd_t corvus_prep_cmd[0x82]; // Prep Command sizes and their // Returns: // nada // -static void dump_buffer(UINT8 *buffer, UINT16 length) { +void corvus_hdc_t::dump_buffer(UINT8 *buffer, UINT16 length) { UINT16 offset; char ascii_dump[16]; @@ -423,7 +146,7 @@ static void dump_buffer(UINT8 *buffer, UINT16 length) { // Parse_HDC_Command // // Process the first byte received from the host. Do some initial evaluation and -// return either TRUE or FALSE as to whether the command was invalid or not. +// return either true or false as to whether the command was invalid or not. // // Note that recv_bytes and xmit_bytes in the corvus_hdc structure are updated as // a side-effect of this command, as is awaiting_modifier. @@ -432,16 +155,14 @@ static void dump_buffer(UINT8 *buffer, UINT16 length) { // data: Initial byte received from the host in Host to Controller mode // // Returns: -// Whether the command was invalid or not (TRUE = invalid command) +// Whether the command was invalid or not (true = invalid command) // -static UINT8 parse_hdc_command(UINT8 data) { - corvus_hdc_t *c = &corvus_hdc; +bool corvus_hdc_t::parse_hdc_command(UINT8 data) { + m_awaiting_modifier = false; // This is the case by definition - c->awaiting_modifier = FALSE; // This is the case by definition + LOG(("parse_hdc_command: Called with data: 0x%2.2x, Prep mode is: %d\n", data, m_prep_mode)); - LOG(("parse_hdc_command: Called with data: 0x%2.2x, Prep mode is: %d\n", data, c->prep_mode)); - - if(!c->prep_mode) { + if(!m_prep_mode) { switch(data) { // // Single-byte commands - Non-Prep mode @@ -463,10 +184,10 @@ static UINT8 parse_hdc_command(UINT8 data) { case PARK_HEADS_OMNI: case ECHO: case PREP_MODE_SELECT: - c->recv_bytes = corvus_cmd[data][0].recv_bytes; - c->xmit_bytes = corvus_cmd[data][0].xmit_bytes; + m_recv_bytes = corvus_cmd[data][0].recv_bytes; + m_xmit_bytes = corvus_cmd[data][0].xmit_bytes; LOG(("parse_hdc_command: Single byte command recognized: 0x%2.2x, to recv: %d, to xmit: %d\n", data, - c->recv_bytes, c->xmit_bytes)); + m_recv_bytes, m_xmit_bytes)); break; // // Double-byte commands @@ -487,15 +208,15 @@ static UINT8 parse_hdc_command(UINT8 data) { // case DELACTIVEUSR_OMNI_CODE: // case DELACTIVENUM_OMNI_CODE: // case FINDACTIVE_CODE: - c->awaiting_modifier = TRUE; + m_awaiting_modifier = true; LOG(("parse_hdc_command: Double byte command recognized: 0x%2.2x\n", data)); break; default: // This is an INVALID command - c->recv_bytes = 1; - c->xmit_bytes = 1; + m_recv_bytes = 1; + m_xmit_bytes = 1; LOG(("parse_hdc_command: Invalid command detected: 0x%2.2x\n", data)); - return TRUE; + return true; } } else { switch(data) { @@ -509,21 +230,21 @@ static UINT8 parse_hdc_command(UINT8 data) { case PREP_VERIFY: case PREP_READ_FIRMWARE: case PREP_WRITE_FIRMWARE: - c->recv_bytes = corvus_prep_cmd[data].recv_bytes; - c->xmit_bytes = corvus_prep_cmd[data].xmit_bytes; + m_recv_bytes = corvus_prep_cmd[data].recv_bytes; + m_xmit_bytes = corvus_prep_cmd[data].xmit_bytes; LOG(("parse_hdc_command: Prep command recognized: 0x%2.2x, to recv: %d, to xmit: %d\n", data, - c->recv_bytes, c->xmit_bytes)); + m_recv_bytes, m_xmit_bytes)); break; default: // This is an INVALID prep command - c->recv_bytes = 1; - c->xmit_bytes = 1; + m_recv_bytes = 1; + m_xmit_bytes = 1; LOG(("parse_hdc_command: Invalid Prep command detected: 0x%2.2x\n", data)); - return TRUE; + return true; } } // if(!prep_mode) - return FALSE; + return false; } @@ -542,9 +263,7 @@ static UINT8 parse_hdc_command(UINT8 data) { // Returns: // status: Command status // -static UINT8 corvus_write_sector(running_machine &machine, UINT8 drv, UINT32 sector, UINT8 *buffer, int len) { - corvus_hdc_t - *c = &corvus_hdc; +UINT8 corvus_hdc_t::corvus_write_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len) { hard_disk_file *disk; // Structures for interface to CHD routines UINT8 tbuffer[512]; // Buffer to hold an entire sector @@ -552,7 +271,7 @@ static UINT8 corvus_write_sector(running_machine &machine, UINT8 drv, UINT32 sec LOG(("corvus_write_sector: Write Drive: %d, physical sector: 0x%5.5x\n", drv, sector)); - disk = corvus_hdc_file(machine, drv); + disk = corvus_hdc_file(drv); if(!disk) { logerror("corvus_write_sector: Failure returned by corvus_hdc_file(%d)\n", drv); return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE; @@ -561,8 +280,8 @@ static UINT8 corvus_write_sector(running_machine &machine, UINT8 drv, UINT32 sec // // Calculate what cylinder the sector resides on for timing purposes // - cylinder = (double) sector / (double) c->sectors_per_track / (double) c->tracks_per_cylinder; - c->delay = abs(c->last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY; + cylinder = (double) sector / (double) m_sectors_per_track / (double) m_tracks_per_cylinder; + m_delay = abs(m_last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY; // // Corvus supports write sizes of 128, 256 and 512 bytes. In the case of a write smaller than @@ -575,11 +294,11 @@ static UINT8 corvus_write_sector(running_machine &machine, UINT8 drv, UINT32 sec } else { hard_disk_read(disk, sector, tbuffer); // Read the existing data into our temporary buffer memcpy(tbuffer, buffer, len); // Overlay the data with the buffer passed - c->delay += INTERSECTOR_DELAY; // Add another delay because of the Read / Write + m_delay += INTERSECTOR_DELAY; // Add another delay because of the Read / Write hard_disk_write(disk, sector, tbuffer); // Re-write the data } - c->last_cylinder = cylinder; + m_last_cylinder = cylinder; LOG(("corvus_write_sector: Full sector dump on a write of %d bytes follows:\n", len)); LOG_BUFFER(len == 512 ? buffer : tbuffer, 512); @@ -602,9 +321,7 @@ static UINT8 corvus_write_sector(running_machine &machine, UINT8 drv, UINT32 sec // Returns: // status: Corvus status // -static UINT8 corvus_write_logical_sector(running_machine &machine, dadr_t *dadr, UINT8 *buffer, int len) { - corvus_hdc_t - *c = &corvus_hdc; +UINT8 corvus_hdc_t::corvus_write_logical_sector(dadr_t *dadr, UINT8 *buffer, int len) { UINT8 status; // Status returned from Physical Sector read UINT8 drv; // Drive number (1 - 15) UINT32 sector; // Sector number on drive @@ -623,18 +340,18 @@ static UINT8 corvus_write_logical_sector(running_machine &machine, dadr_t *dadr, LOG(("corvus_write_logical_sector: Writing based on DADR: 0x%6.6x, logical sector: 0x%5.5x, drive: %d\n", dadr->address_msn_and_drive << 16 | dadr->address_lsb << 8 | dadr->address_mid, sector, drv)); - // Set up the global corvus_hdc so c->tracks_per_cylinder and c->sectors_per_track are valid - corvus_hdc_file(machine, drv); + // Set up the global corvus_hdc so m_tracks_per_cylinder and m_sectors_per_track are valid + corvus_hdc_file(drv); // // Shift the logical sector address forward by the number of firmware cylinders (2) + the number of spare tracks (7) // - sector += (c->tracks_per_cylinder * c->sectors_per_track * 2) + (SPARE_TRACKS * c->sectors_per_track); + sector += (m_tracks_per_cylinder * m_sectors_per_track * 2) + (SPARE_TRACKS * m_sectors_per_track); - status = corvus_write_sector(machine, drv, sector, buffer, len); + status = corvus_write_sector(drv, sector, buffer, len); if(status != STAT_SUCCESS) - c->xmit_bytes = 1; + m_xmit_bytes = 1; return status; } @@ -654,9 +371,7 @@ static UINT8 corvus_write_logical_sector(running_machine &machine, dadr_t *dadr, // Returns: // status: Corvus status // -static UINT8 corvus_read_sector(running_machine &machine, UINT8 drv, UINT32 sector, UINT8 *buffer, int len) { - corvus_hdc_t - *c = &corvus_hdc; +UINT8 corvus_hdc_t::corvus_read_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len) { hard_disk_file *disk; // Structures for interface to CHD routines UINT8 tbuffer[512]; // Buffer to store full sector results in @@ -664,7 +379,7 @@ static UINT8 corvus_read_sector(running_machine &machine, UINT8 drv, UINT32 sect LOG(("corvus_read_sector: Read Drive: %d, physical sector: 0x%5.5x\n", drv, sector)); - disk = corvus_hdc_file(machine, drv); + disk = corvus_hdc_file(drv); if(!disk) { logerror("corvus_read_sector: Failure returned by corvus_hdc_file(%d)\n", drv); return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE; @@ -673,14 +388,14 @@ static UINT8 corvus_read_sector(running_machine &machine, UINT8 drv, UINT32 sect // // Calculate what cylinder the sector resides on for timing purposes // - cylinder = (double) sector / (double) c->sectors_per_track / (double) c->tracks_per_cylinder; - c->delay = abs(c->last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY; + cylinder = (double) sector / (double) m_sectors_per_track / (double) m_tracks_per_cylinder; + m_delay = abs(m_last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY; hard_disk_read(disk, sector, tbuffer); memcpy(buffer, tbuffer, len); - c->last_cylinder = cylinder; + m_last_cylinder = cylinder; LOG(("corvus_read_sector: Data read follows:\n")); LOG_BUFFER(tbuffer, len); @@ -703,9 +418,7 @@ static UINT8 corvus_read_sector(running_machine &machine, UINT8 drv, UINT32 sect // Returns: // status: Corvus status // -static UINT8 corvus_read_logical_sector(running_machine &machine, dadr_t *dadr, UINT8 *buffer, int len) { - corvus_hdc_t - *c = &corvus_hdc; +UINT8 corvus_hdc_t::corvus_read_logical_sector(dadr_t *dadr, UINT8 *buffer, int len) { UINT8 status; // Status returned from Physical Sector read UINT8 drv; // Drive number (1 - 15) UINT32 sector; // Sector number on drive @@ -724,18 +437,18 @@ static UINT8 corvus_read_logical_sector(running_machine &machine, dadr_t *dadr, LOG(("corvus_read_logical_sector: Reading based on DADR: 0x%6.6x, logical sector: 0x%5.5x, drive: %d\n", dadr->address_msn_and_drive << 16 | dadr->address_lsb << 8 | dadr->address_mid, sector, drv)); - // Set up the global corvus_hdc so c->tracks_per_cylinder and c->sectors_per_track are valid - corvus_hdc_file(machine, drv); + // Set up the global corvus_hdc so m_tracks_per_cylinder and m_sectors_per_track are valid + corvus_hdc_file(drv); // // Shift the logical sector address forward by the number of firmware cylinders (2) + the number of spare tracks (7) // - sector += (c->tracks_per_cylinder * c->sectors_per_track * 2) + (SPARE_TRACKS * c->sectors_per_track); + sector += (m_tracks_per_cylinder * m_sectors_per_track * 2) + (SPARE_TRACKS * m_sectors_per_track); - status = corvus_read_sector(machine, drv, sector, buffer, len); + status = corvus_read_sector(drv, sector, buffer, len); if(status != STAT_SUCCESS) - c->xmit_bytes = 1; + m_xmit_bytes = 1; return status; } @@ -756,23 +469,21 @@ static UINT8 corvus_read_logical_sector(running_machine &machine, dadr_t *dadr, // Side-effects: // Fills in the semaphore result code // -static UINT8 corvus_lock_semaphore(running_machine &machine, UINT8 *name) { - corvus_hdc_t - *c = &corvus_hdc; +UINT8 corvus_hdc_t::corvus_lock_semaphore(UINT8 *name) { semaphore_table_block_t semaphore_table; UINT8 offset = 0; - UINT8 found = FALSE; + bool found = false; UINT8 blank_offset = 32; // Initialize to invalid offset UINT8 status; // Status returned from Physical Sector read // // Read the semaphore table from the drive // - status = corvus_read_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256); + status = corvus_read_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256); if(status != STAT_SUCCESS) { logerror("corvus_lock_semaphore: Error reading semaphore table, status: 0x%2.2x\n", status); - c->buffer.semaphore_locking_response.result = SEM_DISK_ERROR; + m_buffer.semaphore_locking_response.result = SEM_DISK_ERROR; return status; } @@ -784,7 +495,7 @@ static UINT8 corvus_lock_semaphore(running_machine &machine, UINT8 *name) { if(blank_offset == 32 && strncmp((char *) &semaphore_table.semaphore_block.semaphore_entry[offset], " ", 8) == 0) blank_offset = offset; if(strncmp((char *) &semaphore_table.semaphore_block.semaphore_entry[offset], (char *) name, 8) == 0) { - found = TRUE; + found = true; break; } } while( ++offset < 32 ); @@ -799,19 +510,19 @@ static UINT8 corvus_lock_semaphore(running_machine &machine, UINT8 *name) { // if(!found) { if(blank_offset == 32) { - c->buffer.semaphore_locking_response.result = SEM_TABLE_FULL; // No space for the semaphore! + m_buffer.semaphore_locking_response.result = SEM_TABLE_FULL; // No space for the semaphore! } else { - c->buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_NOT_SET; // It wasn't there already + m_buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_NOT_SET; // It wasn't there already memcpy(&semaphore_table.semaphore_block.semaphore_entry[blank_offset], name, 8);// Stick it into the table - status = corvus_write_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256); + status = corvus_write_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256); if(status != STAT_SUCCESS) { logerror("corvus_lock_semaphore: Error updating semaphore table, status: 0x%2.2x\n", status); - c->buffer.semaphore_locking_response.result = SEM_DISK_ERROR; + m_buffer.semaphore_locking_response.result = SEM_DISK_ERROR; return status; } } } else { - c->buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_SET; // It's already locked -- sorry + m_buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_SET; // It's already locked -- sorry } return STAT_SUCCESS; @@ -833,22 +544,20 @@ static UINT8 corvus_lock_semaphore(running_machine &machine, UINT8 *name) { // Side-effects: // Fills in the semaphore result code // -static UINT8 corvus_unlock_semaphore(running_machine &machine, UINT8 *name) { - corvus_hdc_t - *c = &corvus_hdc; +UINT8 corvus_hdc_t::corvus_unlock_semaphore(UINT8 *name) { semaphore_table_block_t semaphore_table; UINT8 offset = 0; - UINT8 found = FALSE; + bool found = false; UINT8 status; // Status returned from Physical Sector read // // Read the semaphore table from the drive // - status = corvus_read_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256); + status = corvus_read_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256); if(status != STAT_SUCCESS) { logerror("corvus_unlock_semaphore: Error reading semaphore table, status: 0x%2.2x\n", status); - c->buffer.semaphore_locking_response.result = SEM_DISK_ERROR; + m_buffer.semaphore_locking_response.result = SEM_DISK_ERROR; return status; } @@ -857,7 +566,7 @@ static UINT8 corvus_unlock_semaphore(running_machine &machine, UINT8 *name) { // do { if(strncmp((char *) &semaphore_table.semaphore_block.semaphore_entry[offset], (char *) name, 8) == 0) { - found = TRUE; + found = true; break; } } while( ++offset < 32 ); @@ -871,14 +580,14 @@ static UINT8 corvus_unlock_semaphore(running_machine &machine, UINT8 *name) { // Once that's done, write the updated table to the disk // if(!found) { - c->buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_NOT_SET; // It wasn't there already + m_buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_NOT_SET; // It wasn't there already } else { - c->buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_SET; // It was there + m_buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_SET; // It was there memcpy(&semaphore_table.semaphore_block.semaphore_entry[offset], " ", 8); // Clear it - status = corvus_write_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256); + status = corvus_write_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256); if(status != STAT_SUCCESS) { logerror("corvus_unlock_semaphore: Error updating semaphore table, status: 0x%2.2x\n", status); - c->buffer.semaphore_locking_response.result = SEM_DISK_ERROR; + m_buffer.semaphore_locking_response.result = SEM_DISK_ERROR; return status; } } @@ -900,14 +609,14 @@ static UINT8 corvus_unlock_semaphore(running_machine &machine, UINT8 *name) { // Disk status // // -static UINT8 corvus_init_semaphore_table( running_machine &machine ) { +UINT8 corvus_hdc_t::corvus_init_semaphore_table() { semaphore_table_block_t semaphore_table; UINT8 status; memset(semaphore_table.semaphore_block.semaphore_table, 0x20, 256); - status = corvus_write_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256); + status = corvus_write_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256); if(status != STAT_SUCCESS) { logerror("corvus_init_semaphore_table: Error updating semaphore table, status: 0x%2.2x\n", status); return status; @@ -929,9 +638,7 @@ static UINT8 corvus_init_semaphore_table( running_machine &machine ) { // Returns: // Status of command // -static UINT8 corvus_get_drive_parameters(running_machine &machine, UINT8 drv) { - corvus_hdc_t - *c = &corvus_hdc; +UINT8 corvus_hdc_t::corvus_get_drive_parameters(UINT8 drv) { UINT16 capacity; // Number of usable 512-byte blocks UINT16 raw_capacity; // Number of actual 512-byte blocks union { @@ -953,73 +660,73 @@ static UINT8 corvus_get_drive_parameters(running_machine &machine, UINT8 drv) { // drv -= 1; // Internally, drives start at 0 - if ( ! corvus_hdc_file( machine, drv ) ) + if ( ! corvus_hdc_file( drv ) ) { logerror("corvus_get_drive_parameters: Attempt to retrieve parameters from non-existant drive: %d\n", drv); - c->xmit_bytes = 1; + m_xmit_bytes = 1; return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE; } // // Read the Disk Parameter Block (Sector 1) from the drive // - status = corvus_read_sector(machine, drv, 1, raw_disk_parameter_block.buffer, 512); + status = corvus_read_sector(drv, 1, raw_disk_parameter_block.buffer, 512); if(status != STAT_SUCCESS) { logerror("corvus_get_drive_parameters: Error status returned reading Disk Parameter Block -- status: 0x%2.2x\n", status); - c->xmit_bytes = 1; + m_xmit_bytes = 1; return status; } // // Read the Constellation Parameter Block (Sector 3) from the drive // - status = corvus_read_sector(machine, drv, 3, raw_constellation_parameter_block.buffer, 512); + status = corvus_read_sector(drv, 3, raw_constellation_parameter_block.buffer, 512); if(status != STAT_SUCCESS) { logerror("corvus_get_drive_parameters: Error status returned reading Constellation Parameter Block -- status: 0x%2.2x\n", status); - c->xmit_bytes = 1; + m_xmit_bytes = 1; return status; } // // Build up the parameter packet // - strcpy((char *) c->buffer.drive_param_response.firmware, "V18.4AP -- CONST II - 11/82 %"); // Pulled from some firmware... - c->buffer.drive_param_response.rom_version = VERSION; - c->buffer.drive_param_response.track_info.sectors_per_track = c->sectors_per_track; - c->buffer.drive_param_response.track_info.tracks_per_cylinder = c->tracks_per_cylinder; - c->buffer.drive_param_response.track_info.cylinders_per_drive.msb = (c->cylinders_per_drive & 0xff00) >> 8; - c->buffer.drive_param_response.track_info.cylinders_per_drive.lsb = (c->cylinders_per_drive & 0x00ff); + strcpy((char *) m_buffer.drive_param_response.firmware, "V18.4AP -- CONST II - 11/82 %"); // Pulled from some firmware... + m_buffer.drive_param_response.rom_version = VERSION; + m_buffer.drive_param_response.track_info.sectors_per_track = m_sectors_per_track; + m_buffer.drive_param_response.track_info.tracks_per_cylinder = m_tracks_per_cylinder; + m_buffer.drive_param_response.track_info.cylinders_per_drive.msb = (m_cylinders_per_drive & 0xff00) >> 8; + m_buffer.drive_param_response.track_info.cylinders_per_drive.lsb = (m_cylinders_per_drive & 0x00ff); // // Calculate the user capacity of the drive based on total capacity less spare tracks and firmware tracks // - raw_capacity = c->tracks_per_cylinder * c->cylinders_per_drive * c->sectors_per_track; // Total capacity - capacity = raw_capacity - ((c->tracks_per_cylinder * c->sectors_per_track * 2) + (SPARE_TRACKS * c->sectors_per_track)); - c->buffer.drive_param_response.capacity.msb = (capacity & 0xff0000) >> 16; - c->buffer.drive_param_response.capacity.midb = (capacity & 0x00ff00) >> 8; - c->buffer.drive_param_response.capacity.lsb = (capacity & 0x0000ff); + raw_capacity = m_tracks_per_cylinder * m_cylinders_per_drive * m_sectors_per_track; // Total capacity + capacity = raw_capacity - ((m_tracks_per_cylinder * m_sectors_per_track * 2) + (SPARE_TRACKS * m_sectors_per_track)); + m_buffer.drive_param_response.capacity.msb = (capacity & 0xff0000) >> 16; + m_buffer.drive_param_response.capacity.midb = (capacity & 0x00ff00) >> 8; + m_buffer.drive_param_response.capacity.lsb = (capacity & 0x0000ff); // // Fill in the information from the Disk Parameter Block and Constellation Parameter Block // - c->buffer.drive_param_response.interleave = raw_disk_parameter_block.dpb.interleave; - memcpy(c->buffer.drive_param_response.table_info.mux_parameters, raw_constellation_parameter_block.cpb.mux_parameters, 12); - memcpy(c->buffer.drive_param_response.table_info.pipe_name_table_ptr, + m_buffer.drive_param_response.interleave = raw_disk_parameter_block.dpb.interleave; + memcpy(m_buffer.drive_param_response.table_info.mux_parameters, raw_constellation_parameter_block.cpb.mux_parameters, 12); + memcpy(m_buffer.drive_param_response.table_info.pipe_name_table_ptr, raw_constellation_parameter_block.cpb.pipe_name_table_ptr, 2); - memcpy(c->buffer.drive_param_response.table_info.pipe_ptr_table_ptr, + memcpy(m_buffer.drive_param_response.table_info.pipe_ptr_table_ptr, raw_constellation_parameter_block.cpb.pipe_ptr_table_ptr, 2); - memcpy(c->buffer.drive_param_response.table_info.pipe_area_size, raw_constellation_parameter_block.cpb.pipe_area_size, 2); - memcpy(c->buffer.drive_param_response.table_info.vdo_table, raw_disk_parameter_block.dpb.vdo_table, 14); - memcpy(c->buffer.drive_param_response.table_info.lsi11_vdo_table, raw_disk_parameter_block.dpb.lsi11_vdo_table, 8); - memcpy(c->buffer.drive_param_response.table_info.lsi11_spare_table, raw_disk_parameter_block.dpb.lsi11_spare_table, 8); + memcpy(m_buffer.drive_param_response.table_info.pipe_area_size, raw_constellation_parameter_block.cpb.pipe_area_size, 2); + memcpy(m_buffer.drive_param_response.table_info.vdo_table, raw_disk_parameter_block.dpb.vdo_table, 14); + memcpy(m_buffer.drive_param_response.table_info.lsi11_vdo_table, raw_disk_parameter_block.dpb.lsi11_vdo_table, 8); + memcpy(m_buffer.drive_param_response.table_info.lsi11_spare_table, raw_disk_parameter_block.dpb.lsi11_spare_table, 8); - c->buffer.drive_param_response.drive_number = drv + 1; - c->buffer.drive_param_response.physical_capacity.msb = (raw_capacity & 0xff0000) >> 16; - c->buffer.drive_param_response.physical_capacity.midb = (raw_capacity & 0x00ff00) >> 8; - c->buffer.drive_param_response.physical_capacity.lsb = (raw_capacity & 0x0000ff); + m_buffer.drive_param_response.drive_number = drv + 1; + m_buffer.drive_param_response.physical_capacity.msb = (raw_capacity & 0xff0000) >> 16; + m_buffer.drive_param_response.physical_capacity.midb = (raw_capacity & 0x00ff00) >> 8; + m_buffer.drive_param_response.physical_capacity.lsb = (raw_capacity & 0x0000ff); LOG(("corvus_get_drive_parameters: Drive Parameter packet follows:\n")); - LOG_BUFFER(c->buffer.raw_data, 110); + LOG_BUFFER(m_buffer.raw_data, 110); return STAT_SUCCESS; } @@ -1037,12 +744,10 @@ static UINT8 corvus_get_drive_parameters(running_machine &machine, UINT8 drv) { // Returns: // status: Status of read operation // -static UINT8 corvus_read_boot_block(running_machine &machine, UINT8 block) { - corvus_hdc_t *c = &corvus_hdc; // Pick up global controller structure - +UINT8 corvus_hdc_t::corvus_read_boot_block(UINT8 block) { LOG(("corvus_read_boot_block: Reading boot block: %d\n", block)); - return corvus_read_sector(machine, 0, 25 + block, c->buffer.read_512_response.data, 512); + return corvus_read_sector(0, 25 + block, m_buffer.read_512_response.data, 512); } @@ -1060,18 +765,16 @@ static UINT8 corvus_read_boot_block(running_machine &machine, UINT8 block) { // Returns: // Status of command // -static UINT8 corvus_read_firmware_block(running_machine &machine, UINT8 head, UINT8 sector) { - corvus_hdc_t - *c = &corvus_hdc; // Pick up global controller structure +UINT8 corvus_hdc_t::corvus_read_firmware_block(UINT8 head, UINT8 sector) { UINT16 relative_sector; // Relative sector on drive for Physical Read UINT8 status; - relative_sector = head * c->sectors_per_track + sector; + relative_sector = head * m_sectors_per_track + sector; LOG(("corvus_read_firmware_block: Reading firmware head: 0x%2.2x, sector: 0x%2.2x, relative_sector: 0x%2.2x\n", head, sector, relative_sector)); - status = corvus_read_sector(machine, 0, relative_sector, c->buffer.read_512_response.data, 512); // TODO: Which drive should Prep Mode talk to ??? + status = corvus_read_sector(0, relative_sector, m_buffer.read_512_response.data, 512); // TODO: Which drive should Prep Mode talk to ??? return status; } @@ -1090,18 +793,16 @@ static UINT8 corvus_read_firmware_block(running_machine &machine, UINT8 head, UI // Returns: // Status of command // -static UINT8 corvus_write_firmware_block(running_machine &machine, UINT8 head, UINT8 sector, UINT8 *buffer) { - corvus_hdc_t - *c = &corvus_hdc; // Pick up global controller structure +UINT8 corvus_hdc_t::corvus_write_firmware_block(UINT8 head, UINT8 sector, UINT8 *buffer) { UINT16 relative_sector; // Relative sector on drive for Physical Read UINT8 status; - relative_sector = head * c->sectors_per_track + sector; + relative_sector = head * m_sectors_per_track + sector; LOG(("corvus_write_firmware_block: Writing firmware head: 0x%2.2x, sector: 0x%2.2x, relative_sector: 0x%2.2x\n", head, sector, relative_sector)); - status = corvus_write_sector(machine, 0, relative_sector, buffer, 512); // TODO: Which drive should Prep Mode talk to ??? + status = corvus_write_sector(0, relative_sector, buffer, 512); // TODO: Which drive should Prep Mode talk to ??? return status; } @@ -1118,18 +819,16 @@ static UINT8 corvus_write_firmware_block(running_machine &machine, UINT8 head, U // Returns: // Status of command // -static UINT8 corvus_format_drive(running_machine &machine, UINT8 *pattern, UINT16 len) { - corvus_hdc_t - *c = &corvus_hdc; +UINT8 corvus_hdc_t::corvus_format_drive(UINT8 *pattern, UINT16 len) { UINT32 sector; UINT32 max_sector; UINT8 status = 0; UINT8 tbuffer[512]; - // Set up the global corvus_hdc so c->tracks_per_cylinder and c->sectors_per_track are valid - corvus_hdc_file(machine, 0); + // Set up the global corvus_hdc so m_tracks_per_cylinder and m_sectors_per_track are valid + corvus_hdc_file(0); - max_sector = c->sectors_per_track * c->tracks_per_cylinder * c->cylinders_per_drive; + max_sector = m_sectors_per_track * m_tracks_per_cylinder * m_cylinders_per_drive; // // If we were passed less than 512 bytes, fill the buffer up with the first byte passed (for Omnidrive Format command) @@ -1143,7 +842,7 @@ static UINT8 corvus_format_drive(running_machine &machine, UINT8 *pattern, UINT1 LOG_BUFFER(pattern, 512); for(sector = 0; sector <= max_sector; sector++) { - status = corvus_write_sector(machine, 0, sector, pattern, 512); + status = corvus_write_sector(0, sector, pattern, 512); if(status != STAT_SUCCESS) { logerror("corvus_format_drive: Error while formatting drive in corvus_write_sector--sector: 0x%5.5x, status: 0x%x2.2x\n", sector, status); @@ -1167,18 +866,11 @@ static UINT8 corvus_format_drive(running_machine &machine, UINT8 *pattern, UINT1 // Returns: // hard_disk_file object // -static hard_disk_file *corvus_hdc_file(running_machine &machine, int id) { - corvus_hdc_t - *c = &corvus_hdc; +hard_disk_file *corvus_hdc_t::corvus_hdc_file(int id) { static const char *const tags[] = { "harddisk1", "harddisk2", "harddisk3", "harddisk4" }; - harddisk_image_device *img; - - if (c->root_device) - img = dynamic_cast(c->root_device->subdevice(tags[id])); - else - img = dynamic_cast(machine.device(tags[id])); + harddisk_image_device *img = siblingdevice(tags[id]); if ( !img ) return NULL; @@ -1189,9 +881,9 @@ static hard_disk_file *corvus_hdc_file(running_machine &machine, int id) { // Pick up the Head/Cylinder/Sector info hard_disk_file *file = img->get_hard_disk_file(); hard_disk_info *info = hard_disk_get_info(file); - c->sectors_per_track = info->sectors; - c->tracks_per_cylinder = info->heads; - c->cylinders_per_drive = info->cylinders; + m_sectors_per_track = info->sectors; + m_tracks_per_cylinder = info->heads; + m_cylinders_per_drive = info->cylinders; LOG(("corvus_hdc_file: Attached to drive %u image: H:%d, C:%d, S:%d\n", id, info->heads, info->cylinders, info->sectors)); @@ -1211,46 +903,44 @@ static hard_disk_file *corvus_hdc_file(running_machine &machine, int id) { // Returns: // Nothing // -static void corvus_process_command_packet(running_machine &machine, UINT8 invalid_command_flag) { - corvus_hdc_t *c = &corvus_hdc; - +void corvus_hdc_t::corvus_process_command_packet(bool invalid_command_flag) { if (VERBOSE_RESPONSES) { LOG(("corvus_hdc_data_w: Complete packet received. Dump follows:\n")); - LOG_BUFFER(c->buffer.raw_data, c->offset); + LOG_BUFFER(m_buffer.raw_data, m_offset); } if(!invalid_command_flag) { - if(!c->prep_mode) { - switch(c->buffer.command.code) { + if(!m_prep_mode) { + switch(m_buffer.command.code) { // // Read / Write Chunk commands // case READ_CHUNK_128: - c->buffer.read_128_response.status = - corvus_read_logical_sector(machine, &c->buffer.read_sector_command.dadr, c->buffer.read_128_response.data, 128); + m_buffer.read_128_response.status = + corvus_read_logical_sector(&m_buffer.read_sector_command.dadr, m_buffer.read_128_response.data, 128); break; case READ_SECTOR_256: case READ_CHUNK_256: - c->buffer.read_256_reponse.status = - corvus_read_logical_sector(machine, &c->buffer.read_sector_command.dadr, c->buffer.read_256_reponse.data, 256); + m_buffer.read_256_reponse.status = + corvus_read_logical_sector(&m_buffer.read_sector_command.dadr, m_buffer.read_256_reponse.data, 256); break; case READ_CHUNK_512: - c->buffer.read_512_response.status = - corvus_read_logical_sector(machine, &c->buffer.read_sector_command.dadr, c->buffer.read_512_response.data, 512); + m_buffer.read_512_response.status = + corvus_read_logical_sector(&m_buffer.read_sector_command.dadr, m_buffer.read_512_response.data, 512); break; case WRITE_CHUNK_128: - c->buffer.single_byte_response.status = - corvus_write_logical_sector(machine, &c->buffer.write_128_command.dadr, c->buffer.write_128_command.data, 128); + m_buffer.single_byte_response.status = + corvus_write_logical_sector(&m_buffer.write_128_command.dadr, m_buffer.write_128_command.data, 128); break; case WRITE_SECTOR_256: case WRITE_CHUNK_256: - c->buffer.single_byte_response.status = - corvus_write_logical_sector(machine, &c->buffer.write_256_command.dadr, c->buffer.write_256_command.data, 256); + m_buffer.single_byte_response.status = + corvus_write_logical_sector(&m_buffer.write_256_command.dadr, m_buffer.write_256_command.data, 256); break; case WRITE_CHUNK_512: - c->buffer.single_byte_response.status = - corvus_write_logical_sector(machine, &c->buffer.write_512_command.dadr, c->buffer.write_512_command.data, 512); + m_buffer.single_byte_response.status = + corvus_write_logical_sector(&m_buffer.write_512_command.dadr, m_buffer.write_512_command.data, 512); break; // // Semaphore commands @@ -1259,81 +949,81 @@ static void corvus_process_command_packet(running_machine &machine, UINT8 invali // case SEMAPHORE_UNLOCK_CODE: case SEMAPHORE_INIT_CODE: // case SEMAPHORE_STATUS_CODE: - switch(c->buffer.command.modifier) { + switch(m_buffer.command.modifier) { case SEMAPHORE_LOCK_MOD: - c->buffer.semaphore_locking_response.status = corvus_lock_semaphore(machine, c->buffer.lock_semaphore_command.name); + m_buffer.semaphore_locking_response.status = corvus_lock_semaphore(m_buffer.lock_semaphore_command.name); break; case SEMAPHORE_UNLOCK_MOD: - c->buffer.semaphore_locking_response.status = - corvus_unlock_semaphore(machine, c->buffer.unlock_semaphore_command.name); + m_buffer.semaphore_locking_response.status = + corvus_unlock_semaphore(m_buffer.unlock_semaphore_command.name); break; case SEMAPHORE_INIT_MOD: - c->buffer.single_byte_response.status = corvus_init_semaphore_table(machine); + m_buffer.single_byte_response.status = corvus_init_semaphore_table(); break; case SEMAPHORE_STATUS_MOD: - c->buffer.semaphore_status_response.status = - corvus_read_sector(machine, 0, 7, c->buffer.semaphore_status_response.table, 256); + m_buffer.semaphore_status_response.status = + corvus_read_sector(0, 7, m_buffer.semaphore_status_response.table, 256); break; default: - invalid_command_flag = TRUE; + invalid_command_flag = true; } break; // // Miscellaneous commands // case BOOT: - c->buffer.read_512_response.status = - corvus_read_boot_block(machine, c->buffer.old_boot_command.boot_block); + m_buffer.read_512_response.status = + corvus_read_boot_block(m_buffer.old_boot_command.boot_block); break; case GET_DRIVE_PARAMETERS: - c->buffer.drive_param_response.status = - corvus_get_drive_parameters(machine, c->buffer.get_drive_parameters_command.drive); + m_buffer.drive_param_response.status = + corvus_get_drive_parameters(m_buffer.get_drive_parameters_command.drive); break; case PREP_MODE_SELECT: - c->prep_mode = TRUE; - c->buffer.single_byte_response.status = STAT_SUCCESS; + m_prep_mode = true; + m_buffer.single_byte_response.status = STAT_SUCCESS; break; default: - c->xmit_bytes = 1; // Return a fatal status - c->buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR; + m_xmit_bytes = 1; // Return a fatal status + m_buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR; logerror("corvus_hdc_data_w: Unimplemented command, returning FATAL FAULT status!\n"); break; } } else { // In Prep mode - switch(c->buffer.command.code) { + switch(m_buffer.command.code) { case PREP_MODE_SELECT: - c->prep_mode = TRUE; - c->buffer.single_byte_response.status = STAT_SUCCESS; + m_prep_mode = true; + m_buffer.single_byte_response.status = STAT_SUCCESS; break; case PREP_RESET_DRIVE: - c->prep_mode = FALSE; - c->buffer.single_byte_response.status = STAT_SUCCESS; + m_prep_mode = false; + m_buffer.single_byte_response.status = STAT_SUCCESS; break; case PREP_READ_FIRMWARE: - c->buffer.drive_param_response.status = - corvus_read_firmware_block(machine, (c->buffer.read_firmware_command.encoded_h_s & 0xe0) >> 5, - c->buffer.read_firmware_command.encoded_h_s & 0x1f); + m_buffer.drive_param_response.status = + corvus_read_firmware_block((m_buffer.read_firmware_command.encoded_h_s & 0xe0) >> 5, + m_buffer.read_firmware_command.encoded_h_s & 0x1f); break; case PREP_WRITE_FIRMWARE: - c->buffer.drive_param_response.status = - corvus_write_firmware_block(machine, (c->buffer.write_firmware_command.encoded_h_s & 0xe0) >> 5, - c->buffer.write_firmware_command.encoded_h_s & 0x1f, c->buffer.write_firmware_command.data); + m_buffer.drive_param_response.status = + corvus_write_firmware_block((m_buffer.write_firmware_command.encoded_h_s & 0xe0) >> 5, + m_buffer.write_firmware_command.encoded_h_s & 0x1f, m_buffer.write_firmware_command.data); break; case PREP_FORMAT_DRIVE: - c->buffer.drive_param_response.status = - corvus_format_drive(machine, c->buffer.format_drive_revbh_command.pattern, c->offset - 512); + m_buffer.drive_param_response.status = + corvus_format_drive(m_buffer.format_drive_revbh_command.pattern, m_offset - 512); break; default: - c->xmit_bytes = 1; - c->buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR; - logerror("corvus_hdc_data_w: Unimplemented Prep command %02x, returning FATAL FAULT status!\n", c->buffer.command.code); + m_xmit_bytes = 1; + m_buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR; + logerror("corvus_hdc_data_w: Unimplemented Prep command %02x, returning FATAL FAULT status!\n", m_buffer.command.code); } } if (VERBOSE_RESPONSES) { LOG(("corvus_hdc_data_w: Command execution complete, status: 0x%2.2x. Response dump follows:\n", - c->buffer.single_byte_response.status)); - LOG_BUFFER(c->buffer.raw_data, c->xmit_bytes); + m_buffer.single_byte_response.status)); + LOG_BUFFER(m_buffer.raw_data, m_xmit_bytes); } } // if(!invalid_command_flag) @@ -1345,25 +1035,26 @@ static void corvus_process_command_packet(running_machine &machine, UINT8 invali // // An Illegal command was detected (Truly invalid, not just unimplemented) // - c->buffer.single_byte_response.status = + m_buffer.single_byte_response.status = STAT_FATAL_ERR | STAT_ILL_CMD_OP_CODE; // Respond with an Illegal Op Code - logerror("corvus_hdc_data_w: Illegal command 0x%2.2x, status: 0x%2.2x\n", c->buffer.command.code, c->buffer.single_byte_response.status); + logerror("corvus_hdc_data_w: Illegal command 0x%2.2x, status: 0x%2.2x\n", m_buffer.command.code, m_buffer.single_byte_response.status); } // // Command execution complete, free up the controller // - c->offset = 0; // Point to beginning of buffer for response + m_offset = 0; // Point to beginning of buffer for response - LOG(("corvus_hdc_data_w: Setting one-time mame timer of %d microseconds to simulate disk function\n", c->delay)); + LOG(("corvus_hdc_data_w: Setting one-time mame timer of %d microseconds to simulate disk function\n", m_delay)); // // Set up timers for command completion and timeout from host // - machine.scheduler().timer_set(attotime::from_usec(c->delay), FUNC(corvus_hdc_callback), CALLBACK_CTH_MODE); - c->timeout_timer->enable(0); // We've received enough data, disable the timeout timer + //machine.scheduler().timer_set(attotime::from_usec(m_delay), FUNC(corvus_hdc_callback), CALLBACK_CTH_MODE); + m_cmd_timer->adjust(attotime::from_usec(m_delay), CALLBACK_CTH_MODE); + m_timeout_timer->enable(0); // We've received enough data, disable the timeout timer - c->delay = 0; // Reset delay for next function + m_delay = 0; // Reset delay for next function } @@ -1379,41 +1070,40 @@ static void corvus_process_command_packet(running_machine &machine, UINT8 invali // Returns: // Nothing // -static TIMER_CALLBACK(corvus_hdc_callback) +void corvus_hdc_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { int function = param; - corvus_hdc_t *c = &corvus_hdc; switch(function) { case CALLBACK_CTH_MODE: - c->status |= CONTROLLER_DIRECTION; // Set to Controller-to-Host, Ready mode - c->status &= ~(CONTROLLER_BUSY); + m_status |= CONTROLLER_DIRECTION; // Set to Controller-to-Host, Ready mode + m_status &= ~(CONTROLLER_BUSY); LOG(("corvus_hdc_callback: Callback executed with function CALLBACK_CTH_MODE\n")); break; case CALLBACK_HTC_MODE: - c->status &= ~(CONTROLLER_DIRECTION | + m_status &= ~(CONTROLLER_DIRECTION | CONTROLLER_BUSY); // Set to Host-to-Controller, Ready mode LOG(("corvus_hdc_callback: Callback executed with function CALLBACK_HTC_MODE\n")); break; case CALLBACK_SAME_MODE: - c->status &= ~(CONTROLLER_BUSY); // Set the controller to Ready mode + m_status &= ~(CONTROLLER_BUSY); // Set the controller to Ready mode break; case CALLBACK_TIMEOUT: // We reached a four-second timeout threshold - if(c->offset < c->recv_bytes || (c->offset > c->recv_bytes && c->recv_bytes != 0)) { - c->buffer.single_byte_response.status = STAT_TIMEOUT; - c->status |= CONTROLLER_DIRECTION; - c->status &= ~(CONTROLLER_BUSY); - c->recv_bytes = 0; - c->xmit_bytes = 1; + if(m_offset < m_recv_bytes || (m_offset > m_recv_bytes && m_recv_bytes != 0)) { + m_buffer.single_byte_response.status = STAT_TIMEOUT; + m_status |= CONTROLLER_DIRECTION; + m_status &= ~(CONTROLLER_BUSY); + m_recv_bytes = 0; + m_xmit_bytes = 1; logerror("corvus_hdc_callback: Exceeded four-second timeout for data from host, resetting communications\n"); - } else { // if(c->recv_bytes == 0) This was a variable-size command + } else { // if(m_recv_bytes == 0) This was a variable-size command LOG(("corvus_hdc_callback: Executing variable-length command via four-second timeout\n")); - corvus_process_command_packet(machine, 0); // Process the command + corvus_process_command_packet(0); // Process the command } break; default: @@ -1421,7 +1111,7 @@ static TIMER_CALLBACK(corvus_hdc_callback) assert(0); } if(function != CALLBACK_SAME_MODE) { - c->timeout_timer->enable(0); // Disable the four-second timer now that we're done + m_timeout_timer->enable(0); // Disable the four-second timer now that we're done } } @@ -1438,19 +1128,19 @@ static TIMER_CALLBACK(corvus_hdc_callback) // Returns: // NULL if there's no file to attach to // -UINT8 corvus_hdc_init(running_machine &machine) { - corvus_hdc_t *c = &corvus_hdc; // Pick up global controller structure +void corvus_hdc_t::device_start() { + m_status &= ~(CONTROLLER_DIRECTION | CONTROLLER_BUSY); // Host-to-controller mode, Idle (awaiting command from Host mode) + m_prep_mode = false; // We're not in Prep Mode + m_offset = 0; // Buffer is empty + m_awaiting_modifier = false; // We're not in the middle of a two-byte command + m_xmit_bytes = 0; // We don't have anything to say to the host + m_recv_bytes = 0; // We aren't waiting on additional data from the host - c->status &= ~(CONTROLLER_DIRECTION | CONTROLLER_BUSY); // Host-to-controller mode, Idle (awaiting command from Host mode) - c->prep_mode = FALSE; // We're not in Prep Mode - c->offset = 0; // Buffer is empty - c->awaiting_modifier = FALSE; // We're not in the middle of a two-byte command - c->xmit_bytes = 0; // We don't have anything to say to the host - c->recv_bytes = 0; // We aren't waiting on additional data from the host + m_timeout_timer = timer_alloc(TIMER_TIMEOUT); // Set up a timer to handle the four-second host-to-controller timeout + m_timeout_timer->adjust(attotime::from_seconds(4), CALLBACK_TIMEOUT); + m_timeout_timer->enable(0); // Start this timer out disabled - c->timeout_timer = machine.scheduler().timer_alloc(FUNC(corvus_hdc_callback)); // Set up a timer to handle the four-second host-to-controller timeout - c->timeout_timer->adjust(attotime::from_seconds(4), CALLBACK_TIMEOUT); - c->timeout_timer->enable(0); // Start this timer out disabled + m_cmd_timer = timer_alloc(TIMER_COMMAND); // // Define all of the packet sizes for the commands @@ -1551,18 +1241,6 @@ UINT8 corvus_hdc_init(running_machine &machine) { corvus_prep_cmd[PREP_WRITE_FIRMWARE].xmit_bytes = 1; LOG(("corvus_hdc_init: Drive structures initialized\n")); - - return TRUE; -} - - -UINT8 corvus_hdc_init( device_t *device ) -{ - corvus_hdc_t *c = &corvus_hdc; // Pick up global controller structure - - c->root_device = device; - - return corvus_hdc_init(device->machine()); } @@ -1577,10 +1255,8 @@ UINT8 corvus_hdc_init( device_t *device ) // Returns: // Value in the controller status register // -READ8_HANDLER ( corvus_hdc_status_r ) { - corvus_hdc_t *c = &corvus_hdc; - - return c->status; +READ8_MEMBER ( corvus_hdc_t::status_r ) { + return m_status; } @@ -1598,37 +1274,36 @@ READ8_HANDLER ( corvus_hdc_status_r ) { // Returns: // Value in the controller data register // -READ8_HANDLER ( corvus_hdc_data_r ) { - corvus_hdc_t *c = &corvus_hdc; +READ8_MEMBER ( corvus_hdc_t::read ) { UINT8 result; - if((c->status & CONTROLLER_DIRECTION) == 0) { // Check to see if we're in Controller-to-Host mode - logerror("corvus_hdc_data_r: Data register read when in Host-to-Controller mode (status: 0x%2.2x)\n", c->status); + if((m_status & CONTROLLER_DIRECTION) == 0) { // Check to see if we're in Controller-to-Host mode + logerror("corvus_hdc_data_r: Data register read when in Host-to-Controller mode (status: 0x%2.2x)\n", m_status); return 0; } - if((c->status & CONTROLLER_BUSY) != 0) { // Check to see if we're Busy - logerror("corvus_hdc_data_r: Data register read when Busy (status: 0x%2.2x)\n", c->status); + if((m_status & CONTROLLER_BUSY) != 0) { // Check to see if we're Busy + logerror("corvus_hdc_data_r: Data register read when Busy (status: 0x%2.2x)\n", m_status); return 0; } - result = c->buffer.raw_data[c->offset++]; + result = m_buffer.raw_data[m_offset++]; - if(c->offset == c->xmit_bytes) { - LOG(("corvus_hdc_data_r: Finished transmitting %d bytes of data. Returning to idle mode.\n", c->xmit_bytes)); + if(m_offset == m_xmit_bytes) { + LOG(("corvus_hdc_data_r: Finished transmitting %d bytes of data. Returning to idle mode.\n", m_xmit_bytes)); - c->offset = 0; // We've reached the end of valid data - c->xmit_bytes = 0; // We don't have anything more to say - c->recv_bytes = 0; // No active commands + m_offset = 0; // We've reached the end of valid data + m_xmit_bytes = 0; // We don't have anything more to say + m_recv_bytes = 0; // No active commands - space.machine().scheduler().timer_set((attotime::from_usec(INTERBYTE_DELAY)), FUNC(corvus_hdc_callback), CALLBACK_HTC_MODE); + m_cmd_timer->adjust(attotime::from_usec(INTERBYTE_DELAY), CALLBACK_HTC_MODE); -// c->status &= ~(CONTROLLER_DIRECTION | CONTROLLER_BUSY); // Put us in Idle, Host-to-Controller mode +// m_status &= ~(CONTROLLER_DIRECTION | CONTROLLER_BUSY); // Put us in Idle, Host-to-Controller mode } else { // // Not finished with this packet. Insert an interbyte delay and then let the host continue // - space.machine().scheduler().timer_set((attotime::from_usec(INTERBYTE_DELAY)), FUNC(corvus_hdc_callback), CALLBACK_SAME_MODE); + m_cmd_timer->adjust(attotime::from_usec(INTERBYTE_DELAY), CALLBACK_SAME_MODE); } return result; @@ -1647,60 +1322,58 @@ READ8_HANDLER ( corvus_hdc_data_r ) { // Returns: // Nothing // -WRITE8_HANDLER ( corvus_hdc_data_w ) { - corvus_hdc_t *c = &corvus_hdc; - +WRITE8_MEMBER ( corvus_hdc_t::write ) { // // Received a byte -- check to see if we should really respond // - if((c->status & CONTROLLER_DIRECTION) != 0) { // System wrote to controller when controller wasn't listening + if((m_status & CONTROLLER_DIRECTION) != 0) { // System wrote to controller when controller wasn't listening logerror("corvus_hdc_data_w: Data register written when in Controller-to-Host mode (status: 0x%2.2x, data: 0x%2.2x)\n", - c->status, data); + m_status, data); return; } - if((c->status & CONTROLLER_BUSY) != 0) { // System wrote to controller when controller was busy + if((m_status & CONTROLLER_BUSY) != 0) { // System wrote to controller when controller was busy logerror("corvus_hdc_data_w: Data register written when controller not Ready (status: 0x%2.2x, data: 0x%2.2x)\n", - c->status, data); + m_status, data); return; } // // We're supposed to be paying attention. Make a decision about the data received // - if(c->offset == 0) { // First byte of a packet - LOG(("corvus_hdc_data_w: Received a byte with c->offset == 0. Processing as command: 0x%2.2x\n", data)); - c->invalid_command_flag = parse_hdc_command(data); - c->timeout_timer->reset((attotime::from_seconds(4))); - c->timeout_timer->enable(1); // Start our four-second timer - } else if(c->offset == 1 && c->awaiting_modifier) { // Second byte of a packet - LOG(("corvus_hdc_data_w: Received a byte while awaiting modifier with c->offset == 0. Processing as modifier: 0x%2.2x\n", data)); - c->awaiting_modifier = FALSE; - c->recv_bytes = corvus_cmd[c->buffer.command.code][data].recv_bytes; - c->xmit_bytes = corvus_cmd[c->buffer.command.code][data].xmit_bytes; + if(m_offset == 0) { // First byte of a packet + LOG(("corvus_hdc_data_w: Received a byte with m_offset == 0. Processing as command: 0x%2.2x\n", data)); + m_invalid_command_flag = parse_hdc_command(data); + m_timeout_timer->reset((attotime::from_seconds(4))); + m_timeout_timer->enable(1); // Start our four-second timer + } else if(m_offset == 1 && m_awaiting_modifier) { // Second byte of a packet + LOG(("corvus_hdc_data_w: Received a byte while awaiting modifier with m_offset == 0. Processing as modifier: 0x%2.2x\n", data)); + m_awaiting_modifier = false; + m_recv_bytes = corvus_cmd[m_buffer.command.code][data].recv_bytes; + m_xmit_bytes = corvus_cmd[m_buffer.command.code][data].xmit_bytes; } - c->buffer.raw_data[c->offset++] = data; + m_buffer.raw_data[m_offset++] = data; - assert(c->offset <= MAX_COMMAND_SIZE); // Something is wrong, or I undersized the buffer + assert(m_offset <= MAX_COMMAND_SIZE); // Something is wrong, or I undersized the buffer // // We now have enough information to make a decision whether to execute the command, respond with a fatal response // or just wait for more data. If we can do something, execute the command. Otherwise, just fall through and return // to the user with us Ready for more data and in Host-to-Controller mode. // - if(c->offset == c->recv_bytes) { // We've received enough data to process - corvus_process_command_packet(space.machine(), c->invalid_command_flag); + if(m_offset == m_recv_bytes) { // We've received enough data to process + corvus_process_command_packet(m_invalid_command_flag); } else { // // Reset the four-second timer since we received some data // - c->timeout_timer->reset((attotime::from_seconds(4))); + m_timeout_timer->reset((attotime::from_seconds(4))); // // Make the controller busy for a few microseconds while the command is processed // - c->status |= CONTROLLER_BUSY; - space.machine().scheduler().timer_set((attotime::from_usec(INTERBYTE_DELAY)), FUNC(corvus_hdc_callback), CALLBACK_SAME_MODE); + m_status |= CONTROLLER_BUSY; + m_cmd_timer->adjust(attotime::from_usec(INTERBYTE_DELAY), CALLBACK_SAME_MODE); } }