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