GLD

Version 1 by Alta
on Feb 27, 2008 21:28.

compared with
Current by Alta
on Feb 28, 2008 11:02.

Key
This line was removed.
This word was removed. This word was added.
This line was added.

Changes (6)

View page history
* 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
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 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
* {{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.
* {{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.

The individuals who post here are part of the extended Sun Microsystems community and they might not be employed or in any way formally affiliated with Sun Microsystems. The opinions expressed here are their own, are not necessarily reviewed in advance by anyone but the individual authors, and neither Sun nor any other party necessarily agrees with them.

Copyright 1994-2009 Sun Microsystems, Inc.
Powered by Atlassian Confluence
Sun Guidelines on Public Discourse Privacy Policy Terms of Use Trademarks Site Map Employment Investor Relations Contact