fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
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}