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 __NOLIBBASE__
28 #include "diskimage_device.h"
30 #include <exec/exec.h>
31 #include <proto/exec.h>
33 // #include <proto/expat_au.h>
35 #include "rev/diskimage.device_rev.h"
37 // struct Library *SysBase;
38 // struct Library *DOSBase;
39 // struct Library *IntuitionBase;
40 // struct Library *aroscbase;
42 static void FreeBaseVars (struct DiskImageBase
*libBase
);
43 static struct DiskImageUnit
*InitUnit (struct DiskImageBase
*libBase
, ULONG unit_number
);
44 static void FreeUnit (struct DiskImageBase
*libBase
, struct DiskImageUnit
*unit
);
47 static int InitFunc(struct DiskImageBase
* libBase
)
49 if ((libBase
->UnitSemaphore
= CreateSemaphore()) &&
50 (libBase
->PluginSemaphore
= CreateSemaphore()) &&
51 (libBase
->DiskChangeSemaphore
= CreateSemaphore()) &&
52 (libBase
->Units
= CreateList(TRUE
)) &&
53 (libBase
->Plugins
= CreateList(TRUE
)) &&
54 (libBase
->ReloadPluginsHooks
= CreateList(TRUE
)) &&
55 (libBase
->DiskChangeHooks
= CreateList(TRUE
)))
60 FreeBaseVars(libBase
);
65 static void FreeBaseVars (struct DiskImageBase
*libBase
) {
66 struct Library
*SysBase
= libBase
->SysBase
;
67 DeleteList(libBase
->DiskChangeHooks
);
68 DeleteList(libBase
->ReloadPluginsHooks
);
69 DeleteList(libBase
->Plugins
);
70 DeleteList(libBase
->Units
);
71 DeleteSemaphore(libBase
->DiskChangeSemaphore
);
72 DeleteSemaphore(libBase
->PluginSemaphore
);
73 DeleteSemaphore(libBase
->UnitSemaphore
);
74 if (libBase
->IntuitionBase
) CloseLibrary(libBase
->IntuitionBase
);
75 if (libBase
->UtilityBase
) CloseLibrary(libBase
->UtilityBase
);
76 if (libBase
->DOSBase
) CloseLibrary(libBase
->DOSBase
);
79 static int OpenFunc(struct DiskImageBase
*libBase
, struct IORequest
* io
, ULONG unit_number
, ULONG flags
)
81 struct Library
*SysBase
= libBase
->SysBase
;
82 struct Library
*DOSBase
= libBase
->DOSBase
;
83 struct DiskImageUnit
*unit
;
85 /* Subtle point: any AllocMem() call can cause a call to this device's
86 expunge vector. If lib_OpenCnt is zero, the device might get expunged. */
88 ObtainSemaphore(libBase
->UnitSemaphore
);
90 io
->io_Device
= (struct Device
*)libBase
;
92 io
->io_Error
= IOERR_SUCCESS
;
94 if (unit_number
== ~0) {
95 io
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
97 libBase
->LibNode
.lib_Flags
&= ~LIBF_DELEXP
;
98 ReleaseSemaphore(libBase
->UnitSemaphore
);
100 return IOERR_SUCCESS
;
103 unit
= (struct DiskImageUnit
*)libBase
->Units
->lh_Head
;
104 while (unit
->Node
.ln_Succ
) {
105 if (unit
->UnitNum
== unit_number
) {
108 io
->io_Unit
= (struct Unit
*)unit
;
109 io
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
111 libBase
->LibNode
.lib_Flags
&= ~LIBF_DELEXP
;
112 ReleaseSemaphore(libBase
->UnitSemaphore
);
114 return IOERR_SUCCESS
;
116 unit
= (struct DiskImageUnit
*)unit
->Node
.ln_Succ
;
119 unit
= InitUnit(libBase
, unit_number
);
123 stdin
= Open("NIL:", MODE_OLDFILE
);
124 stdout
= Open("NIL:", MODE_NEWFILE
);
126 if (stdin
&& stdout
) {
127 unit
->UnitProc
= CreateNewProcTags(
128 NP_Name
, unit
->Node
.ln_Name
,
133 NP_Entry
, UnitProcEntry
,
138 if (unit
->UnitProc
) {
139 struct MsgPort
*replyport
= unit
->ReplyPort
;
140 struct DiskImageMsg
*msg
= unit
->DiskImageMsg
;
141 struct MsgPort
*port
;
143 replyport
->mp_SigTask
= FindTask(NULL
);
144 replyport
->mp_Flags
= PA_SIGNAL
;
145 msg
->dim_Unit
= unit
;
146 msg
->dim_Command
= DICMD_STARTUP
;
147 msg
->dim_Tags
= NULL
;
149 port
= GetProcMsgPort(unit
->UnitProc
);
150 PutMsg(port
, &msg
->dim_Msg
);
153 replyport
->mp_Flags
= PA_IGNORE
;
154 replyport
->mp_SigTask
= NULL
;
156 /* Check that it's not DeathMessage */
157 if (GetMsg(replyport
) == &msg
->dim_Msg
) {
158 AddTail(libBase
->Units
, &unit
->Node
);
159 io
->io_Unit
= (struct Unit
*)unit
;
160 io
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
162 libBase
->LibNode
.lib_Flags
&= ~LIBF_DELEXP
;
163 ReleaseSemaphore(libBase
->UnitSemaphore
);
165 return IOERR_SUCCESS
;
167 unit
->UnitProc
= NULL
;
174 FreeUnit(libBase
, unit
);
177 /* IMPORTANT: Mark IORequest as "complete" */
178 io
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
180 /* IMPORTANT: trash io_Device on open failure */
181 io
->io_Device
= NULL
;
183 if (io
->io_Error
== IOERR_SUCCESS
) io
->io_Error
= TDERR_NotSpecified
;
185 libBase
->LibNode
.lib_OpenCnt
--; /* End of expunge protection */
187 ReleaseSemaphore(libBase
->UnitSemaphore
);
192 static void CloseFunc(struct DiskImageBase
*libBase
, struct IORequest
*io
)
194 struct DiskImageUnit
*unit
= (struct DiskImageUnit
*)io
->io_Unit
;
196 ObtainSemaphore(libBase
->UnitSemaphore
);
198 /* IMPORTANT: make sure the IORequest is not used again
199 with a -1 in io_Device, any BeginIO() attempt will
200 immediatly halt (which is better than a subtle corruption
201 that will lead to hard-to-trace crashes!!! */
202 io
->io_Unit
= (struct Unit
*)-1;
203 io
->io_Device
= (struct Device
*)-1;
205 /* see if the unit is still in use */
206 if(unit
&& --unit
->OpenCnt
== 0) {
207 struct MsgPort
*replyport
= unit
->ReplyPort
;
208 struct DiskImageMsg
*msg
= unit
->DiskImageMsg
;
212 replyport
->mp_SigTask
= FindTask(NULL
);
213 replyport
->mp_Flags
= PA_SIGNAL
;
214 msg
->dim_Command
= DICMD_DIE
;
215 msg
->dim_Tags
= NULL
;
217 PutMsg(unit
->MsgPort
, &msg
->dim_Msg
);
221 replyport
->mp_Flags
= PA_IGNORE
;
222 replyport
->mp_SigTask
= NULL
;
224 FreeUnit(libBase
, unit
);
227 /* mark us as having one fewer openers */
228 if (--libBase
->LibNode
.lib_OpenCnt
== 0) {
229 ObtainSemaphore(libBase
->PluginSemaphore
);
230 FreePlugins(libBase
);
231 FreeLocaleInfo(SysBase
, &libBase
->LocaleInfo
);
232 ReleaseSemaphore(libBase
->PluginSemaphore
);
235 ReleaseSemaphore(libBase
->UnitSemaphore
);
238 static struct DiskImageUnit
*InitUnit (struct DiskImageBase
*libBase
, ULONG unit_number
) {
239 struct DiskImageUnit
*unit
;
240 struct Library
*SysBase
= libBase
->SysBase
;
242 unit
= AllocVec(sizeof(*unit
), MEMF_CLEAR
);
248 unit
->UnitNum
= unit_number
;
249 unit
->LibBase
= libBase
;
251 if ((unit
->Node
.ln_Name
= ASPrintf("diskimage.device unit %ld", unit_number
)) &&
252 (unit
->IOSemaphore
= CreateSemaphore()) &&
253 (unit
->MsgSemaphore
= CreateSemaphore()) &&
254 (unit
->ReplyPort
= CreatePortNoSignal()) &&
255 (unit
->DiskImageMsg
= (struct DiskImageMsg
*)CreateMsg(sizeof(*unit
->DiskImageMsg
))) &&
256 (unit
->DeathMsg
= (struct DeathMessage
*)CreateMsg(sizeof(*unit
->DeathMsg
))) &&
257 (unit
->ChangeInts
= CreateList(TRUE
)))
259 unit
->DiskImageMsg
->dim_Msg
.mn_Node
.ln_Name
= unit
->Node
.ln_Name
;
260 unit
->DeathMsg
->dm_Msg
.mn_Node
.ln_Name
= unit
->Node
.ln_Name
;
261 unit
->DiskImageMsg
->dim_Msg
.mn_ReplyPort
= unit
->ReplyPort
;
262 unit
->DeathMsg
->dm_Msg
.mn_ReplyPort
= unit
->ReplyPort
;
266 FreeUnit(libBase
, unit
);
270 static void FreeUnit (struct DiskImageBase
*libBase
, struct DiskImageUnit
*unit
) {
271 struct Library
*SysBase
= libBase
->SysBase
;
273 DeleteList(unit
->ChangeInts
);
274 DeleteMsg(&unit
->DeathMsg
->dm_Msg
);
275 DeleteMsg(&unit
->DiskImageMsg
->dim_Msg
);
276 DeletePortNoSignal(unit
->ReplyPort
);
277 DeleteSemaphore(unit
->MsgSemaphore
);
278 DeleteSemaphore(unit
->IOSemaphore
);
279 FreeVec(unit
->Node
.ln_Name
);
284 static int ExpungeFunc(struct DiskImageBase
*libBase
)
286 FreeBaseVars(libBase
);
290 ADD2INITLIB(InitFunc
, 0);
291 ADD2EXPUNGELIB(ExpungeFunc
, 0);
292 ADD2OPENLIB(OpenFunc
, 0);
293 ADD2CLOSELIB(CloseFunc
, 0);