revert between 56095 -> 55830 in arch
[AROS.git] / arch / ppc-chrp / efika / timer / beginio.c
blobd2bcadf81a34e521bb94015da0a0530a0a465740
1 /*
2 Copyright © 1995-2013, 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 /* See rom/timer/beginio.c for documentation */
19 /****************************************************************************************/
21 #define NEWSTYLE_DEVICE 1
23 #define ioStd(x) ((struct IOStdReq *)x)
25 /****************************************************************************************/
27 #if NEWSTYLE_DEVICE
29 static const UWORD SupportedCommands[] =
31 TR_GETSYSTIME,
32 TR_SETSYSTIME,
33 TR_ADDREQUEST,
34 NSCMD_DEVICEQUERY,
38 #endif
40 /****************************************************************************************/
42 BOOL timer_addToWaitList(struct TimerBase *, struct MinList *, struct timerequest *);
44 #include <devices/timer.h>
45 #include <proto/timer.h>
47 AROS_LH1(void, BeginIO,
48 AROS_LHA(struct timerequest *, timereq, A1),
49 struct TimerBase *, TimerBase, 5, Timer)
51 AROS_LIBFUNC_INIT
53 ULONG unitNum;
54 BOOL replyit = FALSE;
56 uint32_t initial_time = mftbl();
58 Disable();
59 EClockUpdate(TimerBase);
60 Enable();
62 timereq->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
63 timereq->tr_node.io_Error = 0;
65 unitNum = (ULONG)timereq->tr_node.io_Unit;
67 switch(timereq->tr_node.io_Command)
69 #if NEWSTYLE_DEVICE
70 case NSCMD_DEVICEQUERY:
71 #warning In timer.device this is maybe a bit problematic, as the timerequest structure does not have io_Data and io_Length members
73 if (timereq->tr_node.io_Message.mn_Length < sizeof(struct IOStdReq))
75 timereq->tr_node.io_Error = IOERR_BADLENGTH;
77 else if(ioStd(timereq)->io_Length < ((LONG)OFFSET(NSDeviceQueryResult, SupportedCommands)) + sizeof(UWORD *))
79 timereq->tr_node.io_Error = IOERR_BADLENGTH;
81 else
83 struct NSDeviceQueryResult *d;
85 d = (struct NSDeviceQueryResult *)ioStd(timereq)->io_Data;
87 d->DevQueryFormat = 0;
88 d->SizeAvailable = sizeof(struct NSDeviceQueryResult);
89 d->DeviceType = NSDEVTYPE_TIMER;
90 d->DeviceSubType = 0;
91 d->SupportedCommands = (UWORD *)SupportedCommands;
93 ioStd(timereq)->io_Actual = sizeof(struct NSDeviceQueryResult);
95 break;
96 #endif
98 case TR_GETSYSTIME:
99 Disable();
100 EClockUpdate(TimerBase);
101 Enable();
102 GetSysTime(&timereq->tr_time);
104 if(!(timereq->tr_node.io_Flags & IOF_QUICK))
106 ReplyMsg((struct Message *)timereq);
108 replyit = FALSE; /* Because replyit will clear the timeval */
109 break;
111 case TR_SETSYSTIME:
112 Disable();
113 TimerBase->tb_CurrentTime.tv_secs = timereq->tr_time.tv_secs;
114 TimerBase->tb_CurrentTime.tv_micro = timereq->tr_time.tv_micro;
115 EClockSet(TimerBase);
116 Enable();
117 replyit = TRUE;
118 break;
120 case TR_ADDREQUEST:
121 switch(unitNum)
123 case UNIT_WAITUNTIL:
124 /* Firstly, check to see if request is for past */
125 Disable();
126 if(CmpTime(&TimerBase->tb_CurrentTime, &timereq->tr_time) <= 0)
128 Enable();
129 timereq->tr_time.tv_secs = timereq->tr_time.tv_micro = 0;
130 timereq->tr_node.io_Error = 0;
131 replyit = TRUE;
133 else
135 /* Ok, we add this to the list */
136 if (timer_addToWaitList(TimerBase, &TimerBase->tb_Lists[TL_WAITVBL], timereq))
138 TimerSetup(TimerBase, initial_time);
140 Enable();
141 replyit = FALSE;
142 timereq->tr_node.io_Flags &= ~IOF_QUICK;
144 break;
146 case UNIT_MICROHZ:
147 case UNIT_VBLANK:
148 Disable();
149 AddTime(&timereq->tr_time, &TimerBase->tb_Elapsed);
150 /* Slot it into the list */
151 if (timer_addToWaitList(TimerBase, &TimerBase->tb_Lists[TL_VBLANK], timereq))
153 TimerSetup(TimerBase, initial_time);
155 Enable();
156 timereq->tr_node.io_Flags &= ~IOF_QUICK;
157 replyit = FALSE;
158 break;
160 case UNIT_ECLOCK:
161 case UNIT_WAITECLOCK:
162 default:
163 replyit = FALSE;
164 timereq->tr_node.io_Error = IOERR_NOCMD;
165 break;
166 } /* switch(unitNum) */
167 break;
169 case CMD_CLEAR:
170 case CMD_FLUSH:
171 case CMD_INVALID:
172 case CMD_READ:
173 case CMD_RESET:
174 case CMD_START:
175 case CMD_STOP:
176 case CMD_UPDATE:
177 case CMD_WRITE:
178 default:
179 replyit = TRUE;
180 timereq->tr_node.io_Error = IOERR_NOCMD;
181 break;
182 } /* switch(command) */
184 if(replyit)
186 timereq->tr_time.tv_secs = 0;
187 timereq->tr_time.tv_micro = 0;
188 if(!(timereq->tr_node.io_Flags & IOF_QUICK))
190 ReplyMsg((struct Message *)timereq);
194 AROS_LIBFUNC_EXIT
195 } /* BeginIO */
197 BOOL
198 timer_addToWaitList(struct TimerBase *TimerBase,
199 struct MinList *list,
200 struct timerequest *iotr)
202 /* We are disabled, so we should take as little time as possible. */
203 struct timerequest *tr;
204 BOOL added = FALSE;
206 ForeachNode(list, tr)
208 /* If the time in the new request is less than the next request */
209 if(CmpTime(&tr->tr_time, &iotr->tr_time) < 0)
211 /* Add the node before the next request */
212 Insert(
213 (struct List *)list,
214 (struct Node *)iotr,
215 tr->tr_node.io_Message.mn_Node.ln_Pred
217 added = TRUE;
218 break;
223 This will catch the case of either an empty list, or request is
224 for after all other requests
227 if(!added)
228 AddTail((struct List *)list, (struct Node *)iotr);
230 /* Return TRUE if it ended up on head of list */
232 return ((struct timerequest *)list->mlh_Head == iotr) ? TRUE : FALSE;