2 Copyright © 2009-2011, The AROS Development Team. All rights reserved.
5 Desc: functions for memory-stored RawIOInit/RawPutChar
9 #include <proto/exec.h>
10 #include <proto/kernel.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";
27 ULONG length
; /* number of data bytes that follow */
32 struct SignalSemaphore lock
;
33 struct MinList buffers
;
34 struct LogBlock
*block
;
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***********************************************************************
51 AROS_LH0(void, MemoryRawIOInit
,
54 struct ExecBase
*, SysBase
, 84, Exec
)
57 This is a private function. It initializes raw IO. After you
58 have called this function, you can use (!RawMayGetChar()) and
68 This function is for very low level debugging only.
75 RawPutChar(), RawMayGetChar()
79 *****************************************************************************/
86 /* Initialise data struct, memory pool and semaphore */
88 data
= AllocMem(sizeof(struct LogData
), MEMF_PUBLIC
| MEMF_CLEAR
);
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
)
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
)
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
);
123 /* Create a task that will allocate buffers as needed */
126 AllocMem(sizeof(struct Task
), MEMF_PUBLIC
| MEMF_CLEAR
);
127 stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
);
128 if (task
== NULL
|| stack
== NULL
)
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
)
151 /* Signal task to allocate the second buffer */
153 Signal(task
, SIGF_SINGLE
);
164 /*****i***********************************************************************
167 AROS_LH1(void, MemoryRawPutChar
,
170 AROS_LHA(UBYTE
, chr
, D0
),
173 struct ExecBase
*, SysBase
, 86, Exec
)
176 Emits a single character.
179 chr - The character to emit
185 This function is for very low level debugging only.
192 RawIOInit(), RawPutChar(), RawMayGetChar()
196 *****************************************************************************/
200 struct LogBlock
*new_block
;
202 /* Write to screen/serial as well */
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 */
212 if ((new_block
= next_block
) != NULL
)
216 if (new_block
!= NULL
)
218 data
->block
= new_block
;
221 /* If data was missed, add a warning to the log */
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
);
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
;
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
);
266 block
->length
= BLOCK_SIZE
- sizeof(struct LogBlock
);
272 ObtainSemaphore(&data
->lock
);
273 AddTail((struct List
*)&data
->buffers
, (struct Node
*)block
);
274 ReleaseSemaphore(&data
->lock
);