-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathREADME-CODING-IO.txt
67 lines (47 loc) · 2.42 KB
/
README-CODING-IO.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
To code for nd100em this document gives some information on
how to add functionality easily to the emulator.
IO functionality is basically done in two steps. The main
cpu threads executes IOX calls and thus for a device you
need a function for these IOX calls that return suitable
values or sets variables for the device. The actual device
then runs as a separate thread and does the real work.
To avoid race conditions we use a semaphore whenever we
access information in the common device structure created for
that device.
To add a new thread there is basically 2 functions we need
to consider:
pthread_t add_thread(void *funcpointer, bool is_jointype);
void start_threads(void);
The first one is the one actually initializing and starting the
thread, and the second is the main point where the emulator starts
all needed threads. This is where we would add a new device thread.
add_thread is called with two parameters:
* a pointer to our function, which from now on will run as a separate thread.
* and a boolean variable that if true tells the emulator the thread
be waited for to join when it quits. If zero it is instead killed.
For example, the main cpu routine thread addition looks like this:
thread_id = add_thread(&cpu_thread,1);
if (debug) fprintf(debugfile,"Added thread id: %d as cpu_thread\n",thread_id);
if (debug) fflush(debugfile);
The main functionality for the cpu thread is done in another way.
Basically we have one array of 64k containing functionpointers:
void (*ioarr[65536])(ushort);
They are default initialised to a default function that fails
the IOX call after ~ 10uSec, as per real ND100 behaviour:
void Default_IO(ushort ioadd);
The routine that adds new IOX "device" functions is:
void Setup_IO_Handlers ();
We can take an example from currently added devices, the
onboard rtc on the cpu clock. It resides at IOX 10-13 octal,
and to add that one we have in the above routine:
IO_Handler_Add(8,11,&RTC_IO,NULL);
The parameters are start IO address, end IO adress (decimal),
pointer to function that handles device, and pointer to device
data structure. Last one is however not implemented, but thats
the way we will go.
We also have then the structure:
void (*iodata[65536]);
This if for the future IO device handling, as it allows reusing
the same function for multiple identical devices.
Since the function called for IOX is passed the IOX number as its
only parameter, every device can thus find it's own datastructure.