1219089Spjd/*- 2219089Spjd * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org> 3219089Spjd * All rights reserved. 4219089Spjd * 5219089Spjd * Redistribution and use in source and binary forms, with or without 6219089Spjd * modification, are permitted provided that the following conditions 7219089Spjd * are met: 8219089Spjd * 1. Redistributions of source code must retain the above copyright 9219089Spjd * notice, this list of conditions and the following disclaimer. 10219089Spjd * 2. Redistributions in binary form must reproduce the above copyright 11219089Spjd * notice, this list of conditions and the following disclaimer in the 12219089Spjd * documentation and/or other materials provided with the distribution. 13219089Spjd * 14219089Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 15219089Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16219089Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17219089Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 18219089Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19219089Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20219089Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21219089Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22219089Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23219089Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24219089Spjd * SUCH DAMAGE. 25219089Spjd */ 26219089Spjd 27219089Spjd#include <sys/cdefs.h> 28219089Spjd__FBSDID("$FreeBSD: stable/10/sys/cddl/compat/opensolaris/kern/opensolaris_sunddi.c 324745 2017-10-19 07:21:45Z avg $"); 29219089Spjd 30219089Spjd#include <sys/param.h> 31219089Spjd#include <sys/jail.h> 32219089Spjd#include <sys/kernel.h> 33219089Spjd#include <sys/libkern.h> 34219089Spjd#include <sys/limits.h> 35219089Spjd#include <sys/misc.h> 36219089Spjd#include <sys/sunddi.h> 37219089Spjd#include <sys/sysctl.h> 38219089Spjd 39219089Spjdint 40219089Spjdddi_strtol(const char *str, char **nptr, int base, long *result) 41219089Spjd{ 42219089Spjd 43219089Spjd *result = strtol(str, nptr, base); 44219089Spjd return (0); 45219089Spjd} 46219089Spjd 47219089Spjdint 48219089Spjdddi_strtoul(const char *str, char **nptr, int base, unsigned long *result) 49219089Spjd{ 50219089Spjd 51219089Spjd if (str == hw_serial) { 52219089Spjd *result = prison0.pr_hostid; 53219089Spjd return (0); 54219089Spjd } 55219089Spjd 56219089Spjd *result = strtoul(str, nptr, base); 57219089Spjd return (0); 58219089Spjd} 59219089Spjd 60219089Spjdint 61219089Spjdddi_strtoull(const char *str, char **nptr, int base, unsigned long long *result) 62219089Spjd{ 63219089Spjd 64219089Spjd *result = (unsigned long long)strtouq(str, nptr, base); 65219089Spjd return (0); 66219089Spjd} 67219089Spjd 68219089Spjdstruct ddi_soft_state_item { 69219089Spjd int ssi_item; 70219089Spjd void *ssi_data; 71219089Spjd LIST_ENTRY(ddi_soft_state_item) ssi_next; 72219089Spjd}; 73219089Spjd 74219089Spjdstruct ddi_soft_state { 75219089Spjd size_t ss_size; 76219089Spjd kmutex_t ss_lock; 77219089Spjd LIST_HEAD(, ddi_soft_state_item) ss_list; 78219089Spjd}; 79219089Spjd 80219089Spjdstatic void * 81219089Spjdddi_get_soft_state_locked(struct ddi_soft_state *ss, int item) 82219089Spjd{ 83219089Spjd struct ddi_soft_state_item *itemp; 84219089Spjd 85219092Spjd ASSERT(MUTEX_HELD(&ss->ss_lock)); 86219089Spjd 87219089Spjd LIST_FOREACH(itemp, &ss->ss_list, ssi_next) { 88219089Spjd if (itemp->ssi_item == item) 89219089Spjd return (itemp->ssi_data); 90219089Spjd } 91219089Spjd return (NULL); 92219089Spjd} 93219089Spjd 94219089Spjdvoid * 95219089Spjdddi_get_soft_state(void *state, int item) 96219089Spjd{ 97219089Spjd struct ddi_soft_state *ss = state; 98219089Spjd void *data; 99219089Spjd 100219089Spjd mutex_enter(&ss->ss_lock); 101219089Spjd data = ddi_get_soft_state_locked(ss, item); 102219089Spjd mutex_exit(&ss->ss_lock); 103219089Spjd return (data); 104219089Spjd} 105219089Spjd 106219089Spjdint 107219089Spjdddi_soft_state_zalloc(void *state, int item) 108219089Spjd{ 109219089Spjd struct ddi_soft_state *ss = state; 110219089Spjd struct ddi_soft_state_item *itemp; 111219089Spjd 112219089Spjd itemp = kmem_alloc(sizeof(*itemp), KM_SLEEP); 113219089Spjd itemp->ssi_item = item; 114219089Spjd itemp->ssi_data = kmem_zalloc(ss->ss_size, KM_SLEEP); 115219089Spjd 116219089Spjd mutex_enter(&ss->ss_lock); 117219089Spjd if (ddi_get_soft_state_locked(ss, item) != NULL) { 118219089Spjd mutex_exit(&ss->ss_lock); 119219089Spjd kmem_free(itemp->ssi_data, ss->ss_size); 120219089Spjd kmem_free(itemp, sizeof(*itemp)); 121219089Spjd return (DDI_FAILURE); 122219089Spjd } 123219089Spjd LIST_INSERT_HEAD(&ss->ss_list, itemp, ssi_next); 124219089Spjd mutex_exit(&ss->ss_lock); 125219089Spjd return (DDI_SUCCESS); 126219089Spjd} 127219089Spjd 128219089Spjdstatic void 129219089Spjdddi_soft_state_free_locked(struct ddi_soft_state *ss, int item) 130219089Spjd{ 131219089Spjd struct ddi_soft_state_item *itemp; 132219089Spjd 133219092Spjd ASSERT(MUTEX_HELD(&ss->ss_lock)); 134219089Spjd 135219089Spjd LIST_FOREACH(itemp, &ss->ss_list, ssi_next) { 136219089Spjd if (itemp->ssi_item == item) 137219089Spjd break; 138219089Spjd } 139219089Spjd if (itemp != NULL) { 140219089Spjd LIST_REMOVE(itemp, ssi_next); 141219089Spjd kmem_free(itemp->ssi_data, ss->ss_size); 142219089Spjd kmem_free(itemp, sizeof(*itemp)); 143219089Spjd } 144219089Spjd} 145219089Spjd 146219089Spjdvoid 147219089Spjdddi_soft_state_free(void *state, int item) 148219089Spjd{ 149219089Spjd struct ddi_soft_state *ss = state; 150219089Spjd 151219089Spjd mutex_enter(&ss->ss_lock); 152219089Spjd ddi_soft_state_free_locked(ss, item); 153219089Spjd mutex_exit(&ss->ss_lock); 154219089Spjd} 155219089Spjd 156219089Spjdint 157219089Spjdddi_soft_state_init(void **statep, size_t size, size_t nitems __unused) 158219089Spjd{ 159219089Spjd struct ddi_soft_state *ss; 160219089Spjd 161219089Spjd ss = kmem_alloc(sizeof(*ss), KM_SLEEP); 162219089Spjd mutex_init(&ss->ss_lock, NULL, MUTEX_DEFAULT, NULL); 163219089Spjd ss->ss_size = size; 164219089Spjd LIST_INIT(&ss->ss_list); 165219089Spjd *statep = ss; 166219089Spjd return (0); 167219089Spjd} 168219089Spjd 169219089Spjdvoid 170219089Spjdddi_soft_state_fini(void **statep) 171219089Spjd{ 172219089Spjd struct ddi_soft_state *ss = *statep; 173219089Spjd struct ddi_soft_state_item *itemp; 174219089Spjd int item; 175219089Spjd 176219089Spjd mutex_enter(&ss->ss_lock); 177219089Spjd while ((itemp = LIST_FIRST(&ss->ss_list)) != NULL) { 178219089Spjd item = itemp->ssi_item; 179219089Spjd ddi_soft_state_free_locked(ss, item); 180219089Spjd } 181219089Spjd mutex_exit(&ss->ss_lock); 182219089Spjd mutex_destroy(&ss->ss_lock); 183219089Spjd kmem_free(ss, sizeof(*ss)); 184219089Spjd 185219089Spjd *statep = NULL; 186219089Spjd} 187