The GLDv3 interface includes driver entry points that are advertised during registration with the MAC layer and MAC entry points that are invoked by drivers.
void mac_init_ops(struct dev_ops *ops, const char *name);
A GLDv3 device driver must invoke the mac_init_ops(9F) function in its _init(9E) entry point before calling mod_install(9F).
void mac_fini_ops(struct dev_ops *ops);
A GLDv3 device driver must invoke the mac_fini_ops(9F) function in its _fini(9E) entry point after calling mod_remove(9F).
int
_init(void)
{
int rv;
mac_init_ops(&xx_devops, "xx");
if ((rv = mod_install(&xx_modlinkage)) != DDI_SUCCESS) {
mac_fini_ops(&xx_devops);
}
return (rv);
}
int
_fini(void)
{
int rv;
if ((rv = mod_remove(&xx_modlinkage)) == DDI_SUCCESS) {
mac_fini_ops(&xx_devops);
}
return (rv);
}
mac_register_t *mac_alloc(uint_t version);
The mac_alloc(9F) function allocates a new mac_register structure and returns a pointer to it. Initialize the structure members before you pass the new structure to mac_register(). MAC-private elements are initialized by the MAC layer before mac_alloc() returns. The value of version must be MAC_VERSION_V1.
void mac_free(mac_register_t *mregp);
The mac_free(9F) function frees a mac_register structure that was previously allocated by mac_alloc().
int mac_register(mac_register_t *mregp, mac_handle_t *mhp);
To register a new instance with the MAC layer, a GLDv3 driver must invoke the mac_register(9F) function in its attach(9E) entry point. The mregp argument is a pointer to a mac_register registration information structure. On success, the mhp argument is a pointer to a MAC handle for the new MAC instance. This handle is needed by other routines such as mac_tx_update(), mac_link_update(), and mac_rx().
int
xx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
mac_register_t *macp;
/* ... */
if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
xx_error(dip, "mac_alloc failed");
goto failed;
}
macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
macp->m_driver = xxp;
macp->m_dip = dip;
macp->m_src_addr = xxp->xx_curraddr;
macp->m_callbacks = &xx_m_callbacks;
macp->m_min_sdu = 0;
macp->m_max_sdu = ETHERMTU;
macp->m_margin = VLAN_TAGSZ;
if (mac_register(macp, &xxp->xx_mh) == DDI_SUCCESS) {
mac_free(macp);
return (DDI_SUCCESS);
}
/* failed to register with MAC */
mac_free(macp);
failed:
/* ... */
}
int mac_unregister(mac_handle_t mh);
The mac_unregister(9F) function unregisters a MAC instance that was previously registered with mac_register(). The mh argument is the MAC handle that was allocated by mac_register(). Invoke mac_unregister() from the detach(9E) entry point.
int
xx_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
xx_t *xxp; /* driver soft state */
/* ... */
switch (cmd) {
case DDI_DETACH:
if (mac_unregister(xxp->xx_mh) != 0) {
return (DDI_FAILURE);
}
/* ... */
}