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.

215 lines
4.9 KiB

  1. #include "windows.h"
  2. #include <stdio.h>
  3. BOOL
  4. SerialGetDivisorFromBaud(
  5. IN ULONG ClockRate,
  6. IN LONG DesiredBaud,
  7. OUT PSHORT AppropriateDivisor
  8. )
  9. /*++
  10. Routine Description:
  11. This routine will determine a divisor based on an unvalidated
  12. baud rate.
  13. Arguments:
  14. ClockRate - The clock input to the controller.
  15. DesiredBaud - The baud rate for whose divisor we seek.
  16. AppropriateDivisor - Given that the DesiredBaud is valid, the
  17. LONG pointed to by this parameter will be set to the appropriate
  18. value. NOTE: The long is undefined if the DesiredBaud is not
  19. supported.
  20. Return Value:
  21. This function will return STATUS_SUCCESS if the baud is supported.
  22. If the value is not supported it will return a status such that
  23. NT_ERROR(Status) == FALSE.
  24. --*/
  25. {
  26. signed short calculatedDivisor;
  27. unsigned long denominator;
  28. unsigned long remainder;
  29. //
  30. // Allow up to a 1 percent error
  31. //
  32. unsigned long maxRemain18 = 18432;
  33. unsigned long maxRemain30 = 30720;
  34. unsigned long maxRemain42 = 42336;
  35. unsigned long maxRemain80 = 80000;
  36. unsigned long maxRemain;
  37. //
  38. // Reject any non-positive bauds.
  39. //
  40. denominator = DesiredBaud*(unsigned long)16;
  41. if (DesiredBaud <= 0) {
  42. *AppropriateDivisor = -1;
  43. } else if ((signed long)denominator < DesiredBaud) {
  44. //
  45. // If the desired baud was so huge that it cause the denominator
  46. // calculation to wrap, don't support it.
  47. //
  48. *AppropriateDivisor = -1;
  49. printf("baud to big\n");
  50. } else {
  51. if (ClockRate == 1843200) {
  52. maxRemain = maxRemain18;
  53. } else if (ClockRate == 3072000) {
  54. maxRemain = maxRemain30;
  55. } else if (ClockRate == 4233600) {
  56. maxRemain = maxRemain42;
  57. } else {
  58. maxRemain = maxRemain80;
  59. }
  60. calculatedDivisor = (signed short)(ClockRate / denominator);
  61. remainder = ClockRate % denominator;
  62. //
  63. // Round up.
  64. //
  65. if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
  66. calculatedDivisor++;
  67. }
  68. //
  69. // Only let the remainder calculations effect us if
  70. // the baud rate is > 9600.
  71. //
  72. if (DesiredBaud >= 9600) {
  73. //
  74. // If the remainder is less than the maximum remainder (wrt
  75. // the ClockRate) or the remainder + the maximum remainder is
  76. // greater than or equal to the ClockRate then assume that the
  77. // baud is ok.
  78. //
  79. if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
  80. printf("remainder: %d\n",remainder);
  81. printf("error is: %f\n",((double)remainder)/((double)ClockRate));
  82. calculatedDivisor = -1;
  83. }
  84. }
  85. //
  86. // Don't support a baud that causes the denominator to
  87. // be larger than the clock.
  88. //
  89. if (denominator > ClockRate) {
  90. calculatedDivisor = -1;
  91. }
  92. //
  93. // Ok, Now do some special casing so that things can actually continue
  94. // working on all platforms.
  95. //
  96. if (ClockRate == 1843200) {
  97. if (DesiredBaud == 56000) {
  98. calculatedDivisor = 2;
  99. }
  100. } else if (ClockRate == 3072000) {
  101. if (DesiredBaud == 14400) {
  102. calculatedDivisor = 13;
  103. }
  104. } else if (ClockRate == 4233600) {
  105. if (DesiredBaud == 9600) {
  106. calculatedDivisor = 28;
  107. } else if (DesiredBaud == 14400) {
  108. calculatedDivisor = 18;
  109. } else if (DesiredBaud == 19200) {
  110. calculatedDivisor = 14;
  111. } else if (DesiredBaud == 38400) {
  112. calculatedDivisor = 7;
  113. } else if (DesiredBaud == 56000) {
  114. calculatedDivisor = 5;
  115. }
  116. } else if (ClockRate == 8000000) {
  117. if (DesiredBaud == 14400) {
  118. calculatedDivisor = 35;
  119. } else if (DesiredBaud == 56000) {
  120. calculatedDivisor = 9;
  121. }
  122. }
  123. *AppropriateDivisor = calculatedDivisor;
  124. }
  125. if (*AppropriateDivisor == -1) {
  126. return FALSE;
  127. }
  128. return TRUE;
  129. }
  130. void main(int argc,char *argv[]){
  131. unsigned long baudrate;
  132. signed short divisor = -1;
  133. if (argc > 1) {
  134. sscanf(argv[1],"%d",&baudrate);
  135. }
  136. if (!SerialGetDivisorFromBaud(
  137. 1843200,
  138. baudrate,
  139. &divisor
  140. )) {
  141. printf("Couldn't get a divisor\n");
  142. } else {
  143. printf("Divisor is: %d\n",divisor);
  144. }
  145. }