Mon, 14 Jan 2013 09:50:37 +0000
Max out system memory by default
Set the system memory to 2MiB base, 2MiB ext. This is a fully loaded 3B1
motherboard with a RAM expansion board. 512KiB base/no ext is the minimum
which can be specified (e.g. kernel memory map area only) but does not leave
any room for userspace. The kernel doesn't like that and doesn't handle it
gracefully...!
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