1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Copyright 2019 Peter Tribble.
28 * Copyright 2023 Oxide Computer Company
29 */
30
31 /*
32 * Safari Configurator (gptwocfg)
33 */
34
35 #include <sys/types.h>
36 #include <sys/cred.h>
37 #include <sys/mman.h>
38 #include <sys/kmem.h>
39 #include <sys/conf.h>
40 #include <sys/cmn_err.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/sunndi.h>
44 #include <sys/modctl.h>
45 #include <sys/stat.h>
46 #include <sys/param.h>
47 #include <sys/autoconf.h>
48 #include <sys/ksynch.h>
49 #include <sys/promif.h>
50 #include <sys/ndi_impldefs.h>
51 #include <sys/ddi_impldefs.h>
52 #include <sys/gp2cfg.h>
53 #include <sys/machsystm.h>
54 #include <sys/platform_module.h>
55
56 #ifdef DEBUG
57 int gptwocfg_debug = 0;
58
59 static void debug(char *, uintptr_t, uintptr_t,
60 uintptr_t, uintptr_t, uintptr_t);
61
62 #define GPTWO_DEBUG0(level, flag, s) if (gptwocfg_debug >= level) \
63 cmn_err(flag, s)
64 #define GPTWO_DEBUG1(level, flag, fmt, a1) if (gptwocfg_debug >= level) \
65 debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
66 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) if (gptwocfg_debug >= level) \
67 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
68 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) \
69 if (gptwocfg_debug >= level) \
70 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0);
71 #else
72 #define GPTWO_DEBUG0(level, flag, s)
73 #define GPTWO_DEBUG1(level, flag, fmt, a1)
74 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2)
75 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3)
76 #endif
77
78 kmutex_t gptwo_handle_list_lock;
79 gptwocfg_handle_list_t *gptwocfg_handle_list;
80
81 static kmutex_t gptwo_config_list_lock;
82 static gptwocfg_config_t *gptwo_config_list;
83
84 static gptwo_new_nodes_t *
85 gptwocfg_get_obp_created_nodes(dev_info_t *, uint_t);
86
87 void (*gptwocfg_unclaim_address)(uint_t);
88
89 extern caddr_t efcode_vaddr;
90 extern int efcode_size;
91
92 #define GPTWO_NUMBER_OF_DEVICE_TYPES 6
93
94 static kmutex_t gptwocfg_ops_table_lock;
95 gptwocfg_ops_t *gptwocfg_ops_table[GPTWO_NUMBER_OF_DEVICE_TYPES];
96
97 /*
98 * Module linkage information for the kernel.
99 */
100
101 extern struct mod_ops mod_miscops;
102
103 static struct modlmisc modlmisc = {
104 &mod_miscops, /* Type of module */
105 "gptwo configurator",
106 };
107
108 static struct modlinkage modlinkage = {
109 MODREV_1, (void *)&modlmisc, NULL
110 };
111
112 int
_init(void)113 _init(void)
114 {
115 unsigned int i;
116
117 GPTWO_DEBUG0(1, CE_WARN, "gptwocfg (Safari Configurator) "
118 "has been loaded\n");
119
120 mutex_init(&gptwo_config_list_lock, NULL, MUTEX_DRIVER, NULL);
121 mutex_init(&gptwocfg_ops_table_lock, NULL, MUTEX_DRIVER, NULL);
122 gptwo_config_list = NULL;
123
124 mutex_init(&gptwo_handle_list_lock, NULL, MUTEX_DRIVER, NULL);
125 gptwocfg_handle_list = NULL;
126
127 for (i = 0; i < GPTWO_NUMBER_OF_DEVICE_TYPES; i++)
128 gptwocfg_ops_table[i] = NULL;
129
130 return (mod_install(&modlinkage));
131 }
132
133 int
_fini(void)134 _fini(void)
135 {
136 int error;
137
138 error = mod_remove(&modlinkage);
139 if (error != 0) {
140 return (error);
141 }
142 mutex_destroy(&gptwo_config_list_lock);
143 mutex_destroy(&gptwocfg_ops_table_lock);
144 mutex_destroy(&gptwo_handle_list_lock);
145
146 return (0);
147 }
148
149 int
_info(struct modinfo * modinfop)150 _info(struct modinfo *modinfop)
151 {
152 return (mod_info(&modlinkage, modinfop));
153 }
154
155 gptwo_new_nodes_t *
gptwocfg_allocate_node_list(int number_of_nodes)156 gptwocfg_allocate_node_list(int number_of_nodes)
157 {
158 gptwo_new_nodes_t *gptwo_new_nodes;
159 int size;
160
161 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_allocate_node_list- %d nodes",
162 number_of_nodes);
163
164 size = sizeof (gptwo_new_nodes_t) +
165 ((number_of_nodes -1) * sizeof (dev_info_t *));
166
167 gptwo_new_nodes = kmem_zalloc(size, KM_SLEEP);
168
169 gptwo_new_nodes->gptwo_number_of_nodes = number_of_nodes;
170 gptwo_new_nodes->gptwo_version = GP2_VERSION;
171
172 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_allocate_node_list- returned %p\n",
173 gptwo_new_nodes);
174
175 return (gptwo_new_nodes);
176 }
177
178 void
gptwocfg_free_node_list(gptwo_new_nodes_t * gptwo_new_nodes)179 gptwocfg_free_node_list(gptwo_new_nodes_t *gptwo_new_nodes)
180 {
181 int size;
182
183 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_free_node_list- %p %d nodes",
184 gptwo_new_nodes, gptwo_new_nodes->gptwo_number_of_nodes);
185
186 size = sizeof (gptwo_new_nodes_t) +
187 ((gptwo_new_nodes->gptwo_number_of_nodes - 1) *
188 sizeof (dev_info_t *));
189
190 kmem_free(gptwo_new_nodes, size);
191 }
192
193 void
gptwocfg_register_ops(uint_t type,gptwo_cfgfunc_t * cfg_func,gptwo_uncfgfunc_t * uncfg_func)194 gptwocfg_register_ops(uint_t type, gptwo_cfgfunc_t *cfg_func,
195 gptwo_uncfgfunc_t *uncfg_func)
196 {
197 /* KM_SLEEP guarantees success */
198 gptwocfg_ops_t *ops = kmem_zalloc(sizeof (gptwocfg_ops_t), KM_SLEEP);
199
200 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_register_ops: type=%x ops=%lx\n",
201 type, ops);
202 ASSERT(type < GPTWO_NUMBER_OF_DEVICE_TYPES);
203 ops->gptwocfg_type = type;
204 ops->gptwocfg_version = GPTWOCFG_OPS_VERSION;
205 ops->gptwocfg_configure = cfg_func;
206 ops->gptwocfg_unconfigure = uncfg_func;
207
208 mutex_enter(&gptwocfg_ops_table_lock);
209 gptwocfg_ops_table[type] = ops;
210 mutex_exit(&gptwocfg_ops_table_lock);
211 }
212
213
214
215 void
gptwocfg_unregister_ops(uint_t type)216 gptwocfg_unregister_ops(uint_t type)
217 {
218 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unregister_ops: type=%x\n", type);
219
220 ASSERT(type < GPTWO_NUMBER_OF_DEVICE_TYPES);
221
222 mutex_enter(&gptwocfg_ops_table_lock);
223 kmem_free(gptwocfg_ops_table[type], sizeof (gptwocfg_ops_t));
224 gptwocfg_ops_table[type] = NULL;
225 mutex_exit(&gptwocfg_ops_table_lock);
226 }
227
228 gptwocfg_cookie_t
gptwocfg_configure(dev_info_t * ap,spcd_t * pcd,gptwo_aid_t id)229 gptwocfg_configure(dev_info_t *ap, spcd_t *pcd, gptwo_aid_t id)
230 {
231 gptwo_new_nodes_t *new_nodes = NULL;
232 gptwocfg_config_t *config;
233 gptwocfg_ops_t *ops;
234
235 GPTWO_DEBUG3(1, CE_CONT, "gptwocfg_configure: ap=0x%p pcd=%p id=%x\n",
236 ap, pcd, id);
237
238 /*
239 * Look to see if the port is already configured.
240 */
241 mutex_enter(&gptwo_config_list_lock);
242 config = gptwo_config_list;
243 while (config != NULL) {
244 if (config->gptwo_portid == id) {
245 cmn_err(CE_WARN, "gptwocfg: gptwocfg_configure: "
246 "0x%x Port already configured\n", id);
247 mutex_exit(&gptwo_config_list_lock);
248 return (NULL);
249 }
250 config = config->gptwo_next;
251 }
252 mutex_exit(&gptwo_config_list_lock);
253
254 if (pcd == NULL) {
255 GPTWO_DEBUG0(1, CE_CONT, "gptwocfg_configure: pcd=NULL\n");
256 return (NULL);
257 }
258
259 if ((pcd->spcd_magic != PCD_MAGIC) ||
260 (pcd->spcd_version != PCD_VERSION)) {
261 cmn_err(CE_WARN, "gptwocfg: Invalid Port "
262 "Configuration Descriptor\n");
263 return (NULL);
264 }
265
266 if (pcd->spcd_ptype >= GPTWO_NUMBER_OF_DEVICE_TYPES) {
267 cmn_err(CE_WARN,
268 "gptwocfg: Invalid device type %x", pcd->spcd_ptype);
269 return (NULL);
270 }
271
272 if (pcd->spcd_prsv != SPCD_RSV_PASS) {
273 cmn_err(CE_WARN,
274 "gptwocfg: Agent at ID %x has not passed test(s)\n", id);
275 return (NULL);
276 }
277
278 mutex_enter(&gptwocfg_ops_table_lock);
279
280 ops = gptwocfg_ops_table[pcd->spcd_ptype];
281
282 if (ops == NULL) {
283 cmn_err(CE_WARN, "gptwocfg: Ops for type %x have not been "
284 "registered\n", pcd->spcd_ptype);
285 mutex_exit(&gptwocfg_ops_table_lock);
286 return (NULL);
287 }
288
289 if (ops->gptwocfg_configure == NULL) {
290 cmn_err(CE_WARN, "gptwocfg: no configure routine registered "
291 "for sfaari type %x\n", pcd->spcd_ptype);
292 mutex_exit(&gptwocfg_ops_table_lock);
293 return (NULL);
294 }
295
296 new_nodes = ops->gptwocfg_configure(ap, pcd, id);
297
298 mutex_exit(&gptwocfg_ops_table_lock);
299
300 if (new_nodes != NULL) {
301 config = kmem_zalloc(sizeof (gptwocfg_config_t), KM_SLEEP);
302 config->gptwo_version = GP2_VERSION;
303 config->gptwo_ap = ap;
304 config->gptwo_portid = id;
305 config->gptwo_nodes = new_nodes;
306 config->gptwo_ops = ops;
307
308 /*
309 * put config on config list
310 */
311 mutex_enter(&gptwo_config_list_lock);
312 config->gptwo_next = gptwo_config_list;
313 gptwo_config_list = config;
314 mutex_exit(&gptwo_config_list_lock);
315 } else {
316 config = NULL;
317 }
318
319 return ((gptwocfg_cookie_t)config);
320 }
321
322 gptwocfg_cookie_t
gptwocfg_unconfigure(dev_info_t * ap,gptwo_aid_t id)323 gptwocfg_unconfigure(dev_info_t *ap, gptwo_aid_t id)
324 {
325 int i;
326 int failure = 0;
327 dev_info_t *saf_dip;
328 gptwocfg_config_t *config, *temp;
329 gptwo_new_nodes_t *obp_nodes;
330 gptwocfg_ops_t *ops;
331
332 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_unconfigure: ap=0x%p id=0x%lx\n",
333 ap, id);
334
335 mutex_enter(&gptwo_config_list_lock);
336 config = gptwo_config_list;
337 while (config != NULL) {
338 if (config->gptwo_portid == id) {
339 break;
340 }
341 config = config->gptwo_next;
342 }
343 mutex_exit(&gptwo_config_list_lock);
344
345 if (config == NULL) {
346 /*
347 * There is no config structure associated with this agent id
348 * so it was probably built by firmware at start of day. We
349 * need to create a config structure before we can continue.
350 */
351 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure: id=0x%lx "
352 "No config structure - Need to build one\n", id);
353
354 obp_nodes = gptwocfg_get_obp_created_nodes(ap, id);
355
356 if (obp_nodes != NULL) {
357 config = kmem_zalloc(sizeof (gptwocfg_config_t),
358 KM_SLEEP);
359 config->gptwo_version = GP2_VERSION;
360 config->gptwo_ap = ap;
361 config->gptwo_portid = id;
362 config->gptwo_nodes = obp_nodes;
363
364 /*
365 * put config on config list
366 */
367 mutex_enter(&gptwo_config_list_lock);
368 config->gptwo_next = gptwo_config_list;
369 gptwo_config_list = config;
370 mutex_exit(&gptwo_config_list_lock);
371 } else {
372 cmn_err(CE_WARN, "gptwocfg: gptwocfg_unconfigure: "
373 "No OBP created nodes for ap=0x%lx agent id=0x%x",
374 (long)ap, id);
375 return (NULL);
376 }
377 }
378
379 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure config=0x%lx\n",
380 config);
381
382 ops = config->gptwo_ops;
383
384 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure: ops=%lx\n", ops);
385
386 ndi_devi_enter(ap);
387
388 for (i = 0; i < config->gptwo_nodes->gptwo_number_of_nodes; i++) {
389 dev_info_t *fdip = NULL;
390
391 saf_dip = config->gptwo_nodes->gptwo_nodes[i];
392
393 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure saf_dip=0x%lx\n",
394 saf_dip);
395
396 if (saf_dip == NULL) {
397 GPTWO_DEBUG0(1, CE_CONT, "gptwocfg_unconfigure: "
398 "skipping NULLL saf device\n");
399
400 continue;
401 }
402
403 config->gptwo_nodes->gptwo_nodes[i] = NULL;
404
405 if (ops) {
406 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_configure "
407 "ops->gptwocfg_configure=%lx\n",
408 ops->gptwocfg_configure);
409
410 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_unconfigure "
411 "ops->gptwocfg_unconfigure=%lx\n",
412 ops->gptwocfg_unconfigure);
413
414 if (ops->gptwocfg_unconfigure != NULL) {
415 config->gptwo_nodes->gptwo_nodes[i] =
416 ops->gptwocfg_unconfigure(saf_dip);
417
418 }
419 }
420
421 GPTWO_DEBUG1(1, CE_CONT, "e_ddi_branch_destroy <%s>\n",
422 ddi_get_name(saf_dip));
423
424 ASSERT(e_ddi_branch_held(saf_dip));
425
426 /*
427 * Don't hold parent busy when calling
428 * e_ddi_branch_unconfigure/destroy/referenced()
429 */
430 ndi_devi_exit(ap);
431 if (e_ddi_branch_destroy(saf_dip, &fdip, 0)) {
432 char *path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
433
434 /*
435 * If non-NULL, fdip is held and must be released.
436 */
437 if (fdip != NULL) {
438 (void) ddi_pathname(fdip, path);
439 ddi_release_devi(fdip);
440 } else {
441 (void) ddi_pathname(saf_dip, path);
442 }
443
444 cmn_err(CE_WARN, "saf node removal failed: %s (%p)",
445 path, fdip ? (void *)fdip : (void *)saf_dip);
446
447 kmem_free(path, MAXPATHLEN);
448
449 config->gptwo_nodes->gptwo_nodes[i] = saf_dip;
450 failure = 1;
451 }
452 ndi_devi_enter(ap);
453 }
454
455 ndi_devi_exit(ap);
456
457 if (!failure) {
458 gptwocfg_free_node_list(config->gptwo_nodes);
459
460 mutex_enter(&gptwo_config_list_lock);
461 if (gptwo_config_list == config) {
462 gptwo_config_list = config->gptwo_next;
463 } else {
464 temp = gptwo_config_list;
465 while (temp->gptwo_next != config) {
466 temp = temp->gptwo_next;
467 }
468 temp->gptwo_next = config->gptwo_next;
469 }
470 mutex_exit(&gptwo_config_list_lock);
471
472 kmem_free(config, sizeof (gptwocfg_config_t));
473 config = NULL;
474 }
475
476 return (config);
477 }
478
479 int
gptwocfg_next_node(gptwocfg_cookie_t c,dev_info_t * previous,dev_info_t ** next)480 gptwocfg_next_node(gptwocfg_cookie_t c, dev_info_t *previous, dev_info_t **next)
481 {
482 gptwocfg_config_t *cookie;
483 int i, j;
484
485 GPTWO_DEBUG3(1, CE_WARN, "gptwocfg_next_node"
486 "(c=0x%lx, previous=0x%lx, next=0x%lx)\n", c, previous, next);
487
488 cookie = (gptwocfg_config_t *)c;
489
490 for (i = 0; i < cookie->gptwo_nodes->gptwo_number_of_nodes; i++) {
491 GPTWO_DEBUG1(1, CE_WARN, "0x%lx\n",
492 cookie->gptwo_nodes->gptwo_nodes[i]);
493 }
494
495 if (previous == NULL) {
496 for (i = 0; i < cookie->gptwo_nodes->gptwo_number_of_nodes;
497 i++) {
498 if (cookie->gptwo_nodes->gptwo_nodes[i]) {
499 *next = cookie->gptwo_nodes->gptwo_nodes[i];
500 GPTWO_DEBUG1(1, CE_WARN, "returned 0x%lx\n",
501 *next);
502 return (1);
503 }
504 }
505 return (0);
506 }
507
508 for (i = 0; i < cookie->gptwo_nodes->gptwo_number_of_nodes; i++) {
509 if (cookie->gptwo_nodes->gptwo_nodes[i] == previous) {
510 for (j = i + 1;
511 j < cookie->gptwo_nodes->gptwo_number_of_nodes;
512 j++) {
513 if (cookie->gptwo_nodes->gptwo_nodes[j]) {
514 *next =
515 cookie->gptwo_nodes->gptwo_nodes[j];
516 GPTWO_DEBUG1(1, CE_WARN,
517 "returned 0x%lx\n", *next);
518 return (1);
519 }
520 }
521 *next = NULL;
522 GPTWO_DEBUG1(1, CE_WARN, "returned 0x%lx\n",
523 *next);
524 return (1);
525 }
526 }
527
528 /*
529 * previous is probably an invalid dev_info.
530 */
531 return (0);
532 }
533
534 static gptwo_new_nodes_t *
gptwocfg_get_obp_created_nodes(dev_info_t * ap,uint_t id)535 gptwocfg_get_obp_created_nodes(dev_info_t *ap, uint_t id)
536 {
537 gptwo_new_nodes_t *obp_nodes;
538 dev_info_t *saf_dev;
539 int i = 0, nodes = 0;
540
541 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_get_obp_created_nodes - ap=0x%lx "
542 "id=0x%x\n", ap, id);
543
544 ndi_devi_enter(ap);
545
546 /*
547 * First go through all the children of the attachment point
548 * to count matching safari agent ids
549 */
550 saf_dev = ddi_get_child(ap);
551 while (saf_dev != NULL) {
552 if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, DDI_PROP_DONTPASS,
553 "portid", -1) == id) {
554 nodes++;
555 }
556 saf_dev = ddi_get_next_sibling(saf_dev);
557 }
558
559 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_get_obp_created_nodes - %d nodes "
560 "found\n", nodes);
561
562 obp_nodes = gptwocfg_allocate_node_list(nodes);
563
564 /*
565 * Then fill in the nodes structure.
566 */
567 saf_dev = ddi_get_child(ap);
568 while ((saf_dev != NULL) && (i < nodes)) {
569 if (ddi_getprop(DDI_DEV_T_ANY, saf_dev, DDI_PROP_DONTPASS,
570 "portid", -1) == id) {
571 /*
572 * Branch rooted at this dip must have been
573 * held by the DR driver.
574 */
575 ASSERT(e_ddi_branch_held(saf_dev));
576 obp_nodes->gptwo_nodes[i++] = saf_dev;
577 }
578 saf_dev = ddi_get_next_sibling(saf_dev);
579 }
580
581 ndi_devi_exit(ap);
582
583 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_get_obp_created_nodes - "
584 "Returning 0x%lx\n", obp_nodes);
585
586 return (obp_nodes);
587 }
588
589 void
gptwocfg_save_handle(dev_info_t * dip,fco_handle_t fco_handle)590 gptwocfg_save_handle(dev_info_t *dip, fco_handle_t fco_handle)
591 {
592 gptwocfg_handle_list_t *h;
593
594 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_save_handle - "
595 "dip=%lx fco_handle=%lx\n", dip, fco_handle);
596
597 h = kmem_zalloc(sizeof (gptwocfg_handle_list_t), KM_SLEEP);
598
599 mutex_enter(&gptwo_handle_list_lock);
600
601 h->next = gptwocfg_handle_list;
602 h->dip = dip;
603 h->fco_handle = fco_handle;
604 gptwocfg_handle_list = h;
605
606 mutex_exit(&gptwo_handle_list_lock);
607 }
608
609 fco_handle_t
gptwocfg_get_handle(dev_info_t * dip)610 gptwocfg_get_handle(dev_info_t *dip)
611 {
612 gptwocfg_handle_list_t *h, *last;
613 fco_handle_t fco_handle;
614
615 mutex_enter(&gptwo_handle_list_lock);
616
617 h = last = gptwocfg_handle_list;
618
619 while (h != NULL) {
620 if (h->dip == dip) {
621 if (h == gptwocfg_handle_list)
622 gptwocfg_handle_list = h->next;
623 else
624 last->next = h->next;
625
626 mutex_exit(&gptwo_handle_list_lock);
627
628 fco_handle = h->fco_handle;
629
630 kmem_free(h, sizeof (gptwocfg_handle_list_t));
631
632 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_get_handle - "
633 "dip=%lx fco_handle=%lx\n", dip, fco_handle);
634
635 return (fco_handle);
636 }
637 last = h;
638 h = h->next;
639 }
640
641 mutex_exit(&gptwo_handle_list_lock);
642
643 GPTWO_DEBUG1(1, CE_CONT, "gptwocfg_get_handle - dip=%lx NO HANDLE\n",
644 dip);
645
646 return (0);
647 }
648
649 void
gptwocfg_devi_attach_to_parent(dev_info_t * dip)650 gptwocfg_devi_attach_to_parent(dev_info_t *dip)
651 {
652 (void) i_ndi_config_node(dip, DS_LINKED, 0);
653 }
654
655 #ifdef DEBUG
656 static void
debug(char * fmt,uintptr_t a1,uintptr_t a2,uintptr_t a3,uintptr_t a4,uintptr_t a5)657 debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
658 uintptr_t a4, uintptr_t a5)
659 {
660 cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
661 }
662 #endif
663