ADC Home > Reference Library > Technical Q&As > Legacy Documents > Mac OS 9 & Earlier >

Legacy Documentclose button

Important: This document is part of the Legacy section of the ADC Reference Library. This information should not be used for new development.

Current information on this Reference Library topic can be found here:

Ethernet Error on a PowerMac


Q: When I attempt to open the built-in Ethernet driver using the OpenDriver call on a PCI-based Macintosh, the call fails. What is the correct way to access the built-in driver on these new PowerMacs?

A: The new PCI-based PowerMacs implement Open Transport for Network Services, in which the architecture is a precursor to the changes expected for Copland. Since Open Transport is native, there is no longer a dependence on the 68K based Device Manager and Slot Manager. In order to maintain compatibility for the built-in ethernet driver, an ENET Shim was implemented so that applications which called the Ethernet driver directly could continue to work.

The ENET Shim opens when an OpenSlot call is made to open the Ethernet driver in NuBus slot 0. The shim intercepts this request and loads a .ENET driver entry into the driver table. From that time, applications which call OpenDriver will get the driver reference number for the shim driver, which then handles the various Control calls it receives.

Note that the shim only works for the built-in Ethernet device, not for an installed PCI Ethernet card.

The following sequence of calls works for all Ethernet connections in which Open Transport is present:

/*
    File:       ShowOTEnetAddr.c
    Contains:   Simple app to print out Ethernet addresses for any Ethernet card on
                any Mac which has Open Transport installed.
                This includes the PCI based Macs.

    Copyright:  © 1993-1995 by Apple Computer, Inc., all rights reserved.
    Change History (most recent first):
    2/6/96  rkubota (1) initialized the index variable to 0 in main
    To Do:
*/

#include <stdio.h>
#include <Types.h>
#include <Memory.h>
#include <Resources.h>
#include <Events.h>
#include <OpenTransport.h>          // open transport files
#include <OpenTptLinks.h>
struct Address8022
{
    OTAddressType   fAddrFamily;
    UInt8           fHWAddr[k48BitAddrLength];
    UInt16          fSAP;
    UInt8           fSNAP[k8022SNAPLength];
};
typedef struct Address8022 Address8022;
#define kTrue   1
#define kFalse  0
//-------------------------------------------------------------------------------
----------
// Globals
//-------------------------------------------------------------------------------
----------
EndpointRef     gEndpoint1;
//-------------------------------------------------------------------------------
----------
// prototypes
//-------------------------------------------------------------------------------
----------
OSStatus DoBind(void);
OSStatus GetEthernetAddress(char *slotName);
/*******************************************************************************
** DoBindENET
    For this sample, we need to bind to any ethernet endpoint.  In this case
    we bind to enet protocol type 0x8888.  We use an Address8022 variable
    type for expediency
********************************************************************************/

OSStatus DoBind()
{
    OSStatus        osStatus;
    TBind           gRequestInfo;
    Address8022     theAddr =
    {AF_8022, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x8888,
                                    {0x00,0x00,0x00,0x00,0x00}};

        // finish bind information
    gRequestInfo.addr.buf = (UInt8 *)&theAddr;
    gRequestInfo.addr.len = 10; // family type + Ethernet + type field
                    // don't use sizeof(theAddr) since we are binding
                    // to type 1 Ethernet address, not to an 802.2 address.
    gRequestInfo.addr.maxlen = 0;
    gRequestInfo.qlen = 0;

    if (osStatus = OTBind(gEndpoint1, &gRequestInfo, NULL))
    {
        printf("\nCould not bind an endpoint, error = %d\n", osStatus);
        CloseOpenTransport();
        return  -4;
    }

    return osStatus;
}
/*******************************************************************************
** GetEthernetAddress
********************************************************************************/

OSStatus GetEthernetAddress(char *slotName)
{
    OSStatus        osStatus;
    TBind           returnInfo;
    Address8022     theReturnAddr =
    {AF_8022, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0x0000,

                                    {0x00,0x00,0x00,0x00,0x00}};

    returnInfo.addr.buf = (UInt8 *)&theReturnAddr;
    returnInfo.addr.maxlen = 10;
    // family type + 6 bytes for Ethernet + type
    returnInfo.qlen = 0;


    osStatus = OTGetProtAddress(gEndpoint1,&returnInfo,NULL);

    if (osStatus == kOTNoError)
    {
        if (slotName[0] != 0x00)
            printf("\nAddress for PCI Slot %s => ", slotName);
        else
            printf("\nAddress for Ethernet Built-In => ");

        printf("%02x.",(int )theReturnAddr.fHWAddr[0]);
        printf("%02x.",(int )theReturnAddr.fHWAddr[1]);
        printf("%02x.",(int )theReturnAddr.fHWAddr[2]);
        printf("%02x.",(int )theReturnAddr.fHWAddr[3]);
        printf("%02x.",(int )theReturnAddr.fHWAddr[4]);
        printf("%02x",(int )theReturnAddr.fHWAddr[5]);
    }
    else
        printf("\n\nCould not get the Ethernet address, error = %d\n\n", osStatus);

    return osStatus;
}
/*******************************************************************************
** main
********************************************************************************/

main()
{
    OSStatus        osStatus;
    OTPortRecord    devicePortRecord;
    Boolean         foundAPort;
    UInt32          index;

    printf("\n\nEthernet Address Display v1.1\n");
    printf("\nThis application displays the Ethernet address for the\n");
    printf("Ethernet Built-In port and PCI Ethernet cards.\n\n");

    if (osStatus = InitOpenTransport())
    {
        printf("\n\nOpen Transport is not installed!\n\n");
        return 0;
    }

    index = 0;
        // iterate thru each OT port record for ethernet ports.
    while (foundAPort = OTGetIndexedPort(&devicePortRecord,index))
    {
        if ((devicePortRecord.fCapabilities & kOTPortIsDLPI) &&
            (devicePortRecord.fCapabilities & kOTPortIsTPI) &&
            (kOTEthernetDevice == OTGetDeviceTypeFromPortRef(devicePortRecord.fRef)))
        {

            gEndpoint1 = OTOpenEndpoint(
                OTCreateConfiguration(devicePortRecord.fPortName),
                (OTOpenFlags)NULL, NULL,&osStatus);

            if (osStatus == kOTNoError)
            {
                    // we have to bind the endpoint
                    // before we can get it's address info
                osStatus = DoBind();
                if (osStatus == kOTNoError)
                {
                    GetEthernetAddress(devicePortRecord.fSlotID);
                    OTUnbind(gEndpoint1);
                }

                OTCloseProvider(gEndpoint1);
            }


        }
        index++;
    }



        // closing down
    CloseOpenTransport();

    printf("\n\nTo quit the application press Command-Q.\n");

    return 0;
}

[Sep 15 1995]


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.