Changeset 165 for trunk/src/os2ahci/libc.c
- Timestamp:
- Jul 31, 2013, 8:08:59 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/os2ahci/libc.c
r160 r165 4 4 * Copyright (c) 2011 thi.guten Software Development 5 5 * Copyright (c) 2011 Mensys B.V. 6 * Portions copyright (c) 2013 David Azarewicz 6 7 * 7 8 * Authors: Christian Mueller, Markus Thielen … … 38 39 #define HEAP_UNIT_CNT (HEAP_SIZE / HEAP_UNIT) 39 40 40 /* ------------------------ typedefs and structures ------------------------ */41 42 #ifdef NOT_USED43 /* mdelay() calibration status */44 typedef enum {45 MD_NOT_CALIBRATED, /* delay loop not calibrated */46 MD_CALIBRATION_START, /* calibration run started */47 MD_CALIBRATION_END, /* calibration run ended */48 MD_CALIBRATION_DONE /* calibration complete */49 } MDCAL;50 static void _cdecl _far mdelay_timer_callback (ULONG timer_handle,51 ULONG parm1,52 ULONG parm2);53 static int mdelay_cal_end (void);54 #endif55 56 41 /* -------------------------- function prototypes -------------------------- */ 57 42 58 static void long_to_asc (long val, 59 char _far *buf, 60 int base, 61 int zero, int flen); 43 static void long_to_asc(long val, char _far *buf, int base, int zero, int flen); 62 44 63 45 /* ------------------------ global/static variables ------------------------ */ … … 94 76 }; 95 77 96 #ifdef NOT_USED97 /* delay loop calibration data */98 volatile MDCAL mdelay_cal_status = 0; /* delay loop calibration status */99 volatile u32 mdelay_loops_per_ms = 0; /* delay loop counter */100 #endif101 102 78 /* very small heap for dynamic memory management */ 103 79 static u8 heap_buf[HEAP_SIZE]; … … 688 664 } 689 665 690 #ifdef NOT_USED691 /******************************************************************************692 * Calibrate 'mdelay()' loop. This is done by setting up a 1 second timer693 * with a callback that sets 'mdelay_done' to MD_CALIBRATION_END. Then it694 * calls mdelay() with a large milliseond value as initial delay loop counter.695 * When the timer triggers, 'mdelay()' will stop and update the delay loop696 * counter.697 *698 * This function needs to be called at device driver init time. Since it uses699 * ADD timers, it must be called with interrupts enabled. All this is not very700 * precise (we should wait for a clock tick before starting, ...) but we don't701 * really need precise timers.702 */703 void mdelay_cal(void)704 {705 ULONG timer_handle;706 707 dprintf("calibrating delay loop... ");708 709 mdelay_loops_per_ms = 100000;710 mdelay_cal_status = MD_CALIBRATION_START;711 712 ADD_StartTimerMS(&timer_handle, 1000, (PFN) mdelay_timer_callback, 0, 0);713 mdelay(999999999);714 ADD_CancelTimer(timer_handle);715 716 dprintf("done (loops per ms = %ld)\n", mdelay_loops_per_ms);717 }718 719 /******************************************************************************720 * Wait specified number of milliseconds. This is implemented using a busy721 * loop and is only good for delays in the millisecond range but never for more722 * than a few milliseconds and only in situations where a proper timer won't do.723 * As a rule of thumb, don't call this function and use ADD timers, instead.724 *725 * NOTES:726 *727 * - Timers are problematic on x86 platforms because there's no reliable728 * hardware timer on all architectures and the CPU clock speed may change729 * while executing delay loops (AMD Cool&Quiet and Intel SpeedStep), thus730 * calibration routines won't really be sufficient. But this usually only731 * extends the delay and we don't really need a high precision timer. The732 * exception are things like notebooks that are clocked slower when on733 * battery and which got booted while on battery. Should still be OK,734 * though, because our requirements are not that strict.735 *736 * - The code in this function is inefficient by design to make sure it737 * will work with future CPUs which might otherwise be too fast for738 * our loop counters. Part of this design is using volatile variables to739 * force memory operations.740 *741 * - Before using this function, call mdelay_calibrate() to determine the742 * number of inner loops required per millisecond.743 */744 void mdelay(u32 millies)745 {746 volatile u32 i;747 volatile u32 n;748 749 for (i = 0; i < millies; i++) {750 for (n = 0; n < mdelay_loops_per_ms; n++) {751 if (mdelay_cal_end()) {752 /* this is a calibration run that just ended */753 goto complete_calibration;754 }755 }756 }757 return;758 759 complete_calibration:760 /* complete calibration cycle */761 if (i < 1000) {762 /* Initial value for delay loop was too high; interpolate results for763 * an assumed initial delay loop divided by 1000.764 */765 i = i * 1000 + mdelay_loops_per_ms % 1000;766 mdelay_loops_per_ms /= 1000;767 }768 mdelay_loops_per_ms = (mdelay_loops_per_ms * i) / 1000;769 mdelay_cal_status = MD_CALIBRATION_DONE;770 }771 #endif772 773 666 /****************************************************************************** 774 667 * Setup the millisecond timer. This is implemented by blocking (yielding the … … 898 791 } 899 792 900 #ifdef NOT_USED901 /******************************************************************************902 * Timer callback handler for 'mdelay_calibrate()'903 */904 static void _cdecl _far mdelay_timer_callback(ULONG timer_handle,905 ULONG parm1,906 ULONG parm2)907 {908 mdelay_cal_status = MD_CALIBRATION_END;909 }910 911 /******************************************************************************912 * Determine whether an mdelay calibration run has just ended. This is in a913 * function to prevent overzealous optimizers from removing the whole delay914 * loop in mdelay().915 */916 static int mdelay_cal_end(void)917 {918 return(mdelay_cal_status == MD_CALIBRATION_END);919 }920 #endif
Note:
See TracChangeset
for help on using the changeset viewer.