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)

tribblix@gmail.com :: GitHub :: Privacy