revert between 56095 -> 55830 in arch
[AROS.git] / arch / i386-pc / exec / memoryrawio.c
blob238bb35ecfc9b21351ffaeaa367e327a06fb23c0
1 /*
2 Copyright © 2009-2017, 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>
11 #include <string.h>
13 #include "exec_intern.h"
15 #define BLOCK_SIZE (256 * 1024)
16 #define TASK_PRIORITY 0
17 #define STACK_SIZE 4096
20 static const TEXT name[] = "bifteck";
21 static const TEXT data_missed_msg[] = "<*** GAP IN DATA ***>\n";
23 struct LogBlock
25 struct MinNode node;
26 ULONG length; /* number of data bytes that follow */
29 struct LogData
31 struct SignalSemaphore lock;
32 struct MinList buffers;
33 struct LogBlock *block;
34 ULONG block_pos;
35 APTR pool;
38 void Putc(char);
39 static void LogTask();
41 static struct LogData *data;
42 static struct Task *task;
43 static BOOL data_missed = FALSE;
44 static struct LogBlock *next_block = NULL;
47 /*****i***********************************************************************
49 NAME */
50 AROS_LH0(void, MemoryRawIOInit,
52 /* LOCATION */
53 struct ExecBase *, SysBase, 84, Exec)
55 /* FUNCTION
56 This is a private function. It initializes raw IO. After you
57 have called this function, you can use (!RawMayGetChar()) and
58 RawPutChar().
60 INPUTS
61 None.
63 RESULT
64 None.
66 NOTES
67 This function is for very low level debugging only.
69 EXAMPLE
71 BUGS
73 SEE ALSO
74 RawPutChar(), RawMayGetChar()
76 INTERNALS
78 *****************************************************************************/
80 AROS_LIBFUNC_INIT
82 BOOL success = TRUE;
83 APTR stack;
85 /* Initialise data struct, memory pool and semaphore */
87 data = AllocMem(sizeof(struct LogData), MEMF_PUBLIC | MEMF_CLEAR);
88 if (data == NULL)
89 success = FALSE;
91 if (success)
93 data->pool = CreatePool(MEMF_PUBLIC, BLOCK_SIZE, BLOCK_SIZE);
94 NEWLIST(&data->buffers);
95 InitSemaphore(&data->lock);
96 data->lock.ss_Link.ln_Name = (char *)name;
97 if (data->pool == NULL)
98 success = FALSE;
102 if (success)
104 /* Allocate initial buffer */
106 data->block = (struct LogBlock *)AllocPooled(data->pool, BLOCK_SIZE);
107 data->block->length = BLOCK_SIZE - sizeof(struct LogBlock);
108 if (data->block == NULL)
109 success = FALSE;
112 if (success)
114 /* Add semaphore/data to public list along with initial buffer */
116 AddTail((struct List *)&data->buffers, (struct Node *)data->block);
117 AddSemaphore(&data->lock);
120 if (success)
122 /* Create a task that will allocate buffers as needed */
124 task =
125 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
126 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
127 if (task == NULL || stack == NULL)
128 success = FALSE;
131 if (success)
133 /* Initialise and start task */
135 task->tc_Node.ln_Type = NT_TASK;
136 task->tc_Node.ln_Pri = TASK_PRIORITY;
137 task->tc_Node.ln_Name = (char *)name;
138 task->tc_SPUpper = stack + STACK_SIZE;
139 task->tc_SPLower = stack;
140 task->tc_SPReg = stack + STACK_SIZE;
141 NEWLIST(&task->tc_MemEntry);
142 task->tc_UserData = data;
144 if (AddTask(task, LogTask, NULL) == NULL)
145 success = FALSE;
148 if (success)
150 /* Signal task to allocate the second buffer */
152 Signal(task, SIGF_SINGLE);
155 if (!success)
159 AROS_LIBFUNC_EXIT
163 /*****i***********************************************************************
165 NAME */
166 AROS_LH1(void, MemoryRawPutChar,
168 /* SYNOPSIS */
169 AROS_LHA(UBYTE, chr, D0),
171 /* LOCATION */
172 struct ExecBase *, SysBase, 86, Exec)
174 /* FUNCTION
175 Emits a single character.
177 INPUTS
178 chr - The character to emit
180 RESULT
181 None.
183 NOTES
184 This function is for very low level debugging only.
186 EXAMPLE
188 BUGS
190 SEE ALSO
191 RawIOInit(), RawPutChar(), RawMayGetChar()
193 INTERNALS
195 *****************************************************************************/
197 AROS_LIBFUNC_INIT
199 struct LogBlock *new_block;
201 /* Write to screen/serial as well */
202 KrnPutChar(chr);
204 /* Check if we need to move on to a new block */
206 if (data->block_pos == data->block->length)
208 /* Move on to the next block if it exists */
210 Disable();
211 if ((new_block = next_block) != NULL)
212 next_block = NULL;
213 Enable();
215 if (new_block != NULL)
217 data->block = new_block;
218 data->block_pos = 0;
220 /* If data was missed, add a warning to the log */
222 if (data_missed)
224 CopyMem(data_missed_msg,
225 (UBYTE *)data->block + sizeof(struct LogBlock),
226 strlen(data_missed_msg));
227 data->block_pos += strlen(data_missed_msg);
228 data_missed = FALSE;
231 /* Ask for another new block, which will hopefully be allocated
232 * by the time we need it */
234 Signal(task, SIGF_SINGLE);
238 /* Store character in buffer if there's space */
240 if (data->block_pos != data->block->length)
242 if (chr && (chr != '\03'))
244 ((UBYTE *)data->block)[sizeof(struct LogBlock) + data->block_pos++] = chr;
247 else
248 data_missed = TRUE;
250 AROS_LIBFUNC_EXIT
254 static void LogTask()
256 struct LogBlock *block;
258 /* Add a new buffer block to the list each time we're signalled */
260 while (Wait(SIGF_SINGLE))
262 block = (struct LogBlock *)AllocPooled(data->pool, BLOCK_SIZE);
263 if (block != NULL)
265 block->length = BLOCK_SIZE - sizeof(struct LogBlock);
267 Disable();
268 next_block = block;
269 Enable();
271 ObtainSemaphore(&data->lock);
272 AddTail((struct List *)&data->buffers, (struct Node *)block);
273 ReleaseSemaphore(&data->lock);