Esempio n. 1
0
void com_putchar(char ch) 
{
	if (ch == '\n') {
		com_putchar('\r');
	}

	while ((READ_PORT_UCHAR (pv(SER_LSR(COM_BASE))) & SR_LSR_TBE) == 0);

	WRITE_PORT_UCHAR(pv(SER_THR(COM_BASE)), ch);
}
Esempio n. 2
0
File: misc.c Progetto: GYGit/reactos
VOID NTAPI
SerialSendByte(
	IN PKDPC Dpc,
	IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
	IN PVOID Unused1,
	IN PVOID Unused2)
{
	PSERIAL_DEVICE_EXTENSION DeviceExtension;
	PUCHAR ComPortBase;
	UCHAR Byte;
	KIRQL Irql;
	UCHAR IER;
	NTSTATUS Status;

	DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
	ComPortBase = ULongToPtr(DeviceExtension->BaseAddress);

	KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
	while (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer)
		&& READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_THR_EMPTY)
	{
		Status = PopCircularBufferEntry(&DeviceExtension->OutputBuffer, &Byte);
		if (!NT_SUCCESS(Status))
			break;
		WRITE_PORT_UCHAR(SER_THR(ComPortBase), Byte);
		INFO_(SERIAL, "Byte sent to COM%lu: 0x%02x\n",
			DeviceExtension->ComPort, Byte);
		DeviceExtension->SerialPerfStats.TransmittedCount++;
	}
	if (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer))
	{
		/* allow new interrupts */
		IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
		WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_THR_EMPTY);
	}
	KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
}
Esempio n. 3
0
File: misc.c Progetto: GYGit/reactos
VOID NTAPI
SerialReceiveByte(
	IN PKDPC Dpc,
	IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
	IN PVOID Unused1,
	IN PVOID Unused2)
{
	PSERIAL_DEVICE_EXTENSION DeviceExtension;
	PUCHAR ComPortBase;
	UCHAR Byte;
	KIRQL Irql;
	UCHAR IER;
	NTSTATUS Status;

	DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
	ComPortBase = ULongToPtr(DeviceExtension->BaseAddress);

	KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
	while (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DATA_RECEIVED)
	{
		Byte = READ_PORT_UCHAR(SER_RBR(ComPortBase));
		INFO_(SERIAL, "Byte received on COM%lu: 0x%02x\n",
			DeviceExtension->ComPort, Byte);
		Status = PushCircularBufferEntry(&DeviceExtension->InputBuffer, Byte);
		if (NT_SUCCESS(Status))
			DeviceExtension->SerialPerfStats.ReceivedCount++;
		else
			DeviceExtension->SerialPerfStats.BufferOverrunErrorCount++;
	}
	KeSetEvent(&DeviceExtension->InputBufferNotEmpty, 0, FALSE);
	KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);

	/* allow new interrupts */
	IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
	WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_DATA_RECEIVED);
}
Esempio n. 4
0
File: misc.c Progetto: GYGit/reactos
BOOLEAN NTAPI
SerialInterruptService(
	IN PKINTERRUPT Interrupt,
	IN OUT PVOID ServiceContext)
{
	PDEVICE_OBJECT DeviceObject;
	PSERIAL_DEVICE_EXTENSION DeviceExtension;
	PUCHAR ComPortBase;
	UCHAR Iir;
	ULONG Events = 0;
	BOOLEAN ret = FALSE;

	/* FIXME: sometimes, produce SERIAL_EV_RXFLAG event */

	DeviceObject = (PDEVICE_OBJECT)ServiceContext;
	DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
	ComPortBase = ULongToPtr(DeviceExtension->BaseAddress);

	Iir = READ_PORT_UCHAR(SER_IIR(ComPortBase));
	if (Iir == 0xff)
		return TRUE;
	Iir &= SR_IIR_ID_MASK;
	if ((Iir & SR_IIR_SELF) != 0) { return FALSE; }

	switch (Iir)
	{
		case SR_IIR_MSR_CHANGE:
		{
			UCHAR MSR, IER;
			TRACE_(SERIAL, "SR_IIR_MSR_CHANGE\n");

			MSR = READ_PORT_UCHAR(SER_MSR(ComPortBase));
			if (MSR & SR_MSR_CTS_CHANGED)
			{
				if (MSR & SR_MSR_CTS)
					KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL);
				else
				{
					; /* FIXME: stop transmission */
				}
				Events |= SERIAL_EV_CTS;
			}
			if (MSR & SR_MSR_DSR_CHANGED)
			{
				if (MSR & SR_MSR_DSR)
					KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, NULL, NULL);
				else
				{
					; /* FIXME: stop reception */
				}
				Events |= SERIAL_EV_DSR;
			}
			if (MSR & SR_MSR_RI_CHANGED)
			{
				INFO_(SERIAL, "SR_MSR_RI_CHANGED changed: now %d\n", MSR & SI_MSR_RI);
				Events |= SERIAL_EV_RING;
			}
			if (MSR & SR_MSR_DCD_CHANGED)
			{
				INFO_(SERIAL, "SR_MSR_DCD_CHANGED changed: now %d\n", MSR & SR_MSR_DCD);
				Events |= SERIAL_EV_RLSD;
			}
			IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
			WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_MSR_CHANGE);

			ret = TRUE;
			goto done;
		}
		case SR_IIR_THR_EMPTY:
		{
			TRACE_(SERIAL, "SR_IIR_THR_EMPTY\n");

			KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL);
			Events |= SERIAL_EV_TXEMPTY;

			ret = TRUE;
			goto done;
		}
		case SR_IIR_DATA_RECEIVED:
		{
			ULONG AlreadyReceivedBytes, Limit;
			TRACE_(SERIAL, "SR_IIR_DATA_RECEIVED\n");

			KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, NULL, NULL);
			Events |= SERIAL_EV_RXCHAR;

			/* Check if buffer will be 80% full */
			AlreadyReceivedBytes = GetNumberOfElementsInCircularBuffer(
				&DeviceExtension->InputBuffer) * 5;
			Limit = DeviceExtension->InputBuffer.Length * 4;
			if (AlreadyReceivedBytes < Limit && AlreadyReceivedBytes + 1 >= Limit)
			{
				/* Buffer is full at 80% */
				Events |= SERIAL_EV_RX80FULL;
			}

			ret = TRUE;
			goto done;
		}
		case SR_IIR_ERROR:
		{
			UCHAR LSR;
			TRACE_(SERIAL, "SR_IIR_ERROR\n");

			LSR = READ_PORT_UCHAR(SER_LSR(ComPortBase));
			if (LSR & SR_LSR_OVERRUN_ERROR)
			{
				InterlockedIncrement((PLONG)&DeviceExtension->SerialPerfStats.SerialOverrunErrorCount);
				Events |= SERIAL_EV_ERR;
			}
			if (LSR & SR_LSR_PARITY_ERROR)
			{
				InterlockedIncrement((PLONG)&DeviceExtension->SerialPerfStats.ParityErrorCount);
				Events |= SERIAL_EV_ERR;
			}
			if (LSR & SR_LSR_FRAMING_ERROR)
			{
				InterlockedIncrement((PLONG)&DeviceExtension->SerialPerfStats.FrameErrorCount);
				Events |= SERIAL_EV_ERR;
			}
			if (LSR & SR_LSR_BREAK_INT)
			{
				InterlockedIncrement((PLONG)&DeviceExtension->BreakInterruptErrorCount);
				Events |= SERIAL_EV_BREAK;
			}

			ret = TRUE;
			goto done;
		}
	}

done:
	if (!ret)
		return FALSE;
	if (DeviceExtension->WaitOnMaskIrp && (Events & DeviceExtension->WaitMask))
	{
		/* Finish pending IRP */
		PULONG pEvents = (PULONG)DeviceExtension->WaitOnMaskIrp->AssociatedIrp.SystemBuffer;

		DeviceExtension->WaitOnMaskIrp->IoStatus.Status = STATUS_SUCCESS;
		DeviceExtension->WaitOnMaskIrp->IoStatus.Information = sizeof(ULONG);
		*pEvents = Events;
		KeInsertQueueDpc(&DeviceExtension->CompleteIrpDpc, DeviceExtension->WaitOnMaskIrp, NULL);

		/* We are now ready to handle another IRP, even if this one is not completed */
		DeviceExtension->WaitOnMaskIrp = NULL;
		return STATUS_SUCCESS;
	}
	return TRUE;
}
Esempio n. 5
0
UART_TYPE
SerialDetectUartType(
	IN PUCHAR BaseAddress)
{
	UCHAR Lcr, TestLcr;
	UCHAR OldScr, Scr5A, ScrA5;
	BOOLEAN FifoEnabled;
	UCHAR NewFifoStatus;

	Lcr = READ_PORT_UCHAR(SER_LCR(BaseAddress));
	WRITE_PORT_UCHAR(SER_LCR(BaseAddress), Lcr ^ 0xFF);
	TestLcr = READ_PORT_UCHAR(SER_LCR(BaseAddress)) ^ 0xFF;
	WRITE_PORT_UCHAR(SER_LCR(BaseAddress), Lcr);

	/* Accessing the LCR must work for a usable serial port */
	if (TestLcr != Lcr)
		return UartUnknown;

	/* Ensure that all following accesses are done as required */
	READ_PORT_UCHAR(SER_RBR(BaseAddress));
	READ_PORT_UCHAR(SER_IER(BaseAddress));
	READ_PORT_UCHAR(SER_IIR(BaseAddress));
	READ_PORT_UCHAR(SER_LCR(BaseAddress));
	READ_PORT_UCHAR(SER_MCR(BaseAddress));
	READ_PORT_UCHAR(SER_LSR(BaseAddress));
	READ_PORT_UCHAR(SER_MSR(BaseAddress));
	READ_PORT_UCHAR(SER_SCR(BaseAddress));

	/* Test scratch pad */
	OldScr = READ_PORT_UCHAR(SER_SCR(BaseAddress));
	WRITE_PORT_UCHAR(SER_SCR(BaseAddress), 0x5A);
	Scr5A = READ_PORT_UCHAR(SER_SCR(BaseAddress));
	WRITE_PORT_UCHAR(SER_SCR(BaseAddress), 0xA5);
	ScrA5 = READ_PORT_UCHAR(SER_SCR(BaseAddress));
	WRITE_PORT_UCHAR(SER_SCR(BaseAddress), OldScr);

	/* When non-functional, we have a 8250 */
	if (Scr5A != 0x5A || ScrA5 != 0xA5)
		return Uart8250;

	/* Test FIFO type */
	FifoEnabled = (READ_PORT_UCHAR(SER_IIR(BaseAddress)) & 0x80) != 0;
	WRITE_PORT_UCHAR(SER_FCR(BaseAddress), SR_FCR_ENABLE_FIFO);
	NewFifoStatus = READ_PORT_UCHAR(SER_IIR(BaseAddress)) & 0xC0;
	if (!FifoEnabled)
		WRITE_PORT_UCHAR(SER_FCR(BaseAddress), 0);
	switch (NewFifoStatus)
	{
		case 0x00:
			return Uart16450;
		case 0x40:
		case 0x80:
			/* Not sure about this but the documentation says that 0x40
			 * indicates an unusable FIFO but my tests only worked
			 * with 0x80 */
			return Uart16550;
	}

	/* FIFO is only functional for 16550A+ */
	return Uart16550A;
}