Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
EnablerSmpl.c
/* |
File: EnablerSmpl.c |
Contains: This is a sample enabler for an ethernet PC Card, which demonstrates how to |
create a port module |
registration item and set a custom module name that will be used to |
identify the device driver. |
Written by: Carl Fallis - writer of the original sample on which this sample is based |
Hiroko Nishimura - modified the sample to support the Ratoc REX-5589 Ethernet |
PC Card. |
Rich Kubota - modified to demonstrate handling of custom port registration |
Copyright: Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
8/16/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
#include <Types.h> |
#include <Errors.h> |
#include <Devices.h> |
#include <Gestalt.h> |
#include <CodeFragments.h> |
//#include <DriverServices.h> |
#include <PCCardEnablerPlugin.h> |
#include <PCCardTuples.h> |
#include <OpenTptModule.h> |
#include <OpenTptPCISupport.h> |
#include <OpenTptDevLinks.h> |
#include "EnablerSample.h" |
#include "MyPortCalls.h" |
// use the TupleDumper PPC utility which comes with the PC Card DDK to display the data |
// associated with the following Tuples. The following are used with the _IdentifyCard call |
// to verify that the proper card is being supported. |
const unsigned char kCISTPL_VERS_1_Data[] = "\4\1PCMCIA LAN MBH10304 ES\0 01\0\xff"; |
const unsigned char kCISTPL_CONFIG_Data[] = {0x05,0x20,0xF0,0x03,0x03,0x00,0xFF}; |
const unsigned char kCISTPL_CFTABLE_ENTRY_Data[] = {0xE0,0xC1,0x99,0x5F,0x55,0xC5,0x4B,0xD5, |
0x19,0x86,0x10,0x26,0x45,0x65,0x30,0xFF, |
0xFF,0x20,0xFF}; |
//---------------------------------------------------------------------- |
// Local Prototypes |
typedef PCCardTupleIterator PCCardTupleIteratorPtr; |
OSStatus MyValidateHardware(const RegEntryID * lpCardEntry); |
OSStatus MyHandleCardEvent(const RegEntryID *cardRef, PCCardEvent theEvent); |
OSStatus MyGetFirstTuple(UInt32 socket, UInt32 device, PCCardTupleIteratorPtr lpTupleIterator, |
Byte desiredTuple, void *lptupleData, UInt32 *lpTupleBufferSize, Byte *lpFoundTuple); |
OSStatus MyGetNextTuple(PCCardTupleIteratorPtr tupleIterator, Byte desiredTuple, void *tupleData, ByteCount *tupleBufferSize, Byte *foundTuple); |
OSStatus _IdentifyCard(const RegEntryID * lpCardEntry); |
Boolean CheckVers1Tuple(unsigned char * data, char * manufacturerName, char * cardName); |
OSStatus CreatePortProperties(const RegEntryID *cardRef); |
OSStatus MyAddDeviceProperties(const RegEntryID *cardRef, UInt32 device); |
OSStatus MyFinalizeDevice(UInt32 socket, UInt32 device, const RegEntryID *deviceRef); |
void CallPortScanner(void); |
void EnablerOfflinePort(const RegEntryID *cardRef); |
//---------------------------------------------------------------------- |
// Globals |
#pragma export on |
// -------------------- |
// Here's the exported Driver Descriptor |
DriverDescription TheDriverDescription = { |
/* |
* Signature info |
*/ |
kTheDescriptionSignature, /* OSType driverDescSignature */ |
kInitialDriverDescriptor, /* DriverDescVersion driverDescVersion */ |
/* |
* DriverType driverType - these are defined in |
*/ |
kPluginNamePString, /* Name of hardware */ |
kVersionMajor, kVersionMinor, /* NumVersion version */ |
kVersionStage, kVersionNonRel, |
/* |
* DriverOSRuntime driverOSRuntimeInfo |
*/ |
kDriverIsLoadedUponDiscovery | /* Loader runtime options */ |
kDriverIsUnderExpertControl, /* I/O expert handles loads/opens */ |
kPluginNamePString, /* Str31 driverName (OpenDriver param) */ |
0, 0, 0, 0, 0, 0, 0, 0, /* UInt32 driverDescReserved[8] */ |
/* |
* DriverOSService Information. This section contains a vector count followed by |
* a vector of structures, each defining a driver service. |
*/ |
1, /* ServiceCount nServices */ |
/* |
* DriverServiceInfo service[0] |
*/ |
kServiceCategoryPCCard, /* OSType serviceCategory */ |
kServiceTypePCCardEnabler, /* OSType serviceType */ |
1, 0,developStage, 1 |
}; |
// -------------------- |
// Here's the exported Plugin Function TableÉ |
PCCardEnablerPluginDispatchTable ThePluginDispatchTable = |
{ |
/* PCCardEnablerPluginHeader */ |
{ kPCCardEnablerPluginCurrentVersion, 0, 0, 0 }, |
/* CEValidateHardwareProc */ MyValidateHardware, |
/* CEInitializeProc */ CEInitializeCard, |
/* CECleanupProc */ CEFinalizeCard, |
/* CEPowerManagementProc */ CEPowerManagement, |
/* CEHandleEventProc */ CEHandleCardEvent, |
/* CEGetCardInfoProc */ CEGetCardInfo, |
/* CEAddCardPropertiesProc */ CEAddCardProperties, |
/* CEGetDeviceCountProc */ CEGetDeviceCount, |
/* CEGetDeviceNameProc */ CEGetDeviceName, |
/* CEGetDeviceCompatibleNameProc */ CEGetDeviceCompatibleNames, |
/* CEGetDeviceTypeProc */ CEGetDeviceType, |
/* CEGetDeviceTypeNameProc */ CEGetDeviceTypeName, |
/* CEAddDevicePropertiesProc */ MyAddDeviceProperties, |
/* CEConfigureDeviceProc */ CEConfigureDevice, |
/* CEFinalizeDeviceProc */ MyFinalizeDevice, |
/* CEValidateCISProc */ CEValidateCIS, |
/* CEGetFirstTupleProc */ MyGetFirstTuple, |
/* CEGetNextTupleProc */ MyGetNextTuple, |
/* InterruptHandler */ CEDefaultInterruptHandler, |
/* InterruptEnabler */ NULL, |
/* InterruptDisabler */ NULL |
}; |
//---------------------------------------------------------------------- |
// Determine whether the plugin can support this card. |
// Returning noErr means that the card is supported |
OSStatus MyValidateHardware(const RegEntryID *lpCardEntry) |
{ |
OSStatus err; |
#if DEBUG |
DebugStr("\pCustomCardEnabler: MyValidateHardware"); |
#endif |
if (!(lpCardEntry)) return(paramErr); |
// see if we are supposed to handle this card, set global card id |
err = _IdentifyCard(lpCardEntry); |
#if DEBUG1 |
if (err == noErr) DebugStr("\p Enabler will handle this card!;g"); |
#endif |
return(err); |
} |
//---------------------------------------------------------------------- |
// Look to see if this is a card we are supposed to handle |
// If it is return noErr, other wise return kUnsupportedCardErr |
// |
// Identification of the IBM OEM Ethernet card |
// 1) check the manufacturer's ID |
// 2) check the vers 1 for IBM Corp Ethernet |
// 3) check for the config table entry for the bad entry so that we are sure that |
// this is the correct card we say it is our card |
OSStatus _IdentifyCard(const RegEntryID *lpCardEntry) |
{ |
PCCardTupleIteratorPtr iter; |
OSStatus err = noErr; |
UInt32 size=MAX_TUPLE_SIZE, socket, device; |
Boolean match = false; |
int i=0; |
#if DEBUG |
DebugStr("\pCustomCardEnabler: _IdentifyCard"); |
#endif |
if(!(lpCardEntry) ) return(paramErr); |
err = CEGetSocketAndDeviceFromRegEntry(lpCardEntry, &socket, &device); |
if (err != noErr) |
return(err); |
iter = PCCardNewTupleIterator(); |
if (iter == NULL) |
return memFullErr; |
err = CECompareCISTPL_MANFID(lpCardEntry, |
kManifID, |
kManifInfo, |
&match); |
if ((err == noErr) && (match == true)) |
{ |
// do other checking if required like calling CSGetFirstTuple |
// to get more tuple info to compare against |
} |
else |
err = kUnsupportedCardErr; |
// dispose of the tuple iterator |
PCCardDisposeTupleIterator(iter); |
return(err); |
} |
//---------------------------------------------------------------------- |
// Look for the kPCCardInsertionMessage as the event |
OSStatus MyHandleCardEvent(const RegEntryID *cardRef, PCCardEvent theEvent) |
{ |
OSStatus err = noErr; |
#if DEBUG |
DebugStr("\pMyHandleCardEvent called"); |
#endif |
switch (theEvent) |
{ |
case kPCCardInsertionMessage: |
#if DEBUG1 |
DebugStr("\pkPCCardInsertionMessage event passed to MyHandleCardEvent;g"); |
#endif |
break; |
case kPCCardEjectionRequestMessage: |
case kPCCardRemovalMessage: |
#if DEBUG |
DebugStr("\p kPCCardRemovalMessage called"); |
#endif |
// EnablerOfflinePort(cardRef); |
break; |
} |
if (err == noErr) |
// call the default HandleEventProc to complete processing of the event. |
err = CEHandleCardEvent(cardRef, theEvent); |
return err; |
} |
//---------------------------------------------------------------------- |
OSStatus MyGetFirstTuple(UInt32 socket, UInt32 device, |
PCCardTupleIteratorPtr lpTupleIterator, |
Byte desiredTuple, |
void *lpTupleData, |
UInt32 *lpTupleBufferSize, |
Byte *lpFoundTuple) |
{ |
OSStatus err = noErr; |
unsigned char *dataPtr = (unsigned char *)lpTupleData; |
UInt32 i=0; |
#if DEBUG |
// DebugStr("\pCustomCardEnabler: MyGetFirstTuple"); |
#endif |
if(!(lpTupleIterator && lpFoundTuple && lpTupleData && *lpTupleBufferSize)) |
return(paramErr); |
err = CSGetFirstTuple(socket, device,lpTupleIterator,desiredTuple, |
lpTupleData,lpTupleBufferSize,lpFoundTuple); |
if (err != noErr) |
return(err); |
if (*lpTupleBufferSize == 0) |
return(err); |
if (*lpFoundTuple == CISTPL_VERS_1) |
{ |
#if DEBUG1 |
// DebugStr("\pCISTPL_VERS_1"); |
#endif |
for( i = 0; i < sizeof(kCISTPL_VERS_1_Data); i++) |
dataPtr[i] = kCISTPL_VERS_1_Data[i]; |
*lpTupleBufferSize = sizeof(kCISTPL_VERS_1_Data); |
} |
if (*lpFoundTuple == CISTPL_CONFIG) |
{ |
#if DEBUG1 |
DebugStr("\pCISTPL_CONFIG"); |
#endif |
for( i = 0; i < sizeof(kCISTPL_CONFIG_Data); i++) |
dataPtr[i] = kCISTPL_CONFIG_Data[i]; |
*lpTupleBufferSize = sizeof(kCISTPL_CONFIG_Data); |
} |
if (*lpFoundTuple == CISTPL_CFTABLE_ENTRY) |
{ |
#if DEBUG1 |
DebugStr("\pCISTPL_CFTABLE_ENTRY"); |
#endif |
for( i = 0; i < sizeof(kCISTPL_CFTABLE_ENTRY_Data); i++) |
dataPtr[i] = kCISTPL_CFTABLE_ENTRY_Data[i]; |
*lpTupleBufferSize = sizeof(kCISTPL_CFTABLE_ENTRY_Data); |
} |
return(err); |
} |
// |
// MyGetNextTuple |
// |
OSStatus MyGetNextTuple(PCCardTupleIteratorPtr lpTupleIterator, |
Byte desiredTuple, |
void *lpTupleData, |
ByteCount *lpTupleBufferSize, |
Byte *lpFoundTuple) |
{ |
OSStatus err = noErr; |
unsigned char *dataPtr = (unsigned char *)lpTupleData; |
UInt32 i=0; |
#if DEBUG |
// DebugStr("\pCustomCardEnabler: MyGetNextTuple"); |
#endif |
if(!(lpTupleIterator && lpFoundTuple && lpTupleData && *lpTupleBufferSize)) |
return(paramErr); |
err = CSGetNextTuple(lpTupleIterator, desiredTuple,lpTupleData,lpTupleBufferSize, |
lpFoundTuple); |
if (err != noErr) |
return(err); |
if (*lpTupleBufferSize == 0) |
return(err); |
if (*lpFoundTuple == CISTPL_VERS_1) |
{ |
#if DEBUG1 |
// DebugStr("\pCISTPL_VERS_1"); |
#endif |
for( i = 0; i < sizeof(kCISTPL_VERS_1_Data); i++) |
dataPtr[i] = kCISTPL_VERS_1_Data[i]; |
*lpTupleBufferSize = sizeof(kCISTPL_VERS_1_Data); |
} |
if (*lpFoundTuple == CISTPL_CONFIG) |
{ |
#if DEBUG1 |
DebugStr("\pCISTPL_CONFIG"); |
#endif |
for( i = 0; i < sizeof(kCISTPL_CONFIG_Data); i++) |
dataPtr[i] = kCISTPL_CONFIG_Data[i]; |
*lpTupleBufferSize = sizeof(kCISTPL_CONFIG_Data); |
} |
if (*lpFoundTuple == CISTPL_CFTABLE_ENTRY) |
{ |
#if DEBUG1 |
DebugStr("\pCISTPL_CFTABLE_ENTRY"); |
#endif |
for( i = 0; i < sizeof(kCISTPL_CFTABLE_ENTRY_Data); i++) |
dataPtr[i] = kCISTPL_CFTABLE_ENTRY_Data[i]; |
*lpTupleBufferSize = sizeof(kCISTPL_CFTABLE_ENTRY_Data); |
} |
return(err); |
} |
//---------------------------------------------------------------------- |
// Pass in a VERS1 tuple and check that the manufacturer name and card name are |
// the the same as the ones passed in |
Boolean CheckVers1Tuple(unsigned char * data, char * manufacturerName, char * cardName) |
{ |
unsigned char *ptr; |
#if DEBUG |
// DebugStr("\pCustomCardEnabler: CheckVers1Tuple"); |
#endif |
// the manufacturer name is a null terminated string starting in byte three |
ptr = &(data[2]); |
if(CStrCmp((const char *) ptr, manufacturerName) == 0) |
{ |
// the card name is a null terminated string that starts after the manufacturer name |
while(*ptr++) |
; |
if(CStrCmp((const char *) ptr, cardName) != 0) |
return(false); |
} |
else |
return(false); |
// if we make it to here, both names match |
return(true); |
} |
OSStatus MyFinalizeDevice(UInt32 socket, UInt32 device, const RegEntryID *deviceRef) |
{ |
OSStatus err; |
#if DEBUG |
DebugStr("\p MyFinalizeDevice called"); |
#endif |
EnablerOfflinePort(deviceRef); |
err = CEFinalizeDevice(socket, device, deviceRef); |
return err; |
} |
OSStatus MyAddDeviceProperties(const RegEntryID *cardRef, UInt32 device) |
{ |
#pragma unused ( device ) |
OSStatus err; |
#if DEBUG |
DebugStr("\pCustomCardEnabler: MyAddDeviceProperties"); |
#endif |
// This would be a great place to register a port, however, this creates a problem for |
// the shared library since this code could be called at start up time prior to |
// the availability of Open Transport. While I could weak link with OT, if the library |
// is not present, then even when the library becomes available, CFM will not relink |
// with the OT libraries. To handle this case, we implement a port scanner. |
err = CreatePortProperties(cardRef); |
CallPortScanner(); |
return err; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22