dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / mdb / common / modules / usba / usb.c
blobc085fe031d696020cc9c794dacd07ef2c7f1a90e
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2016 Joyent, Inc.
28 #include <stddef.h>
29 #include <sys/mdb_modapi.h>
30 #include <mdb/mdb_ks.h>
32 #include <sys/usb/usba.h>
33 #include <sys/ddi_impldefs.h>
34 #include <sys/usb/usba/usba_types.h>
35 #include <sys/usb/usba/usba_impl.h>
36 #include <sys/usb/usba/hcdi_impl.h>
37 #include <sys/usb/hubd/hub.h>
38 #include <sys/usb/hubd/hubdvar.h>
39 #include <sys/file.h>
40 #include <sys/sunndi.h>
41 #include <unistd.h>
45 * Prototypes
47 /* usba.c */
48 extern uintptr_t mdb_usba_get_usba_device(uintptr_t);
49 extern uintptr_t mdb_usba_hcdi_get_hcdi(struct dev_info *);
52 * Defines
54 /* dcmd options */
55 #define USB_DUMP_VERBOSE 0x01
56 #define USB_DUMP_ACTIVE_PIPES 0x02
58 /* Hardcoded slop factor designed into debug buf logic */
59 #define USB_DEBUG_SIZE_EXTRA_ALLOC 8
63 * Callback arg struct for find_dip (callback func used in usba_device2devinfo).
65 typedef struct usba_device2devinfo_data {
66 uintptr_t u2d_target_usb_dev_p; /* one we're looking for */
67 uintptr_t *u2d_dip_addr; /* Where to store result */
68 boolean_t u2d_found; /* Match found */
69 } usba_device2devinfo_cbdata_t;
73 * Callback for usba_device2dip.
74 * Callback called from the devinfo_children walk invoked in usba_device2dip.
76 * For the current dip, get the (potential) pointer to its usba_device_t
77 * struct.
78 * See if this pointer matches the address of the usba_device_t we're looking
79 * for (passed in as usb_dev_p). If so, stuff its value in u2d_dip_addr,
80 * and terminate the walk.
82 * - dip_addr is the address in core of the dip currently being processed by the
83 * walk
84 * - local_dip is a pointer to a copy of the struct dev_info in local memory
85 * - cb_data is the addr of the callback arg the walker was invoked with
86 * (passed through transparently from walk invoker).
88 * Returns:
89 * - WALK_NEXT on success (match not found yet)
90 * - WALK_ERR on errors.
91 * - WALK_DONE is returned, cb_data.found is set to TRUE, and
92 * *cb_data.u2d_dip_addr is set to the matched dip addr if a dip corresponding
93 * to the desired usba_device_t* is found.
95 /*ARGSUSED*/
96 static int
97 find_dip(uintptr_t dip_addr, const void *local_dip, void *cb_arg)
99 uintptr_t cur_usb_dev;
100 usba_device2devinfo_cbdata_t *cb_data =
101 (usba_device2devinfo_cbdata_t *)cb_arg;
103 if ((cur_usb_dev = mdb_usba_get_usba_device(dip_addr)) ==
104 (uintptr_t)NULL) {
106 * If there's no corresponding usba_device_t, this dip isn't
107 * a usb node. Might be an sd node. Ignore it.
110 return (WALK_NEXT);
113 if (cur_usb_dev == cb_data->u2d_target_usb_dev_p) {
114 *cb_data->u2d_dip_addr = dip_addr;
115 cb_data->u2d_found = TRUE;
117 return (WALK_DONE);
120 return (WALK_NEXT);
125 * Given a usba_device pointer, figure out which dip is associated with it.
126 * Relies on usba_device.usb_root_hub_dip being accurate.
128 * - usb_dev_addr is a pointer to a usba_device_t in core.
129 * - dip_addr is the address of a uintptr_t to receive the address in core
130 * of the found dip (if any).
132 * Returns:
133 * 0 on success (no match found)
134 * 1 on success (match found)
135 * -1 on errors.
137 static int
138 usba_device2dip(uintptr_t usb_dev_addr, uintptr_t *dip_addr)
140 usba_device_t usb_dev;
141 usba_device2devinfo_cbdata_t cb_data;
144 * Walk all USB children of the root hub devinfo.
145 * The callback func looks for a match on the usba_device address.
147 cb_data.u2d_target_usb_dev_p = usb_dev_addr;
148 cb_data.u2d_dip_addr = dip_addr;
149 cb_data.u2d_found = FALSE;
151 if (mdb_vread(&usb_dev, sizeof (usba_device_t),
152 usb_dev_addr) == -1) {
153 mdb_warn("failed to read usba_device struct");
155 return (-1);
159 * Walk devinfo children starting with the root hub node,
160 * looking for a match on the usba_device pointer (which is what
161 * find_dip does).
162 * Result is placed in cb_data.dip_addr.
164 if (mdb_pwalk("devinfo_children", find_dip, &cb_data,
165 (uintptr_t)usb_dev.usb_root_hub_dip) != 0) {
166 mdb_warn("failed to walk devinfo_children");
168 return (-1);
171 if (cb_data.u2d_found == TRUE) {
173 return (1);
176 return (0);
181 * Generic walker usba_list_entry_t walker.
182 * Works for any usba_list_entry_t list.
185 usba_list_walk_init(mdb_walk_state_t *wsp)
187 /* Must have a start addr. */
188 if (wsp->walk_addr == (uintptr_t)NULL) {
189 mdb_warn("not a global walk. Starting address required\n");
191 return (WALK_ERR);
194 return (WALK_NEXT);
199 * Generic list walker step routine.
200 * NOTE: multiple walkers share this routine.
203 usba_list_walk_step(mdb_walk_state_t *wsp)
205 int status;
206 usba_list_entry_t list_entry;
208 if (mdb_vread(&list_entry, sizeof (usba_list_entry_t),
209 (uintptr_t)wsp->walk_addr) == -1) {
210 mdb_warn("failed to read usba_list_entry_t at %p",
211 wsp->walk_addr);
213 return (WALK_ERR);
216 status = wsp->walk_callback(wsp->walk_addr, &list_entry,
217 wsp->walk_cbdata);
218 wsp->walk_addr = (uintptr_t)list_entry.next;
220 /* Check if we're at the last element */
221 if (wsp->walk_addr == (uintptr_t)NULL) {
223 return (WALK_DONE);
226 return (status);
231 * usb_pipe_handle walker
232 * Given a pointer to a usba_device_t, walk the array of endpoint
233 * pipe_handle lists.
234 * For each list, traverse the list, invoking the callback on each element.
236 * Note this function takes the address of a usba_device struct (which is
237 * easily obtainable), but actually traverses a sub-portion of the struct
238 * (which address is not so easily obtainable).
241 usb_pipe_handle_walk_init(mdb_walk_state_t *wsp)
243 if (wsp->walk_addr == (uintptr_t)NULL) {
244 mdb_warn("not a global walk; usba_device_t required\n");
246 return (WALK_ERR);
249 wsp->walk_data = mdb_alloc((sizeof (usba_ph_impl_t)) * USBA_N_ENDPOINTS,
250 UM_SLEEP | UM_GC);
253 * Read the usb_ph_list array into local memory.
254 * Set start address to first element/endpoint in usb_pipehandle_list
256 if (mdb_vread(wsp->walk_data,
257 (sizeof (usba_ph_impl_t)) * USBA_N_ENDPOINTS,
258 (uintptr_t)((size_t)(wsp->walk_addr) +
259 offsetof(usba_device_t, usb_ph_list))) == -1) {
260 mdb_warn("failed to read usb_pipehandle_list at %p",
261 wsp->walk_addr);
263 return (WALK_ERR);
266 wsp->walk_arg = 0;
268 return (WALK_NEXT);
273 usb_pipe_handle_walk_step(mdb_walk_state_t *wsp)
275 int status;
276 usba_ph_impl_t *impl_list = (usba_ph_impl_t *)(wsp->walk_data);
277 intptr_t index = (intptr_t)wsp->walk_arg;
279 /* Find the first valid endpoint, starting from where we left off. */
280 while ((index < USBA_N_ENDPOINTS) &&
281 (impl_list[index].usba_ph_data == NULL)) {
282 index++;
285 /* No more valid endpoints. */
286 if (index >= USBA_N_ENDPOINTS) {
288 return (WALK_DONE);
291 status = wsp->walk_callback((uintptr_t)impl_list[index].usba_ph_data,
292 wsp->walk_data, wsp->walk_cbdata);
294 /* Set up to start at next pipe handle next time. */
295 wsp->walk_arg = (void *)(index + 1);
297 return (status);
302 * Given the address of a usba_pipe_handle_data_t, dump summary info.
304 /*ARGSUSED*/
306 usb_pipe_handle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
308 char *dir, *type, *state;
309 usb_ep_descr_t ept_descr;
310 usba_pipe_handle_data_t pipe_handle;
311 usba_ph_impl_t ph_impl;
313 if (!(flags & DCMD_ADDRSPEC)) {
315 return (DCMD_USAGE);
318 if (mdb_vread(&pipe_handle,
319 sizeof (usba_pipe_handle_data_t), addr) == -1) {
320 mdb_warn("failed to read pipe handle at %p", addr);
322 return (DCMD_ERR);
325 if (mdb_vread(&ph_impl, sizeof (usba_ph_impl_t),
326 (uintptr_t)pipe_handle.p_ph_impl) == -1) {
327 state = "*******";
328 } else {
329 switch (ph_impl.usba_ph_state) {
330 case USB_PIPE_STATE_CLOSED:
331 state = "CLOSED ";
332 break;
334 case USB_PIPE_STATE_IDLE:
335 state = "IDLE ";
336 break;
338 case USB_PIPE_STATE_ACTIVE:
339 state = "ACTIVE ";
340 break;
342 case USB_PIPE_STATE_ERROR:
343 state = "ERROR ";
344 break;
346 case USB_PIPE_STATE_CLOSING:
347 state = "CLOSING";
348 break;
350 default:
351 state = "ILLEGAL";
352 break;
356 bcopy(&pipe_handle.p_ep, &ept_descr, sizeof (usb_ep_descr_t));
358 if (DCMD_HDRSPEC(flags)) {
359 mdb_printf("\n %<u>%-3s %5s %3s %7s %-?s %-?s %-?s%</u>\n",
360 "EP", "TYPE ", "DIR", "STATE ", "P_HANDLE", "P_POLICY",
361 "EP DESCR");
364 dir = ((ept_descr.bEndpointAddress & USB_EP_DIR_MASK) &
365 USB_EP_DIR_IN) ? "In " : "Out";
366 switch (ept_descr.bmAttributes & USB_EP_ATTR_MASK) {
367 case USB_EP_ATTR_CONTROL:
368 type = "Cntrl";
369 break;
371 case USB_EP_ATTR_ISOCH:
372 type = "Isoch";
373 break;
375 case USB_EP_ATTR_BULK:
376 type = "Bulk ";
377 break;
379 case USB_EP_ATTR_INTR:
380 type = "Intr ";
381 break;
383 default:
384 type = "*****";
385 break;
388 mdb_printf(" %3d %5s %3s %7s %-?p %-?p %-?p\n",
389 ept_descr.bEndpointAddress & USB_EP_NUM_MASK, type, dir, state,
390 addr, addr + offsetof(usba_pipe_handle_data_t, p_policy),
391 addr + offsetof(usba_pipe_handle_data_t, p_ep));
393 return (DCMD_OK);
398 * usba_device walker:
400 * walks the chain of usba_device structs headed by usba_device_list in usba.c
401 * NOTE: It uses the generic list walk step routine usba_list_walk_step.
402 * No walk_fini routine is needed.
405 usba_device_walk_init(mdb_walk_state_t *wsp)
407 usba_list_entry_t list_entry;
409 if (wsp->walk_addr != (uintptr_t)NULL) {
410 mdb_warn(
411 "global walk only. Must be invoked without an address\n");
413 return (WALK_ERR);
416 if (mdb_readvar(&list_entry, "usba_device_list") == -1) {
417 mdb_warn("failed to read usba_device_list");
419 return (WALK_ERR);
422 /* List head is not part of usba_device_t, get first usba_device_t */
423 wsp->walk_addr = (uintptr_t)list_entry.next;
425 return (WALK_NEXT);
429 usba_hubd_walk_init(mdb_walk_state_t *wsp)
431 if (wsp->walk_addr != 0) {
432 mdb_warn("hubd only supports global walks.\n");
433 return (WALK_ERR);
436 if (mdb_layered_walk("usba_device", wsp) == -1) {
437 mdb_warn("couldn't walk 'usba_device'");
438 return (WALK_ERR);
441 return (WALK_NEXT);
445 * Getting the hub state is annoying. The root hubs are stored on dev_info_t
446 * while the normal hubs are stored as soft state.
449 usba_hubd_walk_step(mdb_walk_state_t *wsp)
451 usba_device_t ud;
452 hubd_t hubd;
453 struct dev_info dev_info;
454 uintptr_t state_addr;
456 if (mdb_vread(&ud, sizeof (ud), wsp->walk_addr) != sizeof (ud)) {
457 mdb_warn("failed to read usba_device_t at %p", wsp->walk_addr);
458 return (WALK_ERR);
461 if (ud.usb_root_hubd != NULL) {
462 if (mdb_vread(&hubd, sizeof (hubd),
463 (uintptr_t)ud.usb_root_hubd) != sizeof (hubd)) {
464 mdb_warn("failed to read hubd at %p", ud.usb_root_hubd);
465 return (WALK_ERR);
467 return (wsp->walk_callback((uintptr_t)ud.usb_root_hubd, &hubd,
468 wsp->walk_cbdata));
471 if (ud.usb_hubdi == NULL)
472 return (WALK_NEXT);
475 * For non-root hubs, the hubd_t is stored in the soft state. Figure out
476 * the instance from the dev_info_t and then get its soft state.
478 if (mdb_vread(&dev_info, sizeof (struct dev_info),
479 (uintptr_t)ud.usb_dip) != sizeof (struct dev_info)) {
480 mdb_warn("failed to read dev_info_t for device %p at %p",
481 wsp->walk_addr, ud.usb_dip);
482 return (WALK_ERR);
485 if (mdb_get_soft_state_byname("hubd_statep", dev_info.devi_instance,
486 &state_addr, &hubd, sizeof (hubd)) == -1) {
487 mdb_warn("failed to read hubd soft state for instance %d from "
488 "usb device %p", dev_info.devi_instance, wsp->walk_addr);
489 return (WALK_ERR);
492 return (wsp->walk_callback(state_addr, &hubd, wsp->walk_cbdata));
496 * usba_device dcmd
497 * Given the address of a usba_device struct, dump summary info
498 * -v: Print more (verbose) info
499 * -p: Walk/dump all open pipes for this usba_device
501 /*ARGSUSED*/
503 usba_device(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
505 int status;
506 char pathname[MAXNAMELEN];
507 char dname[MODMAXNAMELEN + 1] = "<unatt>"; /* Driver name */
508 char drv_statep[MODMAXNAMELEN+ 10];
509 uint_t usb_flag = 0;
510 boolean_t no_driver_attached = FALSE;
511 uintptr_t dip_addr;
512 struct dev_info devinfo;
514 if (!(flags & DCMD_ADDRSPEC)) {
515 /* Global walk */
516 if (mdb_walk_dcmd("usba_device", "usba_device", argc,
517 argv) == -1) {
518 mdb_warn("failed to walk usba_device");
520 return (DCMD_ERR);
523 return (DCMD_OK);
526 if (mdb_getopts(argc, argv,
527 'p', MDB_OPT_SETBITS, USB_DUMP_ACTIVE_PIPES, &usb_flag,
528 'v', MDB_OPT_SETBITS, USB_DUMP_VERBOSE, &usb_flag, NULL) != argc) {
530 return (DCMD_USAGE);
533 if (usb_flag && !(DCMD_HDRSPEC(flags))) {
534 mdb_printf("\n");
537 if (DCMD_HDRSPEC(flags)) {
538 mdb_printf("%<u>%-15s %4s %-?s %-42s%</u>\n",
539 "NAME", "INST", "DIP", "PATH ");
542 status = usba_device2dip(addr, &dip_addr);
544 * -1 = error
545 * 0 = no error, no match
546 * 1 = no error, match
548 if (status != 1) {
549 if (status == -1) {
550 mdb_warn("error looking for dip for usba_device %p",
551 addr);
552 } else {
553 mdb_warn("failed to find dip for usba_device %p\n",
554 addr);
556 mdb_warn("dip and statep unobtainable\n");
558 return (DCMD_ERR);
561 /* Figure out what driver (name) is attached to this node. */
562 (void) mdb_devinfo2driver(dip_addr, (char *)dname, sizeof (dname));
564 if (mdb_vread(&devinfo, sizeof (struct dev_info),
565 dip_addr) == -1) {
566 mdb_warn("failed to read devinfo");
568 return (DCMD_ERR);
571 if (!(DDI_CF2(&devinfo))) {
572 no_driver_attached = TRUE;
575 (void) mdb_ddi_pathname(dip_addr, pathname, sizeof (pathname));
576 mdb_printf("%-15s %2d %-?p %s\n", dname, devinfo.devi_instance,
577 dip_addr, pathname);
579 if (usb_flag & USB_DUMP_VERBOSE) {
580 int i;
581 uintptr_t statep = (uintptr_t)NULL;
582 char *string_descr;
583 char **config_cloud, **conf_str_descr;
584 usb_dev_descr_t usb_dev_descr;
585 usba_device_t usba_device_struct;
587 if (mdb_vread(&usba_device_struct,
588 sizeof (usba_device_t), addr) == -1) {
589 mdb_warn("failed to read usba_device struct");
591 return (DCMD_ERR);
594 mdb_printf(" usba_device: %-16p\n\n", (usba_device_t *)addr);
596 if (mdb_vread(&usb_dev_descr, sizeof (usb_dev_descr),
597 (uintptr_t)usba_device_struct.usb_dev_descr) == -1) {
598 mdb_warn("failed to read usb_dev_descr_t struct");
600 return (DCMD_ERR);
603 mdb_printf("\n idVendor: 0x%04x idProduct: 0x%04x "
604 "usb_addr: 0x%02x\n", usb_dev_descr.idVendor,
605 usb_dev_descr.idProduct, usba_device_struct.usb_addr);
607 /* Get the string descriptor string into local space. */
608 string_descr = (char *)mdb_alloc(USB_MAXSTRINGLEN, UM_GC);
610 if (usba_device_struct.usb_mfg_str == NULL) {
611 (void) strcpy(string_descr, "<No Manufacturer String>");
612 } else {
613 if (mdb_readstr(string_descr, USB_MAXSTRINGLEN,
614 (uintptr_t)usba_device_struct.usb_mfg_str) == -1) {
615 mdb_warn("failed to read manufacturer "
616 "string descriptor");
617 (void) strcpy(string_descr, "???");
620 mdb_printf("\n Manufacturer String:\t%s\n", string_descr);
622 if (usba_device_struct.usb_product_str == NULL) {
623 (void) strcpy(string_descr, "<No Product String>");
624 } else {
625 if (mdb_readstr(string_descr, USB_MAXSTRINGLEN,
626 (uintptr_t)usba_device_struct.usb_product_str) ==
627 -1) {
628 mdb_warn("failed to read product string "
629 "descriptor");
630 (void) strcpy(string_descr, "???");
633 mdb_printf(" Product String:\t\t%s\n", string_descr);
635 if (usba_device_struct.usb_serialno_str == NULL) {
636 (void) strcpy(string_descr, "<No SerialNumber String>");
637 } else {
638 if (mdb_readstr(string_descr, USB_MAXSTRINGLEN,
639 (uintptr_t)usba_device_struct.usb_serialno_str) ==
640 -1) {
641 mdb_warn("failed to read serial number string "
642 "descriptor");
643 (void) strcpy(string_descr, "???");
646 mdb_printf(" SerialNumber String:\t%s\n", string_descr);
648 if (no_driver_attached) {
649 mdb_printf("\n");
650 } else {
651 mdb_printf(" state_p: ");
654 * Given the dip, find the associated statep. The
655 * convention to generate this soft state anchor is:
656 * <driver_name>_statep
658 (void) mdb_snprintf(drv_statep, sizeof (drv_statep),
659 "%s_statep", dname);
660 if (mdb_devinfo2statep(dip_addr, drv_statep,
661 &statep) == -1) {
662 mdb_warn("failed to find %s state struct for "
663 "dip %p", drv_statep, dip_addr);
665 return (DCMD_ERR);
667 mdb_printf("%-?p\n", statep);
670 config_cloud = (char **)mdb_alloc(sizeof (void *) *
671 usba_device_struct.usb_n_cfgs, UM_GC);
673 conf_str_descr = (char **)mdb_alloc(sizeof (void *) *
674 usba_device_struct.usb_n_cfgs, UM_GC);
676 if ((usba_device_struct.usb_cfg_array) &&
677 (usba_device_struct.usb_cfg_str_descr)) {
678 if ((mdb_vread(config_cloud, sizeof (void *) *
679 usba_device_struct.usb_n_cfgs,
680 (uintptr_t)usba_device_struct.usb_cfg_array) ==
681 -1) || (mdb_vread(conf_str_descr, sizeof (void *)
682 * usba_device_struct.usb_n_cfgs, (uintptr_t)
683 usba_device_struct.usb_cfg_str_descr)) == -1) {
685 mdb_warn("failed to read config cloud "
686 "pointers");
688 } else {
690 mdb_printf("\n Device Config Clouds:\n"
691 " Index\tConfig\t\tConfiguration "
692 "String\n"
693 " -----\t------\t\t"
694 "--------------------\n");
696 for (i = 0; i < usba_device_struct.usb_n_cfgs;
697 i++) {
698 if (mdb_readstr(string_descr,
699 USB_MAXSTRINGLEN,
700 (uintptr_t)conf_str_descr[i]) ==
701 -1) {
702 (void) strcpy(string_descr,
703 "<No Configuration "
704 "String>");
706 mdb_printf(" %4d\t0x%p\t%s\n", i,
707 config_cloud[i], string_descr);
712 mdb_printf("\n Active configuration index: %d\n",
713 usba_device_struct.usb_active_cfg_ndx);
716 if (usb_flag & USB_DUMP_ACTIVE_PIPES) {
718 if (mdb_pwalk_dcmd("usb_pipe_handle", "usb_pipe_handle",
719 0, NULL, addr) == -1) {
720 mdb_warn("failed to walk usb_pipe_handle");
721 return (DCMD_ERR);
725 return (DCMD_OK);
730 * Dump the contents of the usba_debug_buf, from the oldest to newest,
731 * wrapping around if necessary.
733 /*ARGSUSED*/
735 usba_debug_buf(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
737 char *debug_buf_addr; /* addr in core */
738 char *local_debug_buf; /* local copy of buf */
739 int debug_buf_size;
740 char *term_p;
741 int being_cleared;
743 if (flags & DCMD_ADDRSPEC) {
745 return (DCMD_USAGE);
748 if (mdb_readvar(&being_cleared, "usba_clear_debug_buf_flag") ==
749 -1) {
750 mdb_warn("failed to read usba_clear_debug_buf_flag");
752 return (DCMD_ERR);
754 if (being_cleared) {
756 return (DCMD_OK);
759 if (mdb_readvar(&debug_buf_addr, "usba_debug_buf") == -1) {
760 mdb_warn("failed to read usba_debug_buf");
762 return (DCMD_ERR);
765 if (debug_buf_addr == NULL) {
766 mdb_warn("usba_debug_buf not allocated\n");
768 return (DCMD_OK);
772 if (mdb_readvar(&debug_buf_size, "usba_debug_buf_size") == -1) {
773 mdb_warn("failed to read usba_debug_buf_size");
775 return (DCMD_ERR);
778 debug_buf_size += USB_DEBUG_SIZE_EXTRA_ALLOC;
779 local_debug_buf = (char *)mdb_alloc(debug_buf_size, UM_SLEEP | UM_GC);
781 if ((mdb_vread(local_debug_buf, debug_buf_size,
782 (uintptr_t)debug_buf_addr)) == -1) {
783 mdb_warn("failed to read usba_debug_buf at %p",
784 local_debug_buf);
786 return (DCMD_ERR);
788 local_debug_buf[debug_buf_size - 1] = '\0';
790 if (strlen(local_debug_buf) == 0) {
792 return (DCMD_OK);
795 if ((term_p = strstr(local_debug_buf, ">>>>")) == NULL) {
796 mdb_warn("failed to find terminator \">>>>\"\n");
798 return (DCMD_ERR);
802 * Print the chunk of buffer from the terminator to the end.
803 * This will print a null string if no wrap has occurred yet.
805 mdb_printf("%s", term_p+5); /* after >>>>\0 to end of buf */
806 mdb_printf("%s\n", local_debug_buf); /* beg of buf to >>>>\0 */
808 return (DCMD_OK);
811 /*ARGSUSED*/
813 usba_clear_debug_buf(
814 uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
816 int clear = 1;
818 /* stop the tracing */
819 if (mdb_writevar((void*)&clear, "usba_clear_debug_buf_flag") == -1) {
820 mdb_warn("failed to set usba_clear_debug_buf_flag");
822 return (DCMD_ERR);
825 return (DCMD_OK);
828 /* prtusb entries */
829 extern int prtusb(uintptr_t, uint_t, int, const mdb_arg_t *);
831 extern void prt_usb_usage(void);
834 * MDB module linkage information:
836 * We declare a list of structures describing our dcmds, and a function
837 * named _mdb_init to return a pointer to our module information.
839 static const mdb_dcmd_t dcmds[] = {
840 { "usb_pipe_handle", ":",
841 "print a usb_pipe_handle struct", usb_pipe_handle, NULL},
842 { "usba_device", ": [-pv]",
843 "print summary info for a usba_device_t struct", usba_device, NULL},
844 { "usba_debug_buf", NULL,
845 "print usba_debug_buf", usba_debug_buf, NULL},
846 { "usba_clear_debug_buf", NULL,
847 "clear usba_debug_buf", usba_clear_debug_buf, NULL},
848 { "prtusb", "?[-t] [-v] [-i index]",
849 "print trees and descriptors for usba_device_t",
850 prtusb, prt_usb_usage},
851 { NULL }
854 static const mdb_walker_t walkers[] = {
855 /* Generic list walker. */
856 { "usba_list_entry", "walk list of usba_list_entry_t structures",
857 usba_list_walk_init, usba_list_walk_step, NULL, NULL },
858 { "usb_pipe_handle", "walk USB pipe handles, given a usba_device_t ptr",
859 usb_pipe_handle_walk_init, usb_pipe_handle_walk_step, NULL, NULL },
860 { "usba_device", "walk global list of usba_device_t structures",
861 usba_device_walk_init, usba_list_walk_step, NULL, NULL },
862 { "hubd", "walk hubd instances", usba_hubd_walk_init,
863 usba_hubd_walk_step, NULL, NULL },
864 { NULL }
867 static const mdb_modinfo_t modinfo = {
868 MDB_API_VERSION, dcmds, walkers
871 const mdb_modinfo_t *
872 _mdb_init(void)
874 return (&modinfo);