src/wd2010.h

Sat, 17 Nov 2012 19:18:29 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 17 Nov 2012 19:18:29 +0000
changeset 112
a392eb8f9806
child 116
21521e62007f
permissions
-rw-r--r--

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).

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