1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
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"
35 #include <SDI_compiler.h>
36 #include "rev/diskimage.device_rev.h"
40 extern struct DiskImagePlugin ipf_plugin
;
42 PLUGIN_TABLE(&ipf_plugin
)
47 struct CapsImageInfo image_info
;
48 struct CapsTrackInfoT1 track_info
;
49 struct MsgPort
*caps_mp
;
50 struct IORequest
*caps_io
;
51 struct Device
*capsimagebase
;
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"),
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
;
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
,
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
;
116 image
= AllocVec(sizeof(*image
), MEMF_ANY
);
118 error
= ERROR_NO_FREE_STORE
;
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
;
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";
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
;
145 image
->id
= CAPSAddImage();
147 error
= ERROR_NO_FREE_STORE
;
150 image
->lock
= CAPSLockImage(image
->id
, name
);
151 if (image
->lock
!= imgeOk
) {
152 error
= ERROR_OBJECT_WRONG_TYPE
;
153 error_string
= MSG_CAPSERR
;
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
;
162 image
->track_info
.cylinder
= -1;
163 image
->track_info
.head
= -1;
164 image
->track_sectors
= 11;
171 Plugin_CloseImage(Self
, image
);
174 IPlugin_SetDiskImageErrorA(unit
, error
, error_string
, error_args
);
179 void IPF_CloseImage (struct DiskImagePlugin
*Self
, APTR image_ptr
) {
180 struct IPFImage
*image
= image_ptr
;
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
);
193 CloseDevice(image
->caps_io
);
195 DeleteIORequest(image
->caps_io
);
196 DeleteMsgPort(image
->caps_mp
);
201 LONG
IPF_Geometry (struct DiskImagePlugin
*Self
, APTR image_ptr
, struct DriveGeometry
*dg
) {
202 struct IPFImage
*image
= image_ptr
;
203 dg
->dg_Cylinders
= 80;
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
;
222 LONG track
, cyl
, head
, block
, sectors
;
223 CapsLong id
= image
->id
;
224 struct CapsTrackInfoT1
*ti
= &image
->track_info
;
228 buffer
= io
->io_Data
;
229 offset
= io
->io_Offset
;
230 size
= io
->io_Length
;
233 if (offset
& 511) return IOERR_BADADDRESS
;
234 if (size
& 511) return IOERR_BADLENGTH
;
239 sectors
= image
->track_sectors
;
240 track
= offset
/ sectors
;
241 block
= offset
% sectors
;
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
);
257 io
->io_Actual
+= 512;
260 CAPSUnlockTrack(id
, cyl
, head
);
264 return IOERR_SUCCESS
;
267 static LONG
CAPSError (LONG error
) {
270 return IOERR_SUCCESS
;
272 return TDERR_NotSpecified
;
276 static LONG
read_sector (UBYTE
*buf
, int track
, int sector
, UWORD
*data
, LONG len
) {
278 ULONG odd
, even
, chksum
, id
, dlong
;
282 end
= data
+ ((len
+1) >> 1);
285 while (data
<= end
) {
286 while (getmfmword(data
, shift
) != 0x4489) {
288 return TDERR_NoSecHdr
;
296 while (getmfmword(data
, shift
) == 0x4489) {
297 if (data
>= end
) return TDERR_BadSecPreamble
;
301 odd
= getmfmlong(data
, shift
);
302 even
= getmfmlong(data
+ 2, shift
);
304 id
= (odd
<< 1)|even
;
306 for (i
= 0; i
< 4; i
++) {
307 odd
= getmfmlong(data
, shift
);
308 even
= getmfmlong(data
+ 8, shift
);
311 dlong
= (odd
<< 1)|even
;
312 chksum
^= odd
^ even
;
315 odd
= getmfmlong(data
, shift
);
316 even
= getmfmlong(data
+ 2, shift
);
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
);
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
);
334 dlong
= (odd
<< 1)|even
;
337 chksum
^= odd
^ even
;
340 return TDERR_BadSecSum
;
342 return IOERR_SUCCESS
;
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
;