Previous 15994 Revisions Next

r8043 Saturday 15th May, 2010 at 07:31:10 UTC by Fabio Priuli
[TI99 family] Reimplementation of HDC9234 chip (smc92x4) for the HFDC controller. Now it supports all functions according to specifications (except tape functions), including formatting and real timings. Introduced DIP switches for configuring the attached drives. Implemented MFM hard disk (ti99_hd) device, wrapping the plain hard disk image. This also resolves bug #1257. (Michael Zapf)
[src/mess]mess.mak
[src/mess/devices]ti99_hd.c* ti99_hd.h* ti99cart.c
[src/mess/drivers]geneve.c ti99_4p.c ti99_4x.c ti99_8.c
[src/mess/formats]ti99_dsk.c ti99_dsk.h
[src/mess/machine]99_dsk.c 99_dsk.h geneve.c smc92x4.c smc92x4.h ti99_4x.c ti99_4x.h

src/mess/devices/ti99cart.c
r8042r8043
27102710      We take slot numbers from 0 (automatic mode) to the maximum. */
27112711
27122712   ti99_multicart_state *cartslots = (ti99_multicart_state *)device->token;
2713   int slotnumber = (input_port_read(device->machine, "CFG") >> config_cartslot_bit) & config_cartslot_mask;
2713   int slotnumber = input_port_read(device->machine, "CARTSLOT");
27142714   assert(slotnumber>=0 && slotnumber<=255);
27152715   cartslots->fixed_slot = slotnumber-1; /* auto = -1 */
27162716   cartslots->grom_address = 0x0000;
src/mess/devices/ti99_hd.c
r0r8043
1/*************************************************************************
2
3   Hard disk support
4   
5   This device wraps the plain image device as that device does not allow
6   for internal states (like head position)
7   The plain device is a subdevice ("drive") of this device, so we
8   get names like "mfmhd0:drive"
9
10   Michael Zapf, April 2010
11   
12**************************************************************************/
13
14#include "emu.h"
15#include "harddisk.h"
16#include "harddriv.h"
17#include "machine/smc92x4.h"
18
19#include "ti99_hd.h"
20
21typedef struct _mfmhd
22{
23   int current_cylinder;
24   int current_head;
25   int seeking;
26   int status;
27   int id_index; /* position in track for seeking the sector; counts the sector number */
28} mfmhd_state, idehd_state;
29
30#if 0
31static void dump_contents(UINT8 *buffer, int length)
32{
33        for (int i=0; i < length; i+=16)
34        {
35                for (int j=0; j < 16; j+=2)
36                {
37                        printf("%02x%02x ", buffer[i+j], buffer[i+j+1]);
38                }
39                printf("\n");
40        }
41}
42#endif
43
44/*
45   Returns the linear sector number, given the CHS data.
46*/
47static int harddisk_chs_to_lba(hard_disk_file *hdfile, int cylinder, int head, int sector, UINT32 *lba)
48{
49   const hard_disk_info *info;
50   
51   if ( hdfile != NULL)
52   {
53      info = hard_disk_get_info(hdfile);
54
55      if (   (cylinder >= info->cylinders) ||
56         (head >= info->heads) ||
57              (sector >= info->sectors))
58                   return FALSE;
59     
60      *lba = (cylinder * info->heads + head)
61              * info->sectors
62         + sector;
63      return TRUE;
64   }
65   return FALSE;
66}
67
68/* Accessor functions */
69void ti99_mfm_harddisk_read_sector(running_device *harddisk, int cylinder, int head, int sector, UINT8 **buf, int *sector_length)
70{
71        UINT32 lba;
72   mfmhd_state *hd = (mfmhd_state *)harddisk->token;
73   running_device *drive = harddisk->subdevice("drive");
74        hard_disk_file *file = mess_hd_get_hard_disk_file(drive);
75
76        *sector_length = 256;
77        *buf = (UINT8 *)malloc(*sector_length);
78       
79   if (cylinder != hd->current_cylinder)
80   {   
81      return;
82   }
83   
84        if (file==NULL)
85        {
86                hd->status &= ~MFMHD_READY;
87                return;
88        }
89
90        if (!harddisk_chs_to_lba(file, cylinder, head, sector, &lba))
91        {
92                hd->status &= ~MFMHD_READY;
93                return;
94        }
95
96        if (!hard_disk_read(file, lba, *buf))
97        {
98           hd->status &= ~MFMHD_READY;
99                return;
100        }
101/* printf("ti99_hd read sector  c=%04d h=%02d s=%02d\n", cylinder, head, sector); */
102        hd->status |= MFMHD_READY;
103}
104
105void ti99_mfm_harddisk_write_sector(running_device *harddisk, int cylinder, int head, int sector, UINT8 *buf, int sector_length)
106{
107        UINT32 lba;
108   mfmhd_state *hd = (mfmhd_state *)harddisk->token;
109   running_device *drive = harddisk->subdevice("drive");
110        hard_disk_file *file = mess_hd_get_hard_disk_file(drive);
111
112        if (file==NULL)
113        {
114                hd->status &= ~MFMHD_READY;
115                return;
116        }
117
118        if (!harddisk_chs_to_lba(file, cylinder, head, sector, &lba))
119        {
120                hd->status &= ~MFMHD_READY;
121                hd->status |= MFMHD_WRFAULT;
122                return;
123        }
124       
125        if (!hard_disk_write(file, lba, buf))
126   {
127                hd->status &= ~MFMHD_READY;
128                hd->status |= MFMHD_WRFAULT;
129      return;
130   }
131   
132        hd->status |= MFMHD_READY;
133}
134
135#define TI99HD_BLOCKNOTFOUND -1
136
137/*
138   Searches a block containing number * byte, starting at the given
139   position. Returns the position of the first byte of the block.
140*/
141static int find_block(const UINT8 *buffer, int start, int stop, UINT8 byte, size_t number)
142{
143   int i = start;
144   size_t current = number;
145   while (i < stop && current > 0)
146   {
147      if (buffer[i++] != byte)
148      {
149         current = number;
150      }
151      else
152      {
153         current--;
154      }
155   }
156   if (current==0)
157   {
158      return i - number;
159   }
160   else
161      return TI99HD_BLOCKNOTFOUND;
162}
163
164/*
165   Reads a complete track. We have to rebuild the gaps. This is basically
166   done in the same way as in the SDF format in ti99_dsk.
167   
168   WARNING: This function is untested! We need to create a suitable
169   application program for the TI which makes use of it.
170*/
171void ti99_mfm_harddisk_read_track(running_device *harddisk, int head, UINT8 **pbuffer, int *data_count)
172{
173   mfmhd_state *hd = (mfmhd_state *)harddisk->token;
174   running_device *drive = harddisk->subdevice("drive");
175
176   /* We assume an interleave of 3 for 32 sectors. */
177   int step = 3; 
178        UINT32 lba;
179        int i;
180
181        int gap1 = 16;
182        int gap2 = 8;
183        int gap3 = 15;
184        int gap4 = 340;
185        int sync = 13;
186        int count;
187        int size;
188        int position = 0;
189        int sector;
190        int crc;
191
192   const hard_disk_info *info;
193        hard_disk_file *file = mess_hd_get_hard_disk_file(drive);
194
195   if (file==NULL)
196   {
197      hd->status &= ~MFMHD_READY;
198      return;
199   }
200       
201   info = hard_disk_get_info(file);
202
203        count = info->sectors;
204        size = info->sectorbytes/128;
205   
206   *data_count = gap1 + count*(sync+12+gap2+sync+size*128+gap3)+gap4;
207   
208   UINT8 *trackdata = (UINT8*)malloc(*data_count);
209     
210   /* Write lead-in. */
211   memset(trackdata, 0x4e, gap1);
212
213   position += gap1;
214   for (i=0; i < info->sectors; i++)
215   {
216      sector = (i*step) % info->sectors;     
217      memset(&trackdata[position], 0x00, sync);
218      position += 10;
219     
220      /* Write sync */     
221      trackdata[position++] = 0xa1;
222
223      /* Write IDAM */
224      trackdata[position++] = cylinder_to_ident(hd->current_cylinder);
225      trackdata[position++] = hd->current_cylinder;
226      trackdata[position++] = head;
227      trackdata[position++] = sector;
228      trackdata[position++] = (size==1)? 0x00 : (0x01 << (size-1));
229     
230      /* Set CRC16 */
231      crc = ccitt_crc16(0xffff, &trackdata[position-5], 5);
232      trackdata[position++] = (crc>>8)&0xff;
233      trackdata[position++] = crc & 0xff;
234     
235      /* Write Gap2 */
236      memset(&trackdata[position], 0x4e, gap2);
237      position += gap2;
238
239      /* Write sync */
240      memset(&trackdata[position], 0x00, sync);
241      position += sync;
242      trackdata[position++] = 0xa1;
243
244      /* Write DAM */
245      trackdata[position++] = 0xfb;
246     
247      /* Locate the sector content in the image and load it. */
248     
249      if (!harddisk_chs_to_lba(file, hd->current_cylinder, head, sector, &lba))
250      {
251         hd->status &= ~MFMHD_READY;
252         free(trackdata);
253         return;
254      }
255     
256      if (!hard_disk_read(file, lba, &trackdata[position]))
257      {
258         hd->status &= ~MFMHD_READY;
259         free(trackdata);
260         return;
261      }
262     
263      position += size;
264     
265      /* Set CRC16. Includes the address mark. */
266      crc = ccitt_crc16(0xffff, &trackdata[position-size-1], size+1);
267      trackdata[position++] = (crc>>8)&0xff;
268      trackdata[position++] = crc & 0xff;
269     
270      /* Write remaining 3 bytes which would have been used for ECC. */
271      memset(&trackdata[position], 0x00, 3);
272      position += 3;
273     
274      /* Write Gap3 */
275      memset(&trackdata[position], 0x4e, gap3);
276      position += gap3;
277   }
278   /* Write Gap 4 */
279   memset(&trackdata[position], 0x4e, gap4);
280   position += gap4;
281
282   *pbuffer = trackdata;
283   
284   /* Remember to free the buffer! Except when an error has occured,
285      the function returns a newly allocated buffer. */
286}
287
288/*
289   Writes a track to the image. We need to isolate the sector contents.
290   This is basically done in the same way as in the SDF format in ti99_dsk.
291*/
292void ti99_mfm_harddisk_write_track(running_device *harddisk, int head, UINT8 *track_image, int data_count)
293{
294   int current_pos = 0;
295   int found;
296   UINT8 wident, whead = 0, wsector = 0, wsize;
297   UINT16 wcyl = 0;
298   int state;
299   
300   /* Only search in the first 100 bytes for the start. */
301   int gap1 = 16;
302   int sync = 13;
303   
304   UINT32 lba;
305   mfmhd_state *hd = (mfmhd_state *)harddisk->token;
306   running_device *drive = harddisk->subdevice("drive");
307   hard_disk_file *file = mess_hd_get_hard_disk_file(drive);
308
309   /* printf("ti99_hd write track c=%d h=%d\n", hd->current_cylinder, head); */
310
311   if (file==NULL)
312   {
313      hd->status &= ~MFMHD_READY;
314      return;
315   }
316
317   current_pos = find_block(track_image, 0, 100, 0x4e, gap1);
318   
319   /* In case of defect formats, we continue as far as possible. This
320   may lead to sectors not being written. */
321   if (current_pos==TI99HD_BLOCKNOTFOUND)
322   {
323      logerror("ti99_hd Cannot find gap1 for cylinder %d, head %d.\n", hd->current_cylinder, head);
324      /* What now? The track data are illegal, so we refuse to continue. */
325      return;
326   }
327
328   /* Get behind GAP1 */
329   current_pos += gap1;
330   found = FALSE;
331   
332   while (current_pos < data_count)
333   {
334      /* We must find the address block to determine the sector. */
335      int new_pos = find_block(track_image, current_pos, data_count, 0x00, sync);
336      if (new_pos==TI99HD_BLOCKNOTFOUND)
337      {
338         /* Forget about the rest; we're done. */
339         if (found) break;  /* we were already successful, so all ok */
340         logerror("ti99_hd Cannot find sync for track %d, head %d.\n", hd->current_cylinder, head);
341         return;
342      }
343      found = TRUE;
344
345      new_pos = new_pos + sync; /* skip sync bytes */     
346
347      if (track_image[new_pos]==0xa1)
348      {
349         /* IDAM found. */
350         current_pos = new_pos + 1;
351         wident = track_image[current_pos];
352         wcyl = track_image[current_pos+1] + ((track_image[current_pos+2]&0x70)<<4);
353         whead = track_image[current_pos+2]&0x0f;
354         wsector = track_image[current_pos+3];
355         wsize = track_image[current_pos+4];
356
357         if (wcyl == hd->current_cylinder && whead == head)
358         {
359            if (!harddisk_chs_to_lba(file, wcyl, whead, wsector, &lba))
360            {
361               hd->status &= ~MFMHD_READY;
362               hd->status |= MFMHD_WRFAULT;
363               return;
364            }
365
366            /* Skip to the sector content. */
367            new_pos = find_block(track_image, current_pos, data_count, 0x00, sync);
368            current_pos = new_pos + sync;
369            if (track_image[current_pos]==0xa1)
370            {               
371               current_pos += 2;
372               state = hard_disk_write(file, lba, track_image+current_pos);
373               if (state==0)
374               {
375                  logerror("ti99_hd Write error during formatting cylinder %d, head %d\n", wcyl, whead);
376                  hd->status &= ~MFMHD_READY;
377                  hd->status |= MFMHD_WRFAULT;
378                  return;
379               }
380               current_pos = current_pos+256+2; /* Skip contents and CRC */
381            }
382            else
383            {
384               logerror("ti99_hd Cannot find DAM for cylinder %d, head %d, sector %d.\n", wcyl, whead, wsector);
385               return;
386            }
387         }
388         else
389         {
390            logerror("ti99_hd cylinder/head mismatch. Drive is on cyl=%d, head=%d, track data say cyl=%d, head=%d\n", hd->current_cylinder, head, wcyl, whead);
391         }
392      }
393      else
394      {
395         printf("ti99_hd Cannot find IDAM for cylinder %d, head %d, sector %d.\n", wcyl, whead, wsector);
396         return;
397      }
398   }
399}
400
401UINT8 ti99_mfm_harddisk_status(running_device *harddisk)
402{
403   UINT8 status = 0;
404   running_device *drive;
405   mfmhd_state *hd = (mfmhd_state *)harddisk->token;
406   drive = harddisk->subdevice("drive");
407        hard_disk_file *file = mess_hd_get_hard_disk_file(drive);
408       
409   if (file!=NULL)
410      status |= MFMHD_READY;
411
412   if (hd->current_cylinder==0)
413      status |= MFMHD_TRACK00;
414   
415   if (!hd->seeking)
416      status |= MFMHD_SEEKCOMP;
417   
418   if (hd->id_index == 0)
419      status |= MFMHD_INDEX;
420   
421   hd->status = status;
422   return status;
423}
424
425void ti99_mfm_harddisk_seek(running_device *harddisk, int direction)
426{
427   running_device *drive = harddisk->subdevice("drive");
428   mfmhd_state *hd = (mfmhd_state *)harddisk->token;
429   const hard_disk_info *info;
430        hard_disk_file *file = mess_hd_get_hard_disk_file(drive);
431
432   if (file==NULL)   return;       
433       
434   info = hard_disk_get_info(file);
435
436   hd->seeking = TRUE;
437
438   if (direction<0)
439   {
440      if (hd->current_cylinder>0)
441         hd->current_cylinder--;
442   }
443   else
444   {
445      if (hd->current_cylinder < info->cylinders)
446         hd->current_cylinder++;
447   }
448   
449   hd->seeking = FALSE;
450}
451
452void ti99_mfm_harddisk_get_next_id(running_device *harddisk, int head, chrn_id_hd *id)
453{
454   running_device *drive = harddisk->subdevice("drive");
455   mfmhd_state *hd = (mfmhd_state *)harddisk->token;
456   const hard_disk_info *info;
457        hard_disk_file *file;
458   int interleave = 3;
459
460   file = mess_hd_get_hard_disk_file(drive);
461   if (file==NULL)
462   {
463                hd->status &= ~MFMHD_READY;
464      return;
465   }
466   
467   info = hard_disk_get_info(file);
468   
469   hd->current_head = head;
470   
471   /* TODO: implement an interleave suitable for the number of sectors in the track. */
472   hd->id_index = (hd->id_index + interleave) % info->sectors;
473   
474   /* build a new info block. */
475   id->C = hd->current_cylinder;
476   id->H = hd->current_head;
477   id->R = hd->id_index;
478   id->N = 1;
479   id->data_id = hd->id_index;
480   id->flags = 0;
481}
482
483static DEVICE_START( mfmhd )
484{
485}
486
487static DEVICE_START( idehd )
488{
489}
490
491
492MACHINE_DRIVER_START( mfmhd )
493        MDRV_DEVICE_ADD( "drive", HARDDISK, 0 )
494MACHINE_DRIVER_END
495
496MACHINE_DRIVER_START( idehd )
497        MDRV_DEVICE_ADD( "drive", IDE_HARDDISK, 0 )
498MACHINE_DRIVER_END
499
500static const char DEVTEMPLATE_SOURCE[] = __FILE__;
501
502#define DEVTEMPLATE_ID(p,s)             p##mfmhd##s
503#define DEVTEMPLATE_FEATURES            DT_HAS_START | DT_HAS_MACHINE_CONFIG
504#define DEVTEMPLATE_NAME                "TI99 MFM Hard disk"
505#define DEVTEMPLATE_FAMILY              "Hard disks"
506#define DEVTEMPLATE_VERSION      "1.0"
507#define DEVTEMPLATE_CREDITS      "Copyright MESS Team"
508#include "devtempl.h"
509
510#undef DEVTEMPLATE_ID
511#undef DEVTEMPLATE_FEATURES
512#undef DEVTEMPLATE_NAME
513
514#define DEVTEMPLATE_ID(p,s)             p##idehd##s
515#define DEVTEMPLATE_FEATURES            DT_HAS_START | DT_HAS_MACHINE_CONFIG
516#define DEVTEMPLATE_NAME                "TI99 IDE Hard disk"
517#include "devtempl.h"
518
519
520
src/mess/devices/ti99_hd.h
r0r8043
1#ifndef __TI99_HD__
2#define __TI99_HD__
3
4#include "emu.h"
5#include "machine/smc92x4.h"
6
7#define MFMHD_0 "mfmhd0"
8#define MFMHD_1 "mfmhd1"
9#define MFMHD_2 "mfmhd2"
10
11#define IDEHD_0 "idehd0"
12
13/* typedef struct _mfmhd_config mfmhd_config;
14struct _mfmhd_config
15{
16   device_start_func         device_start;
17   device_image_load_func         device_load;
18   device_image_unload_func      device_unload;
19}; */
20
21/* Accessor functions */
22void ti99_mfm_harddisk_read_sector(running_device *harddisk, int cylinder, int head, int sector, UINT8 **buf, int *sector_length);
23void ti99_mfm_harddisk_write_sector(running_device *harddisk, int cylinder, int head, int sector, UINT8 *buf, int sector_length);
24void ti99_mfm_harddisk_read_track(running_device *harddisk, int head, UINT8 **buffer, int *data_count);
25void ti99_mfm_harddisk_write_track(running_device *harddisk, int head, UINT8 *buffer, int data_count);
26UINT8 ti99_mfm_harddisk_status(running_device *harddisk);
27void ti99_mfm_harddisk_seek(running_device *harddisk, int direction);
28void ti99_mfm_harddisk_get_next_id(running_device *harddisk, int head, chrn_id_hd *id);
29
30#define MFMHD   DEVICE_GET_INFO_NAME( mfmhd )
31DEVICE_GET_INFO( mfmhd );
32
33#define IDEHD   DEVICE_GET_INFO_NAME( idehd )
34DEVICE_GET_INFO( idehd );
35
36#define MDRV_MFMHD_3_DRIVES_ADD()         \
37   MDRV_DEVICE_ADD(MFMHD_0, MFMHD, 0)      \
38   MDRV_DEVICE_ADD(MFMHD_1, MFMHD, 0)      \
39   MDRV_DEVICE_ADD(MFMHD_2, MFMHD, 0)      \
40   MDRV_DEVICE_ADD(IDEHD_0, IDEHD, 0)
41#endif
42
43
44/*
45   MDRV_MFMHD_START(mfmhd)            \
46   MDRV_MFMHD_LOAD(mfmhd)            \
47   MDRV_MFMHD_UNLOAD(mfmhd)         
48*/
src/mess/machine/99_dsk.c
r8042r8043
3636#include "99_dsk.h"
3737#include "mm58274c.h"
3838#include "devices/flopdrv.h"
39#include "devices/harddriv.h"
40#include "devices/ti99_hd.h"
41#include "harddisk.h"
42#include "formats/ti99_dsk.h"
3943
40
4144#define MAX_FLOPPIES 4
4245
43static int use_80_track_drives;
44
4546/* defines for DRQ_IRQ_status */
4647enum
4748{
r8042r8043
8990}
9091
9192/*
92    Callback for the ti99_dsk format. Required for the image format handler
93    to find out whether we have a 40-track disk in an 80-track drive.
94*/
95int ti99_image_in_80_track_drive()
96{
97   return use_80_track_drives;
98}
99
100/*
10193    call this when the state of DSKhold or DRQ/IRQ or DVENA change
10294
10395    Emulation is faulty because the CPU is actually stopped in the midst of
r8042r8043
120112   fdc_handle_hold(machine);
121113}
122114
123static void hfdc_int_callback(int which, int state);
124static int hfdc_select_callback(int which, select_mode_t select_mode, int select_line, int gpos);
125static UINT8 hfdc_dma_read_callback(int which, offs_t offset);
126static void hfdc_dma_write_callback(int which, offs_t offset, UINT8 data);
127
128static const smc92x4_intf hfdc_intf =
129{
130   hfdc_select_callback,
131   hfdc_dma_read_callback,
132   hfdc_dma_write_callback,
133   hfdc_int_callback
134};
135
136115/*
137116    callback called whenever DRQ/IRQ state change
138117*/
r8042r8043
170149   {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3}
171150};
172151
173
174152/*
175153    Initializes all available controllers. This routine is only used in the
176154    init state of the emulator. During the normal operation, only the
177155    reset routines are used.
178156*/
157// TODO: Check that:    floppy_mon_w(w->drive, CLEAR_LINE);
158
179159void ti99_floppy_controllers_init_all(running_machine *machine)
180160{
181   /* initialize the controller chip for HFDC */
182   smc92x4_init(0, & hfdc_intf);
183
184161   motor_on_timer = timer_alloc(machine, motor_on_timer_callback, NULL);
185162}
186163
r8042r8043
221198   DVENA = 0;
222199   motor_on = 0;
223200
201   ti99_set_80_track_drives(FALSE);
202   
224203   set_all_geometries(machine, FLOPPY_DRIVE_DS_40);
225   use_80_track_drives = FALSE;
226
204   
227205   ti99_peb_set_card_handlers(0x1100, & fdc_handlers);
228206   if (fdc) {
229207      wd17xx_reset(fdc);      /* resets the fdc */
r8042r8043
414392   DVENA = 0;
415393   motor_on = 0;
416394
395   ti99_set_80_track_drives(FALSE);
396   
417397   set_all_geometries(machine, FLOPPY_DRIVE_DS_40);
418   use_80_track_drives = FALSE;
419398
420399   ti99_peb_set_card_handlers(0x1100, & ccfdc_handlers);
421400
r8042r8043
635614   DVENA = 0;
636615   motor_on = 0;
637616
617   ti99_set_80_track_drives(FALSE);
618   
638619   set_all_geometries(machine, FLOPPY_DRIVE_DS_40);
639       use_80_track_drives = FALSE;
640620
641621   ti99_peb_set_card_handlers(0x1100, & bwg_handlers);
642622
r8042r8043
894874    Reference:
895875    * hfdc manual
896876        <ftp://ftp.whtech.com//datasheets & manuals/Hardware manuals/hfdc manual.max>
877
878    For smc92x4 (HFDC-internal DSR)
879    FM:  gap0=3, gap1=26, gap2=11, gap3=27, gap4=42, sync=6, count=9, size=2, fm=16, gap_byte=ff
880    MFM: gap0=2, gap1=30, gap2=22, gap3=20, gap4=42, sync=12, count=18, size=2, fm=0, gap_byte=4e
897881*/
898882
899883/* prototypes */
r8042r8043
910894   hfdc_mem_w
911895};
912896
897#define HFDC_MAX_FLOPPY 4
898#define HFDC_MAX_HARD 4
899
913900static int hfdc_rtc_enable;
914901static int hfdc_ram_offset[3];
915902static int hfdc_rom_offset;
916903static int cru_sel;
917904static UINT8 *hfdc_ram;
905
918906static int hfdc_irq_state;
907static int hfdc_dip_state;
919908
909static running_device *floppy_unit[4];
910static running_device *harddisk_unit[4];
911
912static UINT8 output1_latch;
913static UINT8 output2_latch;
914
915static int dma_address;
916
917static int line_to_index(UINT8 line, int max)
918{
919   int index = 0;
920   while (index < max)
921   {
922      if ((line & 0x01)!=0)
923         break;
924      else
925      {
926         line = line >> 1;
927         index++;
928      }
929   }
930   if (index==max) return -1;
931   return index;
932}
933
920934/*
921    Select the correct HFDC disk units.
922    floppy disks are selected by the 4 gpos instead of the select lines.
935   Select the HFDC hard disk unit
936   This function implements the selection logic on the PCB (outside the
937   controller chip)
938   The HDC9234 allows up to four drives to be selected by the select lines.
939   This is not enough for controlling four floppy drives and three hard
940   drives, so the user programmable outputs are used to select the floppy
941   drives. This selection happens completely outside of the controller,
942   so we must implement it here.
923943*/
924static int hfdc_select_callback(int which, select_mode_t select_mode, int select_line, int gpos)
944
945static running_device *hfdc_current_harddisk(void)
925946{
926   int disk_unit;
947   int disk_unit = -1;
948   disk_unit = line_to_index((output1_latch>>4)&0x0f, HFDC_MAX_HARD);
927949
928   (void) which;
950   /* The HFDC does not use disk_unit=0. The first HD has index 1. */
951/*   if (disk_unit>=0) printf("Select hard disk %d\n", disk_unit);
952   else printf("No hard disk selected\n");
953*/
954   return harddisk_unit[disk_unit];
955}
929956
930   switch (select_mode)
957/*
958   Select the HFDC floppy disk unit
959   This function implements the selection logic on the PCB (outside the
960   controller chip)
961*/
962
963static running_device *hfdc_current_floppy(void)
964{   
965   int disk_unit = -1;
966   disk_unit = line_to_index(output1_latch & 0x0f, HFDC_MAX_FLOPPY);
967
968   if (disk_unit<0)
931969   {
932   /*case sm_at_harddisk:*/
933   case sm_harddisk:
934      /* hard disk */
935      disk_unit = select_line - 1;
936      break;
970   //   printf("No unit selected\n");
971      return NULL;
972   }
937973
938   case sm_floppy_slow:
939   case sm_floppy_fast:
940      /* floppy disk */
941      /* We use the 4 general purpose output as select lines in order to
942        support 4 drives. */
943      switch (gpos & 0xf)
944      {
945      case 1:
946         disk_unit = 0;
947         break;
948      case 2:
949         disk_unit = 1;
950         break;
951      case 4:
952         disk_unit = 2;
953         break;
954      case 8:
955         disk_unit = 3;
956         break;
957      default:
958         disk_unit = -1;
959         break;
960      }
961      break;
974   // printf("Select floppy disk %d (output1=%02x)\n", index, output1_latch);   
975   return floppy_unit[disk_unit];
976}   
962977
963   default:
964      disk_unit = -1;
978/*
979    Called whenever the state of the sms9234 interrupt pin changes.
980*/
981static WRITE_LINE_DEVICE_HANDLER( ti99_hfdc_intrq_w )
982{
983   hfdc_irq_state = state;
984
985   /* Set INTA */
986   if (state)
987   {
988      ti99_peb_set_ila_bit(device->machine, intb_fdc_bit, 1);
989   }
990   else
991   {
992      ti99_peb_set_ila_bit(device->machine, intb_fdc_bit, 0);
993   }
994
995   /* TODO: Check */
996   fdc_handle_hold(device->machine);
997}
998
999/*
1000    Called whenever the state of the sms9234 DMA in progress changes.
1001*/
1002static WRITE_LINE_DEVICE_HANDLER( ti99_hfdc_dip_w )
1003{
1004   hfdc_dip_state = state;
1005}
1006
1007static WRITE8_DEVICE_HANDLER( ti99_hfdc_auxbus_out )
1008{
1009   switch (offset)
1010   {
1011   case INPUT_STATUS:
1012      logerror("99_dsk: Invalid operation: S0=S1=0, but tried to write (expected: read drive status)\n");
1013      return;
1014   case OUTPUT_DMA_ADDR:
1015      /* Value is dma address byte. Shift previous contents to the left. */
1016      dma_address = ((dma_address << 8) + (data&0xff))&0xffffff;
9651017      break;
1018   case OUTPUT_OUTPUT1:
1019      /* value is output1 */
1020      output1_latch = data;
1021      break;
1022   case OUTPUT_OUTPUT2:
1023      /* value is output2 */
1024      output2_latch = data;
1025      break;
9661026   }
1027}
9671028
968   return disk_unit;
1029static READ_LINE_DEVICE_HANDLER( ti99_hfdc_auxbus_in )
1030{
1031   running_device *drive;
1032   UINT8 reply = 0;
1033
1034   if (output1_latch==0)
1035   {
1036      // printf("Neither floppy nor hard disk selected.\n");
1037      return 0; /* is that the correct default value? */
1038   }
1039
1040   /* If a floppy is selected, we have one line set among the four programmable outputs. */
1041   if ((output1_latch & 0x0f)!=0)
1042   {
1043      drive = hfdc_current_floppy();
1044
1045      /* Get floppy status. */
1046      if (floppy_drive_get_flag_state(drive, FLOPPY_DRIVE_INDEX) == FLOPPY_DRIVE_INDEX)
1047         reply |= DS_INDEX;
1048      if (floppy_tk00_r(drive) == CLEAR_LINE)
1049         reply |= DS_TRK00;
1050      if (floppy_wpt_r(drive) == CLEAR_LINE)
1051         reply |= DS_WRPROT;
1052
1053      /* if (image_exists(disk_img)) */ 
1054
1055      reply |= DS_READY;  /* Floppies don't have a READY line; line is pulled up */
1056      reply |= DS_SKCOM;  /* Same here. */
1057   }
1058   else /* one of the first four lines must be selected */
1059   {
1060      UINT8 state;
1061      drive = hfdc_current_harddisk();
1062      state = ti99_mfm_harddisk_status(drive);
1063      if (state & MFMHD_TRACK00)
1064         reply |= DS_TRK00;
1065      if (state & MFMHD_SEEKCOMP)
1066         reply |= DS_SKCOM;
1067      if (state & MFMHD_WRFAULT)
1068         reply |= DS_WRFAULT;
1069      if (state & MFMHD_INDEX)
1070         reply |= DS_INDEX;
1071      if (state & MFMHD_READY)
1072         reply |= DS_READY;
1073   }
1074   return reply;
9691075}
9701076
9711077/*
9721078    Read a byte from buffer in DMA mode
9731079*/
974static UINT8 hfdc_dma_read_callback(int which, offs_t offset)
1080static UINT8 hfdc_dma_read_callback(void)
9751081{
976   (void) which;
977   return hfdc_ram[offset & 0x7fff];
1082   UINT8 value = hfdc_ram[dma_address & 0x7fff];
1083   dma_address++;   
1084   return value;
9781085}
9791086
9801087/*
9811088    Write a byte to buffer in DMA mode
9821089*/
983static void hfdc_dma_write_callback(int which, offs_t offset, UINT8 data)
1090static void hfdc_dma_write_callback(UINT8 data)
9841091{
985   (void) which;
986   hfdc_ram[offset & 0x7fff] = data;
1092   hfdc_ram[dma_address & 0x7fff] = data;
1093   dma_address++;
9871094}
9881095
989/*
990    Called whenever the state of the sms9234 interrupt pin changes.
1096/*
1097   Preliminary MFM harddisk interface.
9911098*/
992static void hfdc_int_callback(int which, int state)
1099static void hfdc_harddisk_get_next_id(int head, chrn_id_hd *id)
9931100{
994   assert(which == 0);
1101   running_device *harddisk = hfdc_current_harddisk();
1102   ti99_mfm_harddisk_get_next_id(harddisk, head, id);
1103}
9951104
996   hfdc_irq_state = state;
1105static void hfdc_harddisk_seek(int direction)
1106{
1107   running_device *harddisk = hfdc_current_harddisk();
1108   ti99_mfm_harddisk_seek(harddisk, direction);
9971109}
9981110
1111static void hfdc_harddisk_read_sector(int cylinder, int head, int sector, UINT8 **buf, int *sector_length)
1112{
1113   running_device *harddisk = hfdc_current_harddisk();
1114   if (harddisk != NULL)
1115      ti99_mfm_harddisk_read_sector(harddisk, cylinder, head, sector, buf, sector_length);
1116}
1117
1118static void hfdc_harddisk_write_sector(int cylinder, int head, int sector, UINT8 *buf, int sector_length)
1119{
1120   running_device *harddisk = hfdc_current_harddisk();
1121   if (harddisk != NULL)
1122      ti99_mfm_harddisk_write_sector(harddisk, cylinder, head, sector, buf, sector_length);   
1123}
1124
1125static void hfdc_harddisk_read_track(int head, UINT8 **buffer, int *data_count)
1126{
1127   running_device *harddisk = hfdc_current_harddisk();
1128   if (harddisk != NULL)
1129      ti99_mfm_harddisk_read_track(harddisk, head, buffer, data_count);
1130}
1131
1132static void hfdc_harddisk_write_track(int head, UINT8 *buffer, int data_count)
1133{
1134   running_device *harddisk = hfdc_current_harddisk();
1135   if (harddisk != NULL)
1136      ti99_mfm_harddisk_write_track(harddisk, head, buffer, data_count);
1137}
1138
9991139/*
10001140    Reset fdc card, set up handlers
10011141*/
10021142void ti99_hfdc_reset(running_machine *machine)
10031143{
1144   running_device *device = devtag_get_device(machine, "smc92x4");
1145   const char *flopname[] = {FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3};
1146   const char *hardname[] = {MFMHD_0, MFMHD_1, MFMHD_2};
1147   
1148   int i;
1149   
10041150   ti99_disk_DSR = memory_region(machine, region_dsr) + offset_hfdc_dsr;
10051151   hfdc_ram = memory_region(machine, region_dsr) + offset_hfdc_ram;
10061152   hfdc_ram_offset[0] = hfdc_ram_offset[1] = hfdc_ram_offset[2] = 0;
r8042r8043
10161162
10171163   ti99_peb_set_card_handlers(0x1100, & hfdc_handlers);
10181164
1165   if ((input_port_read(machine, "DISKCTRL") & DISK_HFDC)
1166      && (input_port_read(machine, "HFDCDIP")&0x55))
1167      ti99_set_80_track_drives(TRUE);
1168   else
1169      ti99_set_80_track_drives(FALSE);
1170   
1171   smc92x4_set_timing(device, input_port_read(machine, "DRVSPD"));
1172   
10191173   set_all_geometries(machine, FLOPPY_DRIVE_DS_80);
1020   use_80_track_drives = TRUE;
10211174
1022   smc92x4_reset(0);
1175   /* Connect floppy drives to controller. Note that *this* is the
1176      controller, not the controller chip. The pcb contains a select
1177      logic.
1178      TODO: Turn this implementation into a device so that this is
1179      correctly modelled.
1180   */
1181   for (i = 0; i < 4; i++)
1182   {
1183      if (device->owner != NULL)
1184      {
1185         floppy_unit[i] = device->owner->subdevice(flopname[i]);
1186         if (floppy_unit[i]==NULL)
1187         {
1188            floppy_unit[i] = devtag_get_device(device->machine, flopname[i]);
1189         }
1190      }
1191      else
1192      {
1193         floppy_unit[i] = devtag_get_device(device->machine, flopname[i]);
1194      }
1195
1196      if (floppy_unit[i]!=NULL)
1197      {
1198         floppy_drive_set_controller(floppy_unit[i], device);
1199//         floppy_drive_set_index_pulse_callback(floppy_unit[i], smc92x4_index_pulse_callback);
1200         floppy_drive_set_rpm(floppy_unit[i], 300.);
1201      }
1202      else
1203      {
1204         logerror("99_dsk: Image %s is null\n", flopname[i]);
1205      }
1206   }
1207
1208   /* In the HFDC ROM, WDSx selects drive x; drive 0 is not used */
1209   for (i = 1; i < 4; i++)
1210   {
1211      harddisk_unit[i] = devtag_get_device(device->machine, hardname[i-1]);
1212   }
1213   harddisk_unit[0] = NULL;
1214   
1215   if (device) {
1216      smc92x4_reset(device);
1217   }
10231218}
10241219
1220const smc92x4_interface ti99_smc92x4_interface =
1221{
1222   FALSE,      /* do not use the full track layout */
1223   DEVCB_LINE(ti99_hfdc_intrq_w),
1224   DEVCB_LINE(ti99_hfdc_dip_w),
1225   DEVCB_HANDLER(ti99_hfdc_auxbus_out),
1226   DEVCB_LINE(ti99_hfdc_auxbus_in),
1227   
1228   hfdc_current_floppy,
1229   hfdc_dma_read_callback,
1230   hfdc_dma_write_callback,
10251231
1232   /* Preliminary MFM harddisk interface. */
1233   hfdc_harddisk_get_next_id,
1234   hfdc_harddisk_seek,
1235   hfdc_harddisk_read_sector,
1236   hfdc_harddisk_write_sector,
1237   hfdc_harddisk_read_track,
1238   hfdc_harddisk_write_track
1239};
1240
1241int mycheck = 0;
1242
10261243/*
1027    Read disk CRU interface
1244   Read disk CRU interface
1245   HFDC manual p. 44
1246   
1247   CRU Select=0
1248   CRU rel. address   Definition
1249   00         Disk controller interrupt
1250   02         Motor status
1251   04         DMA in progress
1252   
1253   Note that the cru line settings on the board do not match the
1254   description. 02 and 04 switch positions. Similarly, the dip switches
1255   for the drive configurations are not correctly enumerated in the manual.
1256   
1257   CRU Select=1
1258   CRU rel. address   Definition
1259   00         Switch 4 status \_ drive 2 config
1260   02         Switch 3 status /
1261   04         Switch 2 status \_ drive 1 config
1262   06         Switch 1 status /
1263   08         Switch 8 status \_ drive 4 config
1264   0A         Switch 7 status /
1265   0C         Switch 6 status \_ drive 3 config
1266   0E         Switch 5 status /
1267   
1268   config: 00 = 9/16/18 sectors, 40 tracks, 16 msec
1269      10 = 9/16/18 sectors, 40 tracks, 8 msec
1270      01 = 9/16/18 sectors, 80 tracks, 2 msec
1271      11 = 36 sectors, 80 tracks, 2 msec
10281272*/
10291273static int hfdc_cru_r(running_machine *machine, int offset)
10301274{
10311275   int reply;
1032   switch (offset)
1276   if (offset==0)  /* CRU bits 0-7 */
10331277   {
1034   case 0:
10351278      /* CRU bits */
10361279      if (cru_sel)
1280      {
10371281         /* DIP switches.  Logic levels are inverted (on->0, off->1).  CRU
1038            bit order is the reverse of DIP-switch order, too (dip 1 -> bit 7,
1039            dip 8 -> bit 0).  Return value examples:
1040                ff -> 4 slow 40-track DD drives
1041                55 -> 4 fast 40-track DD drives
1042                aa -> 4 80-track DD drives
1043                00 -> 4 80-track HD drives */
1044         reply = use_80_track_drives ? 0x00 : 0x55;
1282         bit order is the reverse of DIP-switch order, too (dip 1 -> bit 7,
1283         dip 8 -> bit 0).
1284         
1285         MZ: 00 should not be used since there is a bug in the
1286         DSR of the HFDC which causes problems with SD disks
1287         (controller tries DD and then fails to fall back to SD) */
1288           
1289         reply = ~(input_port_read(machine, "HFDCDIP"));
1290//         printf("hfdc cru read 7-0 = %02x\n", reply);
1291      }
10451292      else
10461293      {
10471294         reply = 0;
1048         if (hfdc_irq_state)
1295/*         if (hfdc_irq_state)
10491296            reply |= 1;
10501297         if (motor_on)
10511298            reply |= 2;
1052         /*if (hfdc_dma_in_progress)
1053                reply |= 4;*/
1299         if (hfdc_dma_in_progress)
1300            reply |= 4;*/
1301           
1302         if (hfdc_irq_state)
1303            reply |= 0x01;
1304         if (hfdc_dip_state)
1305            reply |= 0x02;
1306         if (motor_on)
1307            reply |= 0x04;
1308//         printf("hfdc cru read 7-0 = %02x\n", reply);
1309
10541310      }
1055      break;
1056
1057   default:
1311   }
1312   else /* CRU bits 8+ */
10581313      reply = 0;
1059      break;
1060   }
1314//   printf("hfdc cru read %d = %d\n", offset, reply);
10611315
10621316   return reply;
10631317}
10641318
10651319
10661320/*
1067    Write disk CRU interface
1321   Write disk CRU interface
1322   HFDC manual p. 43
1323   
1324   CRU rel. address   Definition            Active
1325   00         Device Service Routine Select      HIGH
1326   02         Reset to controller chip      LOW
1327   04         Floppy Motor on / CD0         HIGH
1328   06         ROM page select 0 / CD1
1329   08         ROM page select 1 / CRU input select
1330   12/4/6/8/A      RAM page select at 0x5400
1331   1C/E/0/2/4      RAM page select at 0x5800
1332   26/8/A/C/E      RAM page select at 0x5C00   
1333   
1334   CD0 and CD1 are Clock Divider selections for the Floppy Data Separator (FDC9216)
10681335*/
10691336static void hfdc_cru_w(running_machine *machine, int offset, int data)
1070{
1337{   
10711338   switch (offset)
10721339   {
10731340   case 0:
r8042r8043
10771344
10781345   case 1:
10791346      /* reset fdc (active low) */
1080      if (data)
1347      if (!data)
10811348      {
1082         smc92x4_reset(0);
1083         logerror("CRU sel %d\n", cru_sel);
1349         running_device *device = devtag_get_device(machine, "smc92x4");
1350         smc92x4_reset(device);
10841351      }
10851352      break;
10861353
10871354   case 2:
1088      /* Strobe motor + density ("CD0 OF 9216 CHIP") */
1355      /* Strobe motor and Clock Divider Bit 0 (CD0) */
10891356      if (data && !motor_on)
10901357      {
10911358         DVENA = 1;
r8042r8043
10931360         timer_adjust_oneshot(motor_on_timer, ATTOTIME_IN_MSEC(4230), 0);
10941361      }
10951362      motor_on = data;
1363      //printf("99dsk set motor on / clock divider 0 to %d\n", data);
10961364      break;
10971365
10981366   case 3:
1099      /* rom page select 0 + density ("CD1 OF 9216 CHIP") */
1367      /* rom page select 0 and Clock Divider Bit 1 (CD1) */
11001368      if (data)
11011369         hfdc_rom_offset |= 0x2000;
11021370      else
11031371         hfdc_rom_offset &= ~0x2000;
1372      //printf("99dsk set rom page 0 / clock divider 1 to %d\n", data);
11041373      break;
11051374
11061375   case 4:
r8042r8043
11101379      else
11111380         hfdc_rom_offset &= ~0x1000;
11121381      cru_sel = data;
1113      logerror("CRU sel %d\n", cru_sel);
11141382      break;
11151383
11161384   case 9:
r8042r8043
11351403         hfdc_ram_offset[(offset-9)/5] &= ~(0x400 << ((offset-9)%5));
11361404      break;
11371405   }
1406//   printf("hfdc cru write bit %d = %d\n", offset, data);
11381407}
11391408
11401409
11411410/*
1142    read a byte in disk DSR space
1411   read a byte in disk DSR space
1412   HFDC manual, p. 44
1413   Memory map as seen by the 99/4A PEB
1414   
1415   0x4000 - 0x4fbf   one of four possible ROM pages
1416   0x4fc0 - 0x4fcf   tape select
1417   0x4fd0 - 0x4fdf   disk controller select
1418   0x4fe0 - 0x4fff   time chip select
1419   
1420   0x5000 - 0x53ff   static RAM page 0x10
1421   0x5400 - 0x57ff   static RAM page any of 32 pages
1422   0x5800 - 0x5bff   static RAM page any of 32 pages
1423   0x5c00 - 0x5fff   static RAM page any of 32 pages   
11431424*/
11441425static  READ8_HANDLER(hfdc_mem_r)
11451426{
1146   int reply = 0;
1427   running_device *device = devtag_get_device(space->machine, "smc92x4");
11471428
1148   if (offset < 0x0fc0)
1429   if (offset >= 0x0000 && offset <= 0x0fbf)
11491430   {
11501431      /* dsr ROM */
1151      reply = ti99_disk_DSR[hfdc_rom_offset+offset];
1432      return ti99_disk_DSR[hfdc_rom_offset+offset];
11521433   }
1153   else if (offset < 0x0fd0)
1434   
1435   if (offset >= 0xfc0 && offset <= 0x0fcf)
11541436   {
11551437      /* tape controller */
1438      logerror("99_dsk: Tape support not available (access to offset %04x)\n", offset);
1439      return 0;
11561440   }
1157   else if (offset < 0x0fe0)
1441
1442   if (offset >= 0xfd0 && offset <= 0x0fdf)
1443        {
1444                /* Disk controller. Note that the odd addresses are ignored and
1445                   the addresses used for the write ports are also masked away
1446                   since the write operations in the ti99 system are always
1447                   accompanied by read operations before.
1448                */
1449                if ((offset & 3) == 0x00)
1450                {
1451                     return smc92x4_r(device, (offset>>2)&1);
1452                }
1453                else return 0;
1454        }
1455   if (offset >= 0x0fe0 && offset <= 0x0fff)
11581456   {
1159      /* disk controller */
1160      switch (offset)
1457      /* Real-time clock. Again, ignore odd addresses. */
1458      if ((offset & 1) == 0)
11611459      {
1162      case 0x0fd0:
1163         reply = smc92x4_r(space->machine,0, 0);
1164         //logerror("hfdc9234 data read\n");
1165         break;
1166
1167      case 0x0fd4:
1168         reply = smc92x4_r(space->machine,0, 1);
1169         //logerror("hfdc9234 status read\n");
1170         break;
1460         running_device *clock = devtag_get_device(space->machine, "mm58274c_floppy");
1461         return mm58274c_r(clock, (offset - 0x0fe0) >> 1);
11711462      }
1172      if (offset >= 0x0fd8)
1173         logerror("hfdc9234 read %d\n", offset);
1463      else return 0;
11741464   }
1175   else if (offset < 0x1000)
1465
1466   if (offset >= 0x1000 && offset <= 0x13ff)
11761467   {
1177      /* rtc */
1178      if (! (offset & 1))
1179         reply = mm58274c_r(devtag_get_device(space->machine, "mm58274c_floppy"), (offset - 0x1FE0) >> 1);
1180   }
1181   else if (offset < 0x1400)
1182   {
11831468      /* ram page >08 (hfdc manual says >10) */
1184      reply = hfdc_ram[0x2000+(offset-0x1000)];
1469      return hfdc_ram[0x2000+(offset-0x1000)];
11851470   }
1186   else
1187   {
1188      /* ram with mapper */
1189      reply = hfdc_ram[hfdc_ram_offset[(offset-0x1400) >> 10]+((offset-0x1000) & 0x3ff)];
1190   }
1191   return reply;
1471   
1472   /* The remaining space is ram with mapper:
1473      1400, 1800, 1c00 are the three banks; get the pointer
1474      plus the offset within the bank
1475   */
1476   return hfdc_ram[hfdc_ram_offset[(offset-0x1400) >> 10] + (offset & 0x3ff)];
11921477}
11931478
11941479/*
r8042r8043
11961481*/
11971482static WRITE8_HANDLER(hfdc_mem_w)
11981483{
1199   if (offset < 0x0fc0)
1484   running_device *diskcnt = devtag_get_device(space->machine, "smc92x4");
1485
1486   if (offset >= 0x0000 && offset <= 0x0fbf)
12001487   {
12011488      /* dsr ROM */
1489      logerror("99_dsk: Writing to HFDC ROM ignored (access to offset %04x)\n", offset);
1490      return;
12021491   }
1203   else if (offset < 0x0fd0)
1492   
1493   if (offset >= 0xfc0 && offset <= 0x0fcf)
12041494   {
12051495      /* tape controller */
1496      logerror("99_dsk: Tape support not available (access to offset %04x)\n", offset);
1497      return;
12061498   }
1207   else if (offset < 0x0fe0)
1499
1500   if (offset >= 0xfd0 && offset <= 0x0fdf)
1501        {
1502                /* Disk controller. Note that the odd addresses are ignored. */
1503                if ((offset & 3) == 0x02)   /* 0x0fd2 and 0x0fd6 */
1504                {
1505                     smc92x4_w(diskcnt, (offset>>2)&1, data);
1506                }
1507                return;
1508        }
1509
1510   if (offset >= 0x0fe0 && offset <= 0x0fff)
12081511   {
1209      /* disk controller */
1210      switch (offset)
1512      /* Real-time clock. Again, ignore odd addresses. */
1513      if ((offset & 1) == 0)
12111514      {
1212      case 0x0fd2:
1213         smc92x4_w(space->machine,0, 0, data);
1214         //logerror("hfdc9234 data write %d\n", data);
1215         break;
1216
1217      case 0x0fd6:
1218         smc92x4_w(space->machine,0, 1, data);
1219         //logerror("hfdc9234 command write %d\n", data);
1220         break;
1515         running_device *clock = devtag_get_device(space->machine, "mm58274c_floppy");
1516         mm58274c_w(clock, (offset - 0x0fe0) >> 1, data);
12211517      }
1222      if (offset >= 0x0fd8)
1223         logerror("hfdc9234 write %d %d\n", offset, data);
1518      return;
12241519   }
1225   else if (offset < 0x1000)
1520
1521   if (offset >= 0x1000 && offset <= 0x13ff)
12261522   {
1227      /* rtc */
1228      if (! (offset & 1))
1229         mm58274c_w(devtag_get_device(space->machine, "mm58274c_floppy"), (offset - 0x1FE0) >> 1, data);
1230   }
1231   else if (offset < 0x1400)
1232   {
12331523      /* ram page >08 (hfdc manual says >10) */
12341524      hfdc_ram[0x2000+(offset-0x1000)] = data;
1525      return;
12351526   }
1236   else
1237   {
1238      /* ram with mapper */
1239      hfdc_ram[hfdc_ram_offset[(offset-0x1400) >> 10]+((offset-0x1000) & 0x3ff)] = data;
1240   }
1527   
1528   /* The remaining space is ram with mapper:
1529      1400, 1800, 1c00 are the three banks; get the pointer
1530      plus the offset within the bank
1531   */   
1532//   if ((offset&0x0f)==0) printf("\n");
1533//   printf("%02x ", data);
1534     
1535   hfdc_ram[hfdc_ram_offset[(offset-0x1400) >> 10] + (offset & 0x3ff)] = data;
12411536}
1242
src/mess/machine/99_dsk.h
r8042r8043
11#ifndef TI99_DSK_H_
22#define TI99_DSK_H_
33
4#include "machine/wd17xx.h"
4#include "wd17xx.h"
5#include "smc92x4.h"
56#include "formats/flopimg.h"
67
78/* Note: this currently mirrors the flag in ti99_4x.h */
r8042r8043
1819int ti99_image_in_80_track_drive(void);
1920
2021extern const wd17xx_interface ti99_wd17xx_interface;
22extern const smc92x4_interface ti99_smc92x4_interface;
23
2124#endif /* TI99_DSK_H_ */
src/mess/machine/geneve.c
r8042r8043
4646*/
4747/* TRUE if speech synthesizer present */
4848static char has_speech;
49/* floppy disk controller type */
50static fdc_kind_t fdc_kind;
49
5150/* TRUE if ide card present */
5251static char has_ide;
5352/* TRUE if rs232 card present */
r8042r8043
5756/* TRUE if usb-sm card present */
5857static char has_usb_sm;
5958
60/* TRUE if we are using the alternative boot ROM */
61static char has_alt_boot;
62
6359/* keyboard interface */
6460static int JoySel;
6561enum
r8042r8043
132128/* tms9995_ICount: used to implement memory waitstates (hack) */
133129/* NPW 23-Feb-2004 - externs no longer needed because we now use cpu_adjust_icount(devtag_get_device(space->machine, "maincpu"),) */
134130
131enum
132{
133   BOOT_V09 = 0,
134   BOOT_V10 = 1
135};
135136
136
137137/*===========================================================================*/
138138/*
139139    General purpose code:
r8042r8043
196196   KeyReset = 1;
197197
198198   /* read config */
199   has_speech = (input_port_read(machine, "CFG") >> config_speech_bit) & config_speech_mask;
200   fdc_kind = (fdc_kind_t)((input_port_read(machine, "CFG") >> config_fdc_bit) & config_fdc_mask);
201   has_ide = (input_port_read(machine, "CFG") >> config_ide_bit) & config_ide_mask;
202   has_rs232 = (input_port_read(machine, "CFG") >> config_rs232_bit) & config_rs232_mask;
203   has_usb_sm = (input_port_read(machine, "CFG") >> config_usbsm_bit) & config_usbsm_mask;
204   has_alt_boot = (input_port_read(machine, "CFG") >> config_boot_bit) & config_boot_mask;
199   has_speech = input_port_read(machine, "SPEECH");
200   has_ide =  input_port_read(machine, "HDCTRL") & HD_IDE;
201   has_rs232 = input_port_read(machine, "SERIAL") & SERIAL_TI;
202   has_usb_sm = input_port_read(machine, "HDCTRL") & HD_USB;
205203
206204   /* set up optional expansion hardware */
207205   ti99_peb_reset(0, inta_callback, intb_callback);
r8042r8043
209207   if (has_speech)
210208   {
211209      static const spchroms_interface speech_intf = { region_speech_rom };
212
213210      spchroms_config(machine, &speech_intf);
214211   }
215212
216   switch (fdc_kind)
213   switch (input_port_read(machine, "DISKCTRL"))
217214   {
218   case fdc_kind_TI:
215   case DISK_TIFDC:
219216      ti99_fdc_reset(machine);
220217      break;
221218#if HAS_99CCFDC
222   case fdc_kind_CC:
219   case DISK_CC:
223220      ti99_ccfdc_reset(machine);
224221      break;
225222#endif
226   case fdc_kind_BwG:
223   case DISK_BWG:
227224      ti99_bwg_reset(machine);
228225      break;
229   case fdc_kind_hfdc:
226   case DISK_HFDC:
230227      ti99_hfdc_reset(machine);
231228      break;
232   case fdc_kind_none:
229   case DISK_NONE:
233230      break;
234231   }
235232
r8042r8043
545542   offset &= 0x1fff;
546543
547544   /* Although we could have 128K boot ROM (page f0...ff), the stock
548       Geneve only has 16K. The address is incompletely decoded, so page
549       f0 is mirrored on all even pages up to fe, and f1 is mirrored on
550       f3, f5, ... ff.
551       Currently, MESS is delivered with the 16K ROM only. So for the time
552       being, we won't lose much if we mask the page bits.
553       Michael Zapf, 2008-01-23
554    */
545   Geneve only has 16K. The address is incompletely decoded, so page
546   f0 is mirrored on all even pages up to fe, and f1 is mirrored on
547   f3, f5, ... ff.
548   Currently, MESS is delivered with the 16K ROM only. So for the time
549   being, we won't lose much if we mask the page bits.
550   Michael Zapf, 2008-01-23
551   */
555552   if (page > 0xf1) page &= 0xf1;
556553
557554   switch (page)
r8042r8043
559556   case 0xf0:
560557   case 0xf1:
561558      /* Boot ROM */
562      if (has_alt_boot) return AROM_ptr[(page-0xf0)*0x2000 + offset];
563      else return ROM_ptr[(page-0xf0)*0x2000 + offset];
559      if (input_port_read(space->machine, "BOOTROM")==BOOT_V09)
560         return AROM_ptr[(page-0xf0)*0x2000 + offset];
561      else
562         return ROM_ptr[(page-0xf0)*0x2000 + offset];
564563
565564   case 0xe8:
566565   case 0xe9:
src/mess/machine/smc92x4.c
r8042r8043
11/*
2    SMC9224 and SMC9234 Hard and Floppy Disk Controller (HFDC)
2   HDC9224 and HDC9234 Hard and Floppy Disk Controller (HFDC)
33
4    This controller handles MFM and FM encoded floppy disks and hard disks.
5    The SMC9224 is used in some DEC systems.  The SMC9234 is used in the Myarc
6    HFDC card for the TI99/4a.  The main difference between the two chips is
7    the way the ECC bytes are computed; there are differences in the way seek
8    times are computed, too.
4   This controller handles MFM and FM encoded floppy disks and hard disks.
5   The SMC9224 is used in some DEC systems.  The HDC9234 is used in the
6   Myarc HFDC card for the TI99/4a.  The main difference between the two
7   chips is the way the ECC bytes are computed; there are differences in
8   the way seek times are computed, too.
9   
10   References:
11   * SMC HDC9234 preliminary data book (1988)
12   
13   Michael Zapf, April 2010
914
10    References:
11    * SMC HDC9234 preliminary data book (1988)
12
13    Raphael Nabet, 2003
15   First version by Raphael Nabet, 2003
1416*/
1517
1618#include "emu.h"
1719#include "devices/flopdrv.h"
20#include "devices/harddriv.h"
21#include "harddisk.h"
1822
1923#include "smc92x4.h"
2024
21#define MAX_HFDC 1
22#define MAX_SECTOR_LEN 2048   /* ??? */
25/***************************************************************************
26    TYPE DEFINITIONS
27***************************************************************************/
2328
2429/*
25    hfdc state structure
26*/
27typedef struct hfdc_t
28{
29   UINT8 status;      /* command status register */
30   UINT8 disk_sel;      /* disk selection state */
31   UINT8 regs[10+6];   /* 4th through 10th registers are actually 2 distinct
32                        registers each (one is r/o and the other w/o).  The
33                        11th register ("data") is only used for communication
34                        with the drive in non-DMA modes??? */
35   int reg_ptr;
36   int (*select_callback)(int which, select_mode_t select_mode, int select_line, int gpos);
37   UINT8 (*dma_read_callback)(int which, offs_t offset);
38   void (*dma_write_callback)(int which, offs_t offset, UINT8 data);
39   void (*int_callback)(int which, int state);
40} hfdc_t;
41
42enum
43{
44   disk_sel_none = (UINT8) -1
45};
46
47enum
48{
49   hfdc_reg_dma_low = 0,
50   hfdc_reg_dma_mid,
51   hfdc_reg_dma_high,
52   hfdc_reg_des_sector,
53   hfdc_reg_des_head,
54   hfdc_reg_des_cyl,
55   hfdc_reg_sector_count,
56   hfdc_reg_retry_count,
57   hfdc_reg_mode,
58   hfdc_reg_term,
59      hfdc_reg_cur_head,
60      hfdc_reg_cur_cyl,
61      hfdc_reg_read_6,
62      hfdc_reg_read_7,
63      hfdc_reg_chip_stat,
64      hfdc_reg_drive_stat
65};
66
67/*
6830    Definition of bits in the status register
6931*/
70#define ST_INTPEND   (1<<7)      /* interrupt pending */
71#define ST_DMAREQ   (1<<6)      /* DMA request */
72#define ST_DONE      (1<<5)      /* command done */
73#define ST_TERMCOD   (3<<3)      /* termination code (see below) */
74#define ST_RDYCHNG   (1<<2)      /* ready change */
75#define ST_OVRUN   (1<<1)      /* overrun/underrun */
76#define ST_BADSECT   (1<<0)      /* bad sector */
32#define ST_INTPEND   0x80      /* interrupt pending */
33#define ST_DMAREQ   0x40      /* DMA request */
34#define ST_DONE      0x20      /* command done */
35#define ST_TERMCOD   0x18      /* termination code (see below) */
36#define ST_RDYCHNG   0x04      /* ready change */
37#define ST_OVRUN   0x02      /* overrun/underrun */
38#define ST_BADSECT   0x01      /* bad sector */
7739
7840/*
79    Definition of the termination codes
41    Definition of the termination codes (INT_STATUS)
8042*/
81#define ST_TC_SUCCESS   (0<<3)   /* Successful completion */
82#define ST_TC_RDIDERR   (1<<3)   /* Error in READ-ID sequence */
83#define ST_TC_VRFYERR   (2<<3)   /* Error in VERIFY sequence */
84#define ST_TC_DATAERR   (3<<3)   /* Error in DATA-TRANSFER seq. */
43#define ST_TC_SUCCESS   0x00   /* Successful completion */
44#define ST_TC_RDIDERR   0x08   /* Error in READ-ID sequence */
45#define ST_TC_SEEKERR   0x10   /* Error in SEEK sequence */
46#define ST_TC_DATAERR   0x18   /* Error in DATA-TRANSFER seq. */
8547
8648
8749/*
8850    Definition of bits in the Termination-Conditions register
8951*/
90#define TC_CRCPRE   (1<<7)      /* CRC register preset, must be 1 */
91#define TC_UNUSED   (1<<6)      /* bit 6 is not used and must be 0 */
92#define TC_INTDONE   (1<<5)      /* interrupt on done */
93#define TC_TDELDAT   (1<<4)      /* terminate on deleted data */
94#define TC_TDSTAT3   (1<<3)      /* terminate on drive status 3 change */
95#define TC_TWPROT   (1<<2)      /* terminate on write-protect (FDD only) */
96#define TC_INTRDCH   (1<<1)      /* interrupt on ready change (FDD only) */
97#define TC_TWRFLT   (1<<0)      /* interrupt on write-fault (HDD only) */
52#define TC_CRCPRE   0x80      /* CRC register preset, must be 1 */
53#define TC_UNUSED   0x40      /* bit 6 is not used and must be 0 */
54#define TC_INTDONE   0x20      /* interrupt on done */
55#define TC_TDELDAT   0x10      /* terminate on deleted data */
56#define TC_TDSTAT3   0x08      /* terminate on drive status 3 change */
57#define TC_TWPROT   0x04      /* terminate on write-protect (FDD only) */
58#define TC_INTRDCH   0x02      /* interrupt on ready change (FDD only) */
59#define TC_TWRFLT   0x01      /* interrupt on write-fault (HDD only) */
9860
9961/*
10062    Definition of bits in the Chip-Status register
10163*/
102#define CS_RETREQ   (1<<7)      /* retry required */
103#define CS_ECCATT   (1<<6)      /* ECC correction attempted */
104#define CS_ECCERR   (1<<5)      /* ECC/CRC error */
105#define CS_DELDATA   (1<<4)      /* deleted data mark */
106#define CS_SYNCERR   (1<<3)      /* synchronization error */
107#define CS_COMPERR   (1<<2)      /* compare error */
108#define CS_PRESDRV   (3<<0)      /* present drive selected */
64#define CS_RETREQ   0x80      /* retry required */
65#define CS_ECCATT   0x40      /* ECC correction attempted */
66#define CS_CRCERR   0x20      /* ECC/CRC error */
67#define CS_DELDATA   0x10      /* deleted data mark */
68#define CS_SYNCERR   0x08      /* synchronization error */
69#define CS_COMPERR   0x04      /* compare error */
70#define CS_PRESDRV   0x03      /* present drive selected */
10971
11072/*
111    Definition of bits in the Disk-Status register
73   Definition of bits in the Mode register
11274*/
113#define DS_SELACK   (1<<7)      /* select acknowledge (harddisk only!) */
114#define DS_INDEX   (1<<6)      /* index point */
115#define DS_SKCOM   (1<<5)      /* seek complete */
116#define DS_TRK00   (1<<4)      /* track 0 */
117#define DS_DSTAT3   (1<<3)      /* drive status 3 (MBZ) */
118#define DS_WRPROT   (1<<2)      /* write protect (floppy only!) */
119#define DS_READY   (1<<1)      /* drive ready bit */
120#define DS_WRFAULT   (1<<0)      /* write fault */
75#define MO_TYPE      0x80      /* Hard disk (1) or floppy (0) */
76#define MO_CRCECC   0x60      /* Values for CRC/ECC handling */
77#define MO_DENSITY   0x10      /* FM = 1; MFM = 0 */
78#define MO_UNUSED   0x08      /* Unused, 0 */
79#define MO_STEPRATE   0x07      /* Step rates */
12180
122static hfdc_t hfdc[MAX_HFDC];
123
12481/*
125    Perform the read id field sequence for a floppy disk (but do not perform
126    any implied seek)
82   hfdc state structure
12783
128    which: udc controller index
129    disk_unit: floppy drive index
130    head: selected head
84   status
85   ab7      ecc error
86   ab6      index pulse
87   ab5      seek complete
88   ab4      track 0
89   ab3      user-defined
90   ab2      write-protected
91   ab1      drive ready
92   ab0      write fault
93   
94   output1
95   ab7      drive select 3
96   ab6      drive select 2
97   ab5      drive select 1
98   ab4      drive select 0
99   ab3      programmable outputs
100   ab2      programmable outputs
101   ab1      programmable outputs
102   ab0      programmable outputs
103   
104   output2
105   ab7      drive select 3* (active low, used for tape operations)
106   ab6      reduce write current
107    ab5      step direction
108   ab4      step pulse
109   ab3      desired head 3
110   ab2      desired head 2
111   ab1      desired head 1
112   ab0      desired head 0
131113*/
132static int floppy_read_id(running_machine *machine,int which, int disk_unit, int head)
114
115#define OUT1_DRVSEL3   0x80
116#define OUT1_DRVSEL2   0x40
117#define OUT1_DRVSEL1   0x20
118#define OUT1_DRVSEL0   0x10
119#define OUT2_DRVSEL3_   0x80
120#define OUT2_REDWRT   0x40
121#define OUT2_STEPDIR   0x20
122#define OUT2_STEPPULSE   0x10
123#define OUT2_HEADSEL3   0x08
124#define OUT2_HEADSEL2   0x04
125#define OUT2_HEADSEL1   0x02
126#define OUT2_HEADSEL0   0x01
127
128#define DRIVE_TYPE    0x03
129#define TYPE_AT    0x00
130#define TYPE_FLOPPY    0x02  /* for testing on any floppy type */
131#define TYPE_FLOPPY8    0x02
132#define TYPE_FLOPPY5    0x03
133
134#define MAX_SECTOR_LEN 256
135
136#define FORMAT_LONG FALSE
137
138#define ERROR    0
139#define DONE    1
140#define AGAIN   2
141#define UNDEF   3
142
143typedef struct _smc92x4_state
133144{
134   running_device *disk_img = floppy_get_device(machine, disk_unit);
135   UINT8 revolution_count;
136   chrn_id id;
145   devcb_resolved_write_line    out_intrq_func;      /* INT line */
146   devcb_resolved_write_line    out_dip_func;      /* DMA in progress line */
147   devcb_resolved_write8       out_auxbus_func;   /* AB0-7 lines (using S0,S1 as address) */
148   devcb_resolved_read_line   in_auxbus_func;      /* AB0-7 lines (only single case) */
137149
138   revolution_count = 0;
150   UINT8 output1;      /* UDC-internal register "output1" */
151   UINT8 output2;      /* UDC-internal register "output2" */
152   
153   int   selected_drive_type;
154   /* We need to store the types, although this is not the case in the
155   real hardware. The reason is that poll_drives wants to select the drives
156   without knowing their kinds. In reality this does not matter, since we
157   only check for the seek_complete line, but in our case, floppy and
158   harddrive are pretty different, and we need to know which one to check. */
159   int   types[4];
160   int   head_load_delay_enable;
161   int   register_pointer;
162   
163   UINT8 register_r[12];   
164   UINT8 register_w[12];   
139165
140   while (revolution_count < 4)
141   {
142      if (floppy_drive_get_next_id(disk_img, head, &id))
143      {
144         hfdc[which].regs[hfdc_reg_cur_cyl] = id.C;
145         hfdc[which].regs[hfdc_reg_cur_head] = id.H;
146         hfdc[which].regs[hfdc_reg_read_6] = 0xfe;   /* ident byte */
147         if (id.flags & ID_FLAG_DELETED_DATA)
148            hfdc[which].regs[hfdc_reg_chip_stat] |= CS_DELDATA;
149         return TRUE;
150      }
151   }
166   /* timers to delay execution/completion of commands */
167   emu_timer *timer_data, *timer_rs, *timer_ws, *timer_seek, *timer_track;
152168
153   hfdc[which].status |= ST_TC_RDIDERR;
154   hfdc[which].regs[hfdc_reg_chip_stat] |= CS_SYNCERR;
155   return FALSE;
156}
169   /* Flag which determines whether to use realistic timing. */
170   int use_real_timing;
171   
172   /* Required to store the current iteration within restore. */
173   int seek_count;
174   
175   /* Recent command. */
176   UINT8 command;
177   
178   /* Stores the step direction. */
179   int step_direction;
180   
181   /* Stores the buffered flag. */
182   int buffered;
183   
184   /* Stores the recent id field. */
185   chrn_id_hd recent_id;
186   
187   /* Indicates whether an ID has been found. */
188   int found_id;
189   
190   /* Indicates whether we are already past the seek_id phase in read/write sector. */
191   int after_seek;
192   
193   /* Determines whether the command will be continued. */
194   int to_be_continued;   
195   
196   /* Pointer to interface */
197   const smc92x4_interface *intf;
198   
199} smc92x4_state;
157200
158/*
159    Perform the verify sequence for a floppy disk
201/*
202   Step rates in microseconds for MFM. This is set in the mode register,
203   bits 0-2. Single density doubles all values.
204*/
205static const int step_hd[]    = { 22, 50, 100, 200, 400, 800, 1600, 3200 };
206static const int step_flop8[]    = { 218, 500, 1000, 2000, 4000, 8000, 16000, 32000 };
207static const int step_flop5[]    = { 436, 1000, 2000, 4000, 8000, 16000, 32000, 64000 };
160208
161    which: udc controller index
162    disk_unit: floppy drive index
209/*
210   0.2 seconds for a revolution (300 rpm), +50% average waiting for index
211   hole. Should be properly done with the index hole detection; we're
212   simulating this with a timer for now.
163213*/
164static int floppy_find_sector(running_machine *machine,int which, int disk_unit, int cylinder, int head, int check_secnum, int sector, int *sector_data_id, int *sector_len)
214#define TRACKTIME_FLOPPY 300000   
215#define TRACKTIME_HD 1000   
216
217/*
218   Register names of the HDC. The left part is the set of write registers,
219   while the right part are the read registers.
220*/
221enum
165222{
166   running_device *disk_img = floppy_get_device(machine, disk_unit);
167   UINT8 revolution_count;
168   chrn_id id;
223    DMA7_0=0,
224   DMA15_8=1,
225   DMA23_16=2,
226   DESIRED_SECTOR=3,
227   DESIRED_HEAD=4,    CURRENT_HEAD=4,
228   DESIRED_CYLINDER=5,    CURRENT_CYLINDER=5,
229   SECTOR_COUNT=6,    CURRENT_IDENT=6,
230   RETRY_COUNT=7,       TEMP_STORAGE2=7,
231   MODE=8,       CHIP_STATUS=8,
232   INT_COMM_TERM=9,    DRIVE_STATUS=9,
233   DATA_DELAY=10,       DATA=10,
234   COMMAND=11,       INT_STATUS=11
235};
169236
170   revolution_count = 0;
237#define TRKSIZE_DD      6144
238#define TRKSIZE_SD      3172
171239
172   while (revolution_count < 4)
173   {
174      if (floppy_drive_get_next_id(disk_img, head, &id))
175      {
176         /* compare id values */
177         if ((id.C == cylinder) && (id.H == head) && ((id.R == sector) || ! check_secnum))
178         {
179            * sector_data_id = id.data_id;
180            * sector_len = 1 << (id.N+7);
181            assert((* sector_len) < MAX_SECTOR_LEN);
240/***************************************************************************
241    PROTOTYPES
242***************************************************************************/
182243
183            hfdc[which].regs[hfdc_reg_cur_cyl] = id.C;
184            hfdc[which].regs[hfdc_reg_cur_head] = id.H;
185            hfdc[which].regs[hfdc_reg_read_6] = 0xfe;   /* ident byte (right???) */
186            if (id.flags & ID_FLAG_DELETED_DATA)
187               hfdc[which].regs[hfdc_reg_chip_stat] |= CS_DELDATA;
188            else
189               hfdc[which].regs[hfdc_reg_chip_stat] &= ~CS_DELDATA;
190            return TRUE;
191         }
192      }
244static void smc92x4_process_after_callback(running_device *device);
245static void data_transfer_read(running_device *device, chrn_id_hd id, int transfer_enable);
246static void data_transfer_write(running_device *device, chrn_id_hd id, int deldata, int redcur, int precomp, int write_long);
193247
194       /* index set? */
195      if (floppy_drive_get_flag_state(disk_img, FLOPPY_DRIVE_INDEX))
196      {
197         /* update revolution count */
198         revolution_count++;
199      }
200   }
201
202   return FALSE;
248#if 0
249static void dump_contents(UINT8 *buffer, int length)
250{
251        for (int i=0; i < length; i+=16)
252        {
253                for (int j=0; j < 16; j+=2)
254                {
255                        printf("%02x%02x ", buffer[i+j], buffer[i+j+1]);
256                }
257                printf("\n");
258        }
203259}
260#endif
204261
205static int smc92x4_floppy_read_sector(running_machine *machine,int which, int disk_unit, int cylinder, int head, int check_secnum, int sector, int *dma_address)
262INLINE smc92x4_state *get_safe_token(running_device *device)
206263{
207   int sector_data_id, sector_len;
208   UINT8 buf[MAX_SECTOR_LEN];
209   int i;
210   running_device *disk_img = floppy_get_device(machine, disk_unit);
264   assert(device != NULL);
265   assert(device->token != NULL);
266   return (smc92x4_state *)device->token;
267}
211268
212   if (! floppy_find_sector(machine,which, disk_unit, cylinder, head, check_secnum, sector, & sector_data_id, & sector_len))
213   {
214      hfdc[which].status |= ST_TC_RDIDERR;
215      return FALSE;
216   }
217269
218   floppy_drive_read_sector_data(disk_img, head, sector_data_id, (char *) buf, sector_len);
219   for (i=0; i<sector_len; i++)
220   {
221      (*hfdc[which].dma_write_callback)(which, *dma_address, buf[i]);
222      *dma_address = ((*dma_address) + 1) & 0xffffff;
223   }
224   return TRUE;
270static int image_is_single_density(running_device *current_floppy)
271{
272        floppy_image *image = flopimg_get_image(current_floppy);
273   return (floppy_get_track_size(image, 0, 0)<4000);
225274}
226275
227static int smc92x4_floppy_write_sector(running_machine *machine,int which, int disk_unit, int cylinder, int head, int check_secnum, int sector, int *dma_address)
276static int controller_set_to_single_density(running_device *device)
228277{
229   int sector_data_id, sector_len;
230   UINT8 buf[MAX_SECTOR_LEN];
231   int i;
232   running_device *disk_img = floppy_get_device(machine, disk_unit);
278   smc92x4_state *w = get_safe_token(device);
279   return ((w->register_w[MODE]&MO_DENSITY)!=0);
280}
233281
234   if (! floppy_find_sector(machine,which, disk_unit, cylinder, head, check_secnum, sector, & sector_data_id, & sector_len))
235   {
236      hfdc[which].status |= ST_TC_RDIDERR;
237      return FALSE;
238   }
282static void copyid(chrn_id id1, chrn_id_hd *id2)
283{
284   id2->C = id1.C & 0xff;
285   id2->H = id1.H;
286   id2->R = id1.R;
287   id2->N = id1.N;
288   id2->data_id = id1.data_id;
289   id2->flags = id1.flags;
290}
239291
240   for (i=0; i<sector_len; i++)
292/*
293    Set IRQ
294*/
295static void smc92x4_set_interrupt(running_device *device)
296{
297   smc92x4_state *w = get_safe_token(device);
298   if ((w->register_r[INT_STATUS] & ST_INTPEND) == 0)
241299   {
242      buf[i] = (*hfdc[which].dma_read_callback)(which, *dma_address);
243      *dma_address = ((*dma_address) + 1) & 0xffffff;
300      w->register_r[INT_STATUS] |= ST_INTPEND;
301      devcb_call_write_line(&w->out_intrq_func, ASSERT_LINE);
244302   }
245   floppy_drive_write_sector_data(disk_img, head, sector_data_id, (char *) buf, sector_len, FALSE);
246   return TRUE;
247303}
248304
249static void floppy_step(running_machine *machine,int which, int disk_unit, int direction)
305/*
306    Set DMA in progress
307*/
308static void smc92x4_set_dip(running_device *device, int value)
250309{
251   running_device *disk_img = floppy_get_device(machine, disk_unit);
252   floppy_drive_seek(disk_img, direction);
310   smc92x4_state *w = get_safe_token(device);
311   devcb_call_write_line(&w->out_dip_func, value);
253312}
254313
255static UINT8 floppy_get_disk_status(running_machine *machine,int which, int disk_unit)
314/*
315    Assert Command Done status bit, triggering interrupts as needed
316*/
317static void set_command_done(running_device *device, int flags)
256318{
257   running_device *disk_img = floppy_get_device(machine, disk_unit);
258   int reply = 0;
319   //assert(! (w->status & ST_DONE))
320   smc92x4_state *w = get_safe_token(device);
321   //printf("smc92x4 command %02x done, flags=%02x\n", w->command, flags);
322   
323   w->register_r[INT_STATUS] |= ST_DONE;
324   w->register_r[INT_STATUS] &= ~ST_TERMCOD; /* clear the previously set flags */
325   w->register_r[INT_STATUS] |= flags;
259326
260   if (floppy_drive_get_flag_state(disk_img, FLOPPY_DRIVE_INDEX) == FLOPPY_DRIVE_INDEX)
261      reply |= DS_INDEX;
262   if (floppy_tk00_r(disk_img) == CLEAR_LINE)
263      reply |= DS_TRK00;
264   if (floppy_wpt_r(disk_img) == CLEAR_LINE)
265      reply |= DS_WRPROT;
266   if (image_exists(disk_img))
267      reply |= DS_READY;
268
269   reply |= DS_SKCOM;
270
271   return reply;
327   /* sm92x4 spec, p. 6 */   
328   if (w->register_w[INT_COMM_TERM] & TC_INTDONE)
329      smc92x4_set_interrupt(device);
272330}
273331
274#include "devices/harddriv.h"
275#include "harddisk.h"
276
277static struct
332/*
333   Preserve previously set termination code
334*/
335static void set_command_done(running_device *device)
278336{
279   hard_disk_file *hd_handle;
280   unsigned int wp : 1;      /* TRUE if disk is write-protected */
281   int current_cylinder;
337   //assert(! (w->status & ST_DONE))
338   smc92x4_state *w = get_safe_token(device);
339   //printf("smc92x4 command %02x done\n", w->command);
282340
283   /* disk geometry */
284   unsigned int cylinders, heads, sectors_per_track, bytes_per_sector;
285} hd[10];
341   w->register_r[INT_STATUS] |= ST_DONE;
286342
287static int get_id_from_device( running_device *device )
343   /* sm92x4 spec, p. 6 */   
344   if (w->register_w[INT_COMM_TERM] & TC_INTDONE)
345      smc92x4_set_interrupt(device);
346}
347
348/*
349    Clear IRQ
350*/
351static void smc92x4_clear_interrupt(running_device *device)
288352{
289   int id = -1;
290
291   if ( ! strcmp( "harddisk1", device->tag() ) )
353   smc92x4_state *w = get_safe_token(device);
354   if ((w->register_r[INT_STATUS] & ST_INTPEND) != 0)
292355   {
293      id = 0;
356      devcb_call_write_line(&w->out_intrq_func, CLEAR_LINE);
294357   }
295   else if ( ! strcmp( "harddisk2", device->tag() ) )
296   {
297      id = 1;
298   }
299   else if ( ! strcmp( "harddisk3", device->tag() ) )
300   {
301      id = 2;
302   }
303   assert( id >= 0 );
358}
304359
305   return id;
360/*
361   Sets the DMA address on the external counter. This counter is attached
362   to the auxiliary bus on the PCB.
363*/
364static void set_dma_address(running_device *device, int pos2316, int pos1508, int pos0700)
365{   
366   smc92x4_state *w = get_safe_token(device);
367   devcb_call_write8(&w->out_auxbus_func, OUTPUT_DMA_ADDR, w->register_r[pos2316]);
368   devcb_call_write8(&w->out_auxbus_func, OUTPUT_DMA_ADDR, w->register_r[pos1508]);
369   devcb_call_write8(&w->out_auxbus_func, OUTPUT_DMA_ADDR, w->register_r[pos0700]);   
306370}
307371
372static void dma_add_offset(running_device *device, int offset)
373{
374   smc92x4_state *w = get_safe_token(device);
375   int dma_address = (w->register_w[DMA23_16]<<16) + (w->register_w[DMA15_8]<<8) + w->register_w[DMA7_0];
376   dma_address += offset;
377   
378   w->register_w[DMA23_16] = w->register_r[DMA23_16] = (dma_address & 0xff0000)>>16;
379   w->register_w[DMA15_8]  = w->register_r[DMA15_8]  = (dma_address & 0x00ff00)>>8;
380   w->register_w[DMA7_0]   = w->register_r[DMA7_0]   = (dma_address & 0x0000ff);
381}
308382
309static DEVICE_IMAGE_LOAD(smc92x4_hd)
383/*
384   Get the state from outside and latch it in the register.
385   There should be a bus driver on the PCB which provides the signals from
386   both the hard and floppy drives during S0=S1=0 and STB*=0 times via the
387   auxiliary bus.
388*/
389static void sync_status_in(running_device *device)
310390{
311   const hard_disk_info *info;
391   UINT8 prev;
392   smc92x4_state *w = get_safe_token(device);
312393
313   if ( mess_hd_get_hard_disk_file(image) )
394   prev = w->register_r[DRIVE_STATUS];       
395   w->register_r[DRIVE_STATUS] = devcb_call_read_line(&w->in_auxbus_func);
396
397   /* Raise interrupt if ready changes. TODO: Check this more closely. */
398//   printf("disk status = %02x\n", reply);
399   if (((w->register_r[DRIVE_STATUS] & DS_READY) != (prev & DS_READY))
400      & (w->register_r[INT_STATUS] & ST_RDYCHNG))
314401   {
315      int disk_unit = get_id_from_device( image );
316
317      hd[disk_unit].hd_handle = mess_hd_get_hard_disk_file(image);
318      hd[disk_unit].wp = !image_is_writable(image);
319      hd[disk_unit].current_cylinder = 0;
320      info = hard_disk_get_info(hd[disk_unit].hd_handle);
321      hd[disk_unit].cylinders = info->cylinders;
322      hd[disk_unit].heads = info->heads;
323      hd[disk_unit].sectors_per_track = info->sectors;
324      hd[disk_unit].bytes_per_sector = info->sectorbytes;
325
326      if ((hd[disk_unit].cylinders > 2048) || (hd[disk_unit].heads > 16)
327            || (hd[disk_unit].sectors_per_track > 256)
328            || (hd[disk_unit].bytes_per_sector > 2048))
329      {
330         hd[disk_unit].hd_handle = NULL;
331         return INIT_FAIL;
332      }
333      if (hd[disk_unit].bytes_per_sector != 256)
334      {
335         hd[disk_unit].hd_handle = NULL;
336         return INIT_FAIL;
337      }
338      return INIT_PASS;
402      smc92x4_set_interrupt(device);
339403   }
340
341   return INIT_FAIL;
342404}
343405
344static DEVICE_IMAGE_UNLOAD(smc92x4_hd)
406/*
407   Push the output registers over the auxiliary bus. It is expected that
408   the PCB contains latches to store the values.
409*/
410static void sync_latches_out(running_device *device)
345411{
346   int disk_unit = get_id_from_device( image );
412   smc92x4_state *w = get_safe_token(device);
413   w->output1 = (w->output1 & 0xf0) | (w->register_w[RETRY_COUNT]&0x0f);
347414
348   hd[disk_unit].hd_handle = NULL;
415   devcb_call_write8(&w->out_auxbus_func, OUTPUT_OUTPUT1, w->output1);
416   devcb_call_write8(&w->out_auxbus_func, OUTPUT_OUTPUT2, w->output2);   
349417}
350418
351static int harddisk_read_id(int which, int disk_unit, int head)
419/*************************************************************
420   Timed requests and callbacks
421*************************************************************/
422#if 0
423/* setup a timed data request - data request will be triggered in a few usecs time */
424static void smc92x4_timed_data_request(running_device *device)
352425{
353   hfdc[which].regs[hfdc_reg_cur_cyl] = hd[disk_unit].current_cylinder & 0xff;
354   hfdc[which].regs[hfdc_reg_cur_head] = ((hd[disk_unit].current_cylinder >> 4) & 0x70) | head;
355   hfdc[which].regs[hfdc_reg_read_6] = 0xfe;   /* ident byte */
356   /*if ()
357        hfdc[which].regs[hfdc_reg_chip_stat] |= CS_DELDATA;*/
358
359   return TRUE;
426   smc92x4_state *w = get_safe_token(device);
427   int time = controller_set_to_single_density(device)? 128 : 32;
428   
429   if (!w->use_real_timing)
430      time = 1;
431   
432   /* set new timer */
433   timer_adjust_oneshot(w->timer_data, ATTOTIME_IN_USEC(time, 0));
360434}
435#endif
361436
362static int harddisk_chs_to_lba(int which, int disk_unit, unsigned int cylinder, unsigned int head, unsigned int sector, UINT32 *lba)
437/* setup a timed read sector - read sector will be triggered in a few usecs time */
438static void smc92x4_timed_sector_read_request(running_device *device)
363439{
364   if (cylinder >= hd[disk_unit].cylinders)
365   {
366      hd[disk_unit].current_cylinder = hd[disk_unit].cylinders-1;
367      hfdc[which].status |= ST_TC_RDIDERR;
368      return FALSE;
369   }
440   smc92x4_state *w = get_safe_token(device);
441   int time=0;
442
443   /* set new timer */
444   /* Average time from sector to sector. */
445   if (w->selected_drive_type & TYPE_FLOPPY)
446      time = (controller_set_to_single_density(device))? 30000 : 15000;
370447   else
371   {
372      hd[disk_unit].current_cylinder = cylinder;
373   }
374   if ((head >= hd[disk_unit].heads) || (sector >= hd[disk_unit].sectors_per_track))
375   {
376      hfdc[which].status |= ST_TC_RDIDERR;
377      return FALSE;
378   }
448      time = 1000;
379449
380   * lba = (cylinder*hd[disk_unit].heads + head)*hd[disk_unit].sectors_per_track + sector;
450   if (!w->use_real_timing)
451      time = 1;
381452
382   return TRUE;
453   timer_adjust_oneshot(w->timer_rs, ATTOTIME_IN_USEC(time), 0);
454   w->to_be_continued = TRUE;
383455}
384456
385static int harddisk_read_sector(int which, int disk_unit, int cylinder, int head, int sector, int *dma_address)
457/* setup a timed write sector - write sector will be triggered in a few usecs time */
458static void smc92x4_timed_sector_write_request(running_device *device)
386459{
387   UINT32 lba;
388   UINT8 buf[MAX_SECTOR_LEN];
389   int i;
460   smc92x4_state *w = get_safe_token(device);
461   int time=0;
390462
463   /* Average time from sector to sector. */
464   if (w->selected_drive_type & TYPE_FLOPPY)
465      time = (controller_set_to_single_density(device))? 30000 : 15000;
466   else
467      time = 1000;     
391468
392   if (!hd[disk_unit].hd_handle)
393   {
394      hfdc[which].status |= ST_TC_RDIDERR;
395      return FALSE;
396   }
469   if (!w->use_real_timing)
470      time = 1;
397471
398   if (! harddisk_chs_to_lba(which, disk_unit, cylinder, head, sector, &lba))
399      return FALSE;
472   timer_adjust_oneshot(w->timer_ws, ATTOTIME_IN_USEC(time), 0);
473   w->to_be_continued = TRUE;
474}
400475
401   if (! hard_disk_read(hd[disk_unit].hd_handle, lba, buf))
402   {
403      hfdc[which].status |= ST_TC_DATAERR;
404      return FALSE;
405   }
406   for (i=0; i<hd[disk_unit].bytes_per_sector; i++)
407   {
408      (*hfdc[which].dma_write_callback)(which, *dma_address, buf[i]);
409      *dma_address = ((*dma_address) + 1) & 0xffffff;
410   }
476/*
477   Set up a timed track read/write
478*/
479static void smc92x4_timed_track_request(running_device *device)
480{
481   smc92x4_state *w = get_safe_token(device);
482   int time = 0;
483   
484   if (w->selected_drive_type & TYPE_FLOPPY)
485      time = TRACKTIME_FLOPPY;
486   else
487      time = TRACKTIME_HD;
488   
489   if (!w->use_real_timing)
490      time = 1;
411491
412   return TRUE;
492   timer_adjust_oneshot(w->timer_track, ATTOTIME_IN_USEC(time), 0);
493   
494   w->to_be_continued = TRUE;
413495}
414496
415static int harddisk_write_sector(int which, int disk_unit, int cylinder, int head, int sector, int *dma_address)
497/*
498   Set up a timed track seek
499*/
500static void smc92x4_timed_seek_request(running_device *device)
416501{
417   UINT32 lba;
418   UINT8 buf[MAX_SECTOR_LEN];
419   int i;
502   smc92x4_state *w = get_safe_token(device);
503   int time = 0;
420504
505   int index = w->register_w[MODE] & MO_STEPRATE;
506   int fm = controller_set_to_single_density(device);
507   
508   /* Get seek time. */
509   if ((w->selected_drive_type & DRIVE_TYPE) == TYPE_FLOPPY8)
510      time = step_flop8[index];
421511
422   if (!hd[disk_unit].hd_handle)
512   else if ((w->selected_drive_type & DRIVE_TYPE) == TYPE_FLOPPY5)
513      time = step_flop5[index];     
514   else
515      time = step_hd[index];
516
517   if (fm)
518      time = time * 2;
519   
520   if (!w->use_real_timing)
423521   {
424      hfdc[which].status |= ST_TC_RDIDERR;
425      return FALSE;
522      logerror("smc92x4 info: Disk access without delays\n");
523      time = 1;   
426524   }
525   
526   timer_adjust_oneshot(w->timer_seek, ATTOTIME_IN_USEC(time), 0);
527   w->to_be_continued = TRUE;
528}
427529
428   if (! harddisk_chs_to_lba(which, disk_unit, cylinder, head, sector, &lba))
429      return FALSE;
530#if 0
531static TIMER_CALLBACK(smc92x4_data_callback)
532{
533/*   running_device *device = (running_device *)ptr;
534   smc92x4_state *w = get_safe_token(device); */
535}
536#endif
430537
431   for (i=0; i<hd[disk_unit].bytes_per_sector; i++)
432   {
433      buf[i] = (*hfdc[which].dma_read_callback)(which, *dma_address);
434      *dma_address = ((*dma_address) + 1) & 0xffffff;
435   }
436   if (! hard_disk_write(hd[disk_unit].hd_handle, lba, buf))
437   {
438      hfdc[which].status |= ST_TC_DATAERR;
439      return FALSE;
440   }
538static TIMER_CALLBACK(smc92x4_read_sector_callback)
539{
540   running_device *device = (running_device *)ptr;
541   smc92x4_state *w = get_safe_token(device);
542   int transfer_enabled = w->command & 0x01;
441543
442   return TRUE;
544   /* Now read the sector. */
545   data_transfer_read(device, w->recent_id, transfer_enabled);
546   sync_status_in(device);
547   smc92x4_process_after_callback(device);
443548}
444549
445static void harddisk_step(int which, int disk_unit, int direction)
550static TIMER_CALLBACK(smc92x4_write_sector_callback)
446551{
447   hd[disk_unit].current_cylinder += direction;
552   running_device *device = (running_device *)ptr;
553   smc92x4_state *w = get_safe_token(device);
554   int deldata = w->command & 0x10;
555   int redcur =  w->command & 0x08;
556   int precomp = w->command & 0x07;
557   int write_long = ((w->register_w[MODE]& MO_CRCECC)==0x40);
448558
449   if (hd[disk_unit].current_cylinder >= hd[disk_unit].cylinders)
450      hd[disk_unit].current_cylinder = hd[disk_unit].cylinders-1;
451   if (hd[disk_unit].current_cylinder < 0)
452      hd[disk_unit].current_cylinder = 0;
559   if (deldata)
560      logerror("smc92x4 warn: Write deleted data mark not supported. Writing normal mark.\n");
561
562   /* Now write the sector. */
563   data_transfer_write(device, w->recent_id, deldata, redcur, precomp, write_long);
564   sync_status_in(device);
565   smc92x4_process_after_callback(device);
453566}
454567
455static UINT8 harddisk_get_disk_status(int which, int disk_unit)
568/*
569   Callback for track access. Nothing interesting here, just used for
570   delaying.
571*/
572static TIMER_CALLBACK(smc92x4_track_callback)
456573{
457   int reply;
574   running_device *device = (running_device *)ptr;
575   sync_status_in(device);
576   smc92x4_process_after_callback(device);
577}
458578
459   reply = 0;
579/*
580   Callback for seek request.
581*/
582static TIMER_CALLBACK(smc92x4_seek_callback)
583{
584   running_device *device = (running_device *)ptr;
585   smc92x4_state *w = get_safe_token(device);
586   running_device *current_floppy = NULL;
587/*   int buffered = ((w->register_w[MODE] & MO_STEPRATE)==0); */
588/*    int buffered = (w->command & 0x01); */
460589
461   if (hd[disk_unit].hd_handle)
590   if (w->selected_drive_type & TYPE_FLOPPY)
462591   {
463      reply |= DS_SELACK;
464      /*if ()
465            reply |= DS_INDEX;*/
466      reply |= DS_SKCOM;
467      if (hd[disk_unit].current_cylinder == 0)
468         reply |= DS_TRK00;
469      if (hd[disk_unit].wp)
470         reply |= DS_WRPROT;
471      if (hd[disk_unit].hd_handle)
472         reply |= DS_READY;
473      /*if ()
474            reply |= DS_WRFAULT;*/
592      current_floppy = (*w->intf->current_floppy)();
593      if (current_floppy==NULL)
594      {
595         logerror("smc92x4 error: seek callback: no floppy\n");
596         w->register_r[INT_STATUS] |= ST_TC_SEEKERR;
597      }
598      else
599      {
600         // printf("smc92x4 step %s direction %d\n", current_floppy->tag(), w->step_direction);
601         floppy_drive_seek(current_floppy, w->step_direction);
602      }
475603   }
604   else
605   {
606      // printf("smc92x4 step harddisk direction %d\n", w->step_direction);
607      (*w->intf->mfmhd_seek)(w->step_direction);
608   }   
609   sync_status_in(device);
476610
477   return reply;
611   smc92x4_process_after_callback(device);
478612}
479613
614/*********************************************************************
615   Common functions
616*********************************************************************/
480617
618/*
619   Calculate the ident byte from the cylinder. The specification does not
620   define idents beyond cylinder 1023, but formatting programs seem to
621   continue with 0xfd for cylinders between 1024 and 2047.
622*/
623UINT8 cylinder_to_ident(int cylinder)
624{
625   if (cylinder < 256) return 0xfe;
626   if (cylinder < 512) return 0xff;
627   if (cylinder < 768) return 0xfc;
628   if (cylinder < 1024) return 0xfd;
629   return 0xfd;
630}
481631
482632/*
483    Initialize the controller
633   Calculate the offset from the ident. This is only useful for AT drives;
634   these drives cannot have more than 1024 cylinders.
484635*/
485void smc92x4_init(int which, const smc92x4_intf *intf)
636static int ident_to_cylinder(UINT8 ident)
486637{
487   memset(& hfdc[which], 0, sizeof(hfdc[which]));
488   hfdc[which].select_callback = intf->select_callback;
489   hfdc[which].dma_read_callback = intf->dma_read_callback;
490   hfdc[which].dma_write_callback = intf->dma_write_callback;
491   hfdc[which].int_callback = intf->int_callback;
492   if (hfdc[which].int_callback)
493      (*hfdc[which].int_callback)(which, 0);
638   switch (ident)
639   {
640   case 0xfe: return 0;
641   case 0xff: return 256;
642   case 0xfc: return 512;
643   case 0xfd: return 768;
644   default: return -1;
645   }
494646}
495647
496648/*
497 Reset the controller
649   Common function to set the read registers from the recently read id.
498650*/
499void smc92x4_reset(int which)
651static void update_id_regs(running_device *device, chrn_id_hd id)
500652{
501   int i;
653   /* Flags for current head register. Note that the sizes are not in
654      sequence (128, 256, 512, 1024). This is only interesting for AT
655      mode. */
656   UINT8 sizeflag[] = { 0x60, 0x00, 0x20, 0x40 };
657   smc92x4_state *w = get_safe_token(device);
502658
503   hfdc[which].status = 0;         // ???
504   for (i=0; i<10; i++)
505      hfdc[which].regs[i] = 0;   // ???
506   hfdc[which].reg_ptr = 0;      // ???
507   if (hfdc[which].int_callback)
508      (*hfdc[which].int_callback)(which, 0);
659   w->register_r[CURRENT_CYLINDER] = id.C & 0xff;
660
661   w->register_r[CURRENT_HEAD] = id.H & 0x0f;
662
663   if (id.flags & BAD_SECTOR)
664      w->register_r[CURRENT_HEAD] |= 0x80;
665
666   if ((w->selected_drive_type & DRIVE_TYPE) == TYPE_AT)
667      w->register_r[CURRENT_HEAD] |= sizeflag[id.N];
668   else
669      w->register_r[CURRENT_HEAD] |= ((id.C & 0x700)>>4);
670
671   w->register_r[CURRENT_IDENT] = cylinder_to_ident(id.C);
509672}
510673
511674/*
512 Change the state of IRQ
675   Common procedure: read_id_field (as described in the specification)
513676*/
514static void smc92x4_set_interrupt(int which, int state)
677static void read_id_field(running_device *device, int *steps, int *direction, chrn_id_hd *id)
515678{
516   if ((state != 0) != ((hfdc[which].status & ST_INTPEND) != 0))
679   smc92x4_state *w = get_safe_token(device);
680   int des_cylinder, cur_cylinder;
681   int found = FALSE;
682   sync_latches_out(device);
683   sync_status_in(device);
684   
685   /* Set command termination code. The error code is set first, and
686      on success, it is cleared. */
687   w->register_r[INT_STATUS] |= ST_TC_RDIDERR;
688   
689   /* Try to find an ID field. */
690   if (w->selected_drive_type & TYPE_FLOPPY)
517691   {
518      if (state)
519         hfdc[which].status |= ST_INTPEND;
692      chrn_id idflop;
693      running_device *disk_img = (*w->intf->current_floppy)();
694      if (flopimg_get_image(disk_img) == NULL)
695      {
696         logerror("smc92x4 warn: No disk in drive\n");
697         w->register_r[CHIP_STATUS] |= CS_SYNCERR;
698         return;
699      }
700     
701      /* Check whether image and controller are set to the same density. */
702      if ((image_is_single_density(disk_img) && controller_set_to_single_density(device))
703         || (!image_is_single_density(disk_img) && !controller_set_to_single_density(device))
704         )
705      {
706         found = floppy_drive_get_next_id(disk_img, w->register_w[DESIRED_HEAD]&0x0f, &idflop);
707         copyid(idflop, id); /* Need to use bigger values for HD, but we don't use separate variables here */
708      }
520709      else
521         hfdc[which].status &= ~ST_INTPEND;
710      {
711         logerror("smc92x4 warn: Controller and medium density do not match.\n");
712      }
713      sync_status_in(device);
522714
523      if (hfdc[which].int_callback)
524         (*hfdc[which].int_callback)(which, state);
715      if (!found)
716      {
717         logerror("smc92x4 error: read_id_field (floppy): sync error\n");
718         w->register_r[CHIP_STATUS] |= CS_SYNCERR;
719         return;
720      }
525721   }
722   else
723   {
724      (*w->intf->mfmhd_get_next_id)(w->register_w[DESIRED_HEAD]&0x0f, id);
725      sync_status_in(device);
726      if (!(w->register_r[DRIVE_STATUS]& DS_READY))
727      {
728         logerror("smc92x4 error: read_id_field (harddisk): sync error\n");
729         w->register_r[CHIP_STATUS] |= CS_SYNCERR;
730         return;
731      }
732   }
733   
734   w->register_r[CHIP_STATUS] &= ~CS_SYNCERR;
735   
736   /* Update the registers. */
737   update_id_regs(device, *id);
738   
739   if (id->flags & BAD_CRC)
740   {
741      w->register_r[CHIP_STATUS] |= CS_CRCERR;
742      return;
743   }
744   
745   /* Calculate the steps. */
746   if ((w->selected_drive_type & DRIVE_TYPE) == TYPE_AT)
747   {
748      /* Note: the spec says CURRENT_REGISTER, but that seems wrong. */
749      des_cylinder = ((w->register_r[DATA] & 0x03)<<8) | w->register_w[DESIRED_CYLINDER];
750      cur_cylinder = ident_to_cylinder(w->register_r[CURRENT_IDENT]) + w->register_r[CURRENT_CYLINDER];
751   }
752   else
753   {
754      des_cylinder = ((w->register_w[DESIRED_HEAD] & 0x70)<<4) | w->register_w[DESIRED_CYLINDER];
755      cur_cylinder = ((w->register_r[CURRENT_HEAD] & 0x70)<<4) | w->register_r[CURRENT_CYLINDER];
756   }
757     
758   if (des_cylinder >= cur_cylinder)
759   {
760      *steps = des_cylinder - cur_cylinder;
761      *direction = +1;
762   }
763   else
764   {
765      *steps = cur_cylinder - des_cylinder;
766      *direction = -1;
767   }
768
769   //printf("smc92x4 seek required: %d steps\n", *steps);
770   
771   w->register_r[INT_STATUS] &= ~ST_TC_RDIDERR;
772   return;
526773}
527774
528775/*
529 Select currently selected drive
776   Common procedure: verify (as described in the specification)
530777*/
531static int get_selected_drive(int which, select_mode_t *select_mode, int *disk_unit)
778static int verify(running_device *device, chrn_id_hd *id, int check_sector)
532779{
533   if (hfdc[which].disk_sel == disk_sel_none)
780   smc92x4_state *w = get_safe_token(device);
781   int maxtry = 132;  /* approx. 33792/(256*32) */
782   int pass = 0;
783   int found = FALSE;
784   int foundsect = FALSE;
785   int des_cylinder = 0;
786   
787   /* Set command termination code. The error code is set first, and
788      on success, it is cleared. */
789   w->register_r[INT_STATUS] |= ST_TC_SEEKERR;
790   
791   while (pass < maxtry && !foundsect)
534792   {
535      * select_mode = sm_undefined;
536      * disk_unit = -1;
793      pass++;
794      /* Try to find an ID field. */
795      if (w->selected_drive_type & TYPE_FLOPPY)
796      {
797         chrn_id idflop;
798         running_device *disk_img = (*w->intf->current_floppy)();
799         found = floppy_drive_get_next_id(disk_img, w->register_w[DESIRED_HEAD]&0x0f, &idflop);
800         copyid(idflop, id);
801         if (/* pass==1 && */!found)
802         {
803            w->register_r[CHIP_STATUS] |= CS_SYNCERR;
804            logerror("smc92x4 error: verify (floppy): sync error\n");
805            return ERROR;
806         }
807      }
808      else
809      {
810         (*w->intf->mfmhd_get_next_id)(w->register_w[DESIRED_HEAD]&0x0f, id);
811         sync_status_in(device);
812         if (!(w->register_r[DRIVE_STATUS]& DS_READY))
813         {
814            logerror("smc92x4 error: verify (harddisk): sync error\n");
815            w->register_r[CHIP_STATUS] |= CS_SYNCERR;
816            return ERROR;
817         }
818      }
819     
820      w->register_r[CHIP_STATUS] &= ~CS_SYNCERR;
821     
822      /* Compare with the desired sector ID. */
823      if ((w->selected_drive_type & DRIVE_TYPE) == TYPE_AT)
824      {
825         /* Note: the spec says CURRENT_CYLINDER, but that seems wrong. */
826         des_cylinder = ((w->register_r[DATA] & 0x03)<<8) | w->register_w[DESIRED_CYLINDER];
827      }
828      else
829      {
830         des_cylinder = ((w->register_w[DESIRED_HEAD] & 0x70)<<4) | w->register_w[DESIRED_CYLINDER];
831      }
832//      printf("smc92x4 check id: current = (%d,%d,%d), required = (%d,%d,%d)\n", id->C, id->H, id->R, des_cylinder, w->register_w[DESIRED_HEAD] & 0x0f, w->register_w[DESIRED_SECTOR]);
833      if ((des_cylinder == id->C)
834         && ((w->register_w[DESIRED_HEAD] & 0x0f) == id->H))
835      {
836         if (!check_sector ||  (w->register_w[DESIRED_SECTOR] == id->R))
837            foundsect = TRUE;
838      }
839   }   
840   if (!foundsect)
841   {
842      w->register_r[CHIP_STATUS] |= CS_COMPERR;
843      logerror("smc92x4 error: verify: sector not found, seek error (desired cyl=%d/sec=%d, current cyl=%d/sec=%d)\n", des_cylinder, w->register_w[DESIRED_SECTOR], id->C, id->R);
844      return ERROR;
537845   }
846   
847   w->register_r[INT_STATUS] &= ~ST_TC_SEEKERR;
848   return DONE;
849}
850
851/*
852   Common procedure: data_transfer(read) (as described in the specification)
853*/
854static void data_transfer_read(running_device *device, chrn_id_hd id, int transfer_enable)
855{
856   int i, retry, sector_len;
857   smc92x4_state *w = get_safe_token(device);
858   running_device *current_floppy = NULL;
859   
860   int sector_data_id;
861   UINT8 *buf;
862   
863   sync_latches_out(device);
864   sync_status_in(device);
865   
866   current_floppy = (*w->intf->current_floppy)();
867
868   /* Set command termination code. The error code is set first, and
869      on success, it is cleared. */
870   w->register_r[INT_STATUS] |= ST_TC_DATAERR;
871   
872   /* Save the value. Note that the retry count is only in the first four
873   bits, and it is stored in one's complement. In this implementation
874   we don't work with it. */
875   retry = w->register_w[RETRY_COUNT];
876   
877   /* We are already at the correct sector (found by the verify sequence) */
878   
879   /* Find the data sync mark. Easy, we assume it has been found. */
880   
881   if (id.flags & ID_FLAG_DELETED_DATA)
882      w->register_r[CHIP_STATUS] |= CS_DELDATA;
538883   else
884      w->register_r[CHIP_STATUS] &= ~CS_DELDATA;
885   
886   /* Found. Now update the current cylinder/head registers. */
887   update_id_regs(device, id);
888   
889   /* Initiate the DMA. We assume the DMARQ is positive. */
890   w->register_r[INT_STATUS] &= ~ST_OVRUN;   
891
892   sector_len = 1 << (id.N+7);
893   sector_data_id = id.data_id;
894   
895   if (w->selected_drive_type & TYPE_FLOPPY)
539896   {
540      * select_mode = (select_mode_t) ((hfdc[which].disk_sel >> 2) & 0x3);
541
542      switch (* select_mode)
897      buf = (UINT8 *)malloc(sector_len);
898      floppy_drive_read_sector_data(current_floppy, id.H, sector_data_id, buf, sector_len);
899   }
900   else
901   {
902      /* buf is allocated within the function, and sector_len is also set */
903      (*w->intf->mfmhd_read_sector)(id.C, id.H, id.R, &buf, &sector_len);
904   }
905   sync_status_in(device);
906   
907   if (transfer_enable)
908   {
909      /* Copy via DMA into controller RAM. */
910      set_dma_address(device, DMA23_16, DMA15_8, DMA7_0);
911     
912      smc92x4_set_dip(device, TRUE);
913      for (i=0; i < sector_len; i++)
543914      {
544      case sm_at_harddisk:
545      case sm_harddisk:
546      case sm_floppy_slow:
547      case sm_floppy_fast:
548         if (hfdc[which].select_callback)
549            * disk_unit = (* hfdc[which].select_callback)(which, * select_mode, hfdc[which].disk_sel & 0x3, hfdc[which].regs[hfdc_reg_retry_count] & 0xf);
550         else
551            * disk_unit = hfdc[which].disk_sel & 0x3;
552
553      case sm_undefined:
554         break;
915         (*w->intf->dma_write_callback)(buf[i]);
555916      }
917      smc92x4_set_dip(device, FALSE);
556918   }
919   free(buf);
557920
558   return (* disk_unit != -1);
921   /* Check CRC. We assume everything is OK, no retry required. */
922   w->register_r[CHIP_STATUS] &= ~CS_RETREQ;
923   w->register_r[CHIP_STATUS] &= ~CS_CRCERR;
924   w->register_r[CHIP_STATUS] &= ~CS_ECCATT;
925   
926   /* Update the DMA registers. */
927   if (transfer_enable)
928      dma_add_offset(device, sector_len);
929
930   /* Decrement sector count. */
931   w->register_w[SECTOR_COUNT] = (w->register_w[SECTOR_COUNT]-1)&0xff;
932
933   /* Clear the error bits. */
934   w->register_r[INT_STATUS] &= ~ST_TC_DATAERR;
935   
936   if (w->register_w[SECTOR_COUNT] == 0)
937      return;
938     
939   /* Else this is a multi-sector operation. */
940   w->register_w[DESIRED_SECTOR] =
941   w->register_r[DESIRED_SECTOR] =
942      (w->register_w[DESIRED_SECTOR]+1) & 0xff;
943     
944   /* Reinitialize retry count. */
945   w->register_w[RETRY_COUNT] = retry;
559946}
560947
561948/*
562    Assert Command Done status bit, triggering interrupts as needed
949   Common procedure: data_transfer(write) (as described in the specification)
563950*/
564INLINE void set_command_done(int which)
951static void data_transfer_write(running_device *device, chrn_id_hd id, int deldata, int redcur, int precomp, int write_long)
565952{
566   //assert(! (hfdc[which].status & ST_DONE))
567   hfdc[which].status |= ST_DONE;
568   if (hfdc[which].regs[hfdc_reg_term] & TC_INTDONE)
569      smc92x4_set_interrupt(which, 1);
570}
953   int retry, i, sector_len;
954   smc92x4_state *w = get_safe_token(device);
955   running_device *current_floppy = NULL;
956   UINT8 *buf;
957   int sector_data_id;
958   
959   sync_latches_out(device);
960   sync_status_in(device);
961   
962   current_floppy = (*w->intf->current_floppy)();
963   
964   /* Set command termination code. The error code is set first, and
965      on success, it is cleared. */
966   w->register_r[INT_STATUS] |= ST_TC_DATAERR;
967   
968   /* Save the value. Note that the retry count is only in the first four
969   bits, and it is stored in one's complement. In this implementation
970   we don't work with it. */
971   retry = w->register_w[RETRY_COUNT];
972     
973   /* Initiate the DMA. We assume the DMARQ is positive. */
974   w->register_r[INT_STATUS] &= ~ST_OVRUN;   
571975
572INLINE void step(running_machine *machine,int which, select_mode_t select_mode, int disk_unit, int direction)
573{
574   switch (select_mode)
976   sector_len = 1 << (id.N+7);
977   sector_data_id = id.data_id;
978   
979   buf = (UINT8 *)malloc(sector_len);
980
981   /* Copy via DMA from controller RAM. */
982   set_dma_address(device, DMA23_16, DMA15_8, DMA7_0);
983   
984   smc92x4_set_dip(device, TRUE);
985   for (i=0; i<sector_len; i++)
575986   {
576   case sm_undefined:
577   default:
578      break;
987      buf[i] = (*w->intf->dma_read_callback)();
988   }
989   smc92x4_set_dip(device, FALSE);
990   
991   if (write_long)
992   {
993      logerror("smc92x4 write sector: Write_long not supported. Performing a normal write.\n");
994   }
995   
996   if (w->selected_drive_type & TYPE_FLOPPY)
997   {
998      floppy_drive_write_sector_data(current_floppy, id.H, sector_data_id, (char *) buf, sector_len, FALSE);
999   }
1000   else
1001   {
1002      (*w->intf->mfmhd_write_sector)(id.C, id.H, id.R, buf, sector_len);
1003   }
1004   free(buf);
1005   sync_status_in(device);
1006   
1007   w->register_r[CHIP_STATUS] &= ~CS_RETREQ;
1008   w->register_r[CHIP_STATUS] &= ~CS_CRCERR;
1009   w->register_r[CHIP_STATUS] &= ~CS_ECCATT;
1010   
1011   /* Update the DMA registers. */
1012   dma_add_offset(device, sector_len);
5791013
580   case sm_at_harddisk:
581      break;
1014   /* Decrement sector count. */
1015   w->register_w[SECTOR_COUNT] = (w->register_w[SECTOR_COUNT]-1)&0xff;
5821016
583   case sm_harddisk:
584      /* hard disks may ignore programmed seeks */
585      harddisk_step(which, disk_unit, direction);
586      break;
587
588   case sm_floppy_slow:
589   case sm_floppy_fast:
590      floppy_step(machine,which, disk_unit, direction);
591      break;
592   }
1017   /* Clear the error bits. */
1018   w->register_r[INT_STATUS] &= ~ST_TC_DATAERR;
1019   
1020   if (w->register_w[SECTOR_COUNT] == 0)
1021      return;
1022     
1023   /* Else this is a multi-sector operation. */
1024   w->register_w[DESIRED_SECTOR] =
1025   w->register_r[DESIRED_SECTOR] =
1026      (w->register_w[DESIRED_SECTOR]+1) & 0xff;
1027     
1028   /* Reinitialize retry count. */
1029   w->register_w[RETRY_COUNT] = retry;
5931030}
5941031
1032static void read_sectors_continue(running_device *device);
1033static void write_sectors_continue(running_device *device);
1034
5951035/*
596    Perform the read_id phase on a drive
1036   Read sectors physical / logical. Physical means that the first, the
1037   second, the third sector appearing under the head will be read. These
1038   sectors are usually not in logical sequence. The ordering depends on
1039   the interleave pattern.
5971040*/
598INLINE int read_id(running_machine *machine,int which, select_mode_t select_mode, int disk_unit, int head,
599               int do_implied_seek, int desired_cylinder)
1041static void read_write_sectors(running_device *device)
6001042{
601   int reply;
1043   smc92x4_state *w = get_safe_token(device);
6021044
603   switch (select_mode)
1045   int logical = w->command & 0x04;
1046   int implied_seek_disabled = w->command & 0x02; /* for read */
1047   int write = (w->command & 0x80);
1048   
1049   w->after_seek = FALSE;
1050   
1051   w->to_be_continued = FALSE;
1052   
1053   if (write) /* write sectors */
6041054   {
605   case sm_undefined:
606   default:
607      reply = FALSE;
608      break;
1055      logical = w->command & 0x20;
1056      implied_seek_disabled = w->command & 0x40;
1057   }
1058   
1059   if (!logical)
1060      implied_seek_disabled = FALSE;
1061         
1062   if (!w->found_id)
1063   {
1064      /* First start. */
1065      read_id_field(device, &w->seek_count, &w->step_direction, &w->recent_id);
1066   }
1067   
1068   if ((w->register_r[INT_STATUS] & ST_TC_DATAERR) == ST_TC_SUCCESS)
1069   {   
1070      w->found_id = TRUE;
1071      /* Perform the seek for the cylinder. */
1072      if (!implied_seek_disabled && w->seek_count > 0)
1073      {
1074         smc92x4_timed_seek_request(device);
1075      }
1076      else
1077      {
1078         if (write)
1079            write_sectors_continue(device);
1080         else
1081            read_sectors_continue(device);
1082      }
1083         
1084   }
1085   else
1086   {
1087      set_command_done(device, ST_TC_RDIDERR);
1088   }
1089}
6091090
610   case sm_at_harddisk:
611      reply = FALSE;
612      break;
6131091
614   case sm_harddisk:
615      reply = harddisk_read_id(which, disk_unit, head);
616      break;
1092static void read_sectors_continue(running_device *device)
1093{
1094   smc92x4_state *w = get_safe_token(device);
6171095
618   case sm_floppy_slow:
619   case sm_floppy_fast:
620      reply = floppy_read_id(machine,which, disk_unit, head);
621      break;
1096   int check_sector = TRUE; /* always check the first sector */
1097   int state = AGAIN;
1098   int logical = w->command & 0x04;
1099
1100   /* Needed for the two ways of re-entry: during the seek process, and during sector read */
1101   if (!w->after_seek)
1102   {
1103      // printf("smc92x4 continue with sector read\n");
1104      w->seek_count--;
1105      if (w->seek_count > 0)
1106      {
1107         read_write_sectors(device);
1108         return;
1109      }
1110      w->after_seek = TRUE;
6221111   }
1112   else
1113   {
1114      /* we are here after the sector read. */
1115      w->to_be_continued = FALSE;
1116      if (w->register_r[INT_STATUS] & ST_TERMCOD)
1117      {
1118         logerror("smc92x4 error: data error during sector read: INTSTATUS=%02x\n", w->register_r[INT_STATUS]);
1119         set_command_done(device, ST_TC_DATAERR);
1120         return;         
1121      }
1122   }
6231123
624   if (do_implied_seek && reply)
1124   w->to_be_continued = FALSE;
1125   
1126   /* Wait for SEEK_COMPLETE. We assume the signal has appeared. */
1127   
1128   if (w->register_w[SECTOR_COUNT] > 0 /* && !(w->register_r[DRIVE_STATUS] & DS_INDEX) */)
6251129   {
626      /* perform implied seek */
627      int current_cylinder;
628      int step_direction, step_count;
629      int i;
1130      /* Call the verify sequence. */
1131      state = verify(device, &w->recent_id, check_sector);
1132      if (state==ERROR)
1133      {
1134         // TODO: set command done?
1135         logerror("smc92x4 error: verify error during sector read\n");
1136         return;
1137      }
6301138
631      if (select_mode == sm_at_harddisk)
1139      /* For read physical, only verify the first sector. */
1140      if (!logical)
1141         check_sector = FALSE;
1142     
1143      if (w->recent_id.flags & BAD_SECTOR)
6321144      {
633         switch (hfdc[which].regs[hfdc_reg_read_6])
634         {
635         case 0xfe:
636            current_cylinder = hfdc[which].regs[hfdc_reg_cur_cyl];
637            break;
638         case 0xff:
639            current_cylinder = 256 + hfdc[which].regs[hfdc_reg_cur_cyl];
640            break;
641         case 0xfc:
642            current_cylinder = 512 + hfdc[which].regs[hfdc_reg_cur_cyl];
643            break;
644         case 0xfd:
645            current_cylinder = 1024 + hfdc[which].regs[hfdc_reg_cur_cyl];
646            break;
647         default:
648            assert(1);
649            current_cylinder = 0;
650            break;
651         }
1145         logerror("smc92x4 error: Bad sector, seek error\n");
1146         set_command_done(device, ST_TC_SEEKERR);
6521147      }
653      else if (select_mode == sm_harddisk)
654         current_cylinder = ((hfdc[which].regs[hfdc_reg_cur_head] & 0x70) << 4) | hfdc[which].regs[hfdc_reg_cur_cyl];
6551148      else
656         current_cylinder = hfdc[which].regs[hfdc_reg_cur_cyl];
1149      {
1150/*      printf("smc92x4 read sectors CYL=%02x, HEA=%02x, SEC=%02x, MOD=%02x, CNT=%02x, TRY=%02x\n",
1151         w->register_w[DESIRED_CYLINDER],
1152         w->register_w[DESIRED_HEAD],
1153         w->register_w[DESIRED_SECTOR],
1154         w->register_w[MODE],
1155         w->register_w[SECTOR_COUNT],
1156         w->register_w[RETRY_COUNT]); */
1157         smc92x4_timed_sector_read_request(device);
1158      }
1159   }
1160   else
1161   {
1162      set_command_done(device, ST_TC_SUCCESS);
1163      //printf("smc92x4 read sector command done\n");
1164   }
1165}
6571166
658      if (current_cylinder < desired_cylinder)
1167static void write_sectors_continue(running_device *device)
1168{
1169   smc92x4_state *w = get_safe_token(device);
1170
1171   int check_sector = TRUE; /* always check the first sector */
1172   int state = AGAIN;
1173   int logical = w->command & 0x20;
1174   
1175   /* Needed for the two ways of re-entry: during the seek process, and during sector write */
1176   if (!w->after_seek)
1177   {
1178      w->seek_count--;
1179      if (w->seek_count > 0)
6591180      {
660         step_direction = +1;
661         step_count = desired_cylinder - current_cylinder;
1181         read_write_sectors(device);
1182         return;
6621183      }
663      else
1184      w->after_seek = TRUE;
1185   }
1186   else
1187   {
1188      /* we are here after the sector write. */
1189      w->to_be_continued = FALSE;
1190      if (w->register_r[INT_STATUS] & ST_TERMCOD)
6641191      {
665         step_direction = -1;
666         step_count = current_cylinder - desired_cylinder;
1192         logerror("smc92x4 error: data error during sector write\n");
1193         set_command_done(device, ST_TC_DATAERR);
1194         return;         
6671195      }
1196   }
1197   
1198   w->to_be_continued = FALSE;
6681199
669      for (i=0; i<step_count; i++)
670         step(machine,which, select_mode, disk_unit, step_direction);
1200   if ((w->register_w[RETRY_COUNT] & 0xf0)!= 0xf0)
1201      logerror("smc92x4 warn: RETRY_COUNT in write sector should be set to 0. Ignored.\n");
1202
1203   /* Wait for SEEK_COMPLETE. We assume the signal has appeared. */     
1204   if (w->register_w[SECTOR_COUNT] > 0)
1205   {
1206      /* Call the verify sequence. */
1207      state = verify(device, &w->recent_id, check_sector);
1208      if (state==ERROR)
1209      {
1210         logerror("smc92x4 error: verify error during sector write\n");
1211         return;
1212      }
1213
1214      /* For write physical, only verify the first sector. */
1215      if (!logical)
1216         check_sector = FALSE;
1217
1218/*      printf("smc92x4 write sectors CYL=%02x, HEA=%02x, SEC=%02x, MOD=%02x, CNT=%02x, TRY=%02x\n",
1219         w->register_w[DESIRED_CYLINDER],
1220         w->register_w[DESIRED_HEAD],
1221         w->register_w[DESIRED_SECTOR],
1222         w->register_w[MODE],
1223         w->register_w[SECTOR_COUNT],
1224         w->register_w[RETRY_COUNT]); */
1225      smc92x4_timed_sector_write_request(device);
6711226   }
672
673   return reply;
1227   else
1228   {
1229      set_command_done(device, ST_TC_SUCCESS);
1230      // printf("smc92x4 write sector command done\n");
1231   }
6741232}
6751233
1234/*********************************************************************
1235   Command implementations
1236*********************************************************************/
1237
6761238/*
677    Get the status of a drive
1239    Handle the restore command
6781240*/
679INLINE UINT8 get_disk_status(running_machine *machine,int which, select_mode_t select_mode, int disk_unit)
1241static void restore_drive(running_device *device)
6801242{
681   UINT8 reply;
1243   smc92x4_state *w = get_safe_token(device);
1244   
1245   /* TODO: int_after_seek_complete required for buffered seeks */
1246   sync_status_in(device);
6821247
683   switch (select_mode)
1248   if (w->seek_count>=4096 || !(w->register_r[DRIVE_STATUS] & DS_READY))
6841249   {
685   case sm_undefined:
686   default:
687      reply = 0;
688      break;
1250      logerror("smc92x4 error: seek error in restore\n");
1251      w->register_r[INT_STATUS] |= ST_TC_SEEKERR;
1252      return;
1253   }
1254   
1255   if (w->register_r[DRIVE_STATUS] & DS_TRK00)
1256   {
1257      w->register_r[INT_STATUS] |= ST_TC_SUCCESS;
1258      /* Issue interrupt */
1259      smc92x4_set_interrupt(device);
1260      return;     
1261   }
6891262
690   case sm_at_harddisk:
691      reply = 0;
692      break;
1263   w->step_direction = -1;
1264   smc92x4_timed_seek_request(device);
1265}
6931266
694   case sm_harddisk:
695      reply = harddisk_get_disk_status(which, disk_unit);
696      break;
1267static void restore_continue(running_device *device)
1268{
1269   smc92x4_state *w = get_safe_token(device);
6971270
698   case sm_floppy_slow:
699   case sm_floppy_fast:
700      reply = floppy_get_disk_status(machine,which, disk_unit);
701      break;
1271   w->seek_count++;
1272   
1273   /* Next iteration */
1274   restore_drive(device);
7021275
703   }
704
705   return reply;
1276   w->to_be_continued = FALSE;
7061277}
7071278
7081279/*
709    Handle the step command
1280   Handle the step command. Note that the CURRENT_CYLINDER register is not
1281   updated (this would break the format procedure).
7101282*/
711static void do_step(running_machine *machine,int which, int mode)
1283static void step_in_out(running_device *device)
7121284{
713   select_mode_t select_mode;
714   int disk_unit = 0;
1285   smc92x4_state *w = get_safe_token(device);
1286   int direction = (w->command & 0x02)? -1 : +1;
1287   /* bit 0: 0 -> command ends after last seek pulse, 1 -> command
1288   ends when the drive asserts the seek complete pin */
1289   int buffered = w->command & 0x01;
1290   
1291   w->step_direction = direction;
1292   w->buffered = buffered;
7151293
716   hfdc[which].status = 0;
1294   smc92x4_timed_seek_request(device);
1295   //printf("smc92x4 waiting for drive step\n");
1296}
7171297
718   /* reset chip status */
719   hfdc[which].regs[hfdc_reg_chip_stat] = hfdc[which].disk_sel & 0x3;
1298static void step_continue(running_device *device)
1299{
1300   smc92x4_state *w = get_safe_token(device);
1301   //printf("smc92x4 step continue\n");
1302   w->to_be_continued = FALSE;
1303   set_command_done(device,  ST_TC_SUCCESS);
1304}
7201305
721   if (!get_selected_drive(which, & select_mode, & disk_unit))
1306
1307static void drive_select(running_device *device, int drive);
1308
1309/*
1310   Poll drives
1311   This command is used to find out which drive has complete a buffered
1312   seek (RESTORE, SEEK IN/OUT with BUFFERED set to one)
1313*/
1314static void poll_drives(running_device *device)
1315{
1316   int mask = 0x08;
1317   smc92x4_state *w = get_safe_token(device);
1318   int i;
1319   int flags = w->command & 0x0f;
1320   
1321/* Spec is unclear: Do we continue to poll the drives after we have checked each
1322one for the first time? We are not interested in locking up the emulator, so
1323we decide to poll only once. */
1324   for (i=3; i>=0; i--)
7221325   {
723      /* no unit has been selected */
724      hfdc[which].status |= ST_TC_RDIDERR;
725      hfdc[which].regs[hfdc_reg_chip_stat] |= CS_SYNCERR;
726      goto cleanup;
1326      if (flags & mask)
1327      {
1328         /* Poll drive */
1329         drive_select(device, i|((w->types[i])<<2));
1330         sync_latches_out(device);
1331         sync_status_in(device);
1332         if (w->register_r[DRIVE_STATUS] & DS_SKCOM) return;
1333      }
1334      mask = mask>>1;
7271335   }
1336}
7281337
729   step(machine,which, select_mode, disk_unit, (mode & 2) ? -1 : +1);
1338static void drive_select(running_device *device, int driveparm)
1339{
1340   smc92x4_state *w = get_safe_token(device);
7301341
731cleanup:
732   /* update register state */
733   set_command_done(which);
1342   w->output1 = (0x10 << (driveparm & 0x03)) | (w->register_w[RETRY_COUNT]&0x0f);
1343   w->selected_drive_type = (driveparm>>2) & 0x03;
1344   w->head_load_delay_enable = (driveparm>>4)&0x01;
1345   
1346   /* We need to store the type of the drive for the poll_drives command
1347      to be able to correctly select the device (floppy or hard disk). */
1348   w->types[driveparm&0x03] = w->selected_drive_type;
7341349
735   /* set drive status */
736   hfdc[which].regs[hfdc_reg_drive_stat] = get_disk_status(machine,which, select_mode, disk_unit);
1350   /* Copy the DMA registers to registers CURRENT_HEAD, CURRENT_CYLINDER,
1351   and CURRENT_IDENT. This is required during formatting (p. 14) as the
1352   format command reuses the registers for formatting parameters. */
1353   w->register_r[CURRENT_HEAD] = w->register_r[DMA7_0];
1354   w->register_r[CURRENT_CYLINDER] = w->register_r[DMA15_8];
1355   w->register_r[CURRENT_IDENT] = w->register_r[DMA23_16];
1356   
1357   sync_latches_out(device);
1358   sync_status_in(device);
7371359}
7381360
7391361/*
740    Handle the restore command
1362   Command SEEK/READID
7411363*/
742static void do_restore(running_machine *machine,int which, int mode)
1364static void seek_read_id(running_device *device)
7431365{
744   select_mode_t select_mode;
745   int disk_unit = 0;
746   int seek_count;
1366   smc92x4_state *w = get_safe_token(device);
1367   int step_enable = (w->command & 0x04);
1368   int verify_id = (w->command & 0x01);
1369   int wait = (w->command & 0x02);
7471370
748   hfdc[which].status = 0;
749
750   /* reset chip status */
751   hfdc[which].regs[hfdc_reg_chip_stat] = hfdc[which].disk_sel & 0x3;
752
753   if (!get_selected_drive(which, & select_mode, & disk_unit))
1371   w->to_be_continued = FALSE;
1372   
1373   if (!w->found_id)
7541374   {
755      /* no unit has been selected */
756      /* the drive status will be 0, therefore the SEEK_COMPLETE bit will be
757        cleared, which is what we want */
758      goto cleanup;
1375      /* First start. */
1376      read_id_field(device, &w->seek_count, &w->step_direction, &w->recent_id);
1377      w->found_id = TRUE;
7591378   }
760
761   switch (select_mode)
762   {
763   case sm_undefined:
764   default:
765      break;
766
767   case sm_at_harddisk:
768      break;
769
770   case sm_harddisk:
771   case sm_floppy_slow:
772   case sm_floppy_fast:
773      seek_count = 0;
774      /* limit iterations to 2048 to prevent an endless loop if the disc is locked */
775      while ((seek_count < 2048) && ! (get_disk_status(machine,which, select_mode, disk_unit) & DS_TRK00))
1379   
1380   if ((w->register_r[INT_STATUS] & ST_TC_DATAERR) == ST_TC_SUCCESS)
1381   {   
1382      /* Perform the seek for the cylinder. */
1383      if (step_enable && w->seek_count > 0)
7761384      {
777         step(machine,which, select_mode, disk_unit, -1);
778         seek_count++;
1385         smc92x4_timed_seek_request(device);
7791386      }
780      break;
1387      else
1388      {
1389         if (wait)
1390            logerror("smc92x4:seed_read_id: Waiting for seek_complete not implemented.\n");
1391         
1392         if (verify_id)
1393         {
1394            verify(device, &w->recent_id, TRUE);
1395         }
1396      }
7811397   }
1398   else
1399   {
1400      set_command_done(device, ST_TC_RDIDERR);
1401   }
1402}
7821403
783cleanup:
784   /* update register state */
785   set_command_done(which);
786
787   /* set drive status */
788   hfdc[which].regs[hfdc_reg_drive_stat] = get_disk_status(machine,which, select_mode, disk_unit);
1404static void seek_read_id_continue(running_device *device)
1405{
1406   smc92x4_state *w = get_safe_token(device);
1407   w->seek_count--;
1408   seek_read_id(device);
1409   w->to_be_continued = FALSE;
7891410}
7901411
7911412/*
792    Handle the read command
1413   Formats a track starting from the detection of an index mark until the
1414   detection of another index mark.
1415   The formatting is done exclusively by the controller; user programs may
1416   set parameters for gaps and interleaving.
7931417
794    which: disk controller selected
795    physical_flag: if 1, read consecutive sectors, ignoring sector IDs
796    mode: extra flags (ignored)
1418   1. Before starting the command, the user program must have set up a
1419   sector sequence table in the controller RAM (located on the PCB):
1420   (ident, cylinder, head, sector1, size)  (5 bytes)
1421   (ident, cylinder, head, sector2, size)
1422   (ident, cylinder, head, sector3, size)
1423   ...
1424   ident is not required for floppy FM operation. size is not required
1425   for IBM AT-compatible hard disks.
1426   
1427   2. The DMA registers must point to the beginning of the table
1428   
1429   3. DRIVE_SELECT must be executed (which moves DMA regs to CUR_HEAD ...)
1430   
1431   4. DESIRED_HEAD register must be loaded
1432   
1433   5. The following setup must be done:
1434   
1435   GAP 0 size      DMA7_0         (2s comp)
1436   GAP 1 size      DMA15_8         (2s comp)
1437   GAP 2 size      DMA23_16      (2s comp)
1438   GAP 3 size      DESIRED_SECTOR      (2s comp)
1439   Sync size      DESIRED_CYLINDER   (1s comp)
1440   Sector count      SECTOR_COUNT      (1s comp)
1441   Sector size multiple   RETRY_COUNT       (1s comp)
1442
1443   GAP4 is variable and fills the rest of the track until the next
1444   index hole. Usually we have 247 bytes for FM and 598 for MFM.
1445   
1446   6. The step rate and density must be loaded into the MODE register
1447
1448   7. The drive must be stepped to the desired track.
1449
1450   8. Now this command may be started.
1451   
1452   All data bytes of a sector are filled with 0xe5. The gaps will be filled
1453   with 0x4e (MFM) or 0xff (FM).
1454   
1455   To format another track, the sector id table must be updated, and steps
1456   7 and 8 must be repeated. If the DESIRED_HEAD register must be updated,
1457   the complete setup process must be done.
1458   
1459   Options: Command = 011m rppp
1460   m = set data mark (0 = set deleted)
1461   r = current (1 = reduced)
1462   ppp = precompensation (for sector size = (2^ppp) * 128; ppp<4 for floppy )   
1463   
1464   ===============
1465   
1466   One deviation from the specification: The TI-99 family uses the SDF
1467   and TDF formats. The TDF formats complies with the formats produced
1468   by the standard TI disk controller. It does not use index address marks.
1469   So we could integrate a translation in ti99_dsk when writing to disk,
1470   but when reading, how can ti99_dsk know whether to blow up the format
1471   to full length for this controller or keep it as is for the other
1472   controller? Unless someone comes up with a better idea, we implement
1473   an "undocumented" option in this controller, allowing to create a
1474   different track layout.   
1475   
1476   So there are two layouts for the floppy track:
1477   
1478   - full format, including the index address mark, according to the
1479     specification
1480     
1481   - short format without index AM which matches the PC99 format used
1482     for the TI-99 family.
1483     
1484   The formats are determined by setting the flag in the smc92x4
1485   interface structure.
7971486*/
798static void do_read(running_machine *machine,int which, int physical_flag, int mode)
1487static void format_floppy_track(running_device *device, int flags)
7991488{
800   select_mode_t select_mode;
801   int disk_unit = 0;
802   int dma_base_address, dma_address;
803   int cylinder, head, sector;
1489   smc92x4_state *w = get_safe_token(device);
1490   running_device *current_floppy = NULL;
8041491
805   hfdc[which].status = 0;
1492   floppy_image *floppy;
1493   int i,index,j, exp_size;
1494   int gap0, gap1, gap2, gap3, gap4, sync1, sync2, count, size, fm;
1495   int gap_byte, pre_gap, crc, mark, inam;
1496   UINT8 curr_ident, curr_cyl, curr_head, curr_sect, curr_size;
1497   
1498   int normal_data_mark = flags & 0x10;
1499   
1500   UINT8 *buffer;
8061501
807   /* reset chip status */
808   hfdc[which].regs[hfdc_reg_chip_stat] = hfdc[which].disk_sel & 0x3;
1502   /* Determine the track size. We cannot allow different sizes in this
1503   design. */
1504   int data_count = 0;
8091505
810   dma_base_address = hfdc[which].regs[hfdc_reg_dma_low]
811                  | (hfdc[which].regs[hfdc_reg_dma_mid] << 8)
812                  | (hfdc[which].regs[hfdc_reg_dma_high] << 16);
1506   sync_status_in(device);
1507   
1508   current_floppy = (*w->intf->current_floppy)();
1509        floppy = flopimg_get_image(current_floppy);
8131510
814   sector = hfdc[which].regs[hfdc_reg_des_sector];
815   head = hfdc[which].regs[hfdc_reg_des_head] & 0xf;
816   cylinder = (((int) hfdc[which].regs[hfdc_reg_des_head] << 4) & 0x700)
817            | hfdc[which].regs[hfdc_reg_des_cyl];
1511   if (floppy != NULL)
1512      data_count = floppy_get_track_size(floppy, 0, 0);
1513   
1514        if (data_count==0)
1515        {
1516                if (controller_set_to_single_density(device))
1517                        data_count = TRKSIZE_SD;
1518                else
1519                   data_count = TRKSIZE_DD;
1520        }
1521       
1522        /* Build buffer */
1523        buffer = (UINT8*)malloc(data_count);
1524       
1525   fm = controller_set_to_single_density(device);
1526   
1527   sync2 = (~w->register_w[DESIRED_CYLINDER])&0xff;
1528   gap2 = (-w->register_w[DMA23_16])&0xff;
1529   count = (~w->register_w[SECTOR_COUNT])&0xff;
1530   size = (~w->register_w[RETRY_COUNT])&0xff;
1531   gap_byte = (fm)? 0xff : 0x4e;
8181532
819   if (!get_selected_drive(which, & select_mode, & disk_unit))
820   {
821      /* no unit has been selected */
822      hfdc[which].status |= ST_TC_RDIDERR;
823      hfdc[which].regs[hfdc_reg_chip_stat] |= CS_SYNCERR;
824      goto cleanup;
1533   if (w->intf->full_track_layout)
1534   {   
1535      /* Including the index AM. */
1536      gap0 = (-w->register_w[DMA7_0])&0xff;
1537      gap1 = (-w->register_w[DMA15_8])&0xff;
1538      gap3 = (-w->register_w[DESIRED_SECTOR])&0xff;
1539      gap4 = (fm)? 247 : 598;
1540      pre_gap = gap_byte;
1541      sync1 = sync2;
1542      inam = sync2 + (fm)? 1 : 4;
8251543   }
826
827   if (! (get_disk_status(machine,which, select_mode, disk_unit) & DS_READY))
1544   else
8281545   {
829      /* unit is not ready */
830      hfdc[which].status |= ST_TC_RDIDERR;
831      hfdc[which].regs[hfdc_reg_chip_stat] |= CS_SYNCERR;
832      goto cleanup;
1546      /* Specific overrides for this format. We do not have the index mark. */
1547      gap0 = (fm)? 16 : 40;
1548      gap1 = 0;
1549      gap3 = (fm)? 45 : 24;
1550      gap4 = (fm)? 231 : 712;
1551      pre_gap = (fm)? 0x00 : 0x4e;
1552      sync1 = (fm)? 6 : 10;
1553      inam = 0;
8331554   }
1555   
1556   index = 0;
8341557
835#if 0
836   /* if we enable write-protect test in read operations, the ti99 HFDC DSR is
837    unable to read write-protected floppies! */
838   if ((hfdc[which].regs[hfdc_reg_term] & TC_TWPROT)
839         && (get_disk_status(machine,which, select_mode, disk_unit) & DS_WRPROT))
840   {
841      /* unit is write protected */
842      hfdc[which].status |= ST_TC_RDIDERR;   /* right??? */
843      goto cleanup;
844   }
845#endif
1558   mark = (fm)? 10 : 16;  /* ID/DAM + A1 + CRC */
1559   
1560   exp_size = gap0 + inam + gap1 + count*(sync1 + mark + gap2 + sync2 + size*128 + gap3) + gap4;
1561     
1562   if (exp_size != data_count)
1563      logerror("smc92x4 warn: The current track length in the image (%d) does not match the new track length (%d). Keeping the old length. This will break the image (sorry).\n", data_count, exp_size);
1564   
1565   /* use the backup registers set up during drive_select */
1566   set_dma_address(device, CURRENT_IDENT, CURRENT_CYLINDER, CURRENT_HEAD);
8461567
847   read_id(machine,which, select_mode, disk_unit, head, ! (mode & 0x02), cylinder);
1568   memset(&buffer[index], pre_gap, gap0);
1569   index += gap0;
8481570
849   while (hfdc[which].regs[hfdc_reg_sector_count])
1571   if (w->intf->full_track_layout)
8501572   {
851      /* do read sector */
852      dma_address = dma_base_address;
853      switch (select_mode)
1573      /* Create the Index AM */
1574      memset(&buffer[index], 0x00, sync1);
1575      index += sync1;
1576      if (!fm)
8541577      {
855      case sm_undefined:
856      default:
857         break;
1578         memset(&buffer[index], 0xc2, 3);
1579         index += 3;         
1580      }
1581      memset(&buffer[index], gap_byte, gap1);
1582      index += gap1;     
1583   }
1584   
1585   /* for each sector */
1586   for (j=0; j < count; j++)
1587   {
1588      memset(&buffer[index], 0x00, sync1);
1589      index += sync1;
8581590
859      case sm_at_harddisk:
860         break;
1591      if (!fm)
1592      {
1593         memset(&buffer[index], 0xa1, 3);
1594         index += 3;
1595      }
8611596
862      case sm_harddisk:
863         if (! harddisk_read_sector(which, disk_unit, cylinder, head, sector, &dma_address))
864            goto cleanup;
865         break;
1597      buffer[index++] = 0xfe;
8661598
867      case sm_floppy_slow:
868      case sm_floppy_fast:
869         if (! smc92x4_floppy_read_sector(machine,which, disk_unit, cylinder, head, 1, sector, &dma_address))
870            goto cleanup;
871         break;
872      }
1599      smc92x4_set_dip(device, TRUE);
1600      if (!fm) curr_ident = (*w->intf->dma_read_callback)();
1601      curr_cyl = (*w->intf->dma_read_callback)();
1602      curr_head = (*w->intf->dma_read_callback)();
1603      curr_sect = (*w->intf->dma_read_callback)();
1604      curr_size = (*w->intf->dma_read_callback)();
1605      smc92x4_set_dip(device, FALSE);
8731606
874      hfdc[which].regs[hfdc_reg_sector_count]--;
875      if (hfdc[which].regs[hfdc_reg_sector_count])
876      {
877         /* read more sectors */
1607      buffer[index++] = curr_cyl;
1608      buffer[index++] = curr_head;
1609      buffer[index++] = curr_sect;
1610      buffer[index++] = curr_size;
8781611
879         /* increment desired sector */
880         sector++;
1612      // if (j==0) printf("current_floppy=%s, format track %d, head %d\n",  current_floppy->tag(), curr_cyl, curr_head);
8811613
882         /* update DMA address */
883         dma_base_address = dma_address;
1614      /* Calculate CRC16 (5 bytes for ID) */
1615      crc = ccitt_crc16(0xffff, &buffer[index-5], 5);
1616      buffer[index++] = (crc>>8)&0xff;
1617      buffer[index++] = crc & 0xff;
1618
1619      memset(&buffer[index], gap_byte, gap2);
1620      index += gap2;
1621
1622      memset(&buffer[index], 0x00, sync2);
1623      index += sync2;
1624
1625      if (!fm)
1626      {
1627         memset(&buffer[index], 0xa1, 3);
1628         index += 3;
8841629      }
885   }
1630     
1631      if (normal_data_mark) buffer[index++] = 0xfb;
1632      else buffer[index++] = 0xf8;
8861633
887cleanup:
888   /* update register state */
889   set_command_done(which);
1634      /* Sector data */
1635      for (i=0; i < 128*size; i++) buffer[index++] = 0xe5;
8901636
891   /* update DMA address */
892   hfdc[which].regs[hfdc_reg_dma_low] = dma_base_address & 0xff;
893   hfdc[which].regs[hfdc_reg_dma_mid] = (dma_base_address >> 8) & 0xff;
894   hfdc[which].regs[hfdc_reg_dma_high] = (dma_base_address >> 16) & 0xff;
1637      /* Calculate CRC16 (128*size+1 bytes for sector) */
1638      crc = ccitt_crc16(0xffff, &buffer[index-128*size-1], 128*size+1);
1639      buffer[index++] = (crc>>8)&0xff;
1640      buffer[index++] = crc & 0xff;
8951641
896   /* update desired sector register */
897   hfdc[which].regs[hfdc_reg_des_sector] = sector;
1642      memset(&buffer[index], gap_byte, gap3);
1643      index += gap3;
1644   }
8981645
899   /* set drive status */
900   hfdc[which].regs[hfdc_reg_drive_stat] = get_disk_status(machine,which, select_mode, disk_unit);
1646   memset(&buffer[index], gap_byte, gap4);
1647   index += gap4;
1648
1649   floppy_drive_write_track_data_info_buffer(current_floppy, w->register_w[DESIRED_HEAD]&0x0f, (char *)buffer, &data_count);
1650   free(buffer);
1651   sync_status_in(device);
9011652}
9021653
9031654/*
904    Handle the write command
905
906    which: disk controller selected
907    physical_flag: if 1, ignore CRC/ECC bytes??? (ignored)
908    mode: extra flags (ignored)
1655   Create the track layout of a MFM hard disk. Like floppy disks,
1656   MFM hard disks are interfaced on a track base, that is, we have to
1657   create a complete track layout.
1658   
1659   For more explanations see the comments to format_floppy_track.
9091660*/
910static void do_write(running_machine *machine,int which, int physical_flag, int mode)
1661static void format_harddisk_track(running_device *device, int flags)
9111662{
912   select_mode_t select_mode;
913   int disk_unit = 0;
914   int dma_base_address, dma_address;
915   int cylinder, head, sector;
1663   smc92x4_state *w = get_safe_token(device);
1664   int i,index,j;
1665   int gap0, gap1, gap2, gap3, gap4, sync, count, size, fm, gap_byte, crc;
1666   UINT8 curr_ident, curr_cyl, curr_head, curr_sect, curr_size;
9161667
917   hfdc[which].status = 0;
1668   int normal_data_mark = flags & 0x10;
1669   int data_count=0;
1670   
1671   UINT8 *buffer;
9181672
919   /* reset chip status */
920   hfdc[which].regs[hfdc_reg_chip_stat] = hfdc[which].disk_sel & 0x3;
1673   sync_status_in(device);
1674   
1675        /* Build buffer */
1676        gap0 = (-w->register_w[DMA7_0])&0xff;
1677        gap1 = (-w->register_w[DMA15_8])&0xff;
1678        gap2 = (-w->register_w[DMA23_16])&0xff;
1679        gap3 = (-w->register_w[DESIRED_SECTOR])&0xff;
1680        gap4 = 340;
9211681
922   dma_base_address = hfdc[which].regs[hfdc_reg_dma_low]
923                  | (hfdc[which].regs[hfdc_reg_dma_mid] << 8)
924                  | (hfdc[which].regs[hfdc_reg_dma_high] << 16);
1682   sync = (~w->register_w[DESIRED_CYLINDER])&0xff;
1683   count = (~w->register_w[SECTOR_COUNT])&0xff;
1684   size = (~w->register_w[RETRY_COUNT])&0xff;
9251685
926   sector = hfdc[which].regs[hfdc_reg_des_sector];
927   head = hfdc[which].regs[hfdc_reg_des_head] & 0xf;
928   cylinder = (((int) hfdc[which].regs[hfdc_reg_des_head] << 4) & 0x700)
929            | hfdc[which].regs[hfdc_reg_des_cyl];
1686   data_count = gap1 + count*(sync+12+gap2+sync+size*128+gap3)+gap4;
1687   
1688        buffer = (UINT8*)malloc(data_count);
1689   
1690   index = 0;
1691   fm = controller_set_to_single_density(device);
1692   gap_byte = 0x4e;
1693     
1694   /* use the backup registers set up during drive_select */
1695   set_dma_address(device, CURRENT_IDENT, CURRENT_CYLINDER, CURRENT_HEAD);
9301696
931   if (!get_selected_drive(which, & select_mode, & disk_unit))
1697   for (i=0; i < gap1; i++) buffer[index++] = gap_byte;
1698
1699   /* Now write the sectors. */
1700   for (j=0; j < count; j++)
9321701   {
933      /* no unit has been selected */
934      hfdc[which].status |= ST_TC_RDIDERR;
935      hfdc[which].regs[hfdc_reg_chip_stat] |= CS_SYNCERR;
936      goto cleanup;
1702      for (i=0; i < sync; i++) buffer[index++] = 0x00;
1703      buffer[index++] = 0xa1;
1704
1705      smc92x4_set_dip(device, TRUE);
1706      curr_ident = (*w->intf->dma_read_callback)();
1707      curr_cyl = (*w->intf->dma_read_callback)();
1708      curr_head = (*w->intf->dma_read_callback)();
1709      curr_sect = (*w->intf->dma_read_callback)();
1710      curr_size = (*w->intf->dma_read_callback)();
1711      smc92x4_set_dip(device, FALSE);
1712
1713      buffer[index++] = curr_ident;
1714      buffer[index++] = curr_cyl;
1715      buffer[index++] = curr_head;
1716      buffer[index++] = curr_sect;
1717      buffer[index++] = curr_size;
1718     
1719      /* Calculate CRC16 (5 bytes for ID) */
1720      crc = ccitt_crc16(0xffff, &buffer[index-5], 5);
1721      buffer[index++] = (crc>>8)&0xff;
1722      buffer[index++] = crc & 0xff;
1723
1724      /* GAP 2 */
1725      for (i=0; i < gap2; i++) buffer[index++] = gap_byte;
1726      for (i=0; i < sync; i++) buffer[index++] = 0x00;
1727     
1728      buffer[index++] = 0xa1;
1729     
1730      if (normal_data_mark) buffer[index++] = 0xfb;
1731      else buffer[index++] = 0xf8;
1732
1733      /* Sector data */
1734      for (i=0; i < 128*size; i++) buffer[index++] = 0xe5;
1735
1736      /* Calculate CRC16 (128*size+1 bytes for sector) */
1737      crc = ccitt_crc16(0xffff, &buffer[index-128*size-1], 128*size+1);
1738      buffer[index++] = (crc>>8)&0xff;
1739      buffer[index++] = crc & 0xff;
1740     
1741      /* GAP 3 */
1742      for (i=0; i < 3; i++) buffer[index++] = 0;  /* check that, unclear in spec */
1743      for (i=0; i < gap3 - 3; i++) buffer[index++] = gap_byte;
9371744   }
1745   /* GAP 4 */
1746   for (i=0; i < gap4; i++) buffer[index++] = gap_byte;
1747               
1748   (*w->intf->mfmhd_write_track)(w->register_w[DESIRED_HEAD]&0x0f, buffer, data_count);
1749   free(buffer);
1750   sync_status_in(device);
1751}
9381752
939   if (! (get_disk_status(machine,which, select_mode, disk_unit) & DS_READY))
1753/*
1754   Read a floppy track.
1755   A complete track is read at the position of the head. It reads the
1756   track from one index pulse to the next index pulse. (Note that the
1757   spec talks about "index mark" and "signal from the drive" which is
1758   a bit confusing, since the index AM is behind Gap0, the index hole
1759   is before Gap0. We should check with a real device. Also, it does not
1760   speak about the head, so we assume the head is set in the DESIRED_HEAD
1761   register.)
1762   
1763   TODO: The TDF format does not support index marks. Need to define TDF
1764   in a more flexible way. Also consider format variations.
1765   (Hint: Do a check for the standard "IBM" format. Should probably do
1766   a translation from IBM to PC99 and back. Requires to parse the track
1767   image before. Need to decide whether we generally translate to the IBM
1768   format or generally to the PC99 format between controller and format.
1769   Format is the image is always PC99.)
1770*/
1771static void read_floppy_track(running_device *device, int transfer_only_ids)
1772{
1773   smc92x4_state *w = get_safe_token(device);
1774   running_device *current_floppy = (*w->intf->current_floppy)();
1775
1776   floppy_image *floppy;
1777   /* Determine the track size. We cannot allow different sizes in this
1778   design. */
1779   int data_count = 0;
1780   int i;
1781   UINT8 *buffer;
1782   
1783   sync_latches_out(device);
1784   
1785        floppy = flopimg_get_image(current_floppy);
1786
1787   /* Determine the track size. We cannot allow different sizes in this
1788   design. */       
1789   if (floppy != NULL)
1790      data_count = floppy_get_track_size(floppy, 0, 0);
1791 
1792        if (data_count==0)
1793        {
1794                if (controller_set_to_single_density(device))
1795                        data_count = TRKSIZE_SD;
1796                else
1797                   data_count = TRKSIZE_DD;
1798        }
1799       
1800   buffer = (UINT8*)malloc(data_count);
1801   
1802   floppy_drive_read_track_data_info_buffer( current_floppy, w->register_w[DESIRED_HEAD]&0x0f, (char *)buffer, &data_count);
1803   sync_status_in(device);
1804   
1805   /* Transfer the buffer to the external memory. We assume the memory
1806   pointer has been set appropriately in the registers. */
1807   set_dma_address(device, DMA23_16, DMA15_8, DMA7_0);
1808
1809   if (transfer_only_ids)
9401810   {
941      /* unit is not ready */
942      hfdc[which].status |= ST_TC_RDIDERR;
943      hfdc[which].regs[hfdc_reg_chip_stat] |= CS_SYNCERR;
944      goto cleanup;
1811      logerror("smc92x4 read track: Ignoring transfer-only-ids. Reading complete track.\n");
9451812   }
9461813
947   if ((hfdc[which].regs[hfdc_reg_term] & TC_TWPROT)
948         && (get_disk_status(machine,which, select_mode, disk_unit) & DS_WRPROT))
1814   smc92x4_set_dip(device, TRUE);
1815   for (i=0; i < data_count; i++)
9491816   {
950      /* unit is write protected */
951      hfdc[which].status |= ST_TC_RDIDERR;   /* right??? */
952      goto cleanup;
1817      (*w->intf->dma_write_callback)(buffer[i]);
9531818   }
1819   smc92x4_set_dip(device, FALSE);
1820   
1821   free(buffer);     
1822}
9541823
1824static void read_harddisk_track(running_device *device, int transfer_only_ids)
1825{
1826   smc92x4_state *w = get_safe_token(device);
9551827
956   read_id(machine,which, select_mode, disk_unit, head, ! (mode & 0x40), cylinder);
1828   /* Determine the track size. We cannot allow different sizes in this
1829   design. */
1830   int i;
1831   UINT8 *buffer;
1832   int data_count=0;
9571833
958   while (hfdc[which].regs[hfdc_reg_sector_count])
959   {
960      /* do write sector */
961      dma_address = dma_base_address;
962      switch (select_mode)
963      {
964      case sm_undefined:
965      default:
966         break;
1834   sync_latches_out(device);
1835   
1836   /* buffer and data_count are allocated and set by the function. */   
1837   (*w->intf->mfmhd_read_track)(w->register_w[DESIRED_HEAD]&0x0f, &buffer, &data_count);
1838   sync_status_in(device);
9671839
968      case sm_at_harddisk:
969         break;
1840   /* Transfer the buffer to the external memory. We assume the memory
1841   pointer has been set appropriately in the registers. */
1842   set_dma_address(device, DMA23_16, DMA15_8, DMA7_0);
9701843
971      case sm_harddisk:
972         if (!harddisk_write_sector(which, disk_unit, cylinder, head, sector, &dma_address))
973            goto cleanup;
974         break;
1844   if (transfer_only_ids)
1845   {
1846      logerror("smc92x4 read track: Ignoring transfer-only-ids. Reading complete track.\n");
1847   }
9751848
976      case sm_floppy_slow:
977      case sm_floppy_fast:
978         if (!smc92x4_floppy_write_sector(machine,which, disk_unit, cylinder, head, 1, sector, &dma_address))
979            goto cleanup;
980         break;
981      }
1849   smc92x4_set_dip(device, TRUE);
1850   for (i=0; i < data_count; i++)
1851   {
1852      (*w->intf->dma_write_callback)(buffer[i]);
1853   }
1854   smc92x4_set_dip(device, FALSE);
1855   
1856   free(buffer);     
1857}
9821858
983      hfdc[which].regs[hfdc_reg_sector_count]--;
984      if (hfdc[which].regs[hfdc_reg_sector_count])
985      {
986         /* read more sectors */
9871859
988         /* increment desired sector */
989         sector++;
990
991         /* update DMA address */
992         dma_base_address = dma_address;
993      }
1860static void read_track(running_device *device)
1861{
1862   smc92x4_state *w = get_safe_token(device);
1863   int transfer_only_ids = w->command & 0x01;
1864   
1865   if (w->selected_drive_type & TYPE_FLOPPY)
1866   {
1867      read_floppy_track(device, transfer_only_ids);
9941868   }
1869   else
1870   {
1871      read_harddisk_track(device, transfer_only_ids);
1872   }
1873   
1874   smc92x4_timed_track_request(device);
1875}
9951876
996cleanup:
997   /* update register state */
998   set_command_done(which);
1877static void read_track_continue(running_device *device)
1878{
1879   smc92x4_state *w = get_safe_token(device);
1880   w->to_be_continued = FALSE;
1881   set_command_done(device,  ST_TC_SUCCESS);
1882}
9991883
1000   /* update DMA address */
1001   hfdc[which].regs[hfdc_reg_dma_low] = dma_base_address & 0xff;
1002   hfdc[which].regs[hfdc_reg_dma_mid] = (dma_base_address >> 8) & 0xff;
1003   hfdc[which].regs[hfdc_reg_dma_high] = (dma_base_address >> 16) & 0xff;
1884static void format_track(running_device *device)
1885{
1886   smc92x4_state *w = get_safe_token(device);
1887   int flags = w->command & 0x1f;
1888   
1889   if (w->selected_drive_type & TYPE_FLOPPY)
1890      format_floppy_track(device, flags);
1891   else
1892      format_harddisk_track(device, flags);
10041893
1005   /* update desired sector register */
1006   hfdc[which].regs[hfdc_reg_des_sector] = sector;
1894   smc92x4_timed_track_request(device);
1895}
10071896
1008   /* set drive status */
1009   hfdc[which].regs[hfdc_reg_drive_stat] = get_disk_status(machine,which, select_mode, disk_unit);
1897static void format_track_continue(running_device *device)
1898{
1899   smc92x4_state *w = get_safe_token(device);
1900   w->to_be_continued = FALSE;
1901   set_command_done(device,  ST_TC_SUCCESS);   
10101902}
10111903
10121904/*
1905   Continue to process after callback
1906*/
1907static void smc92x4_process_after_callback(running_device *device)
1908{
1909   smc92x4_state *w = get_safe_token(device);
1910   UINT8 opcode = w->command;
1911   if (opcode >= 0x02 && opcode <= 0x03)
1912   {
1913      restore_continue(device);
1914   }
1915   else if (opcode >= 0x04 && opcode <= 0x07)
1916   {
1917      step_continue(device);
1918   }
1919   else if (opcode >= 0x50 && opcode <= 0x57)
1920   {
1921      seek_read_id_continue(device);
1922   }
1923   else if ((opcode >= 0x58 && opcode <= 0x59)||(opcode >= 0x5C && opcode <= 0x5f))
1924   {         
1925      read_sectors_continue(device);
1926   }     
1927   else if (opcode >= 0x5a && opcode <= 0x5b)
1928   {         
1929      read_track_continue(device);
1930   }     
1931   else if (opcode >= 0x60 && opcode <= 0x7f)
1932   {
1933      format_track_continue(device);
1934   }
1935   else if (opcode >= 0x80)
1936   {
1937      write_sectors_continue(device);
1938   }
1939   else
1940   {
1941      logerror("smc92x4 warn: Invalid command %x or command changed while waiting for callback\n", opcode);
1942   }
1943}
1944
1945/*
10131946    Process a command
10141947*/
1015static void smc92x4_process_command(running_machine *machine,int which, int opcode)
1948static void smc92x4_process_command(running_device *device, UINT8 opcode)
10161949{
1017   if (opcode < 0x80)
1950   smc92x4_state *w = get_safe_token(device);
1951     
1952   //logerror("smc92x4 process command %02x\n", opcode);
1953   if (w->to_be_continued)
10181954   {
1019      switch (opcode >> 4)
1955      logerror("smc92x4 warn: previous command %02x not complete\n", w->command);
1956   }
1957
1958   /* Reset DONE and BAD_SECTOR. */
1959   w->register_r[INT_STATUS] &= ~(ST_DONE | ST_BADSECT);
1960
1961   /* Reset interrupt line (not explicitly mentioned in spec, but seems
1962   reasonable) */
1963   smc92x4_clear_interrupt(device);
1964   w->register_r[INT_STATUS] &= ~(ST_INTPEND | ST_RDYCHNG);
1965   
1966   w->command = opcode;
1967   w->found_id = FALSE;
1968   w->seek_count = 0;
1969   
1970   if (opcode == 0x00)
1971   {
1972      /* RESET */
1973      /* same effect as the RST* pin being active */
1974      logerror("smc92x4 info: reset command\n");
1975      smc92x4_reset(device);
1976   }
1977   else if (opcode == 0x01)
1978   {
1979      /* DESELECT DRIVE */
1980      /* done when no drive is in use */
1981      logerror("smc92x4 drdeselect command\n");
1982      w->output1 &= ~(OUT1_DRVSEL3|OUT1_DRVSEL2|OUT1_DRVSEL1|OUT1_DRVSEL0);
1983      w->output2 |= OUT2_DRVSEL3_;
1984      /* sync the latches on the PCB */
1985      sync_latches_out(device);
1986      sync_status_in(device);
1987   }
1988   else if (opcode >= 0x02 && opcode <= 0x03)
1989   {
1990      /* RESTORE DRIVE */
1991      /* bit 0: 0 -> command ends after last seek pulse, 1 -> command
1992      ends when the drive asserts the seek complete pin */
1993      logerror("smc92x4 restore command %X\n", opcode);
1994      restore_drive(device);
1995   }
1996   else if (opcode >= 0x04 && opcode <= 0x07)
1997   {
1998      /* STEP IN/OUT ONE CYLINDER */
1999      logerror("smc92x4 step in/out command %X\n", opcode);
2000      step_in_out(device);
2001   }
2002   else if (opcode >= 0x08 && opcode <= 0x0f)
2003   {
2004      /* TAPE BACKUP (08-0f)*/
2005      logerror("smc92x4 warn: tape backup command %X not implemented\n", opcode);
2006   }
2007   else if (opcode >= 0x10 && opcode <= 0x1f)
2008   {
2009      /* POLLDRIVE */
2010      logerror("smc92x4 polldrive command %X\n", opcode);
2011      poll_drives(device);
2012   }
2013   else if (opcode >= 0x20 && opcode <= 0x3f)
2014   {
2015      /* DRIVE SELECT */
2016      logerror("smc92x4 drselect command %X\n", opcode);
2017      drive_select(device, opcode&0x1f);
2018   }
2019   else if (opcode >= 0x40 && opcode <= 0x4f)
2020   {
2021      /* SETREGPTR */
2022      logerror("smc92x4 setregptr command %X\n", opcode);
2023      w->register_pointer = opcode & 0xf;
2024      /* Spec does not say anything about the effect of setting an
2025      invalid value (only "care should be taken") */
2026      if (w->register_pointer > 10)
10202027      {
1021      case 0x0:   /* misc commands */
1022         if (opcode < 0x04)
1023         {
1024            switch (opcode)
1025            {
1026            case 0x00:
1027               /* RESET */
1028               /* same effect as the RST* pin being active */
1029               logerror("smc92x4 reset command\n");
1030               smc92x4_reset(which);
1031               break;
1032            case 0x01:
1033               /* DESELECT DRIVE */
1034               /* done when no drive is in use */
1035               logerror("smc92x4 drdeselect command\n");
1036               hfdc[which].disk_sel = disk_sel_none;
1037               set_command_done(which);
1038               break;
1039            case 0x02:
1040            case 0x03:
1041               /* RESTORE DRIVE */
1042               /* bit 0: 0 -> command ends after last seek pulse, 1 -> command
1043                        ends when the drive asserts the seek complete pin */
1044               logerror("smc92x4 restore command %X\n", opcode & 0x01);
1045               do_restore(machine,which, opcode & 0x01);
1046               break;
1047            }
1048         }
1049         else if (opcode < 0x08)
1050         {
1051            /* STEP IN/OUT ONE CYLINDER */
1052            /* bit 1: direction (0 -> inward, 1 -> outward i.e. toward cyl #0) */
1053            /* bit 0: 0 -> command ends after last seek pulse, 1 -> command
1054                    ends when the drive asserts the seek complete pin */
1055            logerror("smc92x4 step command %X\n", opcode & 0x3);
1056            do_step(machine,which, opcode & 0x03);
1057         }
1058         else
1059         {
1060            /* TAPE BACKUP */
1061            logerror("smc92x4 tape backup command %X\n", opcode);
1062         }
1063         break;
1064      case 0x1:
1065         /* POLLDRIVE */
1066         /* bit 3-0: one bit for each drive to test */
1067         logerror("smc92x4 polldrive command %X\n", opcode & 0xf);
1068         break;
1069      case 0x2:
1070      case 0x3:
1071         /* DRSELECT */
1072         /* bit 4: if 1, apply head load delay */
1073         /* bit 3 & 2: disk type (0-3): 0 for hard disk in IBM-AT format, 1
1074                for hard disk in standard SMC format, 2 for high-speed (8" or
1075                HD(?)) floppy, 3 for low-speed (5"1/4 DD?) floppy disk */
1076         /* bit 1 & 0: unit number (0-3)*/
1077         logerror("smc92x4 drselect command %X\n", opcode & 0xf);
1078         hfdc[which].disk_sel = opcode & 0xf;
1079         set_command_done(which);
1080         break;
1081      case 0x4:
1082         /* SETREGPTR */
1083         /* bit 3-0: reg-number (should be in [0,10]) */
1084         logerror("smc92x4 setregptr command %X\n", opcode & 0xf);
1085         hfdc[which].reg_ptr = opcode & 0xf;
1086         set_command_done(which);
1087         break;
1088      case 0x5:
1089         if (opcode < 0x58)
1090         {
1091            /* SEEK/READ ID */
1092            /* bit 2: step enable */
1093            /* bit 1: wait for seek complete signal */
1094            /* bit 0: verify ID */
1095            logerror("smc92x4 seekreadid command %X\n", opcode & 0x7);
1096         }
1097         else
1098         {
1099            /* READ */
1100            /* bits 2-1: 0 -> read physical, 1 -> read track, 2 -> read
1101                    logical with implied seek, 3 -> read logical with no
1102                    implied seek */
1103            /* bit 0: 0 -> do not transfer data (transfer ID fields for
1104                    read track command), 1 -> transfer data */
1105            switch ((opcode >> 1) & 0x3)
1106            {
1107            case 0:
1108               logerror("smc92x4 read physical command %X\n", opcode & 0x1);
1109               do_read(machine,which, 1, opcode & 0x3);
1110               break;
1111            case 1:
1112               logerror("smc92x4 read track command %X\n", opcode & 0x1);
1113               break;
1114            case 2:
1115            case 3:
1116               logerror("smc92x4 read logical command %X\n", opcode & 0x3);
1117               do_read(machine,which, 0, opcode & 0x3);
1118               break;
1119            }
1120         }
1121         break;
1122      case 0x6:
1123      case 0x7:
1124         /* FORMAT TRACK */
1125         /* bit 4: 0 -> write deleted data mark instead of normal address
1126                mark */
1127         /* bit 3: 1 -> write with reduced current */
1128         /* bit 2-0: write precompensation value */
1129         logerror("smc92x4 formattrack command %X\n", opcode & 0xf);
1130         break;
2028         logerror("smc92x4 error: set register pointer: Invalid register number: %d. Setting to 10.\n", w->register_pointer);
2029         w->register_pointer = 10;
11312030      }
11322031   }
2032   else if (opcode >= 0x50 && opcode <= 0x57)
2033   {
2034      /* SEEK/READ ID */
2035      logerror("smc92x4 seekreadid command %X\n", opcode);
2036      seek_read_id(device);
2037   }
2038   else if ((opcode >= 0x58 && opcode <= 0x59)
2039      || (opcode >= 0x5C && opcode <= 0x5f)
2040      || (opcode >= 0x80))
2041   {         
2042      /* READ/WRITE SECTORS PHYSICAL/LOGICAL */
2043      logerror("smc92x4 read/write sector command %X\n", opcode);
2044      read_write_sectors(device);
2045   }     
2046   else if (opcode >= 0x5A && opcode <= 0x5b)
2047   {         
2048      /* READ TRACK */
2049      logerror("smc92x4 read track command %X\n", opcode);
2050      read_track(device);
2051   }     
2052   else if (opcode >= 0x60 && opcode <= 0x7f)
2053   {
2054      /* FORMAT TRACK */
2055      logerror("smc92x4 format track command %X\n", opcode);
2056      format_track(device);
2057   }
11332058   else
11342059   {
1135      /* WRITE */
1136      /* bits 6: 0 -> implied seek, 1-> no implied seek */
1137      /* bit 5: 0 -> write physical, 1 -> write logical */
1138      /* bit 4: 1 -> write deleted data mark instead of normal address mark */
1139      /* bit 3: 1 -> write with reduced current */
1140      /* bit 2-0: write precompensation value */
1141      logerror("smc92x4 write command %X\n", opcode & 0x7f);
1142      switch ((opcode >> 5) & 0x3)
1143      {
1144      case 0:
1145         logerror("smc92x4 write physical command %X\n", opcode & 0x7f);
1146         do_write(machine,which, 1, opcode & 0x7f);
1147         break;
1148      case 1:
1149         logerror("smc92x4 write logical command %X\n", opcode & 0x7f);
1150         do_write(machine,which, 0, opcode & 0x7f);
1151         break;
1152      case 2:
1153         logerror("smc92x4 write physical command??? %X\n", opcode & 0x7f);
1154         do_write(machine,which, 1, opcode & 0x7f);
1155         break;
1156      case 3:
1157         logerror("smc92x4 write logical command??? %X\n", opcode & 0x7f);
1158         do_write(machine,which, 0, opcode & 0x7f);
1159         break;
1160      }
2060      logerror("smc92x4 warn: Invalid command %x, ignored\n", opcode);
11612061   }
2062   
2063   if (!w->to_be_continued)
2064      set_command_done(device);
11622065}
11632066
1164/*
2067/***************************************************************************
11652068    Memory accessors
1166*/
2069****************************************************************************/
11672070
11682071/*
1169    Read a byte of data from a smc99x4 controller
2072   Read a byte of data from a smc92x4 controller
2073   The address (offset) encodes the C/D* line (command and /data)
11702074*/
1171int smc92x4_r(running_machine *machine,int which, int offset)
2075READ8_DEVICE_HANDLER( smc92x4_r )
11722076{
1173   int reply = 0;
1174
1175   switch (offset & 1)
2077   UINT8 reply = 0;
2078   smc92x4_state *w = get_safe_token(device);
2079   
2080   if ((offset & 1) == 0)
11762081   {
1177   case 0:
11782082      /* data register */
1179      logerror("smc92x4 data read\n");
1180      if (hfdc[which].reg_ptr < 10)
1181      {
1182         /* config register */
1183         reply = hfdc[which].regs[(hfdc[which].reg_ptr < 4) ? (hfdc[which].reg_ptr) : (hfdc[which].reg_ptr + 6)];
1184         hfdc[which].reg_ptr++;
1185      }
1186      else if (hfdc[which].reg_ptr == 10)
1187      {
1188         /* data register */
1189      }
1190      else
1191      {
1192         /* ??? */
1193      }
1194      break;
2083      reply = w->register_r[w->register_pointer];
2084      // printf("smc92x4 register_r[%d] -> %02x\n", w->register_pointer, reply);
11952085
1196   case 1:
2086      /* Autoincrement until DATA is reached. */
2087      if (w->register_pointer < DATA)
2088         w->register_pointer++;
2089   }
2090   else
2091   {
11972092      /* status register */
1198      logerror("smc92x4 status read\n");
1199      reply = hfdc[which].status;
1200      smc92x4_set_interrupt(which, 0);
1201      break;
2093      reply = w->register_r[INT_STATUS];
2094      /* Spec (p.3) : The interrupt pin is reset to its inactive state
2095          when the UDC interrupt status register is read. */
2096      // printf("smc92x4 interrupt status read = %02x\n", reply);
2097      smc92x4_clear_interrupt(device);
2098      /* Clear the bits due to int status register read. */
2099      w->register_r[INT_STATUS] &= ~(ST_INTPEND | ST_RDYCHNG);
12022100   }
1203
12042101   return reply;
12052102}
12062103
12072104/*
1208    Write a byte to a smc99x4 controller
2105   Write a byte to a smc99x4 controller
2106   The address (offset) encodes the C/D* line (command and /data)
12092107*/
1210void smc92x4_w(running_machine *machine,int which, int offset, int data)
2108WRITE8_DEVICE_HANDLER( smc92x4_w )
12112109{
2110   smc92x4_state *w = get_safe_token(device);
12122111   data &= 0xff;
12132112
1214   switch (offset & 1)
2113   if ((offset & 1) == 0)
12152114   {
1216   case 0:
12172115      /* data register */
1218      logerror("smc92x4 data write %X\n", data);
1219      if (hfdc[which].reg_ptr < 10)
1220      {
1221         /* config register */
1222         hfdc[which].regs[hfdc[which].reg_ptr] = data;
1223         hfdc[which].reg_ptr++;
1224      }
1225      else if (hfdc[which].reg_ptr == 10)
1226      {
1227         /* data register */
1228      }
1229      else
1230      {
1231         /* ??? */
1232      }
1233      break;
2116      // printf("smc92x4 register_w[%d] <- %X\n", w->register_pointer, data);
2117      w->register_w[w->register_pointer] = data;
12342118
1235   case 1:
2119      /* The DMA registers and the sector register for read and
2120         write are identical. */
2121      if (w->register_pointer < DESIRED_HEAD)
2122         w->register_r[w->register_pointer] = data;
2123     
2124      /* Autoincrement until DATA is reached. */
2125      if (w->register_pointer < DATA)
2126         w->register_pointer++;     
2127   }
2128   else
2129   {
12362130      /* command register */
1237      smc92x4_process_command(machine,which, data);
1238      break;
2131      smc92x4_process_command(device, data);
12392132   }
12402133}
12412134
1242 READ8_HANDLER(smc92x4_0_r)
2135
2136
2137/***************************************************************************
2138    DEVICE FUNCTIONS
2139***************************************************************************/
2140
2141static DEVICE_START( smc92x4 )
12432142{
1244   return smc92x4_r(space->machine,0, offset);
2143   smc92x4_state *w = get_safe_token(device);
2144   assert(device->baseconfig().static_config != NULL);
2145   
2146   w->intf = (const smc92x4_interface*)device->baseconfig().static_config;
2147   devcb_resolve_write_line(&w->out_intrq_func, &w->intf->out_intrq_func, device);
2148   devcb_resolve_write_line(&w->out_dip_func, &w->intf->out_dip_func, device);
2149   devcb_resolve_write8(&w->out_auxbus_func, &w->intf->out_auxbus_func, device);
2150   devcb_resolve_read_line(&w->in_auxbus_func, &w->intf->in_auxbus_func, device);
2151   
2152   /* allocate timers */
2153   /*
2154   w->timer_data = timer_alloc(device->machine, smc92x4_data_callback, (void *)device); */
2155   w->timer_rs = timer_alloc(device->machine, smc92x4_read_sector_callback, (void *)device);
2156   w->timer_ws = timer_alloc(device->machine, smc92x4_write_sector_callback, (void *)device);
2157   w->timer_track = timer_alloc(device->machine, smc92x4_track_callback, (void *)device);
2158   w->timer_seek = timer_alloc(device->machine, smc92x4_seek_callback, (void *)device);
2159   
2160   w->use_real_timing = TRUE;
12452161}
12462162
1247WRITE8_HANDLER(smc92x4_0_w)
2163static DEVICE_RESET( smc92x4 )
12482164{
1249   smc92x4_w(space->machine,0, offset, data);
2165   smc92x4_state *w = get_safe_token(device);
2166   smc92x4_clear_interrupt(device);
2167   smc92x4_set_dip(device, FALSE);
2168   
2169   for (int i=0; i<11; i++)
2170      w->register_r[i] = w->register_w[i] = 0;
12502171}
12512172
1252static const struct harddisk_callback_config smc92x4_harddisk_config =
2173void smc92x4_reset(running_device *device)
12532174{
1254   DEVICE_IMAGE_LOAD_NAME( smc92x4_hd ),
1255   DEVICE_IMAGE_UNLOAD_NAME( smc92x4_hd )
1256};
2175   DEVICE_RESET_CALL( smc92x4 );
2176}
12572177
2178void smc92x4_set_timing(running_device *device, int realistic)
2179{
2180   smc92x4_state *w = get_safe_token(device);
2181   w->use_real_timing = realistic;   
2182}
12582183
1259MACHINE_DRIVER_START( smc92x4_hd )
1260   MDRV_DEVICE_ADD( "harddisk1", HARDDISK, 0 )
1261   MDRV_DEVICE_CONFIG( smc92x4_harddisk_config )
1262   MDRV_DEVICE_ADD( "harddisk2", HARDDISK, 0 )
1263   MDRV_DEVICE_CONFIG( smc92x4_harddisk_config )
1264   MDRV_DEVICE_ADD( "harddisk3", HARDDISK, 0 )
1265   MDRV_DEVICE_CONFIG( smc92x4_harddisk_config )
1266MACHINE_DRIVER_END
2184/***************************************************************************
2185    DEVICE GETINFO
2186***************************************************************************/
2187
2188static const char DEVTEMPLATE_SOURCE[] = __FILE__;
2189
2190#define DEVTEMPLATE_ID(p,s)            p##smc92x4##s
2191#define DEVTEMPLATE_FEATURES            DT_HAS_START | DT_HAS_RESET
2192#define DEVTEMPLATE_NAME            "SMC92x4"
2193#define DEVTEMPLATE_FAMILY            "SMC92x4"
2194#define DEVTEMPLATE_VERSION            "1.0"
2195#define DEVTEMPLATE_CREDITS            "Copyright MESS Team"
2196#include "devtempl.h"
2197
src/mess/machine/ti99_4x.c
r8042r8043
105105   model_99_8,
106106   model_99_4p
107107} ti99_model;
108/* memory extension type */
109static xRAM_kind_t xRAM_kind;
108
110109/* TRUE if speech synthesizer present */
111110static char has_speech;
112/* floppy disk controller type */
113static fdc_kind_t fdc_kind;
111
114112/* TRUE if ide card present */
115113static char has_ide;
116114/* TRUE if evpc card present */
r8042r8043
134132static int handset_buflen;
135133static int handset_clock;
136134static int handset_ack;
135
136/* Expansion RAM type */
137static int xRAM_kind;
138
137139enum
138140{
139141   max_handsets = 4
r8042r8043
498500
499501   /* read config */
500502   if (ti99_model == model_99_8)
501      xRAM_kind = xRAM_kind_99_8;         /* hack */
503      xRAM_kind = RAM_99_8;
502504   else if (ti99_model == model_99_4p)
503      xRAM_kind = xRAM_kind_99_4p_1Mb;   /* hack */
505      xRAM_kind = RAM_99_4P;
504506   else
505      xRAM_kind = (xRAM_kind_t)((input_port_read(machine, "CFG") >> config_xRAM_bit) & config_xRAM_mask);
507      xRAM_kind = input_port_read(machine, "RAM");
508   
506509   if (ti99_model == model_99_8)
507510      has_speech = TRUE;
508511   else
509      has_speech = (input_port_read(machine, "CFG") >> config_speech_bit) & config_speech_mask;
510   fdc_kind = (fdc_kind_t)((input_port_read(machine, "CFG") >> config_fdc_bit) & config_fdc_mask);
511   has_ide = (input_port_read(machine, "CFG") >> config_ide_bit) & config_ide_mask;
512   has_rs232 = (input_port_read(machine, "CFG") >> config_rs232_bit) & config_rs232_mask;
513   has_handset = (ti99_model == model_99_4) && ((input_port_read(machine, "CFG") >> config_handsets_bit) & config_handsets_mask);
514   has_hsgpl = ((ti99_model == model_99_4p) || (input_port_read(machine, "CFG") >> config_hsgpl_bit) & config_hsgpl_mask);
515   has_usb_sm = (input_port_read(machine, "CFG") >> config_usbsm_bit) & config_usbsm_mask;
516   has_pcode = (input_port_read(machine, "CFG") >> config_pcode_bit) & config_pcode_mask;
512      has_speech = input_port_read(machine, "SPEECH");
513   
514   has_ide = input_port_read(machine, "HDCTRL") & HD_IDE;
515   has_rs232 = input_port_read(machine, "SERIAL") & SERIAL_TI;
517516
517   if (ti99_model == model_99_4)
518      has_handset = input_port_read(machine, "HCI") & HCI_IR;
519   else
520      has_handset = FALSE;
521   
522   if (ti99_model == model_99_4p)
523      has_hsgpl = TRUE;
524   else
525      has_hsgpl = input_port_read(machine, "EXTCARD") & EXT_HSGPL;
526
527   has_usb_sm = input_port_read(machine, "HDCTRL") & HD_USB;
528   has_pcode = input_port_read(machine, "EXTCARD") & EXT_PCODE;
529
518530   /* set up optional expansion hardware */
519531   ti99_peb_reset(ti99_model == model_99_4p, tms9901_set_int1, NULL);
520532
r8042r8043
545557
546558   switch (xRAM_kind)
547559   {
548   case xRAM_kind_none:
560   case RAM_NONE:
549561   default:
550562      memory_install_read16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_nop_8_r);
551563      memory_install_write16_handler(space, 0x2000, 0x3fff, 0, 0, ti99_nop_8_w);
552564      memory_install_read16_handler(space, 0xa000, 0xffff, 0, 0, ti99_nop_8_r);
553565      memory_install_write16_handler(space, 0xa000, 0xffff, 0, 0, ti99_nop_8_w);
554566      break;
555   case xRAM_kind_TI:
567   case RAM_TI32:
556568      ti99_TIxram_init(machine);
557569      break;
558   case xRAM_kind_super_AMS:
570   case RAM_SUPERAMS1024:
559571      ti99_sAMSxram_init(machine);
560572      break;
561   case xRAM_kind_99_4p_1Mb:
573   case RAM_99_4P:
562574      ti99_4p_mapper_init(machine);
563575      break;
564   case xRAM_kind_foundation_128k:
565   case xRAM_kind_foundation_512k:
566   case xRAM_kind_myarc_128k:
567   case xRAM_kind_myarc_512k:
576   case RAM_FOUNDATION128:
577   case RAM_FOUNDATION512:
578   case RAM_MYARC128:
579   case RAM_MYARC512:
568580      ti99_myarcxram_init(machine);
569581      break;
570   case xRAM_kind_99_8:
582   case RAM_99_8:
571583      break;
572584   }
573585
574   switch (fdc_kind)
586   switch (input_port_read(machine, "DISKCTRL"))
575587   {
576   case fdc_kind_TI:
588   case DISK_TIFDC:
577589      ti99_fdc_reset(machine);
578590      break;
579591#if HAS_99CCFDC
580   case fdc_kind_CC:
592   case DISK_CC:
581593      ti99_ccfdc_reset(machine);
582594      break;
583595#endif
584   case fdc_kind_BwG:
596   case DISK_BWG:
585597      ti99_bwg_reset(machine);
586598      break;
587   case fdc_kind_hfdc:
599   case DISK_HFDC:
588600      ti99_hfdc_reset(machine);
589601      break;
590   case fdc_kind_none:
602   case DISK_NONE:
591603      break;
592604   }
593605
r8042r8043
650662   TMS9928A_interrupt(device->machine);
651663   if (has_handset)
652664      ti99_handset_task(device->machine);
653   has_mecmouse = (input_port_read(device->machine, "CFG") >> config_mecmouse_bit) & config_mecmouse_mask;
665   has_mecmouse = input_port_read(device->machine, "HCI") & HCI_MECMOUSE;
654666   if (has_mecmouse)
655667      mecmouse_poll(device->machine);
656668}
r8042r8043
662674   if (++line_count == 262)
663675   {
664676      line_count = 0;
665      has_mecmouse = (input_port_read(device->machine, "CFG") >> config_mecmouse_bit) & config_mecmouse_mask;
677      has_mecmouse = input_port_read(device->machine, "HCI") & HCI_MECMOUSE;
666678      if (has_mecmouse)
667679         mecmouse_poll(device->machine);
668680   }
r8042r8043
28192831
28202832   switch (xRAM_kind)
28212833   {
2822   case xRAM_kind_foundation_128k:   /* 128kb foundation */
2823   case xRAM_kind_myarc_128k:      /* 128kb myarc clone */
2834   case RAM_FOUNDATION128:   /* 128kb foundation */
2835   case RAM_MYARC128:      /* 128kb myarc clone */
28242836      myarc_page_offset_mask = 0x0c000;
28252837      break;
2826   case xRAM_kind_foundation_512k:   /* 512kb foundation */
2827   case xRAM_kind_myarc_512k:      /* 512kb myarc clone */
2838   case RAM_FOUNDATION512:   /* 512kb foundation */
2839   case RAM_MYARC512:      /* 512kb myarc clone */
28282840      myarc_page_offset_mask = 0x3c000;
28292841      break;
28302842   default:
r8042r8043
28332845
28342846   switch (xRAM_kind)
28352847   {
2836   case xRAM_kind_foundation_128k:   /* 128kb foundation */
2837   case xRAM_kind_foundation_512k:   /* 512kb foundation */
2848   case RAM_FOUNDATION128:   /* 128kb foundation */
2849   case RAM_FOUNDATION512:   /* 512kb foundation */
28382850      ti99_peb_set_card_handlers(0x1e00, & myarc_expansion_handlers);
28392851      break;
2840   case xRAM_kind_myarc_128k:      /* 128kb myarc clone */
2841   case xRAM_kind_myarc_512k:      /* 512kb myarc clone */
2852   case RAM_MYARC128:      /* 128kb myarc clone */
2853   case RAM_MYARC512:      /* 512kb myarc clone */
28422854      ti99_peb_set_card_handlers(0x1000, & myarc_expansion_handlers);
28432855      ti99_peb_set_card_handlers(0x1900, & myarc_expansion_handlers);
28442856      break;
src/mess/machine/smc92x4.h
r8042r8043
1/* Interface */
2
3#ifndef SMC92X4
4#define SMC92X4      DEVICE_GET_INFO_NAME(smc92x4)
5
6#define INPUT_STATUS    0x00
7#define OUTPUT_DMA_ADDR 0x01
8#define OUTPUT_OUTPUT1    0x02
9#define OUTPUT_OUTPUT2    0x03
10
11#define MFMHD_TRACK00    0x80
12#define MFMHD_SEEKCOMP   0x40
13#define MFMHD_WRFAULT   0x20
14#define MFMHD_READY   0x10
15#define MFMHD_INDEX   0x08
16
17#define BAD_SECTOR    0x1000
18#define BAD_CRC      0x2000
19
120/*
2    smc92x4.h: header file for smc92x4.c
21    Definition of bits in the Disk-Status register
22*/
23#define DS_ECCERR   0x80      /* ECC error */
24#define DS_INDEX   0x40      /* index point */
25#define DS_SKCOM   0x20      /* seek complete */
26#define DS_TRK00   0x10      /* track 0 */
27#define DS_UDEF      0x08      /* user-defined */
28#define DS_WRPROT   0x04      /* write protect */
29#define DS_READY   0x02      /* drive ready bit */
30#define DS_WRFAULT   0x01      /* write fault */
331
4    Raphael Nabet
32/*
33   Needed to adapt to higher cylinder numbers. Floppies do not have such
34   high numbers.
535*/
6
7/* this enum matches the possible values for bits 3-2 of the select register */
8typedef enum select_mode_t
36typedef struct chrn_id_hd
937{
10   sm_undefined = -1,      /* value after reset and drive deselect(right?) */
11   sm_at_harddisk = 0,      /* hard disk in PC-AT compatible harddisk format */
12   sm_harddisk,         /* hard disk */
13   sm_floppy_slow,         /* 8" drive (and 5.25" and 3.5" HD disks?) */
14   sm_floppy_fast         /* 5.25" and 3.5" drive */
15} select_mode_t;
38   UINT16 C;
39   UINT8 H;
40   UINT8 R;
41   UINT8 N;
42   int data_id;         // id for read/write data command
43   unsigned long flags;
44} chrn_id_hd;
1645
17typedef struct smc92x4_intf
46typedef struct _smc92x4_interface
1847{
19   /* select_callback serves 2 purposes:
20    a) the emulated system may use other lines than the normal smc92x4 select
21      lines
22    b) if there is more than one smc92x4 controller, we need to have different
23      drive numbers for each controller
24    which: smc92x4 controller concerned
25    select_mode: any of sm_harddisk, sm_floppy_slow or sm_floppy_fast
26    select_line: state smc92x4 select lines (0: no line active, 1, 2, 3: first,
27      second or third line active)
28    gpos: state of 4 general prurpose outputs that are used as floppy select
29      lines by the (4 LSBits of smc99x4 retry count register)
30    return -1 if no drive is selected, or index of image in MESS IO_FLOPPY
31      IO_HARDDISK device array. */
32   int (*select_callback)(int which, select_mode_t select_mode, int select_line, int gpos);
33   /* dma_read_callback will be called by the smc99x4 core to read the sector
34    buffer */
35   UINT8 (*dma_read_callback)(int which, offs_t offset);
36   /* dma_read_callback will be called by the smc99x4 core to write the sector
37    buffer */
38   void (*dma_write_callback)(int which, offs_t offset, UINT8 data);
39   /* int_callback will be called by the smc99x4 core whenever the state of
40    the interrupt lien changes */
41   void (*int_callback)(int which, int state);
42} smc92x4_intf;
48   /* Disk format support. This flag allows to choose between the full
49      FM/MFM format and an abbreviated track layout. The difference results
50      from legal variations of the layout. This is not part of
51      the smc92x4 specification, but it allows to keep the image format
52      simple without too much case checking. Should be removed as soon as
53      the respective disk formats support the full format. */
54   int full_track_layout;
4355
56   /* Interrupt line. To be connected with the controller PCB. */
57   devcb_write_line out_intrq_func;
4458
45void smc92x4_init(int which, const smc92x4_intf *intf);
46void smc92x4_reset(int which);
47int smc92x4_r(running_machine *machine,int which, int offset);
48void smc92x4_w(running_machine *machine,int which, int offset, int data);
49 READ8_HANDLER(smc92x4_0_r);
50WRITE8_HANDLER(smc92x4_0_w);
59   /* DMA in progress line. To be connected with the controller PCB. */
60   devcb_write_line out_dip_func;
5161
52MACHINE_DRIVER_EXTERN( smc92x4_hd );
62   /* Auxiliary Bus. These 8 lines need to be connected to external latches
63   and to a counter circuitry which works together with the external RAM.
64   We use the S0/S1 lines as address lines.
65   */
66   devcb_write8 out_auxbus_func;
67   
68   /* Auxiliary Bus. This is only used for S0=S1=0, so we need no address
69   lines and consider this line just as a line with 256 states. */
70   devcb_read_line in_auxbus_func;
5371
72   /* Get the currently selected floppy disk. This is determined by the
73      circuitry on the controller board, not within the controller itself.
74   */
75   running_device *(*current_floppy)(void);
76
77   /* Callback to read the contents of the external RAM via the data bus.
78      Note that the address must be set and automatically increased
79      by external circuitry. */
80   UINT8 (*dma_read_callback)(void);
81   
82   /* Callback to write the contents of the external RAM via the data bus.
83      Note that the address must be set and automatically increased
84      by external circuitry. */
85   void (*dma_write_callback)(UINT8 data);
86
87   /* Preliminary MFM hard disk interface. Gets next id. */
88   void (*mfmhd_get_next_id)(int head, chrn_id_hd *id);
89
90   /* Preliminary MFM hard disk interface. Performs a seek. */
91   void (*mfmhd_seek)(int direction);   
92
93   /* Preliminary MFM hard disk interface. Reads a sector. */
94   void (*mfmhd_read_sector)(int cylinder, int head, int sector, UINT8 **buf, int *sector_length);   
95
96   /* Preliminary MFM hard disk interface. Writes a sector. */
97   void (*mfmhd_write_sector)(int cylinder, int head, int sector, UINT8 *buf, int sector_length);   
98
99   /* Preliminary MFM hard disk interface. Reads a track. */
100   void (*mfmhd_read_track)(int head, UINT8 **buffer, int *data_count);   
101
102   /* Preliminary MFM hard disk interface. Writes a track. */
103   void (*mfmhd_write_track)(int head, UINT8 *buffer, int data_count);     
104} smc92x4_interface;
105
106/* device interface */
107extern DEVICE_GET_INFO(smc92x4);
108
109void smc92x4_reset(running_device *device);
110
111/* Used to turn off the delays. */
112void smc92x4_set_timing(running_device *device, int realistic);
113
114/* Generic function to translate between cylinders and idents */
115UINT8 cylinder_to_ident(int cylinder);
116
117READ8_DEVICE_HANDLER( smc92x4_r );
118WRITE8_DEVICE_HANDLER( smc92x4_w );
119
120#define MDRV_SMC92X4_ADD(_tag, _intrf) \
121   MDRV_DEVICE_ADD(_tag, SMC92X4, 0) \
122   MDRV_DEVICE_CONFIG(_intrf)
123   
124#endif
src/mess/machine/ti99_4x.h
r8042r8043
7777   region_hsgpl_len  = /*0x240000*/0x230000
7878};
7979
80/* enum for RAM config */
81typedef enum
82{
83   xRAM_kind_none = 0,
84   xRAM_kind_TI,            /* 32kb TI and clones */
85   xRAM_kind_super_AMS,      /* 1Mb super AMS */
86   xRAM_kind_foundation_128k,   /* 128kb foundation */
87   xRAM_kind_foundation_512k,   /* 512kb foundation */
88   xRAM_kind_myarc_128k,      /* 128kb myarc clone (no ROM) */
89   xRAM_kind_myarc_512k,      /* 512kb myarc clone (no ROM) */
90
91   xRAM_kind_99_4p_1Mb,      /* ti99/4p super AMS clone */
92   xRAM_kind_99_8            /* ti99/8 memory mapper */
93} xRAM_kind_t;
94
95/* enum for fdc config */
96typedef enum
97{
98   fdc_kind_none = 0,
99   fdc_kind_TI,            /* TI fdc */
100   fdc_kind_BwG,            /* SNUG's BwG fdc */
101   fdc_kind_hfdc            /* Myarc's HFDC (handles SD and DD floppies (I
102                                    think an HD update existed) and prehistoric
103                                    MFM hard disks) */
104#if HAS_99CCFDC
105   ,
106   fdc_kind_CC = 0x100         /* CorComp fdc */
107#endif
108} fdc_kind_t;
109
11080/* GROM_port_t: descriptor for a port of 8 GROMs. Required by ti99_4x, ti99pcod */
11181struct _GROM_port_t
11282{
r8042r8043
12494typedef struct _GROM_port_t GROM_port_t;
12595
12696
97#if 0
12798/* defines for input port "CFG" */
12899enum
129100{
r8042r8043
153124   config_pcode_bit   = 18,
154125   config_pcode_mask   = 0x1
155126};
127#endif
156128
157enum {
129/*
130   Configuration values
131*/
132enum
133{
134   RAM_NONE = 0,
135   RAM_TI32,
136   RAM_SUPERAMS1024,
137   RAM_FOUNDATION128,
138   RAM_FOUNDATION512,
139   RAM_MYARC128,
140   RAM_MYARC512,
141   RAM_99_4P,
142   RAM_99_8
143};
144
145enum
146{
147   DISK_NONE = 0,
148   DISK_TIFDC,
149   DISK_BWG,   
150   DISK_HFDC,
151   DISK_CC
152};
153
154enum
155{
156   HD_NONE = 0,
157   HD_IDE,
158   HD_WHTECH,
159   HD_USB = 4
160};
161
162enum
163{
164   SERIAL_NONE = 0,
165   SERIAL_TI
166};
167
168enum
169{
170   EXT_NONE = 0,
171   EXT_HSGPL,
172   EXT_PCODE
173};
174
175enum
176{
177   HCI_NONE = 0,
178   HCI_MECMOUSE = 1,
179   HCI_IR = 4
180};
181
182enum
183{
184   CART_AUTO = 0,
185   CART_1,
186   CART_2,
187   CART_3,
188   CART_4,
189   CART_GK
190};
191
192
193/* Cartridge types */
194enum
195{
158196   STANDARD,
159197   EXBAS,
160198   MINIMEM,
src/mess/formats/ti99_dsk.c
r8042r8043
6666 * TODO: Test with diverse disks, inserted at the start and in the meantime
6767 *       Check delay
6868 *
69 *
70 * FIXME: If image is broken with good first track and defect higher tracks,
71 *        tdf_guess_geometry fails to define a geometry. The guessing should
72 *        always be done.
6973 ********************************************************************/
7074
7175#include <string.h>
r8042r8043
7680#include "formats/ti99_dsk.h"
7781#include "utils.h"
7882
83#define SECTOR_SIZE 256
84#define TI99_IDAM_LENGTH 7
85
7986/*
80   The flag for 80-track drives is set in the controller, so we need to
81   include it here.
87   Determines whether we are using 80 track drives. This variable is
88   necessary unless we get information about the dip
89   switch settings. It is set from 99_dsk.c, currenly the only client.
8290*/
83#include "machine/99_dsk.h"
91static int use_80_track_drives = FALSE;
8492
85#define SECTOR_SIZE 256
86#define TI99_IDAM_LENGTH 7
87
8893struct ti99dsk_geometry
8994{
9095   UINT8 sides;
r8042r8043
104109   int dam_offset;
105110};
106111
112/*
113   Parametrizes the format to use 80 track drives. For TI systems we
114   need to be able to emulate 40 track drives and 80 track drives.
115   This is set in the configuration, but the format has no direct access.
116   So as a preliminary solution we use this global function which sets the
117   flag. This function is called by the controllers defined in 99_dsk.
118*/
119void ti99_set_80_track_drives(int use80)
120{
121   use_80_track_drives = use80;
122}
123
107124#define TI99_DSK_TAG   "ti99dsktag"
108125
109126#if 0
r8042r8043
170187
171188   /* This may fail on startup; therefore we use a special function in
172189       99_dsk to explicitly set the geometry. */
173   if (ti99_image_in_80_track_drive())
190   if (use_80_track_drives)
174191   {
175192      drivetracks = 83;
176193   }
r8042r8043
493510
494511   /* Do we have a 40 track disk in an 80 track drive? In that case we
495512       double the "width" of the tracks. */
496   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
513   if (use_80_track_drives && tag->tracks<=40)
497514   {
498515      imgtrack = track / 2;
499516   }
r8042r8043
623640   int current_pos = 0;
624641   UINT8 *track_image;
625642   int leadin, gap1, gap2;
626   int is_fm;
643   int is_fm, found;
627644   struct ti99dsk_tag *tag = (ti99dsk_tag*)floppy_tag(floppy);
628645   int imgtrack = track;
629646
630647   /* Find out if we are going to write an FM or MFM track. Caution: The
631       original TI controller is known to have a bug in the formatting
632       routine (using a MOVB instead of a MOV instruction when setting the
633       pointer to the track data), outputting false bytes at the
634       beginning of the track. So we don't rely on absolute positions
635       (neither does the controller).
636    */
648   original TI controller is known to have a bug in the formatting
649   routine (using a MOVB instead of a MOV instruction when setting the
650   pointer to the track data), outputting false bytes at the
651   beginning of the track. So we don't rely on absolute positions
652   (neither does the controller).
653   */
637654   track_image = (UINT8*)buffer;
638655
639   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
656   if (use_80_track_drives && tag->tracks<=40)
640657   {
641658      imgtrack = track / 2;
642659   }
r8042r8043
646663   gap1 = 10;
647664   gap2 = 12;
648665   is_fm = FALSE;
649
666   
650667   current_pos = find_block(track_image, 0, 100, 0x4e, leadin);
651
668   
652669   /* In case of defect formats, we continue as far as possible. This
653       may lead to sectors not being written. */
670   may lead to sectors not being written. */
654671   if (current_pos==TI99DSK_BLOCKNOTFOUND)
655672   {
656673      /* Not MFM, possibly FM image */
r8042r8043
668685      is_fm = TRUE;
669686   }
670687
688   found = FALSE;
671689   /* Get behind lead-in */
672690   current_pos += leadin;
673691   while (current_pos < buflen)
r8042r8043
677695      if (new_pos==TI99DSK_BLOCKNOTFOUND)
678696      {
679697         /* Forget about the rest. */
680         logerror("Cannot find any address block for track %d, head %d.\n", track, head);
698         if (found) break;  /* we were already successful, so all ok */
699         logerror("Cannot find gap1 for track %d, head %d.\n", track, head);
681700         return FLOPPY_ERROR_INVALIDIMAGE;
682701      }
702      found = TRUE;
703
683704      if (!is_fm)
684705         new_pos += 3; /* skip sync bytes in MFM */
685706
686707      if (track_image[new_pos + gap1]==0xfe)
687708      {
688         current_pos = new_pos + gap2  + 1;
709         current_pos = new_pos + gap1  + 1;
689710         /* IDAM found. */
690711         int wtrack = track_image[current_pos];
691712         int whead = track_image[current_pos+1];
r8042r8043
712733                  current_pos += SECTOR_SIZE;
713734               }
714735               else
715                  logerror("DAM not found. Don't write sector %d\n", sector);
736                  logerror("DAM not found. Not writing write sector %d\n", sector);
716737               /* else not found, ignore this sector. */
717738            }
718739         }
719         /* else the sector head data do not match the
720                current track and head. Ignore the sector. */
740         else
741         {
742            /* else the sector head data do not match the
743            current track and head. Ignore the sector. */
744            logerror("Wrong track: wtrack=%d, imgtrack=%d, whead=%d, imghead=%d\n",wtrack,imgtrack, whead,head);
745         }
721746      }
722747      else
723748      {
r8042r8043
816841   int imgtrack = track;
817842   struct ti99dsk_tag *tag = (ti99dsk_tag*)floppy_tag(floppy);
818843
819   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
844   if (use_80_track_drives && tag->tracks<=40)
820845   {
821846      imgtrack = track / 2;
822847   }
r8042r8043
852877
853878   struct ti99dsk_tag *tag = (ti99dsk_tag*)floppy_tag(floppy);
854879
855   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
880   if (use_80_track_drives && tag->tracks<=40)
856881   {
857882      imgtrack = track / 2;
858883   }
r8042r8043
882907{
883908   struct ti99dsk_tag *tag = (ti99dsk_tag*)floppy_tag(floppy);
884909
885   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
910   if (use_80_track_drives && tag->tracks<=40)
886911   {
887912      track = track / 2;
888913   }
r8042r8043
10201045 *       Head:             hh       |
10211046 *     Sector:             ss       |
10221047 *       Size:             01       |
1023 *        CRC:         2*  f7       +--- repeat 9 times (8 rarely)
1048 *        CRC:         2*  f7       +--- repeat 9 times (8 in rare cases)
10241049 *       Gap2:        11*  ff       |
10251050 *                     6*  00       |
10261051 *        DAM:             fb       |
r8042r8043
10411066 *       Head:             hh       |
10421067 *     Sector:             ss       |
10431068 *       Size:             01       |
1044 *        CRC:         2*  f7       +--- repeat 18 times (16 rarely)
1069 *        CRC:         2*  f7       +--- repeat 18 times (16 in rare cases)
10451070 *       Gap2:        22*  4e       |
10461071 *                    12*  00       |
10471072 *       Sync:         3*  a1       |
r8042r8043
12481273   floppy_image_read(floppy, buffer, track_offset, buflen);
12491274
12501275   /* Rebuild the CRCs. PC99 did not store the CRC but put
1251       F7F7 in its place.
1252       The first CRC is at position IDAM + 5
1253       The second CRC is at position IDAM + 0x119 (FM) or +0x12d (MFM)
1254       All this is repeated for each sector in the track
1255    */
1276   F7F7 in its place.
1277   The first CRC is at position IDAM + 5
1278   The second CRC is at position IDAM + 0x119 (FM) or +0x12d (MFM)
1279   All this is repeated for each sector in the track
1280   */
12561281   if (determine_offset(tag->format, track_data, &first_idam)==FLOPPY_ERROR_SEEKERROR)
12571282      return FLOPPY_ERROR_SEEKERROR;
12581283
r8042r8043
12631288      if (byte == TI99_IDAM)
12641289      {
12651290         /* Do we have a valid CRCs already? Then this image
1266               already contains proper CRCs handling. Do not
1267               recreate them. */
1291         already contains proper CRCs handling. Do not
1292         recreate them. */
12681293         if (track_data[i+5] != 0xf7 || track_data[i+6] != 0xf7)
12691294            return FLOPPY_ERROR_SUCCESS;
12701295
r8042r8043
12961321   int imgtrack = track;
12971322
12981323   struct ti99dsk_tag *tag = (ti99dsk_tag*)floppy_tag(floppy);
1299   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
1324   if (use_80_track_drives && tag->tracks<=40)
13001325   {
13011326      imgtrack = track / 2;
13021327   }
r8042r8043
13131338   int imgtrack = track;
13141339
13151340   struct ti99dsk_tag *tag = (ti99dsk_tag*)floppy_tag(floppy);
1316   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
1341   if (use_80_track_drives && tag->tracks<=40)
13171342   {
13181343      imgtrack = track / 2;
13191344   }
r8042r8043
13231348      return err;
13241349
13251350   /* According to the TDF format, we don't need the CRC but replace it
1326       with F7F7. For now we keep it and see whether PC99 can cope with
1327       that. (Otherwise we would have to copy the const buffer). */
1351   with F7F7. For now we keep it and see whether PC99 can cope with
1352   that. (Otherwise we would have to copy the const buffer). */
13281353   floppy_image_write(floppy, buffer, offset + track_offset, buflen);
13291354   return FLOPPY_ERROR_SUCCESS;
13301355}
r8042r8043
13451370*/
13461371
13471372/*
1348    Get a sector from a track. This function takes a complete track,
1349    searches for the sector, and passes a pointer to the sector contents
1350    back.
1351    As the original TI controller creates bad bytes at the start of a track
1352    we do *not* assume a simple layout. The strategy is to search the
1353    lead-in of the track, and from this offset, step through the track
1354    in search for the sector. Since we do not have index marks (we cannot
1355    distinguish them from ordinary data, as we do not store the clock), we
1356    do not attempt to detect IDAM or DAM.
1373   Get a sector from a track. This function takes a complete track,
1374   searches for the sector, and passes a pointer to the sector contents
1375   back.
1376   As the original TI controller creates bad bytes at the start of a track
1377   we do *not* assume a simple layout. The strategy is to search the
1378   lead-in of the track, and from this offset, step through the track
1379   in search for the sector. Since we do not have index marks (we cannot
1380   distinguish them from ordinary data, as we do not store the clock), we
1381   do not attempt to detect IDAM or DAM.
13571382*/
13581383static floperr_t ti99_tdf_seek_sector_in_track(floppy_image *floppy, int head, int track, int sector, UINT8 *track_data, UINT8 **sector_data)
13591384{
r8042r8043
14121437
14131438   track_data = (UINT8*)malloc(tag->track_size);
14141439
1415   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
1440   if (use_80_track_drives && tag->tracks<=40)
14161441   {
14171442      imgtrack = track / 2;
14181443   }
r8042r8043
14321457}
14331458
14341459/*
1435    Writes a sector into the track. Note that the indexed_write method
1436    may be used instead of this method, according to the implementation
1437    of flopimg/flopdrv.
1460   Writes a sector into the track. Note that the indexed_write method
1461   may be used instead of this method, according to the implementation
1462   of flopimg/flopdrv.
14381463*/
14391464static floperr_t ti99_tdf_write_sector(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam)
14401465{
r8042r8043
14501475   struct ti99dsk_tag *tag = (ti99dsk_tag*)floppy_tag(floppy);
14511476
14521477   track_data = (UINT8*)malloc(tag->track_size);
1453   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
1478   if (use_80_track_drives && tag->tracks<=40)
14541479   {
14551480      imgtrack = track / 2;
14561481   }
r8042r8043
14981523
14991524   track_data = (UINT8*)malloc(tag->track_size);
15001525
1501   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
1526   if (use_80_track_drives && tag->tracks<=40)
15021527   {
15031528      imgtrack = track / 2;
15041529   }
r8042r8043
15951620   floperr_t retval;
15961621   track_data = (UINT8*)malloc(tag->track_size);
15971622
1598   if (ti99_image_in_80_track_drive() && tag->tracks<=40)
1623   if (use_80_track_drives && tag->tracks<=40)
15991624   {
16001625      imgtrack = track / 2;
16011626   }
r8042r8043
16841709}
16851710
16861711/*
1687    Required for ReadAddress command. This function gets the 1st, 2nd, 3rd,
1688    sector (and so on) from the track, not sector 1, 2, 3. That is, the
1689    returned sector info depends on the interleave and the start sector.
1712   Required for ReadAddress command. This function gets the 1st, 2nd, 3rd,
1713   sector (and so on) from the track, not sector 1, 2, 3. That is, the
1714   returned sector info depends on the interleave and the start sector.
16901715*/
16911716static floperr_t ti99_tdf_get_indexed_sector_info(floppy_image *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags)
16921717{
src/mess/formats/ti99_dsk.h
r8042r8043
1414
1515FLOPPY_OPTIONS_EXTERN(ti99);
1616
17void ti99_set_80_track_drives(int use80);
18
1719#endif /* TI99_DSK_H */
src/mess/mess.mak
r8042r8043
429429   $(MESS_DEVICES)/multcart.o   \
430430   $(MESS_DEVICES)/printer.o   \
431431   $(MESS_DEVICES)/snapquik.o   \
432   $(MESS_DEVICES)/ti99_hd.o    \
432433   $(MESS_DEVICES)/z80bin.o   \
433434   $(MESS_FORMATS)/basicdsk.o   \
434435   $(MESS_FORMATS)/cassimg.o   \
src/mess/drivers/ti99_8.c
r8042r8043
217217
218218/* ti99/8 : 54-key keyboard */
219219static INPUT_PORTS_START(ti99_8)
220   PORT_START( "SPEECH" )
221   PORT_CONFNAME( 0x01, 0x00, "Speech synthesizer" )
222      PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
223      PORT_CONFSETTING( 0x01, DEF_STR( On ) )
220224
221   /* 1 port for config */
222   PORT_START("CFG")   /* config */
223   PORT_DIPNAME( config_fdc_mask << config_fdc_bit, /*fdc_kind_hfdc << config_fdc_bit*/0, "Floppy disk controller")
224   PORT_DIPSETTING( fdc_kind_none << config_fdc_bit, DEF_STR( None ) )
225   PORT_DIPSETTING( fdc_kind_TI << config_fdc_bit, "Texas Instruments SD" )
226#if HAS_99CCFDC
227   PORT_DIPSETTING( fdc_kind_CC << config_fdc_bit, "CorComp" )
228#endif
229   PORT_DIPSETTING( fdc_kind_BwG << config_fdc_bit, "SNUG's BwG" )
230   PORT_DIPSETTING( fdc_kind_hfdc << config_fdc_bit, "Myarc's HFDC" )
231   PORT_DIPNAME( config_ide_mask << config_ide_bit, /*1 << config_ide_bit*/0, "Nouspickel's IDE card")
232   PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
233   PORT_DIPSETTING( 1 << config_ide_bit, DEF_STR( On ) )
234   PORT_DIPNAME( config_rs232_mask << config_rs232_bit, /*1 << config_rs232_bit*/0, "TI RS232 card")
235   PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
236   PORT_DIPSETTING( 1 << config_rs232_bit, DEF_STR( On ) )
237   PORT_DIPNAME( config_hsgpl_mask << config_hsgpl_bit, 0/*1 << config_hsgpl_bit*/, "SNUG HSGPL card")
238   PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
239   PORT_DIPSETTING( 1 << config_hsgpl_bit, DEF_STR( On ) )
240   PORT_DIPNAME( config_mecmouse_mask << config_mecmouse_bit, 0, "Mechatronics Mouse")
241   PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
242   PORT_DIPSETTING( 1 << config_mecmouse_bit, DEF_STR( On ) )
243   PORT_DIPNAME( config_usbsm_mask << config_usbsm_bit, 1 << config_usbsm_bit, "Nouspickel's USB-SM card")
244   PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
245   PORT_DIPSETTING( 1 << config_usbsm_bit, DEF_STR( On ) )
225   PORT_START( "DISKCTRL" )
226   PORT_CONFNAME( 0x07, 0x00, "Disk controller" )
227      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
228      PORT_CONFSETTING(    0x01, "TI SD Floppy Controller" )
229      PORT_CONFSETTING(    0x02, "SNUG BwG Controller" )
230      PORT_CONFSETTING(    0x03, "Myarc HFDC" )
231//      PORT_CONFSETTING(    0x04, "Corcomp" )
246232
247   PORT_DIPNAME( config_cartslot_mask << config_cartslot_bit, 0, "Active cartridge slot")
248      PORT_DIPSETTING( 0, "auto" )
249      PORT_DIPSETTING( 1 << config_cartslot_bit, "Slot 1" )
250      PORT_DIPSETTING( 2 << config_cartslot_bit, "Slot 2" )
251      PORT_DIPSETTING( 3 << config_cartslot_bit, "Slot 3" )
252      PORT_DIPSETTING( 4 << config_cartslot_bit, "Slot 4" )
233   PORT_START( "HDCTRL" )
234   PORT_CONFNAME( 0x03, 0x00, "HD controller" )
235      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
236      PORT_CONFSETTING(    0x01, "Nouspikel IDE Controller" )
237//      PORT_CONFSETTING(    0x02, "WHTech SCSI Controller" )
238   PORT_CONFNAME( 0x08, 0x00, "USB-SM card" )
239      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
240      PORT_CONFSETTING(    0x08, DEF_STR( On ) )
253241
242   PORT_START( "SERIAL" )
243   PORT_CONFNAME( 0x03, 0x00, "Serial/Parallel interface" )
244      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
245      PORT_CONFSETTING(    0x01, "TI RS-232 card" )
246   
247   PORT_START( "EXTCARD" )
248   PORT_CONFNAME( 0x01, 0x00, "HSGPL extension" )
249      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
250      PORT_CONFSETTING(    0x01, DEF_STR( On ) )
251   PORT_CONFNAME( 0x02, 0x00, "P-Code card" )
252      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
253      PORT_CONFSETTING(    0x02, DEF_STR( On ) )
254
255   PORT_START( "HCI" )
256   PORT_CONFNAME( 0x01, 0x00, "Mouse support" )
257      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
258      PORT_CONFSETTING(    0x01, "Mechatronics Mouse" )
259     
260   PORT_START( "CARTSLOT" )
261   PORT_CONFNAME( 0x07, 0x00, "Cartridge slot" )
262      PORT_CONFSETTING(    0x00, "Auto" )
263      PORT_CONFSETTING(    0x01, "Slot 1" )
264      PORT_CONFSETTING(    0x02, "Slot 2" )
265      PORT_CONFSETTING(    0x03, "Slot 3" )
266      PORT_CONFSETTING(    0x04, "Slot 4" )
267//      PORT_CONFSETTING(    0x05, "GRAM Kracker" )
268
269   PORT_START( "HFDCDIP" )
270   PORT_DIPNAME( 0x03, 0x02, "HFDC drive config" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
271      PORT_DIPSETTING( 0x00, "40 track, 16 ms")
272      PORT_DIPSETTING( 0x01, "40 track, 8 ms")
273      PORT_DIPSETTING( 0x02, "80 track, 2 ms")
274      PORT_DIPSETTING( 0x03, "80 track HD, 2 ms")     
275
276   PORT_START( "DRVSPD" )
277   PORT_DIPNAME( 0x01, 0x01, "Floppy and HD speed" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
278      PORT_DIPSETTING( 0x00, "No delay")
279      PORT_DIPSETTING( 0x01, "Realistic")
280
254281   /* 3 ports for mouse */
255282   PORT_START("MOUSEX") /* Mouse - X AXIS */
256283   PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1)
r8042r8043
535562   /* devices */
536563   MDRV_IDE_CONTROLLER_ADD( "ide", ti99_ide_interrupt )
537564
538   MDRV_IMPORT_FROM( smc92x4_hd )
565//   MDRV_IMPORT_FROM( smc92x4_hd )
539566
540567   MDRV_IDE_HARDDISK_ADD( "ide_harddisk" )
541568   MDRV_RTC65271_ADD("ide_rtc", ti99_clk_interrupt_callback)
r8042r8043
590617   /* devices */
591618   MDRV_IDE_CONTROLLER_ADD( "ide", ti99_ide_interrupt )   /* FIXME */
592619
593   MDRV_IMPORT_FROM( smc92x4_hd )
620//   MDRV_IMPORT_FROM( smc92x4_hd )
594621
595622   MDRV_IDE_HARDDISK_ADD( "ide_harddisk" )
596623   MDRV_RTC65271_ADD("ide_rtc", ti99_clk_interrupt_callback)
src/mess/drivers/geneve.c
r8042r8043
220220#include "machine/mm58274c.h"
221221#include "machine/rtc65271.h"
222222#include "formats/ti99_dsk.h"
223#include "devices/ti99_hd.h"
223224
224225/*
225226    memory map
r8042r8043
249250
250251/* 101-key PC XT keyboard + TI joysticks */
251252static INPUT_PORTS_START(geneve)
253   PORT_START( "BOOTROM" )   /* config */
254   PORT_CONFNAME( 0x01, 0x00, "Boot ROM" )
255      PORT_CONFSETTING(    0x00, "Version 0.9" )
256      PORT_CONFSETTING(    0x01, "Version 1.0" )
252257
253   PORT_START("CFG")   /* config */
254      PORT_DIPNAME( config_boot_mask << config_boot_bit, 0x0000, "Boot ROM")
255         PORT_DIPSETTING( 0x0000, "1.0" )
256         PORT_DIPSETTING( 1 << config_boot_bit, "0.9" )
257      PORT_DIPNAME( config_speech_mask << config_speech_bit, 1 << config_speech_bit, "Speech synthesis")
258         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
259         PORT_DIPSETTING( 1 << config_speech_bit, DEF_STR( On ) )
260      PORT_DIPNAME( config_fdc_mask << config_fdc_bit, fdc_kind_hfdc << config_fdc_bit, "Floppy disk controller")
261         PORT_DIPSETTING( fdc_kind_none << config_fdc_bit, DEF_STR( None ) )
262         PORT_DIPSETTING( fdc_kind_TI << config_fdc_bit, "Texas Instruments SD" )
263#if HAS_99CCFDC
264         PORT_DIPSETTING( fdc_kind_CC << config_fdc_bit, "CorComp" )
265#endif
266         PORT_DIPSETTING( fdc_kind_BwG << config_fdc_bit, "SNUG's BwG" )
267         PORT_DIPSETTING( fdc_kind_hfdc << config_fdc_bit, "Myarc's HFDC" )
268      PORT_DIPNAME( config_ide_mask << config_ide_bit, /*1 << config_ide_bit*/0, "Nouspickel's IDE card")
269         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
270         PORT_DIPSETTING( 1 << config_ide_bit, DEF_STR( On ) )
271      PORT_DIPNAME( config_rs232_mask << config_rs232_bit, 1 << config_rs232_bit, "TI RS232 card")
272         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
273         PORT_DIPSETTING( 1 << config_rs232_bit, DEF_STR( On ) )
274      PORT_DIPNAME( config_usbsm_mask << config_usbsm_bit, 1 << config_usbsm_bit, "Nouspickel's USB-SM card")
275         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
276         PORT_DIPSETTING( 1 << config_usbsm_bit, DEF_STR( On ) )
258   PORT_START( "SPEECH" )
259   PORT_CONFNAME( 0x01, 0x00, "Speech synthesizer" )
260      PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
261      PORT_CONFSETTING( 0x01, DEF_STR( On ) )
277262
263   PORT_START( "DISKCTRL" )
264   PORT_CONFNAME( 0x07, 0x00, "Disk controller" )
265      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
266      PORT_CONFSETTING(    0x01, "TI SD Floppy Controller" )
267      PORT_CONFSETTING(    0x02, "SNUG BwG Controller" )
268      PORT_CONFSETTING(    0x03, "Myarc HFDC" )
269//      PORT_CONFSETTING(    0x04, "Corcomp" )
270
271   PORT_START( "HDCTRL" )
272   PORT_CONFNAME( 0x03, 0x00, "HD controller" )
273      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
274      PORT_CONFSETTING(    0x01, "Nouspikel IDE Controller" )
275//      PORT_CONFSETTING(    0x02, "WHTech SCSI Controller" )
276   PORT_CONFNAME( 0x08, 0x00, "USB-SM card" )
277      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
278      PORT_CONFSETTING(    0x08, DEF_STR( On ) )
279
280   PORT_START( "SERIAL" )
281   PORT_CONFNAME( 0x03, 0x00, "Serial/Parallel interface" )
282      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
283      PORT_CONFSETTING(    0x01, "TI RS-232 card" )
284
285   PORT_START( "HFDCDIP" )
286   PORT_DIPNAME( 0xff, 0x55, "HFDC drive config" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
287      PORT_DIPSETTING( 0x00, "40 track, 16 ms")
288      PORT_DIPSETTING( 0xaa, "40 track, 8 ms")
289      PORT_DIPSETTING( 0x55, "80 track, 2 ms")
290      PORT_DIPSETTING( 0xff, "80 track HD, 2 ms")
291     
292   PORT_START( "DRVSPD" )
293   PORT_DIPNAME( 0x01, 0x01, "Floppy and HD speed" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
294      PORT_DIPSETTING( 0x00, "No delay")
295      PORT_DIPSETTING( 0x01, "Realistic")
296         
278297   PORT_START("JOY")   /* col 1: "wired handset 1" (= joystick 1) */
279298      PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_UP/*, "(1UP)", CODE_NONE, OSD_JOY_UP*/) PORT_PLAYER(1)
280299      PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN/*, "(1DOWN)", CODE_NONE, OSD_JOY_DOWN, 0*/) PORT_PLAYER(1)
r8042r8043
508527   /* devices */
509528   MDRV_IDE_CONTROLLER_ADD( "ide", ti99_ide_interrupt )   /* FIXME */
510529
511   MDRV_IMPORT_FROM( smc92x4_hd )
512
513   MDRV_IDE_HARDDISK_ADD( "ide_harddisk" )
514530   MDRV_RTC65271_ADD("ide_rtc", ti99_clk_interrupt_callback)
515531
516532   /* rtc */
r8042r8043
521537   MDRV_TMS9901_ADD("tms9901", tms9901reset_param_ti99)
522538
523539   MDRV_WD179X_ADD("wd179x", ti99_wd17xx_interface )
540   MDRV_SMC92X4_ADD("smc92x4", ti99_smc92x4_interface )
524541
525542   MDRV_FLOPPY_4_DRIVES_ADD(geneve_floppy_config)
543   MDRV_MFMHD_3_DRIVES_ADD()
526544
527545   MDRV_SMARTMEDIA_ADD("smartmedia")
528546
src/mess/drivers/ti99_4p.c
r8042r8043
5656#include "devices/cassette.h"
5757#include "machine/smartmed.h"
5858#include "devices/harddriv.h"
59#include "devices/ti99_hd.h"
5960#include "machine/idectrl.h"
6061#include "machine/smc92x4.h"
6162#include "machine/rtc65271.h"
6263#include "formats/ti99_dsk.h"
6364
65
6466static ADDRESS_MAP_START(memmap, ADDRESS_SPACE_PROGRAM, 16)
6567   AM_RANGE(0x0000, 0x1fff) AM_ROMBANK("bank1")                        /*system ROM*/
6668   AM_RANGE(0x2000, 0x2fff) AM_RAMBANK("bank3")                        /*lower 8kb of RAM extension: AMS bank 2*/
r8042r8043
102104
103105static INPUT_PORTS_START(ti99_4p)
104106
105   /* 1 port for config */
106   PORT_START("CFG")   /* config */
107      PORT_DIPNAME( config_speech_mask << config_speech_bit, 1 << config_speech_bit, "Speech synthesis")
108         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
109         PORT_DIPSETTING( 1 << config_speech_bit, DEF_STR( On ) )
110      PORT_DIPNAME( config_fdc_mask << config_fdc_bit, fdc_kind_hfdc << config_fdc_bit, "Floppy disk controller")
111         PORT_DIPSETTING( fdc_kind_none << config_fdc_bit, DEF_STR( None ) )
112         PORT_DIPSETTING( fdc_kind_TI << config_fdc_bit, "Texas Instruments SD" )
113#if HAS_99CCFDC
114         PORT_DIPSETTING( fdc_kind_CC << config_fdc_bit, "CorComp" )
115#endif
116         PORT_DIPSETTING( fdc_kind_BwG << config_fdc_bit, "SNUG's BwG" )
117         PORT_DIPSETTING( fdc_kind_hfdc << config_fdc_bit, "Myarc's HFDC" )
118      /*PORT_DIPNAME( config_ide_mask << config_ide_bit, 1 << config_ide_bit, IPT_DIPSWITCH_NAME) PORT_NAME("Nouspickel's IDE card")
119            PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
120            PORT_DIPSETTING( 1 << config_ide_bit, DEF_STR( On ) )*/
121      PORT_DIPNAME( config_rs232_mask << config_rs232_bit, /*1 << config_rs232_bit*/0, "TI RS232 card")
122         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
123         PORT_DIPSETTING( 1 << config_rs232_bit, DEF_STR( On ) )
124      PORT_DIPNAME( config_mecmouse_mask << config_mecmouse_bit, 0, "Mechatronics Mouse")
125         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
126         PORT_DIPSETTING( 1 << config_mecmouse_bit, DEF_STR( On ) )
127      PORT_DIPNAME( config_usbsm_mask << config_usbsm_bit, 1 << config_usbsm_bit, "Nouspickel's USB-SM card")
128         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
129         PORT_DIPSETTING( 1 << config_usbsm_bit, DEF_STR( On ) )
107   PORT_START( "SPEECH" )
108   PORT_CONFNAME( 0x01, 0x00, "Speech synthesizer" )
109      PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
110      PORT_CONFSETTING( 0x01, DEF_STR( On ) )
130111
112   PORT_START( "DISKCTRL" )
113   PORT_CONFNAME( 0x07, 0x00, "Disk controller" )
114      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
115      PORT_CONFSETTING(    0x01, "TI SD Floppy Controller" )
116      PORT_CONFSETTING(    0x02, "SNUG BwG Controller" )
117      PORT_CONFSETTING(    0x03, "Myarc HFDC" )
118//      PORT_CONFSETTING(    0x04, "Corcomp" )
131119
120   PORT_START( "HDCTRL" )
121   PORT_CONFNAME( 0x03, 0x00, "HD controller" )
122      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
123      PORT_CONFSETTING(    0x01, "Nouspikel IDE Controller" )
124//      PORT_CONFSETTING(    0x02, "WHTech SCSI Controller" )
125   PORT_CONFNAME( 0x08, 0x00, "USB-SM card" )
126      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
127      PORT_CONFSETTING(    0x08, DEF_STR( On ) )
128
129   PORT_START( "SERIAL" )
130   PORT_CONFNAME( 0x03, 0x00, "Serial/Parallel interface" )
131      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
132      PORT_CONFSETTING(    0x01, "TI RS-232 card" )
133   
134   PORT_START( "EXTCARD" )
135   PORT_CONFNAME( 0x02, 0x00, "P-Code card" )
136      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
137      PORT_CONFSETTING(    0x02, DEF_STR( On ) )
138
139   PORT_START( "HCI" )
140   PORT_CONFNAME( 0x01, 0x00, "Mouse support" )
141      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
142      PORT_CONFSETTING(    0x01, "Mechatronics Mouse" )
143
144   PORT_START( "HFDCDIP" )
145   PORT_DIPNAME( 0xff, 0x55, "HFDC drive config" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
146      PORT_DIPSETTING( 0x00, "40 track, 16 ms")
147      PORT_DIPSETTING( 0xaa, "40 track, 8 ms")
148      PORT_DIPSETTING( 0x55, "80 track, 2 ms")
149      PORT_DIPSETTING( 0xff, "80 track HD, 2 ms")     
150
151   PORT_START( "DRVSPD" )
152   PORT_DIPNAME( 0x01, 0x01, "Floppy and HD speed" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
153      PORT_DIPSETTING( 0x00, "No delay")
154      PORT_DIPSETTING( 0x01, "Realistic")
155
132156   /* 3 ports for mouse */
133157   PORT_START("MOUSEX") /* Mouse - X AXIS */
134158      PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1)
r8042r8043
296320   /* devices */
297321   MDRV_IDE_CONTROLLER_ADD( "ide", ti99_ide_interrupt )   /* FIXME */
298322
299   MDRV_IMPORT_FROM( smc92x4_hd )
300
301   MDRV_IDE_HARDDISK_ADD( "ide_harddisk" )
302323   MDRV_RTC65271_ADD("ide_rtc", ti99_clk_interrupt_callback)
303324
304325   /* MDRV_CASSETTE_ADD( "cassette", default_cassette_config ) */
r8042r8043
306327   /* tms9901 */
307328   MDRV_TMS9901_ADD("tms9901", tms9901reset_param_ti99_4x)
308329
330   MDRV_WD179X_ADD("wd179x", ti99_wd17xx_interface )
331   MDRV_SMC92X4_ADD("smc92x4", ti99_smc92x4_interface )
332
309333   MDRV_FLOPPY_4_DRIVES_ADD(ti99_4p_floppy_config)
334   MDRV_MFMHD_3_DRIVES_ADD()
310335
311336   MDRV_SMARTMEDIA_ADD("smartmedia")
312337
src/mess/drivers/ti99_4x.c
r8042r8043
4444#include "machine/rtc65271.h"
4545#include "devices/ti99cart.h"
4646#include "formats/ti99_dsk.h"
47#include "devices/ti99_hd.h"
4748
4849/*
4950    memory map
r8042r8043
105106/* TI99/4a: 48-key keyboard, plus two optional joysticks (2 shift keys) */
106107static INPUT_PORTS_START(ti99_4a)
107108
108   /* 1 port for config */
109   PORT_START("CFG")   /* config */
110      PORT_DIPNAME( config_xRAM_mask << config_xRAM_bit, xRAM_kind_TI << config_xRAM_bit, "RAM extension")
111         PORT_DIPSETTING( xRAM_kind_none << config_xRAM_bit,            DEF_STR( None ) )
112         PORT_DIPSETTING( xRAM_kind_TI << config_xRAM_bit,            "Texas Instruments 32kb")
113         PORT_DIPSETTING( xRAM_kind_super_AMS << config_xRAM_bit,      "Super AMS 1Mb")
114         PORT_DIPSETTING( xRAM_kind_foundation_128k << config_xRAM_bit,   "Foundation 128kb")
115         PORT_DIPSETTING( xRAM_kind_foundation_512k << config_xRAM_bit,   "Foundation 512kb")
116         PORT_DIPSETTING( xRAM_kind_myarc_128k << config_xRAM_bit,      "Myarc look-alike 128kb")
117         PORT_DIPSETTING( xRAM_kind_myarc_512k << config_xRAM_bit,      "Myarc look-alike 512kb")
118      PORT_DIPNAME( config_speech_mask << config_speech_bit, 1 << config_speech_bit, "Speech synthesis")
119         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
120         PORT_DIPSETTING( 1 << config_speech_bit, DEF_STR( On ) )
121      PORT_DIPNAME( config_fdc_mask << config_fdc_bit, fdc_kind_hfdc << config_fdc_bit, "Floppy disk controller")
122         PORT_DIPSETTING( fdc_kind_none << config_fdc_bit, DEF_STR( None ) )
123         PORT_DIPSETTING( fdc_kind_TI << config_fdc_bit, "Texas Instruments SD" )
124#if HAS_99CCFDC
125         PORT_DIPSETTING( fdc_kind_CC << config_fdc_bit, "CorComp" )
126#endif
127         PORT_DIPSETTING( fdc_kind_BwG << config_fdc_bit, "SNUG's BwG" )
128         PORT_DIPSETTING( fdc_kind_hfdc << config_fdc_bit, "Myarc's HFDC" )
129      PORT_DIPNAME( config_ide_mask << config_ide_bit, 1 << config_ide_bit, "Nouspickel's IDE card")
130         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
131         PORT_DIPSETTING( 1 << config_ide_bit, DEF_STR( On ) )
132      PORT_DIPNAME( config_rs232_mask << config_rs232_bit, 1 << config_rs232_bit, "TI RS232 card")
133         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
134         PORT_DIPSETTING( 1 << config_rs232_bit, DEF_STR( On ) )
135      PORT_DIPNAME( config_hsgpl_mask << config_hsgpl_bit, 0/*1 << config_hsgpl_bit*/, "SNUG HSGPL card")
136         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
137         PORT_DIPSETTING( 1 << config_hsgpl_bit, DEF_STR( On ) )
138      PORT_DIPNAME( config_mecmouse_mask << config_mecmouse_bit, 0, "Mechatronics Mouse")
139         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
140         PORT_DIPSETTING( 1 << config_mecmouse_bit, DEF_STR( On ) )
141      PORT_DIPNAME( config_usbsm_mask << config_usbsm_bit, 1 << config_usbsm_bit, "Nouspickel's USB-SM card")
142         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
143         PORT_DIPSETTING( 1 << config_usbsm_bit, DEF_STR( On ) )
144      PORT_DIPNAME( config_pcode_mask << config_pcode_bit, 0, "P-Code card")
145         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
146         PORT_DIPSETTING( 1 << config_pcode_bit, DEF_STR( On ) )
109   PORT_START( "RAM" )   /* config */
110   PORT_CONFNAME( 0x07, 0x00, "RAM extension" )
111      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
112      PORT_CONFSETTING(    0x01, "Texas Instruments 32 KiB" )
113      PORT_CONFSETTING(    0x02, "Super AMS 1MiB" )
114      PORT_CONFSETTING(    0x03, "Foundation 128 KiB" )
115      PORT_CONFSETTING(    0x04, "Foundation 512 KiB" )
116      PORT_CONFSETTING(    0x05, "Myarc 128 KiB" )
117      PORT_CONFSETTING(    0x06, "Myarc 512 KiB" )
147118
148      PORT_DIPNAME( config_cartslot_mask << config_cartslot_bit, 0, "Active cartridge slot")
149         PORT_DIPSETTING( 0, "auto" )
150         PORT_DIPSETTING( 1 << config_cartslot_bit, "Slot 1" )
151         PORT_DIPSETTING( 2 << config_cartslot_bit, "Slot 2" )
152         PORT_DIPSETTING( 3 << config_cartslot_bit, "Slot 3" )
153         PORT_DIPSETTING( 4 << config_cartslot_bit, "Slot 4" )
119   PORT_START( "SPEECH" )
120   PORT_CONFNAME( 0x01, 0x00, "Speech synthesizer" )
121      PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
122      PORT_CONFSETTING( 0x01, DEF_STR( On ) )
154123
124   PORT_START( "DISKCTRL" )
125   PORT_CONFNAME( 0x07, 0x00, "Disk controller" )
126      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
127      PORT_CONFSETTING(    0x01, "TI SD Floppy Controller" )
128      PORT_CONFSETTING(    0x02, "SNUG BwG Controller" )
129      PORT_CONFSETTING(    0x03, "Myarc HFDC" )
130//      PORT_CONFSETTING(    0x04, "Corcomp" )
131
132   PORT_START( "HDCTRL" )
133   PORT_CONFNAME( 0x03, 0x00, "HD controller" )
134      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
135      PORT_CONFSETTING(    0x01, "Nouspikel IDE Controller" )
136//      PORT_CONFSETTING(    0x02, "WHTech SCSI Controller" )
137   PORT_CONFNAME( 0x04, 0x00, "USB-SM card" )
138      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
139      PORT_CONFSETTING(    0x04, DEF_STR( On ) )
140
141   PORT_START( "SERIAL" )
142   PORT_CONFNAME( 0x03, 0x00, "Serial/Parallel interface" )
143      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
144      PORT_CONFSETTING(    0x01, "TI RS-232 card" )
145   
146   PORT_START( "EXTCARD" )
147   PORT_CONFNAME( 0x01, 0x00, "HSGPL extension" )
148      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
149      PORT_CONFSETTING(    0x01, DEF_STR( On ) )
150   PORT_CONFNAME( 0x02, 0x00, "P-Code card" )
151      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
152      PORT_CONFSETTING(    0x02, DEF_STR( On ) )
153
154   PORT_START( "HCI" )
155   PORT_CONFNAME( 0x01, 0x00, "Mouse support" )
156      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
157      PORT_CONFSETTING(    0x01, "Mechatronics Mouse" )
158     
159   PORT_START( "CARTSLOT" )
160   PORT_CONFNAME( 0x07, 0x00, "Cartridge slot" )
161      PORT_CONFSETTING(    0x00, "Auto" )
162      PORT_CONFSETTING(    0x01, "Slot 1" )
163      PORT_CONFSETTING(    0x02, "Slot 2" )
164      PORT_CONFSETTING(    0x03, "Slot 3" )
165      PORT_CONFSETTING(    0x04, "Slot 4" )
166//      PORT_CONFSETTING(    0x05, "GRAM Kracker" )
167
168   PORT_START( "HFDCDIP" )
169   PORT_DIPNAME( 0xff, 0x55, "HFDC drive config" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
170      PORT_DIPSETTING( 0x00, "40 track, 16 ms")
171      PORT_DIPSETTING( 0xaa, "40 track, 8 ms")
172      PORT_DIPSETTING( 0x55, "80 track, 2 ms")
173      PORT_DIPSETTING( 0xff, "80 track HD, 2 ms")     
174
175   PORT_START( "DRVSPD" )
176   PORT_DIPNAME( 0x01, 0x01, "Floppy and HD speed" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
177      PORT_DIPSETTING( 0x00, "No delay")
178      PORT_DIPSETTING( 0x01, "Realistic")
179
155180   /* 3 ports for mouse */
156181   PORT_START("MOUSEX") /* Mouse - X AXIS */
157182      PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1)
r8042r8043
254279/* TI99/4: 41-key keyboard, plus two optional joysticks  (2 space keys) */
255280static INPUT_PORTS_START(ti99_4)
256281
257   /* 1 port for config */
258   PORT_START("CFG")   /* config */
259      PORT_DIPNAME( config_xRAM_mask << config_xRAM_bit, xRAM_kind_TI << config_xRAM_bit, "RAM extension")
260         PORT_DIPSETTING( xRAM_kind_none << config_xRAM_bit,            DEF_STR( None ) )
261         PORT_DIPSETTING( xRAM_kind_TI << config_xRAM_bit,            "Texas Instruments 32kb")
262         PORT_DIPSETTING( xRAM_kind_super_AMS << config_xRAM_bit,      "Super AMS 1Mb")
263         PORT_DIPSETTING( xRAM_kind_foundation_128k << config_xRAM_bit,   "Foundation 128kb")
264         PORT_DIPSETTING( xRAM_kind_foundation_512k << config_xRAM_bit,   "Foundation 512kb")
265         PORT_DIPSETTING( xRAM_kind_myarc_128k << config_xRAM_bit,      "Myarc look-alike 128kb")
266         PORT_DIPSETTING( xRAM_kind_myarc_512k << config_xRAM_bit,      "Myarc look-alike 512kb")
267      PORT_DIPNAME( config_speech_mask << config_speech_bit, 1 << config_speech_bit, "Speech synthesis")
268         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
269         PORT_DIPSETTING( 1 << config_speech_bit, DEF_STR( On ) )
270      PORT_DIPNAME( config_fdc_mask << config_fdc_bit, fdc_kind_hfdc << config_fdc_bit, "Floppy disk controller")
271         PORT_DIPSETTING( fdc_kind_none << config_fdc_bit, DEF_STR( None ) )
272         PORT_DIPSETTING( fdc_kind_TI << config_fdc_bit, "Texas Instruments SD" )
273#if HAS_99CCFDC
274         PORT_DIPSETTING( fdc_kind_CC << config_fdc_bit, "CorComp" )
275#endif
276         PORT_DIPSETTING( fdc_kind_BwG << config_fdc_bit, "SNUG's BwG" )
277         PORT_DIPSETTING( fdc_kind_hfdc << config_fdc_bit, "Myarc's HFDC" )
278      PORT_DIPNAME( config_ide_mask << config_ide_bit, /*1 << config_ide_bit*/0, "Nouspickel's IDE card")
279         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
280         PORT_DIPSETTING( 1 << config_ide_bit, DEF_STR( On ) )
281      PORT_DIPNAME( config_rs232_mask << config_rs232_bit, 1 << config_rs232_bit, "TI RS232 card")
282         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
283         PORT_DIPSETTING( 1 << config_rs232_bit, DEF_STR( On ) )
284      PORT_DIPNAME( config_handsets_mask << config_handsets_bit, /*1 << config_handsets_bit*/0, "I/R remote handset")
285         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
286         PORT_DIPSETTING( 1 << config_handsets_bit, DEF_STR( On ) )
287      PORT_DIPNAME( config_hsgpl_mask << config_hsgpl_bit, 0/*1 << config_hsgpl_bit*/, "SNUG HSGPL card")
288         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
289         PORT_DIPSETTING( 1 << config_hsgpl_bit, DEF_STR( On ) )
290      PORT_DIPNAME( config_mecmouse_mask << config_mecmouse_bit, 0, "Mechatronics Mouse")
291         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
292         PORT_DIPSETTING( 1 << config_mecmouse_bit, DEF_STR( On ) )
293      PORT_DIPNAME( config_usbsm_mask << config_usbsm_bit, 1 << config_usbsm_bit, "Nouspickel's USB-SM card")
294         PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
295         PORT_DIPSETTING( 1 << config_usbsm_bit, DEF_STR( On ) )
282   PORT_START( "RAM" )   /* config */
283   PORT_CONFNAME( 0x07, 0x00, "RAM extension" )
284      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
285      PORT_CONFSETTING(    0x01, "Texas Instruments 32 KiB" )
286      PORT_CONFSETTING(    0x02, "Super AMS 1MiB" )
287      PORT_CONFSETTING(    0x03, "Foundation 128 KiB" )
288      PORT_CONFSETTING(    0x04, "Foundation 512 KiB" )
289      PORT_CONFSETTING(    0x05, "Myarc 128 KiB" )
290      PORT_CONFSETTING(    0x06, "Myarc 512 KiB" )
296291
292   PORT_START( "SPEECH" )
293   PORT_CONFNAME( 0x01, 0x00, "Speech synthesizer" )
294      PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
295      PORT_CONFSETTING( 0x01, DEF_STR( On ) )
297296
297   PORT_START( "DISKCTRL" )
298   PORT_CONFNAME( 0x07, 0x00, "Disk controller" )
299      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
300      PORT_CONFSETTING(    0x01, "TI SD Floppy Controller" )
301      PORT_CONFSETTING(    0x02, "SNUG BwG Controller" )
302      PORT_CONFSETTING(    0x03, "Myarc HFDC" )
303//      PORT_CONFSETTING(    0x04, "Corcomp" )
304
305   PORT_START( "HDCTRL" )
306   PORT_CONFNAME( 0x03, 0x00, "HD controller" )
307      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
308      PORT_CONFSETTING(    0x01, "Nouspikel IDE Controller" )
309//      PORT_CONFSETTING(    0x02, "WHTech SCSI Controller" )
310   PORT_CONFNAME( 0x08, 0x00, "USB-SM card" )
311      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
312      PORT_CONFSETTING(    0x08, DEF_STR( On ) )
313
314   PORT_START( "SERIAL" )
315   PORT_CONFNAME( 0x03, 0x00, "Serial/Parallel interface" )
316      PORT_CONFSETTING(    0x00, DEF_STR( None ) )
317      PORT_CONFSETTING(    0x01, "TI RS-232 card" )
318   
319   PORT_START( "EXTCARD" )
320   PORT_CONFNAME( 0x01, 0x00, "HSGPL extension" )
321      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
322      PORT_CONFSETTING(    0x01, DEF_STR( On ) )
323   PORT_CONFNAME( 0x02, 0x00, "P-Code card" )
324      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
325      PORT_CONFSETTING(    0x02, DEF_STR( On ) )
326
327   PORT_START( "HCI" )
328   PORT_CONFNAME( 0x01, 0x00, "Mouse support" )
329      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
330      PORT_CONFSETTING(    0x01, "Mechatronics Mouse" )
331   PORT_CONFNAME( 0x04, 0x00, "IR Handset" )
332      PORT_CONFSETTING(    0x00, DEF_STR( Off ) )
333      PORT_CONFSETTING(    0x04, DEF_STR( On ) )   
334     
335   PORT_START( "CARTSLOT" )
336   PORT_CONFNAME( 0x07, 0x00, "Cartridge slot" )
337      PORT_CONFSETTING(    0x00, "Auto" )
338      PORT_CONFSETTING(    0x01, "Slot 1" )
339      PORT_CONFSETTING(    0x02, "Slot 2" )
340      PORT_CONFSETTING(    0x03, "Slot 3" )
341      PORT_CONFSETTING(    0x04, "Slot 4" )
342//      PORT_CONFSETTING(    0x05, "GRAM Kracker" )
343
344   PORT_START( "HFDCDIP" )
345   PORT_DIPNAME( 0xff, 0x55, "HFDC drive config" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
346      PORT_DIPSETTING( 0x00, "40 track, 16 ms")
347      PORT_DIPSETTING( 0xaa, "40 track, 8 ms")
348      PORT_DIPSETTING( 0x55, "80 track, 2 ms")
349      PORT_DIPSETTING( 0xff, "80 track HD, 2 ms")     
350
351   PORT_START( "DRVSPD" )
352   PORT_DIPNAME( 0x01, 0x01, "Floppy and HD speed" ) PORT_CONDITION( "DISKCTRL", 0x07, PORTCOND_EQUALS, 0x03 )
353      PORT_DIPSETTING( 0x00, "No delay")
354      PORT_DIPSETTING( 0x01, "Realistic")
355     
298356   /* 3 ports for mouse */
299357   PORT_START("MOUSEX") /* Mouse - X AXIS */
300358      PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1)
r8042r8043
645703
646704   /* devices */
647705   MDRV_IDE_CONTROLLER_ADD( "ide", ti99_ide_interrupt )   /* FIXME */
648
649   MDRV_IMPORT_FROM( smc92x4_hd )
650
651   MDRV_IDE_HARDDISK_ADD( "ide_harddisk" )
652706   MDRV_RTC65271_ADD("ide_rtc", ti99_clk_interrupt_callback)
653707
654708   MDRV_CASSETTE_ADD( "cassette1", default_cassette_config )
r8042r8043
659713   /* tms9901 */
660714   MDRV_TMS9901_ADD("tms9901", tms9901reset_param_ti99_4x)
661715
716   /* to be moved to controller */
662717   MDRV_WD179X_ADD("wd179x", ti99_wd17xx_interface )
718   MDRV_SMC92X4_ADD("smc92x4", ti99_smc92x4_interface )
663719
664720   MDRV_FLOPPY_4_DRIVES_ADD(ti99_4_floppy_config)
665
721   MDRV_MFMHD_3_DRIVES_ADD()
722   
666723   MDRV_TI99_CARTRIDGE_ADD("ti99_multicart")
667724
668725   MDRV_SMARTMEDIA_ADD("smartmedia")
r8042r8043
700757
701758   /* devices */
702759   MDRV_IDE_CONTROLLER_ADD( "ide", ti99_ide_interrupt )   /* FIXME */
703
704   MDRV_IMPORT_FROM( smc92x4_hd )
705
706   MDRV_IDE_HARDDISK_ADD( "ide_harddisk" )
707760   MDRV_RTC65271_ADD("ide_rtc", ti99_clk_interrupt_callback)
708761
709762   MDRV_CASSETTE_ADD( "cassette1", default_cassette_config )
r8042r8043
714767   /* tms9901 */
715768   MDRV_TMS9901_ADD("tms9901", tms9901reset_param_ti99_4x)
716769
770   /* to be moved to controller */
717771   MDRV_WD179X_ADD("wd179x", ti99_wd17xx_interface )
772   MDRV_SMC92X4_ADD("smc92x4", ti99_smc92x4_interface )
773
718774   MDRV_FLOPPY_4_DRIVES_ADD(ti99_4_floppy_config)
775   MDRV_MFMHD_3_DRIVES_ADD()
719776
720777   MDRV_TI99_CARTRIDGE_ADD("ti99_multicart")
721778
r8042r8043
754811
755812   /* devices */
756813   MDRV_IDE_CONTROLLER_ADD( "ide", ti99_ide_interrupt )   /* FIXME */
757
758   MDRV_IMPORT_FROM( smc92x4_hd )
759
760   MDRV_IDE_HARDDISK_ADD( "ide_harddisk" )
761814   MDRV_RTC65271_ADD("ide_rtc", ti99_clk_interrupt_callback)
762815
763816   MDRV_CASSETTE_ADD( "cassette1", default_cassette_config )
r8042r8043
769822   /* tms9901 */
770823   MDRV_TMS9901_ADD("tms9901", tms9901reset_param_ti99_4x)
771824
825   /* to be moved to controller */
772826   MDRV_WD179X_ADD("wd179x", ti99_wd17xx_interface )
827   MDRV_SMC92X4_ADD("smc92x4", ti99_smc92x4_interface )
828
773829   MDRV_FLOPPY_4_DRIVES_ADD(ti99_4_floppy_config)
830   MDRV_MFMHD_3_DRIVES_ADD()
774831
775832   MDRV_TI99_CARTRIDGE_ADD("ti99_multicart")
776833
r8042r8043
810867
811868   /* devices */
812869   MDRV_IDE_CONTROLLER_ADD( "ide", ti99_ide_interrupt )
813
814   MDRV_IMPORT_FROM( smc92x4_hd )
815
816   MDRV_IDE_HARDDISK_ADD( "ide_harddisk" )
817870   MDRV_RTC65271_ADD("ide_rtc", ti99_clk_interrupt_callback)
818871
819872   MDRV_CASSETTE_ADD( "cassette1", default_cassette_config )
r8042r8043
824877   /* tms9901 */
825878   MDRV_TMS9901_ADD("tms9901", tms9901reset_param_ti99_4x)
826879
880   /* to be moved to controller */
827881   MDRV_WD179X_ADD("wd179x", ti99_wd17xx_interface )
882   MDRV_SMC92X4_ADD("smc92x4", ti99_smc92x4_interface )
883
828884   MDRV_FLOPPY_4_DRIVES_ADD(ti99_4_floppy_config)
885   MDRV_MFMHD_3_DRIVES_ADD()
829886
830887   MDRV_TI99_CARTRIDGE_ADD("ti99_multicart")
831888
832889   MDRV_SMARTMEDIA_ADD("smartmedia")
833890
834   MDRV_TI99_4_RS232_CARD_ADD("rs232")
891   MDRV_TI99_4_RS232_CARD_ADD("rs232")   
835892MACHINE_DRIVER_END
836893
837894
r8042r8043
873930
874931   /* devices */
875932   MDRV_IDE_CONTROLLER_ADD( "ide", ti99_ide_interrupt )   /* FIXME */
876
877   MDRV_IMPORT_FROM( smc92x4_hd )
878
879   MDRV_IDE_HARDDISK_ADD( "ide_harddisk" )
880933   MDRV_RTC65271_ADD("ide_rtc", ti99_clk_interrupt_callback)
881934
882935   MDRV_CASSETTE_ADD( "cassette1", default_cassette_config )
r8042r8043
887940   /* tms9901 */
888941   MDRV_TMS9901_ADD("tms9901", tms9901reset_param_ti99_4x)
889942
943   /* to be moved to controller */
890944   MDRV_WD179X_ADD("wd179x", ti99_wd17xx_interface )
945   MDRV_SMC92X4_ADD("smc92x4", ti99_smc92x4_interface )
946   
891947   MDRV_FLOPPY_4_DRIVES_ADD(ti99_4_floppy_config)
948   MDRV_MFMHD_3_DRIVES_ADD()
949
892950   MDRV_TI99_CARTRIDGE_ADD("ti99_multicart")
893951   MDRV_SMARTMEDIA_ADD("smartmedia")
894952

Previous 15994 Revisions Next


© 1998-2018 The MESS Team