2 Copyright © 2009-2017, The AROS Development Team. All rights reserved.
5 Desc: functions for memory-stored RawIOInit/RawPutChar
9 #include <proto/exec.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";
26 ULONG length
; /* number of data bytes that follow */
31 struct SignalSemaphore lock
;
32 struct MinList buffers
;
33 struct LogBlock
*block
;
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***********************************************************************
50 AROS_LH0(void, MemoryRawIOInit
,
53 struct ExecBase
*, SysBase
, 84, Exec
)
56 This is a private function. It initializes raw IO. After you
57 have called this function, you can use (!RawMayGetChar()) and
67 This function is for very low level debugging only.
74 RawPutChar(), RawMayGetChar()
78 *****************************************************************************/
85 /* Initialise data struct, memory pool and semaphore */
87 data
= AllocMem(sizeof(struct LogData
), MEMF_PUBLIC
| MEMF_CLEAR
);
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
)
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
)
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
);
122 /* Create a task that will allocate buffers as needed */
125 AllocMem(sizeof(struct Task
), MEMF_PUBLIC
| MEMF_CLEAR
);
126 stack
= AllocMem(STACK_SIZE
, MEMF_PUBLIC
);
127 if (task
== NULL
|| stack
== NULL
)
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
)
150 /* Signal task to allocate the second buffer */
152 Signal(task
, SIGF_SINGLE
);
163 /*****i***********************************************************************
166 AROS_LH1(void, MemoryRawPutChar
,
169 AROS_LHA(UBYTE
, chr
, D0
),
172 struct ExecBase
*, SysBase
, 86, Exec
)
175 Emits a single character.
178 chr - The character to emit
184 This function is for very low level debugging only.
191 RawIOInit(), RawPutChar(), RawMayGetChar()
195 *****************************************************************************/
199 struct LogBlock
*new_block
;
201 /* Write to screen/serial as well */
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 */
211 if ((new_block
= next_block
) != NULL
)
215 if (new_block
!= NULL
)
217 data
->block
= new_block
;
220 /* If data was missed, add a warning to the log */
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
);
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
;
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
);
265 block
->length
= BLOCK_SIZE
- sizeof(struct LogBlock
);
271 ObtainSemaphore(&data
->lock
);
272 AddTail((struct List
*)&data
->buffers
, (struct Node
*)block
);
273 ReleaseSemaphore(&data
->lock
);