📄 window.c
字号:
pPcConfigReg = SMC_PCCONFIG_MEM1;
}
else if ((v_WinInfo[uWindow].fWindowCaps & WIN_CAP_IO) == WIN_CAP_IO)
{
//
// I/O memory
//
pPcConfigReg = SMC_PCCONFIG_IO1;
}
else if ((v_WinInfo[uWindow].fWindowCaps & WIN_CAP_ATTRIBUTE) == WIN_CAP_ATTRIBUTE)
{
//
// attribute memory
//
pPcConfigReg = SMC_PCCONFIG_ATT1;
}
else
{
DEBUGMSG(ZONE_PDD, (TEXT("Bad fWindowCaps in WinInfo[%d]\r\n"), uWindow));
return CERR_BAD_WINDOW;
}
//
// Check to see if the Windows is enabled.
//
if (pWindowState->fState & WIN_STATE_ENABLED)
{
//
// Set the desired speed.
//
// The PCMCIA spec only defines speeds of 600ns, 300ns, 250ns, 200ns, 150ns, and 100ns;
// therefore, all requests must be rounded to one of these values.
//
if ((v_WinInfo[uWindow].fWindowCaps & WIN_CAP_COMMON) == WIN_CAP_COMMON)
{
UINT8 exp = pWindowState->fSpeed & WIN_SPEED_EXP_MASK;
UINT8 mant = pWindowState->fSpeed & WIN_SPEED_MANT_MASK;
//
// 301ns and slower, set to 600ns
//
if ((exp >= WIN_SPEED_EXP_1US) || ((exp == WIN_SPEED_EXP_100NS) && (mant > WIN_SPEED_MANT_30)))
{
ulPcConfig |= CalculatePcmciaTimings( 600 );
}
//
// Check to see if it is 300ns
//
else if ((exp == WIN_SPEED_EXP_100NS) && (mant == WIN_SPEED_MANT_30))
{
ulPcConfig |= CalculatePcmciaTimings( 300 );
}
//
// Check to see if it is 250ns
//
else if ((exp == WIN_SPEED_EXP_100NS) && (mant == WIN_SPEED_MANT_25))
{
ulPcConfig |= CalculatePcmciaTimings( 250 );
}
//
// Check to see if it is 200ns
//
else if ((exp == WIN_SPEED_EXP_100NS) && (mant == WIN_SPEED_MANT_20))
{
ulPcConfig |= CalculatePcmciaTimings( 200 );
}
//
// Check to see if it is 150ns
//
else if ((exp == WIN_SPEED_EXP_100NS) && (mant == WIN_SPEED_MANT_15))
{
ulPcConfig |= CalculatePcmciaTimings( 150 );
}
//
// 100ns and faster, set to 100ns
//
else
{
ulPcConfig |= CalculatePcmciaTimings(100);
}
}
//
// All I/O accesses are the same speed per PCMCIA spec
//
else if ((v_WinInfo[uWindow].fWindowCaps & WIN_CAP_IO) == WIN_CAP_IO)
{
ulPcConfig |= CalculatePcmciaTimings(0);
}
else // if ((v_WinInfo[uWindow].fWindowCaps & WIN_CAP_ATTRIBUTE) == WIN_CAP_ATTRIBUTE)
{
//
// 5v attr access timings (they are faster than 3.3v)
//
if (v_WinInfo[uWindow].fSockets == 50)
{
ulPcConfig |= CalculatePcmciaTimings(300);
}
//
// 3.3v attr access timings
//
else
{
ulPcConfig |= CalculatePcmciaTimings(600);
}
}
}
else
{
ulPcConfig = PCCONFIG_ADDRESSTIME_MASK |
PCCONFIG_HOLDTIME_MASK |
PCCONFIG_ACCESSTIME_MASK |
PCCONFIG_MW_8BIT;
}
//
// Check to see if we need to set the window to 8 or 16 bit access.
//
if (pWindowState->fState & WIN_STATE_16BIT)
{
ulPcConfig |= PCCONFIG_MW_16BIT;
DEBUGMSG(ZONE_PDD, (TEXT("Setting window %x to 16 bit access\r\n"), uWindow));
}
else
{
ulPcConfig |= PCCONFIG_MW_8BIT;
DEBUGMSG(ZONE_PDD, (TEXT("Setting window %x to 8 bit access\r\n"), uWindow));
}
//
// Enable the critical section.
//
if ( bUserMode )
{
EnterCriticalSection(&g_PCIC_Crit);
}
//
// Set up the MCWAITn configuration. Note: Since this is a global setting,
// if any window wants the USE_WAIT, then they all get it. This is fine since
// this is typically the way you'd want it anyways.
//
//if ((pWindowState->fSpeed & WIN_SPEED_USE_WAIT) == WIN_SPEED_USE_WAIT)
//{
// //
// // Set WEN bit to use WAIT
// //
// *SMC_PCCONT |= PCCONT_WEN1;
//}
//else
//{
// //
// // Clear bit to not use Wait
// //
// *SMC_PCCONT &= ~PCCONT_WEN1;
//}
//
// Write the new PCCONFIG register settings.
//
*pPcConfigReg = ulPcConfig;
if (bUserMode)
{
LeaveCriticalSection(&g_PCIC_Crit);
}
v_WinState[uWindow].fSpeed = pWindowState->fSpeed;
v_WinState[uWindow].fState = pWindowState->fState;
v_WinState[uWindow].uSize = pWindowState->uSize;
v_WinState[uWindow].uOffset = pWindowState->uOffset;
//
if (uWindow == PCMCIA_IO_WINDOW)
{
pWindowState->uOffset = 0;
}
DEBUGMSG (1,(TEXT("--PDCardSetWindow\n\r")));
return CERR_SUCCESS;
} // PDCardSetWindow
//****************************************************************************
// PDCardInquireWindow
//****************************************************************************
// @func STATUS | PDCardInquireWindow | Report the characteristics and capabilities
// of a memory or I/O window
// @rdesc Returns one of the CERR_* error codes in cardserv.h
//
STATUS PDCardInquireWindow
(
UINT32 uWindow, // @parm Window number (the first window is 0)
PPDCARD_WINDOW_INFO pWinInfo // @parm Pointer to a PDCARD_WINDOW_INFO structure.
)
{
if (uWindow >= PCMCIA_NUM_WINDOWS)
{
return CERR_BAD_WINDOW;
}
EnterCriticalSection(&g_PCIC_Crit);
memcpy(pWinInfo, &v_WinInfo[uWindow], sizeof(PDCARD_WINDOW_INFO));
LeaveCriticalSection(&g_PCIC_Crit);
return CERR_SUCCESS;
}
//****************************************************************************
// CalculatePcmciaTimings
//****************************************************************************
// Calculate the pcmcia timings based on the register settings.
// For example here is for Attribute/Memory Read.
//
//
// Address: _______XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX___________
//
// Data: __________________________XXXXXXXXXXXXXX________________________
//
// CE#: -------______________________________________________-----------
//
// REG#: -------______________________________________________-----------
//
// OE#: --------------------___________________-------------------------
//
//
// |<---------------Cycle time ----------------->|
//
// |< Address >|<-- Access Time -->|< Hold Time >|
// Time ta(CE) th(CE)
// tsu(A)
//
// See PCMCIA Electrical Specification Section 4.7 for the timing numbers.
//
//
//
UINT32 CalculatePcmciaTimings
(
UINT32 NsSpeed
)
{
ULONG ulAddressTime;
ULONG ulHoldTime;
ULONG ulAccessTime;
ULONG ulSMC;
ULONG ulHCLK = REAL_HCLOCK;
ULONG ulHPeriod;
ULONG ulHAccessTime;
ULONG ulHAddressTime;
ULONG ulHHoldTime;
switch(NsSpeed)
{
case 600:
case 0:
default:
ulAccessTime = 600;
ulAddressTime = 100;
ulHoldTime = 35;
break;
case 300:
ulAccessTime = 300;
ulAccessTime = 300;
ulAddressTime = 30;
ulHoldTime = 20;
break;
case 250:
ulAccessTime = 250 - 30 - 20;
ulAddressTime = 30;
ulHoldTime = 20;
break;
case 200:
ulAccessTime = 200 - 20 - 20;
ulAddressTime = 20;
ulHoldTime = 20;
break;
case 150:
ulAccessTime = 150 - 20 - 20;
ulAddressTime = 20;
ulHoldTime = 20;
break;
case 100:
ulAccessTime = 100 - 10 - 15;
ulAddressTime = 10;
ulHoldTime = 15;
break;
//
// Special case for I/O all access.
//
//case 0:
// ulAccessTime = 165 - 70 - 20;
// ulAccessTime = 200;
// ulAddressTime = 70;
// ulHoldTime = 20;
// break;
}
//
// Add in a board delay.
//
ulAccessTime += PCMCIA_BOARD_DELAY;
ulAddressTime += PCMCIA_BOARD_DELAY;
ulHoldTime += PCMCIA_BOARD_DELAY;
//
// This gives us the period in nanosecods.
//
// = 1000000000 (ns/s) / HCLK (cycle/s)
//
// = (ns/cycle)
//
ulHPeriod = (1000000000/ ulHCLK);
//
// Find the number of hclk cycles for cycle time, address time and
// hold time.
//
// = ulAccessTime (ns) / ulHPeriod (ns/Cycles)
// = ulAddressTime (ns) / ulHPeriod (ns/Cycles)
// = ulHoldTime (ns) / ulHPeriod (ns/Cycles)
//
ulHAccessTime = (ulAccessTime + ulHPeriod - 1) / ulHPeriod;
if(ulHAccessTime > 0xFF)
{
ulHAccessTime = 0xFF;
}
ulHAddressTime = (ulAddressTime + ulHPeriod - 1) / ulHPeriod;
if(ulHAddressTime > 0xFF)
{
ulHAddressTime = 0xFF;
}
ulHHoldTime = ((ulHoldTime + ulHPeriod - 1) / ulHPeriod) + 1;
if(ulHHoldTime >0xF)
{
ulHHoldTime = 0xF;
}
ulSMC = (PCCONFIG_ADDRESSTIME_MASK & (ulHAddressTime << PCCONFIG_ADDRESSTIME_SHIFT)) |
(PCCONFIG_HOLDTIME_MASK & (ulHHoldTime << PCCONFIG_HOLDTIME_SHIFT)) |
(PCCONFIG_ACCESSTIME_MASK & (ulHAccessTime << PCCONFIG_ACCESSTIME_SHIFT)) ;
return ulSMC;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -