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