📄 hdq.c
字号:
// Function: HDQ_Write
//
// This function writes a byte of data in 8 bit mode to the specified address.
//
BOOL HDQ_Write(DWORD context, UCHAR address, USHORT data)
{
BOOL rc=FALSE;
HDQ_DEVICE* pDevice=(HDQ_DEVICE*)context;
OMAP2420_HDQ_REGS* pHDQRegs;
DWORD status, i, count;
UCHAR buffer[3];
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"+++HDQ_Write(0x%08x, 0x%02x, 0x%x)\r\n", context, address, data));
// Check if we get correct context
if(pDevice==NULL || pDevice->cookie!=HDQ_DEVICE_COOKIE)
{
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Write: "
L"Incorrect context parameter\r\n"));
goto exit;
};
// Get hardware
pHDQRegs=pDevice->pHDQRegs;
EnterCriticalSection(&pDevice->cs);
// Make sure that clock is present
SetDevicePowerState(pDevice->hParentBus, D0, NULL);
HDQ_PowerUp(context);
// Clear the interrupt
status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Write: "
L"Interrupt status (1) was 0x%02x\r\n", status));
// Need to notify InterruptDone right away
InterruptDone(pDevice->sysIntr);
// Send initialization pulse in 1-wire mode
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_INITIALIZATION);
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);
// Wait on completion interrupt (not documented)
if(WaitForSingleObject(pDevice->hIntrEvent, pDevice->breakTimeout) == WAIT_TIMEOUT)
{
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Write: "
L"Timeout in init pulse\r\n"));
}
// Clear the interrupt
status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Write: "
L"Interrupt status (2) was 0x%02x\r\n", status));
// Need to notify InterruptDone right away
InterruptDone(pDevice->sysIntr);
// Back to HDQ mode.
CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
// We are going to do a write so set write bit in the address
buffer[0]=address|0x80;
buffer[1]=(UCHAR)data;
switch(pDevice->mode)
{
case HDQ_MODE_HDQ8:
count=2;
break;
case HDQ_MODE_HDQ16:
buffer[2]=(UCHAR)(data >> 8);
count=3;
break;
}
// Two write cycles required
for(i=0; i < count; i++)
{
// Write the value, set the direction and go
OUTREG32(&pHDQRegs->ulHDQ_TX_DATA, buffer[i]);
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_DIR); //sr
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);
// Wait on TX complete interrupt.
if (WaitForSingleObject(pDevice->hIntrEvent, pDevice->txTimeout)==WAIT_TIMEOUT)
{
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Write: "
L"Timeout in Tx\r\n"));
goto cleanUp;
}
// Clear the interrupt
status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
InterruptDone(pDevice->sysIntr);
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Write: "
L"Interrupt status (%d) was 0x%x\r\n", 3 + i, status));
// Verify interrupt source
if((status & HDQ_INT_STATUS_TXCOMPLETE)==0)
{
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Write: "
L"TX complete expected (0x%x)\r\n", status));
goto cleanUp;
}
};
// Done
rc=TRUE;
cleanUp:
SetDevicePowerState(pDevice->hParentBus, D4, NULL);
LeaveCriticalSection(&pDevice->cs);
exit:
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"---HDQ_Write(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: HDQ_Read
//
// This function reads from the specified address data in HDQ mode.
//
BOOL HDQ_Read(DWORD context, UCHAR address, USHORT* pData)
{
BOOL rc=FALSE;
HDQ_DEVICE* pDevice=(HDQ_DEVICE*)context;
OMAP2420_HDQ_REGS* pHDQRegs=NULL;
DWORD status, count, i;
UCHAR buffer[2];
//
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"+++HDQ_Read(0x%08x, 0x%02x, 0x%08x)\r\n", context, address, pData));
Sleep(cliDelay1); // tentaive
// Check if we get correct context
if(pDevice==NULL || pDevice->cookie!=HDQ_DEVICE_COOKIE)
{
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_Read: "
L"Incorrect context parameter\r\n"));
goto exit;
}
// Get hardware
pHDQRegs=pDevice->pHDQRegs;
EnterCriticalSection(&pDevice->cs);
// Make sure that clock is present
SetDevicePowerState(pDevice->hParentBus, D0, NULL);
HDQ_PowerUp(context);
switch(pDevice->mode)
{
case HDQ_MODE_HDQ8:
count=1;
break;
case HDQ_MODE_HDQ16:
count=2;
break;
};
// Clear the interrupt.
status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Read: "
L"Interrupt status (1) was 0x%02x\r\n", status));
// Need to notify InterruptDone right away
InterruptDone(pDevice->sysIntr);
// Step 0: send break pulse
// get into status mode; Send break pulse in HDQ mode
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_INITIALIZATION);
// DEBUGMSG(ZONE_HDQ_1WIRE, (L"\tHDQ_Read: 1) Will Send out the break pulse and wait for %ld msec.\r\n",pDevice->breakTimeout));
// DEBUGMSG(ZONE_HDQ_1WIRE, (L"\tHDQ_Read: 2) Next switch to Write mode, send out register Nr and wait for %ld msec.\r\n",pDevice->txTimeout));
// DEBUGMSG(ZONE_HDQ_1WIRE, (L"\tHDQ_Read: 3) Then switch to Read mode and wait for %ld msec.\r\n",pDevice->rxTimeout));
// switch to go mode
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);
// Wait for completion of break pulse to be sent out
// there are no interrupts set on break pulse, so just wait for it to be sent out
Sleep(cliDelay2); // was Sleep(pDevice->breakTimeout); 0.32 msec or so
// Back to HDQ mode.
CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
// Step 1:
// Write the value,
OUTREG32(&pHDQRegs->ulHDQ_TX_DATA, address); //
// Step 2: set the direction as Write and go
CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_DIR); // was SET
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);
//
// Wait on completion on transmit data
if(WaitForSingleObject(pDevice->hIntrEvent, pDevice->txTimeout)==WAIT_TIMEOUT)
{
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"ERROR !! HDQ_Read(): "
L"Timeout in TX for %ld msec.\r\n",pDevice->txTimeout));
// goto cleanUp;
}
// Clear interrupt
status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Read: "
L"Interrupt status (3) was 0x%02x\r\n", status));
// Need to notify InterruptDone right away
InterruptDone(pDevice->sysIntr);
// Verify that register address was sent out completely.
if((status & HDQ_INT_STATUS_TXCOMPLETE)==0)
{ // sr further timing adjustment may be helpful. It works with current settings well so disregard this msg
DEBUGMSG(ZONE_HDQ_1WIRE, (L"ERROR: HDQ_Read: "
L"TX complete expected (0x%02x)\r\n", status));
// goto cleanUp;
}
else
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"\tHDQ_Read: "
L"TX completed (0x%02x) ok.\r\n", status));
// pre-Step 3:
status=0; // INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
for(i=0; i<count; i++)
{
// The RX is slave driven, if we are slow byte can be already done.
if((status & HDQ_INT_STATUS_RXCOMPLETE)==0)
{
// Indicate read & go: 0 to Read bit, 1 to GO bit
// Step 3:
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_DIR); // was CLR
SETREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_GO);
Sleep(cliDelay3);
// Wait on RX complete interrupt
if(WaitForSingleObject(pDevice->hIntrEvent, pDevice->rxTimeout)==WAIT_TIMEOUT)
{
DEBUGMSG(ZONE_ERROR, (L"ERROR: HDQ_Read: "
L"Timeout on RX at %ld msec\r\n",pDevice->rxTimeout));
goto cleanUp;
}
// Clear interrupt
status=INREG32(&pHDQRegs->ulHDQ_INT_STATUS);
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Read: "
L"Interrupt status (5) was 0x%02x\r\n", status));
// Reenable interrupt
InterruptDone(pDevice->sysIntr);
}
// Verify interrupt source
if((status & HDQ_INT_STATUS_RXCOMPLETE)==0)
{
DEBUGMSG(ZONE_HDQ_1WIRE, (L"ERROR: HDQ_Read: "
L"RX complete expected (0x%02x)\r\n", status));
// goto cleanUp;
}
// Get data
buffer[i]=(UCHAR)INREG32(&pHDQRegs->ulHDQ_RX_DATA);
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"\tHDQ_Read: "
L"RX completed data=0x%02x\r\n", buffer[i]));
// Make sure we set GO bit on next byte
status=0;
};
switch (pDevice->mode)
{
case HDQ_MODE_HDQ8:
*pData=buffer[0];
break;
case HDQ_MODE_HDQ16:
*pData=buffer[0]|(buffer[1] << 8);
break;
}
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_Read: "
L"Address:=0x%02x, Data:=0x%02x\r\n", address, *pData));
// Done
rc=TRUE;
//
cleanUp:
SetDevicePowerState(pDevice->hParentBus, D4, NULL); // power off the hdq device
LeaveCriticalSection(&pDevice->cs);
//
exit:
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"---HDQ_Read(rc=%01ld)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: HDQ_SetMode
//
BOOL HDQ_SetMode(DWORD context, DWORD mode)
{
BOOL rc = FALSE;
HDQ_DEVICE *pDevice = (HDQ_DEVICE*)context;
OMAP2420_HDQ_REGS *pHDQRegs;
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"+HDQ_SetMode(0x%08x, %d)\r\n", context, mode));
// Check if we get correct context
if (pDevice == NULL || pDevice->cookie != HDQ_DEVICE_COOKIE)
{
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_SetMode: "
L"Incorrect context paramer\r\n"));
goto cleanUp;
};
pHDQRegs = pDevice->pHDQRegs;
switch (mode)
{
case HDQ_MODE_HDQ8:
CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
pDevice->mode = HDQ_MODE_HDQ8;
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_SetMode: "
L"New mode HDQ8\r\n"));
rc = TRUE;
break;
case HDQ_MODE_HDQ16:
CLRREG32(&pHDQRegs->ulHDQ_CTRL_STATUS, HDQ_CTRL_STATUS_MODE);
pDevice->mode = HDQ_MODE_HDQ16;
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_INFO, (L"HDQ_SetMode: "
L"New mode HDQ16\r\n"));
rc = TRUE;
break;
default:
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_ERROR, (L"ERROR: HDQ_SetMode: "
L"Unsupported mode requested (mode = 0x%x)\r\n", mode));
}
cleanUp:
DEBUGMSG(ZONE_HDQ_1WIRE | ZONE_FUNCTION, (L"-HDQ_SetMode(rc = 0x%x)\r\n", rc));
return rc;
}
/*#ifdef RETAIL_DEBUG
#pragma optimize("", on) // debug
#endif*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -