Wed, 16 Jan 2013 00:41:51 +0000
fix default HDD sectors-per-track
The 64MB Micropolis drive we're trying to emulate in FreeBee has 17 sectors
per track. Fix this in main.c to avoid tripping the sector range checks.
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@116 | 11 | WD2010_REG_ERROR = 1, ///< Error register |
philpem@116 | 12 | WD2010_REG_WRITE_PRECOMP_CYLINDER = 1, ///< Write precompensation cylinder register |
philpem@116 | 13 | WD2010_REG_SECTOR_COUNT = 2, ///< Sector count register |
philpem@116 | 14 | WD2010_REG_SECTOR_NUMBER = 3, ///< Sector number register |
philpem@116 | 15 | WD2010_REG_CYLINDER_LOW = 4, ///< Low byte of cylinder |
philpem@116 | 16 | WD2010_REG_CYLINDER_HIGH = 5, ///< High byte of cylinder |
philpem@116 | 17 | WD2010_REG_SDH = 6, ///< Sector size, drive, and head |
philpem@116 | 18 | WD2010_REG_STATUS = 7, ///< Status register |
philpem@116 | 19 | WD2010_REG_COMMAND = 7, ///< Command register |
philpem@116 | 20 | UNIXPC_REG_MCR2 = 255 ///< UNIX-PC MCR2 register (special!) |
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@116 | 45 | // MCR2 register (LSB is HDSEL3 - head select bit 3) |
philpem@116 | 46 | bool mcr2_hdsel3, mcr2_ddrive1; |
philpem@112 | 47 | // Sector number and count registers |
philpem@112 | 48 | int sector_number, sector_count; |
philpem@112 | 49 | // Last command has the multiple sector flag set? |
philpem@112 | 50 | bool multi_sector; |
philpem@112 | 51 | // Last command uses DRQ bit? |
philpem@112 | 52 | bool cmd_has_drq; |
philpem@112 | 53 | // Current write is a format? |
philpem@112 | 54 | bool formatting; |
philpem@112 | 55 | // Data buffer, current DRQ pointer and length |
philpem@112 | 56 | uint8_t *data; |
philpem@112 | 57 | size_t data_pos, data_len; |
philpem@112 | 58 | // Current disc image file |
philpem@112 | 59 | FILE *disc_image; |
philpem@112 | 60 | // LBA at which to start writing |
philpem@112 | 61 | int write_pos; |
philpem@112 | 62 | // Flag to allow delaying DRQ |
philpem@112 | 63 | bool drq; |
philpem@112 | 64 | } WD2010_CTX; |
philpem@112 | 65 | |
philpem@112 | 66 | /** |
philpem@112 | 67 | * @brief Initialise a WD2010 context. |
philpem@112 | 68 | * @param ctx WD2010 context. |
philpem@112 | 69 | * |
philpem@112 | 70 | * This must be run once when the context is created. |
philpem@112 | 71 | */ |
philpem@112 | 72 | int wd2010_init(WD2010_CTX *ctx, FILE *fp, int secsz, int spt, int heads); |
philpem@112 | 73 | |
philpem@112 | 74 | /** |
philpem@112 | 75 | * @brief Reset a WD2010 context. |
philpem@112 | 76 | * @param ctx WD2010 context. |
philpem@112 | 77 | * |
philpem@112 | 78 | * This should be run if the WD2010 needs to be reset (MR/ line toggled). |
philpem@112 | 79 | */ |
philpem@112 | 80 | void wd2010_reset(WD2010_CTX *ctx); |
philpem@112 | 81 | |
philpem@112 | 82 | /** |
philpem@112 | 83 | * Deinitialise a WD2010 context. |
philpem@112 | 84 | * @param ctx WD2010 context. |
philpem@112 | 85 | */ |
philpem@112 | 86 | void wd2010_done(WD2010_CTX *ctx); |
philpem@112 | 87 | |
philpem@112 | 88 | /** |
philpem@112 | 89 | * @brief Read IRQ Rising Edge status. |
philpem@112 | 90 | * @param ctx WD2010 context. |
philpem@112 | 91 | */ |
philpem@112 | 92 | bool wd2010_get_irq(WD2010_CTX *ctx); |
philpem@112 | 93 | |
philpem@112 | 94 | /** |
philpem@112 | 95 | * @brief Read DRQ status. |
philpem@112 | 96 | * @param ctx WD2010 context. |
philpem@112 | 97 | */ |
philpem@112 | 98 | bool wd2010_get_drq(WD2010_CTX *ctx); |
philpem@112 | 99 | |
philpem@112 | 100 | /** |
philpem@112 | 101 | * @brief Read WD2010 register. |
philpem@112 | 102 | * @param ctx WD2010 context |
philpem@112 | 103 | * @param addr Register address (0, 1, 2, 3, 4, 5, 6, 7, or 8) |
philpem@112 | 104 | */ |
philpem@112 | 105 | uint8_t wd2010_read_reg(WD2010_CTX *ctx, uint8_t addr); |
philpem@112 | 106 | |
philpem@112 | 107 | /** |
philpem@112 | 108 | * @brief Write WD2010 register |
philpem@112 | 109 | * @param ctx WD2010 context |
philpem@112 | 110 | * @param addr Register address (0, 1, 2, 3, 4, 5, 6, 7, or 8) |
philpem@112 | 111 | * @param val Value to write |
philpem@112 | 112 | */ |
philpem@112 | 113 | void wd2010_write_reg(WD2010_CTX *ctx, uint8_t addr, uint8_t val); |
philpem@112 | 114 | |
philpem@112 | 115 | /** |
philpem@112 | 116 | * @brief Read a data byte from the data buffer |
philpem@112 | 117 | * @param ctx WD2010 context |
philpem@112 | 118 | */ |
philpem@112 | 119 | uint8_t wd2010_read_data(WD2010_CTX *ctx); |
philpem@112 | 120 | |
philpem@112 | 121 | /** |
philpem@112 | 122 | * @brief Write a value to the data buffer |
philpem@112 | 123 | * @param ctx WD2010 context |
philpem@112 | 124 | * @param val Value to write |
philpem@112 | 125 | */ |
philpem@112 | 126 | void wd2010_write_data(WD2010_CTX *ctx, uint8_t val); |
philpem@112 | 127 | |
philpem@112 | 128 | void wd2010_dma_miss(WD2010_CTX *ctx); |
philpem@112 | 129 | #endif |