1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * IEEE 802.3ad Link Aggregation.
  28  */
  29 
  30 #include <sys/conf.h>
  31 #include <sys/modctl.h>
  32 #include <sys/aggr.h>
  33 #include <sys/aggr_impl.h>
  34 
  35 /* module description */
  36 #define AGGR_LINKINFO   "Link Aggregation MAC"
  37 
  38 /* device info ptr, only one for instance 0 */
  39 dev_info_t *aggr_dip = NULL;
  40 
  41 static int aggr_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
  42 static int aggr_attach(dev_info_t *, ddi_attach_cmd_t);
  43 static int aggr_detach(dev_info_t *, ddi_detach_cmd_t);
  44 
  45 DDI_DEFINE_STREAM_OPS(aggr_dev_ops, nulldev, nulldev, aggr_attach, aggr_detach,
  46     nodev, aggr_getinfo, D_MP, NULL, ddi_quiesce_not_supported);
  47 
  48 static struct modldrv aggr_modldrv = {
  49         &mod_driverops,             /* Type of module.  This one is a driver */
  50         AGGR_LINKINFO,          /* short description */
  51         &aggr_dev_ops               /* driver specific ops */
  52 };
  53 
  54 static struct modlinkage modlinkage = {
  55         MODREV_1, &aggr_modldrv, NULL
  56 };
  57 
  58 int
  59 _init(void)
  60 {
  61         int     err;
  62 
  63         mac_init_ops(&aggr_dev_ops, "aggr");
  64         if ((err = mod_install(&modlinkage)) != 0)
  65                 mac_fini_ops(&aggr_dev_ops);
  66         return (err);
  67 }
  68 
  69 int
  70 _fini(void)
  71 {
  72         int     err;
  73 
  74         if ((err = mod_remove(&modlinkage)) == 0)
  75                 mac_fini_ops(&aggr_dev_ops);
  76         return (err);
  77 }
  78 
  79 int
  80 _info(struct modinfo *modinfop)
  81 {
  82         return (mod_info(&modlinkage, modinfop));
  83 }
  84 
  85 /*ARGSUSED*/
  86 static int
  87 aggr_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
  88     void **result)
  89 {
  90         switch (infocmd) {
  91         case DDI_INFO_DEVT2DEVINFO:
  92                 *result = aggr_dip;
  93                 return (DDI_SUCCESS);
  94         case DDI_INFO_DEVT2INSTANCE:
  95                 *result = 0;
  96                 return (DDI_SUCCESS);
  97         }
  98         return (DDI_FAILURE);
  99 }
 100 
 101 static int
 102 aggr_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 103 {
 104         switch (cmd) {
 105         case DDI_ATTACH:
 106                 if (ddi_get_instance(dip) != 0) {
 107                         /* we only allow instance 0 to attach */
 108                         return (DDI_FAILURE);
 109                 }
 110                 if (aggr_ioc_init() != 0)
 111                         return (DDI_FAILURE);
 112                 aggr_dip = dip;
 113                 aggr_port_init();
 114                 aggr_grp_init();
 115                 aggr_lacp_init();
 116                 return (DDI_SUCCESS);
 117 
 118         case DDI_RESUME:
 119                 return (DDI_SUCCESS);
 120 
 121         default:
 122                 return (DDI_FAILURE);
 123         }
 124 }
 125 
 126 /*ARGSUSED*/
 127 static int
 128 aggr_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 129 {
 130         switch (cmd) {
 131         case DDI_DETACH:
 132                 if (aggr_grp_count() > 0)
 133                         return (DDI_FAILURE);
 134 
 135                 aggr_dip = NULL;
 136                 aggr_port_fini();
 137                 aggr_grp_fini();
 138                 aggr_lacp_fini();
 139                 aggr_ioc_fini();
 140                 return (DDI_SUCCESS);
 141 
 142         case DDI_SUSPEND:
 143                 return (DDI_SUCCESS);
 144 
 145         default:
 146                 return (DDI_FAILURE);
 147         }
 148 }