File: wd_fdc.h

package info (click to toggle)
fuse-emulator 1.3.2%2Bdfsg1-1
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 10,456 kB
  • ctags: 9,261
  • sloc: ansic: 83,215; sh: 11,503; perl: 3,806; makefile: 1,000; yacc: 254; lex: 143
file content (172 lines) | stat: -rw-r--r-- 5,511 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/* wd_fdc.h: Western Digital floppy disk controller emulation
   Copyright (c) 2003-2015 Stuart Brady, Fredrick Meunier, Philip Kendall,
   Gergely Szasz

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program; if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

   Author contact information:

   Philip: philip-fuse@shadowmagic.org.uk

   Stuart: stuart.brady@gmail.com

*/

#ifndef FUSE_WD_FDC_H
#define FUSE_WD_FDC_H

#include <libspectrum.h>

#include "event.h"
#include "fdd.h"
#include "fuse.h"

/* Status register bits */
enum {
  WD_FDC_SR_MOTORON = 1<<7, /* Motor on or READY */
  WD_FDC_SR_WRPROT  = 1<<6, /* Write-protect */
  WD_FDC_SR_SPINUP  = 1<<5, /* Record type / Spin-up complete */
  WD_FDC_SR_RNF     = 1<<4, /* Record Not Found or SEEK Error */
  WD_FDC_SR_CRCERR  = 1<<3, /* CRC error */
  WD_FDC_SR_LOST    = 1<<2, /* Lost data or TRACK00 */
  WD_FDC_SR_IDX_DRQ = 1<<1, /* Index pulse / Data request */
  WD_FDC_SR_BUSY    = 1<<0  /* Busy (command under execution) */
};

/* Configuration flags (interface-specific) */
enum {
  WD_FLAG_NONE      = 0,
  /* The Beta 128 connects the HLD output pin to the READY input pin and
   * the MOTOR ON output pin on the FDD interface. */
  WD_FLAG_BETA128   = 1<<0,
  /* The Opus Discovery needs a pulse of the DRQ (data request) line for every
   * byte transferred. */
  WD_FLAG_DRQ       = 1<<1,
  /* The MB-02+ provides a READY signal to FDC instead of FDD, so we use
   * 'extra_signal' for this */
  WD_FLAG_RDY       = 1<<2,
  /* HLT (input) pin not connected at all, so we assume it is always 1. */
  WD_FLAG_NOHLT     = 1<<3
};

typedef enum wd_type_t {
  WD1773 = 0,
  FD1793,
  WD1770,
  WD1772,
  WD2797
} wd_type_t;

typedef struct wd_fdc {
  fdd_t *current_drive;

  wd_type_t type;	/* WD1770, FD1793, WD1772, WD1773, WD2797 */

  int rates[ 4 ];
  int spin_cycles;
  fdd_dir_t direction;	/* 0 = spindlewards, 1 = rimwards */
  int dden;		/* SD/DD -> FM/MFM */
  int intrq;		/* INTRQ line status */
  int datarq;		/* DRQ line status */
  int head_load;	/* WD1773/FD1793 */
  int hlt;		/* WD1773/FD1793 Head Load Timing input pin */
  int hlt_time;		/* "... When a logic high is found on the HLT input
			   the head is assumed to be enganged. It is typically
			   derived from a 1 shot triggered by HLD ..."
			   if hlt_time > 0 it means trigger time in ms, if = 0
			   then hlt should be set with wd_fdc_set_hlt()  */
  unsigned int flags;	/* Configuration flags (interface-specific) */
  int extra_signal;	/* Extra line for boards with non-standard wiring */

  enum wd_fdc_state {
    WD_FDC_STATE_NONE = 0,
    WD_FDC_STATE_SEEK,
    WD_FDC_STATE_SEEK_DELAY,
    WD_FDC_STATE_VERIFY,
    WD_FDC_STATE_READ,
    WD_FDC_STATE_WRITE,
    WD_FDC_STATE_READTRACK,
    WD_FDC_STATE_WRITETRACK,
    WD_FDC_STATE_READID,
  } state;

  int read_id;		/* FDC try to read a DAM */

  enum wd_fdc_status_type {
    WD_FDC_STATUS_TYPE1,
    WD_FDC_STATUS_TYPE2,
  } status_type;

  enum wd_fdc_am_type {
    WD_FDC_AM_NONE = 0,
    WD_FDC_AM_INDEX,
    WD_FDC_AM_ID,
    WD_FDC_AM_DATA,
  } id_mark;

  int id_track;
  int id_head;
  int id_sector;
  int id_length;	/* sector length code 0, 1, 2, 3 */
  int non_ibm_len_code;	/* WD2797 can use alternative sector len code set */
  int sector_length;	/* sector length from length code */
  int ddam;		/* read a deleted data mark */
  int rev;		/* revolution counter */

  /* state during transfer */
  int data_check_head;	/* -1 no check, 0/1 wait side 0 or 1 */
  int data_multisector;
  int data_offset;

  libspectrum_byte command_register;    /* command register */
  libspectrum_byte status_register;     /* status register */
  libspectrum_byte track_register;      /* track register */
  libspectrum_byte sector_register;     /* sector register */
  libspectrum_byte data_register;       /* data register */

  libspectrum_word crc;			/* to hold crc */

  void ( *set_intrq ) ( struct wd_fdc *f );
  void ( *reset_intrq ) ( struct wd_fdc *f );
  void ( *set_datarq ) ( struct wd_fdc *f );
  void ( *reset_datarq ) ( struct wd_fdc *f );

} wd_fdc;

void wd_fdc_init_events( void );

/* allocate an fdc */
wd_fdc *wd_fdc_alloc_fdc( wd_type_t type, int hlt_time, unsigned int flags );
void wd_fdc_master_reset( wd_fdc *f );

libspectrum_byte wd_fdc_sr_read( wd_fdc *f );
void wd_fdc_cr_write( wd_fdc *f, libspectrum_byte b );

libspectrum_byte wd_fdc_tr_read( wd_fdc *f );
void wd_fdc_tr_write( wd_fdc *f, libspectrum_byte b );

libspectrum_byte wd_fdc_sec_read( wd_fdc *f );
void wd_fdc_sec_write( wd_fdc *f, libspectrum_byte b );

libspectrum_byte wd_fdc_dr_read( wd_fdc *f );
void wd_fdc_dr_write( wd_fdc *f, libspectrum_byte b );

void wd_fdc_set_intrq( wd_fdc *f );
void wd_fdc_reset_intrq( wd_fdc *f );
void wd_fdc_set_datarq( wd_fdc *f );
void wd_fdc_reset_datarq( wd_fdc *f );
void wd_fdc_set_hlt( wd_fdc *f, int hlt );

#endif                  /* #ifndef FUSE_WD_FDC_H */