⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2p465.cpp

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		goto leave;
		}

	if ( !KeyboardCommandPut(fLights) )
		{
//NKDbgPrintfW(L"ps2p465.cpp KeyboardLights data put failed\r\n");
		goto leave;
		}

leave:
//NKDbgPrintfW(L"ps2p465.cpp KeyboardLights exit\r\n");
	return;
}


/*++

Ps2P465::
KeybdDataRead:

Reads data from HD64465 output port.


--*/
BOOL
Ps2P465::
KeybdDataRead(
	UINT8	*pui8Data
	)
{

	*pui8Data = (UINT8)(REG16(v_pIoRegs, KB_CSR));
//	REG16(v_pIoRegs, KB_ISR) = KB_RDRF;
	return TRUE;
}


/*++

Ps2P465::
KeyboardPollRead:

SPINS waiting for the output buffer to go full and then reads the data
from the output buffer.  Returns true if the buffer goes full, false if
the buffer never goes full.  Remember that output means output of the
HD64465, not the PC.

--*/
BOOL
Ps2P465::
KeyboardPollRead(
	UINT8	*pui8
	)
{
	BOOL	bRet = FALSE;
	UINT8	ui8Status;

	int		cSleeps = 100;	//	Rather arbitrary.

  if(KeyboardInterruptControl == 0) {
	KeyboardInterruptControl = 2;
	while ( cSleeps )
		{
		ui8Status = (UINT8)(REG16(v_pIoRegs, KB_ISR));
		
		if ( ui8Status & KB_RDRF )
			{
			break;
			}
		else
			{
			Sleep(10);
			cSleeps--;
			}
		}

	//	May as well read it even if we failed.
	*pui8 = (UINT8)(REG16(v_pIoRegs, KB_CSR));
	REG16(v_pIoRegs, KB_ISR) = KB_RDRF;

	if ( cSleeps )
		{
		bRet = TRUE;
		}
	else
		{
		ERRORMSG(1,(TEXT("Ps2p465::KeyboardPollRead: too long waiting for keyboard response.\r\n")));
		}
	KeyboardInterruptControl = 0;
  }
	return bRet;
}

/*++

Ps2P465::
KeyboardCommandPut:

This function sends a byte one bit ay a time to the HD64465 keyboard interface.
Then waits for the acknowledge (0xFA) byte.

--*/
BOOL
Ps2P465::
KeyboardCommandPut(
	UINT8	ui8Cmd
	)
{
	UINT8	ui8Data;

	UINT32 i, j, parity;
	UINT32 tm;
	UINT16 k;


	/* Wait for 90 us. */
	BusyWait( Delay_90uS );  // This allows the CLOCK and DATA lines to be high
							 // before the HOST sends a command to the device

	/* KBCIE = 0, KBCOE = 1, KBDOE = 0, KBCD = 0, KBDD = 0 */
	/* Disable input shift register, Set clock line low, Set DATA line tri-state */
	REG16(v_pIoRegs, KB_CSR) = 0x4000;
  
	/* Wait for 90 us. */
	BusyWait( Delay_90uS );

	/* KBCIE = 0, KBCOE = 1, KBDOE = 1, KBCD = 0, KBDD = 0 */
	/* Disable input shift register, Set CLOCK line low, Set DATA line low */
	REG16(v_pIoRegs, KB_CSR) = 0x6000;
	REG16(v_pIoRegs, KB_ISR) = KB_RDRF;		// clear any waiting data

	/* Wait for 90 us. */
	BusyWait( Delay_180uS );

	/* KBCIE = 0, KBCOE = 0, KBDOE = 1, KBCD = 1, KBDD = 0 */
	/* Disable input shift register, Set CLOCK line tri-state, Set DATA line low */
	REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN+0x3000;

	// Poll KBCK pin. (bit 10). Whenever it goes low from high, write  one bit.

	// Data to send: 8 data, 1 parity, 1 stop.
	parity = 0;
	for(i=0; i < 10; i++) {


		// Poll KBCK pin (bit 10) to go low from high.
		tm = 0;
		k = 0;
		while( (!(k & KB_CLK_RD)) && (tm < WRITE_TIMEOUT) ) {	// Wait while CLOCK is low
			k = REG16(v_pIoRegs, KB_CSR);
			tm++;
		}
		if(tm == WRITE_TIMEOUT) goto error_exit;

		tm = 0;
		k = KB_CSR;
		while( (k & KB_CLK_RD) && (tm < WRITE_TIMEOUT) ) {	// Wait while CLOCK is high
			k = REG16(v_pIoRegs, KB_CSR);
			tm++;
		}
		if(tm == WRITE_TIMEOUT) goto error_exit;

		if(i<8) {
			// Send next data bit. LSB first to Keyboard Data Drive (bit 11).
			// Writing 0x3800 means writing 1 to Keyboard Data Drive bit, 
			// Writing 0x3000 means writing 0 to Keyboard Data Drive bit.
			j = (ui8Cmd & (1 << i));
			if(j) {
				parity ++;
				REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN+0x3800;
			}
			else {
				REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN+0x3000;
			}
		}
		else {
			if(i == 8) { // Send the parity bit. make parity + data = odd no. of 1's
				if ((parity % 2) == 0) {
					REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN+0x3800;
				}
				else {
					REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN+0x3000;
				}
			}
			if (i == 9) { // Send the Stop bit
				REG16(v_pIoRegs, KB_CSR) = 0x6800; // set CLOCK low to hold off ACK
			}
		}
	}

	/* Wait for 90 us. */
	BusyWait( Delay_90uS );
	REG16(v_pIoRegs, KB_CSR) = 0x3800;		// set CLOCK high

	/* Wait for 30 us. */
	BusyWait( Delay_30uS );

	k = REG16(v_pIoRegs, KB_CSR);
	REG16(v_pIoRegs, KB_ISR) = KB_RDRF;		// clear any waiting data
	if (KeyboardInterruptControl) {

/* We should try to receive the ACK from the keyboard here but when 
 * the interrupt is enabled the hardware just will not cooperate.
 *
 * So inplace of doing the correct this we just waste 2,000 microseconds
 * and hope that the ACK came in. If the ACK is late it will be processed
 * as a scan code. This causes some other problems.
 */
		REG16(v_pIoRegs, KB_CSR) = 0;			// Disable keyboard input

		/* Wait for 2000 us. */
		BusyWait( Delay_2000uS );
//NKDbgPrintfW(L"ps2p465.cpp KeyboardCommandPut(%02X), delay while ACK comes in.\r\n",ui8Cmd);
	}
	else {

		REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN;
		KeyboardPollRead(&ui8Data);

//NKDbgPrintfW(L"ps2p465.cpp KeyboardCommandPut(%02X), data: %02X\r\n",ui8Cmd,ui8Data);

	}

	/* Enable the keyboard input again. */
	REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN;

	return TRUE;

error_exit:
	// Still Enable the interrupts. So that if the keyboard is 
	// plugged in later on, it'll work.

//NKDbgPrintfW(L"ps2p465.cpp KeyboardCommandPut(%02X), Error.\r\n",ui8Cmd);

	REG16(v_pIoRegs, KB_ISR) = KB_RDRF;
	REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN;

	return FALSE;

}

/*++

Ps2P465::
MouseCommandPut:

This function sends a byte one bit ay a time to the HD64465 Mouse interface.
Then waits for the acknowledge (0xFA) byte.

--*/
BOOL
Ps2P465::
MouseCommandPut(
	UINT8	ui8Cmd
	)
{
	UINT8	ui8Data;

	UINT32 i, j, parity;
	UINT32 tm;
	UINT16 k;

	/* Wait for 90 us. */
	BusyWait( Delay_90uS );  // This allows the CLOCK and DATA lines to be high
							 // before the HOST sends a command to the device

	/* MSCIE = 0, MSCOE = 1, MSDOE = 0, MSCD = 0, MSDD = 0 */
	/* Disable input shift register, Set clock line low, Set DATA line tri-state */
	REG16(v_pIoRegs, MOUSE_CSR) = 0x4000;
  
	/* Wait for 90 us. */
	BusyWait( Delay_90uS );

	/* MSCIE = 0, MSCOE = 1, MSDOE = 1, MSCD = 0, MSDD = 0 */
	/* Disable input shift register, Set CLOCK line low, Set DATA line low */
	REG16(v_pIoRegs, MOUSE_CSR) = 0x6000;
	REG16(v_pIoRegs, MOUSE_ISR) = MOUSE_RDRF;	// clear any waiting data

	/* Wait for 90 us. */
	BusyWait( Delay_180uS );

	/* MSCIE = 0, MSCOE = 0, MSDOE = 1, MSCD = 1, MSDD = 0 */
	/* Disable input shift register, Set CLOCK line tri-state, Set DATA line low */
	REG16(v_pIoRegs, MOUSE_CSR) = MOUSE_CLK_EN+0x3000;

	// Poll MSCK pin. (bit 10). Whenever it goes low from high, write  one bit.

	// Data to send: 8 data, 1 parity, 1 stop.
	parity = 0;
	for(i=0; i < 10; i++) {


		// Poll MSCK pin (bit 10) to go low from high.
		tm = 0;
		k = REG16(v_pIoRegs, MOUSE_CSR);  // Davli k = 0;
		while( (!(k & MOUSE_CLK_RD)) && (tm < WRITE_TIMEOUT) ) {	// Wait while CLOCK is low
			k = REG16(v_pIoRegs, MOUSE_CSR);
			tm++;
		}
		if(tm == WRITE_TIMEOUT) goto error_exit;

		tm = 0;
		k = MOUSE_CSR;
		while( (k & MOUSE_CLK_RD) && (tm < WRITE_TIMEOUT) ) {	// Wait while CLOCK is high
			k = REG16(v_pIoRegs, MOUSE_CSR);
			tm++;
		}
		if(tm == WRITE_TIMEOUT) goto error_exit;

		if(i<8) {
			// Send next data bit. LSB first to Mouse Data Drive (bit 11).
			// Writing 0x3800 means writing 1 to Mouse Data Drive bit, 
			// Writing 0x3000 means writing 0 to Mouse Data Drive bit.
			j = (ui8Cmd & (1 << i));
			if(j) {
				parity ++;
				REG16(v_pIoRegs, MOUSE_CSR) = MOUSE_CLK_EN+0x3800;
			}
			else {
				REG16(v_pIoRegs, MOUSE_CSR) = MOUSE_CLK_EN+0x3000;
			}
		}
		else {
			if(i == 8) { // Send the parity bit. make parity + data = odd no. of 1's
				if ((parity % 2) == 0) {
					REG16(v_pIoRegs, MOUSE_CSR) = MOUSE_CLK_EN+0x3800;
				}
				else {
					REG16(v_pIoRegs, MOUSE_CSR) = MOUSE_CLK_EN+0x3000;
				}
			}
			if (i == 9) { // Send the Stop bit
				REG16(v_pIoRegs, MOUSE_CSR) = 0x6800; // set CLOCK low to hold off ACK
			}
		}
	}

	/* Wait for 90 us. */
	BusyWait( Delay_90uS );
	REG16(v_pIoRegs, MOUSE_CSR) = 0x3800;		// set CLOCK tri-state DATA high

	/* Wait for 30 us. */
	BusyWait( Delay_30uS );
	k = REG16(v_pIoRegs, MOUSE_CSR);
	REG16(v_pIoRegs, MOUSE_ISR) = MOUSE_RDRF;	// clear any waiting data

	if (MouseInterruptControl) {

/* We should try to receive the ACK from the mouse here but when 
 * the interrupt is enabled the hardware just will not cooperate.
 *
 * So inplace of doing the correct this we just waste 2,000 microseconds
 * and hope that the ACK came in. If the ACK is late it will be processed
 * as a data packet byte. This causes some other problems.
 */
		REG16(v_pIoRegs, MOUSE_CSR) = 0;			// Disable Mouse input

		/* Wait for 2000 us. */
		BusyWait( Delay_2000uS );
//NKDbgPrintfW(L"ps2p465.cpp MouseCommandPut(%02X), delay while ACK comes in.\r\n",ui8Cmd);
	}
	else {

		REG16(v_pIoRegs, MOUSE_CSR) = MOUSE_CLK_EN;
		MousePollRead(&ui8Data);

//NKDbgPrintfW(L"ps2p465.cpp MouseCommandPut(%02X), data: %02X\r\n",ui8Cmd,ui8Data);

	}
	/* Enable the Mouse input again. */
	REG16(v_pIoRegs, MOUSE_CSR) = MOUSE_CLK_EN;

	return TRUE;

error_exit:
	// Still Enable the interrupts. So that if the mouse is plugged in later
	// on, it'll work.

//NKDbgPrintfW(L"ps2p465.cpp MouseCommandPut(%02X), Error.\r\n",ui8Cmd);

	REG16(v_pIoRegs, MOUSE_ISR) = MOUSE_RDRF;
	REG16(v_pIoRegs, MOUSE_CSR) = MOUSE_CLK_EN;

	return FALSE;

}

/*++

Ps2P465::
Initialize:

Initializes the Ps2P465 object.


--*/
BOOL
Ps2P465::
Initialize(
	PVBYTE	iopBase
	)
{

	m_iopBase = iopBase;

	m_bMouseFound = FALSE;
	MouseInterruptControl = 0;
	KeyboardInterruptControl = 0;

	if ( MouseTest() )
		{
		m_bMouseFound = TRUE;
		MouseCommandPut(cmdMouseEnable);
		}


	return TRUE;
}


BOOL
KeybdDriverInitializeAddresses(
	void
	)
{

	Delay_30uS   = AdjustMicroSecondsToLoopCount( 30 );
	Delay_90uS   = AdjustMicroSecondsToLoopCount( 90 );
	Delay_180uS  = AdjustMicroSecondsToLoopCount( 180 );
	Delay_2000uS = AdjustMicroSecondsToLoopCount( 2000 );

    //  Map HD64465 PS/2 interface base address
	v_pIoRegs = (PVBYTE)VirtualAlloc(0, 0x1000, MEM_RESERVE, PAGE_NOACCESS);
	if ( v_pIoRegs == NULL )
		{
		ERRORMSG(1,
			(TEXT("KeybdDriverInitializeAddresses: PS2 VirtualAlloc failed!\r\n")));
		goto error_return;
		}

	if ( !VirtualCopy((PVOID)v_pIoRegs, (PVOID)(dwHD64465Base + HD64465_KBC_OFFSET), 0x1000, PAGE_READWRITE|PAGE_NOCACHE) )
		{
		ERRORMSG(1,
			(TEXT("KeybdDriverInitializeAddresses: PS2 VirtualCopy failed!\r\n")));
		goto error_return;
		}

    // Set the register properly to receive
	REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN;

    // Clear any initial interrupts
	REG16(v_pIoRegs, KB_ISR) = KB_RDRF;

    // Set the register properly to receive after clearing interrupt
	REG16(v_pIoRegs, KB_CSR) = KB_CLK_EN;

	return TRUE;

error_return:
	if ( v_pIoRegs )
		VirtualFree((PVOID)v_pIoRegs, 0, MEM_RELEASE);
	v_pIoRegs = 0;
	return FALSE;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -