]> git.sesse.net Git - pistorm/blob - a314/a314device/startup.c
Add code to autoconfigure A314
[pistorm] / a314 / a314device / startup.c
1 #include <exec/types.h>
2 #include <exec/memory.h>
3 #include <exec/tasks.h>
4 #include <hardware/intbits.h>
5 #include <libraries/expansion.h>
6 #include <libraries/expansionbase.h>
7
8 #include <proto/exec.h>
9 #include <proto/expansion.h>
10
11 #include "a314.h"
12 #include "device.h"
13 #include "protocol.h"
14 #include "startup.h"
15 #include "fix_mem_region.h"
16 #include "debug.h"
17
18 #define A314_MANUFACTURER 0x07db
19 #define A314_PRODUCT 0xa3
20
21 #define TASK_PRIORITY 80
22 #define TASK_STACK_SIZE 1024
23
24 struct ExpansionBase *ExpansionBase;
25 struct MsgPort task_mp;
26 struct Task *task;
27 struct ComArea *ca;
28
29 struct InterruptData
30 {
31         struct Task *task;
32         struct ComArea *ca;
33 };
34
35 struct InterruptData interrupt_data;
36 struct Interrupt ports_interrupt;
37
38 extern void task_main();
39 extern void init_sockets();
40 extern void IntServer();
41
42 void NewList(struct List *l)
43 {
44         l->lh_Head = (struct Node *)&(l->lh_Tail);
45         l->lh_Tail = NULL;
46         l->lh_TailPred = (struct Node *)&(l->lh_Head);
47 }
48
49 static struct Task *create_task(char *name, long priority, char *initialPC, unsigned long stacksize)
50 {
51         char *stack = AllocMem(stacksize, MEMF_CLEAR);
52         if (stack == NULL)
53                 return NULL;
54
55         struct Task *tc = AllocMem(sizeof(struct Task), MEMF_CLEAR | MEMF_PUBLIC);
56         if (tc == NULL)
57         {
58                 FreeMem(stack, stacksize);
59                 return NULL;
60         }
61
62         tc->tc_Node.ln_Type = NT_TASK;
63         tc->tc_Node.ln_Pri = priority;
64         tc->tc_Node.ln_Name = name;
65         tc->tc_SPLower = (APTR)stack;
66         tc->tc_SPUpper = (APTR)(stack + stacksize);
67         tc->tc_SPReg = (APTR)(stack + stacksize);
68
69         AddTask(tc, initialPC, 0);
70         return tc;
71 }
72
73 static void init_message_port()
74 {
75         task_mp.mp_Node.ln_Name = device_name;
76         task_mp.mp_Node.ln_Pri = 0;
77         task_mp.mp_Node.ln_Type = NT_MSGPORT;
78         task_mp.mp_Flags = PA_SIGNAL;
79         task_mp.mp_SigBit = SIGB_MSGPORT;
80         task_mp.mp_SigTask = task;
81         NewList(&(task_mp.mp_MsgList));
82 }
83
84 static void add_interrupt_handler()
85 {
86         interrupt_data.task = task;
87         interrupt_data.ca = ca;
88
89         ports_interrupt.is_Node.ln_Type = NT_INTERRUPT;
90         ports_interrupt.is_Node.ln_Pri = 0;
91         ports_interrupt.is_Node.ln_Name = device_name;
92         ports_interrupt.is_Data = (APTR)&interrupt_data;
93         ports_interrupt.is_Code = IntServer;
94
95         AddIntServer(INTB_PORTS, &ports_interrupt);
96 }
97
98 BOOL task_start()
99 {
100         ExpansionBase = (struct ExpansionBase *)OpenLibrary(EXPANSIONNAME, 0);
101         if (!ExpansionBase)
102                 return FALSE;
103
104         struct ConfigDev *cd = FindConfigDev(NULL, A314_MANUFACTURER, A314_PRODUCT);
105         if (!cd)
106         {
107                 CloseLibrary((struct Library *)ExpansionBase);
108                 return FALSE;
109         }
110
111         ca = (struct ComArea *)cd->cd_BoardAddr;
112
113         if (!fix_memory())
114                 return FALSE;
115
116         task = create_task(device_name, TASK_PRIORITY, (void *)task_main, TASK_STACK_SIZE);
117         if (task == NULL)
118         {
119                 debug_printf("Unable to create task\n");
120                 return FALSE;
121         }
122
123         init_message_port();
124         init_sockets();
125
126         ca->a_enable = 0;
127         unsigned char discard_value = ca->a_events;
128
129         ca->r_events = R_EVENT_STARTED;
130
131         add_interrupt_handler();
132
133         ca->a_enable = A_EVENT_R2A_TAIL;
134
135         return TRUE;
136 }