1 #include "ibm.h"
2 #include "disc.h"
3 #include "fdc.h"
4 #include "fdd.h"
5
6 static struct
7 {
8 int type;
9
10 int track;
11
12 int densel;
13
14 int drate;
15
16 int kbps;
17 int fdc_kbps;
18 } fdd[2];
19
20 /* Flags:
21 Bit 0: 300 rpm supported;
22 Bit 1: 360 rpm supported;
23 Bit 2: size (0 = 3.5", 1 = 5.25");
24 Bit 3: double density supported;
25 Bit 4: high density supported;
26 Bit 5: extended density supported;
27 Bit 6: double step for 40-track media;
28 */
29 #define FLAG_RPM_300 1
30 #define FLAG_RPM_360 2
31 #define FLAG_525 4
32 #define FLAG_HOLE0 8
33 #define FLAG_HOLE1 16
34 #define FLAG_HOLE2 32
35 #define FLAG_DOUBLE_STEP 64
36
37 static struct
38 {
39 int max_track;
40 int flags;
41 } drive_types[] =
42 {
43 { /*None*/
44 .max_track = 0,
45 .flags = 0
46 },
47 { /*5.25" DD*/
48 .max_track = 41,
49 .flags = FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0
50 },
51 { /*5.25" HD*/
52 .max_track = 82,
53 .flags = FLAG_RPM_360 | FLAG_525 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP
54 },
55 { /*5.25" HD Dual RPM*/
56 .max_track = 82,
57 .flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP
58 },
59 { /*3.5" DD*/
60 .max_track = 82,
61 .flags = FLAG_RPM_300 | FLAG_HOLE0
62 },
63 { /*3.5" HD*/
64 .max_track = 82,
65 .flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1
66 },
67 { /*3.5" HD 3-Mode*/
68 .max_track = 82,
69 .flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_HOLE0 | FLAG_HOLE1
70 },
71 { /*3.5" ED*/
72 .max_track = 82,
73 .flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2
74 }
75 };
76
77 int fdd_swap = 0;
78
fdd_seek(int drive,int track_diff)79 void fdd_seek(int drive, int track_diff)
80 {
81 drive ^= fdd_swap;
82
83 if (drive >= 2)
84 {
85 disctime = 5000;
86 return;
87 }
88
89 fdd[drive].track += track_diff;
90
91 if (fdd[drive].track < 0)
92 fdd[drive].track = 0;
93
94 if (fdd[drive].track > drive_types[fdd[drive].type].max_track)
95 fdd[drive].track = drive_types[fdd[drive].type].max_track;
96
97 // pclog("fdd_seek: drive=%i track_diff=%i old_track=%i track=%i\n", drive, track_diff, old_track, fdd[drive].track);
98
99 fdc_discchange_clear(drive);
100
101 disc_seek(drive, fdd[drive].track);
102 disctime = 5000;
103 }
104
fdd_disc_changed(int drive)105 void fdd_disc_changed(int drive)
106 {
107 drive ^= fdd_swap;
108
109 /*Force reload of current track data*/
110 if (drive < 2)
111 disc_seek(drive, fdd[drive].track);
112 }
113
fdd_track0(int drive)114 int fdd_track0(int drive)
115 {
116 drive ^= fdd_swap;
117
118 if (drive >= 2)
119 return 0;
120
121 /* If drive is disabled, TRK0 never gets set. */
122 if (!drive_types[fdd[drive].type].max_track) return 0;
123
124 return !fdd[drive].track;
125 }
126
fdd_set_densel(int densel)127 void fdd_set_densel(int densel)
128 {
129 fdd[0].densel = densel;
130 fdd[1].densel = densel;
131 }
132
fdd_getrpm(int drive)133 int fdd_getrpm(int drive)
134 {
135 int hole;
136
137 drive ^= fdd_swap;
138
139 if (drive >= 2)
140 return 0;
141
142 hole = disc_hole(drive);
143
144 if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_360)) return 300;
145 if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_300)) return 360;
146
147 if (drive_types[fdd[drive].type].flags & FLAG_525)
148 {
149 return fdd[drive].densel ? 360 : 300;
150 }
151 else
152 {
153 /* disc_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */
154 if (hole == 1)
155 {
156 return fdd[drive].densel ? 300 : 360;
157 }
158 else
159 {
160 return 300;
161 }
162 }
163
164 switch (fdd[drive].type)
165 {
166 case 0:
167 return 300;
168 case 1:
169 return 360;
170 }
171 }
172
fdd_setswap(int swap)173 void fdd_setswap(int swap)
174 {
175 fdd_swap = swap ? 1 : 0;
176 }
177
fdd_can_read_medium(int drive)178 int fdd_can_read_medium(int drive)
179 {
180 int hole;
181
182 drive ^= fdd_swap;
183
184 if (drive >= 2)
185 return 0;
186
187 hole = disc_hole(drive);
188
189 hole = 1 << (hole + 3);
190
191 // pclog("Drive %02X, type %02X, hole flag %02X, flags %02X, result %02X\n", drive, fdd[drive].type, hole, drive_types[fdd[drive].type].flags, drive_types[fdd[drive].type].flags & hole);
192 return (drive_types[fdd[drive].type].flags & hole) ? 1 : 0;
193 }
194
fdd_doublestep_40(int drive)195 int fdd_doublestep_40(int drive)
196 {
197 if (drive >= 2)
198 return 0;
199 return drive_types[fdd[drive].type].flags & FLAG_DOUBLE_STEP;
200 }
201
fdd_set_type(int drive,int type)202 void fdd_set_type(int drive, int type)
203 {
204 if (drive < 2)
205 fdd[drive].type = type;
206 }
207
fdd_get_type(int drive)208 int fdd_get_type(int drive)
209 {
210 if (drive >= 2)
211 return 0;
212 return fdd[drive].type;
213 }
214
fdd_is_525(int drive)215 int fdd_is_525(int drive)
216 {
217 if (drive >= 2)
218 return 0;
219 return drive_types[fdd[drive].type].flags & FLAG_525;
220 }
221
fdd_is_ed(int drive)222 int fdd_is_ed(int drive)
223 {
224 if (drive >= 2)
225 return 0;
226 return drive_types[fdd[drive].type].flags & FLAG_HOLE2;
227 }
228