Sat, 17 Nov 2012 21:28:48 +0000
ACCESS_CHECK_RD should return the right number of bits!
If the ACCESS_CHECK_RD() macro detects a page fault, it always returns a
32-bit error response ("all bus pins high"). Musashi really doesn't like it
when we pass in a 32-bit value when it expects a 16-bit one!
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
13 ///< register
14 WD2010_REG_SECTOR_COUNT = 2, ///< Sector count register
15 WD2010_REG_SECTOR_NUMBER = 3, ///< Sector number register
16 WD2010_REG_CYLINDER_LOW = 4, ///< Low byte of cylinder
17 WD2010_REG_CYLINDER_HIGH = 5, ///< High byte of cylinder
18 WD2010_REG_SDH = 6, ///< Sector size, drive, and head
19 WD2010_REG_STATUS = 7, ///< Status register
20 WD2010_REG_COMMAND = 7, ///< Command register
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 // Sector number and count registers
46 int sector_number, sector_count;
47 // Last command has the multiple sector flag set?
48 bool multi_sector;
49 // Last command uses DRQ bit?
50 bool cmd_has_drq;
51 // Current write is a format?
52 bool formatting;
53 // Data buffer, current DRQ pointer and length
54 uint8_t *data;
55 size_t data_pos, data_len;
56 // Current disc image file
57 FILE *disc_image;
58 // LBA at which to start writing
59 int write_pos;
60 // Flag to allow delaying DRQ
61 bool drq;
62 } WD2010_CTX;
64 /**
65 * @brief Initialise a WD2010 context.
66 * @param ctx WD2010 context.
67 *
68 * This must be run once when the context is created.
69 */
70 int wd2010_init(WD2010_CTX *ctx, FILE *fp, int secsz, int spt, int heads);
72 /**
73 * @brief Reset a WD2010 context.
74 * @param ctx WD2010 context.
75 *
76 * This should be run if the WD2010 needs to be reset (MR/ line toggled).
77 */
78 void wd2010_reset(WD2010_CTX *ctx);
80 /**
81 * Deinitialise a WD2010 context.
82 * @param ctx WD2010 context.
83 */
84 void wd2010_done(WD2010_CTX *ctx);
86 /**
87 * @brief Read IRQ Rising Edge status.
88 * @param ctx WD2010 context.
89 */
90 bool wd2010_get_irq(WD2010_CTX *ctx);
92 /**
93 * @brief Read DRQ status.
94 * @param ctx WD2010 context.
95 */
96 bool wd2010_get_drq(WD2010_CTX *ctx);
98 /**
99 * @brief Read WD2010 register.
100 * @param ctx WD2010 context
101 * @param addr Register address (0, 1, 2, 3, 4, 5, 6, 7, or 8)
102 */
103 uint8_t wd2010_read_reg(WD2010_CTX *ctx, uint8_t addr);
105 /**
106 * @brief Write WD2010 register
107 * @param ctx WD2010 context
108 * @param addr Register address (0, 1, 2, 3, 4, 5, 6, 7, or 8)
109 * @param val Value to write
110 */
111 void wd2010_write_reg(WD2010_CTX *ctx, uint8_t addr, uint8_t val);
113 /**
114 * @brief Read a data byte from the data buffer
115 * @param ctx WD2010 context
116 */
117 uint8_t wd2010_read_data(WD2010_CTX *ctx);
119 /**
120 * @brief Write a value to the data buffer
121 * @param ctx WD2010 context
122 * @param val Value to write
123 */
124 void wd2010_write_data(WD2010_CTX *ctx, uint8_t val);
126 void wd2010_dma_miss(WD2010_CTX *ctx);
127 #endif