... h4. Chapter 19
h1. Drivers for Network Devices
Solaris network drivers are STREAMS-based. These types of drivers are covered in depth in the [_STREAMS Programming Guide_|http://docs.sun.com/doc/816-4855]. This chapter discusses the Generic LAN driver (GLD), which is a kernel module encapsulating features common to most network drivers. The GLD implements much of the STREAMS and Data Link Provider Interface (DLPI) functionality for a Solaris network driver.
The GLD module is available for Solaris network drivers for the SPARC platform and for both 32-bit and 64-bit x86 platforms.
This chapter provides information on the following subjects: * [Generic LAN Driver Overview|#GLD-overview] * [Declarations and Data Structures|#GLD-decdata] * [GLD Arguments|#GLD-args] * [GLD Entry Points|#GLD-entrypts] * [GLD Service Routines|#GLD-service]
For more information on GLDs, see the {{gld}}(7D), {{dlpi}}(7P), {{gld}}(9E), {{gld}}(9F), {{gld_mac_info}}(9S), and {{gld_stats}}(9S) man pages.
h2. Generic LAN Driver Overview{anchor:overview}
GLD is a multi-threaded, clonable, loadable kernel module providing support to device drivers for local area networks. Local area network (LAN) device drivers in the Solaris OS are STREAMS-based drivers that use DLPI to communicate with network protocol stacks. These protocol stacks use the network drivers to send and receive packets on a local area network.
A network device driver must implement and conform to these requirements: * DDI/DKI specification * STREAMS specification * DLPI specification * programmatic interface for the device
GLD implements most STREAMS and DLPI functionality required of a Solaris LAN driver. Several Solaris network drivers are implemented using GLD.
A Solaris network driver that is implemented using GLD is made up of two distinct parts: a generic component that deals with STREAMS and DLPI interfaces, and a device-specific component that deals with the particular hardware device. The device-specific module indicates its dependency on the GLD module, which is found at {{/kernel/misc/gld}}. The device-specific module then registers with GLD from within the driver's {{attach}}(9E) function. After the device-specific module is successfully loaded, the driver is DLPI-compliant. The device-specific part of the driver calls {{gld}}(9F) functions when that part receives data or needs some service from GLD. When the device-specific driver registers with the GLD, the driver provides pointers to the entry points for later use by GLD. GLD makes calls into the {{gld}}(9E) using these pointers. The {{gld_mac_info}}(9S) structure is the main data interface between GLD and the device-specific driver.
The GLD facility currently supports the following types of devices: * {{DL_ETHER}} --- ISO 8802-3, IEEE 802.3 protocol * {{DL_TPR}} --- IEEE 802.5, Token Passing Ring * {{DL_FDDI}} --- ISO 9314-2, Fibre Distributed Data Interface
GLD drivers are expected to process fully formed MAC-layer packets and should not perform logical link control (LLC) handling.
In some cases, a full DLPI-compliant driver can be implemented without using the GLD facility. One case would be devices that are not ISO 8802-style, that is, IEEE 802, LAN devices. Another case would be devices or services that are not supported by GLD.
h3. Type {{DL_ETHER}}: Ethernet V2 and ISO 8802-3 (IEEE 802.3)
For devices designated type {{DL_ETHER}}, GLD provides support for both Ethernet V2 and ISO 8802-3 (IEEE 802.3) packet processing. Ethernet V2 enables a user to access a conforming provider of data link services without special knowledge of the provider's protocol. A service access point (SAP) is the point through which the user communicates with the service provider.
Streams bound to SAP values in the range [0-255] are treated as equivalent and denote that the user wants to use 8802-3 mode. If the SAP value of the {{DL_BIND_REQ}} is within this range, GLD computes the length of each subsequent {{DL_UNITDATA_REQ}} message on that stream. The length does not include the 14-byte media access control (MAC) header. GLD then transmits 8802-3 frames that have those lengths in the MAC frame header {{type}} fields. Such lengths never exceed 1500.
All frames that are received from the media that have a {{type}} field in the range [0-1500] are assumed to be 8802-3 frames. These frames are routed up all open streams in 8802-3 mode. Those streams with SAP values in the [0-255] range are considered to be in 8802-3 mode. If more than one stream is in 8802-3 mode, the incoming frame is duplicated and routed up these streams.
Those streams that are bound to SAP values that are greater than 1500 are assumed to be in Ethernet V2 mode. These streams receive incoming packets whose Ethernet MAC header {{type}} value exactly matches the value of the SAP to which the stream is bound.
h3. Types {{DL_TPR}} and {{DL_FDDI}}: SNAP Processing
For media types {{DL_TPR}} and {{DL_FDDI}}, GLD implements minimal SNAP (Sub-Net Access Protocol) processing. This processing is for any stream that is bound to a SAP value that is greater than 255. SAP values in the range [0-255] are LLC SAP values. Such values are carried naturally by the media packet format. SAP values that are greater than 255 require a SNAP header, subordinate to the LLC header, to carry the 16-bit Ethernet V2-style SAP value.
SNAP headers are carried under LLC headers with destination SAP 0xAA. Outbound packets with SAP values that are greater than 255 require an LLC+SNAP header take the following form: {code} AA AA 03 00 00 00 XX XX {code}
``XX XX'' represents the 16-bit SAP, corresponding to the Ethernet V2 style ``type.'' This header is unique in supporting non-zero organizational unique identifier fields. LLC control fields other than 03 are considered to be LLC packets with SAP 0xAA. Clients wanting to use SNAP formats other than this format must use LLC and bind to SAP 0xAA.
Incoming packets are checked for conformance with the above format. Packets that conform are matched to any streams that have been bound to the packet's 16-bit SNAP type. In addition, these packets are considered to match the LLC SNAP SAP 0xAA.
Packets received for any LLC SAP are passed up all streams that are bound to an LLC SAP, as described for media type {{DL_ETHER}}.
h3. Type {{DL_TPR}}: Source Routing
For type {{DL_TPR}} devices, GLD implements minimal support for source routing. Source routing support includes the following items: * Specify routing information for a packet to be sent across a bridged medium. The routing information is stored in the MAC header. This information is used to determine the route. * Learn routes. * Solicit and respond to requests for information about possible multiple routes* Select among available routes.
Source routing adds routing information fields to the MAC headers of outgoing packets. In addition, this support recognizes such fields in incoming packets.
GLD's source routing support does not implement the full route determination entity (RDE) specified in Section 9 of ISO 8802-2 (IEEE 802.2). However, this support can interoperate with any RDE implementations that might exist in the same or a bridged network.
h3. Style 1 and Style 2 DLPI Providers
GLD implements both Style 1 and Style 2 DLPI providers. A physical point of attachment (PPA) is the point at which a system attaches itself to a physical communication medium. All communication on that physical medium funnels through the PPA. The Style 1 provider attaches the streams to a particular PPA based on the major or minor device that has been opened. The Style 2 provider requires the DLS, that is, the data link service, user to explicitly identify the desired PPA using {{DL_ATTACH_REQ}}. In this case, {{open}}(9E) creates a stream between the user and GLD, and {{DL_ATTACH_REQ}} subsequently associates a particular PPA with that stream. Style 2 is denoted by a minor number of zero. If a device node whose minor number is not zero is opened, Style 1 is indicated and the associated PPA is the minor number minus 1. In both Style 1 and Style 2 {{open}}s, the device is cloned.
h3. Implemented DLPI Primitives
GLD implements several DLPI primitives. The {{DL_INFO_REQ}} primitive requests information about the DLPI streams. The message consists of one {{M_PROTO}} message block. GLD returns device-dependent values in the {{DL_INFO_ACK}} response to this request. These values are based on information that the GLD-based driver specified in the {{gldm_mac_info}}(9S) structure that was passed to {{gld_register()}}.
GLD returns the following values on behalf of all GLD-based drivers: * Version is {{DL_VERSION_2}} * Service mode is {{DL_CLDLS}}, GLD implements connectionless-mode service. * Provider style is {{DL_STYLE1}} or {{DL_STYLE2}}, depending on how the stream was opened. |
* No optional Quality of Service (QOS) support is present. The QOS fields are zero.
|
| *Note ---* Contrary
{info:title=Note}Contrary
to the DLPI specification, GLD returns the device's correct address length and broadcast address in {{DL_INFO_ACK}} even before the stream has been attached to a
PPA.{info} |
The {{DL_ATTACH_REQ}} primitive is used to associate a PPA with a stream. This request is needed for Style 2 DLS providers to identify the physical medium over |
... which the communication is sent. Upon completion, the state changes from {{DL_UNATTACHED}} to {{DL_UNBOUND}}. The message consists of one {{M_PROTO}} message block. This request is not allowed when Style 1 mode is used. Streams that are opened using Style 1 are already attached to a PPA by the time the open completes.
The {{DL_DETACH_REQ}} primitive requests to detach the PPA from the stream. This detachment is allowed only if the stream was opened using Style 2.
The {{DL_BIND_REQ}} and {{DL_UNBIND_REQ}} primitives bind and unbind a DLSAP (data link service access point) to the stream. The PPA that is associated with a stream completes initialization before the completion of the processing of the {{DL_BIND_REQ}} on that stream. You can bind multiple streams to the same SAP. Each stream in this case receives a copy of any packets that were received for that SAP.
The {{DL_ENABMULTI_REQ}} and {{DL_DISABMULTI_REQ}} primitives enable and disable reception of individual multicast group addresses. Through iterative use of these primitives, an application or other DLS user can create or modify a set of multicast addresses. The streams must be attached to a PPA for these primitives to be accepted.
|
The {{DL_PROMISCON_REQ}} and {{DL_PROMISCOFF_REQ}} primitives turn promiscuous mode on or off on a per-stream basis. These controls operate at either at a physical level or at the SAP level. The DL Provider routes all received messages on the media to the DLS user. Routing continues until a {{DL_DETACH_REQ}} is received, a {{DL_PROMISCOFF_REQ}} is received, or the stream is closed. You can specify physical level promiscuous reception of all packets on the medium or of multicast packets only.
|
| *Note ---* The
{info:title=Note}The
streams must be attached to a PPA for these promiscuous mode primitives to be
accepted.{info} |
The {{DL_UNITDATA_REQ}} primitive is used to send data in a connectionless transfer. Because this service is not acknowledged, delivery is not guaranteed. The message consists of one {{M_PROTO}} message block followed by one or more {{M_DATA}} blocks containing at least one byte of data. |
... The {{DL_UNITDATA_IND}} type is used when a packet is to be passed on upstream. The packet is put into an {{M_PROTO}} message with the primitive set to {{DL_UNITDATA_IND}}.
The {{DL_PHYS_ADDR_REQ}} primitive requests the MAC address currently associated with the PPA attached to the streams. The address is returned by the {{DL_PHYS_ADDR_ACK}} primitive. When using Style 2, this primitive is only valid following a successful {{DL_ATTACH_REQ}}.
The {{DL_SET_PHYS_ADDR_REQ}} primitive changes the MAC address currently associated with the PPA attached to the streams. This primitive affects all other current and future streams attached to this device. Once changed, all streams currently or subsequently opened and attached to this device obtain this new physical address. The new physical address remains in effect until this primitive changes
|
the physical address again or the driver is reloaded.
|
| *Note ---* The
{info:title=Note}The
superuser is allowed to change the physical address of a PPA while other streams are bound to the same
PPA.{info} |
The {{DL_GET_STATISTICS_REQ}} primitive requests a {{DL_GET_STATISTICS_ACK}} response containing statistics information associated with the PPA attached to the |
... stream. Style 2 Streams must be attached to a particular PPA using {{DL_ATTACH_REQ}} before this primitive can succeed.
h3. Implemented {{ioctl}} Functions
GLD implements the {{ioctl}} _ioc_cmd_ function described below. If GLD receives an unrecognizable {{ioctl}} command, GLD passes the command to the device-specific driver's {{gldm_ioctl()}} routine, as described in {{gld}}(9E).
The {{DLIOCRAW}} {{ioctl}} function is used by some DLPI applications, most notably the {{snoop}}(1M) command. The {{DLIOCRAW}} command puts the stream into a raw mode. In raw mode, the driver passes full MAC-level incoming packets upstream in {{M_DATA}} messages instead of transforming the packets into the {{DL_UNITDATA_IND}} form. The {{DL_UNITDATA_IND}} form is normally used for reporting incoming packets. Packet SAP filtering is still performed on streams that are in raw mode. If a stream user wants to receive all incoming packets, the user must also select the appropriate promiscuous modes. After successfully selecting raw mode, the application is also allowed to send fully formatted packets to the driver as {{M_DATA}} messages for transmission. {{DLIOCRAW}} takes no arguments. Once enabled, the stream remains in this mode until closed.
h3. GLD Driver Requirements
GLD-based drivers must include the header file {{<sys/gld.h>}}.
GLD-based drivers must be linked with the {{-N}}_“misc/gld”_ option:{code} %ld -r -N"misc/gld" xx.o -o xx {code}
GLD implements the following functions on behalf of the device-specific driver: * {{open}}(9E) * {{close}}(9E) * {{put}}(9E), required for STREAMS * {{srv}}(9E), required for STREAMS * {{getinfo}}(9E)
The {{mi_idname}} element of the {{module_info}}(9S) structure is a string that specifies the name of the driver. This string must exactly match the name of the driver module as defined in the file system.
The read-side {{qinit}}(9S) structure should specify the following elements:
{{qi_putp}} --- {{NULL}}
{{qi_srvp}} --- {{gld_rsrv}}
{{qi_qopen}} --- {{gld_open}}
{{qi_qclose}} --- {{gld_close}}
The write-side {{qinit}}(9S) structure should specify these elements:
{{qi_putp}} --- {{gld_wput}}
{{qi_srvp}} --- {{gld_wsrv}}
{{qi_qopen}} --- {{NULL}}
{{qi_qclose}} --- {{NULL}}
The {{devo_getinfo}} element of the {{dev_ops}}(9S) structure should specify {{gld_getinfo}} as the {{getinfo}}(9E) routine.
The driver's {{attach}}(9E) function associates the hardware-specific device driver with the GLD facility. {{attach()}} then prepares the device and driver for use.
The {{attach}}(9E) function allocates a {{gld_mac_info}}(9S) structure using {{gld_mac_alloc()}}. The driver usually needs to save more information per device than is defined in the {{macinfo}} structure. The driver should allocate the additional required data structure and save a pointer to the structure in the {{gldm_private}} member of the {{gld_mac_info}}(9S) structure.
The {{attach}}(9E) routine must initialize the {{macinfo}} structure as described in the {{gld_mac_info}}(9S) man page. The {{attach()}} routine should then call {{gld_register()}} to link the driver with the GLD module. The driver should map registers if necessary and be fully initialized and prepared to accept interrupts before calling {{gld_register()}}. The {{attach}}(9E) function should add interrupts but should not enable the device to generate these interrupts. The driver should reset the hardware before calling {{gld_register()}} to ensure the hardware is quiescent. A device must not be put into a state where the device might generate an interrupt before {{gld_register()}} is called. The device is started later when GLD calls the driver's {{gldm_start()}} entry point, which is described in the {{gld}}(9E) man page. After {{gld_register()}} succeeds, the {{gld}}(9E) entry points might be called by GLD at any time.
The {{attach}}(9E) routine should return {{DDI_SUCCESS}} if {{gld_register()}} succeeds. If {{gld_register()}} fails, {{DDI_FAILURE}} is returned. If a failure occurs, the {{attach}}(9E) routine should deallocate any resources that were allocated before {{gld_register()}} was called. The attach routine should then also return {{DDI_FAILURE}}. A failed {{macinfo}} structure should never be reused. Such a structure should be deallocated using {{gld_mac_free()}}.
The {{detach}}(9E) function should attempt to unregister the driver from GLD by calling {{gld_unregister()}}. For more information about {{gld_unregister()}}, see the {{gld}}(9F) man page. The {{detach}}(9E) routine can get a pointer to the needed {{gld_mac_info}}(9S) structure from the device's private data using {{ddi_get_driver_private}}(9F). The {{gld_unregister()}} function checks certain conditions that could require that the driver not be detached. If the checks fail, {{gld_unregister()}} returns {{DDI_FAILURE}}, in which case the driver's {{detach}}(9E) routine must leave the device operational and return {{DDI_FAILURE}}.
If the checks succeed, {{gld_unregister()}} ensures that the device interrupts are stopped. The driver's {{gldm_stop()}} routine is called if necessary. The driver is unlinked from the GLD framework. {{gld_unregister()}} then returns {{DDI_SUCCESS}}. In this case, the {{detach}}(9E) routine should remove interrupts and use {{gld_mac_free()}} to deallocate any {{macinfo}} data structures that were allocated in the {{attach}}(9E) routine. The {{detach()}} routine should then return {{DDI_SUCCESS}}. The routine must remove the interrupt _before_ calling {{gld_mac_free()}}.
h3. Network Statistics
Solaris network drivers must implement statistics variables. GLD tallies some network statistics, but other statistics must be counted by each GLD-based driver. GLD provides support for GLD-based drivers to report a standard set of network driver statistics. Statistics are reported by GLD using the {{kstat}}(7D) and {{kstat}}(9S) mechanisms. The {{DL_GET_STATISTICS_REQ}} DLPI command can also be used to retrieve the current statistics counters. All statistics are maintained as unsigned. The statistics are 32 bits unless otherwise noted.
GLD maintains and reports the following statistics.
{{rbytes64}} \\ Total bytes successfully received on the interface. Stores 64-bit statistics.
{{rbytes}} \\ Total bytes successfully received on the interface
{{obytes64}} \\ Total bytes that have requested transmission on the interface. Stores 64-bit statistics.
{{obytes}} \\ Total bytes that have requested transmission on the interface.
{{ipackets64}} \\ Total packets successfully received on the interface. Stores 64-bit statistics.
{{ipackets}} \\ Total packets successfully received on the interface.
{{opackets64}} \\ Total packets that have requested transmission on the interface. Stores 64-bit statistics.
{{opackets}} \\ Total packets that have requested transmission on the interface.
{{multircv}} \\ Multicast packets successfully received, including group and functional addresses ({{long}}).
{{multixmt}} \\ Multicast packets requested to be transmitted, including group and functional addresses ({{long}}).
{{brdcstrcv}} \\ Broadcast packets successfully received ({{long}}).
{{brdcstxmt}} \\ Broadcast packets that have requested transmission ({{long}}).
{{unknowns}} \\ Valid received packets not accepted by any stream ({{long}}).
{{noxmtbuf}} \\ Packets discarded on output because transmit buffer was busy, or no buffer could be allocated for transmit ({{long}}).
{{blocked}} \\ Number of times a received packet could not be put up a stream because the queue was flow-controlled ({{long}}).
{{xmtretry}} \\ Times transmit was retried after having been delayed due to lack of resources ({{long}}).
{{promisc}} \\ Current “promiscuous” state of the interface (string).
The device-dependent driver tracks the following statistics in a private per-instance structure. To report statistics, GLD calls the driver's {{gldm_get_stats()}} entry point. {{gldm_get_stats()}} then updates device-specific statistics in the {{gld_stats}}(9S) structure. See the {{gldm_get_stats}}(9E) man page for more information. GLD then reports the updated statistics using the named statistics variables that are shown below.
{{ifspeed}} \\ Current estimated bandwidth of the interface in bits per second. Stores 64-bit statistics.
{{media}} \\ Current media type in use by the device (string).
{{intr}} \\ Number of times that the interrupt handler was called, causing an interrupt ({{long}}).
{{norcvbuf}} \\ Number of times a valid incoming packet was known to have been discarded because no buffer could be allocated for receive ({{long}}).
{{ierrors}} \\ Total number of packets that were received but could not be processed due to errors ({{long}}).
{{oerrors}} \\ Total packets that were not successfully transmitted because of errors ({{long}}).
{{missed}} \\ Packets known to have been dropped by the hardware on receive ({{long}}).
{{uflo}} \\ Times FIFO underflowed on transmit ({{long}}).
{{oflo}} \\ Times receiver overflowed during receive ({{long}}).
The following group of statistics applies to networks of type {{DL_ETHER}}. These statistics are maintained by device-specific drivers of that type, as shown previously.
{{align_errors}} \\ Packets that were received with framing errors, that is, the packets did not contain an integral number of octets ({{long}}).
{{fcs_errors}} \\ Packets received with CRC errors ({{long}}).
{{duplex}} \\ Current duplex mode of the interface (string).
{{carrier_errors}} \\ Number of times carrier was lost or never detected on a transmission attempt ({{long}}).
{{collisions}} \\ Ethernet collisions during transmit ({{long}}).
{{ex_collisions}} \\ Frames where excess collisions occurred on transmit, causing transmit failure ({{long}}).
{{tx_late_collisions}} \\ Number of times a transmit collision occurred late, that is, after 512 bit times ({{long}}).
{{defer_xmts}} \\ Packets without collisions where first transmit attempt was delayed because the medium was busy ({{long}}).
{{first_collisions}} \\ Packets successfully transmitted with exactly one collision.
{{multi_collisions}} \\ Packets successfully transmitted with multiple collisions.
{{sqe_errors}} \\ Number of times that SQE test error was reported.
{{macxmt_errors}} \\ Packets encountering transmit MAC failures, except carrier and collision failures.
{{macrcv_errors}} \\ Packets received with MAC errors, except {{align_errors}}, {{fcs_errors}}, and {{toolong_errors}}.
{{toolong_errors}} \\ Packets received larger than the maximum allowed length.
{{runt_errors}} \\ Packets received smaller than the minimum allowed length ({{long}}).
The following group of statistics applies to networks of type {{DL_TPR}}. These statistics are maintained by device-specific drivers of that type, as shown above.
{{line_errors}} \\ Packets received with non-data bits or FCS errors.
{{burst_errors}} \\ Number of times an absence of transitions for five half-bit timers was detected.
{{signal_losses}} \\ Number of times loss of signal condition on the ring was detected.
{{ace_errors}} \\ Number of times that an AMP or SMP frame, in which A is equal to C is equal to 0, is followed by another SMP frame without an intervening AMP frame.
{{internal_errors}} \\ Number of times the station recognized an internal error.
{{lost_frame_errors}} \\ Number of times the TRR timer expired during transmit.
{{frame_copied_errors}} \\ Number of times a frame addressed to this station was received with the FS field `A' bit set to {{1}}.
{{token_errors}} \\ Number of times the station acting as the active monitor recognized an error condition that needed a token transmitted.
{{freq_errors}} \\ Number of times the frequency of the incoming signal differed from the expected frequency.
The following group of statistics applies to networks of type {{DL_FDDI}}. These statistics are maintained by device-specific drivers of that type, as shown above.
{{mac_errors}} \\ Frames detected in error by this MAC that had not been detected in error by another MAC.
{{mac_lost_errors}} \\ Frames received with format errors such that the frame was stripped.
{{mac_tokens}} \\ Number of tokens that were received, that is, the total of non-restricted and restricted tokens.
{{mac_tvx_expired}} \\ Number of times that TVX has expired.
{{mac_late}} \\ Number of TRT expirations since either this MAC was reset or a token was received.
{{mac_ring_ops}} \\ Number of times the ring has entered the “Ring Operational” state from the “Ring Not Operational” state.
h2. Declarations and Data Structures{anchor:decdata}
This section describes the {{gld_mac_info}}(9S) and {{gld_stats}} structures.
h3. {{gld_mac_info}} Structure
The GLD MAC information ({{gld_mac_info}}) structure is the main data interface that links the device-specific driver with GLD. This structure contains data required by GLD and a pointer to an optional additional driver-specific information structure.
Allocate the {{gld_mac_info}} structure using {{gld_mac_alloc()}}. Deallocate the structure using {{gld_mac_free()}}. Drivers must not make any assumptions about the length of this structure, which might vary in different releases of the Solaris OS, GLD, or both. Structure members private to GLD, not documented here, should neither be set nor be read by the device-specific driver.
The {{gld_mac_info}}(9S) structure contains the following fields. {code} caddr_t gldm_private; /* Driver private data */ int (*gldm_reset)(); /* Reset device */ int (*gldm_start)(); /* Start device */ int (*gldm_stop)(); /* Stop device */ int (*gldm_set_mac_addr)(); /* Set device phys addr */ int (*gldm_set_multicast)(); /* Set/delete multicast addr */ int (*gldm_set_promiscuous)(); /* Set/reset promiscuous mode */ int (*gldm_send)(); /* Transmit routine */ uint_t (*gldm_intr)(); /* Interrupt handler */ int (*gldm_get_stats)(); /* Get device statistics */ int (*gldm_ioctl)(); /* Driver-specific ioctls */ char *gldm_ident; /* Driver identity string */ uint32_t gldm_type; /* Device type */ uint32_t gldm_minpkt; /* Minimum packet size */ /* accepted by driver */ uint32_t gldm_maxpkt; /* Maximum packet size */ /* accepted by driver */ uint32_t gldm_addrlen; /* Physical address length */ int32_t gldm_saplen; /* SAP length for DL_INFO_ACK */ unsigned char *gldm_broadcast_addr; /* Physical broadcast addr */ unsigned char *gldm_vendor_addr; /* Factory MAC address */ t_uscalar_t gldm_ppa; /* Physical Point of */ /* Attachment (PPA) number */ dev_info_t *gldm_devinfo; /* Pointer to device's */ /* dev_info node */ ddi_iblock_cookie_t gldm_cookie; /* Device's interrupt */ /* block cookie */ {code}
The {{gldm_private}} structure member is visible to the device driver. {{gldm_private}} is also private to the device-specific driver. {{gldm_private}} is not used or modified by GLD. Conventionally, {{gldm_private}} is used as a pointer to private data, pointing to a per-instance data structure that is both defined and allocated by the driver.
The following group of structure members must be set by the driver before calling {{gld_register()}}, and should not thereafter be modified by the driver. Because {{gld_register()}} might use or cache the values of structure members, changes made by the driver after calling {{gld_register()}} might cause unpredictable results. For more information on these structures, see the {{gld}}(9E) man page. {{gldm_reset}} \\ Pointer to driver entry point.
{{gldm_start}} \\ Pointer to driver entry point.
{{gldm_stop}} \\ Pointer to driver entry point.
{{gldm_set_mac_addr}} \\ Pointer to driver entry point.
{{gldm_set_multicast}} \\ Pointer to driver entry point.
{{gldm_set_promiscuous}} \\ Pointer to driver entry point.
{{gldm_send}} \\ Pointer to driver entry point.
{{gldm_intr}} \\ Pointer to driver entry point.
{{gldm_get_stats}} \\ Pointer to driver entry point.
{{gldm_ioctl}} \\ Pointer to driver entry point. This pointer is allowed to be null.
{{gldm_ident}} \\ Pointer to a string that contains a short description of the device. This pointer is used to identify the device in system messages.
{{gldm_type}} \\ Type of device the driver handles. GLD currently supports the following values: * {{DL_ETHER}} (ISO 8802-3 (IEEE 802.3) and Ethernet Bus) |
* {{DL_TPR}} (IEEE 802.5 Token Passing Ring) * {{DL_FDDI}} (ISO 9314-2 Fibre Distributed Data Interface) |
| \\
|
This structure member must be correctly set for GLD to function properly.
|
... {{gldm_minpkt}} \\ Minimum _Service_ _Data_ _Unit_ size: the minimum packet size, not including the MAC header, that the device can transmit. This size is allowed to be zero if the device-specific driver handles any required padding.
{{gldm_maxpkt}} \\ Maximum _Service_ _Data_ _Unit_ size: the maximum size of packet, not including the MAC header, that can be transmitted by the device. For Ethernet, this number is 1500.
{{gldm_addrlen}} \\ The length in bytes of physical addresses handled by the device. For Ethernet, Token Ring, and FDDI, the value of this structure member should be 6.
{{gldm_saplen}} \\ The length in bytes of the SAP address used by the driver. For GLD-based drivers, the length should always be set to {{-2}}. A length of {{-2}} indicates that 2-byte SAP values are supported and that the SAP appears _after_ the physical address in a DLSAP address. See Appendix A.2, “Message DL_INFO_ACK,” in the DLPI specification for more details.
{{gldm_broadcast_addr}} \\ Pointer to an array of bytes of length {{gldm_addrlen}} containing the broadcast address to be used for transmit. The driver must provide space to hold the broadcast address, fill the space with the appropriate value, and set {{gldm_broadcast_addr}} to point to the address. For Ethernet, Token Ring, and FDDI, the broadcast address is normally {{0xFF-FF-FF-FF-FF-FF}}.
{{gldm_vendor_addr}} \\ Pointer to an array of bytes of length {{gldm_addrlen}} that contains the vendor-provided network physical address of the device. The driver must provide space to hold the address, fill the space with information from the device, and set {{gldm_vendor_addr}} to point to the address.
{{gldm_ppa}} \\ PPA number for this instance of the device. The PPA number should always be set to the instance number that is returned from {{ddi_get_instance}}(9F).
{{gldm_devinfo}} \\ Pointer to the {{dev_info}} node for this device.
{{gldm_cookie}} \\ Interrupt block cookie returned by one of the following routines: * {{ddi_get_iblock_cookie}}(9F) * {{ddi_add_intr}}(9F) |
* {{ddi_get_soft_iblock_cookie}}(9F) * {{ddi_add_softintr}}(9F) |
| \\
|
| This cookie must correspond to the device's receive-interrupt, from which {{gld_recv()}} is called. |
h3. {{gld_stats}} Structure
After calling {{gldm_get_stats()}}, a GLD-based driver uses the ({{gld_stats}}) structure to communicate statistics and state information to GLD. See the {{gld}}(9E) and {{gld}}(7D) man pages. The members of this structure, having been filled in by the GLD-based driver, are used when GLD reports the statistics. In the tables below, the name of the statistics variable reported by GLD is noted in the comments. See the {{gld}}(7D) man page for a more detailed description of the meaning of each statistic.
Drivers must not make any assumptions about the length of this structure. The structure length might vary in different releases of the Solaris OS, GLD, or both. Structure members private to GLD, which are not documented here, should not be set or be read by the device-specific driver.
The following structure members are defined for all media types: {code} uint64_t glds_speed; /* ifspeed */ uint32_t glds_media; /* media */ uint32_t glds_intr; /* intr */ uint32_t glds_norcvbuf; /* norcvbuf */ uint32_t glds_errrcv; /* ierrors */ uint32_t glds_errxmt; /* oerrors */ uint32_t glds_missed; /* missed */ uint32_t glds_underflow; /* uflo */ uint32_t glds_overflow; /* oflo */ {code}
The following structure members are defined for media type {{DL_ETHER}}: {code} uint32_t glds_frame; /* align_errors */ uint32_t glds_crc; /* fcs_errors */ uint32_t glds_duplex; /* duplex */ uint32_t glds_nocarrier; /* carrier_errors */ uint32_t glds_collisions; /* collisions */ uint32_t glds_excoll; /* ex_collisions */ uint32_t glds_xmtlatecoll; /* tx_late_collisions */ uint32_t glds_defer; /* defer_xmts */ uint32_t glds_dot3_first_coll; /* first_collisions */ uint32_t glds_dot3_multi_coll; /* multi_collisions */ uint32_t glds_dot3_sqe_error; /* sqe_errors */ uint32_t glds_dot3_mac_xmt_error; /* macxmt_errors */ uint32_t glds_dot3_mac_rcv_error; /* macrcv_errors */ uint32_t glds_dot3_frame_too_long; /* toolong_errors */ uint32_t glds_short; /* runt_errors */ {code}
The following structure members are defined for media type {{DL_TPR}}: {code} uint32_t glds_dot5_line_error /* line_errors */ uint32_t glds_dot5_burst_error /* burst_errors */ uint32_t glds_dot5_signal_loss /* signal_losses */ uint32_t glds_dot5_ace_error /* ace_errors */ uint32_t glds_dot5_internal_error /* internal_errors */ uint32_t glds_dot5_lost_frame_error /* lost_frame_errors */ uint32_t glds_dot5_frame_copied_error /* frame_copied_errors */ uint32_t glds_dot5_token_error /* token_errors */ uint32_t glds_dot5_freq_error /* freq_errors */ {code}
The following structure members are defined for media type {{DL_FDDI}}: {code} uint32_t glds_fddi_mac_error; /* mac_errors */ uint32_t glds_fddi_mac_lost; /* mac_lost_errors */ uint32_t glds_fddi_mac_token; /* mac_tokens */ uint32_t glds_fddi_mac_tvx_expired; /* mac_tvx_expired */ uint32_t glds_fddi_mac_late; /* mac_late */ uint32_t glds_fddi_mac_ring_op; /* mac_ring_ops */ {code}
Most of the above statistics variables are counters that denote the number of times that the particular event was observed. The following statistics do not represent the number of times:
{{glds_speed}} \\ Estimate of the interface's current bandwidth in bits per second. This object should contain the nominal bandwidth for those interfaces that do not vary in bandwidth or where an accurate estimate cannot be made.
{{glds_media}} \\ Type of media (wiring) or connector used by the hardware. The following media names are supported: * {{GLDM_AUI}} * {{GLDM_BNC}} * {{GLDM_TP}} * {{GLDM_10BT}} * {{GLDM_100BT}} * {{GLDM_100BTX}} * {{GLDM_100BT4}} * {{GLDM_RING4}} * {{GLDM_RING16}} * {{GLDM_FIBER}} * {{GLDM_PHYMII}} * {{GLDM_UNKNOWN}}
{{glds_duplex}} \\ Current duplex state of the interface. Supported values are {{GLD_DUPLEX_HALF}} and {{GLD_DUPLEX_FULL}}. {{GLD_DUPLEX_UNKNOWN}} is also allowed.
h2. GLD Arguments{anchor:args}
The following arguments are used by the GLD routines.
_macinfo_ \\ Pointer to a {{gld_mac_info}}(9S) structure.
_macaddr_ \\ Pointer to the beginning of a character array that contains a valid MAC address. The array is of the length specified by the driver in the {{gldm_addrlen}} element of the {{gld_mac_info}}(9S) structure.
_multicastaddr_ \\ Pointer to the beginning of a character array that contains a multicast, group, or functional address. The array is of the length specified by the driver in the {{gldm_addrlen}} element of the {{gld_mac_info}}(9S) structure.
_multiflag_ \\ Flag indicating whether to enable or disable reception of the multicast address. This argument is specified as {{GLD_MULTI_ENABLE}} or {{GLD_MULTI_DISABLE}}.
_promiscflag_ \\ Flag indicating what type of promiscuous mode, if any, is to be enabled. This argument is specified as {{GLD_MAC_PROMISC_PHYS}}, {{GLD_MAC_PROMISC_MULTI}}, or {{GLD_MAC_PROMISC_NONE}}.
_mp_ \\ {{gld_ioctl()}} uses _mp_ as a pointer to a STREAMS message block containing the {{ioctl}} to be executed. {{gldm_send()}} uses _mp_ as a pointer to a STREAMS message block containing the packet to be transmitted. {{gld_recv()}} uses _mp_ as a pointer to a message block containing a received packet.
_stats_ \\ Pointer to a {{gld_stats}}(9S) structure to be filled in with the current values of statistics counters.
_q_ \\ Pointer to the {{queue}}(9S) structure to be used in the reply to the {{ioctl}}. _dip_ \\ Pointer to the device's {{dev_info}} structure.
_name_ \\ Device interface name.
h2. GLD Entry Points{anchor:entrypts}
Entry points must be implemented by a device-specific network driver that has been designed to interface with GLD.
The {{gld_mac_info}}(9S) structure is the main structure for communication between the device-specific driver and the GLD module. See the {{gld}}(7D) man page. Some elements in that structure are function pointers to the entry points that are described here. The device-specific driver must, in its {{attach}}(9E) routine, initialize these function pointers before calling {{gld_register()}}.
h3. {{gldm_reset()}} Entry Point {code} int _prefix__reset(gld_mac_info_t _*macinfo_); {code}
{{gldm_reset()}} resets the hardware to its initial state.
h3. {{gldm_start()}} Entry Point {code} int _prefix__start(gld_mac_info_t _*macinfo_); {code}
{{gldm_start()}} enables the device to generate interrupts. {{gldm_start()}} also prepares the driver to call {{gld_recv()}} to deliver received data packets to GLD.
h3. {{gldm_stop()}} Entry Point {code} int _prefix__stop(gld_mac_info_t _*macinfo_); {code}
{{gldm_stop()}} disables the device from generating any interrupts and stops the driver from calling {{gld_recv()}} for delivering data packets to GLD. GLD depends on the {{gldm_stop()}} routine to ensure that the device will no longer interrupt. {{gldm_stop()}} must do so without fail. This function should always return {{GLD_SUCCESS}}.
h3. {{gldm_set_mac_addr()}} Entry Point {code} int _prefix__set_mac_addr(gld_mac_info_t _*macinfo_, unsigned char _*macaddr_); {code}
{{gldm_set_mac_addr()}} sets the physical address that the hardware is to use for receiving data. This function enables the device to be programmed through the passed MAC address _macaddr_. If sufficient resources are currently not available to carry out the request, {{gldm_set_mac_add()}} should return {{GLD_NORESOURCES}}. If the requested function is not supported, {{gldm_set_mac_add()}} should return {{GLD_NOTSUPPORTED}}.
h3. {{gldm_set_multicast()}} Entry Point {code} int _prefix__set_multicast(gld_mac_info_t *macinfo, unsigned char *_multicastaddr_, int _multiflag_); {code}
{{gldm_set_multicast()}} enables and disables device-level reception of specific multicast addresses. If the third argument _multiflag_ is set to {{GLD_MULTI_ENABLE}}, then {{gldm_set_multicast()}} sets the interface to receive packets with the multicast address. {{gldm_set_multicast()}} uses the multicast address that is pointed to by the second argument. If _multiflag_ is set to {{GLD_MULTI_DISABLE}}, the driver is allowed to disable reception of the specified multicast address.
This function is called whenever GLD wants to enable or disable reception of a multicast, group, or functional address. GLD makes no assumptions about how the device does multicast support and calls this function to enable or disable a specific multicast address. Some devices might use a hash algorithm and a bitmask to enable collections of multicast addresses. This procedure is allowed, and GLD filters out any superfluous packets. If disabling an address could result in disabling more than one address at the device level, the device driver should keep any necessary information. This approach avoids disabling an address that GLD has enabled but not disabled.
{{gldm_set_multicast()}} is not called to enable a particular multicast address that is already enabled. Similarly, {{gldm_set_multicast()}} is not called to disable an address that is not currently enabled. GLD keeps track of multiple requests for the same multicast address. GLD only calls the driver's entry point when the first request to enable, or the last request to disable, a particular multicast address is made. If sufficient resources are currently not available to carry out the request, the function should return {{GLD_NORESOURCES}}. The function should return {{GLD_NOTSUPPORTED}} if the requested function is not supported. h3. {{gldm_set_promiscuous()}} Entry Point {code} int _prefix__set_promiscuous(gld_mac_info_t _*macinfo_, int _promiscflag_); {code}
{{gldm_set_promiscuous()}} enables and disables promiscuous mode. This function is called whenever GLD wants to enable or disable the reception of all packets on the medium. The function can also be limited to multicast packets on the medium. If the second argument _promiscflag_ is set to the value of {{GLD_MAC_PROMISC_PHYS}}, then the function enables physical-level promiscuous mode. Physical-level promiscuous mode causes the reception of all packets on the medium. If _promiscflag_ is set to {{GLD_MAC_PROMISC_MULTI}}, then reception of all multicast packets are enabled. If _promiscflag_ is set to {{GLD_MAC_PROMISC_NONE}}, then promiscuous mode is disabled.
In promiscuous multicast mode, drivers for devices without multicast-only promiscuous mode must set the device to physical promiscuous mode. This approach ensures that all multicast packets are received. In this case, the routine should return {{GLD_SUCCESS}}. The GLD software filters out any superfluous packets. If sufficient resources are currently not available to carry out the request, the function should return {{GLD_NORESOURCES}}. {{gld_set_promiscuous()}} should return {{GLD_NOTSUPPORTED}} if the requested function is not supported.
For forward compatibility, {{gldm_set_promiscuous()}} routines should treat any unrecognized values for _promiscflag_ as though these values were {{GLD_MAC_PROMISC_PHYS}}.
h3. {{gldm_send()}} Entry Point {code} int _prefix__send(gld_mac_info_t _*macinfo_, mblk_t _*mp_); {code}
{{gldm_send()}} queues a packet to the device for transmission. This routine is passed a STREAMS message containing the packet to be sent. The message might include multiple message blocks. The {{send()}} routine must traverse all the message blocks in the message to access the entire packet to be sent. The driver should be prepared to handle and skip over any zero-length message continuation blocks in the chain. The driver should also check that the packet does not exceed the maximum allowable packet size. The driver must pad the packet, if necessary, to the minimum allowable packet size. If the send routine successfully transmits or queues the packet, {{GLD_SUCCESS}} should be returned.
The send routine should return {{GLD_NORESOURCES}} if the packet for transmission cannot be immediately accepted. In this case, GLD retries later. If {{gldm_send()}} ever returns {{GLD_NORESOURCES}}, the driver must call {{gld_sched()}} at a later time when resources have become available. This call to {{gld_sched()}} informs GLD to retry packets that the driver previously failed to queue for transmission. (If the driver's {{gldm_stop()}} routine is called, the driver is absolved from this obligation until the driver returns {{GLD_NORESOURCES}} from the {{gldm_send()}} routine. However, extra calls to {{gld_sched()}} do not cause incorrect operation.)
If the driver's send routine returns {{GLD_SUCCESS}}, then the driver is responsible for freeing the message when the message is no longer needed. If the hardware uses DMA to read the data directly, the driver must not free the message until the hardware has completely read the data. In this case, the driver can free the message in the interrupt routine. Alternatively, the driver can reclaim the buffer at the start of a future send operation. If the send routine returns anything other than {{GLD_SUCCESS}}, then the driver must not free the message. Return {{GLD_NOLINK}} if {{gldm_send()}} is called when there is no physical connection to the network or link partner.
h3. {{gldm_intr()}} Entry Point {code} int _prefix__intr(gld_mac_info_t _*macinfo_); {code}
{{gldm_intr()}} is called when the device might have interrupted. Because interrupts can be shared with other devices, the driver must check the device status to determine whether that device actually caused the interrupt. If the device that the driver controls did not cause the interrupt, then this routine must return {{DDI_INTR_UNCLAIMED}}. Otherwise, the driver must service the interrupt and return {{DDI_INTR_CLAIMED}}. If the interrupt was caused by successful receipt of a packet, this routine should put the received packet into a STREAMS message of type {{M_DATA}} and pass that message to {{gld_recv()}}.
{{gld_recv()}} passes the inbound packet upstream to the appropriate next layer of the network protocol stack. The routine must correctly set the {{b_rptr}} and {{b_wptr}} members of the STREAMS message before calling {{gld_recv()}}.
The driver should avoid holding mutex or other locks during the call to {{gld_recv()}}. In particular, locks that could be taken by a transmit thread must not be held during a call to {{gld_recv()}}. In some cases, the interrupt thread that calls {{gld_recv()}} sends an outgoing packet, which results in a call to the driver's {{gldm_send()}} routine. If {{gldm_send()}} tries to acquire a mutex that is held by {{gldm_intr()}} when {{gld_recv()}} is called, a panic occurs due to recursive mutex entry. If other driver entry points attempt to acquire a mutex that the driver holds across a call to {{gld_recv()}}, deadlock can result.
The interrupt code should increment statistics counters for any errors. Errors include the failure to allocate a buffer that is needed for the received data and any hardware-specific errors, such as CRC errors or framing errors.
h3. {{gldm_get_stats()}} Entry Point {code} int _prefix__get_stats(gld_mac_info_t _*macinfo_, struct gld_stats _*stats_); {code}
{{gldm_get_stats()}} gathers statistics from the hardware, driver private counters, or both, and updates the {{gld_stats}}(9S) structure pointed to by _stats_. This routine is called by GLD for statistics requests. GLD uses the {{gldm_get_stats()}} mechanism to acquire device-dependent statistics from the driver before GLD composes the reply to the statistics request. See the {{gld_stats}}(9S), {{gld}}(7D), and {{qreply}}(9F) man pages for more information about defined statistics counters.
h3. {{gldm_ioctl()}} Entry Point {code} int _prefix__ioctl(gld_mac_info_t _*macinfo_, queue_t _*q_, mblk_t _*mp_); {code}
{{gldm_ioctl()}} implements any device-specific {{ioctl}} commands. This element is allowed to be null if the driver does not implement any {{ioctl}} functions. The driver is responsible for converting the message block into an {{ioctl}} reply message and calling the {{qreply}}(9F) function before returning {{GLD_SUCCESS}}. This function should always return {{GLD_SUCCESS}}. The driver should report any errors as needed in a message to be passed to {{qreply}}(9F). If the {{gldm_ioctl}} element is specified as {{NULL}}, GLD returns a message of type {{M_IOCNAK}} with an error of {{EINVAL}}.
h3. GLD Return Values
Some entry point functions in GLD can return the following values, subject to the restrictions above:
{{GLD_BADARG}} \\ If the function detected an unsuitable argument, for example, a bad multicast address, a bad MAC address, or a bad packet
{{GLD_FAILURE}} \\ On hardware failure
{{GLD_SUCCESS}} \\ On success
h2. GLD Service Routines{anchor:service}
This section provides the syntax and description for the GLD service routines.
h3. {{gld_mac_alloc()}} Function {code} gld_mac_info_t *gld_mac_alloc(dev_info_t _*dip_); {code}
{{gld_mac_alloc()}} allocates a new {{gld_mac_info}}(9S) structure and returns a pointer to the structure. Some of the GLD-private elements of the structure might be initialized before {{gld_mac_alloc()}} returns. All other elements are initialized to zero. The device driver must initialize some structure members, as described in the {{gld_mac_info}}(9S) man page, before passing the pointer to the {{gld_mac_info}} structure to {{gld_register()}}.
h3. {{gld_mac_free()}} Function {code} void gld_mac_free(gld_mac_info_t _*macinfo_); {code}
{{gld_mac_free()}} frees a {{gld_mac_info}}(9S) structure previously allocated by {{gld_mac_alloc()}}.
h3. {{gld_register()}} Function {code} int gld_register(dev_info_t _*dip_, char _*name_, gld_mac_info_t _*macinfo_); {code}
{{gld_register()}} is called from the device driver's {{attach}}(9E) routine. {{gld_register()}} links the GLD-based device driver with the GLD framework. Before calling {{gld_register()}}, the device driver's {{attach}}(9E) routine uses {{gld_mac_alloc()}} to allocate a {{gld_mac_info}}(9S) structure, and then initializes several structure elements. See {{gld_mac_info}}(9S) for more information. A successful call to {{gld_register()}} performs the following actions: * Links the device-specific driver with the GLD system * Sets the device-specific driver's private data pointer, using {{ddi_set_driver_private}}(9F) to point to the {{macinfo}} structure * Creates the minor device node * Returns {{DDI_SUCCESS}}
The device interface name passed to {{gld_register()}} must exactly match the name of the driver module as that name exists in the file system.
The driver's {{attach}}(9E) routine should return {{DDI_SUCCESS}} if {{gld_register()}} succeeds. If {{gld_register()}} does not return {{DDI_SUCCESS}}, the {{attach}}(9E) routine should deallocate any allocated resources before calling {{gld_register()}}, and then return {{DDI_FAILURE}}.
h3. {{gld_unregister()}} Function {code} int gld_unregister(gld_mac_info_t _*macinfo_); {code}
{{gld_unregister()}} is called by the device driver's {{detach}}(9E) function, and if successful, performs the following tasks: * Ensures that the device's interrupts are stopped, calling the driver's {{gldm_stop()}} routine if necessary * Removes the minor device node * Unlinks the device-specific driver from the GLD system * Returns {{DDI_SUCCESS}}
If {{gld_unregister()}} returns {{DDI_SUCCESS}}, the {{detach}}(9E) routine should deallocate any data structures allocated in the {{attach}}(9E) routine, using {{gld_mac_free()}} to deallocate the {{macinfo}} structure, and return {{DDI_SUCCESS}}. If {{gld_unregister()}} does not return {{DDI_SUCCESS}}, the driver's {{detach}}(9E) routine must leave the device operational and return {{DDI_FAILURE}}.
h3. {{gld_recv()}} Function {code} void gld_recv(gld_mac_info_t _*macinfo_, mblk_t _*mp_); {code}
{{gld_recv()}} is called by the driver's interrupt handler to pass a received packet upstream. The driver must construct and pass a STREAMS {{M_DATA}} message containing the raw packet. {{gld_recv()}} determines which STREAMS queues should receive a copy of the packet, duplicating the packet if necessary. {{gld_recv()}} then formats a {{DL_UNITDATA_IND}} message, if required, and passes the data up all appropriate streams.
The driver should avoid holding mutex or other locks during the call to {{gld_recv()}}. In particular, locks that could be taken by a transmit thread must not be held during a call to {{gld_recv()}}. The interrupt thread that calls {{gld_recv()}} in some cases carries out processing that includes sending an outgoing packet. Transmission of the packet results in a call to the driver's {{gldm_send()}} routine. If {{gldm_send()}} tries to acquire a mutex that is held by {{gldm_intr()}} when {{gld_recv()}} is called, a panic occurs due to a recursive mutex entry. If other driver entry points attempt to acquire a mutex that the driver holds across a call to {{gld_recv()}}, deadlock can result.
h3. {{gld_sched()}} Function {code} void gld_sched(gld_mac_info_t _*macinfo_); {code}
{{gld_sched()}} is called by the device driver to reschedule stalled outbound packets. Whenever the driver's {{gldm_send()}} routine returns {{GLD_NORESOURCES}}, the driver must call {{gld_sched()}} to inform the GLD framework to retry previously unsendable packets. {{gld_sched()}} should be called as soon as possible after resources become available so that GLD resumes passing outbound packets to the driver's {{gldm_send()}} routine. (If the driver's {{gldm_stop()}} routine is called, the driver need not retry until {{GLD_NORESOURCES}} is returned from {{gldm_send()}}. However, extra calls to {{gld_sched()}} do not cause incorrect operation.)
h3. {{gld_intr()}} Function {code} uint_t gld_intr(caddr_t); {code}
{{gld_intr()}} is GLD's main interrupt handler. Normally, {{gld_intr()}} is specified as the interrupt routine in the device driver's call to {{ddi_add_intr}}(9F). The argument to the interrupt handler is specified as _int_handler_arg_ in the call to {{ddi_add_intr}}(9F). This argument must be a pointer to the {{gld_mac_info}}(9S) structure. {{gld_intr()}}, when appropriate, calls the device driver's {{gldm_intr()}} function, passing that pointer to the {{gld_mac_info}}(9S) structure. However, to use a high-level interrupt, the driver must provide its own high-level interrupt handler and trigger a soft interrupt from within the handler. In this case, {{gld_intr()}} would normally be specified as the soft interrupt handler in the call to {{ddi_add_softintr()}}. {{gld_intr()}} returns a value that is appropriate for an interrupt handler. |