WIP build diskimage device with %build_module.
[AROS.git] / workbench / devs / diskimage / device / init_aros.c
blobc62b441ab490223fad657a2d9e7e52d0e9aea3b2
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 __NOLIBBASE__
28 #include "diskimage_device.h"
29 #include "progress.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)))
57 return TRUE;
60 FreeBaseVars(libBase);
62 return FALSE;
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;
91 io->io_Unit = NULL;
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) {
106 unit->OpenCnt++;
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);
120 if (unit) {
121 BPTR stdin, stdout;
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,
129 NP_StackSize, 32768,
130 NP_Input, stdin,
131 NP_Output, stdout,
132 NP_CurrentDir, ZERO,
133 NP_Entry, UnitProcEntry,
134 NP_Priority, 4,
135 TAG_END);
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);
151 WaitPort(replyport);
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;
166 } else {
167 unit->UnitProc = NULL;
169 } else {
170 Close(stdin);
171 Close(stdout);
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);
189 return io->io_Error;
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;
210 Remove(&unit->Node);
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);
218 WaitPort(replyport);
219 GetMsg(replyport);
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);
243 if (!unit) {
244 return NULL;
247 unit->OpenCnt = 1;
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;
263 return unit;
266 FreeUnit(libBase, unit);
267 return NULL;
270 static void FreeUnit (struct DiskImageBase *libBase, struct DiskImageUnit *unit) {
271 struct Library *SysBase = libBase->SysBase;
272 if (unit) {
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);
280 FreeVec(unit);
284 static int ExpungeFunc(struct DiskImageBase *libBase)
286 FreeBaseVars(libBase);
287 return TRUE;
290 ADD2INITLIB(InitFunc, 0);
291 ADD2EXPUNGELIB(ExpungeFunc, 0);
292 ADD2OPENLIB(OpenFunc, 0);
293 ADD2CLOSELIB(CloseFunc, 0);