GLD(9E) Driver Entry Points GLD(9E)
NAME
gld, gldm_reset, gldm_start, gldm_stop, gldm_set_mac_addr,
gldm_set_multicast, gldm_set_promiscuous, gldm_send, gldm_intr,
gldm_get_stats, gldm_ioctl - Generic LAN Driver entry points
SYNOPSIS
#include <sys/gld.h>
int prefix_reset(
gld_mac_info_t *macinfo);
int prefix_start(
gld_mac_info_t *macinfo);
int prefix_stop(
gld_mac_info_t * macinfo);
int prefix_set_mac_addr(
gld_mac_info_t * macinfo,
unsigned char *macaddr);
int prefix_set_multicast(
gld_mac_info_t * macinfo,
unsigned char *multicastaddr,
int multiflag);
int prefix_set_promiscuous(
gld_mac_info_t *macinfo,
int promiscflag);
int prefix_send(
gld_mac_info_t *macinfo,
mblk_t *mp);
uint_t prefix_intr(
gld_mac_info_t *macinfo);
int prefix_get_stats(
gld_mac_info_t *macinfo,
struct gld_stats *stats);
int prefix_ioctl(
gld_mac_info_t *macinfo,
queue_t *q,
mblk_t *mp);
INTERFACE LEVEL
illumos architecture specific (illumos DDI).
PARAMETERS
macinfo Pointer to a
gld_mac_info(9S) structure.
macaddr Pointer to the beginning of a character array
containing a valid MAC address. The array will be 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
containing a multicast, group, or functional address.
The array will be of the length specified by the driver
in the
gldm_addrlen element of the
gld_mac_info(9S) structure.
multiflag A flag indicating whether reception of the multicast
address is to be enabled or disabled. This argument is
specified as
GLD_MULTI_ENABLE or
GLD_MULTI_DISABLE.
promiscflag A 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 Pointer to a STREAMS message block containing the
packet to be transmitted or the ioctl to be executed.
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.
DESCRIPTION
These entry points must be implemented by a device-specific network
driver designed to interface with the Generic LAN Driver (GLD).
As described in
gld(4D), the main data structure for communication
between the device-specific driver and the GLD module is the
gld_mac_info(9S) structure. Some of the elements in that structure are
function pointers to the entry points described here. The device-specific
driver must, in its
attach(9E) routine, initialize these function
pointers before calling
gld_register().
gldm_reset() resets the hardware to its initial state.
gldm_start() enables the device to generate interrupts and prepares the
driver to call
gld_recv() for delivering received data packets to GLD.
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, and it must do so without fail.
gldm_set_mac_addr() sets the physical address that the hardware is to use
for receiving data. This function should program the device to the passed
MAC address
macaddr.
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 the function sets the interface to receive packets
with the multicast address 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 may use a
hash algorithm and a bitmask to enable collections of multicast
addresses; this is allowed, and GLD will filter out any superfluous
packets that are not required. If disabling an address could result in
disabling more than one address at the device level, it is the
responsibility of the device driver to keep whatever information it needs
to avoid disabling an address that GLD has enabled but not disabled.
gldm_set_multicast() will not be called to enable a particular multicast
address that is already enabled, nor to disable an address that is not
currently enabled. GLD keeps track of multiple requests for the same
multicast address and 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.
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, or all 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, resulting in the reception of all packets on the
medium. If
promiscflag is set to
GLD_MAC_PROMISC_MULTI, then reception of
all multicast packets will be enabled. If
promiscflag is set to
GLD_MAC_PROMISC_NONE, then promiscuous mode is disabled.
In the case of a request for promiscuous multicast mode, drivers for
devices that have no multicast-only promiscuous mode must set the device
to physical promiscuous mode to ensure that all multicast packets are
received. In this case the routine should return
GLD_SUCCESS. The GLD
software will filter out any superfluous packets that are not required.
For forward compatibility,
gldm_set_promiscuous() routines should treat
any unrecognized values for
promiscflag as though they were
GLD_MAC_PROMISC_PHYS.
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
may comprise multiple message blocks, and the send routine must chain
through 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
check to ensure that the packet does not exceed the maximum allowable
packet size, and must pad the packet, if necessary, to the minimum
allowable packet size. If the send routine successfully transmits or
queues the packet, it should return
GLD_SUCCESS.
The send routine should return
GLD_NORESOURCES if it cannot immediately
accept the packet for transmission; in this case GLD will retry it later.
If
gldm_send() ever returns
GLD_NORESOURCES, the driver must, at a later
time when resources have become available, call
gld_sched() to inform GLD
that it should 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 it later again returns
GLD_NORESOURCES from its
gldm_send() routine; however, extra calls to
gld_sched() will not cause incorrect operation.)
If the driver's send routine returns
GLD_SUCCESS, then the driver is
responsible for freeing the message when the driver and the hardware no
longer need it. If the send routine copied the message into the device,
or into a private buffer, then the send routine may free the message
after the copy is made. If the hardware uses DMA to read the data
directly out of the message data blocks, then the driver must not free
the message until the hardware has completed reading the data. In this
case the driver will probably free the message in the interrupt routine,
or in a buffer-reclaim operation at the beginning of a future send
operation. If the send routine returns anything other than
GLD_SUCCESS,
then the driver must not free the message.
gldm_intr() is called when the device might have interrupted. Since it is
possible to share interrupts with other devices, the driver must check
the device status to determine whether it actually caused an interrupt.
If the device that the driver controls did not cause the interrupt, then
this routine must return
DDI_INTR_UNCLAIMED. Otherwise it must service
the interrupt and should 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() will pass the inbound packet upstream to the appropriate next
layer of the network protocol stack. It is important to 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
may not be held during a call to
gld_recv(): the interrupt thread that
calls
gld_recv() may in some cases carry out processing that includes
sending an outgoing packet, resulting in a call to the driver's
gldm_send() routine. If the
gldm_send() routine were to try to acquire a
mutex being held by the
gldm_intr() routine at the time it calls
gld_recv(), this could result in a panic due to recursive mutex entry.
The interrupt code should increment statistics counters for any errors.
This includes failure to allocate a buffer needed for the received data
and any hardware-specific errors such as CRC errors or framing errors.
gldm_get_stats() gathers statistics from the hardware and/or driver
private counters, and updates the
gld_stats(9S) structure pointed to by
stats. This routine is called by GLD when it gets a request for
statistics, and provides the mechanism by which GLD acquires device
dependent statistics from the driver before composing its reply to the
statistics request. See
gld_stats(9S) and
gld(4D) for a description of
the defined statistics counters.
gldm_ioctl() implements any device-specific ioctl commands. This element
may be specified as
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;
any errors the driver may wish to report should be returned via the
message passed to
qreply(9F). If the
gldm_ioctl element is specified as
NULL, GLD will return a message of type
M_IOCNAK with an error of
EINVAL.
RETURN VALUES
gldm_intr() must return:
DDI_INTR_CLAIMED if and only if the device definitely interrupted.
DDI_INTR_UNCLAIMED if the device did not interrupt.
The other functions must return:
GLD_SUCCESS on success.
gldm_stop() and
gldm_ioctl() should
always return this value.
GLD_NORESOURCES if there are insufficient resources to carry out the
request at this time. Only
gldm_set_mac_addr(),
gldm_set_multicast(),
gldm_set_promiscuous(), and
gldm_send() may return this value.
GLD_NOLINK if
gldm_send() is called when there is no physical
connection to a network or link partner.
GLD_NOTSUPPORTED if the requested function is not supported. Only
gldm_set_mac_addr(),
gldm_set_multicast(), and
gldm_set_promiscuous() may return this value.
GLD_BADARG if the function detected an unsuitable argument, for
example, a bad multicast address, a bad MAC address,
or a bad packet or packet length.
GLD_FAILURE on hardware failure.
SEE ALSO
gld(4D),
dlpi(4P),
attach(9E),
ddi_add_intr(9F),
gld(9F),
gld_mac_info(9S),
gld_stats(9S) Writing Device Drivers January 3, 2001
GLD(9E)