tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / workbench / network / stacks / AROSTCP / bsdsocket / kern / amiga_time.c
blobe83f8f4051ef9a8b849a70833fbf35b2ea49227e
1 /*
2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
4 * All rights reserved.
5 * Copyright (C) 2005 - 2007 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 * MA 02111-1307, USA.
23 #include <conf.h>
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/synch.h>
28 #include <sys/syslog.h>
29 #include <sys/socket.h>
30 #include <sys/socketvar.h>
31 #include <sys/protosw.h> /* for protocol timeouts */
32 #include <net/if.h> /* for if timeout */
33 #include <netinet/in.h>
34 #include <net/sana2arp.h> /* for arp timeout */
36 #include <kern/amiga_includes.h>
37 #include <kern/amiga_time.h>
40 * include prototypes for timeout functions
42 #include <net/if_protos.h> /* if_slowtimo() */
43 #include <kern/uipc_domain_protos.h> /* pfslowtimo(), pffasttimo() */
46 * Global timer base pointer used throughout the code.
47 * Commodore says that same base should not be used by different task,
48 * so API users should have their own base pointer.
50 #ifdef __MORPHOS__
51 struct Library *TimerBase = NULL;
52 #else
53 struct Device *TimerBase = NULL;
54 #endif
56 static struct MsgPort *timerport = NULL; /* Timer message reply port */
57 static struct timerequest *timerIORequest = NULL; /* template IORequest */
60 * timeoutrequest pointers for all the timeouts
62 static struct timeoutRequest *ifTimer = NULL,
63 *arpTimer = NULL,
64 *protoSlowTimer = NULL,
65 *protoFastTimer = NULL;
67 static BOOL can_send_timeouts = FALSE;
70 * Initialize the timer. This MUST be called before any Timer functions are
71 * used (including get_time() and microtime() which use GetSysTime())
72 * (see sys/time.h).
74 * timerIORequest is used as a template from which all needed timer
75 * IO messages are copied. The command field of the request is initialized to
76 * TR_ADDREQUEST. Requests node type is initialized to NT_UNKNOWN for us
77 * to be able to recognize if it has been used.
79 * Note that we need to check manually the version of the opened device. The
80 * version number must be at least 36 since we use the GetSysTime() function
81 * which is not defined in earlier versions.
83 * This initializes all the needed timeoutrequests too.
85 ULONG
86 timer_init(void)
88 LONG error;
89 #if defined(__AROS__)
90 D(bug("[AROSTCP](amiga_timer.c) timer_init()\n"));
91 #endif
94 * Return success if already initialized
96 if (timerport != NULL)
97 return TRUE;
100 * allocate and initialize the timer message reply port
102 timerport = CreateMsgPort();
103 if (timerport != NULL) {
105 * allocate and initialize the template message structure
107 timerIORequest = (struct timerequest *)
108 CreateIORequest(timerport, sizeof(struct timerequest));
109 if (timerIORequest != NULL) {
110 error = OpenDevice(TIMERNAME, UNIT_VBLANK,
111 (struct IORequest *)timerIORequest, 0);
112 if (error == 0) {
114 * Make sure that we got at least V36 timer, since we use some
115 * functions defined only in V36 and later.
117 if ((timerIORequest->tr_node.io_Device)->dd_Library.lib_Version >= 36) {
119 * initialize TimerBase from timerIORequest
121 TimerBase = timerIORequest->tr_node.io_Device;
123 * Initialize some fields of the IO request to common values
125 timerIORequest->tr_node.io_Command = TR_ADDREQUEST;
127 * NT_UNKNOWN means unused, too (see note on exec/nodes.h)
129 timerIORequest->tr_node.io_Message.mn_Node.ln_Type = NT_UNKNOWN;
132 * create timeout requests for all timeouts;
134 ifTimer = createTimeoutRequest(if_slowtimo, 1 / IFNET_SLOWHZ, 0);
135 arpTimer = createTimeoutRequest(arptimer, ARPT_AGE, 0);
136 protoSlowTimer = createTimeoutRequest(pfslowtimo, 0, 1000000 / PR_SLOWHZ);
137 protoFastTimer = createTimeoutRequest(pffasttimo, 0, 1000000 / PR_FASTHZ);
138 if (protoFastTimer && protoSlowTimer && arpTimer && ifTimer) {
139 can_send_timeouts = TRUE;
140 return (ULONG)(1 << timerport->mp_SigBit);
147 * clean all in case of any error
149 timer_deinit();
151 return (0);
155 * Deinitialize the timer.
156 * The requests are cancelled first.
158 void
159 timer_deinit(void)
161 #if defined(__AROS__)
162 D(bug("[AROSTCP](amiga_timer.c) timer_deinit()\n"));
163 #endif
164 can_send_timeouts = FALSE;
166 if (protoFastTimer)
167 deleteTimeoutRequest(protoFastTimer);
168 if (protoSlowTimer)
169 deleteTimeoutRequest(protoSlowTimer);
170 if (arpTimer)
171 deleteTimeoutRequest(arpTimer);
172 if (ifTimer)
173 deleteTimeoutRequest(ifTimer);
175 if (timerIORequest) {
176 TimerBase = NULL;
177 if (timerIORequest->tr_node.io_Device != NULL)
178 CloseDevice((struct IORequest *)timerIORequest);
179 DeleteIORequest((struct IORequest *)timerIORequest);
180 timerIORequest = NULL;
182 if (timerport) {
183 DeleteMsgPort(timerport);
184 timerport = NULL;
189 * Function to send all the timeout requests when everything is initialized
190 * DON'T even try to call this function otherwise!
192 void
193 timer_send(void)
195 #if defined(__AROS__)
196 D(bug("[AROSTCP](amiga_timer.c) timer_send()\n"));
197 #endif
198 if (can_send_timeouts != FALSE) {
200 * Start timeout requests
202 sendTimeoutRequest(ifTimer);
203 sendTimeoutRequest(arpTimer);
204 sendTimeoutRequest(protoSlowTimer);
205 sendTimeoutRequest(protoFastTimer);
207 can_send_timeouts = FALSE;
212 * functions to create new timeoutRequest (after timer is initialized!)
214 struct timeoutRequest *
215 createTimeoutRequest(TimerCallback_t fun,
216 ULONG seconds, ULONG micros)
218 struct timeoutRequest *tr;
219 #if defined(__AROS__)
220 D(bug("[AROSTCP](amiga_timer.c) createTimeoutRequest()\n"));
221 #endif
223 #if DIAGNOSTIC
225 * sanity check the micros value
227 if (micros >= 1000000) {
228 log(LOG_ERR, "More than 1000000 microseconds in initTimeoutRequest()\n");
229 return NULL;
231 #endif
234 * allocate IO request
236 tr = (struct timeoutRequest *)CreateIORequest(timerport, sizeof(*tr));
237 if (tr == NULL)
238 return NULL;
241 * copy initial values from the initialized timerrequest
244 /* Node */
245 tr->timeout_request.tr_node.io_Message.mn_Node.ln_Type =
246 timerIORequest->tr_node.io_Message.mn_Node.ln_Type;
247 tr->timeout_request.tr_node.io_Message.mn_Node.ln_Pri =
248 timerIORequest->tr_node.io_Message.mn_Node.ln_Pri;
249 tr->timeout_request.tr_node.io_Message.mn_Node.ln_Name =
250 timerIORequest->tr_node.io_Message.mn_Node.ln_Name;
252 /* Message */
253 tr->timeout_request.tr_node.io_Message.mn_ReplyPort =
254 timerIORequest->tr_node.io_Message.mn_ReplyPort;
256 /* IORequest */
257 tr->timeout_request.tr_node.io_Device = timerIORequest->tr_node.io_Device;
258 tr->timeout_request.tr_node.io_Unit = timerIORequest->tr_node.io_Unit;
259 tr->timeout_request.tr_node.io_Command = timerIORequest->tr_node.io_Command;
260 tr->timeout_request.tr_node.io_Flags = timerIORequest->tr_node.io_Flags;
263 * set our own fields
265 tr->timeout_timeval.tv_secs = seconds;
266 tr->timeout_timeval.tv_micro = micros;
267 tr->timeout_function = fun;
269 return tr;
272 void
273 deleteTimeoutRequest(struct timeoutRequest *tr)
275 #if defined(__AROS__)
276 D(bug("[AROSTCP](amiga_timer.c) deleteTimeoutRequest()\n"));
277 #endif
279 * Abort the request if ever used
281 if (((struct Node *)tr)->ln_Type != NT_UNKNOWN) {
282 AbortIO((struct IORequest *)tr);
283 WaitIO((struct IORequest *)tr);
285 * Make sure the signal gets cleared
287 SetSignal(0, 1 << timerport->mp_SigBit);
290 * free the request
292 DeleteIORequest((struct IORequest *)tr);
295 BOOL timer_poll(VOID)
297 struct timeoutRequest *timerReply;
298 /* Uncomment the following lines to get debug - however please note: this func runs often */
299 //#if defined(__AROS__)
300 //D(bug("[AROSTCP](amiga_timer.c) timer_poll()\n"));
301 //#endif
303 * Get all messages from the timer reply port.
305 if (timerReply = (struct timeoutRequest *)GetMsg(timerport)) {
307 * enter softclock interrupt level
309 spl_t s = splsoftclock();
311 * handle the timeout
313 handleTimeoutRequest(timerReply);
315 * restart timeout request
317 sendTimeoutRequest(timerReply);
319 * restore previous interrupt level
321 splx(s);
323 return TRUE;
326 return FALSE;