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