Re: \Storage Card doesn't always reload when ATADISK reloaded



Andrew,

The door switch is not in the CF spec and it does not really indicate the actual insertion state of the CF card. Usually this is used as an additional signal in the system to disable access to the card. I've seen this used extensively on digital cameras.

The card detect signals (which are defined in the PCMCIA/CF spec) are already handled in PCMCIA.DLL. This is what the OS is monitoring for insertion/removal notification.

If your CF card is modeled after a PCMCIA card, then you can get notification of an insertion and removal by registering for PCMCIA event notifications. Here is how I did it.

Also, at startup, if there is a CF in the slot, I think the OS generates an insertion signal artificially.

Nick.


PCMCIAHelper.H file: #include <cardserv.h>

// define the function prototypes.
// define PCMCIA_CARD_REGISTER_CLIENT as a pointer to a function that returns
// a CARD_CLIENT_HANDLE and takes CLIENT_CALLBACK and PCARD_REGISTER_PARMS as
// parameters.
typedef CARD_CLIENT_HANDLE (CALLBACK* PCMCIA_CARD_REGISTER_CLIENT) (CLIENT_CALLBACK, PCARD_REGISTER_PARMS);


// define PCMCIA_CARD_DEREGISTER_CLIENT as a pointer to a function that returns
// a STATUS and takes CARD_CLIENT_HANDLE as a parameter.
typedef STATUS (CALLBACK* PCMCIA_CARD_DEREGISTER_CLIENT) (CARD_CLIENT_HANDLE);


// define PCMCIA_CARD_GET_STATUS as a pointer to a function that returns
// a STATUS and takes PCARD_STATUS as a parameter.
typedef STATUS				(CALLBACK* PCMCIA_CARD_GET_STATUS) (PCARD_STATUS);


PCMCIAHelper.C file:

#include <windows.h>
#include <ceddk.h>

// Variables that are global to this module.
CARD_CLIENT_HANDLE hCard = NULL;
HINSTANCE hLibrary = NULL;

// pointers to the functions we need in PCMCIA.DLL
PCMCIA_CARD_REGISTER_CLIENT fnCardRegisterClient;
PCMCIA_CARD_DEREGISTER_CLIENT fnCardDeregisterClient;
PCMCIA_CARD_GET_STATUS fnCardGetStatus;

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  Function:

    PCMCIAEvent

  Description:

    Callback entry point for card insertion/removal notifications.

  Arguments:

	CardEvent - what happened.
	hSocket - which socket/function pair.
	pCardEventParms - additional stuff related to CardEvent.  This is event
	                  specific.

  Return Value:

	1

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
STATUS PCMCIAEvent(CARD_EVENT CardEvent, CARD_SOCKET_HANDLE hSocket, PCARD_EVENT_PARMS pCardEventParms)
{
CARD_STATUS card_status;
card_status.hSocket = hSocket;


// get our device state pointer so we can inform the rest of the system that something has happened.
PDEVICESTATE pds = (PDEVICESTATE) pCardEventParms->uClientData;


	switch(CardEvent)
	{
		case CE_CARD_REMOVAL:			// 0x05

			break;						

		case CE_CARD_INSERTION:			// 0x40
			// pCardEventParms->Parm1 contains the PC Card PnP ID String
			// pCardEventParms->Parm2 contains the driver handle
			
			break;

case CE_REGISTRATION_COMPLETE: // 0x82
// pCardEventParms->Parm1 contains the driver handle
fnCardGetStatus(&card_status);
DEBUGMSG(ZONE_PCMCIA, (_T("PCMCIAEvent:CE_REGISTRATION_COMPLETE:Socket=%d, Function=%d, Card State = 0x%08x, Socket State = 0x%08x"),hSocket.uSocket, hSocket.uFunction, card_status.fCardState, card_status.fSocketState));
break;


case CE_BATTERY_DEAD: // 0x01
case CE_BATTERY_LOW: // 0x02
case CE_CARD_LOCK: // 0x03
case CE_CARD_READY: // 0x04
case CE_CARD_UNLOCK: // 0x06
case CE_EJECTION_COMPLETE: // 0x07
case CE_EJECTION_REQUEST: // 0x08
case CE_INSERTION_COMPLETE: // 0x09
case CE_INSERTION_REQUEST: // 0x0A
case CE_PM_RESUME: // 0x0B
case CE_PM_SUSPEND: // 0x0C
case CE_EXCLUSIVE_COMPLETE: // 0x0D // pCardEventParms->Parm1 contains the exclusive status
case CE_EXCLUSIVE_REQUEST: // 0x0E
case CE_RESET_PHYSICAL: // 0x0F
case CE_RESET_REQUEST: // 0x10
case CE_CARD_RESET: // 0x11
case CE_MTD_REQUEST: // 0x12
case CE_CLIENT_INFO: // 0x14
case CE_TIMER_EXPIRED: // 0x15
case CE_SS_UPDATED: // 0x16
case CE_WRITE_PROTECT: // 0x17
case CE_RESET_COMPLETE: // 0x80
case CE_ERASE_COMPLETE: // 0x81
case CE_STATUS_CHANGE_INTERRUPT:// 0xFE
DEBUGMSG(ZONE_PCMCIA, (_T("PCMCIAEvent:Unhandled Event 0x%08x"),CardEvent));
break;
}


	return (STATUS) TRUE;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  Function:

    RegisterWithCardServices

  Description:

Regisers the callback function PCMCIAEvent with card services. When something
happens to the PCMCIA card (insertion/removal) we'll get notified.


++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
BOOL RegisterWithCardServices(PDEVICESTATE pds)
{
	BOOL rVal = FALSE;
	CARD_REGISTER_PARMS params;
	int state = 0;

// Get notified of everything. See EVENT_MASK_XXXX in the PB help for the flags.
params.fAttributes = CLIENT_ATTR_MTD_DRIVER | CLIENT_ATTR_NOTIFY_SHARED | CLIENT_ATTR_NOTIFY_EXCLUSIVE;


	params.fEventMask = 0xffff;

// when the callback happens we want to have access to our device state so pass
// a pointer to it here.
params.uClientData = (DWORD) pds;


hLibrary = LoadLibrary(L"PCMCIA.DLL");
if(NULL != hLibrary)
{
state++;
fnCardRegisterClient = (PCMCIA_CARD_REGISTER_CLIENT) GetProcAddress(hLibrary, L"CardRegisterClient");
if(NULL != fnCardRegisterClient)
{
state++;
fnCardDeregisterClient = (PCMCIA_CARD_DEREGISTER_CLIENT) GetProcAddress(hLibrary, L"CardDeregisterClient");
if(NULL != fnCardDeregisterClient)
{
state++;
fnCardGetStatus = (PCMCIA_CARD_GET_STATUS) GetProcAddress(hLibrary, L"CardGetStatus");
if(NULL != fnCardGetStatus)
{
state++;
hCard = fnCardRegisterClient( PCMCIAEvent, &params);
if(NULL != hCard)
rVal = TRUE;
}
}
}
}


// if we failed for some reason, display which call failed and the last error, and clean up.
if(!rVal)
{
DWORD dwTemp = GetLastError();
DEBUGMSG(ZONE_PCMCIA, (_T("RegisterWithCardServices failed. State = %d. GLE returned 0x%08x"), state, dwTemp));


		if(NULL != hLibrary)
			FreeLibrary(hLibrary);

	}

	return rVal;
}

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  Function:

    DeregisterWithCardServices

  Description:

Deregisers the callback function PCMCIAEvent with card services. This unhooks
the callback.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
BOOL DeregisterWithCardServices(PDEVICESTATE pds)
{
BOOL rVal = TRUE;
STATUS status;


	status = fnCardDeregisterClient(hCard);

if(CERR_SUCCESS != status)
{
DEBUGMSG(ZONE_PCMCIA, (_T("DeregisterWithCardServices:CardDeregisterClient failed.")));
rVal = FALSE;
}


// even if the deregister call fails, we still need to unload the library we are using.
if(NULL != hLibrary)
{
if(!FreeLibrary(hLibrary))
{
DEBUGMSG(ZONE_PCMCIA, (_T("DeregisterWithCardServices:FreeLibrary failed.")));
rVal = FALSE;
}
}


	return rVal;
}



Andrew Worsley wrote:
On our (4.2) platform, we programmatically load/unload (dismount) the \Storage Card and the ATADISK driver, based on the state of a switch on our CompactFlash card door.

Most of the time, this works fine. However, it seems that if I unload, then reload in quick succession (caused by someone opening then closing the card door), then the \Storage Card filesystem doesn't always reappear, even though ATADISK gets reloaded.

The unload sequence we follow is:
1. DismountStore() to dismount DSK1: (we have the reg configured so that \Storage Card is always DSK1:). We don't (currently) wait for any notification that the store has unloaded.
2. DeactivateDevice() for ATADISK.
3. Wait for a BLOCK_DRIVER_GUID notification that tells us that DSK1: (ATADISK driver) has been removed.
4. Unload sequence is now complete, and we allow reloading (eg if the door closes again).


The load sequence is:
1. ActivateDeviceEx() for ATADISK.
2. When ATADISK load is complete, it sends a BLOCK_DRIVER_GUID notification, for the benefit of Storage Manager.
3. Storage Manager loads a FAT filesystem for each partition (we have only one normally).
4. We wait for notification (FindFirstChangeNotification() for root directory changes) that the \Storage Card directory has appeared.
5. Sequence complete - filesystem is now ready to use.


This all works nicely, as long as we don't unload, then reload too quickly. If we do, the (re)load sequence fails at step 3 above.

What seems to happen (based on stepping through the code with the debugger) is that Storage Manager's PnP thread receives the BLOCK_DRIVER_GUID attach notification, and calls its MountStore() function. That function then searches through its list of stores, and finds a matching one that it marked as detached. It therefore marks it as attached again (rather than its more usual call to AddStore()), and then returns (without sending a STORE_MOUNT_GUID attach notification - perhaps that is significant?).

In any case, the end result is that the \Storage Card filesystem doesn't seem to be reloaded, as I don't get a filesystem notification for it (or a STORE_MOUNT_GUID PnP notification - I've tried that approach too), and I can't see it with the remote file viewer, or from an application.

Does anyone have any idea what might be going on here? Better still, how can I get it to work (ie to always load the filesystem when ATADISK (re)
loads up)?
.



Relevant Pages

  • Storage Card doesnt always reload when ATADISK reloaded
    ... our CompactFlash card door. ... even though ATADISK gets reloaded. ... Wait for a BLOCK_DRIVER_GUID notification that tells us that DSK1: ... Storage Manager loads a FAT filesystem for each partition (we have ...
    (microsoft.public.windowsce.platbuilder)
  • Re: Strange Paypal "Chargeback" claim
    ... Shortly after she received a notification via ebay that the ... and used the "refund payment" option to refund the paypal ... asked their card issuer to reverse a payment made to you. ... Although a chargeback may appear to be similar to a PayPal claim, ...
    (uk.people.consumers.ebay)
  • Strange Paypal "Chargeback" claim
    ... Shortly after she received a notification via ebay that the ... and used the "refund payment" option to refund the paypal ... asked their card issuer to reverse a payment made to you. ... Although a chargeback may appear to be similar to a PayPal claim, ...
    (uk.people.consumers.ebay)
  • Re: RequestDeviceNotifications for WLAN card
    ... Do you have to do something to the card before it can connect to a wireless ... I have an application that needs to get notification when ever a WLAN ... driver, However there is no generic CLSID for the WLAN SDIO driver (or ...
    (microsoft.public.windowsce.platbuilder)
  • CE 6.0 CF card mount problem!
    ... CF Card, ... ATADISK: ... Dumping registry for key PCMCIA ... FSDMGR!LoadPartitionDriver: Loading partition driver mspart.dll ...
    (microsoft.public.windowsce.platbuilder)