GLD Entry Points
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().
gldm_reset() Entry Point
int prefix_reset(gld_mac_info_t *macinfo);
gldm_reset() resets the hardware to its initial state.
gldm_start() Entry Point
int prefix_start(gld_mac_info_t *macinfo);
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.
gldm_stop() Entry Point
int prefix_stop(gld_mac_info_t *macinfo);
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.
gldm_set_mac_addr() Entry Point
int prefix_set_mac_addr(gld_mac_info_t *macinfo, unsigned char *macaddr);
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.
gldm_set_multicast() Entry Point
int prefix_set_multicast(gld_mac_info_t *macinfo,
unsigned char *multicastaddr, int multiflag);
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.
gldm_set_promiscuous() Entry Point
int prefix_set_promiscuous(gld_mac_info_t *macinfo, int promiscflag);
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.
gldm_send() Entry Point
int prefix_send(gld_mac_info_t *macinfo, mblk_t *mp);
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.
gldm_intr() Entry Point
int prefix_intr(gld_mac_info_t *macinfo);
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.
gldm_get_stats() Entry Point
int prefix_get_stats(gld_mac_info_t *macinfo, struct gld_stats *stats);
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.
gldm_ioctl() Entry Point
int prefix_ioctl(gld_mac_info_t *macinfo, queue_t *q, mblk_t *mp);
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.
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