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 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 26*cd21e7c5SGarrett D'Amore /* 27*cd21e7c5SGarrett D'Amore * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved. 28*cd21e7c5SGarrett D'Amore */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * nx1394.c 327c478bd9Sstevel@tonic-gate * 1394 Services Layer Nexus Support Routines 337c478bd9Sstevel@tonic-gate * Routines in this file implement nexus bus_ops. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <sys/conf.h> 377c478bd9Sstevel@tonic-gate #include <sys/ddi.h> 387c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 397c478bd9Sstevel@tonic-gate #include <sys/sunddi.h> 407c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 417c478bd9Sstevel@tonic-gate #include <sys/types.h> 427c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #include <sys/tnf_probe.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #include <sys/1394/t1394.h> 477c478bd9Sstevel@tonic-gate #include <sys/1394/s1394.h> 487c478bd9Sstevel@tonic-gate #include <sys/1394/h1394.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate static int nx1394_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, 517c478bd9Sstevel@tonic-gate ddi_dma_attr_t *attr, int (*waitfnp)(caddr_t), caddr_t arg, 527c478bd9Sstevel@tonic-gate ddi_dma_handle_t *handlep); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static int nx1394_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, 557c478bd9Sstevel@tonic-gate void *arg, void *result); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate static int nx1394_get_event_cookie(dev_info_t *dip, dev_info_t *rdip, 587c478bd9Sstevel@tonic-gate char *name, ddi_eventcookie_t *event_cookiep); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate static int nx1394_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 617c478bd9Sstevel@tonic-gate ddi_eventcookie_t eventhdl, void (*callback)(), void *arg, 627c478bd9Sstevel@tonic-gate ddi_callback_id_t *cb_id); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate static int nx1394_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id); 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static int nx1394_post_event(dev_info_t *dip, dev_info_t *rdip, 677c478bd9Sstevel@tonic-gate ddi_eventcookie_t eventhdl, void *impl_data); 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate struct bus_ops nx1394_busops = { 707c478bd9Sstevel@tonic-gate BUSO_REV, 717c478bd9Sstevel@tonic-gate nullbusmap, /* bus_map */ 727c478bd9Sstevel@tonic-gate NULL, /* bus_get_intrspec */ 737c478bd9Sstevel@tonic-gate NULL, /* bus_add_intrspec */ 747c478bd9Sstevel@tonic-gate NULL, /* bus_remove_intrspec */ 757c478bd9Sstevel@tonic-gate i_ddi_map_fault, /* XXXX bus_map_fault */ 76*cd21e7c5SGarrett D'Amore NULL, /* bus_dma_map */ 777c478bd9Sstevel@tonic-gate nx1394_dma_allochdl, 787c478bd9Sstevel@tonic-gate ddi_dma_freehdl, 797c478bd9Sstevel@tonic-gate ddi_dma_bindhdl, 807c478bd9Sstevel@tonic-gate ddi_dma_unbindhdl, 817c478bd9Sstevel@tonic-gate ddi_dma_flush, 827c478bd9Sstevel@tonic-gate ddi_dma_win, 837c478bd9Sstevel@tonic-gate ddi_dma_mctl, /* bus_dma_ctl */ 847c478bd9Sstevel@tonic-gate nx1394_bus_ctl, /* bus_ctl */ 857c478bd9Sstevel@tonic-gate ddi_bus_prop_op, /* bus_prop_op */ 867c478bd9Sstevel@tonic-gate nx1394_get_event_cookie, /* (*bus_get_eventcookie() */ 877c478bd9Sstevel@tonic-gate nx1394_add_eventcall, /* (*bus_add_eventcall)(); */ 887c478bd9Sstevel@tonic-gate nx1394_remove_eventcall, /* (*bus_remove_eventcall)(); */ 897c478bd9Sstevel@tonic-gate nx1394_post_event, /* (*bus_post_event)(); */ 907c478bd9Sstevel@tonic-gate 0, /* (*interrupt control)(); */ 917c478bd9Sstevel@tonic-gate 0, /* (*bus_config)(); */ 927c478bd9Sstevel@tonic-gate 0, /* (*bus_unconfig)(); */ 937c478bd9Sstevel@tonic-gate 0, /* (*bus_fm_init)(); */ 947c478bd9Sstevel@tonic-gate 0, /* (*bus_fm_fini)(); */ 957c478bd9Sstevel@tonic-gate 0, /* (*bus_fm_access_enter)(); */ 967c478bd9Sstevel@tonic-gate 0, /* (*bus_fm_access_exit)(); */ 977c478bd9Sstevel@tonic-gate 0, /* (*bus_power)(); */ 987c478bd9Sstevel@tonic-gate i_ddi_intr_ops /* (*bus_intr_op)(); */ 997c478bd9Sstevel@tonic-gate }; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * removal/insertion/reset events 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate #define NX1394_EVENT_TAG_HOT_REMOVAL 0 1057c478bd9Sstevel@tonic-gate #define NX1394_EVENT_TAG_HOT_INSERTION 1 1067c478bd9Sstevel@tonic-gate #define NX1394_EVENT_TAG_BUS_RESET 2 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static ndi_event_definition_t nx1394_event_defs[] = { 1097c478bd9Sstevel@tonic-gate {NX1394_EVENT_TAG_HOT_REMOVAL, DDI_DEVI_REMOVE_EVENT, EPL_KERNEL, 1107c478bd9Sstevel@tonic-gate NDI_EVENT_POST_TO_TGT}, 1117c478bd9Sstevel@tonic-gate {NX1394_EVENT_TAG_HOT_INSERTION, DDI_DEVI_INSERT_EVENT, EPL_KERNEL, 1127c478bd9Sstevel@tonic-gate NDI_EVENT_POST_TO_TGT}, 1137c478bd9Sstevel@tonic-gate {NX1394_EVENT_TAG_BUS_RESET, DDI_DEVI_BUS_RESET_EVENT, EPL_KERNEL, 1147c478bd9Sstevel@tonic-gate NDI_EVENT_POST_TO_ALL}, 1157c478bd9Sstevel@tonic-gate }; 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate #define NX1394_N_EVENTS \ 1187c478bd9Sstevel@tonic-gate (sizeof (nx1394_event_defs) / sizeof (ndi_event_definition_t)) 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate static ndi_event_set_t nx1394_events = { 1217c478bd9Sstevel@tonic-gate NDI_EVENTS_REV1, NX1394_N_EVENTS, nx1394_event_defs 1227c478bd9Sstevel@tonic-gate }; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * nx1394_bus_ctl() 1267c478bd9Sstevel@tonic-gate * This routine implements nexus bus ctl operations. Of importance are 1277c478bd9Sstevel@tonic-gate * DDI_CTLOPS_REPORTDEV, DDI_CTLOPS_INITCHILD, DDI_CTLOPS_UNINITCHILD 1287c478bd9Sstevel@tonic-gate * and DDI_CTLOPS_POWER. For DDI_CTLOPS_INITCHILD, it tries to lookup 1297c478bd9Sstevel@tonic-gate * reg property on the child node and builds and sets the name 1307c478bd9Sstevel@tonic-gate * (name is of the form GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA], where 1317c478bd9Sstevel@tonic-gate * GGGGGGGGGGGGGGGG is the GUID and AAAAAAAAAAAA is the optional unit 1327c478bd9Sstevel@tonic-gate * address). 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate static int 1357c478bd9Sstevel@tonic-gate nx1394_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg, 1367c478bd9Sstevel@tonic-gate void *result) 1377c478bd9Sstevel@tonic-gate { 1387c478bd9Sstevel@tonic-gate int status; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_bus_ctl_enter, S1394_TNF_SL_NEXUS_STACK, ""); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate switch (op) { 1437c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REPORTDEV: { 1447c478bd9Sstevel@tonic-gate dev_info_t *pdip = ddi_get_parent(rdip); 1457c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?%s%d at %s%d", 1467c478bd9Sstevel@tonic-gate ddi_node_name(rdip), ddi_get_instance(rdip), 1477c478bd9Sstevel@tonic-gate ddi_node_name(pdip), ddi_get_instance(pdip)); 1487c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK, 1497c478bd9Sstevel@tonic-gate ""); 1507c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 1517c478bd9Sstevel@tonic-gate } 1527c478bd9Sstevel@tonic-gate 1537c478bd9Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD: { 1547c478bd9Sstevel@tonic-gate dev_info_t *ocdip, *cdip = (dev_info_t *)arg; 1557c478bd9Sstevel@tonic-gate dev_info_t *pdip = ddi_get_parent(cdip); 1567c478bd9Sstevel@tonic-gate int reglen, i; 1577c478bd9Sstevel@tonic-gate uint32_t *regptr; 1587c478bd9Sstevel@tonic-gate char addr[MAXNAMELEN]; 1597c478bd9Sstevel@tonic-gate 1607c478bd9Sstevel@tonic-gate TNF_PROBE_1(nx1394_bus_ctl_init_child, 1617c478bd9Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_opaque, dip, cdip); 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate i = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 1647c478bd9Sstevel@tonic-gate DDI_PROP_DONTPASS, "reg", (int **)®ptr, 1657c478bd9Sstevel@tonic-gate (uint_t *)®len); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate if (i != DDI_PROP_SUCCESS) { 1687c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!%s(%d): \"reg\" property not found", 1697c478bd9Sstevel@tonic-gate ddi_node_name(cdip), ddi_get_instance(cdip)); 1707c478bd9Sstevel@tonic-gate TNF_PROBE_2(nx1394_bus_ctl, 1717c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg, 1727c478bd9Sstevel@tonic-gate "Reg property not found", tnf_int, reason, i); 1737c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, 1747c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op, 1757c478bd9Sstevel@tonic-gate "initchild"); 1767c478bd9Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate ASSERT(reglen != 0); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* 1827c478bd9Sstevel@tonic-gate * addr is of the format GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA] 1837c478bd9Sstevel@tonic-gate */ 1847c478bd9Sstevel@tonic-gate if (regptr[2] || regptr[3]) { 1857c478bd9Sstevel@tonic-gate (void) sprintf(addr, "%08x%08x,%04x%08x", regptr[0], 1867c478bd9Sstevel@tonic-gate regptr[1], regptr[2], regptr[3]); 1877c478bd9Sstevel@tonic-gate } else { 1887c478bd9Sstevel@tonic-gate (void) sprintf(addr, "%08x%08x", regptr[0], regptr[1]); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate ddi_prop_free(regptr); 1917c478bd9Sstevel@tonic-gate ddi_set_name_addr(cdip, addr); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate /* 1947c478bd9Sstevel@tonic-gate * Check for a node with the same name & addr as the current 1957c478bd9Sstevel@tonic-gate * node. If such a node exists, return failure. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate if ((ocdip = ndi_devi_find(pdip, ddi_node_name(cdip), addr)) != 1987c478bd9Sstevel@tonic-gate NULL && ocdip != cdip) { 1997c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, 2007c478bd9Sstevel@tonic-gate "!%s(%d): Duplicate dev_info node found %s@%s", 2017c478bd9Sstevel@tonic-gate ddi_node_name(cdip), ddi_get_instance(cdip), 2027c478bd9Sstevel@tonic-gate ddi_node_name(ocdip), addr); 2037c478bd9Sstevel@tonic-gate TNF_PROBE_1(nx1394_bus_ctl, 2047c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg, 2057c478bd9Sstevel@tonic-gate "Duplicate nodes"); 2067c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, 2077c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op, 2087c478bd9Sstevel@tonic-gate "initchild"); 2097c478bd9Sstevel@tonic-gate ddi_set_name_addr(cdip, NULL); 2107c478bd9Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate /* 2147c478bd9Sstevel@tonic-gate * If HAL (parent dip) has "active-dma-flush" property, then 2157c478bd9Sstevel@tonic-gate * add property to child as well. Workaround for active 2167c478bd9Sstevel@tonic-gate * context flushing bug in Schizo rev 2.1 and 2.2. 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate if (ddi_prop_exists(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS, 2197c478bd9Sstevel@tonic-gate "active-dma-flush") != 0) { 2207c478bd9Sstevel@tonic-gate status = ndi_prop_update_int(DDI_DEV_T_NONE, cdip, 2217c478bd9Sstevel@tonic-gate "active-dma-flush", 1); 2227c478bd9Sstevel@tonic-gate if (status != NDI_SUCCESS) { 2237c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "!%s(%d): Unable to add " 2247c478bd9Sstevel@tonic-gate "\"active-dma-flush\" property", 2257c478bd9Sstevel@tonic-gate ddi_node_name(cdip), 2267c478bd9Sstevel@tonic-gate ddi_get_instance(cdip)); 2277c478bd9Sstevel@tonic-gate TNF_PROBE_1(nx1394_bus_ctl, 2287c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, 2297c478bd9Sstevel@tonic-gate msg, "Unable to add \"active-dma-flush\" " 2307c478bd9Sstevel@tonic-gate "property"); 2317c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, 2327c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, 2337c478bd9Sstevel@tonic-gate op, "initchild"); 2347c478bd9Sstevel@tonic-gate ddi_set_name_addr(cdip, NULL); 2357c478bd9Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED); 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, 2407c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op, "initchild"); 2417c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD: { 2457c478bd9Sstevel@tonic-gate ddi_prop_remove_all((dev_info_t *)arg); 2467c478bd9Sstevel@tonic-gate ddi_set_name_addr((dev_info_t *)arg, NULL); 2477c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK, 2487c478bd9Sstevel@tonic-gate "", tnf_string, op, "uninitchild"); 2497c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate case DDI_CTLOPS_IOMIN: { 2537c478bd9Sstevel@tonic-gate status = ddi_ctlops(dip, rdip, op, arg, result); 2547c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK, 2557c478bd9Sstevel@tonic-gate "", tnf_string, op, "iomin"); 2567c478bd9Sstevel@tonic-gate return (status); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate case DDI_CTLOPS_POWER: { 2607c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * These ops correspond to functions that "shouldn't" be called 2657c478bd9Sstevel@tonic-gate * by a 1394 client driver. 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate case DDI_CTLOPS_DMAPMAPC: 2687c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REPORTINT: 2697c478bd9Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE: 2707c478bd9Sstevel@tonic-gate case DDI_CTLOPS_NREGS: 2717c478bd9Sstevel@tonic-gate case DDI_CTLOPS_SIDDEV: 2727c478bd9Sstevel@tonic-gate case DDI_CTLOPS_SLAVEONLY: 2737c478bd9Sstevel@tonic-gate case DDI_CTLOPS_AFFINITY: 2747c478bd9Sstevel@tonic-gate case DDI_CTLOPS_POKE: 2757c478bd9Sstevel@tonic-gate case DDI_CTLOPS_PEEK: { 2767c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "!%s(%d): invalid op (%d) from %s(%d)", 2777c478bd9Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip), 2787c478bd9Sstevel@tonic-gate op, ddi_node_name(rdip), ddi_get_instance(rdip)); 2797c478bd9Sstevel@tonic-gate TNF_PROBE_2(nx1394_bus_ctl, S1394_TNF_SL_NEXUS_ERROR, "", 2807c478bd9Sstevel@tonic-gate tnf_string, msg, "invalid op", tnf_int, op, op); 2817c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK, 2827c478bd9Sstevel@tonic-gate ""); 2837c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up 2887c478bd9Sstevel@tonic-gate */ 2897c478bd9Sstevel@tonic-gate default: { 2907c478bd9Sstevel@tonic-gate status = ddi_ctlops(dip, rdip, op, arg, result); 2917c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK, 2927c478bd9Sstevel@tonic-gate ""); 2937c478bd9Sstevel@tonic-gate return (status); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate /* 2997c478bd9Sstevel@tonic-gate * nx1394_dma_allochdl() 3007c478bd9Sstevel@tonic-gate * Merges the ddi_dma_attr_t passed in by the target (using 3017c478bd9Sstevel@tonic-gate * ddi_dma_alloc_handle() call) with that of the hal and passes the alloc 3027c478bd9Sstevel@tonic-gate * handle request up the device by calling ddi_dma_allochdl(). 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate static int 3057c478bd9Sstevel@tonic-gate nx1394_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, 3067c478bd9Sstevel@tonic-gate int (*waitfnp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 3097c478bd9Sstevel@tonic-gate ddi_dma_attr_t *hal_attr; 3107c478bd9Sstevel@tonic-gate int status; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique (per thread)", ddi_dma_attr_t)) 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_dma_allochdl_enter, S1394_TNF_SL_NEXUS_STACK, 3157c478bd9Sstevel@tonic-gate ""); 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* 3187c478bd9Sstevel@tonic-gate * If hal calls ddi_dma_alloc_handle, dip == rdip == hal dip. 3197c478bd9Sstevel@tonic-gate * Unfortunately, we cannot verify this (by way of looking up for hal 3207c478bd9Sstevel@tonic-gate * dip) here because h1394_attach() may happen much later. 3217c478bd9Sstevel@tonic-gate */ 3227c478bd9Sstevel@tonic-gate if (dip != rdip) { 3237c478bd9Sstevel@tonic-gate hal = s1394_dip_to_hal(ddi_get_parent(rdip)); 3247c478bd9Sstevel@tonic-gate ASSERT(hal); 3257c478bd9Sstevel@tonic-gate hal_attr = &hal->halinfo.dma_attr; 3267c478bd9Sstevel@tonic-gate ASSERT(hal_attr); 3277c478bd9Sstevel@tonic-gate ddi_dma_attr_merge(attr, hal_attr); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate status = ddi_dma_allochdl(dip, rdip, attr, waitfnp, arg, handlep); 3307c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_dma_allochdl_exit, S1394_TNF_SL_NEXUS_STACK, 3317c478bd9Sstevel@tonic-gate "", tnf_int, status, status); 3327c478bd9Sstevel@tonic-gate return (status); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * nx1394_get_event_cookie() 3377c478bd9Sstevel@tonic-gate * Called when a child node calls ddi_get_eventcookie(). 3387c478bd9Sstevel@tonic-gate * Returns event cookie corresponding to event "name". 3397c478bd9Sstevel@tonic-gate */ 3407c478bd9Sstevel@tonic-gate static int 3417c478bd9Sstevel@tonic-gate nx1394_get_event_cookie(dev_info_t *dip, dev_info_t *rdip, char *name, 3427c478bd9Sstevel@tonic-gate ddi_eventcookie_t *event_cookiep) 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate int ret; 3457c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_get_event_cookie_enter, 3487c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, name, name); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate hal = s1394_dip_to_hal(dip); 3517c478bd9Sstevel@tonic-gate ASSERT(hal); 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate ret = ndi_event_retrieve_cookie(hal->hal_ndi_event_hdl, 3547c478bd9Sstevel@tonic-gate rdip, name, event_cookiep, 0); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate TNF_PROBE_4_DEBUG(nx1394_get_event_cookie_exit, 3577c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip, (void *)dip, 3587c478bd9Sstevel@tonic-gate tnf_opaque, requestor_dip, (void *)rdip, tnf_string, event_name, 3597c478bd9Sstevel@tonic-gate name, tnf_int, request_status, ret); 3607c478bd9Sstevel@tonic-gate 3617c478bd9Sstevel@tonic-gate return (ret); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* 3667c478bd9Sstevel@tonic-gate * nx1394_add_eventcall() 3677c478bd9Sstevel@tonic-gate * This gets called when a child node calls ddi_add_eventcall(). Registers 3687c478bd9Sstevel@tonic-gate * the specified callback for the requested event cookie with the ndi 3697c478bd9Sstevel@tonic-gate * event framework. 3707c478bd9Sstevel@tonic-gate * dip is the hal dip. This routine calls ndi_event_add_callback(), 3717c478bd9Sstevel@tonic-gate * allowing requests for events we don't generate to pass up the tree. 3727c478bd9Sstevel@tonic-gate */ 3737c478bd9Sstevel@tonic-gate static int 3747c478bd9Sstevel@tonic-gate nx1394_add_eventcall(dev_info_t *dip, dev_info_t *rdip, 3757c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie, void (*callback)(), void *arg, 3767c478bd9Sstevel@tonic-gate ddi_callback_id_t *cb_id) 3777c478bd9Sstevel@tonic-gate { 3787c478bd9Sstevel@tonic-gate int ret; 3797c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 3807c478bd9Sstevel@tonic-gate #if defined(DEBUG) 3817c478bd9Sstevel@tonic-gate char *event_name = NULL; 3827c478bd9Sstevel@tonic-gate #endif 3837c478bd9Sstevel@tonic-gate 3847c478bd9Sstevel@tonic-gate hal = s1394_dip_to_hal(dip); 3857c478bd9Sstevel@tonic-gate ASSERT(hal); 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_add_eventcall_enter, S1394_TNF_SL_NEXUS_STACK, 3887c478bd9Sstevel@tonic-gate ""); 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate ret = ndi_event_add_callback(hal->hal_ndi_event_hdl, rdip, cookie, 3917c478bd9Sstevel@tonic-gate callback, arg, NDI_NOSLEEP, cb_id); 3927c478bd9Sstevel@tonic-gate #if defined(DEBUG) 3937c478bd9Sstevel@tonic-gate event_name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie); 3947c478bd9Sstevel@tonic-gate if (event_name == NULL) 3957c478bd9Sstevel@tonic-gate event_name = ""; 3967c478bd9Sstevel@tonic-gate #endif 3977c478bd9Sstevel@tonic-gate TNF_PROBE_4_DEBUG(nx1394_add_eventcall_exit, S1394_TNF_SL_NEXUS_STACK, 3987c478bd9Sstevel@tonic-gate "", tnf_opaque, parent_dip, (void *)dip, tnf_opaque, requestor_dip, 3997c478bd9Sstevel@tonic-gate (void *)rdip, tnf_string, event_name, event_name, tnf_int, 4007c478bd9Sstevel@tonic-gate request_status, ret); 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate return (ret); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate /* 4067c478bd9Sstevel@tonic-gate * nx1394_remove_eventcall() 4077c478bd9Sstevel@tonic-gate * Called as a result of a child node calling ddi_remove_eventcall(). 4087c478bd9Sstevel@tonic-gate * Unregisters the callback corresponding to the callback id passed in. 4097c478bd9Sstevel@tonic-gate */ 4107c478bd9Sstevel@tonic-gate static int 4117c478bd9Sstevel@tonic-gate nx1394_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id) 4127c478bd9Sstevel@tonic-gate { 4137c478bd9Sstevel@tonic-gate int ret; 4147c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 4157c478bd9Sstevel@tonic-gate ddi_eventcookie_t cookie; 4167c478bd9Sstevel@tonic-gate #if defined(DEBUG) 4177c478bd9Sstevel@tonic-gate char *event_name = NULL; 4187c478bd9Sstevel@tonic-gate #endif 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate ASSERT(cb_id); 4217c478bd9Sstevel@tonic-gate cookie = ((ndi_event_callbacks_t *)cb_id)->ndi_evtcb_cookie; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate hal = s1394_dip_to_hal(dip); 4247c478bd9Sstevel@tonic-gate ASSERT(hal); 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_remove_eventcall_enter, 4277c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, ""); 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate ret = ndi_event_remove_callback(hal->hal_ndi_event_hdl, cb_id); 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate #if defined(DEBUG) 4327c478bd9Sstevel@tonic-gate event_name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie); 4337c478bd9Sstevel@tonic-gate if (event_name == NULL) 4347c478bd9Sstevel@tonic-gate event_name = ""; 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate TNF_PROBE_4_DEBUG(nx1394_remove_eventcall_exit, 4377c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip, (void *)dip, 4387c478bd9Sstevel@tonic-gate tnf_opaque, callback_id, (void *)cb_id, tnf_string, event_name, 4397c478bd9Sstevel@tonic-gate event_name, tnf_int, request_status, ret); 4407c478bd9Sstevel@tonic-gate #endif 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate return (ret); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate /* 4467c478bd9Sstevel@tonic-gate * nx1394_post_event() 4477c478bd9Sstevel@tonic-gate * Called when a child node calls ddi_post_event. If the event is one of 4487c478bd9Sstevel@tonic-gate * the events supported by us (bus reset/insert/remove, for now), builds 4497c478bd9Sstevel@tonic-gate * a t1394_localinfo_t structure and calls ndi_event_run_callbacks(). This 4507c478bd9Sstevel@tonic-gate * will result in all registered callbacks being invoked with 4517c478bd9Sstevel@tonic-gate * t1394_localinfo_t as the impl_data. (see ddi_add_eventcall for callback 4527c478bd9Sstevel@tonic-gate * arguments.) If the event is not defined by us, the request is 4537c478bd9Sstevel@tonic-gate * propagated up the device tree by calling ndi_post_event(). 4547c478bd9Sstevel@tonic-gate */ 4557c478bd9Sstevel@tonic-gate static int 4567c478bd9Sstevel@tonic-gate nx1394_post_event(dev_info_t *dip, dev_info_t *rdip, ddi_eventcookie_t cookie, 4577c478bd9Sstevel@tonic-gate void *impl_data) 4587c478bd9Sstevel@tonic-gate { 4597c478bd9Sstevel@tonic-gate int ret; 4607c478bd9Sstevel@tonic-gate char *name; 4617c478bd9Sstevel@tonic-gate s1394_hal_t *hal; 4627c478bd9Sstevel@tonic-gate t1394_localinfo_t localinfo; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate hal = s1394_dip_to_hal(dip); 4657c478bd9Sstevel@tonic-gate ASSERT(hal); 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_post_event_enter, S1394_TNF_SL_NEXUS_STACK, 4687c478bd9Sstevel@tonic-gate ""); 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie); 4717c478bd9Sstevel@tonic-gate /* name is NULL if we don't generate the event */ 4727c478bd9Sstevel@tonic-gate if (name != NULL) { 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate mutex_enter(&hal->topology_tree_mutex); 4757c478bd9Sstevel@tonic-gate localinfo.bus_generation = hal->generation_count; 4767c478bd9Sstevel@tonic-gate localinfo.local_nodeID = hal->node_id; 4777c478bd9Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex); 4787c478bd9Sstevel@tonic-gate impl_data = &localinfo; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate ret = ndi_event_run_callbacks(hal->hal_ndi_event_hdl, 4817c478bd9Sstevel@tonic-gate rdip, cookie, impl_data); 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate TNF_PROBE_4_DEBUG(nx1394_post_event_exit, 4847c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip, 4857c478bd9Sstevel@tonic-gate (void *)dip, tnf_opaque, requestor_dip, (void *)rdip, 4867c478bd9Sstevel@tonic-gate tnf_string, event_name, name, tnf_int, request_status, ret); 4877c478bd9Sstevel@tonic-gate return (ret); 4887c478bd9Sstevel@tonic-gate 4897c478bd9Sstevel@tonic-gate } else { 4907c478bd9Sstevel@tonic-gate ret = ndi_post_event(ddi_get_parent(dip), rdip, cookie, 4917c478bd9Sstevel@tonic-gate impl_data); 4927c478bd9Sstevel@tonic-gate TNF_PROBE_2_DEBUG(nx1394_post_event_exit, 4937c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, msg, 4947c478bd9Sstevel@tonic-gate "Not our event", tnf_int, ret, ret); 4957c478bd9Sstevel@tonic-gate return (ret); 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate } 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * nx1394_define_events() 5017c478bd9Sstevel@tonic-gate * Allocates event handle for the hal dip and binds event set to it. 5027c478bd9Sstevel@tonic-gate */ 5037c478bd9Sstevel@tonic-gate int 5047c478bd9Sstevel@tonic-gate nx1394_define_events(s1394_hal_t *hal) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate int ret; 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_define_events_enter, S1394_TNF_SL_NEXUS_STACK, 5097c478bd9Sstevel@tonic-gate ""); 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate /* get event handle */ 5127c478bd9Sstevel@tonic-gate ret = ndi_event_alloc_hdl(hal->halinfo.dip, hal->halinfo.hw_interrupt, 5137c478bd9Sstevel@tonic-gate &hal->hal_ndi_event_hdl, NDI_SLEEP); 5147c478bd9Sstevel@tonic-gate if (ret != NDI_SUCCESS) { 5157c478bd9Sstevel@tonic-gate TNF_PROBE_1(nx1394_define_events_alloc_fail, 5167c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret); 5177c478bd9Sstevel@tonic-gate } else { 5187c478bd9Sstevel@tonic-gate /* and bind to it */ 5197c478bd9Sstevel@tonic-gate ret = ndi_event_bind_set(hal->hal_ndi_event_hdl, &nx1394_events, 5207c478bd9Sstevel@tonic-gate NDI_SLEEP); 5217c478bd9Sstevel@tonic-gate if (ret != NDI_SUCCESS) { 5227c478bd9Sstevel@tonic-gate TNF_PROBE_1(nx1394_define_events_bind_fail, 5237c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret); 5247c478bd9Sstevel@tonic-gate (void) ndi_event_free_hdl(hal->hal_ndi_event_hdl); 5257c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_define_events_exit, 5267c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, ""); 5277c478bd9Sstevel@tonic-gate return (DDI_FAILURE); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_define_events_exit, S1394_TNF_SL_NEXUS_STACK, 5327c478bd9Sstevel@tonic-gate ""); 5337c478bd9Sstevel@tonic-gate 5347c478bd9Sstevel@tonic-gate return (DDI_SUCCESS); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate /* 5387c478bd9Sstevel@tonic-gate * nx1394_undefine_events() 5397c478bd9Sstevel@tonic-gate * Unbinds event set bound to the hal and frees the event handle. 5407c478bd9Sstevel@tonic-gate */ 5417c478bd9Sstevel@tonic-gate void 5427c478bd9Sstevel@tonic-gate nx1394_undefine_events(s1394_hal_t *hal) 5437c478bd9Sstevel@tonic-gate { 5447c478bd9Sstevel@tonic-gate int ret; 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_undefine_events_enter, 5477c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, ""); 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate ret = ndi_event_unbind_set(hal->hal_ndi_event_hdl, &nx1394_events, 5507c478bd9Sstevel@tonic-gate NDI_SLEEP); 5517c478bd9Sstevel@tonic-gate if (ret != NDI_SUCCESS) { 5527c478bd9Sstevel@tonic-gate TNF_PROBE_1(nx1394_undefine_events_unbind_fail, 5537c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret); 5547c478bd9Sstevel@tonic-gate } else { 5557c478bd9Sstevel@tonic-gate ret = ndi_event_free_hdl(hal->hal_ndi_event_hdl); 5567c478bd9Sstevel@tonic-gate if (ret != NDI_SUCCESS) { 5577c478bd9Sstevel@tonic-gate TNF_PROBE_1(nx1394_undefine_events_free_hdl_fail, 5587c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret); 5597c478bd9Sstevel@tonic-gate } 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_undefine_events_exit, 5637c478bd9Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, ""); 5647c478bd9Sstevel@tonic-gate } 565