📄 hw.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*==================================================================
File: hw.c
Contains: Serial-over-DMA driver.
==================================================================*/
#include <windows.h>
#include <serhw.h>
#include <ser16550.h>
#include <windev.h>
#include <notify.h>
#include "serdma.h"
#undef ZONE_INIT
#include <serdbg.h>
#define DEBUGMODE 0
//
/////////////////// Start of exported entrypoints ////////////////
//
//
// @doc OEM
// @func PVOID | SL_Open | Configures 16550 for default behaviour.
//
VOID
SL_Open(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSERDMA_UART_INFO pHWHead = (PSERDMA_UART_INFO)pHead;
RETAILMSG(DEBUGMODE, (TEXT("SL_Open 0x%X (%d opens)\r\n"), pHead, pHWHead->OpenCount));
pHWHead->OpenCount++;
}
//
// @doc OEM
// @func PVOID | SL_Close | Does nothing except keep track of the
// open count so that other routines know what to do.
//
VOID
SL_Close(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSERDMA_UART_INFO pHWHead = (PSERDMA_UART_INFO)pHead;
RETAILMSG(DEBUGMODE, (TEXT("SL_Close \r\n")));
if ( pHWHead->OpenCount ) pHWHead->OpenCount--;
}
//
// @doc OEM
// @func PVOID | SL_Init | Initializes 16550 device head.
//
VOID
SL_Init(
PVOID pHead, // @parm points to device head
PUCHAR pRegBase, // Pointer to 16550 register base (actually used to pass the DMAChannelNumber for SERDMA)
UINT8 RegStride, // Stride amongst the 16550 registers (always 0 for SERDMA)
EVENT_FUNC EventCallback, // This callback exists in MDD
PVOID pMddHead, // This is the first parm to callback
PLOOKUP_TBL pBaudTable // BaudRate Table (always NULL for SERDMA)
)
{
PSERDMA_UART_INFO pHWHead = (PSERDMA_UART_INFO)pHead;
RETAILMSG(DEBUGMODE, (TEXT("SL_Init\r\n")));
// Store info for callback function
pHWHead->EventCallback = EventCallback;
pHWHead->pMddHead = pMddHead;
// Initialize internal members
pHWHead->DMAChannelNumber = (DWORD)pRegBase;
pHWHead->DSRIsHigh = 0;
pHWHead->OpenCount = 0;
}
//
// @doc OEM
// @func void | SL_PostInit | This routine takes care of final initialization.
//
// @rdesc None.
//
BOOL
SL_PostInit(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSERDMA_UART_INFO pHWHead = (PSERDMA_UART_INFO)pHead;
WCHAR DMADeviceName[6]; // "DMAx"
RETAILMSG(DEBUGMODE, (TEXT("+SL_PostInit \r\n")));
wcscpy(DMADeviceName, L"DMA0:");
DMADeviceName[3] = L'0'+(WCHAR)pHWHead->DMAChannelNumber; // DMAChannelNumber has already been validated to be 0...9
pHWHead->hDMAChannel = CreateFile(DMADeviceName,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (pHWHead->hDMAChannel == INVALID_HANDLE_VALUE) {
DEBUGMSG (ZONE_INIT | ZONE_ERROR,
(TEXT("Couldn't open DMA device %s with error %d, SL_PostInit failed\r\n"), DMADeviceName, GetLastError()));
return FALSE;
}
RETAILMSG(DEBUGMODE, (TEXT("-SL_PostInit \r\n")));
return TRUE;
}
//
// @doc OEM
// @func PVOID | SL_Deinit | De-initializes 16550 device head.
//
VOID
SL_Deinit(
PVOID pHead // @parm points to device head
)
{
PSERDMA_UART_INFO pHWHead = (PSERDMA_UART_INFO)pHead;
RETAILMSG(DEBUGMODE, (TEXT("SL_Deinit \r\n")));
if (pHWHead->hDMAChannel && pHWHead->hDMAChannel != INVALID_HANDLE_VALUE) {
CloseHandle(pHWHead->hDMAChannel);
}
pHWHead->hDMAChannel = NULL;
}
//
// @doc OEM
// @func void | SL_ClearDtr | This routine clears DTR.
//
// @rdesc None.
//
VOID
SL_ClearDTR(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
RETAILMSG(DEBUGMODE, (TEXT("SL_ClearDTR, 0x%X\r\n"), pHead));
ASSERT(FALSE); // this should not be called for SERDMA
}
//
// @doc OEM
// @func VOID | SL_SetDTR | This routine sets DTR.
//
// @rdesc None.
//
VOID
SL_SetDTR(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
RETAILMSG(DEBUGMODE, (TEXT("SL_SetDTR, 0x%X\r\n"), pHead));
ASSERT(FALSE); // this should not be called for SERDMA
}
//
// @doc OEM
// @func VOID | SL_ClearRTS | This routine clears RTS.
//
// @rdesc None.
//
VOID
SL_ClearRTS(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
RETAILMSG(DEBUGMODE, (TEXT("SL_ClearRTS, 0x%X\r\n"), pHead));
ASSERT(FALSE); // this should not be called for SERDMA
}
//
// @doc OEM
// @func VOID | SL_SetRTS | This routine sets RTS.
//
// @rdesc None.
//
VOID
SL_SetRTS(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
RETAILMSG(DEBUGMODE, (TEXT("SL_SetRTS, 0x%X\r\n"), pHead));
ASSERT(FALSE); // this should not be called for SERDMA
}
//
// @doc OEM
// @func VOID | SL_ClearBreak | This routine clears break.
//
// @rdesc None.
//
VOID
SL_ClearBreak(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
RETAILMSG(DEBUGMODE, (TEXT("SL_ClearBreak:\r\n")));
ASSERT(FALSE); // not called for SERDMA
}
//
// @doc OEM
// @func VOID | SL_SetBreak | This routine sets break.
//
// @rdesc None.
//
VOID
SL_SetBreak(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
RETAILMSG(DEBUGMODE, (TEXT("SL_SetBreak, 0x%X\r\n"), pHead));
ASSERT(FALSE); // not called for SERDMA
}
//
// @doc OEM
// @func BOOL | SL_SetBaudRate |
// This routine sets the baud rate of the device.
//
// @rdesc None.
//
BOOL
SL_SetBaudRate(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG BaudRate // @parm ULONG representing decimal baud rate.
)
{
RETAILMSG (DEBUGMODE, (TEXT("SL_SetbaudRate 0x%X, %d\r\n"), pHead, BaudRate));
// This is a no-op for SERDMA
return TRUE;
}
//
// @doc OEM
// @func BOOL | SL_SetByteSize |
// This routine sets the WordSize of the device.
//
// @rdesc None.
//
BOOL
SL_SetByteSize(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG ByteSize // @parm ULONG ByteSize field from DCB.
)
{
RETAILMSG(DEBUGMODE,(TEXT("SL_SetByteSize 0x%X, 0x%X\r\n"), pHead, ByteSize));
// This is a no-op for SERDMA
return TRUE;
}
//
// @doc OEM
// @func BOOL | SL_SetParity |
// This routine sets the parity of the device.
//
// @rdesc None.
//
BOOL
SL_SetParity(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG Parity // @parm ULONG parity field from DCB.
)
{
RETAILMSG(DEBUGMODE,(TEXT("SL_SetParity 0x%X, 0x%X\r\n"), pHead, Parity));
// This is a no-op for SERDMA
return TRUE;
}
//
// @doc OEM
// @func VOID | SL_SetStopBits |
// This routine sets the Stop Bits for the device.
//
// @rdesc None.
//
BOOL
SL_SetStopBits(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG StopBits // @parm ULONG StopBits field from DCB.
)
{
RETAILMSG (DEBUGMODE,(TEXT("SL_SetStopBits 0x%X, 0x%X\r\n"), pHead, StopBits));
// This is a no-op for SERDMA
return TRUE;
}
//
// @doc OEM
// @func ULONG | SL_GetRxBufferSize | This function returns
// the size of the hardware buffer passed to the interrupt
// initialize function. It would be used only for devices
// which share a buffer between the MDD/PDD and an ISR.
//
//
// @rdesc This routine always returns 0 for 16550 UARTS.
//
ULONG
SL_GetRxBufferSize(
PVOID pHead
)
{
RETAILMSG(DEBUGMODE, (TEXT("SL_GetRxBufferSize \r\n")));
// This is a no-op for SERDMA
return 0;
}
//
// @doc OEM
// @func ULONG | SL_GetInterruptType | This function is called
// by the MDD whenever an interrupt occurs. The return code
// is then checked by the MDD to determine which of the four
// interrupt handling routines are to be called.
//
// @rdesc This routine returns a bitmask indicating which interrupts
// are currently pending.
//
INTERRUPT_TYPE
SL_GetInterruptType(
PVOID pHead // Pointer to hardware head
)
{
RETAILMSG(DEBUGMODE, (TEXT("+SL_GetInterruptType \r\n")));
ASSERT(FALSE); // This should never be called for SERDMA, as there are no interrupts involved
RETAILMSG(DEBUGMODE, (TEXT("-SL_GetInterruptType \r\n")));
return INTR_NONE;
}
// @doc OEM
// @func ULONG | SL_RxIntr | This routine gets several characters from the hardware
// receive buffer and puts them in a buffer provided via the second argument.
// It returns the number of bytes lost to overrun.
//
// @rdesc The return value indicates the number of overruns detected.
// The actual number of dropped characters may be higher.
//
ULONG
SL_RxIntr(
PVOID pHead, // @parm Pointer to hardware head
PUCHAR pRxBuffer, // @parm Pointer to receive buffer
ULONG *pBufflen // @parm In = max bytes to read, out = bytes read
)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -