revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / diskimage / plugins / ipf.c
bloba1cab2c0caa411e02b547a3e4c0b164fd56d5ffd
1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
2 **
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
5 ** are met:
6 **
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
9 **
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
27 #define USED_PLUGIN_API_VERSION 8
28 #include <devices/diskimage.h>
29 #include <caps/capsimage.h>
30 #include <proto/exec.h>
31 #include <proto/dos.h>
32 #include <proto/capsimage.h>
33 #include "device_locale.h"
34 #include "endian.h"
35 #include <SDI_compiler.h>
36 #include "rev/diskimage.device_rev.h"
38 PLUGIN_VERSTAG("IPF")
40 extern struct DiskImagePlugin ipf_plugin;
42 PLUGIN_TABLE(&ipf_plugin)
44 struct IPFImage {
45 CapsLong id, lock;
46 UBYTE track_sectors;
47 struct CapsImageInfo image_info;
48 struct CapsTrackInfoT1 track_info;
49 struct MsgPort *caps_mp;
50 struct IORequest *caps_io;
51 struct Device *capsimagebase;
52 CapsLong caps_init;
55 BOOL IPF_Init (struct DiskImagePlugin *Self, const struct PluginData *data);
56 BOOL IPF_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
57 const UBYTE *test, LONG testsize);
58 APTR IPF_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file, CONST_STRPTR name);
59 void IPF_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr);
60 LONG IPF_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg);
61 LONG IPF_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io);
62 static LONG CAPSError (LONG error);
64 struct DiskImagePlugin ipf_plugin = {
65 PLUGIN_NODE(0, "IPF"),
66 PLUGIN_FLAG_M68K,
68 ZERO,
69 NULL,
70 IPF_Init,
71 NULL,
72 IPF_CheckImage,
73 IPF_OpenImage,
74 IPF_CloseImage,
75 IPF_Geometry,
76 IPF_Read,
77 NULL,
78 NULL,
79 NULL,
80 NULL,
81 NULL
84 static struct Library *SysBase;
85 static struct Library *DOSBase;
86 static struct DIPluginIFace *IPlugin;
88 BOOL IPF_Init (struct DiskImagePlugin *Self, const struct PluginData *data) {
89 SysBase = data->SysBase;
90 DOSBase = data->DOSBase;
91 IPlugin = data->IPlugin;
92 return TRUE;
95 #define IPF_MAGIC MAKE_ID('C','A','P','S')
97 BOOL IPF_CheckImage (struct DiskImagePlugin *Self, BPTR file, CONST_STRPTR name, QUAD file_size,
98 const UBYTE *test, LONG testsize)
100 return testsize >= sizeof(ULONG) && rbe32(test) == IPF_MAGIC;
103 APTR IPF_OpenImage (struct DiskImagePlugin *Self, APTR unit, BPTR file,
104 CONST_STRPTR name)
106 LONG done = FALSE;
107 LONG error = NO_ERROR;
108 LONG error_string = NO_ERROR_STRING;
109 IPTR error_args[4] = {0};
110 struct IPFImage *image = NULL;
111 struct Device *CapsImageBase;
112 CapsLong caps_err;
114 Close(file);
116 image = AllocVec(sizeof(*image), MEMF_ANY);
117 if (!image) {
118 error = ERROR_NO_FREE_STORE;
119 goto error;
121 image->id = -1;
123 image->caps_mp = CreateMsgPort();
124 image->caps_io = CreateIORequest(image->caps_mp, sizeof(struct IORequest));
125 if (!image->caps_io) {
126 error = ERROR_NO_FREE_STORE;
127 goto error;
130 if (OpenDevice("capsimage.device", 0, image->caps_io, 0) != IOERR_SUCCESS) {
131 error = ERROR_OBJECT_NOT_FOUND;
132 error_string = MSG_REQ;
133 error_args[0] = (IPTR)"capsimage.device";
134 goto error;
136 image->capsimagebase = image->caps_io->io_Device;
137 CapsImageBase = image->capsimagebase;
139 image->caps_init = CAPSInit();
140 if (image->caps_init != imgeOk) {
141 error = ERROR_NO_FREE_STORE;
142 goto error;
145 image->id = CAPSAddImage();
146 if (image->id < 0) {
147 error = ERROR_NO_FREE_STORE;
148 goto error;
150 image->lock = CAPSLockImage(image->id, name);
151 if (image->lock != imgeOk) {
152 error = ERROR_OBJECT_WRONG_TYPE;
153 error_string = MSG_CAPSERR;
154 goto error;
156 caps_err = CAPSGetImageInfo(&image->image_info, image->id);
157 if (caps_err != imgeOk) {
158 error = ERROR_OBJECT_WRONG_TYPE;
159 error_string = MSG_CAPSERR;
160 goto error;
162 image->track_info.cylinder = -1;
163 image->track_info.head = -1;
164 image->track_sectors = 11;
166 done = TRUE;
168 error:
169 if (!done) {
170 if (image) {
171 Plugin_CloseImage(Self, image);
172 image = NULL;
174 IPlugin_SetDiskImageErrorA(unit, error, error_string, error_args);
176 return image;
179 void IPF_CloseImage (struct DiskImagePlugin *Self, APTR image_ptr) {
180 struct IPFImage *image = image_ptr;
181 if (image) {
182 if (image->capsimagebase) {
183 struct Device *CapsImageBase = image->capsimagebase;
184 if (image->caps_init == imgeOk) {
185 if (image->id >= 0) {
186 if (image->lock == imgeOk) {
187 CAPSUnlockImage(image->id);
189 CAPSRemImage(image->id);
191 CAPSExit();
193 CloseDevice(image->caps_io);
195 DeleteIORequest(image->caps_io);
196 DeleteMsgPort(image->caps_mp);
197 FreeVec(image);
201 LONG IPF_Geometry (struct DiskImagePlugin *Self, APTR image_ptr, struct DriveGeometry *dg) {
202 struct IPFImage *image = image_ptr;
203 dg->dg_Cylinders = 80;
204 dg->dg_Heads = 2;
205 dg->dg_TrackSectors = image->track_sectors;
206 dg->dg_CylSectors = dg->dg_TrackSectors << 1;
207 dg->dg_TotalSectors = dg->dg_CylSectors * 80;
208 return IOERR_SUCCESS;
211 static LONG read_sector (UBYTE *buf, int track, int sector, UWORD *data, LONG len);
212 static UWORD getmfmword (const UWORD *mbuf, ULONG shift);
213 static ULONG getmfmlong (const UWORD *mbuf, ULONG shift);
215 static const CapsULong caps_flags = DI_LOCK_DENVAR|DI_LOCK_DENNOISE|DI_LOCK_NOISE|DI_LOCK_UPDATEFD|DI_LOCK_TYPE;
217 LONG IPF_Read (struct DiskImagePlugin *Self, APTR image_ptr, struct IOStdReq *io) {
218 struct IPFImage *image = image_ptr;
219 struct Device *CapsImageBase = image->capsimagebase;
220 UBYTE *buffer;
221 ULONG offset, size;
222 LONG track, cyl, head, block, sectors;
223 CapsLong id = image->id;
224 struct CapsTrackInfoT1 *ti = &image->track_info;
225 CapsLong caps_err;
226 LONG err;
228 buffer = io->io_Data;
229 offset = io->io_Offset;
230 size = io->io_Length;
231 io->io_Actual = 0;
233 if (offset & 511) return IOERR_BADADDRESS;
234 if (size & 511) return IOERR_BADLENGTH;
236 offset >>= 9;
237 size >>= 9;
239 sectors = image->track_sectors;
240 track = offset / sectors;
241 block = offset % sectors;
243 while (size) {
244 cyl = track >> 1;
245 head = track & 1;
246 ti->type = 1;
247 caps_err = CAPSLockTrack((struct CapsTrackInfo *)ti, id, cyl, head, caps_flags);
248 if (caps_err != imgeOk) return CAPSError(caps_err);
250 for (; size && block < sectors; block++, size--) {
251 err = read_sector(buffer, track, block, (UWORD *)ti->trackbuf, ti->tracklen);
252 if (err != IOERR_SUCCESS) {
253 CAPSUnlockTrack(id, cyl, head);
254 return err;
256 buffer += 512;
257 io->io_Actual += 512;
260 CAPSUnlockTrack(id, cyl, head);
261 block = 0;
262 track++;
264 return IOERR_SUCCESS;
267 static LONG CAPSError (LONG error) {
268 switch (error) {
269 case imgeOk:
270 return IOERR_SUCCESS;
271 default:
272 return TDERR_NotSpecified;
276 static LONG read_sector (UBYTE *buf, int track, int sector, UWORD *data, LONG len) {
277 ULONG shift = 0;
278 ULONG odd, even, chksum, id, dlong;
279 UWORD *end;
280 ULONG i;
282 end = data + ((len+1) >> 1);
283 end -= 540;
285 while (data <= end) {
286 while (getmfmword(data, shift) != 0x4489) {
287 if (data >= end) {
288 return TDERR_NoSecHdr;
290 shift++;
291 if (shift == 16) {
292 shift = 0;
293 data++;
296 while (getmfmword(data, shift) == 0x4489) {
297 if (data >= end) return TDERR_BadSecPreamble;
298 data++;
301 odd = getmfmlong(data, shift);
302 even = getmfmlong(data + 2, shift);
303 data += 4;
304 id = (odd << 1)|even;
305 chksum = odd ^ even;
306 for (i = 0; i < 4; i++) {
307 odd = getmfmlong(data, shift);
308 even = getmfmlong(data + 8, shift);
309 data += 2;
311 dlong = (odd << 1)|even;
312 chksum ^= odd ^ even;
314 data += 8;
315 odd = getmfmlong(data, shift);
316 even = getmfmlong(data + 2, shift);
317 data += 4;
318 if (((odd << 1)|even) != chksum ||
319 ((id & 0xff000000) >> 24) != 0xff ||
320 ((id & 0x00ff0000) >> 16) != track)
322 return TDERR_BadSecHdr;
325 odd = getmfmlong(data, shift);
326 even = getmfmlong(data + 2, shift);
327 data += 4;
328 chksum = (odd << 1)|even;
329 if (((id & 0x0000ff00) >> 8) == sector) {
330 for (i = 0; i < 128; i++) {
331 odd = getmfmlong(data, shift);
332 even = getmfmlong(data + 256, shift);
333 data += 2;
334 dlong = (odd << 1)|even;
335 wbe32(buf, dlong);
336 buf += 4;
337 chksum ^= odd ^ even;
339 if (chksum) {
340 return TDERR_BadSecSum;
342 return IOERR_SUCCESS;
344 data += 512;
347 return TDERR_NoSecHdr;
350 #define MFMMASK 0x55555555
352 static UWORD getmfmword (const UWORD *mbuf, ULONG shift) {
353 return (rbe16(&mbuf[0]) << shift) | (rbe16(&mbuf[1]) >> (16 - shift));
356 static ULONG getmfmlong (const UWORD *mbuf, ULONG shift) {
357 return ((getmfmword (mbuf, shift) << 16) | getmfmword (mbuf + 1, shift)) & MFMMASK;