New bitmap method SetRGBConversionFunction which can be used to
[tangerine.git] / rom / timer / beginio.c
blob339742c76f4cdc111f93957037db02d87fe6659e
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: BeginIO - Start up a timer.device request.
6 Lang: english
7 */
9 #include "timer_intern.h"
10 #include <devices/newstyle.h>
11 #include <exec/errors.h>
12 #include <exec/initializers.h>
13 #include <proto/exec.h>
14 #include <aros/debug.h>
16 /****************************************************************************************/
18 #define NEWSTYLE_DEVICE 1
20 #define ioStd(x) ((struct IOStdReq *)x)
22 /****************************************************************************************/
24 #if NEWSTYLE_DEVICE
26 static const UWORD SupportedCommands[] =
28 TR_GETSYSTIME,
29 TR_SETSYSTIME,
30 TR_ADDREQUEST,
31 NSCMD_DEVICEQUERY,
35 #endif
37 /****************************************************************************************/
39 static void addToWaitList(struct TimerBase *, struct MinList *, struct timerequest *);
41 /*****i***********************************************************************
43 NAME */
44 #include <devices/timer.h>
45 #include <proto/timer.h>
46 AROS_LH1(void, BeginIO,
48 /* SYNOPSIS */
49 AROS_LHA(struct timerequest *, timereq, A1),
51 /* LOCATION */
52 struct TimerBase *, TimerBase, 5, Timer)
54 /* FUNCTION
55 BeginIO() will perform a timer.device command. It is normally
56 called from within DoIO() and SendIO().
58 INPUT
59 timereq - The request to process.
61 RESULT
62 The requested message will be processed.
64 NOTES
65 This function is safe to call from interrupts.
67 EXAMPLE
69 BUGS
71 SEE ALSO
72 exec/Abort(), exec/SendIO(), exec/DoIO()
74 INTERNALS
76 HISTORY
77 23-01-1998 iaint Implemented again.
79 ******************************************************************************/
81 AROS_LIBFUNC_INIT
82 AROS_LIBBASE_EXT_DECL(struct TimerBase *, TimerBase)
84 ULONG unitNum;
85 BOOL replyit = FALSE;
87 timereq->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
88 timereq->tr_node.io_Error = 0;
90 unitNum = (ULONG)timereq->tr_node.io_Unit;
92 switch(timereq->tr_node.io_Command)
94 #if NEWSTYLE_DEVICE
95 case NSCMD_DEVICEQUERY:
96 #warning In timer.device this is maybe a bit problematic, as the timerequest structure does not have io_Data and io_Length members
98 if (timereq->tr_node.io_Message.mn_Length < sizeof(struct IOStdReq))
100 timereq->tr_node.io_Error = IOERR_BADLENGTH;
102 else if(ioStd(timereq)->io_Length < ((LONG)OFFSET(NSDeviceQueryResult, SupportedCommands)) + sizeof(UWORD *))
104 timereq->tr_node.io_Error = IOERR_BADLENGTH;
106 else
108 struct NSDeviceQueryResult *d;
110 d = (struct NSDeviceQueryResult *)ioStd(timereq)->io_Data;
112 d->DevQueryFormat = 0;
113 d->SizeAvailable = sizeof(struct NSDeviceQueryResult);
114 d->DeviceType = NSDEVTYPE_TIMER;
115 d->DeviceSubType = 0;
116 d->SupportedCommands = (UWORD *)SupportedCommands;
118 ioStd(timereq)->io_Actual = sizeof(struct NSDeviceQueryResult);
120 break;
121 #endif
123 case TR_GETSYSTIME:
124 GetSysTime(&timereq->tr_time);
126 if(!(timereq->tr_node.io_Flags & IOF_QUICK))
128 ReplyMsg((struct Message *)timereq);
130 replyit = FALSE; /* Because replyit will clear the timeval */
131 break;
133 case TR_SETSYSTIME:
134 Disable();
135 TimerBase->tb_CurrentTime.tv_secs = timereq->tr_time.tv_secs;
136 TimerBase->tb_CurrentTime.tv_micro = timereq->tr_time.tv_micro;
137 Enable();
138 replyit = TRUE;
139 break;
141 case TR_ADDREQUEST:
142 switch(unitNum)
144 case UNIT_WAITUNTIL:
145 /* Firstly, check to see if request is for past */
146 Disable();
147 if(CmpTime(&TimerBase->tb_CurrentTime, &timereq->tr_time) <= 0)
149 Enable();
150 timereq->tr_time.tv_secs = timereq->tr_time.tv_micro = 0;
151 timereq->tr_node.io_Error = 0;
152 replyit = TRUE;
154 else
156 /* Ok, we add this to the list */
157 addToWaitList(TimerBase, &TimerBase->tb_Lists[TL_WAITVBL], timereq);
158 Enable();
159 replyit = FALSE;
160 timereq->tr_node.io_Flags &= ~IOF_QUICK;
162 break;
164 case UNIT_VBLANK:
166 Adjust the time request to be relative to the
167 the elapsed time counter that we keep.
169 Disable();
170 AddTime(&timereq->tr_time, &TimerBase->tb_Elapsed);
172 /* Slot it into the list */
173 addToWaitList(TimerBase, &TimerBase->tb_Lists[TL_VBLANK], timereq);
174 Enable();
175 timereq->tr_node.io_Flags &= ~IOF_QUICK;
176 replyit = FALSE;
177 break;
179 case UNIT_MICROHZ:
180 case UNIT_ECLOCK:
181 case UNIT_WAITECLOCK:
182 default:
183 replyit = FALSE;
184 timereq->tr_node.io_Error = IOERR_NOCMD;
185 break;
186 } /* switch(unitNum) */
187 break;
189 case CMD_CLEAR:
190 case CMD_FLUSH:
191 case CMD_INVALID:
192 case CMD_READ:
193 case CMD_RESET:
194 case CMD_START:
195 case CMD_STOP:
196 case CMD_UPDATE:
197 case CMD_WRITE:
198 default:
199 replyit = TRUE;
200 timereq->tr_node.io_Error = IOERR_NOCMD;
201 break;
203 } /* switch(command) */
205 if(replyit)
207 timereq->tr_time.tv_secs = 0;
208 timereq->tr_time.tv_micro = 0;
209 if(!(timereq->tr_node.io_Flags & IOF_QUICK))
211 ReplyMsg((struct Message *)timereq);
215 AROS_LIBFUNC_EXIT
216 } /* BeginIO */
218 static void
219 addToWaitList( struct TimerBase *TimerBase,
220 struct MinList *list,
221 struct timerequest *iotr)
223 /* We are disabled, so we should take as little time as possible. */
224 struct timerequest *tr;
225 BOOL added = FALSE;
227 tr = (struct timerequest *)list->mlh_Head;
229 while(tr->tr_node.io_Message.mn_Node.ln_Succ != NULL)
231 /* If the time in the new request is less than the next request */
232 if(CmpTime(&tr->tr_time, &iotr->tr_time) < 0)
234 /* Add the node before the next request */
235 Insert(
236 (struct List *)list,
237 (struct Node *)iotr,
238 tr->tr_node.io_Message.mn_Node.ln_Pred
240 added = TRUE;
241 break;
243 tr = (struct timerequest *)tr->tr_node.io_Message.mn_Node.ln_Succ;
247 This will catch the case of either an empty list, or request is
248 for after all other requests
251 if(!added)
252 AddTail((struct List *)list, (struct Node *)iotr);
254 #if DEBUG
256 int i = 0;
257 bug("Current list contents:\n");
258 ForeachNode(list, tr)
260 bug("%ld: %ld.%ld\n", i,
261 tr->tr_time.tv_secs, tr->tr_time.tv_micro);
262 i++;
265 #endif /* DEBUG */