2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
5 Desc: BeginIO - Start up a timer.device request.
9 #include <exec/errors.h>
10 #include <exec/initializers.h>
11 #include <devices/timer.h>
12 #include <proto/exec.h>
13 #include <proto/timer.h>
14 #include <devices/newstyle.h>
16 #include <timer_intern.h>
19 #include <aros/debug.h>
21 static void timer_addToWaitList(struct TimerBase
*TimerBase
, UWORD unit
, struct timerequest
*tr
);
23 #define NEWSTYLE_DEVICE 1
25 #define ioStd(x) ((struct IOStdReq *)x)
29 static const UWORD SupportedCommands
[] =
41 AROS_LH1(void, BeginIO
,
42 AROS_LHA(struct timerequest
*, timereq
, A1
),
43 struct TimerBase
*, TimerBase
, 5, Timer
)
51 timereq
->tr_node
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
52 timereq
->tr_node
.io_Error
= 0;
54 unitNum
= (ULONG
)timereq
->tr_node
.io_Unit
;
56 D(bug("timer: %d %d %x %d/%d task: '%s'\n", unitNum
, timereq
->tr_node
.io_Command
,
57 timereq
, timereq
->tr_time
.tv_secs
, timereq
->tr_time
.tv_micro
, FindTask(0)->tc_Node
.ln_Name
));
59 switch(timereq
->tr_node
.io_Command
)
62 case NSCMD_DEVICEQUERY
:
63 if (timereq
->tr_node
.io_Message
.mn_Length
< sizeof(struct IOStdReq
))
65 timereq
->tr_node
.io_Error
= IOERR_BADLENGTH
;
67 else if(ioStd(timereq
)->io_Length
< ((LONG
)OFFSET(NSDeviceQueryResult
, SupportedCommands
)) + sizeof(UWORD
*))
69 timereq
->tr_node
.io_Error
= IOERR_BADLENGTH
;
73 struct NSDeviceQueryResult
*d
;
75 d
= (struct NSDeviceQueryResult
*)ioStd(timereq
)->io_Data
;
77 d
->DevQueryFormat
= 0;
78 d
->SizeAvailable
= sizeof(struct NSDeviceQueryResult
);
79 d
->DeviceType
= NSDEVTYPE_TIMER
;
81 d
->SupportedCommands
= (UWORD
*)SupportedCommands
;
83 ioStd(timereq
)->io_Actual
= sizeof(struct NSDeviceQueryResult
);
89 GetSysTime(&timereq
->tr_time
);
90 if(!(timereq
->tr_node
.io_Flags
& IOF_QUICK
)) {
91 ReplyMsg((struct Message
*)timereq
);
93 replyit
= FALSE
; /* Because replyit will clear the timeval */
98 TimerBase
->tb_CurrentTime
.tv_secs
= timereq
->tr_time
.tv_secs
;
99 TimerBase
->tb_CurrentTime
.tv_micro
= timereq
->tr_time
.tv_micro
;
109 convertunits(TimerBase
, &timereq
->tr_time
, UNIT_VBLANK
);
110 /* Firstly, check to see if request is for past */
112 if(!cmp64(&TimerBase
->tb_vb_count
, &timereq
->tr_time
)) {
114 timereq
->tr_time
.tv_secs
= timereq
->tr_time
.tv_micro
= 0;
115 timereq
->tr_node
.io_Error
= 0;
118 timer_addToWaitList(TimerBase
, UNIT_VBLANK
, timereq
);
121 timereq
->tr_node
.io_Flags
&= ~IOF_QUICK
;
126 convertunits(TimerBase
, &timereq
->tr_time
, UNIT_MICROHZ
);
128 addmicro(TimerBase
, &timereq
->tr_time
);
129 timer_addToWaitList(TimerBase
, UNIT_MICROHZ
, timereq
);
131 timereq
->tr_node
.io_Flags
&= ~IOF_QUICK
;
135 convertunits(TimerBase
, &timereq
->tr_time
, UNIT_VBLANK
);
136 add64(&timereq
->tr_time
, &TimerBase
->tb_vb_count
);
138 timer_addToWaitList(TimerBase
, UNIT_VBLANK
, timereq
);
140 timereq
->tr_node
.io_Flags
&= ~IOF_QUICK
;
145 addmicro(TimerBase
, &timereq
->tr_time
);
146 timer_addToWaitList(TimerBase
, UNIT_MICROHZ
, timereq
);
148 timereq
->tr_node
.io_Flags
&= ~IOF_QUICK
;
151 case UNIT_WAITECLOCK
:
153 timer_addToWaitList(TimerBase
, UNIT_MICROHZ
, timereq
);
155 timereq
->tr_node
.io_Flags
&= ~IOF_QUICK
;
160 timereq
->tr_node
.io_Error
= IOERR_NOCMD
;
162 } /* switch(unitNum) */
176 timereq
->tr_node
.io_Error
= IOERR_NOCMD
;
178 } /* switch(command) */
182 timereq
->tr_time
.tv_secs
= 0;
183 timereq
->tr_time
.tv_micro
= 0;
184 if(!(timereq
->tr_node
.io_Flags
& IOF_QUICK
))
186 ReplyMsg((struct Message
*)timereq
);
194 static void timer_addToWaitList(struct TimerBase
*TimerBase
, UWORD unit
, struct timerequest
*iotr
)
196 /* We are disabled, so we should take as little time as possible. */
197 struct timerequest
*tr
;
198 BOOL added
= FALSE
, first
= TRUE
;
199 struct MinList
*list
= &TimerBase
->tb_Lists
[unit
];
201 if (unit
== UNIT_VBLANK
) {
202 // always wait at least 1 full vblank
203 if (equ64(&iotr
->tr_time
, &TimerBase
->tb_vb_count
))
204 inc64(&iotr
->tr_time
);
205 inc64(&iotr
->tr_time
);
208 ForeachNode(list
, tr
) {
209 /* If the time in the new request is less than the next request */
210 if(CmpTime(&tr
->tr_time
, &iotr
->tr_time
) < 0) {
211 /* Add the node before the next request */
212 Insert((struct List
*)list
, (struct Node
*)iotr
, tr
->tr_node
.io_Message
.mn_Node
.ln_Pred
);
220 This will catch the case of either an empty list, or request is
221 for after all other requests
225 AddTail((struct List
*)list
, (struct Node
*)iotr
);
227 /* recalculate timers, list was empty or was added to head of list */
229 CheckTimer(TimerBase
, unit
);
231 D(bug("added %x: %d/%d->%d/%d\n", iotr
,
232 (unit
== UNIT_VBLANK
? TimerBase
->tb_vb_count
.tv_secs
: TimerBase
->tb_micro_count
.tv_secs
),
233 (unit
== UNIT_VBLANK
? TimerBase
->tb_vb_count
.tv_usec
: TimerBase
->tb_micro_count
.tv_usec
),
234 iotr
->tr_time
.tv_secs
, iotr
->tr_time
.tv_micro
));