Updated PCI IDs to latest snapshot.
[tangerine.git] / rom / devs / console / console.c
bloba38ff71c6ab22e43464dab24358fffb8dcd420d2
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Console.device
6 Lang: English
7 */
9 /****************************************************************************************/
12 #include <string.h>
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"
35 #endif
37 #include "consoleif.h"
39 #include LC_LIBDEFS_FILE
41 #define SDEBUG 0
42 #define DEBUG 0
43 #include <aros/debug.h>
45 /****************************************************************************************/
47 #define NEWSTYLE_DEVICE 1
49 /****************************************************************************************/
52 /****************************************************************************************/
54 #if NEWSTYLE_DEVICE
56 static const UWORD SupportedCommands[] =
58 CMD_READ,
59 CMD_WRITE,
60 NSCMD_DEVICEQUERY,
64 #endif
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;
85 APTR stack;
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);
103 if(stack != NULL)
105 #if 1
106 struct TagItem tags[] =
108 {TASKTAG_ARG1, (IPTR)ConsoleDevice },
109 {TAG_DONE }
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;
116 #else
117 task->tc_SPReg = (UBYTE *)task->tc_SPLower + SP_OFFSET;
118 #endif
120 if(NewAddTask(task, consoleTaskEntry, NULL, tags) != NULL)
122 return ConsoleDevice;
123 /* ALL OK */
126 #else
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;
133 #else
134 task->tc_SPReg = (UBYTE *)task->tc_SPLower + SP_OFFSET + sizeof(APTR);
135 ((APTR *)(task->tc_SPLower + SP_OFFSET))[0] = ConsoleDevice;
136 #endif
138 if(AddTask(task, consoleTaskEntry, NULL) != NULL)
140 return TRUE;
141 /* ALL OK */
144 #endif
146 FreeMem(stack, COTASK_STACKSIZE);
148 FreeMem(task, sizeof(struct Task));
151 Alert(AT_DeadEnd | AN_ConsoleDev | AG_NoMemory);
152 return FALSE;
155 /****************************************************************************************/
157 static int GM_UNIQUENAME(Open)
159 LIBBASETYPEPTR ConsoleDevice,
160 struct IOStdReq *ioreq,
161 ULONG unitnum,
162 ULONG flags
165 BOOL success = FALSE;
167 /* Keep compiler happy */
168 flags=0;
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"));
175 goto open_fail;
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;
185 success = TRUE;
187 else
189 Class *classptr = NULL; /* Keep compiler happy */
191 struct TagItem conunit_tags[] =
193 {A_Console_Window, 0},
194 {TAG_DONE, 0}
197 /* Init tags */
199 conunit_tags[0].ti_Data = (IPTR)ioreq->io_Data; /* Window */
202 /* Select class of which to create console object */
203 switch (unitnum)
205 case CONU_STANDARD:
206 D(bug("Opening CONU_STANDARD console\n"));
207 classptr = STDCONCLASSPTR;
208 break;
210 case CONU_CHARMAP:
211 classptr = CHARMAPCLASSPTR;
212 break;
214 case CONU_SNIPMAP:
215 classptr = SNIPMAPCLASSPTR;
216 break;
218 default:
219 goto open_fail;
223 /* Create console object */
224 ioreq->io_Unit = (struct Unit *)NewObjectA(classptr, NULL, conunit_tags);
225 if (ioreq->io_Unit)
227 struct opAddTail add_msg;
228 success = TRUE;
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) */
242 if (!success)
243 goto open_fail;
245 return TRUE;
247 open_fail:
249 ioreq->io_Error = IOERR_OPENFAIL;
251 return FALSE;
254 /****************************************************************************************/
256 static int GM_UNIQUENAME(Close)
258 LIBBASETYPEPTR ConsoleDevice,
259 struct IORequest *ioreq
262 if (ioreq->io_Unit)
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);
274 return TRUE;
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)
289 AROS_LIBFUNC_INIT
290 LONG error=0;
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)
301 #if NEWSTYLE_DEVICE
302 case NSCMD_DEVICEQUERY:
303 if(ioreq->io_Length < ((LONG)OFFSET(NSDeviceQueryResult, SupportedCommands)) + sizeof(UWORD *))
305 ioreq->io_Error = IOERR_BADLENGTH;
307 else
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);
321 break;
322 #endif
325 case CMD_WRITE: {
326 ULONG towrite;
328 #if DEBUG
330 char *str;
331 int i;
332 str = ioreq->io_Data;
333 for (i = 0; i < ioreq->io_Length; i ++)
335 kprintf("%c\n", *str ++);
338 #endif
339 if (ioreq->io_Length == -1) {
340 towrite = strlen((STRPTR)ioreq->io_Data);
341 } else {
342 towrite = ioreq->io_Length;
346 ioreq->io_Actual = writeToConsole((struct ConUnit *)ioreq->io_Unit
347 , ioreq->io_Data
348 , towrite
349 , ConsoleDevice
352 break; }
354 case CMD_READ:
355 done_quick = FALSE;
357 break;
359 default:
360 error = IOERR_NOCMD;
361 break;
363 } /* switch (ioreq->io_Command) */
365 if (!done_quick)
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);
372 else
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");
384 AROS_LIBFUNC_EXIT
387 /****************************************************************************************/
389 AROS_LH1(LONG, abortio,
390 AROS_LHA(struct IORequest *, ioreq, A1),
391 struct ConsoleBase *, ConsoleDevice, 6, Console)
393 AROS_LIBFUNC_INIT
395 LONG ret = -1;
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);
417 ret = 0;
420 ReleaseSemaphore(&ConsoleDevice->consoleTaskLock);
422 return ret;
424 AROS_LIBFUNC_EXIT
427 /****************************************************************************************/