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