Class does not implement OM_SET method.
[tangerine.git] / arch / i386-pc / timer / beginio.c
blobd64377d57629cbaeb5f8f329b945fa5cf0d244b8
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id: beginio.c 12532 2001-10-27 19:46:10Z chodorowski $
5 Desc: BeginIO - Start up a timer.device request.
6 Lang: english
7 */
9 #include "ticks.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>
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 BOOL timer_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 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
88 EClockUpdate(TimerBase);
90 timereq->tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
91 timereq->tr_node.io_Error = 0;
93 unitNum = (ULONG)timereq->tr_node.io_Unit;
95 switch(timereq->tr_node.io_Command)
97 #if NEWSTYLE_DEVICE
98 case NSCMD_DEVICEQUERY:
99 #warning In timer.device this is maybe a bit problematic, as the timerequest structure does not have io_Data and io_Length members
101 if (timereq->tr_node.io_Message.mn_Length < sizeof(struct IOStdReq))
103 timereq->tr_node.io_Error = IOERR_BADLENGTH;
105 else if(ioStd(timereq)->io_Length < ((LONG)OFFSET(NSDeviceQueryResult, SupportedCommands)) + sizeof(UWORD *))
107 timereq->tr_node.io_Error = IOERR_BADLENGTH;
109 else
111 struct NSDeviceQueryResult *d;
113 d = (struct NSDeviceQueryResult *)ioStd(timereq)->io_Data;
115 d->DevQueryFormat = 0;
116 d->SizeAvailable = sizeof(struct NSDeviceQueryResult);
117 d->DeviceType = NSDEVTYPE_TIMER;
118 d->DeviceSubType = 0;
119 d->SupportedCommands = (UWORD *)SupportedCommands;
121 ioStd(timereq)->io_Actual = sizeof(struct NSDeviceQueryResult);
123 break;
124 #endif
126 case TR_GETSYSTIME:
127 EClockUpdate(TimerBase);
128 GetSysTime(&timereq->tr_time);
130 if(!(timereq->tr_node.io_Flags & IOF_QUICK))
132 ReplyMsg((struct Message *)timereq);
134 replyit = FALSE; /* Because replyit will clear the timeval */
135 break;
137 case TR_SETSYSTIME:
138 Disable();
139 TimerBase->tb_CurrentTime.tv_secs = timereq->tr_time.tv_secs;
140 TimerBase->tb_CurrentTime.tv_micro = timereq->tr_time.tv_micro;
141 EClockSet(TimerBase);
142 Enable();
143 replyit = TRUE;
144 break;
146 case TR_ADDREQUEST:
147 switch(unitNum)
149 case UNIT_WAITUNTIL:
150 /* Firstly, check to see if request is for past */
151 Disable();
152 if(CmpTime(&TimerBase->tb_CurrentTime, &timereq->tr_time) <= 0)
154 Enable();
155 timereq->tr_time.tv_secs = timereq->tr_time.tv_micro = 0;
156 timereq->tr_node.io_Error = 0;
157 replyit = TRUE;
159 else
161 /* Ok, we add this to the list */
162 if (timer_addToWaitList(TimerBase, &TimerBase->tb_Lists[TL_WAITVBL], timereq))
164 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
165 Timer0Setup(TimerBase);
167 Enable();
168 replyit = FALSE;
169 timereq->tr_node.io_Flags &= ~IOF_QUICK;
171 break;
173 case UNIT_MICROHZ:
174 case UNIT_VBLANK:
175 Disable();
176 AddTime(&timereq->tr_time, &TimerBase->tb_Elapsed);
177 /* Slot it into the list */
178 if (timer_addToWaitList(TimerBase, &TimerBase->tb_Lists[TL_VBLANK], timereq))
180 outb((inb(0x61) & 0xfd) | 1, 0x61); /* Enable the timer (set GATE on) */
181 Timer0Setup(TimerBase);
183 Enable();
184 timereq->tr_node.io_Flags &= ~IOF_QUICK;
185 replyit = FALSE;
186 break;
188 case UNIT_ECLOCK:
189 case UNIT_WAITECLOCK:
190 default:
191 replyit = FALSE;
192 timereq->tr_node.io_Error = IOERR_NOCMD;
193 break;
194 } /* switch(unitNum) */
195 break;
197 case CMD_CLEAR:
198 case CMD_FLUSH:
199 case CMD_INVALID:
200 case CMD_READ:
201 case CMD_RESET:
202 case CMD_START:
203 case CMD_STOP:
204 case CMD_UPDATE:
205 case CMD_WRITE:
206 default:
207 replyit = TRUE;
208 timereq->tr_node.io_Error = IOERR_NOCMD;
209 break;
210 } /* switch(command) */
212 if(replyit)
214 timereq->tr_time.tv_secs = 0;
215 timereq->tr_time.tv_micro = 0;
216 if(!(timereq->tr_node.io_Flags & IOF_QUICK))
218 ReplyMsg((struct Message *)timereq);
222 AROS_LIBFUNC_EXIT
223 } /* BeginIO */
225 BOOL
226 timer_addToWaitList(struct TimerBase *TimerBase,
227 struct MinList *list,
228 struct timerequest *iotr)
230 /* We are disabled, so we should take as little time as possible. */
231 struct timerequest *tr;
232 BOOL added = FALSE;
234 ForeachNode(list, tr)
236 /* If the time in the new request is less than the next request */
237 if(CmpTime(&tr->tr_time, &iotr->tr_time) < 0)
239 /* Add the node before the next request */
240 Insert(
241 (struct List *)list,
242 (struct Node *)iotr,
243 tr->tr_node.io_Message.mn_Node.ln_Pred
245 added = TRUE;
246 break;
251 This will catch the case of either an empty list, or request is
252 for after all other requests
255 if(!added)
256 AddTail((struct List *)list, (struct Node *)iotr);
258 /* Return TRUE if it ended up on head of list */
260 return ((struct timerequest *)list->mlh_Head == iotr) ? TRUE : FALSE;