Sat, 17 Nov 2012 19:18:29 +0000
add HDD support + fixes
Patch-Author: Andrew Warkentin <andreww591!gmail>
Patch-Message-ID: <50A772FC.8020009@gmail.com>
I have added floppy write support, full hard disk emulation, and proper handling of DMA page faults to FreeBee. I also fixed the floppy step commands, changed the "force interrupt" floppy command to generate a type 1 status, and changed the DMA address counter to reset to 3fff when a transfer completes (which is what Unix seems to expect - without it, the kernel says that the floppy isn't ready). The floppy, hard disk, and DMA page fault tests all pass. Initializing hard disks and floppies also works (the geometry for both is still fixed by the size of the image, though, and format commands only appear to succeed, but they don't modify the image). Unix still doesn't run, though (it hangs after reading some sectors from the floppy).
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