revert between 56095 -> 55830 in arch
[AROS.git] / rom / devs / ahci / timer.c
blob911d40a08ae10d211e24378ff311fe2b8124fc8f
1 /*
2 Copyright © 2009-2018, 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 #include <aros/debug.h>
18 #include <proto/exec.h>
20 /* We want all other bases obtained from our base */
21 #define __NOLIBBASE__
23 #include <exec/types.h>
24 #include <devices/timer.h>
25 #include <exec/io.h>
26 #include <proto/timer.h>
28 #include "timer.h"
30 ULONG iters_per_100ns = ~0;
32 static BOOL ahci_Calibrate(struct IORequest* tmr)
34 struct Device *TimerBase = tmr->io_Device;
35 register ULONG x;
36 register ULONG scale = 0x8000; // min iterations...
37 volatile register ULONG t = 1;
38 struct timeval t1, t2;
40 D(bug("[AHCI ] Calibration started\n"));
42 while (scale <= 0x80000000)
44 Forbid();
45 GetUpTime(&t1);
46 for (x = 1; x < scale; x++)
47 t = (((t + x) * t) - x) / x; // add, mul, sub, div, trivial benchmark.
49 GetUpTime(&t2);
50 Permit();
51 SubTime(&t2, &t1);
53 // ok, it's going to be totally insane, if secs > 1.
54 if (t2.tv_secs != 0)
56 bug("[AHCI ] micro wait useless.\n");
57 return FALSE;
60 /*
61 * we expect at least 10000 times longer period, which should be 'achievable'
62 * unlikely we will cross the magic boundary here of 4 billion instructions in 10 millisecond (yielding 400'000MIPS?)
63 * 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...
66 if (t2.tv_micro >= 10000)
67 break;
68 scale <<= 1;
71 D(bug("[AHCI ] Executed %ld ops in %ldus\n", scale, t2.tv_micro));
73 // always round up to the next value.. so 30.9 -> 31, 5.1 -> 6, etc
74 x = (x + t2.tv_micro - 1) / t2.tv_micro;
75 x = (x+9) / 10;
77 bug("[AHCI ] Approximate number of iterations per 100 nanoseconds: %ld\n", x);
78 iters_per_100ns = x;
79 return TRUE;
82 struct IORequest *ahci_OpenTimer()
84 struct MsgPort *p = CreateMsgPort();
85 if (NULL != p)
87 struct IORequest *io = CreateIORequest(p, sizeof(struct timerequest));
89 if (NULL != io)
92 * We only need this timer for relatively long delays
94 if (0 == OpenDevice(TIMERNAME, UNIT_MICROHZ, io, 0))
96 if (iters_per_100ns == ~0)
98 ahci_Calibrate(io);
100 return io;
102 else
104 bug("[AHCI ] Failed to open timer.device, unit MICROHZ\n");
106 DeleteIORequest(io);
108 else
110 bug("[AHCI ] Failed to create timerequest\n");
112 DeleteMsgPort(p);
114 else
116 bug("[AHCI ] Failed to create timer port\n");
119 return NULL;
122 void ahci_CloseTimer(struct IORequest *tmr)
124 if (NULL != tmr)
126 struct MsgPort *p = tmr->io_Message.mn_ReplyPort;
127 CloseDevice(tmr);
128 DeleteIORequest(tmr);
129 DeleteMsgPort(p);
133 void ahci_WaitNano(register ULONG ns)
135 volatile register ULONG t = 1;
136 ns = (ns + 99) / 100;
137 ns *= iters_per_100ns;
138 while (ns > 0)
140 t = (((t + ns) * t) - ns) / ns; // add, mul, sub, div, trivial benchmark.
141 --ns;
145 ULONG ahci_WaitTO(struct IORequest* tmr, ULONG secs, ULONG micro, ULONG sigs)
147 ULONG iosig = 1 << tmr->io_Message.mn_ReplyPort->mp_SigBit;
149 //D(bug("[AHCI--] Timed wait %lds %ldu\n", secs, micro));
151 tmr->io_Command = TR_ADDREQUEST;
152 tmr->io_Flags = 0;
153 ((struct timerequest*)tmr)->tr_time.tv_secs = secs;
154 ((struct timerequest*)tmr)->tr_time.tv_micro = micro;
156 SendIO(tmr);
157 sigs = Wait(sigs | iosig);
158 if (0 == (sigs & iosig)) {
159 if (!CheckIO(tmr))
160 AbortIO(tmr);
162 WaitIO(tmr);
164 SetSignal(0, iosig);
166 return sigs &~ iosig;