Copyright ã1995 by NeXT Computer, Inc.  All Rights Reserved.

IOEthernet

Inherits From:	IODirectDevice : IODevice : Object

Conforms To:	IONetworkDeviceMethods

Declared In:	driverkit/IOEthernet.h

Class Description

IOEthernet is an abstract class for controlling Ethernet devices. It provides a framework for sending and receiving packets, handling interrupts, and setting and detecting transmission timeouts. It also provides an IONetwork instance that connects the driver with the kernel networking subsystem, as well as an I/O thread from which most of the IOEthernet instance methods are invoked. 

IOEthernet includes support for multicast mode and promiscuous mode. It doesn't currently provide gdb support for non-NeXT drivers. (gdb support enables the kernel running the IOEthernet driver to be debugged over the network.) 

IOEthernet's multicast support consists mainly of keeping a list of the multicast addresses at which multicast packets should be received and providing methods for configuring multicast addresses. Depending on the hardware's capability, you can either implement enableMulticastMode and disableMulticastMode to allow and disallow receptions of all multicast packets or implement addMulticastAddress: and removeMulticastAddress: to configure the hardware for individual addresses.

Most hardware implementations don't guarantee filtering based on individual addresses. For this reason, the isUnwantedMulticastPacket: method exists to indicate packets that aren't bound for an address in the list of valid multicast addresses. A subclass of IOEthernet written for hardware that implements partial or no filtering based upon individual addresses should invoke this method each time it receives a multicast packet to determine whether it should be discarded or not.

To write an Ethernet driver, you create a subclass of IOEthernet.

Implementing a Subclass

Your subclass of IOEthernet must do the following:

·	Implement probe: and initFromDeviceDescription:. The implementation of probe: should allocate an instance and invoke initFromDeviceDescription:. See the IODevice specification for more information on implementing probe:.

·	Implement transmit:, resetAndEnable:, interruptOccurred, and timeoutOccurred. These methods perform the real work of the driver. interruptOccurred is invoked from the I/O thread whenever the Ethernet hardware interrupts. See the EISA/ISA method descriptions in the IODirectDevice specification for more information on interruptOccurred and timeoutOccurred. 

If your subclass supports multicast mode, you must implement either enableMulticastMode and disableMulticastMode or addMulticastAddress: and removeMulticastAddress:.

If your subclass supports promiscuous mode, you must implement enablePromiscuousMode and disablePromiscuousMode.

IONetworkDeviceMethods Protocol Implementation

In IOEthernet's implementation, finishInitialization invokes resetAndEnable:YES if [self isRunning] == YES.

Instance Variables

None declared in this class.

Adopted Protocols

IONetworkDeviceMethods	- allocateNetbuf
- finishInitialization
- outputPacket:address:
- performCommand:data:

Method Types

Creating and destroying IOEthernet instances
- free
- initFromDeviceDescription:
- attachToNetworkWithAddress:

Handling interrupts	- interruptOccurred (IODirectDevice)

Transmitting packets	- transmit:
- performLoopback:

Setting and handling hardware timeouts	
- setRelativeTimeout:
- relativeTimeout
- clearTimeout
- timeoutOccurred (IODirectDevice)

Setting and getting the state of the hardware
- isRunning
- resetAndEnable

Supporting multicast	- enableMulticastMode
- disableMulticastMode
- addMulticastAddress:
- removeMulticastAddress:
- isUnwantedMulticastPacket:

Supporting promiscuity	- disablePromiscuousMode
- enablePromiscuousMode

Instance Methods

addMulticastAddress:

- (void)addMulticastAddress:(enet_addr_t *)address 

Does nothing. Subclasses that support multicast mode can implement this method so that it notifies the hardware that it should receive packets sent to address. Some subclasses that support multicast don't implement this method because their hardware doesn't provide filtering based upon individual multicast addresses. Instead, they inspect all multicast packets, using isUnwantedMulticastPacket: to weed out packets to unwanted multicast addresses. This method, followed by enableMulticastMode, is invoked in the I/O thread every time a new multicast address is added to the list that IOEthernet maintains.

See also:  - enableMulticastMode, - isUnwantedMulticastPacket:, - removeMulticastAddress:

attachToNetworkWithAddress:

- (IONetwork *)attachToNetworkWithAddress:(enet_addr_t)address

Creates an IONetwork instance and attaches to the network subsystem by sending the IONetwork an initForNetworkDevice:... message. Before returning, this method logs a message including the ethernet address. Returns the IONetwork instance just created.

You invoke this method at the end of your implementation of initFromDeviceDescription:. You must invoke resetAndEnable:NO before invoking this method, as described under initFromDeviceDescription:.

clearTimeout

- (void)clearTimeout

If a transmission timeout is scheduled, unschedules the timeout. This method is normally invoked from a subclass's implementation of interruptOccurred.

See also:  setRelativeTimeout:, relativeTimeout, timeoutOccurred

disableMulticastMode

- (void)disableMulticastMode

Does nothing. Subclasses that support multicast mode and implement enableMulticastMode should implement this method so that it disables the hardware's support for multicast mode. This method is invoked in the I/O thread when the last multicast address has been removed from the list that IOEthernet maintains.

See also:  - enableMulticastMode

disablePromiscuousMode

- (void)disablePromiscuousMode

Does nothing. Subclasses that support promiscuous mode must implement this method so that it disables the hardware's support for promiscuous mode. This method is invoked in the I/O thread by the networking subsystem.

See also:  - enablePromiscuousMode

enableMulticastMode

- (BOOL)enableMulticastMode

Does nothing and returns YES. Subclasses that support multicast mode can implement this method so that it enables the hardware's support for multicast mode. Every time a new multicast address is added to the list that IOEthernet maintains, addMulticastAddress: and this method are invoked in the I/O thread. 

See also:  - disableMulticastMode

enablePromiscuousMode

- (BOOL)enablePromiscuousMode

Does nothing and returns YES. Subclasses that support promiscuous mode must implement this method so that it enables the hardware's support for promiscuous mode. This method is invoked in the I/O thread by the networking subsystem.

See also:  - enablePromiscuousMode

free

- free

Frees the IOEthernet instance and returns nil.

initFromDeviceDescription:

- initFromDeviceDescription:(IODeviceDescription *)deviceDescription 

Initializes a newly allocated IOEthernet instance. This includes invoking initFromDeviceDescription: on super; invoking startIOThread; setting the name, kind, and unit of this instance; and invoking registerDevice.

Subclasses of IOEthernet should implement this method so that it invokes [super initFromDeviceDescription:] and then performs any device-specific initialization. The subclass implementation should invoke resetAndEnable:NO and should finish by invoking attachToNetworkWithAddress:. An example of a subclass implementation of this method is below. Italicized text delineated in angle brackets, that is << >>, is to be filled in with device-specific code.

- initFromDeviceDescription:(IODeviceDescription *)devDesc
{
    IOEISADeviceDescription *deviceDescription = 
                            (IOEISADeviceDescription *)devDesc;
    IORange                *io;

    if ([super initFromDeviceDescription:devDesc] == nil) 
            return nil;

    << Perform any 1-time hardware initialization. >>

    /* NOTE: This implementation of resetAndEnable: sets myAddress. */
    [self resetAndEnable:NO];  // Finish initializing the hardware

    << Perform any additional software initialization. >>

    network = [self attachToNetworkWithAddress:myAddress];
    return self;
}

Returns self if the instance was successfully initialized; otherwise, frees itself and returns nil.

isRunning

- (BOOL)isRunning

Returns YES if the hardware is currently capable of communication with other stations in the network; otherwise, returns NO.

See also:  - setRunning:

isUnwantedMulticastPacket:

- (BOOL)isUnwantedMulticastPacket:(ether_header_t *)header 

Determines whether the specified packet is to a multicast address that this device shouldn't listen to. Returns YES if the packet should be dropped; otherwise, returns NO.

See also:  - addMulticastAddress:

performLoopback:

- (void)performLoopback:(netbuf_t)packet

Determines whether the outgoing packet should be received by this device (because it's a broadcast packet, for example, or a multicast packet for an enabled address). If so, simulates reception by sending a copy of packet to the protocol stack. You should invoke this method in your transmit: method if your hardware device can't receive its own packets.

relativeTimeout

- (unsigned int)relativeTimeout

Returns the number of milliseconds until a transmission timeout will occur. If no transmission timeout is currently scheduled, this method returns zero.

See also:  clearTimeout, setRelativeTimeout:, timeoutOccurred

removeMulticastAddress:

- (void)removeMulticastAddress:(enet_addr_t *)address 

Does nothing. Subclasses that support multicast mode can implement this method so that it notifies the hardware that it should stop listening for packets sent to address.

See also:  - addMulticastAddress:, - disableMulticastMode

resetAndEnable:

- (BOOL)resetAndEnable:(BOOL)enable 

Does nothing and returns YES. Subclasses of IOEthernet must implement this method so that it resets and initializes the hardware. Interrupts should be enabled if enable is YES; otherwise, they should be left disabled. In either case, this method should invoke setRunning: to record the basic state of the device. 

This method should return YES if it encounters no errors (no matter what the value of enable is); if it encounters errors, it should return NO. For example, the result from resetAndEnable:NO should be YES if the reset is successful.

The only time this method is invoked, with the exception of any invocations from your IOEthernet subclass implementation, is during initialization. Specifically, resetAndEnable:YES is invoked once in the I/O thread after attachToNetworkWithAddress: is invoked. 

See also:  - setRunning:

setRelativeTimeout:

- (void)setRelativeTimeout:(unsigned int)timeout 

Schedules a timeout to occur in timeout milliseconds. This method is generally invoked by the IOEthernet's transmit: method. When timeout milliseconds pass without the timeout being cleared (with clearTimeout), the method timeoutOccurred is invoked. 

See also:  clearTimeout, relativeTimeout, timeoutOccurred

setRunning:

- (void)setRunning:(BOOL)running 

Sets whether the hardware is on line. The value of running should be YES to indicate that the hardware is on line; otherwise, it should be NO. This method is invoked only by methods in IOEthernet subclassesÐnot by IOEthernet's own method implementations. You should invoke this method in your implementation of resetAndEnable:.

See also:  - isRunning

transmit:

- (void)transmit:(netbuf_t)packet 

Does nothing except free packet, using the nb_free() function. This method is invoked by the kernel networking subsystem when the hardware should transmit a packet. 

Subclasses of IOEthernet must implement this method. To determine the number of bytes of data to be transmitted, use the nb_size() function. To get a pointer to the data, use nb_map(). After getting the information you need from packet, you must free it with nb_free(). Just before transmitting the packet, you can set a timeout with setRelativeTimeout:. If your hardware can't receive packets it transmits, you must invoke performLoopback: in your implementation of this method.

This method can be invoked in many contexts, not just from the I/O thread (or from the I/O task). For example, transmit: and interruptOccurred can run at the same time, so any common structures they both use must be protected with locks.