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 // in contrast to init.c we use auto opening for AROS
29 #include "diskimage_device.h"
31 #include <exec/exec.h>
32 #include <proto/exec.h>
33 #include <proto/stdc.h>
38 #include <aros/debug.h>
40 static void FreeBaseVars (struct DiskImageBase
*libBase
);
41 static struct DiskImageUnit
*InitUnit (struct DiskImageBase
*libBase
, ULONG unit_number
);
42 static void FreeUnit (struct DiskImageBase
*libBase
, struct DiskImageUnit
*unit
);
44 static int LibInit(struct DiskImageBase
*libBase
)
46 D(bug("[diskimage/init] libbase %p\n", libBase
));
48 libBase
->SysBase
= (struct Library
*)SysBase
;
50 libBase
->DOSBase
= (struct Library
*)__aros_getbase_DOSBase();
51 libBase
->UtilityBase
= (struct Library
*)__aros_getbase_UtilityBase();
52 libBase
->IntuitionBase
= (struct Library
*)__aros_getbase_IntuitionBase();
53 libBase
->StdCBase
= (struct Library
*)__aros_getbase_StdCBase();
55 if ((libBase
->UnitSemaphore
= CreateSemaphore()) &&
56 (libBase
->PluginSemaphore
= CreateSemaphore()) &&
57 (libBase
->DiskChangeSemaphore
= CreateSemaphore()) &&
58 (libBase
->Units
= CreateList(TRUE
)) &&
59 (libBase
->Plugins
= CreateList(TRUE
)) &&
60 (libBase
->ReloadPluginsHooks
= CreateList(TRUE
)) &&
61 (libBase
->DiskChangeHooks
= CreateList(TRUE
)))
66 FreeBaseVars(libBase
);
70 static void FreeBaseVars (struct DiskImageBase
*libBase
) {
71 // struct Library *SysBase = libBase->SysBase;
73 DeleteList(libBase
->DiskChangeHooks
);
74 DeleteList(libBase
->ReloadPluginsHooks
);
75 DeleteList(libBase
->Plugins
);
76 DeleteList(libBase
->Units
);
77 DeleteSemaphore(libBase
->DiskChangeSemaphore
);
78 DeleteSemaphore(libBase
->PluginSemaphore
);
79 DeleteSemaphore(libBase
->UnitSemaphore
);
82 static int LibOpen(struct DiskImageBase
*libBase
, struct IORequest
*io
, ULONG unit_number
, ULONG flags
)
84 D(bug("[diskimage/open] libbase %p opencnt %d IORequest %p unit %d flags %d\n",
85 libBase
, libBase
->LibNode
.lib_OpenCnt
, io
, unit_number
, flags
));
87 struct DiskImageUnit
*unit
;
89 /* Subtle point: any AllocMem() call can cause a call to this device's
90 expunge vector. If lib_OpenCnt is zero, the device might get expunged. */
92 ObtainSemaphore(libBase
->UnitSemaphore
);
94 io
->io_Device
= (struct Device
*)libBase
;
96 io
->io_Error
= IOERR_SUCCESS
;
98 if (unit_number
== ~0) {
99 io
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
101 libBase
->LibNode
.lib_Flags
&= ~LIBF_DELEXP
;
102 ReleaseSemaphore(libBase
->UnitSemaphore
);
107 unit
= (struct DiskImageUnit
*)libBase
->Units
->lh_Head
;
108 while (unit
->Node
.ln_Succ
) {
109 if (unit
->UnitNum
== unit_number
) {
112 io
->io_Unit
= (struct Unit
*)unit
;
113 io
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
115 libBase
->LibNode
.lib_Flags
&= ~LIBF_DELEXP
;
116 ReleaseSemaphore(libBase
->UnitSemaphore
);
120 unit
= (struct DiskImageUnit
*)unit
->Node
.ln_Succ
;
123 unit
= InitUnit(libBase
, unit_number
);
127 stdin
= Open("NIL:", MODE_OLDFILE
);
128 stdout
= Open("NIL:", MODE_NEWFILE
);
130 if (stdin
&& stdout
) {
131 unit
->UnitProc
= CreateNewProcTags(
132 NP_Name
, unit
->Node
.ln_Name
,
137 NP_Entry
, UnitProcEntry
,
142 if (unit
->UnitProc
) {
143 struct MsgPort
*replyport
= unit
->ReplyPort
;
144 struct DiskImageMsg
*msg
= unit
->DiskImageMsg
;
145 struct MsgPort
*port
;
147 replyport
->mp_SigTask
= FindTask(NULL
);
148 replyport
->mp_Flags
= PA_SIGNAL
;
149 msg
->dim_Unit
= unit
;
150 msg
->dim_Command
= DICMD_STARTUP
;
151 msg
->dim_Tags
= NULL
;
153 port
= GetProcMsgPort(unit
->UnitProc
);
154 PutMsg(port
, &msg
->dim_Msg
);
157 replyport
->mp_Flags
= PA_IGNORE
;
158 replyport
->mp_SigTask
= NULL
;
160 /* Check that it's not DeathMessage */
161 if (GetMsg(replyport
) == &msg
->dim_Msg
) {
162 AddTail(libBase
->Units
, &unit
->Node
);
163 io
->io_Unit
= (struct Unit
*)unit
;
164 io
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
166 libBase
->LibNode
.lib_Flags
&= ~LIBF_DELEXP
;
167 ReleaseSemaphore(libBase
->UnitSemaphore
);
171 unit
->UnitProc
= NULL
;
178 FreeUnit(libBase
, unit
);
181 /* IMPORTANT: Mark IORequest as "complete" */
182 io
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
184 /* IMPORTANT: trash io_Device on open failure */
185 io
->io_Device
= NULL
;
187 if (io
->io_Error
== IOERR_SUCCESS
) io
->io_Error
= TDERR_NotSpecified
;
189 /* End of expunge protection */
190 ReleaseSemaphore(libBase
->UnitSemaphore
);
195 static int LibClose(struct DiskImageBase
*libBase
, struct IORequest
*io
)
197 D(bug("[diskimage/close] libbase %p IORequest %p unit %d\n", libBase
, io
, io
->io_Unit
));
199 struct DiskImageUnit
*unit
= (struct DiskImageUnit
*)io
->io_Unit
;
201 ObtainSemaphore(libBase
->UnitSemaphore
);
203 /* IMPORTANT: make sure the IORequest is not used again
204 with a -1 in io_Device, any BeginIO() attempt will
205 immediatly halt (which is better than a subtle corruption
206 that will lead to hard-to-trace crashes!!! */
207 io
->io_Unit
= (struct Unit
*)-1;
208 io
->io_Device
= (struct Device
*)-1;
210 /* see if the unit is still in use */
211 if(unit
&& --unit
->OpenCnt
== 0) {
212 struct MsgPort
*replyport
= unit
->ReplyPort
;
213 struct DiskImageMsg
*msg
= unit
->DiskImageMsg
;
217 replyport
->mp_SigTask
= FindTask(NULL
);
218 replyport
->mp_Flags
= PA_SIGNAL
;
219 msg
->dim_Command
= DICMD_DIE
;
220 msg
->dim_Tags
= NULL
;
222 PutMsg(unit
->MsgPort
, &msg
->dim_Msg
);
226 replyport
->mp_Flags
= PA_IGNORE
;
227 replyport
->mp_SigTask
= NULL
;
229 FreeUnit(libBase
, unit
);
232 if (libBase
->LibNode
.lib_OpenCnt
== 1) {
233 ObtainSemaphore(libBase
->PluginSemaphore
);
234 FreePlugins(libBase
);
235 FreeLocaleInfo(SysBase
, &libBase
->LocaleInfo
);
236 ReleaseSemaphore(libBase
->PluginSemaphore
);
239 ReleaseSemaphore(libBase
->UnitSemaphore
);
244 static struct DiskImageUnit
*InitUnit (struct DiskImageBase
*libBase
, ULONG unit_number
) {
245 struct DiskImageUnit
*unit
;
246 // struct Library *SysBase = libBase->SysBase;
248 unit
= AllocVec(sizeof(*unit
), MEMF_CLEAR
);
254 unit
->UnitNum
= unit_number
;
255 unit
->LibBase
= libBase
;
257 if ((unit
->Node
.ln_Name
= ASPrintf("diskimage.device unit %ld", unit_number
)) &&
258 (unit
->IOSemaphore
= CreateSemaphore()) &&
259 (unit
->MsgSemaphore
= CreateSemaphore()) &&
260 (unit
->ReplyPort
= CreatePortNoSignal()) &&
261 (unit
->DiskImageMsg
= (struct DiskImageMsg
*)CreateMsg(sizeof(*unit
->DiskImageMsg
))) &&
262 (unit
->DeathMsg
= (struct DeathMessage
*)CreateMsg(sizeof(*unit
->DeathMsg
))) &&
263 (unit
->ChangeInts
= CreateList(TRUE
)))
265 unit
->DiskImageMsg
->dim_Msg
.mn_Node
.ln_Name
= unit
->Node
.ln_Name
;
266 unit
->DeathMsg
->dm_Msg
.mn_Node
.ln_Name
= unit
->Node
.ln_Name
;
267 unit
->DiskImageMsg
->dim_Msg
.mn_ReplyPort
= unit
->ReplyPort
;
268 unit
->DeathMsg
->dm_Msg
.mn_ReplyPort
= unit
->ReplyPort
;
272 FreeUnit(libBase
, unit
);
276 static void FreeUnit (struct DiskImageBase
*libBase
, struct DiskImageUnit
*unit
) {
277 // struct Library *SysBase = libBase->SysBase;
279 DeleteList(unit
->ChangeInts
);
280 DeleteMsg(&unit
->DeathMsg
->dm_Msg
);
281 DeleteMsg(&unit
->DiskImageMsg
->dim_Msg
);
282 DeletePortNoSignal(unit
->ReplyPort
);
283 DeleteSemaphore(unit
->MsgSemaphore
);
284 DeleteSemaphore(unit
->IOSemaphore
);
285 FreeVec(unit
->Node
.ln_Name
);
290 static int LibExpunge(struct DiskImageBase
*libBase
)
292 D(bug("[diskimage/expunge] libbase %p opencnt %d\n", libBase
, libBase
->LibNode
.lib_OpenCnt
));
294 FreeBaseVars(libBase
);
299 ADD2INITLIB(LibInit
, 0)
300 ADD2EXPUNGELIB(LibExpunge
, 0)
301 ADD2OPENDEV(LibOpen
, 0)
302 ADD2CLOSEDEV(LibClose
, 0)