File: wd_fdc.h

package info (click to toggle)
fuse-emulator 1.0.0.1a%2Bdfsg1-4
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 9,568 kB
  • sloc: ansic: 67,895; sh: 10,265; perl: 3,386; makefile: 787; yacc: 227; lex: 139
file content (170 lines) | stat: -rw-r--r-- 5,460 bytes parent folder | download
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
/* wd_fdc.h: Western Digital floppy disk controller emulation
   Copyright (c) 2003-2007 Stuart Brady, Fredrick Meunier, Philip Kendall,
   Gergely Szasz

   $Id: wd_fdc.h 4060 2009-07-30 13:21:38Z fredm $

   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: sdbrady@ntlworld.com

*/

#ifndef FUSE_WD_FDC_H
#define FUSE_WD_FDC_H

#include <libspectrum.h>

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

static const int WD_FDC_SR_MOTORON = 1<<7; /* Motor on */
static const int WD_FDC_SR_WRPROT  = 1<<6; /* Write-protect */
static const int WD_FDC_SR_SPINUP  = 1<<5; /* Record type / Spin-up complete */
static const int WD_FDC_SR_RNF     = 1<<4; /* Record Not Found */
static const int WD_FDC_SR_CRCERR  = 1<<3; /* CRC error */
static const int WD_FDC_SR_LOST    = 1<<2; /* Lost data */
static const int WD_FDC_SR_IDX_DRQ = 1<<1; /* Index pulse / Data request */
static const int WD_FDC_SR_BUSY    = 1<<0; /* Busy (command under execution) */

static const int WD_FLAG_NONE      = 0;
static const int WD_FLAG_BETA128   = 1<<0; /* Beta128 connects HLD output pin to READY input pin and
					      MOTOR ON pin on FDD interface */
static const int WD_FLAG_OPUS      = 1<<1; /* Opus Discovery need `datarq' line for every byte */

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

extern int wd_fdc_index_pulse;
extern int wd_fdc_index_interrupt;

typedef struct wd_fdc_drive {
  fdd_t fdd;			/* floppy disk drive */
  disk_t disk;			/* the floppy disk itself */
  int index_pulse;
  int index_interrupt;

} wd_fdc_drive;

typedef struct wd_fdc {
  wd_fdc_drive *current_drive;

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

  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;		/* Beta128 connects HLD output pin to READY input pin and
				   MOTOR ON pin on FDD interface */

  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 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 );
  void *iface;

} wd_fdc;

int 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 */