Leaked source code of windows server 2003
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
#include "windows.h"
#include <stdio.h>
BOOL SerialGetDivisorFromBaud( IN ULONG ClockRate, IN LONG DesiredBaud, OUT PSHORT AppropriateDivisor )
/*++
Routine Description:
This routine will determine a divisor based on an unvalidated baud rate.
Arguments:
ClockRate - The clock input to the controller.
DesiredBaud - The baud rate for whose divisor we seek.
AppropriateDivisor - Given that the DesiredBaud is valid, the LONG pointed to by this parameter will be set to the appropriate value. NOTE: The long is undefined if the DesiredBaud is not supported.
Return Value:
This function will return STATUS_SUCCESS if the baud is supported. If the value is not supported it will return a status such that NT_ERROR(Status) == FALSE.
--*/
{
signed short calculatedDivisor; unsigned long denominator; unsigned long remainder;
//
// Allow up to a 1 percent error
//
unsigned long maxRemain18 = 18432; unsigned long maxRemain30 = 30720; unsigned long maxRemain42 = 42336; unsigned long maxRemain80 = 80000; unsigned long maxRemain;
//
// Reject any non-positive bauds.
//
denominator = DesiredBaud*(unsigned long)16;
if (DesiredBaud <= 0) {
*AppropriateDivisor = -1;
} else if ((signed long)denominator < DesiredBaud) {
//
// If the desired baud was so huge that it cause the denominator
// calculation to wrap, don't support it.
//
*AppropriateDivisor = -1; printf("baud to big\n");
} else {
if (ClockRate == 1843200) { maxRemain = maxRemain18; } else if (ClockRate == 3072000) { maxRemain = maxRemain30; } else if (ClockRate == 4233600) { maxRemain = maxRemain42; } else { maxRemain = maxRemain80; }
calculatedDivisor = (signed short)(ClockRate / denominator); remainder = ClockRate % denominator;
//
// Round up.
//
if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
calculatedDivisor++; }
//
// Only let the remainder calculations effect us if
// the baud rate is > 9600.
//
if (DesiredBaud >= 9600) {
//
// If the remainder is less than the maximum remainder (wrt
// the ClockRate) or the remainder + the maximum remainder is
// greater than or equal to the ClockRate then assume that the
// baud is ok.
//
if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) { printf("remainder: %d\n",remainder); printf("error is: %f\n",((double)remainder)/((double)ClockRate)); calculatedDivisor = -1; }
}
//
// Don't support a baud that causes the denominator to
// be larger than the clock.
//
if (denominator > ClockRate) {
calculatedDivisor = -1;
}
//
// Ok, Now do some special casing so that things can actually continue
// working on all platforms.
//
if (ClockRate == 1843200) {
if (DesiredBaud == 56000) { calculatedDivisor = 2; }
} else if (ClockRate == 3072000) {
if (DesiredBaud == 14400) { calculatedDivisor = 13; }
} else if (ClockRate == 4233600) {
if (DesiredBaud == 9600) { calculatedDivisor = 28; } else if (DesiredBaud == 14400) { calculatedDivisor = 18; } else if (DesiredBaud == 19200) { calculatedDivisor = 14; } else if (DesiredBaud == 38400) { calculatedDivisor = 7; } else if (DesiredBaud == 56000) { calculatedDivisor = 5; }
} else if (ClockRate == 8000000) {
if (DesiredBaud == 14400) { calculatedDivisor = 35; } else if (DesiredBaud == 56000) { calculatedDivisor = 9; }
}
*AppropriateDivisor = calculatedDivisor;
}
if (*AppropriateDivisor == -1) {
return FALSE;
}
return TRUE;
}
void main(int argc,char *argv[]){
unsigned long baudrate; signed short divisor = -1;
if (argc > 1) {
sscanf(argv[1],"%d",&baudrate);
}
if (!SerialGetDivisorFromBaud( 1843200, baudrate, &divisor )) {
printf("Couldn't get a divisor\n");
} else {
printf("Divisor is: %d\n",divisor);
}
}
|