Wed, 16 Jan 2013 00:34:11 +0000
[wd2010] use size_t for init filesize, make disc init more verbose
philpem@48 | 1 | #ifndef _WD279X_H |
philpem@48 | 2 | #define _WD279X_H |
philpem@48 | 3 | |
philpem@48 | 4 | #include <stdbool.h> |
philpem@48 | 5 | #include <stddef.h> |
philpem@48 | 6 | #include <stdint.h> |
philpem@48 | 7 | #include <stdio.h> |
philpem@48 | 8 | |
philpem@49 | 9 | /// WD279x registers |
philpem@49 | 10 | typedef enum { |
philpem@49 | 11 | WD2797_REG_STATUS = 0, ///< Status register |
philpem@49 | 12 | WD2797_REG_COMMAND = 0, ///< Command register |
philpem@49 | 13 | WD2797_REG_TRACK = 1, ///< Track register |
philpem@49 | 14 | WD2797_REG_SECTOR = 2, ///< Sector register |
philpem@49 | 15 | WD2797_REG_DATA = 3 ///< Data register |
philpem@49 | 16 | } WD2797_REG; |
philpem@49 | 17 | |
philpem@49 | 18 | /// WD279x emulator error codes |
philpem@49 | 19 | typedef enum { |
philpem@49 | 20 | WD2797_ERR_OK = 0, ///< Operation succeeded |
philpem@49 | 21 | WD2797_ERR_BAD_GEOM = -1, ///< Bad geometry, or image file too small |
philpem@49 | 22 | WD2797_ERR_NO_MEMORY = -2 ///< Out of memory |
philpem@49 | 23 | } WD2797_ERR; |
philpem@48 | 24 | |
philpem@48 | 25 | typedef struct { |
philpem@48 | 26 | // Current track, head and sector |
philpem@48 | 27 | int track, head, sector; |
philpem@111 | 28 | // Track and sector registers |
philpem@111 | 29 | int track_reg, sector_reg; |
philpem@48 | 30 | // Geometry of current disc |
philpem@48 | 31 | int geom_secsz, geom_spt, geom_heads, geom_tracks; |
philpem@79 | 32 | // IRQ status |
philpem@79 | 33 | bool irq; |
philpem@48 | 34 | // Status of last command |
philpem@48 | 35 | uint8_t status; |
philpem@48 | 36 | // Last command uses DRQ bit? |
philpem@48 | 37 | bool cmd_has_drq; |
philpem@48 | 38 | // The last value written to the data register |
philpem@48 | 39 | uint8_t data_reg; |
philpem@48 | 40 | // Last step direction. -1 for "towards zero", 1 for "away from zero" |
philpem@48 | 41 | int last_step_dir; |
philpem@48 | 42 | // Data buffer, current DRQ pointer and length |
philpem@49 | 43 | uint8_t *data; |
philpem@48 | 44 | size_t data_pos, data_len; |
philpem@48 | 45 | // Current disc image file |
philpem@48 | 46 | FILE *disc_image; |
philpem@111 | 47 | // Write protect flag |
philpem@111 | 48 | int writeable; |
philpem@111 | 49 | // LBA at which to start writing |
philpem@111 | 50 | int write_pos; |
philpem@111 | 51 | // True if a format command is in progress |
philpem@111 | 52 | int formatting; |
philpem@49 | 53 | } WD2797_CTX; |
philpem@49 | 54 | |
philpem@49 | 55 | /** |
philpem@49 | 56 | * @brief Initialise a WD2797 context. |
philpem@49 | 57 | * @param ctx WD2797 context. |
philpem@49 | 58 | * |
philpem@49 | 59 | * This must be run once when the context is created. |
philpem@49 | 60 | */ |
philpem@49 | 61 | void wd2797_init(WD2797_CTX *ctx); |
philpem@49 | 62 | |
philpem@49 | 63 | /** |
philpem@49 | 64 | * @brief Reset a WD2797 context. |
philpem@49 | 65 | * @param ctx WD2797 context. |
philpem@49 | 66 | * |
philpem@49 | 67 | * This should be run if the WD2797 needs to be reset (nRST line toggled). |
philpem@49 | 68 | */ |
philpem@49 | 69 | void wd2797_reset(WD2797_CTX *ctx); |
philpem@49 | 70 | |
philpem@49 | 71 | /** |
philpem@49 | 72 | * Deinitialise a WD2797 context. |
philpem@49 | 73 | * @param ctx WD2797 context. |
philpem@49 | 74 | */ |
philpem@49 | 75 | void wd2797_done(WD2797_CTX *ctx); |
philpem@49 | 76 | |
philpem@49 | 77 | /** |
philpem@49 | 78 | * @brief Read IRQ Rising Edge status. Clears Rising Edge status if it is set. |
philpem@49 | 79 | * @note No more IRQs will be sent until the Status Register is read, or a new command is written to the CR. |
philpem@49 | 80 | * @param ctx WD2797 context. |
philpem@49 | 81 | */ |
philpem@49 | 82 | bool wd2797_get_irq(WD2797_CTX *ctx); |
philpem@49 | 83 | |
philpem@49 | 84 | /** |
philpem@49 | 85 | * @brief Read DRQ status. |
philpem@49 | 86 | * @param ctx WD2797 context. |
philpem@49 | 87 | */ |
philpem@49 | 88 | bool wd2797_get_drq(WD2797_CTX *ctx); |
philpem@49 | 89 | |
philpem@49 | 90 | /** |
philpem@49 | 91 | * @brief Assign a disc image to the WD2797. |
philpem@49 | 92 | * @param ctx WD2797 context. |
philpem@49 | 93 | * @param fp Disc image file, already opened in "r+b" mode. |
philpem@49 | 94 | * @param secsz Sector size: either 128, 256, 512 or 1024. |
philpem@49 | 95 | * @param spt Sectors per track. |
philpem@49 | 96 | * @param heads Number of heads (1 or 2). |
philpem@49 | 97 | * @return Error code; WD279X_E_OK if everything worked OK. |
philpem@49 | 98 | */ |
philpem@111 | 99 | WD2797_ERR wd2797_load(WD2797_CTX *ctx, FILE *fp, int secsz, int spt, int heads, int writeable); |
philpem@49 | 100 | |
philpem@49 | 101 | /** |
philpem@49 | 102 | * @brief Deassign the current image file. |
philpem@49 | 103 | * @param ctx WD2797 context. |
philpem@49 | 104 | */ |
philpem@49 | 105 | void wd2797_unload(WD2797_CTX *ctx); |
philpem@49 | 106 | |
philpem@49 | 107 | /** |
philpem@49 | 108 | * @brief Read WD279x register. |
philpem@49 | 109 | * @param ctx WD2797 context |
philpem@49 | 110 | * @param addr Register address (0, 1, 2 or 3) |
philpem@49 | 111 | */ |
philpem@49 | 112 | uint8_t wd2797_read_reg(WD2797_CTX *ctx, uint8_t addr); |
philpem@49 | 113 | |
philpem@49 | 114 | /** |
philpem@49 | 115 | * @brief Write WD279X register |
philpem@49 | 116 | * @param ctx WD2797 context |
philpem@49 | 117 | * @param addr Register address (0, 1, 2 or 3) |
philpem@49 | 118 | * @param val Value to write |
philpem@49 | 119 | */ |
philpem@49 | 120 | void wd2797_write_reg(WD2797_CTX *ctx, uint8_t addr, uint8_t val); |
philpem@49 | 121 | |
philpem@111 | 122 | void wd2797_dma_miss(WD2797_CTX *ctx); |
philpem@48 | 123 | #endif |