📄 cominfo.c
字号:
/*********************************************************************
* Microsoft Diagnostics Version 2.0
*
* A diagnostic utility to detect as much useful information about a
* customer's computer system as is possible.
*
* Microsoft Diagnostics: We detect the World.
*
* COMINFO.C - Source file for serial port detection code.
********************************************************************/
/* Include Files */
#include "msd.h"
/*********************************************************************
* GetComInfo - Gets the COM port information.
*
* Returns: TRUE if an error occured.
*********************************************************************/
BOOL GetComInfo (COM_STRUCT *pCom, BOOL fMinimumInfo)
{
WORD i, wWait; /* Looping variables */
WORD wIndex; /* Index for strings */
WORD wPort; /* COM port address */
WORD wLCR; /* Line Control Register value */
WORD wMSR; /* Modem Status Register value */
WORD wNewIID; /* Used to store changed IID value */
DWORD dwBaudRateDivisor; /* Used to calculate the baud rate */
BOOL fArcnetCard; /* True if the 02E0-02EF range should */
/* be avoided */
/* 40:0 is the port address of the first valid COM port */
WORD FAR * fwPortAddress = (WORD FAR *) 0x00400000;
/* Determine if an Arcnet card is present at 02E0 */
fArcnetCard = ArcnetCardPresent();
/* Set the values in the structure for each port */
/* Zero out the count of COM ports */
pCom->wNmbrComPorts = 0;
for (i = 0; i < MAX_COM_PORTS; ++i)
{
{
/* Load the port address from the DOS Device table, if it exists */
pCom->ComxInfo[i].wPortAddress = *(fwPortAddress++);
wPort = pCom->ComxInfo[i].wPortAddress;
/* Determine if the port exists in the right range */
if (wPort >= 0x220 && wPort <= 0x3FF)
{
++(pCom->wNmbrComPorts);
pCom->ComxInfo[i].fComPortDetected = TRUE;
}
else
pCom->ComxInfo[i].fComPortDetected = FALSE;
/* If the Arcnet card is present, disable COM4 testing */
if (fArcnetCard && wPort >= 0x2E0 && wPort <= 0x2FF)
pCom->ComxInfo[i].fComPortDetected = FALSE;
if (fMinimumInfo || !(pCom->ComxInfo[i].fComPortDetected))
continue;
}
{
/* Read the Line Control Register Port */
wLCR = inp (wPort + 3);
/* If the DLAB bit (bit 7) is 1, we can obtain the Baud Rate */
/* Divisor from *fwPortAddress (LSB) and *fwPortAddress + 1 */
/* (MSB) */
/* If the DLAB bit is not set, set it, then read the Baud Rate */
/* Divisor */
if (!(0x80 & wLCR))
outp (wPort + 3, 0x80 | wLCR);
/* Pause briefly for the port to respond */
for (wWait = 0; wWait < 25; ++wWait)
;
dwBaudRateDivisor = (WORD) (inp (wPort)) +
(WORD) (inp (wPort + 1) << 8);
/* Pause briefly for the port to respond */
for (wWait = 0; wWait < 25; ++wWait)
;
/* If the DLAB bit was not set originally, put it back to it's */
/* original state. */
if (!(0x80 & wLCR))
outp (wPort + 3, wLCR);
}
{
/* Calculate the BAUD rate */
if (dwBaudRateDivisor == 0)
pCom->ComxInfo[i].dwBaudRate = 0;
else
pCom->ComxInfo[i].dwBaudRate = 115200L / dwBaudRateDivisor;
}
{
/* Parity - If bit 3 of the LCR register is off, parity is none. */
/* none. If bit 3 is on, bits 4 and 5 come into play */
/* like this: */
/* */
/* Bits: 5 4 */
/* 0 0 - Odd parity */
/* 0 1 - Even parity */
/* 1 0 - Mark parity */
/* 1 1 - Space parity */
if ((wLCR & 0x08) == 0)
pCom->ComxInfo[i].wParity = 0;
else
pCom->ComxInfo[i].wParity = ((wLCR & 0x30) >> 4) + 1;
memset (pCom->ComxInfo[i].szParity, '\0', MAX_PARITY);
wIndex = pCom->ComxInfo[i].wParity;
strcpy (pCom->ComxInfo[i].szParity, paszParityDesc[wIndex]);
}
{
/* Data Bits - Stored in the LCR in bits 0 and 1: */
/* */
/* Bits: 1 0 */
/* 0 0 - 5 data bits */
/* 0 1 - 6 data bits */
/* 1 0 - 7 data bits */
/* 1 1 - 8 data bits */
pCom->ComxInfo[i].wDataBits = (wLCR & 0x03) + 5;
}
{
/* Stop Bits - Stored in the LCR in bit 2. Off is 1 stop bit, */
/* On is two stop bits. */
/* Note: If data bits is 5 and LCR bit 2 is on, */
/* stop bits = 1.5. */
pCom->ComxInfo[i].wStopBits = (wLCR & 0x04) ? 2 : 1;
if (pCom->ComxInfo[i].wDataBits == 5 &&
pCom->ComxInfo[i].wStopBits == 2)
pCom->ComxInfo[i].wStopBits = 3;
}
{
/* Read the Modem Status Register values */
wMSR = inp (wPort + 6);
}
{
/* Carrier Detect is bit 7 of the MSR */
pCom->ComxInfo[i].fCarrierDetect = (wMSR & 0x80) ? TRUE : FALSE;
}
{
/* Ring Indicator is bit 6 of the MSR */
pCom->ComxInfo[i].fRingIndicator = (wMSR & 0x40) ? TRUE : FALSE;
}
{
/* Data Set Ready (DSR) is bit 5 of the MSR */
pCom->ComxInfo[i].fDataSetReady = (wMSR & 0x20) ? TRUE : FALSE;
}
{
/* Clear to Send is bit 4 of the MSR */
pCom->ComxInfo[i].fClearToSend = (wMSR & 0x10) ? TRUE : FALSE;
}
{
/* Determine the UART chip type. This is accomplished by */
/* outputing 11000001 to the FIFO Control Register (FCR). */
/* Then, bits 6 and 7 are checked to see if they are on. The */
/* list below shows how the chip type is determined: */
/* */
/* Bits: 7 6 */
/* 0 0 - INS8250 UART */
/* 0 1 - Unknown */
/* 1 0 - NS16550 UART */
/* 1 1 - NS16550AN UART */
/* */
/* This may cause problems with TSR communications programs and */
/* COM programs running in OS/2 or Windows while MSD runs, */
/* because in order to determine the chip type, I must modify */
/* the behavior of the UART chip. */
/* Turn on bits 6 and 7 */
outp (wPort + 2, 0xC1);
/* Pause for a moment to allow the port to take the change. */
for (wWait = 0; wWait < 25; ++wWait)
;
/* Read the changed value */
wNewIID = inp (wPort + 2);
/* Set the chip type, based on bits 6 and 7 */
wIndex = pCom->ComxInfo[i].wUartChip = wNewIID >> 6;
memset (pCom->ComxInfo[i].szUartChip, '\0', MAX_UART_CHIP);
strcpy (pCom->ComxInfo[i].szUartChip, paszUartChips[wIndex]);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -