Reorganised C type definitions. Use now sys/type/..._t.h files for defining
[AROS.git] / arch / common / ata.device / timer.c
blob6817f1e8cbc79fd67e0ec0697a004ea71585c311
1 /*
2 Copyright © 2009, The AROS Development Team. All rights reserved
3 $Id$
5 Desc:
6 Lang: English
7 */
8 /*
9 * PARTIAL CHANGELOG:
10 * DATE NAME ENTRY
11 * ---------- ------------------ -------------------------------------------------------------------
12 * 2005-03-06 T. Wiszkowski few corrections (thanks, Georg)
13 * 2005-03-05 T. Wiszkowski created file; initial benchmarked nanowait and timer-based micro/sec wait
16 #define DEBUG 0
17 #include <exec/types.h>
18 #include <devices/timer.h>
19 #include <exec/io.h>
20 #include <proto/exec.h>
21 #include <aros/debug.h>
22 #include <proto/timer.h>
23 #include "timer.h"
25 ULONG iters_per_100ns = 0;
26 struct Device *TimerBase = 0;
28 static BOOL ata_Calibrate(struct IORequest* tmr)
30 register ULONG x;
31 register ULONG scale = 0x8000; // min iterations...
32 volatile register ULONG t = 1;
33 struct timeval t1, t2;
35 D(bug("[ATA ] Calibration started\n"));
37 while (scale <= 0x80000000)
39 Forbid();
40 GetSysTime(&t1);
41 for (x = 1; x < scale; x++)
42 t = (((t + x) * t) - x) / x; // add, mul, sub, div, trivial benchmark.
44 GetSysTime(&t2);
45 Permit();
46 SubTime(&t2, &t1);
48 // ok, it's going to be totally insane, if secs > 1.
49 if (t2.tv_secs != 0)
51 bug("[ATA ] micro wait useless.\n");
52 return FALSE;
55 /*
56 * we expect at least 10000 times longer period, which should be 'achievable'
57 * unlikely we will cross the magic boundary here of 4 billion instructions in 10 millisecond (yielding 400'000MIPS?)
58 * on the other side, if we go as low as 1, then 4 iterations of add/sub/mul/div is perfectly fine yielding a bit more than 400ns...
61 if (t2.tv_micro >= 10000)
62 break;
63 scale <<= 1;
66 D(bug("[ATA ] Executed %ld ops in %ldus\n", scale, t2.tv_micro));
68 // always round up to the next value.. so 30.9 -> 31, 5.1 -> 6, etc
69 x = (x + t2.tv_micro - 1) / t2.tv_micro;
70 x = (x+9) / 10;
72 bug("[ATA ] Approximate number of iterations per 100 nanoseconds: %ld\n", x);
73 iters_per_100ns = x;
74 return TRUE;
77 struct IORequest *ata_OpenTimer()
79 struct MsgPort *p = CreateMsgPort();
80 if (NULL != p)
82 struct IORequest *io = CreateIORequest(p, sizeof(struct timerequest));
84 if (NULL != io)
87 * ok. ECLOCK does not have too great resolution, either.
88 * we will have to sacrifice our performance a little bit, meaning, the 400ns will turn into (worst case) 2us.
89 * hopefully we won't have to call that TOO often...
91 if (0 == OpenDevice("timer.device", UNIT_MICROHZ, io, 0))
93 if (0 == TimerBase)
95 TimerBase = io->io_Device;
96 ata_Calibrate(io);
98 return io;
100 else
102 bug("[ATA ] Failed to open timer.device, unit MICROHZ\n");
104 DeleteIORequest(io);
106 else
108 bug("[ATA ] Failed to create timerequest\n");
110 DeleteMsgPort(p);
112 else
114 bug("[ATA ] Failed to create timer port\n");
117 return NULL;
120 void ata_CloseTimer(struct IORequest *tmr)
122 if (NULL != tmr)
124 struct MsgPort *p = tmr->io_Message.mn_ReplyPort;
125 CloseDevice(tmr);
126 DeleteIORequest(tmr);
127 DeleteMsgPort(p);
131 void ata_WaitNano(register ULONG ns)
133 volatile register ULONG t = 1;
134 ns = (ns + 99) / 100;
135 ns *= iters_per_100ns;
136 while (ns > 0)
138 t = (((t + ns) * t) - ns) / ns; // add, mul, sub, div, trivial benchmark.
139 --ns;
143 ULONG ata_WaitTO(struct IORequest* tmr, ULONG secs, ULONG micro, ULONG sigs)
145 ULONG sig = 1 << tmr->io_Message.mn_ReplyPort->mp_SigBit;
147 //D(bug("[ATA--] Timed wait %lds %ldu\n", secs, micro));
149 tmr->io_Command = TR_ADDREQUEST;
150 ((struct timerequest*)tmr)->tr_time.tv_secs = secs;
151 ((struct timerequest*)tmr)->tr_time.tv_micro = micro;
153 SendIO(tmr);
154 sigs = Wait(sigs | sig);
155 if (0 == (sigs & sig))
157 if (!CheckIO(tmr))
158 AbortIO(tmr);
160 WaitIO(tmr);
162 SetSignal(0, sig);
164 return sigs &~ sig;