+ /*
+ * See "Building Hardware and Firmware to Complement Microsoft Windows Headless Operation"
+ * Out-of-Band Management Port Device Requirements:
+ * The device must act as a 16550 or 16450 UART.
+ * Windows Server 2003 will test this device using the following process:
+ * 1. Save off the current modem status register.
+ * 2. Place the UART into diagnostic mode (The UART is placed into loopback mode
+ * by writing SERIAL_MCR_LOOP to the modem control register).
+ * 3. The modem status register is read and the high bits are checked. This means
+ * SERIAL_MSR_CTS, SERIAL_MSR_DSR, SERIAL_MSR_RI and SERIAL_MSR_DCD should
+ * all be clear.
+ * 4. Place the UART in diagnostic mode and turn on OUTPUT (Loopback Mode and
+ * OUTPUT are both turned on by writing (SERIAL_MCR_LOOP | SERIAL_MCR_OUT1)
+ * to the modem control register).
+ * 5. The modem status register is read and the ring indicator is checked.
+ * This means SERIAL_MSR_RI should be set.
+ * 6. Restore original modem status register.
+ *
+ * REMARK: Strangely enough, the Virtual PC 2007 virtual machine
+ * doesn't pass this test.
+ */
+
+ BOOLEAN RetVal = FALSE;
+ UCHAR Mcr, Msr;
+
+ /* Save the Modem Control Register */
+ Mcr = READ_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER);
+
+ /* Enable loop (diagnostic) mode (set Bit 4 of the MCR) */
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER, SERIAL_MCR_LOOP);
+
+ /* Clear all modem output bits */
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER, SERIAL_MCR_LOOP);
+
+ /* Read the Modem Status Register */
+ Msr = READ_PORT_UCHAR(Address + MODEM_STATUS_REGISTER);
+
+ /*
+ * The upper nibble of the MSR (modem output bits) must be
+ * equal to the lower nibble of the MCR (modem input bits).
+ */
+ if ((Msr & (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_DCD)) == 0x00)
+ {
+ /* Set all modem output bits */
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER,
+ SERIAL_MCR_OUT1 | SERIAL_MCR_LOOP); // Windows
+/* ReactOS
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER,
+ SERIAL_MCR_DTR | SERIAL_MCR_RTS | SERIAL_MCR_OUT1 | SERIAL_MCR_OUT2 | SERIAL_MCR_LOOP);
+*/
+
+ /* Read the Modem Status Register */
+ Msr = READ_PORT_UCHAR(Address + MODEM_STATUS_REGISTER);
+
+ /*
+ * The upper nibble of the MSR (modem output bits) must be
+ * equal to the lower nibble of the MCR (modem input bits).
+ */
+ if (Msr & SERIAL_MSR_RI) // Windows
+ // if (Msr & (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_DCD) == 0xF0) // ReactOS
+ {
+ RetVal = TRUE;
+ }
+ }
+
+ /* Restore the MCR */
+ WRITE_PORT_UCHAR(Address + MODEM_CONTROL_REGISTER, Mcr);
+
+ return RetVal;
+}
+
+static BOOLEAN
+ComPortTest2(IN PUCHAR Address)
+{
+ /*
+ * This test checks whether the 16450/16550 scratch register is available.
+ * If not, the serial port is considered as unexisting.
+ */
+
+ UCHAR Byte = 0;
+
+ do
+ {
+ WRITE_PORT_UCHAR(Address + SCRATCH_REGISTER, Byte);
+
+ if (READ_PORT_UCHAR(Address + SCRATCH_REGISTER) != Byte)
+ return FALSE;
+
+ } while (++Byte != 0);
+
+ return TRUE;