1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  14  */
  15 
  16 #include <sys/sysmacros.h>
  17 #include <sys/types.h>
  18 #include <sys/kmem.h>
  19 #include <sys/ddi.h>
  20 #include <sys/sunddi.h>
  21 #include <sys/modctl.h>
  22 #include <sys/class.h>
  23 #include <sys/cmn_err.h>
  24 
  25 #ifdef _KERNEL
  26 #include <sys/debug.h>
  27 #else
  28 #include <assert.h>
  29 #endif
  30 
  31 #include "krrp_params.h"
  32 
  33 #ifdef _KERNEL
  34 #define krrp_verify(X) VERIFY(X)
  35 #else
  36 #define krrp_verify(X) assert(X)
  37 #endif
  38 
  39 #define KRRP_PARAM_EXPAND(enum_name, dtype) \
  40         {KRRP_PARAM_##enum_name, #enum_name, DATA_TYPE_##dtype},
  41 static struct {
  42         krrp_param_t    param;
  43         const char              *name;
  44         data_type_t             dtype;
  45 } krrp_params[] = {
  46         {KRRP_PARAM_UNKNOWN, NULL, DATA_TYPE_UNKNOWN},
  47         KRRP_PARAM_MAP(KRRP_PARAM_EXPAND)
  48 };
  49 #undef KRRP_PARAM_EXPAND
  50 static size_t krrp_params_sz = sizeof (krrp_params) / sizeof (krrp_params[0]);
  51 
  52 static const char *krrp_param_get_name(krrp_param_t);
  53 static data_type_t krrp_param_get_dtype(krrp_param_t);
  54 
  55 int
  56 krrp_param_get(krrp_param_t p, nvlist_t *nvl, void *result)
  57 {
  58         int rc = 0;
  59         data_type_t param_dtype;
  60         const char *name = NULL;
  61         krrp_param_array_t *param;
  62 
  63         krrp_verify(nvl != NULL);
  64 
  65         param_dtype = krrp_param_get_dtype(p);
  66         name = krrp_param_get_name(p);
  67 
  68         switch (param_dtype) {
  69         case DATA_TYPE_BOOLEAN:
  70                 rc = nvlist_lookup_boolean_value(nvl, name, result);
  71                 break;
  72         case DATA_TYPE_UINT16:
  73                 rc = nvlist_lookup_uint16(nvl, name, result);
  74                 break;
  75         case DATA_TYPE_UINT32:
  76                 rc = nvlist_lookup_uint32(nvl, name, result);
  77                 break;
  78         case DATA_TYPE_INT32:
  79                 rc = nvlist_lookup_int32(nvl, name, result);
  80                 break;
  81         case DATA_TYPE_UINT64:
  82                 rc = nvlist_lookup_uint64(nvl, name, result);
  83                 break;
  84         case DATA_TYPE_STRING:
  85                 rc = nvlist_lookup_string(nvl, name, result);
  86                 break;
  87         case DATA_TYPE_NVLIST:
  88                 rc = nvlist_lookup_nvlist(nvl, name, result);
  89                 break;
  90         case DATA_TYPE_NVLIST_ARRAY:
  91                 param = result;
  92                 rc = nvlist_lookup_nvlist_array(nvl, name,
  93                     &param->array, &param->nelem);
  94                 break;
  95         default:
  96                 krrp_verify(0);
  97         }
  98 
  99         krrp_verify(rc == 0 || rc == ENOENT);
 100 
 101         return (rc);
 102 }
 103 
 104 int
 105 krrp_param_put(krrp_param_t p, nvlist_t *nvl, void *value)
 106 {
 107         data_type_t param_dtype;
 108         const char *name = NULL;
 109         krrp_param_array_t *param;
 110 
 111         krrp_verify(nvl != NULL);
 112 
 113         param_dtype = krrp_param_get_dtype(p);
 114         name = krrp_param_get_name(p);
 115 
 116         if (nvlist_exists(nvl, name))
 117                 return (EEXIST);
 118 
 119         switch (param_dtype) {
 120         case DATA_TYPE_BOOLEAN:
 121                 if (value != NULL) {
 122                         fnvlist_add_boolean_value(nvl, name,
 123                             *((boolean_t *)value));
 124                 } else
 125                         fnvlist_add_boolean_value(nvl, name, B_TRUE);
 126 
 127                 break;
 128         case DATA_TYPE_UINT16:
 129                 fnvlist_add_uint16(nvl, name, *((uint16_t *)value));
 130                 break;
 131         case DATA_TYPE_UINT32:
 132                 fnvlist_add_uint32(nvl, name, *((uint32_t *)value));
 133                 break;
 134         case DATA_TYPE_INT32:
 135                 fnvlist_add_int32(nvl, name, *((int32_t *)value));
 136                 break;
 137         case DATA_TYPE_UINT64:
 138                 fnvlist_add_uint64(nvl, name, *((uint64_t *)value));
 139                 break;
 140         case DATA_TYPE_STRING:
 141                 krrp_verify(value != NULL);
 142                 fnvlist_add_string(nvl, name, value);
 143                 break;
 144         case DATA_TYPE_NVLIST:
 145                 fnvlist_add_nvlist(nvl, name, value);
 146                 break;
 147         case DATA_TYPE_NVLIST_ARRAY:
 148                 param = value;
 149                 fnvlist_add_nvlist_array(nvl, name,
 150                     param->array, param->nelem);
 151                 break;
 152         default:
 153                 krrp_verify(0);
 154         }
 155 
 156         return (0);
 157 }
 158 
 159 boolean_t
 160 krrp_param_exists(krrp_param_t p, nvlist_t *nvl)
 161 {
 162         return (nvlist_exists(nvl, krrp_param_get_name(p)));
 163 }
 164 
 165 static const char *
 166 krrp_param_get_name(krrp_param_t p)
 167 {
 168         if (p > KRRP_PARAM_UNKNOWN && p < krrp_params_sz)
 169                 return (krrp_params[p].name);
 170 
 171         krrp_verify(0);
 172 
 173         return (NULL);
 174 }
 175 
 176 static data_type_t
 177 krrp_param_get_dtype(krrp_param_t p)
 178 {
 179         if (p > KRRP_PARAM_UNKNOWN && p < krrp_params_sz)
 180                 return (krrp_params[p].dtype);
 181 
 182         krrp_verify(0);
 183 
 184         return (DATA_TYPE_UNKNOWN);
 185 }