revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / diskimage / device / init_aros.c
blobbae6af7d380db1b1a804d1cf3fb56e8f8c5091d1
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 // in contrast to init.c we use auto opening for AROS
29 #include "diskimage_device.h"
30 #include "progress.h"
31 #include <exec/exec.h>
32 #include <proto/exec.h>
33 #include <proto/stdc.h>
35 #include <expat.h>
37 #define DEBUG 0
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)))
63 return TRUE;
66 FreeBaseVars(libBase);
67 return FALSE;
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;
95 io->io_Unit = NULL;
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);
104 return TRUE;
107 unit = (struct DiskImageUnit *)libBase->Units->lh_Head;
108 while (unit->Node.ln_Succ) {
109 if (unit->UnitNum == unit_number) {
110 unit->OpenCnt++;
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);
118 return TRUE;
120 unit = (struct DiskImageUnit *)unit->Node.ln_Succ;
123 unit = InitUnit(libBase, unit_number);
124 if (unit) {
125 BPTR stdin, stdout;
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,
133 NP_StackSize, 32768,
134 NP_Input, stdin,
135 NP_Output, stdout,
136 NP_CurrentDir, ZERO,
137 NP_Entry, UnitProcEntry,
138 NP_Priority, 4,
139 TAG_END);
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);
155 WaitPort(replyport);
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);
169 return TRUE;
170 } else {
171 unit->UnitProc = NULL;
173 } else {
174 Close(stdin);
175 Close(stdout);
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);
192 return FALSE;
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;
215 Remove(&unit->Node);
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);
223 WaitPort(replyport);
224 GetMsg(replyport);
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);
241 return TRUE;
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);
249 if (!unit) {
250 return NULL;
253 unit->OpenCnt = 1;
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;
269 return unit;
272 FreeUnit(libBase, unit);
273 return NULL;
276 static void FreeUnit (struct DiskImageBase *libBase, struct DiskImageUnit *unit) {
277 // struct Library *SysBase = libBase->SysBase;
278 if (unit) {
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);
286 FreeVec(unit);
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);
295 return TRUE;
299 ADD2INITLIB(LibInit, 0)
300 ADD2EXPUNGELIB(LibExpunge, 0)
301 ADD2OPENDEV(LibOpen, 0)
302 ADD2CLOSEDEV(LibClose, 0)