Fri, 18 Apr 2014 01:34:20 -0600
added RTC emulation (attempts to set the date are ignored, and the year is currently hardcoded to 1987 because UNIX PC SysV has a few Y2K bugs)
1 #ifndef _WD279X_H
2 #define _WD279X_H
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <stdint.h>
7 #include <stdio.h>
9 /// WD279x registers
10 typedef enum {
11 WD2797_REG_STATUS = 0, ///< Status register
12 WD2797_REG_COMMAND = 0, ///< Command register
13 WD2797_REG_TRACK = 1, ///< Track register
14 WD2797_REG_SECTOR = 2, ///< Sector register
15 WD2797_REG_DATA = 3 ///< Data register
16 } WD2797_REG;
18 /// WD279x emulator error codes
19 typedef enum {
20 WD2797_ERR_OK = 0, ///< Operation succeeded
21 WD2797_ERR_BAD_GEOM = -1, ///< Bad geometry, or image file too small
22 WD2797_ERR_NO_MEMORY = -2 ///< Out of memory
23 } WD2797_ERR;
25 typedef struct {
26 // Current track, head and sector
27 int track, head, sector;
28 // Track and sector registers
29 int track_reg, sector_reg;
30 // Geometry of current disc
31 int geom_secsz, geom_spt, geom_heads, geom_tracks;
32 // IRQ status
33 bool irq;
34 // Status of last command
35 uint8_t status;
36 // Last command uses DRQ bit?
37 bool cmd_has_drq;
38 // The last value written to the data register
39 uint8_t data_reg;
40 // Last step direction. -1 for "towards zero", 1 for "away from zero"
41 int last_step_dir;
42 // Data buffer, current DRQ pointer and length
43 uint8_t *data;
44 size_t data_pos, data_len;
45 // Current disc image file
46 FILE *disc_image;
47 // Write protect flag
48 int writeable;
49 // LBA at which to start writing
50 int write_pos;
51 // True if a format command is in progress
52 int formatting;
53 } WD2797_CTX;
55 /**
56 * @brief Initialise a WD2797 context.
57 * @param ctx WD2797 context.
58 *
59 * This must be run once when the context is created.
60 */
61 void wd2797_init(WD2797_CTX *ctx);
63 /**
64 * @brief Reset a WD2797 context.
65 * @param ctx WD2797 context.
66 *
67 * This should be run if the WD2797 needs to be reset (nRST line toggled).
68 */
69 void wd2797_reset(WD2797_CTX *ctx);
71 /**
72 * Deinitialise a WD2797 context.
73 * @param ctx WD2797 context.
74 */
75 void wd2797_done(WD2797_CTX *ctx);
77 /**
78 * @brief Read IRQ Rising Edge status. Clears Rising Edge status if it is set.
79 * @note No more IRQs will be sent until the Status Register is read, or a new command is written to the CR.
80 * @param ctx WD2797 context.
81 */
82 bool wd2797_get_irq(WD2797_CTX *ctx);
84 /**
85 * @brief Read DRQ status.
86 * @param ctx WD2797 context.
87 */
88 bool wd2797_get_drq(WD2797_CTX *ctx);
90 /**
91 * @brief Assign a disc image to the WD2797.
92 * @param ctx WD2797 context.
93 * @param fp Disc image file, already opened in "r+b" mode.
94 * @param secsz Sector size: either 128, 256, 512 or 1024.
95 * @param spt Sectors per track.
96 * @param heads Number of heads (1 or 2).
97 * @return Error code; WD279X_E_OK if everything worked OK.
98 */
99 WD2797_ERR wd2797_load(WD2797_CTX *ctx, FILE *fp, int secsz, int spt, int heads, int writeable);
101 /**
102 * @brief Deassign the current image file.
103 * @param ctx WD2797 context.
104 */
105 void wd2797_unload(WD2797_CTX *ctx);
107 /**
108 * @brief Read WD279x register.
109 * @param ctx WD2797 context
110 * @param addr Register address (0, 1, 2 or 3)
111 */
112 uint8_t wd2797_read_reg(WD2797_CTX *ctx, uint8_t addr);
114 /**
115 * @brief Write WD279X register
116 * @param ctx WD2797 context
117 * @param addr Register address (0, 1, 2 or 3)
118 * @param val Value to write
119 */
120 void wd2797_write_reg(WD2797_CTX *ctx, uint8_t addr, uint8_t val);
122 void wd2797_dma_miss(WD2797_CTX *ctx);
123 #endif