2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
9 /****************************************************************************************/
14 #include <proto/exec.h>
15 #include <proto/console.h>
16 #include <proto/intuition.h>
17 #include <exec/resident.h>
18 #include <exec/errors.h>
19 #include <exec/memory.h>
20 #include <exec/initializers.h>
21 #include <devices/inputevent.h>
22 #include <devices/conunit.h>
23 #include <devices/newstyle.h>
24 #include <intuition/intuition.h>
25 #include <intuition/screens.h>
26 #include <intuition/classusr.h>
27 #include <graphics/rastport.h>
28 #include <aros/libcall.h>
29 #include <aros/symbolsets.h>
31 #include <graphics/rastport.h>
33 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
34 # include "console_gcc.h"
37 #include "consoleif.h"
39 #include LC_LIBDEFS_FILE
43 #include <aros/debug.h>
45 /****************************************************************************************/
47 #define NEWSTYLE_DEVICE 1
49 /****************************************************************************************/
52 /****************************************************************************************/
56 static const UWORD SupportedCommands
[] =
66 /****************************************************************************************/
68 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR ConsoleDevice
)
70 NEWLIST(&ConsoleDevice
->unitList
);
71 InitSemaphore(&ConsoleDevice
->unitListLock
);
72 InitSemaphore(&ConsoleDevice
->consoleTaskLock
);
74 /* Create the console classes */
75 CONSOLECLASSPTR
= makeConsoleClass(ConsoleDevice
);
76 STDCONCLASSPTR
= makeStdConClass(ConsoleDevice
);
77 if (!CONSOLECLASSPTR
|| !STDCONCLASSPTR
)
78 Alert(AT_DeadEnd
| AN_ConsoleDev
| AG_NoMemory
);
80 /* Create the console.device task. */
81 ConsoleDevice
->consoleTask
= AllocMem(sizeof(struct Task
), MEMF_CLEAR
|MEMF_PUBLIC
);
82 if(ConsoleDevice
->consoleTask
)
84 struct Task
* const task
= ConsoleDevice
->consoleTask
;
87 /* Initialise the task */
88 NEWLIST(&task
->tc_MemEntry
);
89 task
->tc_Node
.ln_Type
= NT_TASK
;
90 task
->tc_Node
.ln_Name
= "console.device";
91 task
->tc_Node
.ln_Pri
= COTASK_PRIORITY
;
93 /* Initialise Command Port now we have the task */
94 ConsoleDevice
->commandPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
95 ConsoleDevice
->commandPort
.mp_SigTask
= task
;
96 ConsoleDevice
->commandPort
.mp_Flags
= PA_SIGNAL
;
97 ConsoleDevice
->commandPort
.mp_SigBit
= 16;
98 NEWLIST(&ConsoleDevice
->commandPort
.mp_MsgList
);
100 task
->tc_SigAlloc
= 1L<<16 | SysBase
->TaskSigAlloc
;
102 stack
= AllocMem(COTASK_STACKSIZE
, MEMF_PUBLIC
);
106 struct TagItem tags
[] =
108 {TASKTAG_ARG1
, (IPTR
)ConsoleDevice
},
112 task
->tc_SPLower
= stack
;
113 task
->tc_SPUpper
= (UBYTE
*)stack
+ COTASK_STACKSIZE
;
114 #if AROS_STACK_GROWS_DOWNWARDS
115 task
->tc_SPReg
= (UBYTE
*)task
->tc_SPUpper
- SP_OFFSET
;
117 task
->tc_SPReg
= (UBYTE
*)task
->tc_SPLower
+ SP_OFFSET
;
120 if(NewAddTask(task
, consoleTaskEntry
, NULL
, tags
) != NULL
)
122 return ConsoleDevice
;
127 task
->tc_SPLower
= stack
;
128 task
->tc_SPUpper
= (UBYTE
*)stack
+ COTASK_STACKSIZE
;
130 #if AROS_STACK_GROWS_DOWNWARDS
131 task
->tc_SPReg
= (UBYTE
*)task
->tc_SPUpper
- SP_OFFSET
- sizeof(APTR
);
132 ((APTR
*)task
->tc_SPUpper
)[-1] = ConsoleDevice
;
134 task
->tc_SPReg
= (UBYTE
*)task
->tc_SPLower
+ SP_OFFSET
+ sizeof(APTR
);
135 ((APTR
*)(task
->tc_SPLower
+ SP_OFFSET
))[0] = ConsoleDevice
;
138 if(AddTask(task
, consoleTaskEntry
, NULL
) != NULL
)
146 FreeMem(stack
, COTASK_STACKSIZE
);
148 FreeMem(task
, sizeof(struct Task
));
151 Alert(AT_DeadEnd
| AN_ConsoleDev
| AG_NoMemory
);
155 /****************************************************************************************/
157 static int GM_UNIQUENAME(Open
)
159 LIBBASETYPEPTR ConsoleDevice
,
160 struct IOStdReq
*ioreq
,
165 BOOL success
= FALSE
;
167 /* Keep compiler happy */
170 EnterFunc(bug("OpenConsole()\n"));
172 if (ioreq
->io_Message
.mn_Length
< sizeof(struct IOStdReq
))
174 D(bug("console.device/open: IORequest structure passed to OpenDevice is too small!\n"));
178 if (((LONG
)unitnum
) == CONU_LIBRARY
) /* unitnum is ULONG while CONU_LIBRARY is -1 :-( */
180 D(bug("Opening CONU_LIBRARY unit\n"));
181 ioreq
->io_Device
= (struct Device
*)ConsoleDevice
;
183 /* Set io_Unit to NULL, so that CloseDevice knows this is a CONU_LIBRARY unit */
184 ioreq
->io_Unit
= NULL
;
189 Class
*classptr
= NULL
; /* Keep compiler happy */
191 struct TagItem conunit_tags
[] =
193 {A_Console_Window
, 0},
199 conunit_tags
[0].ti_Data
= (IPTR
)ioreq
->io_Data
; /* Window */
202 /* Select class of which to create console object */
206 D(bug("Opening CONU_STANDARD console\n"));
207 classptr
= STDCONCLASSPTR
;
211 classptr
= CHARMAPCLASSPTR
;
215 classptr
= SNIPMAPCLASSPTR
;
223 /* Create console object */
224 ioreq
->io_Unit
= (struct Unit
*)NewObjectA(classptr
, NULL
, conunit_tags
);
227 struct opAddTail add_msg
;
230 /* Add the newly created unit to console's list of units */
231 ObtainSemaphore(&ConsoleDevice
->unitListLock
);
233 add_msg
.MethodID
= OM_ADDTAIL
;
234 add_msg
.opat_List
= (struct List
*)&ConsoleDevice
->unitList
;
235 DoMethodA((Object
*)ioreq
->io_Unit
, (Msg
)&add_msg
);
237 ReleaseSemaphore(&ConsoleDevice
->unitListLock
);
238 } /* if (console unit created) */
240 } /* if (not CONU_LIBRARY) */
249 ioreq
->io_Error
= IOERR_OPENFAIL
;
254 /****************************************************************************************/
256 static int GM_UNIQUENAME(Close
)
258 LIBBASETYPEPTR ConsoleDevice
,
259 struct IORequest
*ioreq
264 ULONG mid
= OM_REMOVE
;
266 /* Remove the consoe from the console list */
267 ObtainSemaphore(&ConsoleDevice
->unitListLock
);
268 DoMethodA((Object
*)ioreq
->io_Unit
, (Msg
)&mid
);
269 ReleaseSemaphore(&ConsoleDevice
->unitListLock
);
271 DisposeObject((Object
*)ioreq
->io_Unit
);
277 /****************************************************************************************/
279 ADD2INITLIB(GM_UNIQUENAME(Init
),0)
280 ADD2OPENDEV(GM_UNIQUENAME(Open
),0)
281 ADD2CLOSEDEV(GM_UNIQUENAME(Close
),0)
283 /****************************************************************************************/
285 AROS_LH1(void, beginio
,
286 AROS_LHA(struct IOStdReq
*, ioreq
, A1
),
287 struct ConsoleBase
*, ConsoleDevice
, 5, Console
)
292 BOOL done_quick
= TRUE
;
294 /* WaitIO will look into this */
295 ioreq
->io_Message
.mn_Node
.ln_Type
=NT_MESSAGE
;
297 EnterFunc(bug("BeginIO(ioreq=%p)\n", ioreq
));
299 switch (ioreq
->io_Command
)
302 case NSCMD_DEVICEQUERY
:
303 if(ioreq
->io_Length
< ((LONG
)OFFSET(NSDeviceQueryResult
, SupportedCommands
)) + sizeof(UWORD
*))
305 ioreq
->io_Error
= IOERR_BADLENGTH
;
309 struct NSDeviceQueryResult
*d
;
311 d
= (struct NSDeviceQueryResult
*)ioreq
->io_Data
;
313 d
->DevQueryFormat
= 0;
314 d
->SizeAvailable
= sizeof(struct NSDeviceQueryResult
);
315 d
->DeviceType
= NSDEVTYPE_CONSOLE
;
316 d
->DeviceSubType
= 0;
317 d
->SupportedCommands
= (UWORD
*)SupportedCommands
;
319 ioreq
->io_Actual
= sizeof(struct NSDeviceQueryResult
);
332 str
= ioreq
->io_Data
;
333 for (i
= 0; i
< ioreq
->io_Length
; i
++)
335 kprintf("%c\n", *str
++);
339 if (ioreq
->io_Length
== -1) {
340 towrite
= strlen((STRPTR
)ioreq
->io_Data
);
342 towrite
= ioreq
->io_Length
;
346 ioreq
->io_Actual
= writeToConsole((struct ConUnit
*)ioreq
->io_Unit
363 } /* switch (ioreq->io_Command) */
367 /* Mark IO request to be done non-quick */
368 ioreq
->io_Flags
&= ~IOF_QUICK
;
369 /* Send to input device task */
370 PutMsg(&ConsoleDevice
->commandPort
, (struct Message
*)ioreq
);
375 /* If the quick bit is not set but the IO request was done quick,
376 ** reply the message to tell we're throgh
378 ioreq
->io_Error
= error
;
379 if (!(ioreq
->io_Flags
& IOF_QUICK
))
380 ReplyMsg (&ioreq
->io_Message
);
383 ReturnVoid("BeginIO");
387 /****************************************************************************************/
389 AROS_LH1(LONG
, abortio
,
390 AROS_LHA(struct IORequest
*, ioreq
, A1
),
391 struct ConsoleBase
*, ConsoleDevice
, 6, Console
)
397 ObtainSemaphore(&ConsoleDevice
->consoleTaskLock
);
399 /* The ioreq can either be in the ConsoleDevice->commandPort MsgPort,
400 or be in the ConsoleDevice->readRequests List, or be already done.
402 In the first two cases ln_Type will be NT_MESSAGE (= it can be
403 aborted), in the last case ln_Type will be NT_REPLYMSG (cannot
404 abort, because already done)
406 The consoleTaskLock Semaphore hopefully makes sure that there are no
407 other/"in-between" cases.
411 if (ioreq
->io_Message
.mn_Node
.ln_Type
!= NT_REPLYMSG
)
413 ioreq
->io_Error
= IOERR_ABORTED
;
414 Remove(&ioreq
->io_Message
.mn_Node
);
415 ReplyMsg(&ioreq
->io_Message
);
420 ReleaseSemaphore(&ConsoleDevice
->consoleTaskLock
);
427 /****************************************************************************************/