Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / arch / i386-pc / exec / memoryrawio.c
blobf69276cfcc540916faa7c30ae9c8fe62a40f7086
1 /*
2 Copyright © 2009, 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>
14 #define BLOCK_SIZE (256 * 1024)
15 #define TASK_PRIORITY 0
16 #define STACK_SIZE 4096
19 static const TEXT name[] = "bifteck";
20 static const TEXT data_missed_msg[] = "<*** GAP IN DATA ***>\n";
22 struct LogBlock
24 struct MinNode node;
25 ULONG length; /* number of data bytes that follow */
28 struct LogData
30 struct SignalSemaphore lock;
31 struct MinList buffers;
32 struct LogBlock *block;
33 ULONG block_pos;
34 APTR pool;
37 void Putc(char);
38 static void LogTask();
40 static struct LogData *data;
41 static struct Task *task;
42 static BOOL data_missed = FALSE;
43 static struct LogBlock *next_block = NULL;
46 /*****i***********************************************************************
48 NAME */
49 AROS_LH0(void, MemoryRawIOInit,
51 /* LOCATION */
52 struct ExecBase *, SysBase, 84, Exec)
54 /* FUNCTION
55 This is a private function. It initializes raw IO. After you
56 have called this function, you can use (!RawMayGetChar()) and
57 RawPutChar().
59 INPUTS
60 None.
62 RESULT
63 None.
65 NOTES
66 This function is for very low level debugging only.
68 EXAMPLE
70 BUGS
72 SEE ALSO
73 RawPutChar(), RawMayGetChar()
75 INTERNALS
77 *****************************************************************************/
79 AROS_LIBFUNC_INIT
81 BOOL success = TRUE;
82 APTR stack;
84 /* Initialise data struct, memory pool and semaphore */
86 data = AllocMem(sizeof(struct LogData), MEMF_PUBLIC | MEMF_CLEAR);
87 if (data == NULL)
88 success = FALSE;
90 if (success)
92 data->pool = CreatePool(MEMF_PUBLIC, BLOCK_SIZE, BLOCK_SIZE);
93 NEWLIST(&data->buffers);
94 InitSemaphore(&data->lock);
95 data->lock.ss_Link.ln_Name = (char *)name;
96 if (data->pool == NULL)
97 success = FALSE;
101 if (success)
103 /* Allocate initial buffer */
105 data->block = (struct LogBlock *)AllocPooled(data->pool, BLOCK_SIZE);
106 data->block->length = BLOCK_SIZE - sizeof(struct LogBlock);
107 if (data->block == NULL)
108 success = FALSE;
111 if (success)
113 /* Add semaphore/data to public list along with initial buffer */
115 AddTail((struct List *)&data->buffers, (struct Node *)data->block);
116 AddSemaphore(&data->lock);
119 if (success)
121 /* Create a task that will allocate buffers as needed */
123 task =
124 AllocMem(sizeof(struct Task), MEMF_PUBLIC | MEMF_CLEAR);
125 stack = AllocMem(STACK_SIZE, MEMF_PUBLIC);
126 if (task == NULL || stack == NULL)
127 success = FALSE;
130 if (success)
132 /* Initialise and start task */
134 task->tc_Node.ln_Type = NT_TASK;
135 task->tc_Node.ln_Pri = TASK_PRIORITY;
136 task->tc_Node.ln_Name = (char *)name;
137 task->tc_SPUpper = stack + STACK_SIZE;
138 task->tc_SPLower = stack;
139 task->tc_SPReg = stack + STACK_SIZE;
140 NEWLIST(&task->tc_MemEntry);
141 task->tc_UserData = data;
143 if (AddTask(task, LogTask, NULL) == NULL)
144 success = FALSE;
147 if (success)
149 /* Signal task to allocate the second buffer */
151 Signal(task, SIGF_SINGLE);
154 if (!success)
158 AROS_LIBFUNC_EXIT
162 /*****i***********************************************************************
164 NAME */
165 AROS_LH1(void, MemoryRawPutChar,
167 /* SYNOPSIS */
168 AROS_LHA(UBYTE, chr, D0),
170 /* LOCATION */
171 struct ExecBase *, SysBase, 86, Exec)
173 /* FUNCTION
174 Emits a single character.
176 INPUTS
177 chr - The character to emit
179 RESULT
180 None.
182 NOTES
183 This function is for very low level debugging only.
185 EXAMPLE
187 BUGS
189 SEE ALSO
190 RawIOInit(), RawPutChar(), RawMayGetChar()
192 INTERNALS
194 *****************************************************************************/
196 AROS_LIBFUNC_INIT
198 struct LogBlock *new_block;
200 /* Write to screen as well */
202 Putc(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 != '\03')
243 ((UBYTE *)data->block)[sizeof(struct LogBlock) + data->block_pos++] =
244 chr;
246 else
247 data_missed = TRUE;
249 AROS_LIBFUNC_EXIT
253 static void LogTask()
255 struct LogBlock *block;
257 /* Add a new buffer block to the list each time we're signalled */
259 while (Wait(SIGF_SINGLE))
261 block = (struct LogBlock *)AllocPooled(data->pool, BLOCK_SIZE);
262 if (block != NULL)
264 block->length = BLOCK_SIZE - sizeof(struct LogBlock);
266 Disable();
267 next_block = block;
268 Enable();
270 ObtainSemaphore(&data->lock);
271 AddTail((struct List *)&data->buffers, (struct Node *)block);
272 ReleaseSemaphore(&data->lock);