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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * The driver portion of kmdb, which manages /dev/kmdb and passes requests along
29 * to the kmdb misc module (kmdbmod).
34 #include <sys/modctl.h>
36 #include <sys/sunddi.h>
40 #include <sys/policy.h>
41 #include <sys/kobj_impl.h>
43 #include <sys/sysmacros.h>
44 #include <sys/consdev.h>
46 #define KDRV_CFG_MAXLEN 2048
48 static dev_info_t
*kdrv_dip
;
52 kdrv_open(dev_t
*dev
, int openflags
, int otyp
, cred_t
*credp
)
57 if (secpolicy_kmdb(credp
) != 0)
65 kdrv_close(dev_t dev
, int openflags
, int otyp
, cred_t
*credp
)
70 typedef struct kdrv_flags_map
{
76 static const kdrv_flags_map_t kdrv_flags_map
[] = {
77 { "kmdb-auto-entry", 1, KMDB_F_AUTO_ENTRY
},
78 { "kmdb-trap-noswitch", 0, KMDB_F_TRAP_NOSWITCH
},
79 { "kmdb-driver-debug", 0, KMDB_F_DRV_DEBUG
},
84 kdrv_activate(intptr_t arg
)
93 if (cons_polledio
== NULL
) {
94 cmn_err(CE_NOTE
, "kmdb not supported: no console polled I/O");
99 memsz
= ddi_prop_get_int(DDI_DEV_T_ANY
, kdrv_dip
,
100 DDI_PROP_DONTPASS
, "kmdb-memseg-size", 0);
102 for (flags
= 0, i
= 0; kdrv_flags_map
[i
].fm_name
!= NULL
; i
++) {
103 const kdrv_flags_map_t
*fm
= &kdrv_flags_map
[i
];
104 if (ddi_prop_get_int(DDI_DEV_T_ANY
, kdrv_dip
, DDI_PROP_DONTPASS
,
105 (char *)fm
->fm_name
, fm
->fm_defval
))
106 flags
|= fm
->fm_flag
;
109 cfg
= kmem_alloc(KDRV_CFG_MAXLEN
, KM_SLEEP
);
111 if ((rc
= copyinstr((caddr_t
)arg
, cfg
, KDRV_CFG_MAXLEN
, &got
)) != 0) {
112 kmem_free(cfg
, KDRV_CFG_MAXLEN
);
113 return (rc
== ENAMETOOLONG
? E2BIG
: EFAULT
);
116 rc
= kctl_modload_activate(memsz
, cfg
, flags
);
118 kmem_free(cfg
, KDRV_CFG_MAXLEN
);
124 kdrv_deactivate(void)
126 return (kctl_deactivate());
131 kdrv_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int flags
, cred_t
*credp
,
136 return (kdrv_activate(arg
));
139 return (kdrv_deactivate());
148 kdrv_getinfo(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
, void **result
)
150 int error
= DDI_SUCCESS
;
153 case DDI_INFO_DEVT2DEVINFO
:
156 case DDI_INFO_DEVT2INSTANCE
:
157 *result
= (void *)(uintptr_t)getminor((dev_t
)arg
);
168 kdrv_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
170 if (cmd
!= DDI_ATTACH
)
171 return (DDI_FAILURE
);
173 if (ddi_create_minor_node(dip
, ddi_get_name(dip
), S_IFCHR
,
174 ddi_get_instance(dip
), DDI_PSEUDO
, 0) != DDI_SUCCESS
)
175 return (DDI_FAILURE
);
179 if (kctl_attach(dip
) != 0)
180 return (DDI_FAILURE
);
182 return (DDI_SUCCESS
);
186 kdrv_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
188 if (cmd
!= DDI_DETACH
)
189 return (DDI_FAILURE
);
191 if (kctl_detach() == EBUSY
)
192 return (DDI_FAILURE
);
194 ddi_remove_minor_node(dip
, NULL
);
196 return (DDI_SUCCESS
);
199 static struct cb_ops kdrv_cb_ops
= {
202 nodev
, /* not a block driver */
203 nodev
, /* no print routine */
204 nodev
, /* no dump routine */
205 nodev
, /* no read routine */
206 nodev
, /* no write routine */
208 nodev
, /* no devmap routine */
209 nodev
, /* no mmap routine */
210 nodev
, /* no segmap routine */
211 nochpoll
, /* no chpoll routine */
213 0, /* not a STREAMS driver */
214 D_NEW
| D_MP
, /* safe for multi-thread/multi-processor */
217 static struct dev_ops kdrv_ops
= {
218 DEVO_REV
, /* devo_rev */
220 kdrv_getinfo
, /* devo_getinfo */
221 nulldev
, /* devo_identify */
222 nulldev
, /* devo_probe */
223 kdrv_attach
, /* devo_attach */
224 kdrv_detach
, /* devo_detach */
225 nodev
, /* devo_reset */
226 &kdrv_cb_ops
, /* devo_cb_ops */
227 (struct bus_ops
*)0, /* devo_bus_ops */
228 NULL
, /* devo_power */
229 ddi_quiesce_not_needed
, /* devo_quiesce */
232 static struct modldrv modldrv
= {
238 static struct modlinkage modlinkage
= {
247 return (mod_install(&modlinkage
));
251 _info(struct modinfo
*modinfop
)
253 return (mod_info(&modlinkage
, modinfop
));
259 return (mod_remove(&modlinkage
));