Thu, 11 Apr 2013 09:37:11 +0100
Check return value of fread()
1 #ifndef _WD2010_H
2 #define _WD2010_H
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <stdint.h>
7 #include <stdio.h>
9 /// WD2010 registers
10 typedef enum {
11 WD2010_REG_ERROR = 1, ///< Error register
12 WD2010_REG_WRITE_PRECOMP_CYLINDER = 1, ///< Write precompensation cylinder register
13 WD2010_REG_SECTOR_COUNT = 2, ///< Sector count register
14 WD2010_REG_SECTOR_NUMBER = 3, ///< Sector number register
15 WD2010_REG_CYLINDER_LOW = 4, ///< Low byte of cylinder
16 WD2010_REG_CYLINDER_HIGH = 5, ///< High byte of cylinder
17 WD2010_REG_SDH = 6, ///< Sector size, drive, and head
18 WD2010_REG_STATUS = 7, ///< Status register
19 WD2010_REG_COMMAND = 7, ///< Command register
20 UNIXPC_REG_MCR2 = 255 ///< UNIX-PC MCR2 register (special!)
21 } WD2010_REG;
23 /// WD2010 emulator error codes
24 typedef enum {
25 WD2010_ERR_OK = 0, ///< Operation succeeded
26 WD2010_ERR_BAD_GEOM = -1, ///< Bad geometry, or image file too small
27 WD2010_ERR_NO_MEMORY = -2 ///< Out of memory
28 } WD2010_ERR;
30 typedef struct {
31 // Current track, head and sector
32 int track, head, sector;
33 // Geometry of current disc
34 int geom_secsz, geom_spt, geom_heads, geom_tracks;
35 // IRQ status
36 bool irq;
37 // Status of last command
38 uint8_t status;
39 // Error resgister
40 uint8_t error_reg;
41 // Cylinder number registers
42 uint8_t cylinder_high_reg, cylinder_low_reg;
43 // SDH register (sets sector size, drive number, and head number)
44 uint8_t sdh;
45 // MCR2 register (LSB is HDSEL3 - head select bit 3)
46 bool mcr2_hdsel3, mcr2_ddrive1;
47 // Sector number and count registers
48 int sector_number, sector_count;
49 // Last command has the multiple sector flag set?
50 bool multi_sector;
51 // Last command uses DRQ bit?
52 bool cmd_has_drq;
53 // Current write is a format?
54 bool formatting;
55 // Data buffer, current DRQ pointer and length
56 uint8_t *data;
57 size_t data_pos, data_len;
58 // Current disc image file
59 FILE *disc_image;
60 // LBA at which to start writing
61 int write_pos;
62 // Flag to allow delaying DRQ
63 bool drq;
64 } WD2010_CTX;
66 /**
67 * @brief Initialise a WD2010 context.
68 * @param ctx WD2010 context.
69 *
70 * This must be run once when the context is created.
71 */
72 int wd2010_init(WD2010_CTX *ctx, FILE *fp, int secsz, int spt, int heads);
74 /**
75 * @brief Reset a WD2010 context.
76 * @param ctx WD2010 context.
77 *
78 * This should be run if the WD2010 needs to be reset (MR/ line toggled).
79 */
80 void wd2010_reset(WD2010_CTX *ctx);
82 /**
83 * Deinitialise a WD2010 context.
84 * @param ctx WD2010 context.
85 */
86 void wd2010_done(WD2010_CTX *ctx);
88 /**
89 * @brief Read IRQ Rising Edge status.
90 * @param ctx WD2010 context.
91 */
92 bool wd2010_get_irq(WD2010_CTX *ctx);
94 /**
95 * @brief Read DRQ status.
96 * @param ctx WD2010 context.
97 */
98 bool wd2010_get_drq(WD2010_CTX *ctx);
100 /**
101 * @brief Read WD2010 register.
102 * @param ctx WD2010 context
103 * @param addr Register address (0, 1, 2, 3, 4, 5, 6, 7, or 8)
104 */
105 uint8_t wd2010_read_reg(WD2010_CTX *ctx, uint8_t addr);
107 /**
108 * @brief Write WD2010 register
109 * @param ctx WD2010 context
110 * @param addr Register address (0, 1, 2, 3, 4, 5, 6, 7, or 8)
111 * @param val Value to write
112 */
113 void wd2010_write_reg(WD2010_CTX *ctx, uint8_t addr, uint8_t val);
115 /**
116 * @brief Read a data byte from the data buffer
117 * @param ctx WD2010 context
118 */
119 uint8_t wd2010_read_data(WD2010_CTX *ctx);
121 /**
122 * @brief Write a value to the data buffer
123 * @param ctx WD2010 context
124 * @param val Value to write
125 */
126 void wd2010_write_data(WD2010_CTX *ctx, uint8_t val);
128 void wd2010_dma_miss(WD2010_CTX *ctx);
129 #endif