oops .. forgot to offset from objects bounds
[AROS.git] / arch / i386-pc / exec / memoryrawio.c
blobeec506e9cebd08d2b1f01aa1b68576d2927144df
1 /*
2 Copyright © 2009-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: functions for memory-stored RawIOInit/RawPutChar
6 Lang: English
7 */
9 #include <proto/exec.h>
10 #include <proto/kernel.h>
12 #include <string.h>
14 #include "exec_intern.h"
16 #define BLOCK_SIZE (256 * 1024)
17 #define TASK_PRIORITY 0
18 #define STACK_SIZE 4096
21 static const TEXT name[] = "bifteck";
22 static const TEXT data_missed_msg[] = "<*** GAP IN DATA ***>\n";
24 struct LogBlock
26 struct MinNode node;
27 ULONG length; /* number of data bytes that follow */
30 struct LogData
32 struct SignalSemaphore lock;
33 struct MinList buffers;
34 struct LogBlock *block;
35 ULONG block_pos;
36 APTR pool;
39 void Putc(char);
40 static void LogTask();
42 static struct LogData *data;
43 static struct Task *task;
44 static BOOL data_missed = FALSE;
45 static struct LogBlock *next_block = NULL;
48 /*****i***********************************************************************
50 NAME */
51 AROS_LH0(void, MemoryRawIOInit,
53 /* LOCATION */
54 struct ExecBase *, SysBase, 84, Exec)
56 /* FUNCTION
57 This is a private function. It initializes raw IO. After you
58 have called this function, you can use (!RawMayGetChar()) and
59 RawPutChar().
61 INPUTS
62 None.
64 RESULT
65 None.
67 NOTES
68 This function is for very low level debugging only.
70 EXAMPLE
72 BUGS
74 SEE ALSO
75 RawPutChar(), RawMayGetChar()
77 INTERNALS
79 *****************************************************************************/
81 AROS_LIBFUNC_INIT
83 BOOL success = TRUE;
84 APTR stack;
86 /* Initialise data struct, memory pool and semaphore */
88 data = AllocMem(sizeof(struct LogData), MEMF_PUBLIC | MEMF_CLEAR);
89 if (data == NULL)
90 success = FALSE;
92 if (success)
94 data->pool = CreatePool(MEMF_PUBLIC, BLOCK_SIZE, BLOCK_SIZE);
95 NEWLIST(&data->buffers);
96 InitSemaphore(&data->lock);
97 data->lock.ss_Link.ln_Name = (char *)name;
98 if (data->pool == NULL)
99 success = FALSE;
103 if (success)
105 /* Allocate initial buffer */
107 data->block = (struct LogBlock *)AllocPooled(data->pool, BLOCK_SIZE);
108 data->block->length = BLOCK_SIZE - sizeof(struct LogBlock);
109 if (data->block == NULL)
110 success = FALSE;
113 if (success)
115 /* Add semaphore/data to public list along with initial buffer */
117 AddTail((struct List *)&data->buffers, (struct Node *)data->block);
118 AddSemaphore(&data->lock);
121 if (success)
123 /* Create a task that will allocate buffers as needed */
125 task =
126 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
127 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
128 if (task == NULL || stack == NULL)
129 success = FALSE;
132 if (success)
134 /* Initialise and start task */
136 task->tc_Node.ln_Type = NT_TASK;
137 task->tc_Node.ln_Pri = TASK_PRIORITY;
138 task->tc_Node.ln_Name = (char *)name;
139 task->tc_SPUpper = stack + STACK_SIZE;
140 task->tc_SPLower = stack;
141 task->tc_SPReg = stack + STACK_SIZE;
142 NEWLIST(&task->tc_MemEntry);
143 task->tc_UserData = data;
145 if (AddTask(task, LogTask, NULL) == NULL)
146 success = FALSE;
149 if (success)
151 /* Signal task to allocate the second buffer */
153 Signal(task, SIGF_SINGLE);
156 if (!success)
160 AROS_LIBFUNC_EXIT
164 /*****i***********************************************************************
166 NAME */
167 AROS_LH1(void, MemoryRawPutChar,
169 /* SYNOPSIS */
170 AROS_LHA(UBYTE, chr, D0),
172 /* LOCATION */
173 struct ExecBase *, SysBase, 86, Exec)
175 /* FUNCTION
176 Emits a single character.
178 INPUTS
179 chr - The character to emit
181 RESULT
182 None.
184 NOTES
185 This function is for very low level debugging only.
187 EXAMPLE
189 BUGS
191 SEE ALSO
192 RawIOInit(), RawPutChar(), RawMayGetChar()
194 INTERNALS
196 *****************************************************************************/
198 AROS_LIBFUNC_INIT
200 struct LogBlock *new_block;
202 /* Write to screen/serial as well */
203 KrnPutChar(chr);
205 /* Check if we need to move on to a new block */
207 if (data->block_pos == data->block->length)
209 /* Move on to the next block if it exists */
211 Disable();
212 if ((new_block = next_block) != NULL)
213 next_block = NULL;
214 Enable();
216 if (new_block != NULL)
218 data->block = new_block;
219 data->block_pos = 0;
221 /* If data was missed, add a warning to the log */
223 if (data_missed)
225 CopyMem(data_missed_msg,
226 (UBYTE *)data->block + sizeof(struct LogBlock),
227 strlen(data_missed_msg));
228 data->block_pos += strlen(data_missed_msg);
229 data_missed = FALSE;
232 /* Ask for another new block, which will hopefully be allocated
233 * by the time we need it */
235 Signal(task, SIGF_SINGLE);
239 /* Store character in buffer if there's space */
241 if (data->block_pos != data->block->length)
243 if (chr && (chr != '\03'))
245 ((UBYTE *)data->block)[sizeof(struct LogBlock) + data->block_pos++] = chr;
248 else
249 data_missed = TRUE;
251 AROS_LIBFUNC_EXIT
255 static void LogTask()
257 struct LogBlock *block;
259 /* Add a new buffer block to the list each time we're signalled */
261 while (Wait(SIGF_SINGLE))
263 block = (struct LogBlock *)AllocPooled(data->pool, BLOCK_SIZE);
264 if (block != NULL)
266 block->length = BLOCK_SIZE - sizeof(struct LogBlock);
268 Disable();
269 next_block = block;
270 Enable();
272 ObtainSemaphore(&data->lock);
273 AddTail((struct List *)&data->buffers, (struct Node *)block);
274 ReleaseSemaphore(&data->lock);