1 #ifndef FDC765_H_INCLUDED
2 
3 #define FDC765_H_INCLUDED 1
4 
5 /* 765: Library to emulate the uPD765a floppy controller (aka Intel 8272)
6 
7     Copyright (C) 2002,2003,2004  John Elliott <jce@seasip.demon.co.uk>
8 
9     Modifications to add dirty flags
10     (c) 2005 Philip Kendall <pak21-spectrum@srcf.ucam.org>
11 
12     This library is free software; you can redistribute it and/or
13     modify it under the terms of the GNU Library General Public
14     License as published by the Free Software Foundation; either
15     version 2 of the License, or (at your option) any later version.
16 
17     This library is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20     Library General Public License for more details.
21 
22     You should have received a copy of the GNU Library General Public
23     License along with this library; if not, write to the Free
24     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 #include <stdarg.h>
32 
33 /*
34     Functions which your program should provide are marked here by
35     the word EXT:
36 
37     NOTE: This library emulates enough of a uPD765A controller (aka Intel 8272)
38     for an Amstrad CP/M BIOS. Features the Amstrad BIOS does not use, such as:
39 
40     * DMA mode
41     * Multitrack mode
42     * Multisector reads/writes
43     * Read/Write deleted data
44 
45     are not implemented.
46 
47 */
48 
49 #define MAX_SECTOR_LEN  8192	/* Max size of sectors this FDC can handle */
50 #define SHORT_TIMEOUT   1000	/* Timeouts, in machine cycles */
51 #define LONGER_TIMEOUT  1333333L
52 
53 /* EXT: called by the FDC to print debugging messages
54  *
55  * We assume that the normal debug level is 0. As we get more and more
56  * nitpicky, the debug level gets higher.
57  *
58  * Level 5 dumps out all command sequences sent to the FDC.
59  * Level 4 logs all sector reads, writes & seeks.
60  */
61 void fdc_dprintf(int debuglevel, char *fmt, ...);
62 
63 typedef void (*lib765_error_function_t)(int debuglevel, char *fmt, va_list ap);
64 
65 extern lib765_error_function_t lib765_error_function;
66 
67 void lib765_default_error_function(int debuglevel, char *fmt, va_list ap);
68 
69 void lib765_register_error_function(lib765_error_function_t ef);
70 
71 /******************************* Types ************************************/
72 typedef unsigned char fdc_byte;	/* 8-bit byte */
73 typedef short         fd_err_t; /* Error code returned from disc routines */
74 
75 /****************************** Defines ***********************************/
76 
77 /* Floppy drive types */
78 #define FD_NC9256 (-1)	/* PCW9256 drives 2 and 3 */
79 #define FD_NONE   ( 0)	/* Drive B: on single-drive computers */
80 #define FD_30     ( 1)	/* 3"    */
81 #define FD_35     ( 2)	/* 3.5"  */
82 #define FD_525    ( 3)	/* 5.25" */
83 
84 /* Floppy drive errors */
85 #define FD_E_OK	       (0) 	/* OK */
86 #define FD_E_SEEKFAIL (-1)	/* Seek fail */
87 #define FD_E_NOADDR   (-2)	/* Missing address mark */
88 #define FD_E_NODATA   (-3) 	/* No data */
89 #define FD_E_DATAERR  (-4)	/* CRC Data error */
90 #define FD_E_NOSECTOR (-5)	/* Sector not found */
91 #define FD_E_NOTRDY   (-6)	/* Drive not ready */
92 #define FD_E_READONLY (-7)	/* Read only */
93 
94 /* Floppy disk dirty flags */
95 #define FD_D_UNAVAILABLE (-1)	/* Disk dirty information not available */
96 #define FD_D_CLEAN       ( 0)	/* Disk not written to */
97 #define FD_D_DIRTY       ( 1)	/* Disk written to */
98 
99 struct fdc_765;
100 
101 /********************************** CLASSES ********************************/
102 
103 /* This is yet another attempt to write object-oriented C.
104  *
105  * Variables in these structs are marked as PUBLIC, READONLY or PRIVATE.
106  * Your program can play with PUBLIC variables how it likes, but should
107  * not alter READONLY ones, and it shouldn't touch the PRIVATE ones at all.
108  *
109  * Use FLOPPY_DRIVE for dummy drives (units which aren't connected at all)
110  * and DSK_FLOPPY_DRIVE / LIBDSK_FLOPPY_DRIVE for drives that are real.
111  *
112  * These structures MUST be initialised (see fd_init() below) before use.
113  */
114 
115 /* lib765 v0.1.0: Implementation details hidden away behind opaque
116  * pointers; accessor functions used instead */
117 
118 typedef struct floppy_drive *FDRV_PTR;
119 
120 /* Accessor functions replace direct access to structure members */
121 
122 int fd_gettype    (FDRV_PTR fd); /* 0 for none, 1 for 3", 2 for 3.5", 3 for 5.25" */
123 int fd_getheads   (FDRV_PTR fd); /* No. of heads in the drive: 1 or 2 */
124 int fd_getcyls    (FDRV_PTR fd); /* No. of cylinders the drive can access:
125                                   * eg: a nominally 40-track drive can usually go up
126                                   * to 42 tracks with a bit of "persuasion" */
127 int fd_getreadonly(FDRV_PTR fd); /* Is the drive (or the disc therein) set to R/O? */
128 
129 void fd_settype    (FDRV_PTR fd, int type);
130 void fd_setheads   (FDRV_PTR fd, int heads);
131 void fd_setcyls    (FDRV_PTR fd, int cyls);
132 void fd_setreadonly(FDRV_PTR fd, int ro);
133 
134 int fd_getmotor    (FDRV_PTR fd); /* Is the motor on for this drive? */
135 int fd_getcurcyl   (FDRV_PTR fd); /* What cylinder is this drive on?
136                                    * Current cylinder. Note that if the drive is
137                                    * double-stepping, this is the "real" cylinder -
138                                    * so it could = 24 and be reading cylinder 12
139                                    * of a 40-track DSK file. */
140 
141 /* Create a default (not-connected) drive */
142 
143 FDRV_PTR fd_new(void);
144 
145 /* Destroy any kind of drive */
146 void     fd_destroy(FDRV_PTR *fd);
147 
148 /* Special emulation for PCW9256 drive 2 */
149 
150 FDRV_PTR fd_newnc9(FDRV_PTR fd);
151 FDRV_PTR fd9_getproxy(FDRV_PTR self);
152 void     fd9_setproxy(FDRV_PTR self, FDRV_PTR PROXY);
153 
154 
155 /* Subclass of FLOPPY_DRIVE: a drive which emulates discs using the CPCEMU
156  * .DSK format */
157 
158 FDRV_PTR fd_newdsk(void);
159 
160 /* Get / set DSK file associated with this drive.
161  * Note that doing fdd_setfilename() causes an implicit eject on the
162  * previous disc in the drive. */
163 char *   fdd_getfilename(FDRV_PTR fd);
164 void	 fdd_setfilename(FDRV_PTR fd, const char *s);
165 
166 /* This function is specific to DSK-type drives, and is not called by the
167  * FDC. It is intended for use by administration interfaces */
168 fd_err_t fdd_new_dsk(FDRV_PTR fd);
169 
170 
171 #ifdef DSK_ERR_OK	/* LIBDSK headers included */
172 /* Subclass of FLOPPY_DRIVE: a drive which emulates discs using LIBDSK
173  * for disc I/O. */
174 FDRV_PTR fd_newldsk(void);
175 
176 /* Get / set DSK file associated with this drive.
177  * Note that doing fdd_setfilename() causes an implicit eject on the
178  * previous disc in the drive. */
179 char *   fdl_getfilename(FDRV_PTR fd);
180 void	 fdl_setfilename(FDRV_PTR fd, const char *s);
181 
182 /* Set the LIBDSK drive type. NULL for automatic */
183 const char *   fdl_gettype(FDRV_PTR fd);
184 void	 fdl_settype(FDRV_PTR fd, const char *s);
185 /* Set the LIBDSK compression type. NULL for automatic */
186 const char *   fdl_getcomp(FDRV_PTR fd);
187 void	 fdl_setcomp(FDRV_PTR fd, const char *s);
188 #endif
189 
190 
191 
192 typedef struct fdc_765 *FDC_PTR;
193 
194 /* This is called when the FDC interrupts */
195 typedef void (*FDC_ISR)(FDC_PTR self, int status);
196 
197 FDC_PTR fdc_new(void);
198 void    fdc_destroy(FDC_PTR *p);
199 
200 /* Reading FDC internal state */
201 fdc_byte fdc_readst0(FDC_PTR fdc);
202 fdc_byte fdc_readst1(FDC_PTR fdc);
203 fdc_byte fdc_readst2(FDC_PTR fdc);
204 fdc_byte fdc_readst3(FDC_PTR fdc);
205 
206 int fdc_getunit(FDC_PTR fdc);	/* Get current unit */
207 int fdc_gethead(FDC_PTR fdc);	/* Get current head */
208 
209 void fdc_setisr(FDC_PTR self, FDC_ISR isr);
210 FDC_ISR fdc_getisr(FDC_PTR self);
211 
212 /* The FDC's four drives. You must set these. */
213 FDRV_PTR fdc_getdrive(FDC_PTR self, int drive);
214 void fdc_setdrive(FDC_PTR self, int drive, FDRV_PTR ptr);
215 
216 
217 /*********************** WRAPPER FUNCTIONS ********************************/
218 
219 /* Wrappers for the floppy's member functions */
220 /* Seek to a cylinder */
221 fd_err_t fd_seek_cylinder(FDRV_PTR fd, int cylinder);
222 /* Read ID from current cylinder, head "head". "sector" is a number
223  * which should increase every time you call this function, to simulate
224  * the rotation of the disc. Fills the buffer at "buf" with the sector ID. */
225 fd_err_t fd_read_id(FDRV_PTR fd, int head, int sector, fdc_byte *buf);
226 /* Read a sector. xcylinder and xhead are values expected from the sector ID;
227  * while "head" and "sector" are the actual place to look on the disc.
228  * Data will be returned to "buf", maximum "len" bytes. */
229 fd_err_t fd_read_sector(FDRV_PTR fd, int xcylinder,
230                 int xhead, int head, int sector, fdc_byte *buf,
231 		int len, int *deleted, int skip_deleted, int mfm, int multi);
232 /* Write a sector; parameters as for "read sector" */
233 fd_err_t  fd_write_sector(FDRV_PTR fd, int xcylinder,
234                 int xhead, int head, int sector, fdc_byte *buf, int len,
235 		int deleted, int skip_deleted, int mfm, int multi);
236 /* Read an entire track; parameters as for "read sector" */
237 fd_err_t  fd_read_track   (struct floppy_drive *fd, int xcylinder,
238                 int xhead, int head, fdc_byte *buf, int *len);
239 /* Format a track of "sectors" sectors, on the current cylinder. "track"
240  * holds the sector ID information, and "filler" is the filler byte */
241 fd_err_t  fd_format_track (struct floppy_drive *fd, int head,
242 		int sectors, fdc_byte *track, fdc_byte filler);
243 /* Get the drive status - bits 7-3 of the DD_DRIVE_STATUS value */
244 fdc_byte fd_drive_status(FDRV_PTR fd);
245 /* Return 1 if the drive is ready, 0 if it is not */
246 fdc_byte fd_isready(FDRV_PTR fd);
247 /* Return 1 if the disc has been changed (defined as the disc being ejected
248  * since last FDC reset). For PcW16 changeline support. */
249 fdc_byte fd_changed(FDRV_PTR fd);
250 /* Has this floppy been written to since it was inserted? */
251 #define LIB765_EXPOSES_DIRTY
252 int fd_dirty(FDRV_PTR fd);
253 /* Eject the disc from the drive */
254 void fd_eject(FDRV_PTR fd);
255 /* Set the drive's data rate */
256 void fd_set_datarate(FDRV_PTR fd, fdc_byte rate);
257 /* Reset the drive */
258 void fd_reset(FDRV_PTR fd);
259 
260 
261 
262 /* Interface to the FDC itself */
263 
264 /* Reset the FDC. MUST be called to initialise the FDC structure */
265 void fdc_reset     (FDC_PTR self);
266 /* Write a byte to the FDC's data register */
267 void fdc_write_data(FDC_PTR self, fdc_byte value);
268 /* Read the FDC's data register */
269 fdc_byte fdc_read_data (FDC_PTR self);
270 /* Read the FDC's main control register */
271 fdc_byte fdc_read_ctrl (FDC_PTR self);
272 /* Raise / lower the FDC's terminal count line */
273 void fdc_set_terminal_count(FDC_PTR self, fdc_byte value);
274 /* Start/stop drive motors. Bit 0 corresponds to drive 1's motor, etc. */
275 void fdc_set_motor(FDC_PTR self, fdc_byte running);
276 /* Call this once every cycle round the emulator's main loop */
277 void fdc_tick(FDC_PTR self);
278 /* Write to the Digital Output Register. Write -1 to disable DOR emulation */
279 void fdc_write_dor(FDC_PTR self, int value);
280 /* Read from the Digital Input Register. */
281 fdc_byte fdc_read_dir(FDC_PTR self);
282 /* Write to the Data Rate Register. */
283 void fdc_write_drr(FDC_PTR self, fdc_byte value);
284 
285 #ifdef __cplusplus
286 }
287 #endif
288 
289 #endif /* ndef FDC765_H_INCLUDED */
290 
291