cominfo.c
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:16k
源码类别:

操作系统开发

开发平台:

Visual C++

  1. /*********************************************************************
  2.  * Microsoft Diagnostics Version 2.0
  3.  *
  4.  * A diagnostic utility to detect as much useful information about a
  5.  *   customer's computer system as is possible.
  6.  *
  7.  * Microsoft Diagnostics:  We detect the World.
  8.  *
  9.  * COMINFO.C - Source file for serial port detection code.
  10.  ********************************************************************/
  11. /* Include Files */
  12. #include "msd.h"
  13. /*********************************************************************
  14.  * GetComInfo - Gets the COM port information.
  15.  *
  16.  * Returns:  TRUE if an error occured.
  17.  *********************************************************************/
  18. BOOL GetComInfo (COM_STRUCT *pCom, BOOL fMinimumInfo)
  19. {
  20.   WORD  i, wWait;           /* Looping variables                    */
  21.   WORD  wIndex;             /* Index for strings                    */
  22.   WORD  wPort;              /* COM port address                     */
  23.   WORD  wLCR;               /* Line Control Register value          */
  24.   WORD  wMSR;               /* Modem Status Register value          */
  25.   WORD  wNewIID;            /* Used to store changed IID value      */
  26.   DWORD dwBaudRateDivisor;  /* Used to calculate the baud rate      */
  27.   BOOL  fArcnetCard;        /* True if the 02E0-02EF range should   */
  28.                             /*   be avoided                         */
  29.   /* 40:0 is the port address of the first valid COM port */
  30.   WORD FAR * fwPortAddress = (WORD FAR *) 0x00400000;
  31.   /* Determine if an Arcnet card is present at 02E0 */
  32.   fArcnetCard = ArcnetCardPresent();
  33.   /* Set the values in the structure for each port */
  34.   /* Zero out the count of COM ports */
  35.   pCom->wNmbrComPorts = 0;
  36.   for (i = 0; i < MAX_COM_PORTS; ++i)
  37.     {
  38.       {
  39.         /* Load the port address from the DOS Device table, if it exists */
  40.         pCom->ComxInfo[i].wPortAddress = *(fwPortAddress++);
  41.         wPort = pCom->ComxInfo[i].wPortAddress;
  42.         /* Determine if the port exists in the right range */
  43.         if (wPort >= 0x220  &&  wPort <= 0x3FF)
  44.           {
  45.             ++(pCom->wNmbrComPorts);
  46.             pCom->ComxInfo[i].fComPortDetected = TRUE;
  47.           }
  48.         else
  49.           pCom->ComxInfo[i].fComPortDetected = FALSE;
  50.         /* If the Arcnet card is present, disable COM4 testing */
  51.         if (fArcnetCard && wPort >= 0x2E0 && wPort <= 0x2FF)
  52.           pCom->ComxInfo[i].fComPortDetected = FALSE;
  53.         if (fMinimumInfo || !(pCom->ComxInfo[i].fComPortDetected))
  54.           continue;
  55.       }
  56.       {
  57.         /* Read the Line Control Register Port */
  58.         wLCR = inp (wPort + 3);
  59.         /* If the DLAB bit (bit 7) is 1, we can obtain the Baud Rate    */
  60.         /*   Divisor from *fwPortAddress (LSB) and *fwPortAddress + 1   */
  61.         /*   (MSB)                                                      */
  62.         /* If the DLAB bit is not set, set it, then read the Baud Rate  */
  63.         /*   Divisor                                                    */
  64.         if (!(0x80 & wLCR))
  65.           outp (wPort + 3, 0x80 | wLCR);
  66.         /* Pause briefly for the port to respond */
  67.         for (wWait = 0; wWait < 25; ++wWait)
  68.           ;
  69.         dwBaudRateDivisor = (WORD) (inp (wPort)) +
  70.                             (WORD) (inp (wPort + 1) << 8);
  71.         /* Pause briefly for the port to respond */
  72.         for (wWait = 0; wWait < 25; ++wWait)
  73.           ;
  74.         /* If the DLAB bit was not set originally, put it back to it's  */
  75.         /*   original state.                                            */
  76.         if (!(0x80 & wLCR))
  77.           outp (wPort + 3, wLCR);
  78.       }
  79.       {
  80.         /* Calculate the BAUD rate */
  81.         if (dwBaudRateDivisor == 0)
  82.           pCom->ComxInfo[i].dwBaudRate = 0;
  83.         else
  84.           pCom->ComxInfo[i].dwBaudRate = 115200L / dwBaudRateDivisor;
  85.       }
  86.       {
  87.         /* Parity - If bit 3 of the LCR register is off, parity is none. */
  88.         /*          none.  If bit 3 is on, bits 4 and 5 come into play   */
  89.         /*          like this:                                           */
  90.         /*                                                               */
  91.         /*              Bits: 5 4                                        */
  92.         /*                    0 0 - Odd parity                           */
  93.         /*                    0 1 - Even parity                          */
  94.         /*                    1 0 - Mark parity                          */
  95.         /*                    1 1 - Space parity                         */
  96.         if ((wLCR & 0x08) == 0)
  97.           pCom->ComxInfo[i].wParity = 0;
  98.         else
  99.           pCom->ComxInfo[i].wParity = ((wLCR & 0x30) >> 4) + 1;
  100.         memset (pCom->ComxInfo[i].szParity, '', MAX_PARITY);
  101.         wIndex = pCom->ComxInfo[i].wParity;
  102.         strcpy (pCom->ComxInfo[i].szParity, paszParityDesc[wIndex]);
  103.       }
  104.       {
  105.         /* Data Bits - Stored in the LCR in bits 0 and 1: */
  106.         /*                                                */
  107.         /*              Bits: 1 0                         */
  108.         /*                    0 0 - 5 data bits           */
  109.         /*                    0 1 - 6 data bits           */
  110.         /*                    1 0 - 7 data bits           */
  111.         /*                    1 1 - 8 data bits           */
  112.         pCom->ComxInfo[i].wDataBits = (wLCR & 0x03) + 5;
  113.       }
  114.       {
  115.         /* Stop Bits - Stored in the LCR in bit 2.  Off is 1 stop bit, */
  116.         /*             On is two stop bits.                            */
  117.         /*             Note:  If data bits is 5 and LCR bit 2 is on,   */
  118.         /*                    stop bits = 1.5.                         */
  119.         pCom->ComxInfo[i].wStopBits = (wLCR & 0x04) ? 2 : 1;
  120.         if (pCom->ComxInfo[i].wDataBits == 5 &&
  121.             pCom->ComxInfo[i].wStopBits == 2)
  122.           pCom->ComxInfo[i].wStopBits = 3;
  123.       }
  124.       {
  125.         /* Read the Modem Status Register values */
  126.         wMSR = inp (wPort + 6);
  127.       }
  128.       {
  129.         /* Carrier Detect is bit 7 of the MSR */
  130.         pCom->ComxInfo[i].fCarrierDetect = (wMSR & 0x80) ? TRUE : FALSE;
  131.       }
  132.       {
  133.         /* Ring Indicator is bit 6 of the MSR */
  134.         pCom->ComxInfo[i].fRingIndicator = (wMSR & 0x40) ? TRUE : FALSE;
  135.       }
  136.       {
  137.         /* Data Set Ready (DSR) is bit 5 of the MSR */
  138.         pCom->ComxInfo[i].fDataSetReady = (wMSR & 0x20) ? TRUE : FALSE;
  139.       }
  140.       {
  141.         /* Clear to Send is bit 4 of the MSR */
  142.         pCom->ComxInfo[i].fClearToSend = (wMSR & 0x10) ? TRUE : FALSE;
  143.       }
  144.       {
  145.         /* Determine the UART chip type.  This is accomplished by       */
  146.         /*   outputing 11000001 to the FIFO Control Register (FCR).     */
  147.         /*   Then, bits 6 and 7 are checked to see if they are on.  The */
  148.         /*   list below shows how the chip type is determined:          */
  149.         /*                                                              */
  150.         /* Bits: 7 6                                                    */
  151.         /*       0 0 - INS8250 UART                                     */
  152.         /*       0 1 - Unknown                                          */
  153.         /*       1 0 - NS16550 UART                                     */
  154.         /*       1 1 - NS16550AN UART                                   */
  155.         /*                                                              */
  156.         /* This may cause problems with TSR communications programs and */
  157.         /*   COM programs running in OS/2 or Windows while MSD runs,    */
  158.         /*   because in order to determine the chip type, I must modify */
  159.         /*   the behavior of the UART chip.                             */
  160.         /* Turn on bits 6 and 7 */
  161.         outp (wPort + 2, 0xC1);
  162.         /* Pause for a moment to allow the port to take the change. */
  163.         for (wWait = 0; wWait < 25; ++wWait)
  164.           ;
  165.         /* Read the changed value */
  166.         wNewIID = inp (wPort + 2);
  167.         /* Set the chip type, based on bits 6 and 7 */
  168.         wIndex = pCom->ComxInfo[i].wUartChip = wNewIID >> 6;
  169.         memset (pCom->ComxInfo[i].szUartChip, '', MAX_UART_CHIP);
  170.         strcpy (pCom->ComxInfo[i].szUartChip, paszUartChips[wIndex]);
  171.       }
  172.     }
  173.   return (FALSE);
  174. }
  175. /*********************************************************************
  176.  * SprintComInfo - Put Com port information into a set of strings to
  177.  *                 be printed or displayed.
  178.  *
  179.  * Returns:  NULL if an error occured.
  180.  *********************************************************************/
  181. QSZ * SprintComInfo (COM_STRUCT *pCom,
  182.                      CHAR szSumStrings[][MAX_SUMM_INFO + 5])
  183. {
  184.   WORD wNmbrStrings;         /* Number of strings                    */
  185.   WORD wNmbrChars;           /* Number of characters in the strings  */
  186.   WORD wComIndex;            /* Index to the structure of COM data   */
  187.   WORD i;                    /* Looping variables                    */
  188.   QSZ  *pqszStrings = NULL;  /* Location for storing string pointers */
  189.   /* Summary information */
  190.   if (szSumStrings != NULL)
  191.     {
  192.       sprintf (szSumStrings[0], "%d", pCom->wNmbrComPorts);
  193.       return (NULL);
  194.     }
  195.   /* Calculate the amount of space required for the strings */
  196.   wNmbrChars   = (MAX_COM_TITLES + 3) * (MAX_COM_INFO_LINE + 1);
  197.   wNmbrStrings = MAX_COM_TITLES + 3;
  198.   /* Allocate space for the pointer area and string area */
  199.   pqszStrings = AllocStringSpace (wNmbrStrings, wNmbrChars);
  200.   if (pqszStrings == NULL)
  201.     return (NULL);
  202.   /* Put the first two strings in place */
  203.   Qmemset (pqszStrings[0], ' ', COM_TITLE_WIDTH + COM_INFO_COL_WIDTH - 5);
  204.   Qstrcpy (&pqszStrings[0][COM_TITLE_WIDTH + COM_INFO_COL_WIDTH - 5],
  205.           pszComHeader);
  206.   pqszStrings[1] = pqszStrings[0] + Qstrlen (pqszStrings[0]) + 1;
  207.   Qmemset (pqszStrings[1], ' ', COM_TITLE_WIDTH + COM_INFO_COL_WIDTH - 5);
  208.   Qstrcpy (&pqszStrings[1][COM_TITLE_WIDTH + COM_INFO_COL_WIDTH - 5],
  209.           pszComUnderline);
  210.   pqszStrings[2] = pqszStrings[1] + Qstrlen (pqszStrings[1]) + 1;
  211.   /* Put the COM port information in place */
  212.   for (i = 2, wComIndex = 0; wComIndex < MAX_COM_TITLES;
  213.        ++i, ++wComIndex)
  214.     {
  215.       WORD wPort;             /* Port number for each display line */
  216.       WORD wLength;           /* Current length of string          */
  217.       WORD wInfoColumn;       /* Column to place the information   */
  218.       CHAR chBuffer[80];      /* Buffer for string data            */
  219.       PSZ  pszString = NULL;  /* String pointer                    */
  220.       /* Clear out the string */
  221.       Qmemset (pqszStrings[i], ' ', MAX_COM_INFO_LINE);
  222.       pqszStrings[i][MAX_COM_INFO_LINE] = '';
  223.       /* Put on the title */
  224.       Qstrncpy (pqszStrings[i], paszComTitles[wComIndex],
  225.                strlen (paszComTitles[wComIndex]));
  226.       for (wPort = 0; wPort < MAX_COM_PORTS; ++wPort)
  227.         {
  228.           wInfoColumn = wPort * COM_INFO_COL_WIDTH + COM_TITLE_WIDTH;
  229.           /* Put the N/A under the Port Address for ports that don't exist */
  230.           if (wComIndex == COM_PORT_ADDRESS &&
  231.               pCom->ComxInfo[wPort].fComPortDetected == FALSE)
  232.             {
  233.               QstrncpyAlign (&pqszStrings[i][wInfoColumn], pszNA,
  234.                             strlen (pszNA), COM_INFO_COL_WIDTH);
  235.             }
  236.           /* Add the strings only if the COM port exists */
  237.           if (pCom->ComxInfo[wPort].fComPortDetected)
  238.             {
  239.               switch (wComIndex)
  240.                 {
  241.                   case COM_PORT_ADDRESS:
  242.                     {
  243.                       sprintf (chBuffer, "%04XH",
  244.                                pCom->ComxInfo[wPort].wPortAddress);
  245.                       QstrncpyAlign (&pqszStrings[i][wInfoColumn], chBuffer,
  246.                                     strlen (chBuffer), COM_INFO_COL_WIDTH);
  247.                       break;
  248.                     }
  249.                   case COM_BAUD_RATE:
  250.                     {
  251.                       sprintf (chBuffer, "%Lu",
  252.                                pCom->ComxInfo[wPort].dwBaudRate);
  253.                       QstrncpyAlign (&pqszStrings[i][wInfoColumn], chBuffer,
  254.                                     strlen (chBuffer), COM_INFO_COL_WIDTH);
  255.                       break;
  256.                     }
  257.                   case COM_PARITY:
  258.                     {
  259.                       wLength = strlen (pCom->ComxInfo[wPort].szParity);
  260.                       QstrncpyAlign (&pqszStrings[i][wInfoColumn],
  261.                                     pCom->ComxInfo[wPort].szParity,
  262.                                     wLength, COM_INFO_COL_WIDTH);
  263.                       break;
  264.                     }
  265.                   case COM_DATA_BITS:
  266.                     {
  267.                       sprintf (chBuffer, "%d",
  268.                                pCom->ComxInfo[wPort].wDataBits);
  269.                       QstrncpyAlign (&pqszStrings[i][wInfoColumn], chBuffer,
  270.                                     strlen (chBuffer), COM_INFO_COL_WIDTH);
  271.                       break;
  272.                     }
  273.                   case COM_STOP_BITS:
  274.                     {
  275.                       if (pCom->ComxInfo[wPort].wStopBits < 3)
  276.                         {
  277.                           sprintf (chBuffer, "%d",
  278.                                    pCom->ComxInfo[wPort].wStopBits);
  279.                           QstrncpyAlign (&pqszStrings[i][wInfoColumn],
  280.                                         chBuffer,
  281.                                         strlen (chBuffer),
  282.                                         COM_INFO_COL_WIDTH);
  283.                         }
  284.                       else
  285.                         {
  286.                           wLength = strlen (psz1point5);
  287.                           QstrncpyAlign (&pqszStrings[i][wInfoColumn],
  288.                                         psz1point5,
  289.                                         wLength,
  290.                                         COM_INFO_COL_WIDTH);
  291.                         }
  292.                       break;
  293.                     }
  294.                   case COM_CARRIER_DETECT:
  295.                     {
  296.                       pszString = (pCom->ComxInfo[wPort].fCarrierDetect) ?
  297.                                   pszYes : pszNo;
  298.                       wLength = strlen (pszString);
  299.                       QstrncpyAlign (&pqszStrings[i][wInfoColumn], pszString,
  300.                                     wLength, COM_INFO_COL_WIDTH);
  301.                       break;
  302.                     }
  303.                   case COM_RING_INDICATOR:
  304.                     {
  305.                       pszString = (pCom->ComxInfo[wPort].fRingIndicator) ?
  306.                                   pszYes : pszNo;
  307.                       wLength = strlen (pszString);
  308.                       QstrncpyAlign (&pqszStrings[i][wInfoColumn], pszString,
  309.                                     wLength, COM_INFO_COL_WIDTH);
  310.                       break;
  311.                     }
  312.                   case COM_DATA_SET_READY:
  313.                     {
  314.                       pszString = (pCom->ComxInfo[wPort].fDataSetReady) ?
  315.                                   pszYes : pszNo;
  316.                       wLength = strlen (pszString);
  317.                       QstrncpyAlign (&pqszStrings[i][wInfoColumn], pszString,
  318.                                     wLength, COM_INFO_COL_WIDTH);
  319.                       break;
  320.                     }
  321.                   case COM_CLEAR_TO_SEND:
  322.                     {
  323.                       pszString = (pCom->ComxInfo[wPort].fClearToSend) ?
  324.                                   pszYes : pszNo;
  325.                       wLength = strlen (pszString);
  326.                       QstrncpyAlign (&pqszStrings[i][wInfoColumn], pszString,
  327.                                     wLength, COM_INFO_COL_WIDTH);
  328.                       break;
  329.                     }
  330.                   case COM_UART_CHIP:
  331.                     {
  332.                       wLength = strlen (pCom->ComxInfo[wPort].szUartChip);
  333.                       QstrncpyAlign (&pqszStrings[i][wInfoColumn],
  334.                                     pCom->ComxInfo[wPort].szUartChip,
  335.                                     wLength, COM_INFO_COL_WIDTH);
  336.                       break;
  337.                     }
  338.                 }
  339.             }
  340.         }
  341.       PrepNextString (pqszStrings, i);
  342.     }
  343.   /* Set the last pointer to a NULL */
  344.   pqszStrings[i] = NULL;
  345.   /* Return the pointer to pqszStrings */
  346.   return (pqszStrings);
  347. }