66 #include <sys/instance.h>
67 #include <sys/modctl.h>
68 #include <sys/open.h>
69 #include <sys/stat.h>
70 #include <sys/sunddi.h>
71 #include <sys/sunndi.h>
72 #include <sys/systm.h>
73 #include <sys/mkdev.h>
74
75 /*
76 * Config information
77 */
78 static int pseudonex_intr_op(dev_info_t *dip, dev_info_t *rdip,
79 ddi_intr_op_t op, ddi_intr_handle_impl_t *hdlp, void *result);
80
81 static int pseudonex_attach(dev_info_t *, ddi_attach_cmd_t);
82 static int pseudonex_detach(dev_info_t *, ddi_detach_cmd_t);
83 static int pseudonex_open(dev_t *, int, int, cred_t *);
84 static int pseudonex_close(dev_t, int, int, cred_t *);
85 static int pseudonex_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
86 static int pseudonex_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *,
87 void *);
88
89 static void *pseudonex_state;
90
91 typedef struct pseudonex_state {
92 dev_info_t *pnx_devi;
93 } pseudonex_state_t;
94
95 static struct bus_ops pseudonex_bus_ops = {
96 BUSO_REV,
97 nullbusmap, /* bus_map */
98 NULL, /* bus_get_intrspec */
99 NULL, /* bus_add_intrspec */
100 NULL, /* bus_remove_intrspec */
101 i_ddi_map_fault, /* bus_map_fault */
102 ddi_no_dma_map, /* bus_dma_map */
103 ddi_no_dma_allochdl, /* bus_dma_allochdl */
104 NULL, /* bus_dma_freehdl */
105 NULL, /* bus_dma_bindhdl */
106 NULL, /* bus_dma_unbindhdl */
107 NULL, /* bus_dma_flush */
108 NULL, /* bus_dma_win */
109 NULL, /* bus_dma_ctl */
110 pseudonex_ctl, /* bus_ctl */
111 ddi_bus_prop_op, /* bus_prop_op */
112 0, /* bus_get_eventcookie */
113 0, /* bus_add_eventcall */
114 0, /* bus_remove_eventcall */
115 0, /* bus_post_event */
116 NULL, /* bus_intr_ctl */
117 NULL, /* bus_config */
118 NULL, /* bus_unconfig */
119 NULL, /* bus_fm_init */
120 NULL, /* bus_fm_fini */
121 NULL, /* bus_fm_access_enter */
122 NULL, /* bus_fm_access_exit */
123 NULL, /* bus_power */
124 pseudonex_intr_op /* bus_intr_op */
125 };
126
127 static struct cb_ops pseudonex_cb_ops = {
128 pseudonex_open, /* open */
129 pseudonex_close, /* close */
130 nodev, /* strategy */
131 nodev, /* print */
132 nodev, /* dump */
133 nodev, /* read */
134 nodev, /* write */
135 pseudonex_ioctl, /* ioctl */
136 nodev, /* devmap */
137 nodev, /* mmap */
138 nodev, /* segmap */
139 nochpoll, /* poll */
211 pseudonex_state_t *pnx_state;
212
213 switch (cmd) {
214 case DDI_ATTACH:
215 break;
216 case DDI_RESUME:
217 return (DDI_SUCCESS);
218 default:
219 return (DDI_FAILURE);
220 }
221
222 /*
223 * Save the devi for this instance in the soft_state data.
224 */
225 instance = ddi_get_instance(devi);
226 if (ddi_soft_state_zalloc(pseudonex_state, instance) != DDI_SUCCESS)
227 return (DDI_FAILURE);
228 pnx_state = ddi_get_soft_state(pseudonex_state, instance);
229 pnx_state->pnx_devi = devi;
230
231 if (ddi_create_minor_node(devi, "devctl", S_IFCHR, instance,
232 DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
233 ddi_remove_minor_node(devi, NULL);
234 ddi_soft_state_free(pseudonex_state, instance);
235 return (DDI_FAILURE);
236 }
237 ddi_report_dev(devi);
238 return (DDI_SUCCESS);
239 }
240
241 /*ARGSUSED*/
242 static int
243 pseudonex_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
244 {
245 int instance = ddi_get_instance(devi);
246
247 if (cmd == DDI_SUSPEND)
248 return (DDI_SUCCESS);
249
250 ddi_remove_minor_node(devi, NULL);
251 ddi_soft_state_free(pseudonex_state, instance);
252 return (DDI_SUCCESS);
253 }
254
255 /*ARGSUSED*/
256 static int
257 pseudonex_open(dev_t *devp, int flags, int otyp, cred_t *credp)
258 {
259 int instance;
260
261 if (otyp != OTYP_CHR)
262 return (EINVAL);
263
264 instance = getminor(*devp);
265 if (ddi_get_soft_state(pseudonex_state, instance) == NULL)
266 return (ENXIO);
267
268 return (0);
269 }
357 LOCK_DEV_OPS(dmp);
358 for (inst = 0; inst <= MAXMIN32; inst++) {
359 for (tdip = devnamesp[childmaj].dn_head; tdip != NULL;
360 tdip = ddi_get_next(tdip)) {
361 /* is this the current node? */
362 if (tdip == child)
363 continue;
364 if (inst == ddi_get_instance(tdip)) {
365 break;
366 }
367 }
368 if (tdip == NULL) {
369 UNLOCK_DEV_OPS(dmp);
370 return (inst);
371 }
372 }
373 UNLOCK_DEV_OPS(dmp);
374 return (-1);
375 }
376
377 static int
378 pseudonex_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
379 void *arg, void *result)
380 {
381 switch (ctlop) {
382 case DDI_CTLOPS_REPORTDEV:
383 if (rdip == NULL)
384 return (DDI_FAILURE);
385 cmn_err(CE_CONT, "?pseudo-device: %s%d\n",
386 ddi_driver_name(rdip), ddi_get_instance(rdip));
387 return (DDI_SUCCESS);
388
389 case DDI_CTLOPS_INITCHILD:
390 {
391 char name[12]; /* enough for a decimal integer */
392 int instance = -1;
393 dev_info_t *child = (dev_info_t *)arg;
394 const char *childname = ddi_driver_name(child);
395 char **childlist;
396 uint_t nelems;
|
66 #include <sys/instance.h>
67 #include <sys/modctl.h>
68 #include <sys/open.h>
69 #include <sys/stat.h>
70 #include <sys/sunddi.h>
71 #include <sys/sunndi.h>
72 #include <sys/systm.h>
73 #include <sys/mkdev.h>
74
75 /*
76 * Config information
77 */
78 static int pseudonex_intr_op(dev_info_t *dip, dev_info_t *rdip,
79 ddi_intr_op_t op, ddi_intr_handle_impl_t *hdlp, void *result);
80
81 static int pseudonex_attach(dev_info_t *, ddi_attach_cmd_t);
82 static int pseudonex_detach(dev_info_t *, ddi_detach_cmd_t);
83 static int pseudonex_open(dev_t *, int, int, cred_t *);
84 static int pseudonex_close(dev_t, int, int, cred_t *);
85 static int pseudonex_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
86 static int pseudonex_fm_init(dev_info_t *, dev_info_t *, int,
87 ddi_iblock_cookie_t *);
88 static int pseudonex_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *,
89 void *);
90
91 static void *pseudonex_state;
92
93 typedef struct pseudonex_state {
94 dev_info_t *pnx_devi;
95 int pnx_fmcap;
96 ddi_iblock_cookie_t pnx_fm_ibc;
97 } pseudonex_state_t;
98
99 static struct bus_ops pseudonex_bus_ops = {
100 BUSO_REV,
101 nullbusmap, /* bus_map */
102 NULL, /* bus_get_intrspec */
103 NULL, /* bus_add_intrspec */
104 NULL, /* bus_remove_intrspec */
105 i_ddi_map_fault, /* bus_map_fault */
106 ddi_no_dma_map, /* bus_dma_map */
107 ddi_no_dma_allochdl, /* bus_dma_allochdl */
108 NULL, /* bus_dma_freehdl */
109 NULL, /* bus_dma_bindhdl */
110 NULL, /* bus_dma_unbindhdl */
111 NULL, /* bus_dma_flush */
112 NULL, /* bus_dma_win */
113 NULL, /* bus_dma_ctl */
114 pseudonex_ctl, /* bus_ctl */
115 ddi_bus_prop_op, /* bus_prop_op */
116 0, /* bus_get_eventcookie */
117 0, /* bus_add_eventcall */
118 0, /* bus_remove_eventcall */
119 0, /* bus_post_event */
120 NULL, /* bus_intr_ctl */
121 NULL, /* bus_config */
122 NULL, /* bus_unconfig */
123 pseudonex_fm_init, /* bus_fm_init */
124 NULL, /* bus_fm_fini */
125 NULL, /* bus_fm_access_enter */
126 NULL, /* bus_fm_access_exit */
127 NULL, /* bus_power */
128 pseudonex_intr_op /* bus_intr_op */
129 };
130
131 static struct cb_ops pseudonex_cb_ops = {
132 pseudonex_open, /* open */
133 pseudonex_close, /* close */
134 nodev, /* strategy */
135 nodev, /* print */
136 nodev, /* dump */
137 nodev, /* read */
138 nodev, /* write */
139 pseudonex_ioctl, /* ioctl */
140 nodev, /* devmap */
141 nodev, /* mmap */
142 nodev, /* segmap */
143 nochpoll, /* poll */
215 pseudonex_state_t *pnx_state;
216
217 switch (cmd) {
218 case DDI_ATTACH:
219 break;
220 case DDI_RESUME:
221 return (DDI_SUCCESS);
222 default:
223 return (DDI_FAILURE);
224 }
225
226 /*
227 * Save the devi for this instance in the soft_state data.
228 */
229 instance = ddi_get_instance(devi);
230 if (ddi_soft_state_zalloc(pseudonex_state, instance) != DDI_SUCCESS)
231 return (DDI_FAILURE);
232 pnx_state = ddi_get_soft_state(pseudonex_state, instance);
233 pnx_state->pnx_devi = devi;
234
235 pnx_state->pnx_fmcap = DDI_FM_EREPORT_CAPABLE;
236 ddi_fm_init(devi, &pnx_state->pnx_fmcap, &pnx_state->pnx_fm_ibc);
237
238 if (ddi_create_minor_node(devi, "devctl", S_IFCHR, instance,
239 DDI_NT_NEXUS, 0) != DDI_SUCCESS) {
240 ddi_remove_minor_node(devi, NULL);
241 ddi_soft_state_free(pseudonex_state, instance);
242 return (DDI_FAILURE);
243 }
244 ddi_report_dev(devi);
245 return (DDI_SUCCESS);
246 }
247
248 /*ARGSUSED*/
249 static int
250 pseudonex_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
251 {
252 int instance = ddi_get_instance(devi);
253
254 if (cmd == DDI_SUSPEND)
255 return (DDI_SUCCESS);
256
257 if (cmd != DDI_DETACH)
258 return (DDI_FAILURE);
259
260 ddi_fm_fini(devi);
261 ddi_remove_minor_node(devi, NULL);
262 ddi_soft_state_free(pseudonex_state, instance);
263 return (DDI_SUCCESS);
264 }
265
266 /*ARGSUSED*/
267 static int
268 pseudonex_open(dev_t *devp, int flags, int otyp, cred_t *credp)
269 {
270 int instance;
271
272 if (otyp != OTYP_CHR)
273 return (EINVAL);
274
275 instance = getminor(*devp);
276 if (ddi_get_soft_state(pseudonex_state, instance) == NULL)
277 return (ENXIO);
278
279 return (0);
280 }
368 LOCK_DEV_OPS(dmp);
369 for (inst = 0; inst <= MAXMIN32; inst++) {
370 for (tdip = devnamesp[childmaj].dn_head; tdip != NULL;
371 tdip = ddi_get_next(tdip)) {
372 /* is this the current node? */
373 if (tdip == child)
374 continue;
375 if (inst == ddi_get_instance(tdip)) {
376 break;
377 }
378 }
379 if (tdip == NULL) {
380 UNLOCK_DEV_OPS(dmp);
381 return (inst);
382 }
383 }
384 UNLOCK_DEV_OPS(dmp);
385 return (-1);
386 }
387
388 /* ARGSUSED */
389 static int
390 pseudonex_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap,
391 ddi_iblock_cookie_t *ibc)
392 {
393 pseudonex_state_t *pnx_state;
394
395 pnx_state = ddi_get_soft_state(pseudonex_state, ddi_get_instance(dip));
396 ASSERT(pnx_state != NULL);
397 ASSERT(ibc != NULL);
398 *ibc = pnx_state->pnx_fm_ibc;
399 return (pnx_state->pnx_fmcap & cap);
400 }
401
402 static int
403 pseudonex_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop,
404 void *arg, void *result)
405 {
406 switch (ctlop) {
407 case DDI_CTLOPS_REPORTDEV:
408 if (rdip == NULL)
409 return (DDI_FAILURE);
410 cmn_err(CE_CONT, "?pseudo-device: %s%d\n",
411 ddi_driver_name(rdip), ddi_get_instance(rdip));
412 return (DDI_SUCCESS);
413
414 case DDI_CTLOPS_INITCHILD:
415 {
416 char name[12]; /* enough for a decimal integer */
417 int instance = -1;
418 dev_info_t *child = (dev_info_t *)arg;
419 const char *childname = ddi_driver_name(child);
420 char **childlist;
421 uint_t nelems;
|