📄 socket.c
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995, 1996, 1997 Microsoft Corporation
Copyright (c) 1998 NEC Electronics Inc.
Module Name:
socket.c
Abstract:
This is provided as a sample for VRC4173 to platform writers.
Functions:
PDCardGetSocket()
PDCardSetSocket()
PDCardSetSocketIreq()
PDCardInquireAdapter()
PDCardResetSocket()
PDCardGetAdapter()
PDCardSetAdapter()
Notes:
Last Update : 8/4/99
--*/
#include <windows.h>
#include <types.h>
#include <cardserv.h>
#include <sockserv.h>
#include <sockpd.h>
#include <memory.h>
#include <drvlib.h>
#define NUM_SOCKETS 2
#define NUM_POWER_ENTRIES 3
extern volatile UINT8 *v_pPcmciaCSR1; // The CSR register for slot#0
extern volatile UINT8 *v_pPcmciaCSR2; // The CSR register for slot#1
extern CRITICAL_SECTION v_MemAccessCrit;
//
// @doc DRIVERS
//
PDCARD_ADAPTER_INFO v_AdapterInfo = {
1, // memory granularity (for production platforms, this should be 1)
0, // adapter capabilities
8, // cache line size in 32-bit words
NUM_POWER_ENTRIES
};
PDCARD_POWER_ENTRY v_PowerEntries[NUM_POWER_ENTRIES] = {
{ 0, PWR_SUPPLY_VCC | PWR_SUPPLY_VPP1 | PWR_SUPPLY_VPP2 },
{ 33, PWR_SUPPLY_VCC | PWR_SUPPLY_VPP1 | PWR_SUPPLY_VPP2 },
{ 50, PWR_SUPPLY_VCC | PWR_SUPPLY_VPP1 | PWR_SUPPLY_VPP2 }
};
PDCARD_SOCKET_STATE v_SockState[NUM_SOCKETS] = {
{
SOCK_CAP_IO,
EVENT_MASK_BATTERY_DEAD|EVENT_MASK_BATTERY_LOW|EVENT_MASK_CARD_DETECT, // status change interrupt mask
0, // present socket state
0, // control and indicators
0, // interface type
0, // IREQ control, Enable/Disable XXX, bug fix for NEC
0, // Vcc
0, // Vpp1
0 // Vpp2
}
,{
SOCK_CAP_IO,
EVENT_MASK_BATTERY_DEAD|EVENT_MASK_BATTERY_LOW|EVENT_MASK_CARD_DETECT, // status change interrupt mask
0, // present socket state
0, // control and indicators
0, // interface type
0, // IREQ Control, Enable/Disable
0, // Vcc
0, // Vpp1
0 // Vpp2
}
};
VOID SetupWindows(VOID)
{
PDCARD_WINDOW_STATE WinState;
DWORD status;
int i;
//
// Initialize the memory and I/O windows
//
status = CERR_SUCCESS;
i = 0;
while (status == CERR_SUCCESS) {
status = PDCardGetWindow(i, &WinState);
if (status == CERR_SUCCESS) {
//
// on init only setup non-I/O windows
//
if (!(WinState.fState & WIN_STATE_MAPS_IO))
status = PDCardSetWindow(i, &WinState);
}
i++;
}
}
//
// PDCardGetSocket
//
// @func STATUS | PDCardGetSocket | Get the socket state of the specified socket.
// @rdesc Returns one of the CERR_* return codes in cardserv.h.
//
// @comm This function reads the specified socket's state and returns it in
// the PDCARD_SOCKET_STATE structure.
//
STATUS
PDCardGetSocket(
UINT32 uSocket, // @parm Socket number (first socket is 0)
PPDCARD_SOCKET_STATE pState // @parm Pointer to PDCARD_SOCKET_STATE structure
)
{
UINT8 tmp;
if (uSocket >= NUM_SOCKETS) {
return CERR_BAD_SOCKET;
}
EnterCriticalSection(&g_PCIC_Crit);
memcpy(pState, &v_SockState[uSocket], sizeof(PDCARD_SOCKET_STATE));
if (uSocket)
tmp = PD365Read2(INDEX_INTERFACE_STATUS);
else
tmp = PD365Read1(INDEX_INTERFACE_STATUS);
pState->fNotifyEvents = 0; // Start off with nothing
if ((tmp & DATA_CARD_DETECT_CD1) && (tmp & DATA_CARD_DETECT_CD2)) {
pState->fNotifyEvents |= EVENT_MASK_CARD_DETECT;
}
if (tmp & DATA_WRITE_PROTECT) {
pState->fNotifyEvents |= EVENT_MASK_WRITE_PROTECT;
}
if (~tmp & DATA_BATTERY_VOLTAGE_DETECT_BVD1) {
DEBUGMSG(ZONE_PDD,
(TEXT("<< GET >> DATA_BATTERY_DEAD_OR_STS_CHG \r\n")));
pState->fNotifyEvents |= EVENT_MASK_BATTERY_DEAD ;
} else if (~tmp & DATA_BATTERY_VOLTAGE_DETECT_BVD2) {
DEBUGMSG(ZONE_PDD,(TEXT("<< GET >> DATA_BATTERY_WARNING \r\n")));
pState->fNotifyEvents |= EVENT_MASK_BATTERY_LOW;
}
// According to 4171 spec, 1 == 'PC_Card is ready'
if (~tmp & DATA_READY_BUSY) {
DEBUGMSG(ZONE_PDD,(TEXT("<< GET >> DATA_READY_CHANGE \r\n")));
pState->fNotifyEvents |= EVENT_MASK_CARD_READY;
}
if (uSocket)
tmp = PD365Read2(INDEX_INTERRUPT_AND_GENERAL_CONTROL);
else
tmp = PD365Read1(INDEX_INTERRUPT_AND_GENERAL_CONTROL);
if (tmp & DATA_CARD_IS_IO) {
DEBUGMSG(ZONE_PDD,(TEXT("<< GET >> DATA_CARD_IS_IO \r\n")));
pState->fInterfaceType = CFG_IFACE_MEMORY_IO ; // I/O TYPE SET
} else {
DEBUGMSG(ZONE_PDD,(TEXT("<< GET >> DATA_CARD_IS_MEMORY \r\n")));
pState->fInterfaceType = CFG_IFACE_MEMORY ; // MEMORY TYPE SET
}
if ((tmp & (DATA_IRQ_BIT0|DATA_IRQ_BIT1)) == (DATA_IRQ_BIT0|DATA_IRQ_BIT1)) {
pState->fIREQRouting = SOCK_IREQ_ENABLE;
}
pState->fControlCaps |= SOCK_ENABLE_SPEAKER;
LeaveCriticalSection(&g_PCIC_Crit);
return CERR_SUCCESS;
}
//
// PDCardSetSocket
//
// @func STATUS | PDCardSetSocket | Set the socket state of the specified socket.
// @rdesc Returns one of the CERR_* return codes in cardserv.h.
//
// @comm This function sets the specified socket's state and adjusts the socket
// controller appropriately.
// PDCardGetSocketState will usually be called first and adjustments will
// be made to the PDCARD_SOCKET_STATE structure before PDCardSetSocketState
// is called. This avoids duplicated socket state on different layers and
// it avoids unintentionally setting socket parameters.
//
// @xref <f PDCardGetSocketState>
//
STATUS
PDCardSetSocket(
UINT32 uSocket, // @parm Socket number (first socket is 0)
PPDCARD_SOCKET_STATE pState // @parm Pointer to PDCARD_SOCKET_STATE structure
)
{
UINT8 fIntMask1 = 0;
UINT8 fIntMask2 = 0;
UINT8 CardIsMemoryToIo = 0;
if (uSocket >= NUM_SOCKETS) {
return CERR_BAD_SOCKET;
}
fIntMask1 = DATA_READY_ENABLE;
if (pState->fInterruptEvents & EVENT_MASK_BATTERY_DEAD) {
DEBUGMSG(ZONE_PDD,(TEXT("<< SET >> EVENT_MASK_BATTERY_DEAD \r\n")));
fIntMask1 |= DATA_BATTERY_DEAD_STSCHG_ENABLE ;
}
if (pState->fInterruptEvents & EVENT_MASK_BATTERY_LOW) {
DEBUGMSG(ZONE_PDD,(TEXT("<< SET >> EVENT_MASK_BATTERY_LOW \r\n")));
fIntMask1 |= DATA_BATTERY_WARNING_ENABLE ;
}
if (pState->fInterruptEvents & EVENT_MASK_CARD_DETECT) {
DEBUGMSG(ZONE_PDD,(TEXT("<< SET >> EVENT_MASK_CARD_DETECT \r\n")));
fIntMask1 |= DATA_CARD_DETECT_ENABLE ;
}
EnterCriticalSection(&g_PCIC_Crit);
if (uSocket) {
PD365Write2(INDEX_MANAGEMENT_INTERRUPT_CONFIGURATION,fIntMask1);
} else {
PD365Write1(INDEX_MANAGEMENT_INTERRUPT_CONFIGURATION,fIntMask1);
}
fIntMask2 = DATA_CARD_RESET;
if (pState->fInterfaceType & CFG_IFACE_MEMORY_IO) {
fIntMask2 |= DATA_CARD_IS_IO;
if (uSocket) {
if ( !(PD365Read2(INDEX_INTERRUPT_AND_GENERAL_CONTROL) & DATA_CARD_IS_IO) ) {
CardIsMemoryToIo = 1;
}
} else {
if ( !(PD365Read1(INDEX_INTERRUPT_AND_GENERAL_CONTROL) & DATA_CARD_IS_IO) ) {
CardIsMemoryToIo = 1;
}
}
}
if (pState->fIREQRouting & SOCK_IREQ_ENABLE) {
DEBUGMSG(ZONE_PDD,
(TEXT("<< SET >> IREQRouting & SOCK_IREQ_ENABLE \r\n")));
// VRC4173 doesn't support Interrupt Routing.
// fIntMask |= DATA_IRQ_BIT0|DATA_IRQ_BIT1;
}
// To avoid continuing interrupt, INDEX_CARD_STATUS_CHANGE register must be read,
// just before DATA_CARD_IS_IO bit is changed from 0 to 1
if (uSocket) {
if ( CardIsMemoryToIo == 1 ) {
PD365Read2(INDEX_CARD_STATUS_CHANGE); // Interrupt Clear
CardIsMemoryToIo = 0;
}
PD365Write2(INDEX_INTERRUPT_AND_GENERAL_CONTROL,fIntMask2);
} else {
if ( CardIsMemoryToIo == 1 ) {
PD365Read1(INDEX_CARD_STATUS_CHANGE); // Interrupt Clear
CardIsMemoryToIo = 0;
}
PD365Write1(INDEX_INTERRUPT_AND_GENERAL_CONTROL,fIntMask2);
}
memcpy(&v_SockState[uSocket], pState, sizeof(PDCARD_SOCKET_STATE));
LeaveCriticalSection(&g_PCIC_Crit);
return CERR_SUCCESS;
}
//
// PDCardInquireAdapter
//
// @func STATUS | PDCardInquireAdapter | Returns the socket controller's characteristics
// and capabilities.
// @rdesc Returns one of the CERR_* return codes in cardserv.h.
//
STATUS
PDCardInquireAdapter(
PPDCARD_ADAPTER_INFO pAdapterInfo // @parm Pointer to PDCARD_ADAPTER_INFO structure.
)
{
if (pAdapterInfo->uPowerEntries < NUM_POWER_ENTRIES) {
pAdapterInfo->uPowerEntries = NUM_POWER_ENTRIES;
return CERR_BAD_ARG_LENGTH;
}
// Copy the adapter info
memcpy(pAdapterInfo, &v_AdapterInfo, sizeof(PDCARD_ADAPTER_INFO));
pAdapterInfo = (PPDCARD_ADAPTER_INFO)(((UINT)pAdapterInfo) + sizeof(PDCARD_ADAPTER_INFO));
// Copy the power entries at the end
memcpy(pAdapterInfo, &v_PowerEntries, sizeof(v_PowerEntries));
return CERR_SUCCESS;
}
//
// PDCardResetSocket
//
// @func STATUS | PDCardResetSocket | Resets the specified socket.
// @rdesc Returns one of the CERR_* return codes in cardserv.h.
//
STATUS
PDCardResetSocket(
UINT32 uSocket // @parm Socket number (first socket is 0)
)
{
int t;
PDCARD_SOCKET_STATE State;
UINT8 tmp;
EnterCriticalSection(&g_PCIC_Crit);
//
// If there is a card inserted, then reset it.
//
if (uSocket)
tmp = PD365Read2(INDEX_INTERFACE_STATUS);
else
tmp = PD365Read1(INDEX_INTERFACE_STATUS);
if ((tmp & DATA_CARD_DETECT_CD1) && (tmp & DATA_CARD_DETECT_CD2)) {
Sleep(10);
EnterCriticalSection( &v_MemAccessCrit );
//
// Assert the RESET signal for 1 ms
//
if (uSocket) {
PD365Write2(INDEX_INTERRUPT_AND_GENERAL_CONTROL,
(UINT8)(PD365Read2(INDEX_INTERRUPT_AND_GENERAL_CONTROL) & ~DATA_CARD_RESET));
Sleep(1);
PD365Write2(INDEX_INTERRUPT_AND_GENERAL_CONTROL,
(UINT8)(PD365Read2(INDEX_INTERRUPT_AND_GENERAL_CONTROL) | DATA_CARD_RESET));
} else {
PD365Write1(INDEX_INTERRUPT_AND_GENERAL_CONTROL,
(UINT8)(PD365Read1(INDEX_INTERRUPT_AND_GENERAL_CONTROL) & ~DATA_CARD_RESET));
Sleep(1);
PD365Write1(INDEX_INTERRUPT_AND_GENERAL_CONTROL,
(UINT8)(PD365Read1(INDEX_INTERRUPT_AND_GENERAL_CONTROL) | DATA_CARD_RESET));
}
//
// Wait at least 20 ms before checking RDY
//
Sleep(20);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -