xref: /titanic_51/usr/src/cmd/mdb/common/modules/uhci/uhci.c (revision a7317ceb814150d472383df8b987d7e3282ea15b)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <gelf.h>
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <sys/mdb_modapi.h>
307c478bd9Sstevel@tonic-gate #include <mdb/mdb_ks.h>
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include <sys/usb/usba.h>
337c478bd9Sstevel@tonic-gate #include <sys/usb/usba/usba_types.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <sys/usb/hcd/uhci/uhci.h>
367c478bd9Sstevel@tonic-gate #include <sys/usb/hcd/uhci/uhcid.h>
377c478bd9Sstevel@tonic-gate #include <sys/usb/hcd/uhci/uhciutil.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #define	UHCI_TD	0
417c478bd9Sstevel@tonic-gate #define	UHCI_QH	1
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /* Prototypes */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate int	uhci_td(uintptr_t, uint_t, int, const mdb_arg_t *);
477c478bd9Sstevel@tonic-gate int	uhci_qh(uintptr_t, uint_t, int, const mdb_arg_t *);
487c478bd9Sstevel@tonic-gate int	uhci_td_walk_init(mdb_walk_state_t *);
497c478bd9Sstevel@tonic-gate int	uhci_td_walk_step(mdb_walk_state_t *);
507c478bd9Sstevel@tonic-gate int	uhci_qh_walk_init(mdb_walk_state_t *);
517c478bd9Sstevel@tonic-gate int	uhci_qh_walk_step(mdb_walk_state_t *);
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * Callback for find_uhci_statep (called back from walk "softstate" in
567c478bd9Sstevel@tonic-gate  * find_uhci_statep).
577c478bd9Sstevel@tonic-gate  *
587c478bd9Sstevel@tonic-gate  * - uhci_instancep is the value of the current pointer in the array of soft
597c478bd9Sstevel@tonic-gate  * state instance pointers (see i_ddi_soft_state in ddi_impldefs.h)
607c478bd9Sstevel@tonic-gate  * - local_ss is a pointer to the copy of the i_ddi_soft_state in local space
617c478bd9Sstevel@tonic-gate  * - cb_arg is a pointer to the cb arg (an instance of state_find_data).
627c478bd9Sstevel@tonic-gate  *
637c478bd9Sstevel@tonic-gate  * For the current uchi_state_t*, see if the td address is in its pool.
647c478bd9Sstevel@tonic-gate  *
657c478bd9Sstevel@tonic-gate  * Returns WALK_NEXT on success (match not found yet), WALK_ERR on errors.
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  * WALK_DONE is returned, cb_data.found is set to TRUE, and
687c478bd9Sstevel@tonic-gate  * *cb_data.fic_uhci_statep is filled in with the contents of the state
697c478bd9Sstevel@tonic-gate  * struct in core. This forces the walk to terminate.
707c478bd9Sstevel@tonic-gate  */
717c478bd9Sstevel@tonic-gate typedef struct find_instance_struct {
727c478bd9Sstevel@tonic-gate 	void		*fic_td_qh;	/* td/qh we want uhci instance for */
737c478bd9Sstevel@tonic-gate 	boolean_t	fic_td_or_qh;	/* which one td_qh points to */
747c478bd9Sstevel@tonic-gate 	boolean_t	fic_found;
757c478bd9Sstevel@tonic-gate 	uhci_state_t	*fic_uhci_statep; /* buffer uhci_state's written into */
767c478bd9Sstevel@tonic-gate } find_instance_cb_t;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*ARGSUSED*/
797c478bd9Sstevel@tonic-gate static int
807c478bd9Sstevel@tonic-gate find_uhci_instance(uintptr_t uhci_instancep, const void *local_ss, void *cb_arg)
817c478bd9Sstevel@tonic-gate {
827c478bd9Sstevel@tonic-gate 	int			td_pool_size, qh_pool_size;
837c478bd9Sstevel@tonic-gate 	find_instance_cb_t	*cb_data = (find_instance_cb_t *)cb_arg;
847c478bd9Sstevel@tonic-gate 	uhci_state_t		*uhcip = cb_data->fic_uhci_statep;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	if (mdb_vread(cb_data->fic_uhci_statep, sizeof (uhci_state_t),
887c478bd9Sstevel@tonic-gate 	    uhci_instancep) == -1) {
897c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read uhci_state at %p", uhci_instancep);
907c478bd9Sstevel@tonic-gate 		return (-1);
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	if (mdb_readsym(&td_pool_size, sizeof (int), "uhci_td_pool_size") ==
947c478bd9Sstevel@tonic-gate 	    -1) {
957c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read uhci_td_pool_size");
967c478bd9Sstevel@tonic-gate 		return (-1);
977c478bd9Sstevel@tonic-gate 	}
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	if (mdb_readsym(&qh_pool_size, sizeof (int), "uhci_qh_pool_size") ==
1007c478bd9Sstevel@tonic-gate 	    -1) {
1017c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read uhci_td_pool_size");
1027c478bd9Sstevel@tonic-gate 		return (-1);
1037c478bd9Sstevel@tonic-gate 	}
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	/*
1067c478bd9Sstevel@tonic-gate 	 * See if the addr is within the appropriate pool for this instance.
1077c478bd9Sstevel@tonic-gate 	 */
1087c478bd9Sstevel@tonic-gate 	if ((cb_data->fic_td_or_qh == UHCI_TD &&
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	    ((uhci_td_t *)cb_data->fic_td_qh >= uhcip->uhci_td_pool_addr &&
1117c478bd9Sstevel@tonic-gate 	    (uhci_td_t *)cb_data->fic_td_qh <= (uhcip->uhci_td_pool_addr +
1127c478bd9Sstevel@tonic-gate 	    td_pool_size - sizeof (uhci_td_t)))) ||
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	    (cb_data->fic_td_or_qh == UHCI_QH &&
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	    ((queue_head_t *)cb_data->fic_td_qh >= uhcip->uhci_qh_pool_addr &&
1177c478bd9Sstevel@tonic-gate 	    (queue_head_t *)cb_data->fic_td_qh <= (uhcip->uhci_qh_pool_addr +
1187c478bd9Sstevel@tonic-gate 	    qh_pool_size - sizeof (queue_head_t))))) {
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 		/* td/qh address is within pool for this instance of uhci. */
1217c478bd9Sstevel@tonic-gate 		cb_data->fic_found = TRUE;
1227c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
1267c478bd9Sstevel@tonic-gate }
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate /*
1297c478bd9Sstevel@tonic-gate  * Figure out which instance of uhci owns a td/qh.
1307c478bd9Sstevel@tonic-gate  *
1317c478bd9Sstevel@tonic-gate  * - td_qh: a pointer to a uhci td or qh
1327c478bd9Sstevel@tonic-gate  * - td_or_qh: a flag indicating which it is (td/qh),
1337c478bd9Sstevel@tonic-gate  * - uhci_statep, pointer to a uhci_state_t, to be filled in with data from
1347c478bd9Sstevel@tonic-gate  * the found instance of uhci_state_t.
1357c478bd9Sstevel@tonic-gate  *
1367c478bd9Sstevel@tonic-gate  * Only works for Cntl/Interrupt tds/qhs; others are dynamically allocated
1377c478bd9Sstevel@tonic-gate  * and so cannot be found with this method.
1387c478bd9Sstevel@tonic-gate  *
1397c478bd9Sstevel@tonic-gate  * Returns 0 on success (no match found), 1 on success (match found),
1407c478bd9Sstevel@tonic-gate  * -1 on errors.
1417c478bd9Sstevel@tonic-gate  */
1427c478bd9Sstevel@tonic-gate static int
1437c478bd9Sstevel@tonic-gate find_uhci_statep(void *td_qh, boolean_t td_or_qh, uhci_state_t *uhci_statep)
1447c478bd9Sstevel@tonic-gate {
1457c478bd9Sstevel@tonic-gate 	find_instance_cb_t	cb_data;
1467c478bd9Sstevel@tonic-gate 	uintptr_t		uhci_ss;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	if (uhci_statep == NULL) {
1507c478bd9Sstevel@tonic-gate 		mdb_warn("failed to find uhci statep: "
1517c478bd9Sstevel@tonic-gate 		    "NULL uhci_statep param\n");
1527c478bd9Sstevel@tonic-gate 		return (-1);
1537c478bd9Sstevel@tonic-gate 	}
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	cb_data.fic_td_qh = td_qh;
1567c478bd9Sstevel@tonic-gate 	cb_data.fic_td_or_qh = td_or_qh;
1577c478bd9Sstevel@tonic-gate 	cb_data.fic_found = FALSE;
1587c478bd9Sstevel@tonic-gate 	cb_data.fic_uhci_statep = uhci_statep;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	if (mdb_readsym(&uhci_ss, sizeof (uhci_statep),
1627c478bd9Sstevel@tonic-gate 	    "uhci_statep") == -1) {
1637c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read uhci_statep");
1647c478bd9Sstevel@tonic-gate 		return (-1);
1657c478bd9Sstevel@tonic-gate 	}
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	/*
1697c478bd9Sstevel@tonic-gate 	 * Walk all instances of uhci.
1707c478bd9Sstevel@tonic-gate 	 * The callback func checks if td_qh belongs to a given instance
1717c478bd9Sstevel@tonic-gate 	 * of uhci.
1727c478bd9Sstevel@tonic-gate 	 */
1737c478bd9Sstevel@tonic-gate 	if (mdb_pwalk("softstate", find_uhci_instance, &cb_data,
1747c478bd9Sstevel@tonic-gate 	    uhci_ss) != 0) {
1757c478bd9Sstevel@tonic-gate 		mdb_warn("failed to walk softstate");
1767c478bd9Sstevel@tonic-gate 		return (-1);
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	if (cb_data.fic_found == TRUE) {
1807c478bd9Sstevel@tonic-gate 		return (1);
1817c478bd9Sstevel@tonic-gate 	}
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	return (0);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate  * Dump a UHCI TD (transaction descriptor);
1887c478bd9Sstevel@tonic-gate  * or (-d) the chain of TDs starting with the one specified.
1897c478bd9Sstevel@tonic-gate  */
1907c478bd9Sstevel@tonic-gate int
1917c478bd9Sstevel@tonic-gate uhci_td(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	uint_t		depth_flag = FALSE;
1947c478bd9Sstevel@tonic-gate 	uhci_state_t	uhci_state, *uhcip = &uhci_state;
1957c478bd9Sstevel@tonic-gate 	uhci_td_t	td;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
1997c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate 	if (addr & ~QH_LINK_PTR_MASK) {
2027c478bd9Sstevel@tonic-gate 		mdb_warn("address must be on a 16-byte boundary.\n");
2037c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
2077c478bd9Sstevel@tonic-gate 	    'd', MDB_OPT_SETBITS, TRUE, &depth_flag,
2087c478bd9Sstevel@tonic-gate 	    NULL) != argc) {
2097c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
2107c478bd9Sstevel@tonic-gate 	}
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 	if (depth_flag) {
2147c478bd9Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("uhci_td", "uhci_td", 0, NULL, addr) == -1) {
2157c478bd9Sstevel@tonic-gate 			mdb_warn("failed to walk 'uhci_td'");
2167c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
2177c478bd9Sstevel@tonic-gate 		}
2187c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	if (find_uhci_statep((void *)addr, UHCI_TD, uhcip) != 1) {
2237c478bd9Sstevel@tonic-gate 		mdb_warn("failed to find uhci_statep");
2247c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	if (mdb_vread(&td, sizeof (td), addr) != sizeof (td))  {
2287c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read td at vaddr %p", addr);
2297c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	mdb_printf("\n  UHCI td struct at (vaddr) %08x:\n", addr);
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	if (!(td.link_ptr & HC_END_OF_LIST) && td.link_ptr != NULL) {
2357c478bd9Sstevel@tonic-gate 		mdb_printf("        link_ptr (paddr)    : %-8x        "
2367c478bd9Sstevel@tonic-gate 		    "(vaddr)      : %p\n",
2377c478bd9Sstevel@tonic-gate 		    td.link_ptr,
2387c478bd9Sstevel@tonic-gate 		    /* Note: uhcip needed by TD_VADDR macro */
2397c478bd9Sstevel@tonic-gate 		    TD_VADDR(td.link_ptr & QH_LINK_PTR_MASK));
2407c478bd9Sstevel@tonic-gate 	} else {
2417c478bd9Sstevel@tonic-gate 		mdb_printf("        link_ptr (paddr)    : %-8x\n",
2427c478bd9Sstevel@tonic-gate 		    td.link_ptr);
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 	mdb_printf("        td_dword2           : %08x\n", td.dw2);
2457c478bd9Sstevel@tonic-gate 	mdb_printf("        td_dword3           : %08x\n", td.dw3);
2467c478bd9Sstevel@tonic-gate 	mdb_printf("        buffer_address      : %08x\n", td.buffer_address);
2477c478bd9Sstevel@tonic-gate 	mdb_printf("        qh_td_prev          : %?p        "
2487c478bd9Sstevel@tonic-gate 	    "tw_td_next   : %?p\n",
2497c478bd9Sstevel@tonic-gate 	    td.qh_td_prev, td.tw_td_next);
2507c478bd9Sstevel@tonic-gate 	mdb_printf("        outst_td_prev        : %?p        "
2517c478bd9Sstevel@tonic-gate 	    "outst_td_next : %?p\n",
2527c478bd9Sstevel@tonic-gate 	    td.outst_td_prev, td.outst_td_next);
2537c478bd9Sstevel@tonic-gate 	mdb_printf("        tw                  : %?p        "
2547c478bd9Sstevel@tonic-gate 	    "flag         : %02x\n", td.tw, td.flag);
2557c478bd9Sstevel@tonic-gate 	mdb_printf("        isoc_next           : %?p        "
2567c478bd9Sstevel@tonic-gate 	    "isoc_prev    : %0x\n", td.isoc_next, td.isoc_prev);
2577c478bd9Sstevel@tonic-gate 	mdb_printf("        isoc_pkt_index      : %0x        "
2587c478bd9Sstevel@tonic-gate 	    "startingframe: %0x\n", td.isoc_pkt_index, td.starting_frame);
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	if (td.link_ptr == NULL)  {
2627c478bd9Sstevel@tonic-gate 		mdb_printf("        --> Link pointer = NULL\n");
2637c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
2647c478bd9Sstevel@tonic-gate 	} else {
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 		/* Inform user if link is to a TD or QH.  */
2677c478bd9Sstevel@tonic-gate 		if (td.link_ptr & HC_END_OF_LIST)  {
2687c478bd9Sstevel@tonic-gate 			mdb_printf("        "
2697c478bd9Sstevel@tonic-gate 			    "--> Link pointer invalid (terminate bit set).\n");
2707c478bd9Sstevel@tonic-gate 		} else {
2717c478bd9Sstevel@tonic-gate 			if ((td.link_ptr & HC_QUEUE_HEAD) == HC_QUEUE_HEAD)  {
2727c478bd9Sstevel@tonic-gate 				mdb_printf("        "
2737c478bd9Sstevel@tonic-gate 				    "--> Link pointer points to a QH.\n");
2747c478bd9Sstevel@tonic-gate 			} else {
2757c478bd9Sstevel@tonic-gate 				mdb_printf("        "
2767c478bd9Sstevel@tonic-gate 				    "--> Link pointer points to a TD.\n");
2777c478bd9Sstevel@tonic-gate 			}
2787c478bd9Sstevel@tonic-gate 		}
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate  * Dump a UHCI QH (queue head).
2867c478bd9Sstevel@tonic-gate  * -b walk/dump the chian of QHs starting with the one specified.
2877c478bd9Sstevel@tonic-gate  * -d also dump the chain of TDs starting with the one specified.
2887c478bd9Sstevel@tonic-gate  */
2897c478bd9Sstevel@tonic-gate int
2907c478bd9Sstevel@tonic-gate uhci_qh(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 	uint_t		breadth_flag = FALSE, depth_flag = FALSE;
2937c478bd9Sstevel@tonic-gate 	uhci_state_t	uhci_state, *uhcip = &uhci_state;
2947c478bd9Sstevel@tonic-gate 	queue_head_t	qh;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	if (!(flags & DCMD_ADDRSPEC))
2987c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	if (addr & ~QH_LINK_PTR_MASK) {
3017c478bd9Sstevel@tonic-gate 		mdb_warn("address must be on a 16-byte boundary.\n");
3027c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
3037c478bd9Sstevel@tonic-gate 	}
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	if (mdb_getopts(argc, argv,
3067c478bd9Sstevel@tonic-gate 	    'b', MDB_OPT_SETBITS, TRUE, &breadth_flag,
3077c478bd9Sstevel@tonic-gate 	    'd', MDB_OPT_SETBITS, TRUE, &depth_flag,
3087c478bd9Sstevel@tonic-gate 	    NULL) != argc) {
3097c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	if (breadth_flag) {
3147c478bd9Sstevel@tonic-gate 		uint_t		new_argc = 0;
3157c478bd9Sstevel@tonic-gate 		mdb_arg_t	new_argv[1];
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 		if (depth_flag) {
3197c478bd9Sstevel@tonic-gate 			new_argc = 1;
3207c478bd9Sstevel@tonic-gate 			new_argv[0].a_type = MDB_TYPE_STRING;
3217c478bd9Sstevel@tonic-gate 			new_argv[0].a_un.a_str = "-d";
3227c478bd9Sstevel@tonic-gate 		}
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 		if ((mdb_pwalk_dcmd("uhci_qh", "uhci_qh", new_argc, new_argv,
3257c478bd9Sstevel@tonic-gate 		    addr)) != 0)  {
3267c478bd9Sstevel@tonic-gate 			mdb_warn("failed to walk 'uhci_qh'");
3277c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
3287c478bd9Sstevel@tonic-gate 		}
3297c478bd9Sstevel@tonic-gate 		return (DCMD_OK);
3307c478bd9Sstevel@tonic-gate 	}
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	if (find_uhci_statep((void *)addr, UHCI_QH, uhcip) != 1) {
3347c478bd9Sstevel@tonic-gate 		mdb_warn("failed to find uhci_statep");
3357c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	if (mdb_vread(&qh, sizeof (qh), addr) != sizeof (qh))  {
3407c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read qh at vaddr %p", addr);
3417c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
3427c478bd9Sstevel@tonic-gate 	}
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	mdb_printf("\n  UHCI qh struct at (vaddr) %08x:\n", addr);
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate 	if (!(qh.link_ptr & HC_END_OF_LIST) && qh.link_ptr != NULL) {
3477c478bd9Sstevel@tonic-gate 		mdb_printf("        link_ptr (paddr)    : %08x        "
3487c478bd9Sstevel@tonic-gate 		    "(vaddr)      : %p\n",
3497c478bd9Sstevel@tonic-gate 		    qh.link_ptr,
3507c478bd9Sstevel@tonic-gate 		    /* Note: uhcip needed by QH_VADDR macro */
3517c478bd9Sstevel@tonic-gate 		    QH_VADDR(qh.link_ptr & QH_LINK_PTR_MASK));
3527c478bd9Sstevel@tonic-gate 	} else {
3537c478bd9Sstevel@tonic-gate 		mdb_printf(
3547c478bd9Sstevel@tonic-gate 		    "        link_ptr (paddr)    : %08x\n",
3557c478bd9Sstevel@tonic-gate 		    qh.link_ptr);
3567c478bd9Sstevel@tonic-gate 	}
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate 	if (!(qh.element_ptr & HC_END_OF_LIST) && qh.element_ptr != NULL) {
3597c478bd9Sstevel@tonic-gate 		mdb_printf("        element_ptr (paddr) : %08x        "
3607c478bd9Sstevel@tonic-gate 		    "(vaddr)      : %p\n",
3617c478bd9Sstevel@tonic-gate 		    qh.element_ptr,
3627c478bd9Sstevel@tonic-gate 		    /* Note: uhcip needed by TD_VADDR macro */
3637c478bd9Sstevel@tonic-gate 		    TD_VADDR(qh.element_ptr & QH_LINK_PTR_MASK));
3647c478bd9Sstevel@tonic-gate 	} else {
3657c478bd9Sstevel@tonic-gate 		mdb_printf(
3667c478bd9Sstevel@tonic-gate 		    "        element_ptr (paddr) : %08x\n", qh.element_ptr);
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	mdb_printf("        node                : %04x            "
3707c478bd9Sstevel@tonic-gate 	    "flag         : %04x\n",
3717c478bd9Sstevel@tonic-gate 	    qh.node, qh.qh_flag);
3727c478bd9Sstevel@tonic-gate 	mdb_printf("        prev_qh             : %?p        "
3737c478bd9Sstevel@tonic-gate 	    "td_tailp     : %?p\n",
3747c478bd9Sstevel@tonic-gate 	    qh.prev_qh, qh.td_tailp);
3757c478bd9Sstevel@tonic-gate 	mdb_printf("        bulk_xfer_isoc_info : %?p\n", qh.bulk_xfer_info);
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	if (qh.link_ptr == NULL)  {
3797c478bd9Sstevel@tonic-gate 		mdb_printf("        --> Link pointer = NULL\n");
3807c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
3817c478bd9Sstevel@tonic-gate 	} else {
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 		/* Inform user if next link is a TD or QH.  */
3847c478bd9Sstevel@tonic-gate 		if (qh.link_ptr & HC_END_OF_LIST)  {
3857c478bd9Sstevel@tonic-gate 			mdb_printf("        "
3867c478bd9Sstevel@tonic-gate 			    "--> Link pointer invalid (terminate bit set).\n");
3877c478bd9Sstevel@tonic-gate 		} else {
3887c478bd9Sstevel@tonic-gate 			if ((qh.link_ptr & HC_QUEUE_HEAD) == HC_QUEUE_HEAD)  {
3897c478bd9Sstevel@tonic-gate 				mdb_printf("        "
3907c478bd9Sstevel@tonic-gate 				    "--> Link pointer points to a QH.\n");
3917c478bd9Sstevel@tonic-gate 			} else {
3927c478bd9Sstevel@tonic-gate 				/* Should never happen. */
3937c478bd9Sstevel@tonic-gate 				mdb_warn("        "
3947c478bd9Sstevel@tonic-gate 				    "--> Link pointer points to a TD.\n");
3957c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
3967c478bd9Sstevel@tonic-gate 			}
3977c478bd9Sstevel@tonic-gate 		}
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	if (qh.element_ptr == NULL)  {
4027c478bd9Sstevel@tonic-gate 		mdb_printf("        element_ptr = NULL\n");
4037c478bd9Sstevel@tonic-gate 		return (DCMD_ERR);
4047c478bd9Sstevel@tonic-gate 	} else {
4057c478bd9Sstevel@tonic-gate 
4067c478bd9Sstevel@tonic-gate 		/* Inform user if next element is a TD or QH.  */
4077c478bd9Sstevel@tonic-gate 		if (qh.element_ptr & HC_END_OF_LIST)  {
4087c478bd9Sstevel@tonic-gate 			mdb_printf("        "
4097c478bd9Sstevel@tonic-gate 			    "-->Element pointer invalid (terminate bit set)."
4107c478bd9Sstevel@tonic-gate 			    "\n");
4117c478bd9Sstevel@tonic-gate 			return (DCMD_OK);
4127c478bd9Sstevel@tonic-gate 		} else {
4137c478bd9Sstevel@tonic-gate 			if ((qh.element_ptr & HC_QUEUE_HEAD) == HC_QUEUE_HEAD) {
4147c478bd9Sstevel@tonic-gate 				mdb_printf("        "
4157c478bd9Sstevel@tonic-gate 				    "--> Element pointer points to a QH.\n");
4167c478bd9Sstevel@tonic-gate 				/* Should never happen in UHCI implementation */
4177c478bd9Sstevel@tonic-gate 				return (DCMD_ERR);
4187c478bd9Sstevel@tonic-gate 			} else {
4197c478bd9Sstevel@tonic-gate 				mdb_printf("        "
4207c478bd9Sstevel@tonic-gate 				    "--> Element pointer points to a TD.\n");
4217c478bd9Sstevel@tonic-gate 			}
4227c478bd9Sstevel@tonic-gate 		}
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	/*
4267c478bd9Sstevel@tonic-gate 	 * If the user specified the -d (depth) option,
4277c478bd9Sstevel@tonic-gate 	 * dump all TDs linked to this TD via the element_ptr.
4287c478bd9Sstevel@tonic-gate 	 */
4297c478bd9Sstevel@tonic-gate 	if (depth_flag) {
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 		/* Traverse and display all the TDs in the chain */
4327c478bd9Sstevel@tonic-gate 		if (mdb_pwalk_dcmd("uhci_td", "uhci_td", argc, argv,
4337c478bd9Sstevel@tonic-gate 		    (uintptr_t)(TD_VADDR(qh.element_ptr &
4347c478bd9Sstevel@tonic-gate 		    QH_LINK_PTR_MASK))) == -1) {
4357c478bd9Sstevel@tonic-gate 			mdb_warn("failed to walk 'uhci_td'");
4367c478bd9Sstevel@tonic-gate 			return (DCMD_ERR);
4377c478bd9Sstevel@tonic-gate 		}
4387c478bd9Sstevel@tonic-gate 	}
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	return (DCMD_OK);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate /*
4447c478bd9Sstevel@tonic-gate  * Walk a list of UHCI Transaction Descriptors (td's).
4457c478bd9Sstevel@tonic-gate  * Stop at the end of the list, or if the next element in the list is a
4467c478bd9Sstevel@tonic-gate  * queue head (qh).
4477c478bd9Sstevel@tonic-gate  * User must specify the address of the first td to look at.
4487c478bd9Sstevel@tonic-gate  */
4497c478bd9Sstevel@tonic-gate int
4507c478bd9Sstevel@tonic-gate uhci_td_walk_init(mdb_walk_state_t *wsp)
4517c478bd9Sstevel@tonic-gate {
4527c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)  {
4537c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
4547c478bd9Sstevel@tonic-gate 	}
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (uhci_td_t), UM_SLEEP | UM_GC);
4577c478bd9Sstevel@tonic-gate 	wsp->walk_arg = mdb_alloc(sizeof (uhci_state_t), UM_SLEEP | UM_GC);
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	/*
4617c478bd9Sstevel@tonic-gate 	 * Read the uhci_state_t for the instance of uhci
4627c478bd9Sstevel@tonic-gate 	 * using this td address into buf pointed to by walk_arg.
4637c478bd9Sstevel@tonic-gate 	 */
4647c478bd9Sstevel@tonic-gate 	if (find_uhci_statep((void *)wsp->walk_addr, UHCI_TD,
4657c478bd9Sstevel@tonic-gate 	    wsp->walk_arg) != 1) {
4667c478bd9Sstevel@tonic-gate 		mdb_warn("failed to find uhci_statep");
4677c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate /*
4747c478bd9Sstevel@tonic-gate  * At each step, read a TD into our private storage, and then invoke
4757c478bd9Sstevel@tonic-gate  * the callback function.  We terminate when we reach a QH, or
4767c478bd9Sstevel@tonic-gate  * link_ptr is NULL.
4777c478bd9Sstevel@tonic-gate  */
4787c478bd9Sstevel@tonic-gate int
4797c478bd9Sstevel@tonic-gate uhci_td_walk_step(mdb_walk_state_t *wsp)
4807c478bd9Sstevel@tonic-gate {
4817c478bd9Sstevel@tonic-gate 	int status;
4827c478bd9Sstevel@tonic-gate 	uhci_state_t	*uhcip = (uhci_state_t *)wsp->walk_arg;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (uhci_td_t), wsp->walk_addr)
4867c478bd9Sstevel@tonic-gate 	    == -1) {
4877c478bd9Sstevel@tonic-gate 		mdb_warn("failed to read td at %p", wsp->walk_addr);
4887c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
4897c478bd9Sstevel@tonic-gate 	}
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
4927c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	/* Next td. */
4957c478bd9Sstevel@tonic-gate 	wsp->walk_addr = ((uhci_td_t *)wsp->walk_data)->link_ptr;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	/* Check if we're at the last element */
4987c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL || wsp->walk_addr & HC_END_OF_LIST)
4997c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	/* Make sure next element is a TD.  If a QH, stop.  */
5027c478bd9Sstevel@tonic-gate 	if (((((uhci_td_t *)wsp->walk_data)->link_ptr) & HC_QUEUE_HEAD)
5037c478bd9Sstevel@tonic-gate 	    == HC_QUEUE_HEAD)  {
5047c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
5057c478bd9Sstevel@tonic-gate 	}
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	/* Strip terminate etc. bits.  */
5087c478bd9Sstevel@tonic-gate 	wsp->walk_addr &= QH_LINK_PTR_MASK; /* there is no TD_LINK_PTR_MASK */
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)
5117c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	/*
5147c478bd9Sstevel@tonic-gate 	 * Convert link_ptr paddr to vaddr
5157c478bd9Sstevel@tonic-gate 	 * Note: uhcip needed by TD_VADDR macro
5167c478bd9Sstevel@tonic-gate 	 */
5177c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)TD_VADDR(wsp->walk_addr);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	return (status);
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate /*
5237c478bd9Sstevel@tonic-gate  * Walk a list of UHCI Queue Heads (qh's).
5247c478bd9Sstevel@tonic-gate  * Stop at the end of the list, or if the next element in the list is a
5257c478bd9Sstevel@tonic-gate  * Transaction Descriptor (td).
5267c478bd9Sstevel@tonic-gate  * User must specify the address of the first qh to look at.
5277c478bd9Sstevel@tonic-gate  */
5287c478bd9Sstevel@tonic-gate int
5297c478bd9Sstevel@tonic-gate uhci_qh_walk_init(mdb_walk_state_t *wsp)
5307c478bd9Sstevel@tonic-gate {
5317c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)
5327c478bd9Sstevel@tonic-gate 		return (DCMD_USAGE);
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	wsp->walk_data = mdb_alloc(sizeof (queue_head_t), UM_SLEEP | UM_GC);
5357c478bd9Sstevel@tonic-gate 	wsp->walk_arg = mdb_alloc(sizeof (uhci_state_t), UM_SLEEP | UM_GC);
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	/*
5397c478bd9Sstevel@tonic-gate 	 * Read the uhci_state_t for the instance of uhci
5407c478bd9Sstevel@tonic-gate 	 * using this td address into buf pointed to by walk_arg.
5417c478bd9Sstevel@tonic-gate 	 */
5427c478bd9Sstevel@tonic-gate 	if (find_uhci_statep((void *)wsp->walk_addr, UHCI_QH,
5437c478bd9Sstevel@tonic-gate 	    (uhci_state_t *)wsp->walk_arg) != 1) {
5447c478bd9Sstevel@tonic-gate 		mdb_warn("failed to find uhci_statep");
5457c478bd9Sstevel@tonic-gate 		return (WALK_ERR);
5467c478bd9Sstevel@tonic-gate 	}
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	return (WALK_NEXT);
5497c478bd9Sstevel@tonic-gate }
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate /*
5527c478bd9Sstevel@tonic-gate  * At each step, read a QH into our private storage, and then invoke
5537c478bd9Sstevel@tonic-gate  * the callback function.  We terminate when we reach a QH, or
5547c478bd9Sstevel@tonic-gate  * link_ptr is NULL.
5557c478bd9Sstevel@tonic-gate  */
5567c478bd9Sstevel@tonic-gate int
5577c478bd9Sstevel@tonic-gate uhci_qh_walk_step(mdb_walk_state_t *wsp)
5587c478bd9Sstevel@tonic-gate {
5597c478bd9Sstevel@tonic-gate 	int status;
5607c478bd9Sstevel@tonic-gate 	uhci_state_t	*uhcip = (uhci_state_t *)wsp->walk_arg;
5617c478bd9Sstevel@tonic-gate 
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)	/* Should never occur */
5647c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 	if (mdb_vread(wsp->walk_data, sizeof (queue_head_t), wsp->walk_addr)
5677c478bd9Sstevel@tonic-gate 	    == -1) {
5687c478bd9Sstevel@tonic-gate 		mdb_warn("failure reading qh at %p", wsp->walk_addr);
5697c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
5707c478bd9Sstevel@tonic-gate 	}
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
5737c478bd9Sstevel@tonic-gate 	    wsp->walk_cbdata);
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	/* Next QH. */
5767c478bd9Sstevel@tonic-gate 	wsp->walk_addr = ((queue_head_t *)wsp->walk_data)->link_ptr;
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	/* Check if we're at the last element */
5807c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL || wsp->walk_addr & HC_END_OF_LIST)  {
5817c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
5827c478bd9Sstevel@tonic-gate 	}
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	/* Make sure next element is a QH.  If a TD, stop.  */
585*a7317cebSRichard Lowe 	if (((((queue_head_t *)wsp->walk_data)->link_ptr) & HC_QUEUE_HEAD)
586*a7317cebSRichard Lowe 	    != HC_QUEUE_HEAD)  {
5877c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
5887c478bd9Sstevel@tonic-gate 	}
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	/* Strip terminate etc. bits.  */
5917c478bd9Sstevel@tonic-gate 	wsp->walk_addr &= QH_LINK_PTR_MASK;
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	if (wsp->walk_addr == NULL)
5947c478bd9Sstevel@tonic-gate 		return (WALK_DONE);
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	/*
5977c478bd9Sstevel@tonic-gate 	 * Convert link_ptr paddr to vaddr
5987c478bd9Sstevel@tonic-gate 	 * Note: uhcip needed by QH_VADDR macro
5997c478bd9Sstevel@tonic-gate 	 */
6007c478bd9Sstevel@tonic-gate 	wsp->walk_addr = (uintptr_t)QH_VADDR(wsp->walk_addr);
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	return (status);
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate /*
6067c478bd9Sstevel@tonic-gate  * MDB module linkage information:
6077c478bd9Sstevel@tonic-gate  *
6087c478bd9Sstevel@tonic-gate  * We declare a list of structures describing our dcmds, and a function
6097c478bd9Sstevel@tonic-gate  * named _mdb_init to return a pointer to our module information.
6107c478bd9Sstevel@tonic-gate  */
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate static const mdb_dcmd_t dcmds[] = {
6137c478bd9Sstevel@tonic-gate 	{ "uhci_td", ": [-d]", "print UHCI TD", uhci_td, NULL },
6147c478bd9Sstevel@tonic-gate 	{ "uhci_qh", ": [-bd]", "print UHCI QH", uhci_qh, NULL},
6157c478bd9Sstevel@tonic-gate 	{ NULL }
6167c478bd9Sstevel@tonic-gate };
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate static const mdb_walker_t walkers[] = {
6207c478bd9Sstevel@tonic-gate 	{ "uhci_td", "walk list of UHCI TD structures",
6217c478bd9Sstevel@tonic-gate 	    uhci_td_walk_init, uhci_td_walk_step, NULL,
6227c478bd9Sstevel@tonic-gate 	    NULL },
6237c478bd9Sstevel@tonic-gate 	{ "uhci_qh", "walk list of UHCI QH structures",
6247c478bd9Sstevel@tonic-gate 	    uhci_qh_walk_init, uhci_qh_walk_step, NULL,
6257c478bd9Sstevel@tonic-gate 	    NULL },
6267c478bd9Sstevel@tonic-gate 	{ NULL }
6277c478bd9Sstevel@tonic-gate };
6287c478bd9Sstevel@tonic-gate 
6297c478bd9Sstevel@tonic-gate static const mdb_modinfo_t modinfo = {
6307c478bd9Sstevel@tonic-gate 	MDB_API_VERSION, dcmds, walkers
6317c478bd9Sstevel@tonic-gate };
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate const mdb_modinfo_t *
6357c478bd9Sstevel@tonic-gate _mdb_init(void)
6367c478bd9Sstevel@tonic-gate {
6377c478bd9Sstevel@tonic-gate 	return (&modinfo);
6387c478bd9Sstevel@tonic-gate }
639