/* * ReactOS kernel * Copyright (C) 2000 David Welch * Copyright (C) 1999 Gareth Owen , Ramon von Handel * Copyright (C) 1991, 1992 Linus Torvalds * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, * MA 02139, USA. * */ /* $Id$ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/hal/x86/udelay.c * PURPOSE: Busy waiting * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) * UPDATE HISTORY: * 06/11/99 Created */ /* INCLUDES ***************************************************************/ #include #define NDEBUG #include /* GLOBALS ******************************************************************/ static unsigned int delay_count = 1; #define MILLISEC (10) #define FREQ (1000/MILLISEC) #define PRECISION (8) #define TMR_CTRL 0x43 /* I/O for control */ #define TMR_CNT0 0x40 /* I/O for counter 0 */ #define TMR_CNT1 0x41 /* I/O for counter 1 */ #define TMR_CNT2 0x42 /* I/O for counter 2 */ #define TMR_SC0 0 /* Select channel 0 */ #define TMR_SC1 0x40 /* Select channel 1 */ #define TMR_SC2 0x80 /* Select channel 2 */ #define TMR_LOW 0x10 /* RW low byte only */ #define TMR_HIGH 0x20 /* RW high byte only */ #define TMR_BOTH 0x30 /* RW both bytes */ #define TMR_MD0 0 /* Mode 0 */ #define TMR_MD1 0x2 /* Mode 1 */ #define TMR_MD2 0x4 /* Mode 2 */ #define TMR_MD3 0x6 /* Mode 3 */ #define TMR_MD4 0x8 /* Mode 4 */ #define TMR_MD5 0xA /* Mode 5 */ #define TMR_BCD 1 /* BCD mode */ #define TMR_LATCH 0 /* Latch command */ #define TMR_READ 0xF0 /* Read command */ #define TMR_CNT 0x20 /* CNT bit (Active low, subtract it) */ #define TMR_STAT 0x10 /* Status bit (Active low, subtract it) */ #define TMR_CH2 0x8 /* Channel 2 bit */ #define TMR_CH1 0x4 /* Channel 1 bit */ #define TMR_CH0 0x2 /* Channel 0 bit */ static BOOLEAN UdelayCalibrated = FALSE; /* FUNCTIONS **************************************************************/ void init_pit(float h, unsigned char channel) { unsigned int temp=0; temp = 1193180/h; // WRITE_PORT_UCHAR((PUCHAR)TMR_CTRL, // (channel*0x40) + TMR_BOTH + TMR_MD3); WRITE_PORT_UCHAR((PUCHAR)TMR_CTRL, (channel*0x40) + TMR_BOTH + TMR_MD2); WRITE_PORT_UCHAR((PUCHAR)(0x40+channel), (unsigned char) temp); WRITE_PORT_UCHAR((PUCHAR)(0x40+channel), (unsigned char) (temp>>8)); } VOID STDCALL __KeStallExecutionProcessor(ULONG Loops) { register unsigned int i; for (i=0; i> 8); /* MSB */ /* Stage 1: Coarse calibration */ WaitFor8254Wraparound(); delay_count = 1; do { delay_count <<= 1; /* Next delay count to try */ WaitFor8254Wraparound(); __KeStallExecutionProcessor(delay_count); /* Do the delay */ CurCount = Read8254Timer(); } while (CurCount > LATCH / 2); delay_count >>= 1; /* Get bottom value for delay */ /* Stage 2: Fine calibration */ DbgPrint("delay_count: %d", delay_count); calib_bit = delay_count; /* Which bit are we going to test */ for(i=0;i>= 1; /* Next bit to calibrate */ if(!calib_bit) break; /* If we have done all bits, stop */ delay_count |= calib_bit; /* Set the bit in delay_count */ WaitFor8254Wraparound(); __KeStallExecutionProcessor(delay_count); /* Do the delay */ CurCount = Read8254Timer(); if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */ delay_count &= ~calib_bit; /* calibrated bit back off */ } /* We're finished: Do the finishing touches */ delay_count /= (MILLISEC / 2); /* Calculate delay_count for 1ms */ DbgPrint("]\n"); DbgPrint("delay_count: %d\n", delay_count); DbgPrint("CPU speed: %d\n", delay_count/250); #if 0 DbgPrint("About to start delay loop test\n"); DbgPrint("Waiting for five minutes..."); for (i = 0; i < (5*60*1000*20); i++) { KeStallExecutionProcessor(50); } DbgPrint("finished\n"); for(;;); #endif } /* EOF */