43f4c68c3e9fd34283b0adf0aa0f353afd42a06c
[AROS.git] / arch / ppc-chrp / efika / timer / beginio.c
blob43f4c68c3e9fd34283b0adf0aa0f353afd42a06c
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: BeginIO - Start up a timer.device request.
6 Lang: english
7 */
9 #include "lowlevel.h"
10 #include <devices/newstyle.h>
11 #include <exec/errors.h>
12 #include <exec/initializers.h>
13 #include <proto/exec.h>
14 #include <asm/io.h>
15 #include <asm/mpc5200b.h>
17 /****************************************************************************************/
19 #define NEWSTYLE_DEVICE 1
21 #define ioStd(x) ((struct IOStdReq *)x)
23 /****************************************************************************************/
25 #if NEWSTYLE_DEVICE
27 static const UWORD SupportedCommands[] =
29 TR_GETSYSTIME,
30 TR_SETSYSTIME,
31 TR_ADDREQUEST,
32 NSCMD_DEVICEQUERY,
36 #endif
38 /****************************************************************************************/
40 BOOL timer_addToWaitList(struct TimerBase *, struct MinList *, struct timerequest *);
42 /*****i***********************************************************************
44 NAME */
45 #include <devices/timer.h>
46 #include <proto/timer.h>
47 AROS_LH1(void, BeginIO,
49 /* SYNOPSIS */
50 AROS_LHA(struct timerequest *, timereq, A1),
52 /* LOCATION */
53 struct TimerBase *, TimerBase, 5, Timer)
55 /* FUNCTION
56 BeginIO() will perform a timer.device command. It is normally
57 called from within DoIO() and SendIO().
59 INPUT
60 timereq - The request to process.
62 RESULT
63 The requested message will be processed.
65 NOTES
66 This function is safe to call from interrupts.
68 EXAMPLE
70 BUGS
72 SEE ALSO
73 exec/Abort(), exec/SendIO(), exec/DoIO()
75 INTERNALS
77 HISTORY
78 23-01-1998 iaint Implemented again.
80 ******************************************************************************/
82 AROS_LIBFUNC_INIT
84 ULONG unitNum;
85 BOOL replyit = FALSE;
87 uint32_t initial_time = mftbl();
89 Disable();
90 EClockUpdate(TimerBase);
91 Enable();
93 timereq->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
94 timereq->tr_node.io_Error = 0;
96 unitNum = (ULONG)timereq->tr_node.io_Unit;
98 switch(timereq->tr_node.io_Command)
100 #if NEWSTYLE_DEVICE
101 case NSCMD_DEVICEQUERY:
102 #warning In timer.device this is maybe a bit problematic, as the timerequest structure does not have io_Data and io_Length members
104 if (timereq->tr_node.io_Message.mn_Length < sizeof(struct IOStdReq))
106 timereq->tr_node.io_Error = IOERR_BADLENGTH;
108 else if(ioStd(timereq)->io_Length < ((LONG)OFFSET(NSDeviceQueryResult, SupportedCommands)) + sizeof(UWORD *))
110 timereq->tr_node.io_Error = IOERR_BADLENGTH;
112 else
114 struct NSDeviceQueryResult *d;
116 d = (struct NSDeviceQueryResult *)ioStd(timereq)->io_Data;
118 d->DevQueryFormat = 0;
119 d->SizeAvailable = sizeof(struct NSDeviceQueryResult);
120 d->DeviceType = NSDEVTYPE_TIMER;
121 d->DeviceSubType = 0;
122 d->SupportedCommands = (UWORD *)SupportedCommands;
124 ioStd(timereq)->io_Actual = sizeof(struct NSDeviceQueryResult);
126 break;
127 #endif
129 case TR_GETSYSTIME:
130 Disable();
131 EClockUpdate(TimerBase);
132 Enable();
133 GetSysTime(&timereq->tr_time);
135 if(!(timereq->tr_node.io_Flags & IOF_QUICK))
137 ReplyMsg((struct Message *)timereq);
139 replyit = FALSE; /* Because replyit will clear the timeval */
140 break;
142 case TR_SETSYSTIME:
143 Disable();
144 TimerBase->tb_CurrentTime.tv_secs = timereq->tr_time.tv_secs;
145 TimerBase->tb_CurrentTime.tv_micro = timereq->tr_time.tv_micro;
146 EClockSet(TimerBase);
147 Enable();
148 replyit = TRUE;
149 break;
151 case TR_ADDREQUEST:
152 switch(unitNum)
154 case UNIT_WAITUNTIL:
155 /* Firstly, check to see if request is for past */
156 Disable();
157 if(CmpTime(&TimerBase->tb_CurrentTime, &timereq->tr_time) <= 0)
159 Enable();
160 timereq->tr_time.tv_secs = timereq->tr_time.tv_micro = 0;
161 timereq->tr_node.io_Error = 0;
162 replyit = TRUE;
164 else
166 /* Ok, we add this to the list */
167 if (timer_addToWaitList(TimerBase, &TimerBase->tb_Lists[TL_WAITVBL], timereq))
169 TimerSetup(TimerBase, initial_time);
171 Enable();
172 replyit = FALSE;
173 timereq->tr_node.io_Flags &= ~IOF_QUICK;
175 break;
177 case UNIT_MICROHZ:
178 case UNIT_VBLANK:
179 Disable();
180 AddTime(&timereq->tr_time, &TimerBase->tb_Elapsed);
181 /* Slot it into the list */
182 if (timer_addToWaitList(TimerBase, &TimerBase->tb_Lists[TL_VBLANK], timereq))
184 TimerSetup(TimerBase, initial_time);
186 Enable();
187 timereq->tr_node.io_Flags &= ~IOF_QUICK;
188 replyit = FALSE;
189 break;
191 case UNIT_ECLOCK:
192 case UNIT_WAITECLOCK:
193 default:
194 replyit = FALSE;
195 timereq->tr_node.io_Error = IOERR_NOCMD;
196 break;
197 } /* switch(unitNum) */
198 break;
200 case CMD_CLEAR:
201 case CMD_FLUSH:
202 case CMD_INVALID:
203 case CMD_READ:
204 case CMD_RESET:
205 case CMD_START:
206 case CMD_STOP:
207 case CMD_UPDATE:
208 case CMD_WRITE:
209 default:
210 replyit = TRUE;
211 timereq->tr_node.io_Error = IOERR_NOCMD;
212 break;
213 } /* switch(command) */
215 if(replyit)
217 timereq->tr_time.tv_secs = 0;
218 timereq->tr_time.tv_micro = 0;
219 if(!(timereq->tr_node.io_Flags & IOF_QUICK))
221 ReplyMsg((struct Message *)timereq);
225 AROS_LIBFUNC_EXIT
226 } /* BeginIO */
228 BOOL
229 timer_addToWaitList(struct TimerBase *TimerBase,
230 struct MinList *list,
231 struct timerequest *iotr)
233 /* We are disabled, so we should take as little time as possible. */
234 struct timerequest *tr;
235 BOOL added = FALSE;
237 ForeachNode(list, tr)
239 /* If the time in the new request is less than the next request */
240 if(CmpTime(&tr->tr_time, &iotr->tr_time) < 0)
242 /* Add the node before the next request */
243 Insert(
244 (struct List *)list,
245 (struct Node *)iotr,
246 tr->tr_node.io_Message.mn_Node.ln_Pred
248 added = TRUE;
249 break;
254 This will catch the case of either an empty list, or request is
255 for after all other requests
258 if(!added)
259 AddTail((struct List *)list, (struct Node *)iotr);
261 /* Return TRUE if it ended up on head of list */
263 return ((struct timerequest *)list->mlh_Head == iotr) ? TRUE : FALSE;