2 Copyright © 2009, The AROS Development Team. All rights reserved
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
17 #include <exec/types.h>
18 #include <devices/timer.h>
20 #include <proto/exec.h>
21 #include <aros/debug.h>
22 #include <proto/timer.h>
25 ULONG iters_per_100ns
= ~0;
27 static BOOL
ahci_Calibrate(struct IORequest
* tmr
)
29 struct Device
*TimerBase
= tmr
->io_Device
;
31 register ULONG scale
= 0x8000; // min iterations...
32 volatile register ULONG t
= 1;
33 struct timeval t1
, t2
;
35 D(bug("[AHCI ] Calibration started\n"));
37 while (scale
<= 0x80000000)
41 for (x
= 1; x
< scale
; x
++)
42 t
= (((t
+ x
) * t
) - x
) / x
; // add, mul, sub, div, trivial benchmark.
48 // ok, it's going to be totally insane, if secs > 1.
51 bug("[AHCI ] micro wait useless.\n");
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)
66 D(bug("[AHCI ] 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
;
72 bug("[AHCI ] Approximate number of iterations per 100 nanoseconds: %ld\n", x
);
77 struct IORequest
*ahci_OpenTimer()
79 struct MsgPort
*p
= CreateMsgPort();
82 struct IORequest
*io
= CreateIORequest(p
, sizeof(struct timerequest
));
87 * We only need this timer for relatively long delays
89 if (0 == OpenDevice(TIMERNAME
, UNIT_MICROHZ
, io
, 0))
91 if (iters_per_100ns
== ~0)
99 bug("[AHCI ] Failed to open timer.device, unit MICROHZ\n");
105 bug("[AHCI ] Failed to create timerequest\n");
111 bug("[AHCI ] Failed to create timer port\n");
117 void ahci_CloseTimer(struct IORequest
*tmr
)
121 struct MsgPort
*p
= tmr
->io_Message
.mn_ReplyPort
;
123 DeleteIORequest(tmr
);
128 void ahci_WaitNano(register ULONG ns
)
130 volatile register ULONG t
= 1;
131 ns
= (ns
+ 99) / 100;
132 ns
*= iters_per_100ns
;
135 t
= (((t
+ ns
) * t
) - ns
) / ns
; // add, mul, sub, div, trivial benchmark.
140 ULONG
ahci_WaitTO(struct IORequest
* tmr
, ULONG secs
, ULONG micro
, ULONG sigs
)
142 ULONG iosig
= 1 << tmr
->io_Message
.mn_ReplyPort
->mp_SigBit
;
145 ULONG total
= secs
* 1000000 + micro
;
147 secs
= total
/ 1000000;
148 micro
= total
% 1000000;
151 //D(bug("[AHCI--] Timed wait %lds %ldu\n", secs, micro));
153 tmr
->io_Command
= TR_ADDREQUEST
;
155 ((struct timerequest
*)tmr
)->tr_time
.tv_secs
= secs
;
156 ((struct timerequest
*)tmr
)->tr_time
.tv_micro
= micro
;
159 sigs
= Wait(sigs
| iosig
);
160 if (0 == (sigs
& iosig
)) {
168 return sigs
&~ iosig
;