fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 274 lines 5.1 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/drivers/block/blkpri.c * 7 * Created: 2017-10-28 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2017-2019 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <stdint.h> 24#include <stdlib.h> 25#include <string.h> 26 27#include <drivers/pri/pri.h> 28#include <drivers/pri/pri-img.h> 29 30#include <drivers/block/blkpri.h> 31 32 33static 34int dsk_pri_read (disk_t *dsk, void *buf, uint32_t i, uint32_t n) 35{ 36 return (1); 37} 38 39static 40int dsk_pri_write (disk_t *dsk, const void *buf, uint32_t i, uint32_t n) 41{ 42 return (1); 43} 44 45static 46int dsk_pri_save (disk_pri_t *dp) 47{ 48 if (dp->dsk.fname == NULL) { 49 return (1); 50 } 51 52 if (dp->img == NULL) { 53 return (1); 54 } 55 56 if (dsk_get_readonly (&dp->dsk)) { 57 return (1); 58 } 59 60 dp->img->readonly = 0; 61 62 if (pri_img_save (dp->dsk.fname, dp->img, dp->type)) { 63 return (1); 64 } 65 66 dp->dirty = 0; 67 68 return (0); 69} 70 71static 72int dsk_pri_commit (disk_pri_t *dp) 73{ 74 if (dp->dirty == 0) { 75 return (0); 76 } 77 78 if (dsk_pri_save (dp)) { 79 fprintf (stderr, 80 "disk %u: writing back pri image to %s failed\n", 81 dp->dsk.drive, 82 (dp->dsk.fname != NULL) ? dp->dsk.fname : "<none>" 83 ); 84 85 return (1); 86 } 87 88 return (0); 89} 90 91static 92int dsk_pri_set_msg (disk_t *dsk, const char *msg, const char *val) 93{ 94 if (strcmp (msg, "commit") == 0) { 95 return (dsk_pri_commit (dsk->ext)); 96 } 97 98 return (1); 99} 100 101static 102void dsk_pri_del (disk_t *dsk) 103{ 104 disk_pri_t *dp; 105 106 dp = dsk->ext; 107 108 dsk_pri_commit (dp); 109 110 if (dp->img != NULL) { 111 pri_img_del (dp->img); 112 } 113 114 free (dp); 115} 116 117disk_t *dsk_pri_open_fp (FILE *fp, unsigned type, int ro) 118{ 119 disk_t *dsk; 120 disk_pri_t *dp; 121 122 if ((dp = malloc (sizeof (disk_pri_t))) == NULL) { 123 return (NULL); 124 } 125 126 dsk = &dp->dsk; 127 128 dsk_init (dsk, dp, 0, 0, 0, 0); 129 dsk_set_type (dsk, PCE_DISK_PRI); 130 dsk_set_readonly (dsk, ro); 131 132 dsk->del = dsk_pri_del; 133 dsk->read = dsk_pri_read; 134 dsk->write = dsk_pri_write; 135 dsk->set_msg = dsk_pri_set_msg; 136 137 dp->dirty = 0; 138 dp->type = type; 139 140 dp->img = pri_img_load_fp (fp, type); 141 142 if (dp->img == NULL) { 143 dsk_pri_del (dsk); 144 return (NULL); 145 } 146 147 if (dp->img->readonly) { 148 dsk_set_readonly (dsk, 1); 149 } 150 151 return (dsk); 152} 153 154disk_t *dsk_pri_open (const char *fname, unsigned type, int ro) 155{ 156 disk_t *dsk; 157 FILE *fp; 158 159 if (type == PRI_FORMAT_NONE) { 160 type = pri_probe (fname); 161 162 if (type == PRI_FORMAT_NONE) { 163 type = pri_guess_type (fname); 164 } 165 } 166 167 if (type == PRI_FORMAT_NONE) { 168 return (NULL); 169 } 170 171 if (ro) { 172 fp = fopen (fname, "rb"); 173 } 174 else { 175 fp = fopen (fname, "r+b"); 176 177 if (fp == NULL) { 178 ro = 1; 179 fp = fopen (fname, "rb"); 180 } 181 } 182 183 if (fp == NULL) { 184 return (NULL); 185 } 186 187 dsk = dsk_pri_open_fp (fp, type, ro); 188 189 fclose (fp); 190 191 if (dsk == NULL) { 192 return (NULL); 193 } 194 195 dsk_set_fname (dsk, fname); 196 197 return (dsk); 198} 199 200 201static 202int dsk_pri_init_pri (pri_img_t *img, unsigned long c, unsigned long h, unsigned long s) 203{ 204 unsigned ci, hi; 205 pri_trk_t *trk; 206 207 if ((c > 65535) || (h > 65535) || (s > 65535)) { 208 return (1); 209 } 210 211 for (ci = 0; ci < c; ci++) { 212 for (hi = 0; hi < h; hi++) { 213 if ((trk = pri_img_get_track (img, ci, hi, 1)) == NULL) { 214 return (1); 215 } 216 } 217 } 218 219 return (0); 220} 221 222int dsk_pri_create_fp (FILE *fp, unsigned type, uint32_t c, uint32_t h, uint32_t s) 223{ 224 int r; 225 pri_img_t *img; 226 227 img = pri_img_new(); 228 229 if (img == NULL) { 230 return (1); 231 } 232 233 if (dsk_pri_init_pri (img, c, h, s)) { 234 pri_img_del (img); 235 return (1); 236 } 237 238 r = pri_img_save_fp (fp, img, type); 239 240 pri_img_del (img); 241 242 return (r); 243} 244 245int dsk_pri_create (const char *name, unsigned type, uint32_t c, uint32_t h, uint32_t s) 246{ 247 int r; 248 FILE *fp; 249 250 if (type == PRI_FORMAT_NONE) { 251 type = pri_guess_type (name); 252 } 253 254 if ((fp = fopen (name, "wb")) == NULL) { 255 return (1); 256 } 257 258 r = dsk_pri_create_fp (fp, type, c, h, s); 259 260 fclose (fp); 261 262 return (r); 263} 264 265 266unsigned dsk_pri_probe_fp (FILE *fp) 267{ 268 return (pri_probe_fp (fp)); 269} 270 271unsigned dsk_pri_probe (const char *fname) 272{ 273 return (pri_probe (fname)); 274}