Previous 199869 Revisions Next

r28764 Thursday 20th March, 2014 at 20:24:48 UTC by Curt Coder
(MESS) corvushd: Converted to a device. (nw)
[src/emu/bus/ieee488]hardbox.c hardbox.h softbox.c softbox.h
[src/mess/drivers]softbox.c
[src/mess/includes]corvushd.h softbox.h
[src/mess/machine]concept_exp.c concept_exp.h corvushd.c

trunk/src/emu/bus/ieee488/softbox.c
r28763r28764
1818
1919
2020#include "softbox.h"
21#include "bus/rs232/rs232.h"
22#include "cpu/z80/z80.h"
23#include "imagedev/harddriv.h"
24#include "includes/corvushd.h"
25#include "machine/i8251.h"
26#include "machine/i8255.h"
2721
2822
2923//**************************************************************************
r28763r28764
3630#define I8255_1_TAG     "ic16"
3731#define COM8116_TAG     "ic14"
3832#define RS232_TAG       "rs232"
33#define CORVUS_HDC_TAG   "corvus"
3934
4035
4136
r28763r28764
9388   AM_RANGE(0x0c, 0x0c) AM_WRITE(dbrg_w)
9489   AM_RANGE(0x10, 0x13) AM_DEVREADWRITE(I8255_0_TAG, i8255_device, read, write)
9590   AM_RANGE(0x14, 0x17) AM_DEVREADWRITE(I8255_1_TAG, i8255_device, read, write)
96   AM_RANGE(0x18, 0x18) AM_READWRITE_LEGACY(corvus_hdc_data_r, corvus_hdc_data_w)
91   AM_RANGE(0x18, 0x18) AM_DEVREADWRITE(CORVUS_HDC_TAG, corvus_hdc_t, read, write)
9792ADDRESS_MAP_END
9893
9994
r28763r28764
202197
203198   */
204199
205   UINT8 status = corvus_hdc_status_r(space, 0);
200   UINT8 status = m_hdc->status_r(space, 0);
206201   UINT8 data = 0;
207202
208203   data |= (status & CONTROLLER_BUSY) ? 0 : 0x10;
r28763r28764
282277   MCFG_COM8116_FR_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_rxc))
283278   MCFG_COM8116_FT_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_txc))
284279
280   MCFG_DEVICE_ADD(CORVUS_HDC_TAG, CORVUS_HDC, 0)
285281   MCFG_HARDDISK_ADD("harddisk1")
286282   MCFG_HARDDISK_ADD("harddisk2")
287283   MCFG_HARDDISK_ADD("harddisk3")
r28763r28764
345341   : device_t(mconfig, SOFTBOX, "PET SoftBox", tag, owner, clock, "pet_softbox", __FILE__),
346342      device_ieee488_interface(mconfig, *this),
347343      m_maincpu(*this, Z80_TAG),
348      m_dbrg(*this, COM8116_TAG)
344      m_dbrg(*this, COM8116_TAG),
345      m_hdc(*this, CORVUS_HDC_TAG)
349346{
350347}
351348
r28763r28764
356353
357354void softbox_device::device_start()
358355{
359   corvus_hdc_init(this);
360356}
361357
362358
trunk/src/emu/bus/ieee488/hardbox.c
r28763r28764
4343
4444
4545#include "hardbox.h"
46#include "cpu/z80/z80.h"
47#include "machine/i8251.h"
48#include "machine/i8255.h"
49#include "imagedev/harddriv.h"
50#include "includes/corvushd.h"
5146
5247
5348
r28763r28764
5853#define Z80_TAG         "z80"
5954#define I8255_0_TAG     "ic17"
6055#define I8255_1_TAG     "ic16"
56#define CORVUS_HDC_TAG   "corvus"
6157
6258
6359
r28763r28764
126122   ADDRESS_MAP_GLOBAL_MASK(0xff)
127123   AM_RANGE(0x10, 0x13) AM_DEVREADWRITE(I8255_0_TAG, i8255_device, read, write)
128124   AM_RANGE(0x14, 0x17) AM_DEVREADWRITE(I8255_1_TAG, i8255_device, read, write)
129   AM_RANGE(0x18, 0x18) AM_READWRITE_LEGACY(corvus_hdc_data_r, corvus_hdc_data_w)
125   AM_RANGE(0x18, 0x18) AM_DEVREADWRITE(CORVUS_HDC_TAG, corvus_hdc_t, read, write)
130126ADDRESS_MAP_END
131127
132128
r28763r28764
247243
248244   */
249245
250   UINT8 status = corvus_hdc_status_r(space, 0);
246   UINT8 status = m_hdc->status_r(space, 0);
251247   UINT8 data = 0;
252248
253249   data |= (status & CONTROLLER_BUSY) ? 0 : 0x10;
r28763r28764
302298   // devices
303299   MCFG_I8255A_ADD(I8255_0_TAG, ppi0_intf)
304300   MCFG_I8255A_ADD(I8255_1_TAG, ppi1_intf)
301
302   MCFG_DEVICE_ADD(CORVUS_HDC_TAG, CORVUS_HDC, 0)
305303   MCFG_HARDDISK_ADD("harddisk1")
306304   MCFG_HARDDISK_ADD("harddisk2")
307305   MCFG_HARDDISK_ADD("harddisk3")
r28763r28764
365363hardbox_device::hardbox_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
366364   : device_t(mconfig, HARDBOX, "HardBox", tag, owner, clock, "hardbox", __FILE__),
367365      device_ieee488_interface(mconfig, *this),
368      m_maincpu(*this, Z80_TAG)
366      m_maincpu(*this, Z80_TAG),
367      m_hdc(*this, CORVUS_HDC_TAG)
369368{
370369}
371370
r28763r28764
376375
377376void hardbox_device::device_start()
378377{
379   corvus_hdc_init(this);
380378}
381379
382380
trunk/src/emu/bus/ieee488/softbox.h
r28763r28764
1515#define __PET_SOFTBOX__
1616
1717#include "ieee488.h"
18#include "bus/rs232/rs232.h"
19#include "cpu/z80/z80.h"
20#include "imagedev/harddriv.h"
21#include "includes/corvushd.h"
1822#include "machine/com8116.h"
23#include "machine/i8251.h"
24#include "machine/i8255.h"
1925
2026
2127
r28763r28764
6571
6672   required_device<cpu_device> m_maincpu;
6773   required_device<com8116_device> m_dbrg;
74   required_device<corvus_hdc_t> m_hdc;
6875
6976   int m_ifc;  // Tracks previous state of IEEE-488 IFC line
7077};
trunk/src/emu/bus/ieee488/hardbox.h
r28763r28764
1515#define __PET_HARDBOX__
1616
1717#include "ieee488.h"
18#include "cpu/z80/z80.h"
19#include "machine/i8251.h"
20#include "machine/i8255.h"
21#include "imagedev/harddriv.h"
22#include "includes/corvushd.h"
1823
1924
2025
r28763r28764
6267   };
6368
6469   required_device<cpu_device> m_maincpu;
70   required_device<corvus_hdc_t> m_hdc;
6571
6672   int m_ifc;  // Tracks previous state of IEEE-488 IFC line
6773};
trunk/src/mess/machine/concept_exp.c
r28763r28764
1818#include "formats/basicdsk.h"
1919
2020// HDC controller
21#include "includes/corvushd.h"
2221#include "imagedev/harddriv.h"
2322
2423//**************************************************************************
r28763r28764
123122
124123concept_hdc_device::concept_hdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
125124               : device_t(mconfig, CONCEPT_HDC, "Corvus Concept HDC controller", tag, owner, clock, "concept_hdc", __FILE__),
126                  concept_exp_card_device( mconfig, *this )
125                  concept_exp_card_device( mconfig, *this ),
126                  m_hdc(*this, "hdc")
127127{
128128}
129129
r28763r28764
343343
344344void concept_hdc_device::device_start()
345345{
346   corvus_hdc_init(machine());
347346}
348347
349348
r28763r28764
358357   switch (offset)
359358   {
360359      case 0:     // HDC Data Register
361         return corvus_hdc_data_r(space, offset);
360         return m_hdc->read(space, offset);
362361
363362      case 1:     // HDC Status Register
364         return corvus_hdc_status_r(space, offset);
363         return m_hdc->status_r(space, offset);
365364   }
366365
367366   return 0;
r28763r28764
373372   switch (offset)
374373   {
375374      case 0:     // HDC Data Register
376         corvus_hdc_data_w(space, offset, data);
375         m_hdc->write(space, offset, data);
377376         break;
378377   }
379378}
r28763r28764
388387
389388
390389static MACHINE_CONFIG_FRAGMENT( hdc )
390   MCFG_DEVICE_ADD("hdc", CORVUS_HDC, 0)
391391   MCFG_HARDDISK_ADD( "harddisk1" )
392392MACHINE_CONFIG_END
393393
trunk/src/mess/machine/concept_exp.h
r28763r28764
33
44#include "emu.h"
55#include "machine/wd17xx.h"
6#include "includes/corvushd.h"
67
78// FIXME: Concept expansion ports should just use the Apple II Bus device!
89// The code below is outdated and inaccurate!
r28763r28764
110111   virtual machine_config_constructor device_mconfig_additions() const;
111112
112113protected:
114   required_device<corvus_hdc_t> m_hdc;
113115};
114116
115117
trunk/src/mess/machine/corvushd.c
r28763r28764
6868#include <ctype.h>
6969
7070
71const device_type CORVUS_HDC = &device_creator<corvus_hdc_t>;
72
73corvus_hdc_t::corvus_hdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
74   device_t(mconfig, CORVUS_HDC, "Corvus Flat Cable HDC", tag, owner, clock, "corvus_hdc", __FILE__),
75   m_status(0),
76   m_prep_mode(false),
77   m_sectors_per_track(0),
78   m_tracks_per_cylinder(0),
79   m_cylinders_per_drive(0),
80   m_offset(0),
81   m_awaiting_modifier(false),
82   m_recv_bytes(0),
83   m_xmit_bytes(0),
84   m_last_cylinder(0),
85   m_delay(0),
86   m_invalid_command_flag(false)
87{
88}
89
7190#define VERBOSE 0
7291#define VERBOSE_RESPONSES 0
7392#define VERSION 1
r28763r28764
83102
84103#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
85104#define LOG_BUFFER(p,s) do { if (VERBOSE) dump_buffer(p,s); } while (0)
86//
87// Structures
88//
89105
90// Sector addressing scheme for Rev B/H drives used in various commands (Called a DADR in the docs)
91struct dadr_t {
92   UINT8 address_msn_and_drive;// Most significant nibble: Most signficant nibble of sector address, Least significant nibble: Drive #
93   UINT8 address_lsb;          // Least significant byte of sector address
94   UINT8 address_mid;          // Middle byte of sector address
95};
96106
97// Controller structure
98struct corvus_hdc_t {
99   device_t *root_device;
100   UINT8   status;             // Controller status byte (DIRECTION + BUSY/READY)
101   char    prep_mode;          // Whether the controller is in Prep Mode or not
102   // Physical drive info
103   UINT8   sectors_per_track;  // Number of sectors per track for this drive
104   UINT8   tracks_per_cylinder;// Number of tracks per cylinder (heads)
105   UINT16  cylinders_per_drive;// Number of cylinders per drive
106   // Command Processing
107   UINT16  offset;             // Current offset into raw_data buffer
108   char    awaiting_modifier;  // We've received a two-byte command and we're waiting for the mod
109   UINT16  recv_bytes;         // Number of bytes expected to be received from Host
110   UINT16  xmit_bytes;         // Number of bytes expected to be transmitted to host
111   // Timing-related values
112   UINT16  last_cylinder;      // Last cylinder accessed - for calculating seek times
113   UINT32  delay;              // Delay in microseconds for callback
114   emu_timer   *timeout_timer; // Four-second timer for timeouts
115   UINT8   invalid_command_flag;       // I hate this, but it saves a lot more tests
116107
117   //
118   // Union below represents both an input and output buffer and interpretations of it
119   //
120   union {
121      //
122      // Raw Buffer
123      //
124      UINT8       raw_data[MAX_COMMAND_SIZE];
125      //
126      // Basic interpretation of code and modifier
127      //
128      struct {
129         UINT8   code;       // First byte of data is the code (command)
130         UINT8   modifier;   // Second byte of data is the modifier
131      } command;
132      //
133      // Basic response code
134      //
135      struct {
136         UINT8   status;     // Status code returned by the command executed
137      } single_byte_response;
138      //
139      // Read sector command
140      //
141      struct {
142         UINT8   code;       // Command code
143         dadr_t  dadr;       // Encoded drive and sector to read
144      } read_sector_command;
145      //
146      // 128-byte Read Sector response
147      //
148      struct {
149         UINT8   status;     // Status code returned by command executed
150         UINT8   data[128];  // Data returned from read
151      } read_128_response;
152      //
153      // 256-byte Read Sector response
154      //
155      struct {
156         UINT8   status;     // Status code returned by command executed
157         UINT8   data[256];  // Data returned from read
158      } read_256_reponse;
159      //
160      // 512-byte Read Sector response
161      //
162      struct {
163         UINT8   status;     // Status code returned by command executed
164         UINT8   data[512];  // Data returned by read
165      } read_512_response;
166      //
167      // Write 128-byte sector command
168      //
169      struct {
170         UINT8   code;       // Command code
171         dadr_t  dadr;       // Encoded drive and sector to write
172         UINT8   data[128];  // Data to be written
173      } write_128_command;
174      //
175      // Write 256-byte sector command
176      //
177      struct {
178         UINT8   code;       // Command code
179         dadr_t  dadr;       // Encoded drive and sector to write
180         UINT8   data[256];  // Data to be written
181      } write_256_command;
182      //
183      // Write 512-byte sector command
184      //
185      struct {
186         UINT8   code;       // Command Code
187         dadr_t  dadr;       // Encoded drive and sector to write
188         UINT8   data[512];  // Data to be written
189      } write_512_command;
190      //
191      // Semaphore Lock command
192      //
193      struct {
194         UINT8   code;       // Command code
195         UINT8   modifier;   // Command code modifier
196         UINT8   name[8];    // Semaphore name
197      } lock_semaphore_command;
198      //
199      // Semaphore Unlock command
200      //
201      struct {
202         UINT8   code;       // Command code
203         UINT8   modifier;   // Command code modifier
204         UINT8   name[8];    // Semaphore name
205      } unlock_semaphore_command;
206      //
207      // Semaphore Lock/Unlock response
208      //
209      struct {
210         UINT8   status;     // Disk access status
211         UINT8   result;     // Semaphore action status
212         UINT8   unused[10]; // Unused
213      } semaphore_locking_response;
214      //
215      // Initialize Semaphore table command
216      //
217      struct {
218         UINT8   code;       // Command code
219         UINT8   modifier;   // Command code modifier
220         UINT8   unused[3];  // Unused
221      } init_semaphore_command;
222      //
223      // Semaphore Status command
224      //
225      struct {
226         UINT8   code;       // Command code
227         UINT8   modifier;   // Command code modifier
228         UINT8   zero_three; // Don't ask me...
229         UINT8   unused[2];  // Unused
230      } semaphore_status_command;
231      //
232      // Semaphore Status response
233      //
234      struct {
235         UINT8   status;     // Disk access status
236         UINT8   table[256]; // Contents of the semaphore table
237      } semaphore_status_response;
238      //
239      // Get Drive Parameters command (0x10)
240      //
241      struct {
242         UINT8   code;       // Command code
243         UINT8   drive;      // Drive number (starts at 1)
244      } get_drive_parameters_command;
245      //
246      // Get Drive Parameters command response
247      //
248      struct {
249         UINT8   status;                     // Status code returned by command executed
250         UINT8   firmware[33];               // Firmware message
251         UINT8   rom_version;                // ROM Version
252         struct {
253            UINT8   sectors_per_track;      // Sectors/Track
254            UINT8   tracks_per_cylinder;    // Tracks/Cylinder (heads)
255            struct {
256               UINT8   lsb;
257               UINT8   msb;
258            } cylinders_per_drive;          // Byte-flipped Cylinders/Drive
259         } track_info;
260         struct {
261            UINT8   lsb;                    // Least significant byte
262            UINT8   midb;                   // Middle byte
263            UINT8   msb;                    // Most significant byte
264         } capacity;                         // 24-bit value, byte-flipped (lsb..msb)
265         UINT8   unused[16];
266         UINT8   interleave;                 // Interleave factor
267         struct {
268            UINT8   mux_parameters[12];
269            UINT8   pipe_name_table_ptr[2]; // Pointer to table of 64 entries, 8 bytes each (table of names)
270            UINT8   pipe_ptr_table_ptr[2];  // Pointer to table of 64 entries, 8 bytes each.  See pp. 29 - Mass Storage GTI
271            UINT8   pipe_area_size[2];      // Size of pipe area (lsb, msb)
272            struct {
273               UINT8   track_offset[2];
274            } vdo_table[7];                 // Virtual drive table
275            UINT8   lsi11_vdo_table[8];
276            UINT8   lsi11_spare_table[8];
277         } table_info;
278         UINT8   drive_number;               // Physical drive number
279         struct {
280            UINT8   lsb;                    // Least
281            UINT8   midb;                   // Middle
282            UINT8   msb;                    // Most
283         } physical_capacity;                // Physical capacity of drive
284      } drive_param_response;
285      //
286      // 2-byte Boot command (0x14)
287      //
288      struct {
289         UINT8   code;       // Command code
290         UINT8   boot_block; // Which boot block to read (0-7)
291      } old_boot_command;
292      //
293      // Read Firmware command (Prep Mode 0x32)
294      //
295      struct {
296         UINT8   code;       // Command Code
297         UINT8   encoded_h_s;// Encoded Head (bits 7-5) / Sector (bits 4-0)
298      } read_firmware_command;
299      //
300      // Write Firmware command (Prep Mode 0x33)
301      //
302      struct {
303         UINT8   code;       // Command Code
304         UINT8   encoded_h_s; // Encoded Head (bits 7-5) / Sector (bits 4-0)
305         UINT8   data[512];  // Data to be written
306      } write_firmware_command;
307      //
308      // Format Drive command (Prep Mode 0x01)
309      //
310      // Note that the following is a BLATANT ASSUMPTION.  Technically, the Format Drive command
311      // uses a variable-length buffer for the pattern.  Unfortunately, the docs don't explain how to determine the
312      // length of the buffer passed.  I assume it's a timeout; however, the docs happen to say that
313      // all Corvus diagnostic programs send 513 bytes total, including the command, so I'm going with that.
314      //
315      struct {
316         UINT8   code;       // Command Code
317         UINT8   pattern[512]; // Pattern to be written
318      } format_drive_revbh_command;
319   } buffer;
320};
321
322// Structure of Block #1, the Disk Parameter Block
323struct disk_parameter_block_t {
324   struct {
325      UINT8   lsb;
326      UINT8   msb;
327   } spared_track[8];          // Spared track table (0xffff indicates end)
328   UINT8   interleave;         // Interleave factor
329   UINT8   reserved;
330   struct {
331      UINT8 track_offset[2];  // Virtual drive offsets (lsb, msb) 0xffff indicates unused
332   } vdo_table[7];
333   UINT8   lsi11_vdo_table[8];
334   UINT8   lsi11_spare_table[8];
335   UINT8   reserved2[432];
336   struct {
337      UINT8   lsb;
338      UINT8   msb;
339   } revh_spare_table[16];
340};
341
342// Structure of Block #3, the Constellation Parameter Block
343struct constellation_parameter_block_t {
344   UINT8   mux_parameters[12];
345   UINT8   pipe_name_table_ptr[2];
346   UINT8   pipe_ptr_table_ptr[2];
347   UINT8   pipe_area_size[2];
348   UINT8   reserved[470];
349   UINT8   software_protection[12];
350   UINT8   serial_number[12];
351};
352
353// Structure of Block #7, the Semaphore Table Block
354struct semaphore_table_block_t {
355   union {
356      UINT8   semaphore_table[256];           // Table consists of 256 bytes
357      struct {
358         UINT8   semaphore_name[8];          // Each semaphore name is 8 bytes
359      } semaphore_entry[32];                  // 32 Entries
360   } semaphore_block;
361   UINT8   unused[256];                        // Remaining half of block is unused
362};
363
364// Command size structure (number of bytes to xmit and recv for each command)
365struct corvus_cmd_t {
366   UINT16  recv_bytes;                         // Number of bytes from host for this command
367   UINT16  xmit_bytes;                         // Number of bytes to return to host
368};
369
370108//
371// Prototypes
372//
373static hard_disk_file *corvus_hdc_file(running_machine &machine, int id);
374static TIMER_CALLBACK(corvus_hdc_callback);
375
376//
377// Globals
378//
379static corvus_hdc_t corvus_hdc;                 // The controller itself
380static corvus_cmd_t corvus_cmd[0xf5][0xc1];     // Command sizes and their return sizes
381static corvus_cmd_t corvus_prep_cmd[0x82];      // Prep Command sizes and their return sizes
382
383
384
385//
386109// Dump_Buffer
387110//
388111// Dump a buffer to the error log in a nice format.
r28763r28764
394117// Returns:
395118//      nada
396119//
397static void dump_buffer(UINT8 *buffer, UINT16 length) {
120void corvus_hdc_t::dump_buffer(UINT8 *buffer, UINT16 length) {
398121   UINT16  offset;
399122   char    ascii_dump[16];
400123
r28763r28764
423146// Parse_HDC_Command
424147//
425148// Process the first byte received from the host.  Do some initial evaluation and
426// return either TRUE or FALSE as to whether the command was invalid or not.
149// return either true or false as to whether the command was invalid or not.
427150//
428151// Note that recv_bytes and xmit_bytes in the corvus_hdc structure are updated as
429152// a side-effect of this command, as is awaiting_modifier.
r28763r28764
432155//      data:   Initial byte received from the host in Host to Controller mode
433156//
434157// Returns:
435//      Whether the command was invalid or not (TRUE = invalid command)
158//      Whether the command was invalid or not (true = invalid command)
436159//
437static UINT8 parse_hdc_command(UINT8 data) {
438   corvus_hdc_t *c = &corvus_hdc;
160bool corvus_hdc_t::parse_hdc_command(UINT8 data) {
161   m_awaiting_modifier = false;               // This is the case by definition
439162
440   c->awaiting_modifier = FALSE;               // This is the case by definition
163   LOG(("parse_hdc_command: Called with data: 0x%2.2x, Prep mode is: %d\n", data, m_prep_mode));
441164
442   LOG(("parse_hdc_command: Called with data: 0x%2.2x, Prep mode is: %d\n", data, c->prep_mode));
443
444   if(!c->prep_mode) {
165   if(!m_prep_mode) {
445166      switch(data) {
446167         //
447168         // Single-byte commands - Non-Prep mode
r28763r28764
463184         case PARK_HEADS_OMNI:
464185         case ECHO:
465186         case PREP_MODE_SELECT:
466            c->recv_bytes = corvus_cmd[data][0].recv_bytes;
467            c->xmit_bytes = corvus_cmd[data][0].xmit_bytes;
187            m_recv_bytes = corvus_cmd[data][0].recv_bytes;
188            m_xmit_bytes = corvus_cmd[data][0].xmit_bytes;
468189            LOG(("parse_hdc_command: Single byte command recognized: 0x%2.2x, to recv: %d, to xmit: %d\n", data,
469               c->recv_bytes, c->xmit_bytes));
190               m_recv_bytes, m_xmit_bytes));
470191            break;
471192         //
472193         // Double-byte commands
r28763r28764
487208      //  case DELACTIVEUSR_OMNI_CODE:
488209      //  case DELACTIVENUM_OMNI_CODE:
489210      //  case FINDACTIVE_CODE:
490            c->awaiting_modifier = TRUE;
211            m_awaiting_modifier = true;
491212            LOG(("parse_hdc_command: Double byte command recognized: 0x%2.2x\n", data));
492213            break;
493214
494215         default:                            // This is an INVALID command
495            c->recv_bytes = 1;
496            c->xmit_bytes = 1;
216            m_recv_bytes = 1;
217            m_xmit_bytes = 1;
497218            LOG(("parse_hdc_command: Invalid command detected: 0x%2.2x\n", data));
498            return TRUE;
219            return true;
499220      }
500221   } else {
501222      switch(data) {
r28763r28764
509230         case PREP_VERIFY:
510231         case PREP_READ_FIRMWARE:
511232         case PREP_WRITE_FIRMWARE:
512            c->recv_bytes = corvus_prep_cmd[data].recv_bytes;
513            c->xmit_bytes = corvus_prep_cmd[data].xmit_bytes;
233            m_recv_bytes = corvus_prep_cmd[data].recv_bytes;
234            m_xmit_bytes = corvus_prep_cmd[data].xmit_bytes;
514235            LOG(("parse_hdc_command: Prep command recognized: 0x%2.2x, to recv: %d, to xmit: %d\n", data,
515               c->recv_bytes, c->xmit_bytes));
236               m_recv_bytes, m_xmit_bytes));
516237            break;
517238
518239         default:                            // This is an INVALID prep command
519            c->recv_bytes = 1;
520            c->xmit_bytes = 1;
240            m_recv_bytes = 1;
241            m_xmit_bytes = 1;
521242            LOG(("parse_hdc_command: Invalid Prep command detected: 0x%2.2x\n", data));
522            return TRUE;
243            return true;
523244      }
524245   }   // if(!prep_mode)
525246
526   return FALSE;
247   return false;
527248}
528249
529250
r28763r28764
542263// Returns:
543264//      status: Command status
544265//
545static UINT8 corvus_write_sector(running_machine &machine, UINT8 drv, UINT32 sector, UINT8 *buffer, int len) {
546   corvus_hdc_t
547         *c = &corvus_hdc;
266UINT8 corvus_hdc_t::corvus_write_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len) {
548267   hard_disk_file
549268         *disk;              // Structures for interface to CHD routines
550269   UINT8   tbuffer[512];       // Buffer to hold an entire sector
r28763r28764
552271
553272   LOG(("corvus_write_sector: Write Drive: %d, physical sector: 0x%5.5x\n", drv, sector));
554273
555   disk = corvus_hdc_file(machine, drv);
274   disk = corvus_hdc_file(drv);
556275   if(!disk) {
557276      logerror("corvus_write_sector: Failure returned by corvus_hdc_file(%d)\n", drv);
558277      return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE;
r28763r28764
561280   //
562281   // Calculate what cylinder the sector resides on for timing purposes
563282   //
564   cylinder = (double) sector / (double) c->sectors_per_track / (double) c->tracks_per_cylinder;
565   c->delay = abs(c->last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY;
283   cylinder = (double) sector / (double) m_sectors_per_track / (double) m_tracks_per_cylinder;
284   m_delay = abs(m_last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY;
566285
567286   //
568287   // Corvus supports write sizes of 128, 256 and 512 bytes.  In the case of a write smaller than
r28763r28764
575294   } else {
576295      hard_disk_read(disk, sector, tbuffer);      // Read the existing data into our temporary buffer
577296      memcpy(tbuffer, buffer, len);                   // Overlay the data with the buffer passed
578      c->delay += INTERSECTOR_DELAY;                  // Add another delay because of the Read / Write
297      m_delay += INTERSECTOR_DELAY;                  // Add another delay because of the Read / Write
579298      hard_disk_write(disk, sector, tbuffer);     // Re-write the data
580299   }
581300
582   c->last_cylinder = cylinder;
301   m_last_cylinder = cylinder;
583302
584303   LOG(("corvus_write_sector: Full sector dump on a write of %d bytes follows:\n", len));
585304   LOG_BUFFER(len == 512 ? buffer : tbuffer, 512);
r28763r28764
602321// Returns:
603322//      status: Corvus status
604323//
605static UINT8 corvus_write_logical_sector(running_machine &machine, dadr_t *dadr, UINT8 *buffer, int len) {
606   corvus_hdc_t
607         *c = &corvus_hdc;
324UINT8 corvus_hdc_t::corvus_write_logical_sector(dadr_t *dadr, UINT8 *buffer, int len) {
608325   UINT8   status;             // Status returned from Physical Sector read
609326   UINT8   drv;                // Drive number (1 - 15)
610327   UINT32  sector;             // Sector number on drive
r28763r28764
623340   LOG(("corvus_write_logical_sector: Writing based on DADR: 0x%6.6x, logical sector: 0x%5.5x, drive: %d\n",
624341      dadr->address_msn_and_drive << 16 | dadr->address_lsb << 8 | dadr->address_mid, sector, drv));
625342
626   // Set up the global corvus_hdc so c->tracks_per_cylinder and c->sectors_per_track are valid
627   corvus_hdc_file(machine, drv);
343   // Set up the global corvus_hdc so m_tracks_per_cylinder and m_sectors_per_track are valid
344   corvus_hdc_file(drv);
628345
629346   //
630347   // Shift the logical sector address forward by the number of firmware cylinders (2) + the number of spare tracks (7)
631348   //
632   sector += (c->tracks_per_cylinder * c->sectors_per_track * 2) + (SPARE_TRACKS * c->sectors_per_track);
349   sector += (m_tracks_per_cylinder * m_sectors_per_track * 2) + (SPARE_TRACKS * m_sectors_per_track);
633350
634   status = corvus_write_sector(machine, drv, sector, buffer, len);
351   status = corvus_write_sector(drv, sector, buffer, len);
635352
636353   if(status != STAT_SUCCESS)
637      c->xmit_bytes = 1;
354      m_xmit_bytes = 1;
638355
639356   return status;
640357}
r28763r28764
654371// Returns:
655372//      status: Corvus status
656373//
657static UINT8 corvus_read_sector(running_machine &machine, UINT8 drv, UINT32 sector, UINT8 *buffer, int len) {
658   corvus_hdc_t
659         *c = &corvus_hdc;
374UINT8 corvus_hdc_t::corvus_read_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len) {
660375   hard_disk_file
661376         *disk;              // Structures for interface to CHD routines
662377   UINT8   tbuffer[512];       // Buffer to store full sector results in
r28763r28764
664379
665380   LOG(("corvus_read_sector: Read Drive: %d, physical sector: 0x%5.5x\n", drv, sector));
666381
667   disk = corvus_hdc_file(machine, drv);
382   disk = corvus_hdc_file(drv);
668383   if(!disk) {
669384      logerror("corvus_read_sector: Failure returned by corvus_hdc_file(%d)\n", drv);
670385      return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE;
r28763r28764
673388   //
674389   // Calculate what cylinder the sector resides on for timing purposes
675390   //
676   cylinder = (double) sector / (double) c->sectors_per_track / (double) c->tracks_per_cylinder;
677   c->delay = abs(c->last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY;
391   cylinder = (double) sector / (double) m_sectors_per_track / (double) m_tracks_per_cylinder;
392   m_delay = abs(m_last_cylinder - cylinder) * TRACK_SEEK_TIME + INTERSECTOR_DELAY;
678393
679394   hard_disk_read(disk, sector, tbuffer);
680395
681396   memcpy(buffer, tbuffer, len);
682397
683   c->last_cylinder = cylinder;
398   m_last_cylinder = cylinder;
684399
685400   LOG(("corvus_read_sector: Data read follows:\n"));
686401   LOG_BUFFER(tbuffer, len);
r28763r28764
703418// Returns:
704419//      status: Corvus status
705420//
706static UINT8 corvus_read_logical_sector(running_machine &machine, dadr_t *dadr, UINT8 *buffer, int len) {
707   corvus_hdc_t
708         *c = &corvus_hdc;
421UINT8 corvus_hdc_t::corvus_read_logical_sector(dadr_t *dadr, UINT8 *buffer, int len) {
709422   UINT8   status;                             // Status returned from Physical Sector read
710423   UINT8   drv;                                // Drive number (1 - 15)
711424   UINT32  sector;                             // Sector number on drive
r28763r28764
724437   LOG(("corvus_read_logical_sector: Reading based on DADR: 0x%6.6x, logical sector: 0x%5.5x, drive: %d\n",
725438      dadr->address_msn_and_drive << 16 | dadr->address_lsb << 8 | dadr->address_mid, sector, drv));
726439
727   // Set up the global corvus_hdc so c->tracks_per_cylinder and c->sectors_per_track are valid
728   corvus_hdc_file(machine, drv);
440   // Set up the global corvus_hdc so m_tracks_per_cylinder and m_sectors_per_track are valid
441   corvus_hdc_file(drv);
729442
730443   //
731444   // Shift the logical sector address forward by the number of firmware cylinders (2) + the number of spare tracks (7)
732445   //
733   sector += (c->tracks_per_cylinder * c->sectors_per_track * 2) + (SPARE_TRACKS * c->sectors_per_track);
446   sector += (m_tracks_per_cylinder * m_sectors_per_track * 2) + (SPARE_TRACKS * m_sectors_per_track);
734447
735   status = corvus_read_sector(machine, drv, sector, buffer, len);
448   status = corvus_read_sector(drv, sector, buffer, len);
736449
737450   if(status != STAT_SUCCESS)
738      c->xmit_bytes = 1;
451      m_xmit_bytes = 1;
739452
740453   return status;
741454}
r28763r28764
756469// Side-effects:
757470//      Fills in the semaphore result code
758471//
759static UINT8 corvus_lock_semaphore(running_machine &machine, UINT8 *name) {
760   corvus_hdc_t
761         *c = &corvus_hdc;
472UINT8 corvus_hdc_t::corvus_lock_semaphore(UINT8 *name) {
762473   semaphore_table_block_t
763474         semaphore_table;
764475   UINT8   offset = 0;
765   UINT8   found = FALSE;
476   bool    found = false;
766477   UINT8   blank_offset = 32;  // Initialize to invalid offset
767478   UINT8   status;             // Status returned from Physical Sector read
768479
769480   //
770481   // Read the semaphore table from the drive
771482   //
772   status = corvus_read_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
483   status = corvus_read_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
773484   if(status != STAT_SUCCESS) {
774485      logerror("corvus_lock_semaphore: Error reading semaphore table, status: 0x%2.2x\n", status);
775      c->buffer.semaphore_locking_response.result = SEM_DISK_ERROR;
486      m_buffer.semaphore_locking_response.result = SEM_DISK_ERROR;
776487      return status;
777488   }
778489
r28763r28764
784495      if(blank_offset == 32 && strncmp((char *) &semaphore_table.semaphore_block.semaphore_entry[offset], "        ", 8) == 0)
785496         blank_offset = offset;
786497      if(strncmp((char *) &semaphore_table.semaphore_block.semaphore_entry[offset], (char *) name, 8) == 0) {
787         found = TRUE;
498         found = true;
788499         break;
789500      }
790501   } while( ++offset < 32 );
r28763r28764
799510   //
800511   if(!found) {
801512      if(blank_offset == 32) {
802         c->buffer.semaphore_locking_response.result = SEM_TABLE_FULL;                   // No space for the semaphore!
513         m_buffer.semaphore_locking_response.result = SEM_TABLE_FULL;                   // No space for the semaphore!
803514      } else {
804         c->buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_NOT_SET;          // It wasn't there already
515         m_buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_NOT_SET;          // It wasn't there already
805516         memcpy(&semaphore_table.semaphore_block.semaphore_entry[blank_offset], name, 8);// Stick it into the table
806         status = corvus_write_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
517         status = corvus_write_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
807518         if(status != STAT_SUCCESS) {
808519            logerror("corvus_lock_semaphore: Error updating semaphore table, status: 0x%2.2x\n", status);
809            c->buffer.semaphore_locking_response.result = SEM_DISK_ERROR;
520            m_buffer.semaphore_locking_response.result = SEM_DISK_ERROR;
810521            return status;
811522         }
812523      }
813524   } else {
814      c->buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_SET;                  // It's already locked -- sorry
525      m_buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_SET;                  // It's already locked -- sorry
815526   }
816527
817528   return STAT_SUCCESS;
r28763r28764
833544// Side-effects:
834545//      Fills in the semaphore result code
835546//
836static UINT8 corvus_unlock_semaphore(running_machine &machine, UINT8 *name) {
837   corvus_hdc_t
838         *c = &corvus_hdc;
547UINT8 corvus_hdc_t::corvus_unlock_semaphore(UINT8 *name) {
839548   semaphore_table_block_t
840549         semaphore_table;
841550   UINT8   offset = 0;
842   UINT8   found = FALSE;
551   bool    found = false;
843552   UINT8   status;             // Status returned from Physical Sector read
844553
845554   //
846555   // Read the semaphore table from the drive
847556   //
848   status = corvus_read_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
557   status = corvus_read_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
849558   if(status != STAT_SUCCESS) {
850559      logerror("corvus_unlock_semaphore: Error reading semaphore table, status: 0x%2.2x\n", status);
851      c->buffer.semaphore_locking_response.result = SEM_DISK_ERROR;
560      m_buffer.semaphore_locking_response.result = SEM_DISK_ERROR;
852561      return status;
853562   }
854563
r28763r28764
857566   //
858567   do {
859568      if(strncmp((char *) &semaphore_table.semaphore_block.semaphore_entry[offset], (char *) name, 8) == 0) {
860         found = TRUE;
569         found = true;
861570         break;
862571      }
863572   } while( ++offset < 32 );
r28763r28764
871580   // Once that's done, write the updated table to the disk
872581   //
873582   if(!found) {
874      c->buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_NOT_SET;              // It wasn't there already
583      m_buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_NOT_SET;              // It wasn't there already
875584   } else {
876      c->buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_SET;                  // It was there
585      m_buffer.semaphore_locking_response.result = SEM_PRIOR_STATE_SET;                  // It was there
877586      memcpy(&semaphore_table.semaphore_block.semaphore_entry[offset], "        ", 8);    // Clear it
878      status = corvus_write_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
587      status = corvus_write_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
879588      if(status != STAT_SUCCESS) {
880589         logerror("corvus_unlock_semaphore: Error updating semaphore table, status: 0x%2.2x\n", status);
881         c->buffer.semaphore_locking_response.result = SEM_DISK_ERROR;
590         m_buffer.semaphore_locking_response.result = SEM_DISK_ERROR;
882591         return status;
883592      }
884593   }
r28763r28764
900609//      Disk status
901610//
902611//
903static UINT8 corvus_init_semaphore_table( running_machine &machine ) {
612UINT8 corvus_hdc_t::corvus_init_semaphore_table() {
904613   semaphore_table_block_t
905614         semaphore_table;
906615   UINT8   status;
907616
908617   memset(semaphore_table.semaphore_block.semaphore_table, 0x20, 256);
909618
910   status = corvus_write_sector(machine, 0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
619   status = corvus_write_sector(0, 7, semaphore_table.semaphore_block.semaphore_table, 256);
911620   if(status != STAT_SUCCESS) {
912621      logerror("corvus_init_semaphore_table: Error updating semaphore table, status: 0x%2.2x\n", status);
913622      return status;
r28763r28764
929638// Returns:
930639//      Status of command
931640//
932static UINT8 corvus_get_drive_parameters(running_machine &machine, UINT8 drv) {
933   corvus_hdc_t
934         *c = &corvus_hdc;
641UINT8 corvus_hdc_t::corvus_get_drive_parameters(UINT8 drv) {
935642   UINT16  capacity;                           // Number of usable 512-byte blocks
936643   UINT16  raw_capacity;                       // Number of actual 512-byte blocks
937644   union {
r28763r28764
953660   //
954661   drv -= 1;                                   // Internally, drives start at 0
955662
956   if ( ! corvus_hdc_file( machine, drv ) )
663   if ( ! corvus_hdc_file( drv ) )
957664   {
958665      logerror("corvus_get_drive_parameters: Attempt to retrieve parameters from non-existant drive: %d\n", drv);
959      c->xmit_bytes = 1;
666      m_xmit_bytes = 1;
960667      return STAT_FATAL_ERR | STAT_DRIVE_NOT_ONLINE;
961668   }
962669
963670   //
964671   // Read the Disk Parameter Block (Sector 1) from the drive
965672   //
966   status = corvus_read_sector(machine, drv, 1, raw_disk_parameter_block.buffer, 512);
673   status = corvus_read_sector(drv, 1, raw_disk_parameter_block.buffer, 512);
967674   if(status != STAT_SUCCESS) {
968675      logerror("corvus_get_drive_parameters: Error status returned reading Disk Parameter Block -- status: 0x%2.2x\n", status);
969      c->xmit_bytes = 1;
676      m_xmit_bytes = 1;
970677      return status;
971678   }
972679
973680   //
974681   // Read the Constellation Parameter Block (Sector 3) from the drive
975682   //
976   status = corvus_read_sector(machine, drv, 3, raw_constellation_parameter_block.buffer, 512);
683   status = corvus_read_sector(drv, 3, raw_constellation_parameter_block.buffer, 512);
977684   if(status != STAT_SUCCESS) {
978685      logerror("corvus_get_drive_parameters: Error status returned reading Constellation Parameter Block -- status: 0x%2.2x\n", status);
979      c->xmit_bytes = 1;
686      m_xmit_bytes = 1;
980687      return status;
981688   }
982689
983690   //
984691   // Build up the parameter packet
985692   //
986   strcpy((char *) c->buffer.drive_param_response.firmware, "V18.4AP   -- CONST II - 11/82  %");   // Pulled from some firmware...
987   c->buffer.drive_param_response.rom_version = VERSION;
988   c->buffer.drive_param_response.track_info.sectors_per_track = c->sectors_per_track;
989   c->buffer.drive_param_response.track_info.tracks_per_cylinder = c->tracks_per_cylinder;
990   c->buffer.drive_param_response.track_info.cylinders_per_drive.msb = (c->cylinders_per_drive & 0xff00) >> 8;
991   c->buffer.drive_param_response.track_info.cylinders_per_drive.lsb = (c->cylinders_per_drive & 0x00ff);
693   strcpy((char *) m_buffer.drive_param_response.firmware, "V18.4AP   -- CONST II - 11/82  %");   // Pulled from some firmware...
694   m_buffer.drive_param_response.rom_version = VERSION;
695   m_buffer.drive_param_response.track_info.sectors_per_track = m_sectors_per_track;
696   m_buffer.drive_param_response.track_info.tracks_per_cylinder = m_tracks_per_cylinder;
697   m_buffer.drive_param_response.track_info.cylinders_per_drive.msb = (m_cylinders_per_drive & 0xff00) >> 8;
698   m_buffer.drive_param_response.track_info.cylinders_per_drive.lsb = (m_cylinders_per_drive & 0x00ff);
992699
993700   //
994701   // Calculate the user capacity of the drive based on total capacity less spare tracks and firmware tracks
995702   //
996   raw_capacity = c->tracks_per_cylinder * c->cylinders_per_drive * c->sectors_per_track; // Total capacity
997   capacity = raw_capacity - ((c->tracks_per_cylinder * c->sectors_per_track * 2) + (SPARE_TRACKS * c->sectors_per_track));
998   c->buffer.drive_param_response.capacity.msb = (capacity & 0xff0000) >> 16;
999   c->buffer.drive_param_response.capacity.midb = (capacity & 0x00ff00) >> 8;
1000   c->buffer.drive_param_response.capacity.lsb = (capacity & 0x0000ff);
703   raw_capacity = m_tracks_per_cylinder * m_cylinders_per_drive * m_sectors_per_track; // Total capacity
704   capacity = raw_capacity - ((m_tracks_per_cylinder * m_sectors_per_track * 2) + (SPARE_TRACKS * m_sectors_per_track));
705   m_buffer.drive_param_response.capacity.msb = (capacity & 0xff0000) >> 16;
706   m_buffer.drive_param_response.capacity.midb = (capacity & 0x00ff00) >> 8;
707   m_buffer.drive_param_response.capacity.lsb = (capacity & 0x0000ff);
1001708
1002709   //
1003710   // Fill in the information from the Disk Parameter Block and Constellation Parameter Block
1004711   //
1005   c->buffer.drive_param_response.interleave = raw_disk_parameter_block.dpb.interleave;
1006   memcpy(c->buffer.drive_param_response.table_info.mux_parameters, raw_constellation_parameter_block.cpb.mux_parameters, 12);
1007   memcpy(c->buffer.drive_param_response.table_info.pipe_name_table_ptr,
712   m_buffer.drive_param_response.interleave = raw_disk_parameter_block.dpb.interleave;
713   memcpy(m_buffer.drive_param_response.table_info.mux_parameters, raw_constellation_parameter_block.cpb.mux_parameters, 12);
714   memcpy(m_buffer.drive_param_response.table_info.pipe_name_table_ptr,
1008715      raw_constellation_parameter_block.cpb.pipe_name_table_ptr, 2);
1009   memcpy(c->buffer.drive_param_response.table_info.pipe_ptr_table_ptr,
716   memcpy(m_buffer.drive_param_response.table_info.pipe_ptr_table_ptr,
1010717      raw_constellation_parameter_block.cpb.pipe_ptr_table_ptr, 2);
1011   memcpy(c->buffer.drive_param_response.table_info.pipe_area_size, raw_constellation_parameter_block.cpb.pipe_area_size, 2);
1012   memcpy(c->buffer.drive_param_response.table_info.vdo_table, raw_disk_parameter_block.dpb.vdo_table, 14);
1013   memcpy(c->buffer.drive_param_response.table_info.lsi11_vdo_table, raw_disk_parameter_block.dpb.lsi11_vdo_table, 8);
1014   memcpy(c->buffer.drive_param_response.table_info.lsi11_spare_table, raw_disk_parameter_block.dpb.lsi11_spare_table, 8);
718   memcpy(m_buffer.drive_param_response.table_info.pipe_area_size, raw_constellation_parameter_block.cpb.pipe_area_size, 2);
719   memcpy(m_buffer.drive_param_response.table_info.vdo_table, raw_disk_parameter_block.dpb.vdo_table, 14);
720   memcpy(m_buffer.drive_param_response.table_info.lsi11_vdo_table, raw_disk_parameter_block.dpb.lsi11_vdo_table, 8);
721   memcpy(m_buffer.drive_param_response.table_info.lsi11_spare_table, raw_disk_parameter_block.dpb.lsi11_spare_table, 8);
1015722
1016   c->buffer.drive_param_response.drive_number = drv + 1;
1017   c->buffer.drive_param_response.physical_capacity.msb = (raw_capacity & 0xff0000) >> 16;
1018   c->buffer.drive_param_response.physical_capacity.midb = (raw_capacity & 0x00ff00) >> 8;
1019   c->buffer.drive_param_response.physical_capacity.lsb = (raw_capacity & 0x0000ff);
723   m_buffer.drive_param_response.drive_number = drv + 1;
724   m_buffer.drive_param_response.physical_capacity.msb = (raw_capacity & 0xff0000) >> 16;
725   m_buffer.drive_param_response.physical_capacity.midb = (raw_capacity & 0x00ff00) >> 8;
726   m_buffer.drive_param_response.physical_capacity.lsb = (raw_capacity & 0x0000ff);
1020727
1021728   LOG(("corvus_get_drive_parameters: Drive Parameter packet follows:\n"));
1022   LOG_BUFFER(c->buffer.raw_data, 110);
729   LOG_BUFFER(m_buffer.raw_data, 110);
1023730
1024731   return STAT_SUCCESS;
1025732}
r28763r28764
1037744// Returns:
1038745//      status: Status of read operation
1039746//
1040static UINT8 corvus_read_boot_block(running_machine &machine, UINT8 block) {
1041   corvus_hdc_t    *c = &corvus_hdc;           // Pick up global controller structure
1042
747UINT8 corvus_hdc_t::corvus_read_boot_block(UINT8 block) {
1043748   LOG(("corvus_read_boot_block: Reading boot block: %d\n", block));
1044749
1045   return corvus_read_sector(machine, 0, 25 + block, c->buffer.read_512_response.data, 512);
750   return corvus_read_sector(0, 25 + block, m_buffer.read_512_response.data, 512);
1046751
1047752}
1048753
r28763r28764
1060765// Returns:
1061766//      Status of command
1062767//
1063static UINT8 corvus_read_firmware_block(running_machine &machine, UINT8 head, UINT8 sector) {
1064   corvus_hdc_t
1065         *c = &corvus_hdc;   // Pick up global controller structure
768UINT8 corvus_hdc_t::corvus_read_firmware_block(UINT8 head, UINT8 sector) {
1066769   UINT16  relative_sector;    // Relative sector on drive for Physical Read
1067770   UINT8   status;
1068771
1069   relative_sector = head * c->sectors_per_track + sector;
772   relative_sector = head * m_sectors_per_track + sector;
1070773
1071774   LOG(("corvus_read_firmware_block: Reading firmware head: 0x%2.2x, sector: 0x%2.2x, relative_sector: 0x%2.2x\n",
1072775      head, sector, relative_sector));
1073776
1074   status = corvus_read_sector(machine, 0, relative_sector, c->buffer.read_512_response.data, 512);        // TODO: Which drive should Prep Mode talk to ???
777   status = corvus_read_sector(0, relative_sector, m_buffer.read_512_response.data, 512);        // TODO: Which drive should Prep Mode talk to ???
1075778   return status;
1076779}
1077780
r28763r28764
1090793// Returns:
1091794//      Status of command
1092795//
1093static UINT8 corvus_write_firmware_block(running_machine &machine, UINT8 head, UINT8 sector, UINT8 *buffer) {
1094   corvus_hdc_t
1095         *c = &corvus_hdc;   // Pick up global controller structure
796UINT8 corvus_hdc_t::corvus_write_firmware_block(UINT8 head, UINT8 sector, UINT8 *buffer) {
1096797   UINT16  relative_sector;    // Relative sector on drive for Physical Read
1097798   UINT8   status;
1098799
1099   relative_sector = head * c->sectors_per_track + sector;
800   relative_sector = head * m_sectors_per_track + sector;
1100801
1101802   LOG(("corvus_write_firmware_block: Writing firmware head: 0x%2.2x, sector: 0x%2.2x, relative_sector: 0x%2.2x\n",
1102803      head, sector, relative_sector));
1103804
1104   status = corvus_write_sector(machine, 0, relative_sector, buffer, 512); // TODO: Which drive should Prep Mode talk to ???
805   status = corvus_write_sector(0, relative_sector, buffer, 512); // TODO: Which drive should Prep Mode talk to ???
1105806   return status;
1106807}
1107808
r28763r28764
1118819// Returns:
1119820//      Status of command
1120821//
1121static UINT8 corvus_format_drive(running_machine &machine, UINT8 *pattern, UINT16 len) {
1122   corvus_hdc_t
1123         *c = &corvus_hdc;
822UINT8 corvus_hdc_t::corvus_format_drive(UINT8 *pattern, UINT16 len) {
1124823   UINT32  sector;
1125824   UINT32  max_sector;
1126825   UINT8   status = 0;
1127826   UINT8   tbuffer[512];
1128827
1129   // Set up the global corvus_hdc so c->tracks_per_cylinder and c->sectors_per_track are valid
1130   corvus_hdc_file(machine, 0);
828   // Set up the global corvus_hdc so m_tracks_per_cylinder and m_sectors_per_track are valid
829   corvus_hdc_file(0);
1131830
1132   max_sector = c->sectors_per_track * c->tracks_per_cylinder * c->cylinders_per_drive;
831   max_sector = m_sectors_per_track * m_tracks_per_cylinder * m_cylinders_per_drive;
1133832
1134833   //
1135834   // If we were passed less than 512 bytes, fill the buffer up with the first byte passed (for Omnidrive Format command)
r28763r28764
1143842   LOG_BUFFER(pattern, 512);
1144843
1145844   for(sector = 0; sector <= max_sector; sector++) {
1146      status = corvus_write_sector(machine, 0, sector, pattern, 512);
845      status = corvus_write_sector(0, sector, pattern, 512);
1147846      if(status != STAT_SUCCESS) {
1148847         logerror("corvus_format_drive: Error while formatting drive in corvus_write_sector--sector: 0x%5.5x, status: 0x%x2.2x\n",
1149848            sector, status);
r28763r28764
1167866// Returns:
1168867//      hard_disk_file object
1169868//
1170static hard_disk_file *corvus_hdc_file(running_machine &machine, int id) {
1171   corvus_hdc_t
1172         *c = &corvus_hdc;
869hard_disk_file *corvus_hdc_t::corvus_hdc_file(int id) {
1173870   static const char *const tags[] = {
1174871      "harddisk1", "harddisk2", "harddisk3", "harddisk4"
1175872   };
1176   harddisk_image_device *img;
873   harddisk_image_device *img = siblingdevice<harddisk_image_device>(tags[id]);
1177874
1178   if (c->root_device)
1179      img = dynamic_cast<harddisk_image_device *>(c->root_device->subdevice(tags[id]));
1180   else
1181      img = dynamic_cast<harddisk_image_device *>(machine.device(tags[id]));
1182
1183875   if ( !img )
1184876      return NULL;
1185877
r28763r28764
1189881   // Pick up the Head/Cylinder/Sector info
1190882   hard_disk_file *file = img->get_hard_disk_file();
1191883   hard_disk_info *info = hard_disk_get_info(file);
1192   c->sectors_per_track = info->sectors;
1193   c->tracks_per_cylinder = info->heads;
1194   c->cylinders_per_drive = info->cylinders;
884   m_sectors_per_track = info->sectors;
885   m_tracks_per_cylinder = info->heads;
886   m_cylinders_per_drive = info->cylinders;
1195887
1196888   LOG(("corvus_hdc_file: Attached to drive %u image: H:%d, C:%d, S:%d\n", id, info->heads, info->cylinders, info->sectors));
1197889
r28763r28764
1211903// Returns:
1212904//      Nothing
1213905//
1214static void corvus_process_command_packet(running_machine &machine, UINT8 invalid_command_flag) {
1215   corvus_hdc_t    *c = &corvus_hdc;
1216
906void corvus_hdc_t::corvus_process_command_packet(bool invalid_command_flag) {
1217907   if (VERBOSE_RESPONSES)
1218908   {
1219909      LOG(("corvus_hdc_data_w: Complete packet received.  Dump follows:\n"));
1220      LOG_BUFFER(c->buffer.raw_data, c->offset);
910      LOG_BUFFER(m_buffer.raw_data, m_offset);
1221911   }
1222912
1223913   if(!invalid_command_flag) {
1224      if(!c->prep_mode) {
1225         switch(c->buffer.command.code) {
914      if(!m_prep_mode) {
915         switch(m_buffer.command.code) {
1226916            //
1227917            // Read / Write Chunk commands
1228918            //
1229919            case READ_CHUNK_128:
1230               c->buffer.read_128_response.status =
1231                  corvus_read_logical_sector(machine, &c->buffer.read_sector_command.dadr, c->buffer.read_128_response.data, 128);
920               m_buffer.read_128_response.status =
921                  corvus_read_logical_sector(&m_buffer.read_sector_command.dadr, m_buffer.read_128_response.data, 128);
1232922               break;
1233923            case READ_SECTOR_256:
1234924            case READ_CHUNK_256:
1235               c->buffer.read_256_reponse.status =
1236                  corvus_read_logical_sector(machine, &c->buffer.read_sector_command.dadr, c->buffer.read_256_reponse.data, 256);
925               m_buffer.read_256_reponse.status =
926                  corvus_read_logical_sector(&m_buffer.read_sector_command.dadr, m_buffer.read_256_reponse.data, 256);
1237927               break;
1238928            case READ_CHUNK_512:
1239               c->buffer.read_512_response.status =
1240                  corvus_read_logical_sector(machine, &c->buffer.read_sector_command.dadr, c->buffer.read_512_response.data, 512);
929               m_buffer.read_512_response.status =
930                  corvus_read_logical_sector(&m_buffer.read_sector_command.dadr, m_buffer.read_512_response.data, 512);
1241931               break;
1242932            case WRITE_CHUNK_128:
1243               c->buffer.single_byte_response.status =
1244                  corvus_write_logical_sector(machine, &c->buffer.write_128_command.dadr, c->buffer.write_128_command.data, 128);
933               m_buffer.single_byte_response.status =
934                  corvus_write_logical_sector(&m_buffer.write_128_command.dadr, m_buffer.write_128_command.data, 128);
1245935               break;
1246936            case WRITE_SECTOR_256:
1247937            case WRITE_CHUNK_256:
1248               c->buffer.single_byte_response.status =
1249                  corvus_write_logical_sector(machine, &c->buffer.write_256_command.dadr, c->buffer.write_256_command.data, 256);
938               m_buffer.single_byte_response.status =
939                  corvus_write_logical_sector(&m_buffer.write_256_command.dadr, m_buffer.write_256_command.data, 256);
1250940               break;
1251941            case WRITE_CHUNK_512:
1252               c->buffer.single_byte_response.status =
1253                  corvus_write_logical_sector(machine, &c->buffer.write_512_command.dadr, c->buffer.write_512_command.data, 512);
942               m_buffer.single_byte_response.status =
943                  corvus_write_logical_sector(&m_buffer.write_512_command.dadr, m_buffer.write_512_command.data, 512);
1254944               break;
1255945            //
1256946            // Semaphore commands
r28763r28764
1259949         //  case SEMAPHORE_UNLOCK_CODE:
1260950            case SEMAPHORE_INIT_CODE:
1261951         //  case SEMAPHORE_STATUS_CODE:
1262               switch(c->buffer.command.modifier) {
952               switch(m_buffer.command.modifier) {
1263953                  case SEMAPHORE_LOCK_MOD:
1264                     c->buffer.semaphore_locking_response.status = corvus_lock_semaphore(machine, c->buffer.lock_semaphore_command.name);
954                     m_buffer.semaphore_locking_response.status = corvus_lock_semaphore(m_buffer.lock_semaphore_command.name);
1265955                     break;
1266956                  case SEMAPHORE_UNLOCK_MOD:
1267                     c->buffer.semaphore_locking_response.status =
1268                        corvus_unlock_semaphore(machine, c->buffer.unlock_semaphore_command.name);
957                     m_buffer.semaphore_locking_response.status =
958                        corvus_unlock_semaphore(m_buffer.unlock_semaphore_command.name);
1269959                     break;
1270960                  case SEMAPHORE_INIT_MOD:
1271                     c->buffer.single_byte_response.status = corvus_init_semaphore_table(machine);
961                     m_buffer.single_byte_response.status = corvus_init_semaphore_table();
1272962                     break;
1273963                  case SEMAPHORE_STATUS_MOD:
1274                     c->buffer.semaphore_status_response.status =
1275                        corvus_read_sector(machine, 0, 7, c->buffer.semaphore_status_response.table, 256);
964                     m_buffer.semaphore_status_response.status =
965                        corvus_read_sector(0, 7, m_buffer.semaphore_status_response.table, 256);
1276966                     break;
1277967                  default:
1278                     invalid_command_flag = TRUE;
968                     invalid_command_flag = true;
1279969               }
1280970               break;
1281971            //
1282972            // Miscellaneous commands
1283973            //
1284974            case BOOT:
1285               c->buffer.read_512_response.status =
1286                  corvus_read_boot_block(machine, c->buffer.old_boot_command.boot_block);
975               m_buffer.read_512_response.status =
976                  corvus_read_boot_block(m_buffer.old_boot_command.boot_block);
1287977               break;
1288978            case GET_DRIVE_PARAMETERS:
1289               c->buffer.drive_param_response.status =
1290                  corvus_get_drive_parameters(machine, c->buffer.get_drive_parameters_command.drive);
979               m_buffer.drive_param_response.status =
980                  corvus_get_drive_parameters(m_buffer.get_drive_parameters_command.drive);
1291981               break;
1292982            case PREP_MODE_SELECT:
1293               c->prep_mode = TRUE;
1294               c->buffer.single_byte_response.status = STAT_SUCCESS;
983               m_prep_mode = true;
984               m_buffer.single_byte_response.status = STAT_SUCCESS;
1295985               break;
1296986            default:
1297               c->xmit_bytes = 1;                      // Return a fatal status
1298               c->buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR;
987               m_xmit_bytes = 1;                      // Return a fatal status
988               m_buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR;
1299989               logerror("corvus_hdc_data_w: Unimplemented command, returning FATAL FAULT status!\n");
1300990               break;
1301991         }
1302992      } else {    // In Prep mode
1303         switch(c->buffer.command.code) {
993         switch(m_buffer.command.code) {
1304994            case PREP_MODE_SELECT:
1305               c->prep_mode = TRUE;
1306               c->buffer.single_byte_response.status = STAT_SUCCESS;
995               m_prep_mode = true;
996               m_buffer.single_byte_response.status = STAT_SUCCESS;
1307997               break;
1308998            case PREP_RESET_DRIVE:
1309               c->prep_mode = FALSE;
1310               c->buffer.single_byte_response.status = STAT_SUCCESS;
999               m_prep_mode = false;
1000               m_buffer.single_byte_response.status = STAT_SUCCESS;
13111001               break;
13121002            case PREP_READ_FIRMWARE:
1313               c->buffer.drive_param_response.status =
1314                  corvus_read_firmware_block(machine, (c->buffer.read_firmware_command.encoded_h_s & 0xe0) >> 5,
1315                     c->buffer.read_firmware_command.encoded_h_s & 0x1f);
1003               m_buffer.drive_param_response.status =
1004                  corvus_read_firmware_block((m_buffer.read_firmware_command.encoded_h_s & 0xe0) >> 5,
1005                     m_buffer.read_firmware_command.encoded_h_s & 0x1f);
13161006               break;
13171007            case PREP_WRITE_FIRMWARE:
1318               c->buffer.drive_param_response.status =
1319                  corvus_write_firmware_block(machine, (c->buffer.write_firmware_command.encoded_h_s & 0xe0) >> 5,
1320                     c->buffer.write_firmware_command.encoded_h_s & 0x1f, c->buffer.write_firmware_command.data);
1008               m_buffer.drive_param_response.status =
1009                  corvus_write_firmware_block((m_buffer.write_firmware_command.encoded_h_s & 0xe0) >> 5,
1010                     m_buffer.write_firmware_command.encoded_h_s & 0x1f, m_buffer.write_firmware_command.data);
13211011               break;
13221012            case PREP_FORMAT_DRIVE:
1323               c->buffer.drive_param_response.status =
1324                  corvus_format_drive(machine, c->buffer.format_drive_revbh_command.pattern, c->offset - 512);
1013               m_buffer.drive_param_response.status =
1014                  corvus_format_drive(m_buffer.format_drive_revbh_command.pattern, m_offset - 512);
13251015               break;
13261016            default:
1327               c->xmit_bytes = 1;
1328               c->buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR;
1329               logerror("corvus_hdc_data_w: Unimplemented Prep command %02x, returning FATAL FAULT status!\n", c->buffer.command.code);
1017               m_xmit_bytes = 1;
1018               m_buffer.single_byte_response.status = STAT_FAULT | STAT_FATAL_ERR;
1019               logerror("corvus_hdc_data_w: Unimplemented Prep command %02x, returning FATAL FAULT status!\n", m_buffer.command.code);
13301020         }
13311021      }
13321022      if (VERBOSE_RESPONSES)
13331023      {
13341024         LOG(("corvus_hdc_data_w: Command execution complete, status: 0x%2.2x.  Response dump follows:\n",
1335            c->buffer.single_byte_response.status));
1336         LOG_BUFFER(c->buffer.raw_data, c->xmit_bytes);
1025            m_buffer.single_byte_response.status));
1026         LOG_BUFFER(m_buffer.raw_data, m_xmit_bytes);
13371027      }
13381028
13391029   } // if(!invalid_command_flag)
r28763r28764
13451035      //
13461036      // An Illegal command was detected (Truly invalid, not just unimplemented)
13471037      //
1348      c->buffer.single_byte_response.status =
1038      m_buffer.single_byte_response.status =
13491039         STAT_FATAL_ERR | STAT_ILL_CMD_OP_CODE;      // Respond with an Illegal Op Code
13501040
1351      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);
1041      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);
13521042   }
13531043   //
13541044   // Command execution complete, free up the controller
13551045   //
1356   c->offset = 0;                                  // Point to beginning of buffer for response
1046   m_offset = 0;                                  // Point to beginning of buffer for response
13571047
1358   LOG(("corvus_hdc_data_w: Setting one-time mame timer of %d microseconds to simulate disk function\n", c->delay));
1048   LOG(("corvus_hdc_data_w: Setting one-time mame timer of %d microseconds to simulate disk function\n", m_delay));
13591049
13601050   //
13611051   // Set up timers for command completion and timeout from host
13621052   //
1363   machine.scheduler().timer_set(attotime::from_usec(c->delay), FUNC(corvus_hdc_callback), CALLBACK_CTH_MODE);
1364   c->timeout_timer->enable(0);            // We've received enough data, disable the timeout timer
1053   //machine.scheduler().timer_set(attotime::from_usec(m_delay), FUNC(corvus_hdc_callback), CALLBACK_CTH_MODE);
1054   m_cmd_timer->adjust(attotime::from_usec(m_delay), CALLBACK_CTH_MODE);
1055   m_timeout_timer->enable(0);            // We've received enough data, disable the timeout timer
13651056
1366   c->delay = 0;                                   // Reset delay for next function
1057   m_delay = 0;                                   // Reset delay for next function
13671058}
13681059
13691060
r28763r28764
13791070// Returns:
13801071//      Nothing
13811072//
1382static TIMER_CALLBACK(corvus_hdc_callback)
1073void corvus_hdc_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
13831074{
13841075   int function = param;
1385   corvus_hdc_t *c = &corvus_hdc;
13861076
13871077   switch(function) {
13881078      case CALLBACK_CTH_MODE:
1389         c->status |= CONTROLLER_DIRECTION;              // Set to Controller-to-Host, Ready mode
1390         c->status &= ~(CONTROLLER_BUSY);
1079         m_status |= CONTROLLER_DIRECTION;              // Set to Controller-to-Host, Ready mode
1080         m_status &= ~(CONTROLLER_BUSY);
13911081
13921082         LOG(("corvus_hdc_callback: Callback executed with function CALLBACK_CTH_MODE\n"));
13931083
13941084         break;
13951085      case CALLBACK_HTC_MODE:
1396         c->status &= ~(CONTROLLER_DIRECTION |
1086         m_status &= ~(CONTROLLER_DIRECTION |
13971087            CONTROLLER_BUSY);                           // Set to Host-to-Controller, Ready mode
13981088
13991089         LOG(("corvus_hdc_callback: Callback executed with function CALLBACK_HTC_MODE\n"));
14001090
14011091         break;
14021092      case CALLBACK_SAME_MODE:
1403         c->status &= ~(CONTROLLER_BUSY);                // Set the controller to Ready mode
1093         m_status &= ~(CONTROLLER_BUSY);                // Set the controller to Ready mode
14041094
14051095         break;
14061096      case CALLBACK_TIMEOUT:                              // We reached a four-second timeout threshold
1407         if(c->offset < c->recv_bytes || (c->offset > c->recv_bytes && c->recv_bytes != 0)) {
1408            c->buffer.single_byte_response.status = STAT_TIMEOUT;
1409            c->status |= CONTROLLER_DIRECTION;
1410            c->status &= ~(CONTROLLER_BUSY);
1411            c->recv_bytes = 0;
1412            c->xmit_bytes = 1;
1097         if(m_offset < m_recv_bytes || (m_offset > m_recv_bytes && m_recv_bytes != 0)) {
1098            m_buffer.single_byte_response.status = STAT_TIMEOUT;
1099            m_status |= CONTROLLER_DIRECTION;
1100            m_status &= ~(CONTROLLER_BUSY);
1101            m_recv_bytes = 0;
1102            m_xmit_bytes = 1;
14131103            logerror("corvus_hdc_callback: Exceeded four-second timeout for data from host, resetting communications\n");
1414         } else { // if(c->recv_bytes == 0)                 This was a variable-size command
1104         } else { // if(m_recv_bytes == 0)                 This was a variable-size command
14151105            LOG(("corvus_hdc_callback: Executing variable-length command via four-second timeout\n"));
1416            corvus_process_command_packet(machine, 0);          // Process the command
1106            corvus_process_command_packet(0);          // Process the command
14171107         }
14181108         break;
14191109      default:
r28763r28764
14211111         assert(0);
14221112   }
14231113   if(function != CALLBACK_SAME_MODE) {
1424      c->timeout_timer->enable(0);                // Disable the four-second timer now that we're done
1114      m_timeout_timer->enable(0);                // Disable the four-second timer now that we're done
14251115   }
14261116}
14271117
r28763r28764
14381128// Returns:
14391129//      NULL if there's no file to attach to
14401130//
1441UINT8 corvus_hdc_init(running_machine &machine) {
1442   corvus_hdc_t            *c = &corvus_hdc;   // Pick up global controller structure
1131void corvus_hdc_t::device_start() {
1132   m_status &= ~(CONTROLLER_DIRECTION | CONTROLLER_BUSY); // Host-to-controller mode, Idle (awaiting command from Host mode)
1133   m_prep_mode = false;                       // We're not in Prep Mode
1134   m_offset = 0;                              // Buffer is empty
1135   m_awaiting_modifier = false;               // We're not in the middle of a two-byte command
1136   m_xmit_bytes = 0;                          // We don't have anything to say to the host
1137   m_recv_bytes = 0;                          // We aren't waiting on additional data from the host
14431138
1444   c->status &= ~(CONTROLLER_DIRECTION | CONTROLLER_BUSY); // Host-to-controller mode, Idle (awaiting command from Host mode)
1445   c->prep_mode = FALSE;                       // We're not in Prep Mode
1446   c->offset = 0;                              // Buffer is empty
1447   c->awaiting_modifier = FALSE;               // We're not in the middle of a two-byte command
1448   c->xmit_bytes = 0;                          // We don't have anything to say to the host
1449   c->recv_bytes = 0;                          // We aren't waiting on additional data from the host
1139   m_timeout_timer = timer_alloc(TIMER_TIMEOUT);  // Set up a timer to handle the four-second host-to-controller timeout
1140   m_timeout_timer->adjust(attotime::from_seconds(4), CALLBACK_TIMEOUT);
1141   m_timeout_timer->enable(0);        // Start this timer out disabled
14501142
1451   c->timeout_timer = machine.scheduler().timer_alloc(FUNC(corvus_hdc_callback));  // Set up a timer to handle the four-second host-to-controller timeout
1452   c->timeout_timer->adjust(attotime::from_seconds(4), CALLBACK_TIMEOUT);
1453   c->timeout_timer->enable(0);        // Start this timer out disabled
1143   m_cmd_timer = timer_alloc(TIMER_COMMAND);
14541144
14551145   //
14561146   // Define all of the packet sizes for the commands
r28763r28764
15511241   corvus_prep_cmd[PREP_WRITE_FIRMWARE].xmit_bytes = 1;
15521242
15531243   LOG(("corvus_hdc_init: Drive structures initialized\n"));
1554
1555   return TRUE;
15561244}
15571245
15581246
1559UINT8 corvus_hdc_init( device_t *device )
1560{
1561   corvus_hdc_t            *c = &corvus_hdc;   // Pick up global controller structure
1562
1563   c->root_device = device;
1564
1565   return corvus_hdc_init(device->machine());
1566}
1567
1568
15691247//
15701248// Corvus_HDC_Status_R
15711249//
r28763r28764
15771255// Returns:
15781256//      Value in the controller status register
15791257//
1580READ8_HANDLER ( corvus_hdc_status_r ) {
1581   corvus_hdc_t *c = &corvus_hdc;
1582
1583   return c->status;
1258READ8_MEMBER ( corvus_hdc_t::status_r ) {
1259   return m_status;
15841260}
15851261
15861262
r28763r28764
15981274// Returns:
15991275//      Value in the controller data register
16001276//
1601READ8_HANDLER ( corvus_hdc_data_r ) {
1602   corvus_hdc_t *c = &corvus_hdc;
1277READ8_MEMBER ( corvus_hdc_t::read ) {
16031278   UINT8 result;
16041279
1605   if((c->status & CONTROLLER_DIRECTION) == 0) {   // Check to see if we're in Controller-to-Host mode
1606      logerror("corvus_hdc_data_r: Data register read when in Host-to-Controller mode (status: 0x%2.2x)\n", c->status);
1280   if((m_status & CONTROLLER_DIRECTION) == 0) {   // Check to see if we're in Controller-to-Host mode
1281      logerror("corvus_hdc_data_r: Data register read when in Host-to-Controller mode (status: 0x%2.2x)\n", m_status);
16071282      return 0;
16081283   }
16091284
1610   if((c->status & CONTROLLER_BUSY) != 0) {        // Check to see if we're Busy
1611      logerror("corvus_hdc_data_r: Data register read when Busy (status: 0x%2.2x)\n", c->status);
1285   if((m_status & CONTROLLER_BUSY) != 0) {        // Check to see if we're Busy
1286      logerror("corvus_hdc_data_r: Data register read when Busy (status: 0x%2.2x)\n", m_status);
16121287      return 0;
16131288   }
16141289
1615   result = c->buffer.raw_data[c->offset++];
1290   result = m_buffer.raw_data[m_offset++];
16161291
1617   if(c->offset == c->xmit_bytes) {
1618      LOG(("corvus_hdc_data_r: Finished transmitting %d bytes of data.  Returning to idle mode.\n", c->xmit_bytes));
1292   if(m_offset == m_xmit_bytes) {
1293      LOG(("corvus_hdc_data_r: Finished transmitting %d bytes of data.  Returning to idle mode.\n", m_xmit_bytes));
16191294
1620      c->offset = 0;          // We've reached the end of valid data
1621      c->xmit_bytes = 0;      // We don't have anything more to say
1622      c->recv_bytes = 0;      // No active commands
1295      m_offset = 0;          // We've reached the end of valid data
1296      m_xmit_bytes = 0;      // We don't have anything more to say
1297      m_recv_bytes = 0;      // No active commands
16231298
1624      space.machine().scheduler().timer_set((attotime::from_usec(INTERBYTE_DELAY)), FUNC(corvus_hdc_callback), CALLBACK_HTC_MODE);
1299      m_cmd_timer->adjust(attotime::from_usec(INTERBYTE_DELAY), CALLBACK_HTC_MODE);
16251300
1626//      c->status &= ~(CONTROLLER_DIRECTION | CONTROLLER_BUSY); // Put us in Idle, Host-to-Controller mode
1301//      m_status &= ~(CONTROLLER_DIRECTION | CONTROLLER_BUSY); // Put us in Idle, Host-to-Controller mode
16271302   } else {
16281303      //
16291304      // Not finished with this packet.  Insert an interbyte delay and then let the host continue
16301305      //
1631      space.machine().scheduler().timer_set((attotime::from_usec(INTERBYTE_DELAY)), FUNC(corvus_hdc_callback), CALLBACK_SAME_MODE);
1306      m_cmd_timer->adjust(attotime::from_usec(INTERBYTE_DELAY), CALLBACK_SAME_MODE);
16321307   }
16331308
16341309   return result;
r28763r28764
16471322// Returns:
16481323//      Nothing
16491324//
1650WRITE8_HANDLER ( corvus_hdc_data_w ) {
1651   corvus_hdc_t    *c = &corvus_hdc;
1652
1325WRITE8_MEMBER ( corvus_hdc_t::write ) {
16531326   //
16541327   // Received a byte -- check to see if we should really respond
16551328   //
1656   if((c->status & CONTROLLER_DIRECTION) != 0) {       // System wrote to controller when controller wasn't listening
1329   if((m_status & CONTROLLER_DIRECTION) != 0) {       // System wrote to controller when controller wasn't listening
16571330      logerror("corvus_hdc_data_w: Data register written when in Controller-to-Host mode (status: 0x%2.2x, data: 0x%2.2x)\n",
1658         c->status, data);
1331         m_status, data);
16591332      return;
16601333   }
16611334
1662   if((c->status & CONTROLLER_BUSY) != 0) {            // System wrote to controller when controller was busy
1335   if((m_status & CONTROLLER_BUSY) != 0) {            // System wrote to controller when controller was busy
16631336      logerror("corvus_hdc_data_w: Data register written when controller not Ready (status: 0x%2.2x, data: 0x%2.2x)\n",
1664         c->status, data);
1337         m_status, data);
16651338      return;
16661339   }
16671340
16681341   //
16691342   // We're supposed to be paying attention.  Make a decision about the data received
16701343   //
1671   if(c->offset == 0)  {                                                   // First byte of a packet
1672      LOG(("corvus_hdc_data_w: Received a byte with c->offset == 0.  Processing as command: 0x%2.2x\n", data));
1673      c->invalid_command_flag = parse_hdc_command(data);
1674      c->timeout_timer->reset((attotime::from_seconds(4)));
1675      c->timeout_timer->enable(1);                                // Start our four-second timer
1676   } else if(c->offset == 1 && c->awaiting_modifier) {                     // Second byte of a packet
1677      LOG(("corvus_hdc_data_w: Received a byte while awaiting modifier with c->offset == 0.  Processing as modifier: 0x%2.2x\n", data));
1678      c->awaiting_modifier = FALSE;
1679      c->recv_bytes = corvus_cmd[c->buffer.command.code][data].recv_bytes;
1680      c->xmit_bytes = corvus_cmd[c->buffer.command.code][data].xmit_bytes;
1344   if(m_offset == 0)  {                                                   // First byte of a packet
1345      LOG(("corvus_hdc_data_w: Received a byte with m_offset == 0.  Processing as command: 0x%2.2x\n", data));
1346      m_invalid_command_flag = parse_hdc_command(data);
1347      m_timeout_timer->reset((attotime::from_seconds(4)));
1348      m_timeout_timer->enable(1);                                // Start our four-second timer
1349   } else if(m_offset == 1 && m_awaiting_modifier) {                     // Second byte of a packet
1350      LOG(("corvus_hdc_data_w: Received a byte while awaiting modifier with m_offset == 0.  Processing as modifier: 0x%2.2x\n", data));
1351      m_awaiting_modifier = false;
1352      m_recv_bytes = corvus_cmd[m_buffer.command.code][data].recv_bytes;
1353      m_xmit_bytes = corvus_cmd[m_buffer.command.code][data].xmit_bytes;
16811354   }
16821355
1683   c->buffer.raw_data[c->offset++] = data;
1356   m_buffer.raw_data[m_offset++] = data;
16841357
1685   assert(c->offset <= MAX_COMMAND_SIZE);                                  // Something is wrong, or I undersized the buffer
1358   assert(m_offset <= MAX_COMMAND_SIZE);                                  // Something is wrong, or I undersized the buffer
16861359
16871360   //
16881361   // We now have enough information to make a decision whether to execute the command, respond with a fatal response
16891362   // or just wait for more data.  If we can do something, execute the command.  Otherwise, just fall through and return
16901363   // to the user with us Ready for more data and in Host-to-Controller mode.
16911364   //
1692   if(c->offset == c->recv_bytes) {                        // We've received enough data to process
1693      corvus_process_command_packet(space.machine(), c->invalid_command_flag);
1365   if(m_offset == m_recv_bytes) {                        // We've received enough data to process
1366      corvus_process_command_packet(m_invalid_command_flag);
16941367   } else {
16951368      //
16961369      // Reset the four-second timer since we received some data
16971370      //
1698      c->timeout_timer->reset((attotime::from_seconds(4)));
1371      m_timeout_timer->reset((attotime::from_seconds(4)));
16991372
17001373      //
17011374      // Make the controller busy for a few microseconds while the command is processed
17021375      //
1703      c->status |= CONTROLLER_BUSY;
1704      space.machine().scheduler().timer_set((attotime::from_usec(INTERBYTE_DELAY)), FUNC(corvus_hdc_callback), CALLBACK_SAME_MODE);
1376      m_status |= CONTROLLER_BUSY;
1377      m_cmd_timer->adjust(attotime::from_usec(INTERBYTE_DELAY), CALLBACK_SAME_MODE);
17051378   }
17061379}
trunk/src/mess/includes/softbox.h
r28763r28764
2121#define I8255_1_TAG     "ic16"
2222#define COM8116_TAG     "ic14"
2323#define RS232_TAG       "rs232"
24#define CORVUS_HDC_TAG   "corvus"
2425
2526class softbox_state : public driver_device
2627{
r28763r28764
2930      : driver_device(mconfig, type, tag),
3031         m_maincpu(*this, Z80_TAG),
3132         m_dbrg(*this, COM8116_TAG),
32         m_ieee(*this, IEEE488_TAG)
33         m_ieee(*this, IEEE488_TAG),
34         m_hdc(*this, CORVUS_HDC_TAG)
3335   { }
3436
3537   required_device<cpu_device> m_maincpu;
3638   required_device<com8116_device> m_dbrg;
3739   required_device<ieee488_device> m_ieee;
40   required_device<corvus_hdc_t> m_hdc;
3841
3942   virtual void machine_start();
4043   virtual void device_reset_after_children();
trunk/src/mess/includes/corvushd.h
r28763r28764
1313#ifndef CORVUSHD_H_
1414#define CORVUSHD_H_
1515
16#include "emu.h"
17#include "imagedev/harddriv.h"
18#include <ctype.h>
1619
1720//
1821// Controller Commands
r28763r28764
171174#define CONTROLLER_BUSY         0x80    // Set = Busy, Clear = Ready
172175#define CONTROLLER_DIRECTION    0x40    // Set = Controller->Host, Clear = Host->Controller
173176
177#define MAX_COMMAND_SIZE 4096   // The maximum size of a command packet (the controller only has 5K of RAM...)
174178
175/*----------- defined in machine/corvushd.c -----------*/
179class corvus_hdc_t :  public device_t
180{
181public:
182   // construction/destruction
183   corvus_hdc_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
176184
177//
178// Prototypes
179//
180UINT8 corvus_hdc_init( running_machine &machine );
181UINT8 corvus_hdc_init( device_t *device );
182DECLARE_READ8_HANDLER ( corvus_hdc_status_r );
183DECLARE_READ8_HANDLER ( corvus_hdc_data_r );
184DECLARE_WRITE8_HANDLER ( corvus_hdc_data_w );
185   DECLARE_READ8_MEMBER( read );
186   DECLARE_WRITE8_MEMBER( write );
187   DECLARE_READ8_MEMBER( status_r );
185188
189protected:
190   // device-level overrides
191   virtual void device_start();
192   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
186193
194private:
195   enum
196   {
197      TIMER_TIMEOUT,
198      TIMER_COMMAND
199   };
200
201   // Sector addressing scheme for Rev B/H drives used in various commands (Called a DADR in the docs)
202   struct dadr_t {
203      UINT8 address_msn_and_drive;// Most significant nibble: Most signficant nibble of sector address, Least significant nibble: Drive #
204      UINT8 address_lsb;          // Least significant byte of sector address
205      UINT8 address_mid;          // Middle byte of sector address
206   };
207
208   UINT8   m_status;             // Controller status byte (DIRECTION + BUSY/READY)
209   bool    m_prep_mode;          // Whether the controller is in Prep Mode or not
210   // Physical drive info
211   UINT8   m_sectors_per_track;  // Number of sectors per track for this drive
212   UINT8   m_tracks_per_cylinder;// Number of tracks per cylinder (heads)
213   UINT16  m_cylinders_per_drive;// Number of cylinders per drive
214   // Command Processing
215   UINT16  m_offset;             // Current offset into raw_data buffer
216   bool    m_awaiting_modifier;  // We've received a two-byte command and we're waiting for the mod
217   UINT16  m_recv_bytes;         // Number of bytes expected to be received from Host
218   UINT16  m_xmit_bytes;         // Number of bytes expected to be transmitted to host
219   // Timing-related values
220   UINT16  m_last_cylinder;      // Last cylinder accessed - for calculating seek times
221   UINT32  m_delay;              // Delay in microseconds for callback
222   emu_timer   *m_timeout_timer; // Four-second timer for timeouts
223   emu_timer *m_cmd_timer;
224   bool   m_invalid_command_flag;       // I hate this, but it saves a lot more tests
225
226   //
227   // Union below represents both an input and output buffer and interpretations of it
228   //
229   union {
230      //
231      // Raw Buffer
232      //
233      UINT8       raw_data[MAX_COMMAND_SIZE];
234      //
235      // Basic interpretation of code and modifier
236      //
237      struct {
238         UINT8   code;       // First byte of data is the code (command)
239         UINT8   modifier;   // Second byte of data is the modifier
240      } command;
241      //
242      // Basic response code
243      //
244      struct {
245         UINT8   status;     // Status code returned by the command executed
246      } single_byte_response;
247      //
248      // Read sector command
249      //
250      struct {
251         UINT8   code;       // Command code
252         dadr_t  dadr;       // Encoded drive and sector to read
253      } read_sector_command;
254      //
255      // 128-byte Read Sector response
256      //
257      struct {
258         UINT8   status;     // Status code returned by command executed
259         UINT8   data[128];  // Data returned from read
260      } read_128_response;
261      //
262      // 256-byte Read Sector response
263      //
264      struct {
265         UINT8   status;     // Status code returned by command executed
266         UINT8   data[256];  // Data returned from read
267      } read_256_reponse;
268      //
269      // 512-byte Read Sector response
270      //
271      struct {
272         UINT8   status;     // Status code returned by command executed
273         UINT8   data[512];  // Data returned by read
274      } read_512_response;
275      //
276      // Write 128-byte sector command
277      //
278      struct {
279         UINT8   code;       // Command code
280         dadr_t  dadr;       // Encoded drive and sector to write
281         UINT8   data[128];  // Data to be written
282      } write_128_command;
283      //
284      // Write 256-byte sector command
285      //
286      struct {
287         UINT8   code;       // Command code
288         dadr_t  dadr;       // Encoded drive and sector to write
289         UINT8   data[256];  // Data to be written
290      } write_256_command;
291      //
292      // Write 512-byte sector command
293      //
294      struct {
295         UINT8   code;       // Command Code
296         dadr_t  dadr;       // Encoded drive and sector to write
297         UINT8   data[512];  // Data to be written
298      } write_512_command;
299      //
300      // Semaphore Lock command
301      //
302      struct {
303         UINT8   code;       // Command code
304         UINT8   modifier;   // Command code modifier
305         UINT8   name[8];    // Semaphore name
306      } lock_semaphore_command;
307      //
308      // Semaphore Unlock command
309      //
310      struct {
311         UINT8   code;       // Command code
312         UINT8   modifier;   // Command code modifier
313         UINT8   name[8];    // Semaphore name
314      } unlock_semaphore_command;
315      //
316      // Semaphore Lock/Unlock response
317      //
318      struct {
319         UINT8   status;     // Disk access status
320         UINT8   result;     // Semaphore action status
321         UINT8   unused[10]; // Unused
322      } semaphore_locking_response;
323      //
324      // Initialize Semaphore table command
325      //
326      struct {
327         UINT8   code;       // Command code
328         UINT8   modifier;   // Command code modifier
329         UINT8   unused[3];  // Unused
330      } init_semaphore_command;
331      //
332      // Semaphore Status command
333      //
334      struct {
335         UINT8   code;       // Command code
336         UINT8   modifier;   // Command code modifier
337         UINT8   zero_three; // Don't ask me...
338         UINT8   unused[2];  // Unused
339      } semaphore_status_command;
340      //
341      // Semaphore Status response
342      //
343      struct {
344         UINT8   status;     // Disk access status
345         UINT8   table[256]; // Contents of the semaphore table
346      } semaphore_status_response;
347      //
348      // Get Drive Parameters command (0x10)
349      //
350      struct {
351         UINT8   code;       // Command code
352         UINT8   drive;      // Drive number (starts at 1)
353      } get_drive_parameters_command;
354      //
355      // Get Drive Parameters command response
356      //
357      struct {
358         UINT8   status;                     // Status code returned by command executed
359         UINT8   firmware[33];               // Firmware message
360         UINT8   rom_version;                // ROM Version
361         struct {
362            UINT8   sectors_per_track;      // Sectors/Track
363            UINT8   tracks_per_cylinder;    // Tracks/Cylinder (heads)
364            struct {
365               UINT8   lsb;
366               UINT8   msb;
367            } cylinders_per_drive;          // Byte-flipped Cylinders/Drive
368         } track_info;
369         struct {
370            UINT8   lsb;                    // Least significant byte
371            UINT8   midb;                   // Middle byte
372            UINT8   msb;                    // Most significant byte
373         } capacity;                         // 24-bit value, byte-flipped (lsb..msb)
374         UINT8   unused[16];
375         UINT8   interleave;                 // Interleave factor
376         struct {
377            UINT8   mux_parameters[12];
378            UINT8   pipe_name_table_ptr[2]; // Pointer to table of 64 entries, 8 bytes each (table of names)
379            UINT8   pipe_ptr_table_ptr[2];  // Pointer to table of 64 entries, 8 bytes each.  See pp. 29 - Mass Storage GTI
380            UINT8   pipe_area_size[2];      // Size of pipe area (lsb, msb)
381            struct {
382               UINT8   track_offset[2];
383            } vdo_table[7];                 // Virtual drive table
384            UINT8   lsi11_vdo_table[8];
385            UINT8   lsi11_spare_table[8];
386         } table_info;
387         UINT8   drive_number;               // Physical drive number
388         struct {
389            UINT8   lsb;                    // Least
390            UINT8   midb;                   // Middle
391            UINT8   msb;                    // Most
392         } physical_capacity;                // Physical capacity of drive
393      } drive_param_response;
394      //
395      // 2-byte Boot command (0x14)
396      //
397      struct {
398         UINT8   code;       // Command code
399         UINT8   boot_block; // Which boot block to read (0-7)
400      } old_boot_command;
401      //
402      // Read Firmware command (Prep Mode 0x32)
403      //
404      struct {
405         UINT8   code;       // Command Code
406         UINT8   encoded_h_s;// Encoded Head (bits 7-5) / Sector (bits 4-0)
407      } read_firmware_command;
408      //
409      // Write Firmware command (Prep Mode 0x33)
410      //
411      struct {
412         UINT8   code;       // Command Code
413         UINT8   encoded_h_s; // Encoded Head (bits 7-5) / Sector (bits 4-0)
414         UINT8   data[512];  // Data to be written
415      } write_firmware_command;
416      //
417      // Format Drive command (Prep Mode 0x01)
418      //
419      // Note that the following is a BLATANT ASSUMPTION.  Technically, the Format Drive command
420      // uses a variable-length buffer for the pattern.  Unfortunately, the docs don't explain how to determine the
421      // length of the buffer passed.  I assume it's a timeout; however, the docs happen to say that
422      // all Corvus diagnostic programs send 513 bytes total, including the command, so I'm going with that.
423      //
424      struct {
425         UINT8   code;       // Command Code
426         UINT8   pattern[512]; // Pattern to be written
427      } format_drive_revbh_command;
428   } m_buffer;
429
430   // Structure of Block #1, the Disk Parameter Block
431   struct disk_parameter_block_t {
432      struct {
433         UINT8   lsb;
434         UINT8   msb;
435      } spared_track[8];          // Spared track table (0xffff indicates end)
436      UINT8   interleave;         // Interleave factor
437      UINT8   reserved;
438      struct {
439         UINT8 track_offset[2];  // Virtual drive offsets (lsb, msb) 0xffff indicates unused
440      } vdo_table[7];
441      UINT8   lsi11_vdo_table[8];
442      UINT8   lsi11_spare_table[8];
443      UINT8   reserved2[432];
444      struct {
445         UINT8   lsb;
446         UINT8   msb;
447      } revh_spare_table[16];
448   };
449
450   // Structure of Block #3, the Constellation Parameter Block
451   struct constellation_parameter_block_t {
452      UINT8   mux_parameters[12];
453      UINT8   pipe_name_table_ptr[2];
454      UINT8   pipe_ptr_table_ptr[2];
455      UINT8   pipe_area_size[2];
456      UINT8   reserved[470];
457      UINT8   software_protection[12];
458      UINT8   serial_number[12];
459   };
460
461   // Structure of Block #7, the Semaphore Table Block
462   struct semaphore_table_block_t {
463      union {
464         UINT8   semaphore_table[256];           // Table consists of 256 bytes
465         struct {
466            UINT8   semaphore_name[8];          // Each semaphore name is 8 bytes
467         } semaphore_entry[32];                  // 32 Entries
468      } semaphore_block;
469      UINT8   unused[256];                        // Remaining half of block is unused
470   };
471
472   // Command size structure (number of bytes to xmit and recv for each command)
473   struct corvus_cmd_t {
474      UINT16  recv_bytes;                         // Number of bytes from host for this command
475      UINT16  xmit_bytes;                         // Number of bytes to return to host
476   };
477
478   void dump_buffer(UINT8 *buffer, UINT16 length);
479   bool parse_hdc_command(UINT8 data);
480   UINT8 corvus_write_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len);
481   UINT8 corvus_write_logical_sector(dadr_t *dadr, UINT8 *buffer, int len);
482   UINT8 corvus_read_sector(UINT8 drv, UINT32 sector, UINT8 *buffer, int len);
483   UINT8 corvus_read_logical_sector(dadr_t *dadr, UINT8 *buffer, int len);
484   UINT8 corvus_lock_semaphore(UINT8 *name);
485   UINT8 corvus_unlock_semaphore(UINT8 *name);
486   UINT8 corvus_init_semaphore_table();
487   UINT8 corvus_get_drive_parameters(UINT8 drv);
488   UINT8 corvus_read_boot_block(UINT8 block);
489   UINT8 corvus_read_firmware_block(UINT8 head, UINT8 sector);
490   UINT8 corvus_write_firmware_block(UINT8 head, UINT8 sector, UINT8 *buffer);
491   UINT8 corvus_format_drive(UINT8 *pattern, UINT16 len);
492   hard_disk_file *corvus_hdc_file(int id);
493   void corvus_process_command_packet(bool local_invalid_command_flag);
494
495   corvus_cmd_t corvus_cmd[0xf5][0xc1];     // Command sizes and their return sizes
496   corvus_cmd_t corvus_prep_cmd[0x82];      // Prep Command sizes and their return sizes
497};
498
499
500// device type definition
501extern const device_type CORVUS_HDC;
502
187503#endif /* CORVUSHD_H_ */
trunk/src/mess/drivers/softbox.c
r28763r28764
138138   AM_RANGE(0x0c, 0x0c) AM_WRITE(dbrg_w)
139139   AM_RANGE(0x10, 0x13) AM_DEVREADWRITE(I8255_0_TAG, i8255_device, read, write)
140140   AM_RANGE(0x14, 0x17) AM_DEVREADWRITE(I8255_1_TAG, i8255_device, read, write)
141   AM_RANGE(0x18, 0x18) AM_READWRITE_LEGACY(corvus_hdc_data_r, corvus_hdc_data_w)
141   AM_RANGE(0x18, 0x18) AM_DEVREADWRITE(CORVUS_HDC_TAG, corvus_hdc_t, read, write)
142142ADDRESS_MAP_END
143143
144144
r28763r28764
276276
277277   */
278278
279   UINT8 status = corvus_hdc_status_r(space, 0);
279   UINT8 status = m_hdc->status_r(space, 0);
280280   UINT8 data = 0;
281281
282282   data |= (status & CONTROLLER_BUSY) ? 0 : 0x10;
r28763r28764
339339
340340void softbox_state::machine_start()
341341{
342   corvus_hdc_init(machine());
343342}
344343
345344
r28763r28764
414413   MCFG_COM8116_FT_HANDLER(DEVWRITELINE(I8251_TAG, i8251_device, write_txc))
415414
416415   MCFG_CBM_IEEE488_ADD("c8050")
416   
417   MCFG_DEVICE_ADD(CORVUS_HDC_TAG, CORVUS_HDC, 0)
417418   MCFG_HARDDISK_ADD("harddisk1")
418419   MCFG_HARDDISK_ADD("harddisk2")
419420   MCFG_HARDDISK_ADD("harddisk3")

Previous 199869 Revisions Next


© 1997-2024 The MAME Team