1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*0Sstevel@tonic-gate * Use is subject to license terms.
25*0Sstevel@tonic-gate */
26*0Sstevel@tonic-gate
27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
28*0Sstevel@tonic-gate
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate * nx1394.c
31*0Sstevel@tonic-gate * 1394 Services Layer Nexus Support Routines
32*0Sstevel@tonic-gate * Routines in this file implement nexus bus_ops.
33*0Sstevel@tonic-gate */
34*0Sstevel@tonic-gate
35*0Sstevel@tonic-gate #include <sys/conf.h>
36*0Sstevel@tonic-gate #include <sys/ddi.h>
37*0Sstevel@tonic-gate #include <sys/modctl.h>
38*0Sstevel@tonic-gate #include <sys/sunddi.h>
39*0Sstevel@tonic-gate #include <sys/cmn_err.h>
40*0Sstevel@tonic-gate #include <sys/types.h>
41*0Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
42*0Sstevel@tonic-gate
43*0Sstevel@tonic-gate #include <sys/tnf_probe.h>
44*0Sstevel@tonic-gate
45*0Sstevel@tonic-gate #include <sys/1394/t1394.h>
46*0Sstevel@tonic-gate #include <sys/1394/s1394.h>
47*0Sstevel@tonic-gate #include <sys/1394/h1394.h>
48*0Sstevel@tonic-gate
49*0Sstevel@tonic-gate static int nx1394_dma_allochdl(dev_info_t *dip, dev_info_t *rdip,
50*0Sstevel@tonic-gate ddi_dma_attr_t *attr, int (*waitfnp)(caddr_t), caddr_t arg,
51*0Sstevel@tonic-gate ddi_dma_handle_t *handlep);
52*0Sstevel@tonic-gate
53*0Sstevel@tonic-gate static int nx1394_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op,
54*0Sstevel@tonic-gate void *arg, void *result);
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate static int nx1394_get_event_cookie(dev_info_t *dip, dev_info_t *rdip,
57*0Sstevel@tonic-gate char *name, ddi_eventcookie_t *event_cookiep);
58*0Sstevel@tonic-gate
59*0Sstevel@tonic-gate static int nx1394_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
60*0Sstevel@tonic-gate ddi_eventcookie_t eventhdl, void (*callback)(), void *arg,
61*0Sstevel@tonic-gate ddi_callback_id_t *cb_id);
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gate static int nx1394_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id);
64*0Sstevel@tonic-gate
65*0Sstevel@tonic-gate static int nx1394_post_event(dev_info_t *dip, dev_info_t *rdip,
66*0Sstevel@tonic-gate ddi_eventcookie_t eventhdl, void *impl_data);
67*0Sstevel@tonic-gate
68*0Sstevel@tonic-gate struct bus_ops nx1394_busops = {
69*0Sstevel@tonic-gate BUSO_REV,
70*0Sstevel@tonic-gate nullbusmap, /* bus_map */
71*0Sstevel@tonic-gate NULL, /* bus_get_intrspec */
72*0Sstevel@tonic-gate NULL, /* bus_add_intrspec */
73*0Sstevel@tonic-gate NULL, /* bus_remove_intrspec */
74*0Sstevel@tonic-gate i_ddi_map_fault, /* XXXX bus_map_fault */
75*0Sstevel@tonic-gate ddi_dma_map, /* bus_dma_map */
76*0Sstevel@tonic-gate nx1394_dma_allochdl,
77*0Sstevel@tonic-gate ddi_dma_freehdl,
78*0Sstevel@tonic-gate ddi_dma_bindhdl,
79*0Sstevel@tonic-gate ddi_dma_unbindhdl,
80*0Sstevel@tonic-gate ddi_dma_flush,
81*0Sstevel@tonic-gate ddi_dma_win,
82*0Sstevel@tonic-gate ddi_dma_mctl, /* bus_dma_ctl */
83*0Sstevel@tonic-gate nx1394_bus_ctl, /* bus_ctl */
84*0Sstevel@tonic-gate ddi_bus_prop_op, /* bus_prop_op */
85*0Sstevel@tonic-gate nx1394_get_event_cookie, /* (*bus_get_eventcookie() */
86*0Sstevel@tonic-gate nx1394_add_eventcall, /* (*bus_add_eventcall)(); */
87*0Sstevel@tonic-gate nx1394_remove_eventcall, /* (*bus_remove_eventcall)(); */
88*0Sstevel@tonic-gate nx1394_post_event, /* (*bus_post_event)(); */
89*0Sstevel@tonic-gate 0, /* (*interrupt control)(); */
90*0Sstevel@tonic-gate 0, /* (*bus_config)(); */
91*0Sstevel@tonic-gate 0, /* (*bus_unconfig)(); */
92*0Sstevel@tonic-gate 0, /* (*bus_fm_init)(); */
93*0Sstevel@tonic-gate 0, /* (*bus_fm_fini)(); */
94*0Sstevel@tonic-gate 0, /* (*bus_fm_access_enter)(); */
95*0Sstevel@tonic-gate 0, /* (*bus_fm_access_exit)(); */
96*0Sstevel@tonic-gate 0, /* (*bus_power)(); */
97*0Sstevel@tonic-gate i_ddi_intr_ops /* (*bus_intr_op)(); */
98*0Sstevel@tonic-gate };
99*0Sstevel@tonic-gate
100*0Sstevel@tonic-gate /*
101*0Sstevel@tonic-gate * removal/insertion/reset events
102*0Sstevel@tonic-gate */
103*0Sstevel@tonic-gate #define NX1394_EVENT_TAG_HOT_REMOVAL 0
104*0Sstevel@tonic-gate #define NX1394_EVENT_TAG_HOT_INSERTION 1
105*0Sstevel@tonic-gate #define NX1394_EVENT_TAG_BUS_RESET 2
106*0Sstevel@tonic-gate
107*0Sstevel@tonic-gate static ndi_event_definition_t nx1394_event_defs[] = {
108*0Sstevel@tonic-gate {NX1394_EVENT_TAG_HOT_REMOVAL, DDI_DEVI_REMOVE_EVENT, EPL_KERNEL,
109*0Sstevel@tonic-gate NDI_EVENT_POST_TO_TGT},
110*0Sstevel@tonic-gate {NX1394_EVENT_TAG_HOT_INSERTION, DDI_DEVI_INSERT_EVENT, EPL_KERNEL,
111*0Sstevel@tonic-gate NDI_EVENT_POST_TO_TGT},
112*0Sstevel@tonic-gate {NX1394_EVENT_TAG_BUS_RESET, DDI_DEVI_BUS_RESET_EVENT, EPL_KERNEL,
113*0Sstevel@tonic-gate NDI_EVENT_POST_TO_ALL},
114*0Sstevel@tonic-gate };
115*0Sstevel@tonic-gate
116*0Sstevel@tonic-gate #define NX1394_N_EVENTS \
117*0Sstevel@tonic-gate (sizeof (nx1394_event_defs) / sizeof (ndi_event_definition_t))
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gate static ndi_event_set_t nx1394_events = {
120*0Sstevel@tonic-gate NDI_EVENTS_REV1, NX1394_N_EVENTS, nx1394_event_defs
121*0Sstevel@tonic-gate };
122*0Sstevel@tonic-gate
123*0Sstevel@tonic-gate /*
124*0Sstevel@tonic-gate * nx1394_bus_ctl()
125*0Sstevel@tonic-gate * This routine implements nexus bus ctl operations. Of importance are
126*0Sstevel@tonic-gate * DDI_CTLOPS_REPORTDEV, DDI_CTLOPS_INITCHILD, DDI_CTLOPS_UNINITCHILD
127*0Sstevel@tonic-gate * and DDI_CTLOPS_POWER. For DDI_CTLOPS_INITCHILD, it tries to lookup
128*0Sstevel@tonic-gate * reg property on the child node and builds and sets the name
129*0Sstevel@tonic-gate * (name is of the form GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA], where
130*0Sstevel@tonic-gate * GGGGGGGGGGGGGGGG is the GUID and AAAAAAAAAAAA is the optional unit
131*0Sstevel@tonic-gate * address).
132*0Sstevel@tonic-gate */
133*0Sstevel@tonic-gate static int
nx1394_bus_ctl(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t op,void * arg,void * result)134*0Sstevel@tonic-gate nx1394_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
135*0Sstevel@tonic-gate void *result)
136*0Sstevel@tonic-gate {
137*0Sstevel@tonic-gate int status;
138*0Sstevel@tonic-gate
139*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_bus_ctl_enter, S1394_TNF_SL_NEXUS_STACK, "");
140*0Sstevel@tonic-gate
141*0Sstevel@tonic-gate switch (op) {
142*0Sstevel@tonic-gate case DDI_CTLOPS_REPORTDEV: {
143*0Sstevel@tonic-gate dev_info_t *pdip = ddi_get_parent(rdip);
144*0Sstevel@tonic-gate cmn_err(CE_CONT, "?%s%d at %s%d",
145*0Sstevel@tonic-gate ddi_node_name(rdip), ddi_get_instance(rdip),
146*0Sstevel@tonic-gate ddi_node_name(pdip), ddi_get_instance(pdip));
147*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
148*0Sstevel@tonic-gate "");
149*0Sstevel@tonic-gate return (DDI_SUCCESS);
150*0Sstevel@tonic-gate }
151*0Sstevel@tonic-gate
152*0Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD: {
153*0Sstevel@tonic-gate dev_info_t *ocdip, *cdip = (dev_info_t *)arg;
154*0Sstevel@tonic-gate dev_info_t *pdip = ddi_get_parent(cdip);
155*0Sstevel@tonic-gate int reglen, i;
156*0Sstevel@tonic-gate uint32_t *regptr;
157*0Sstevel@tonic-gate char addr[MAXNAMELEN];
158*0Sstevel@tonic-gate
159*0Sstevel@tonic-gate TNF_PROBE_1(nx1394_bus_ctl_init_child,
160*0Sstevel@tonic-gate S1394_TNF_SL_HOTPLUG_STACK, "", tnf_opaque, dip, cdip);
161*0Sstevel@tonic-gate
162*0Sstevel@tonic-gate i = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
163*0Sstevel@tonic-gate DDI_PROP_DONTPASS, "reg", (int **)®ptr,
164*0Sstevel@tonic-gate (uint_t *)®len);
165*0Sstevel@tonic-gate
166*0Sstevel@tonic-gate if (i != DDI_PROP_SUCCESS) {
167*0Sstevel@tonic-gate cmn_err(CE_NOTE, "!%s(%d): \"reg\" property not found",
168*0Sstevel@tonic-gate ddi_node_name(cdip), ddi_get_instance(cdip));
169*0Sstevel@tonic-gate TNF_PROBE_2(nx1394_bus_ctl,
170*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg,
171*0Sstevel@tonic-gate "Reg property not found", tnf_int, reason, i);
172*0Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
173*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op,
174*0Sstevel@tonic-gate "initchild");
175*0Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED);
176*0Sstevel@tonic-gate }
177*0Sstevel@tonic-gate
178*0Sstevel@tonic-gate ASSERT(reglen != 0);
179*0Sstevel@tonic-gate
180*0Sstevel@tonic-gate /*
181*0Sstevel@tonic-gate * addr is of the format GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA]
182*0Sstevel@tonic-gate */
183*0Sstevel@tonic-gate if (regptr[2] || regptr[3]) {
184*0Sstevel@tonic-gate (void) sprintf(addr, "%08x%08x,%04x%08x", regptr[0],
185*0Sstevel@tonic-gate regptr[1], regptr[2], regptr[3]);
186*0Sstevel@tonic-gate } else {
187*0Sstevel@tonic-gate (void) sprintf(addr, "%08x%08x", regptr[0], regptr[1]);
188*0Sstevel@tonic-gate }
189*0Sstevel@tonic-gate ddi_prop_free(regptr);
190*0Sstevel@tonic-gate ddi_set_name_addr(cdip, addr);
191*0Sstevel@tonic-gate
192*0Sstevel@tonic-gate /*
193*0Sstevel@tonic-gate * Check for a node with the same name & addr as the current
194*0Sstevel@tonic-gate * node. If such a node exists, return failure.
195*0Sstevel@tonic-gate */
196*0Sstevel@tonic-gate if ((ocdip = ndi_devi_find(pdip, ddi_node_name(cdip), addr)) !=
197*0Sstevel@tonic-gate NULL && ocdip != cdip) {
198*0Sstevel@tonic-gate cmn_err(CE_NOTE,
199*0Sstevel@tonic-gate "!%s(%d): Duplicate dev_info node found %s@%s",
200*0Sstevel@tonic-gate ddi_node_name(cdip), ddi_get_instance(cdip),
201*0Sstevel@tonic-gate ddi_node_name(ocdip), addr);
202*0Sstevel@tonic-gate TNF_PROBE_1(nx1394_bus_ctl,
203*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg,
204*0Sstevel@tonic-gate "Duplicate nodes");
205*0Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
206*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op,
207*0Sstevel@tonic-gate "initchild");
208*0Sstevel@tonic-gate ddi_set_name_addr(cdip, NULL);
209*0Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED);
210*0Sstevel@tonic-gate }
211*0Sstevel@tonic-gate
212*0Sstevel@tonic-gate /*
213*0Sstevel@tonic-gate * If HAL (parent dip) has "active-dma-flush" property, then
214*0Sstevel@tonic-gate * add property to child as well. Workaround for active
215*0Sstevel@tonic-gate * context flushing bug in Schizo rev 2.1 and 2.2.
216*0Sstevel@tonic-gate */
217*0Sstevel@tonic-gate if (ddi_prop_exists(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
218*0Sstevel@tonic-gate "active-dma-flush") != 0) {
219*0Sstevel@tonic-gate status = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
220*0Sstevel@tonic-gate "active-dma-flush", 1);
221*0Sstevel@tonic-gate if (status != NDI_SUCCESS) {
222*0Sstevel@tonic-gate cmn_err(CE_NOTE, "!%s(%d): Unable to add "
223*0Sstevel@tonic-gate "\"active-dma-flush\" property",
224*0Sstevel@tonic-gate ddi_node_name(cdip),
225*0Sstevel@tonic-gate ddi_get_instance(cdip));
226*0Sstevel@tonic-gate TNF_PROBE_1(nx1394_bus_ctl,
227*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_string,
228*0Sstevel@tonic-gate msg, "Unable to add \"active-dma-flush\" "
229*0Sstevel@tonic-gate "property");
230*0Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
231*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string,
232*0Sstevel@tonic-gate op, "initchild");
233*0Sstevel@tonic-gate ddi_set_name_addr(cdip, NULL);
234*0Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED);
235*0Sstevel@tonic-gate }
236*0Sstevel@tonic-gate }
237*0Sstevel@tonic-gate
238*0Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
239*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op, "initchild");
240*0Sstevel@tonic-gate return (DDI_SUCCESS);
241*0Sstevel@tonic-gate }
242*0Sstevel@tonic-gate
243*0Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD: {
244*0Sstevel@tonic-gate ddi_prop_remove_all((dev_info_t *)arg);
245*0Sstevel@tonic-gate ddi_set_name_addr((dev_info_t *)arg, NULL);
246*0Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
247*0Sstevel@tonic-gate "", tnf_string, op, "uninitchild");
248*0Sstevel@tonic-gate return (DDI_SUCCESS);
249*0Sstevel@tonic-gate }
250*0Sstevel@tonic-gate
251*0Sstevel@tonic-gate case DDI_CTLOPS_IOMIN: {
252*0Sstevel@tonic-gate status = ddi_ctlops(dip, rdip, op, arg, result);
253*0Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
254*0Sstevel@tonic-gate "", tnf_string, op, "iomin");
255*0Sstevel@tonic-gate return (status);
256*0Sstevel@tonic-gate }
257*0Sstevel@tonic-gate
258*0Sstevel@tonic-gate case DDI_CTLOPS_POWER: {
259*0Sstevel@tonic-gate return (DDI_SUCCESS);
260*0Sstevel@tonic-gate }
261*0Sstevel@tonic-gate
262*0Sstevel@tonic-gate /*
263*0Sstevel@tonic-gate * These ops correspond to functions that "shouldn't" be called
264*0Sstevel@tonic-gate * by a 1394 client driver.
265*0Sstevel@tonic-gate */
266*0Sstevel@tonic-gate case DDI_CTLOPS_DMAPMAPC:
267*0Sstevel@tonic-gate case DDI_CTLOPS_REPORTINT:
268*0Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE:
269*0Sstevel@tonic-gate case DDI_CTLOPS_NREGS:
270*0Sstevel@tonic-gate case DDI_CTLOPS_SIDDEV:
271*0Sstevel@tonic-gate case DDI_CTLOPS_SLAVEONLY:
272*0Sstevel@tonic-gate case DDI_CTLOPS_AFFINITY:
273*0Sstevel@tonic-gate case DDI_CTLOPS_POKE:
274*0Sstevel@tonic-gate case DDI_CTLOPS_PEEK: {
275*0Sstevel@tonic-gate cmn_err(CE_CONT, "!%s(%d): invalid op (%d) from %s(%d)",
276*0Sstevel@tonic-gate ddi_node_name(dip), ddi_get_instance(dip),
277*0Sstevel@tonic-gate op, ddi_node_name(rdip), ddi_get_instance(rdip));
278*0Sstevel@tonic-gate TNF_PROBE_2(nx1394_bus_ctl, S1394_TNF_SL_NEXUS_ERROR, "",
279*0Sstevel@tonic-gate tnf_string, msg, "invalid op", tnf_int, op, op);
280*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
281*0Sstevel@tonic-gate "");
282*0Sstevel@tonic-gate return (DDI_FAILURE);
283*0Sstevel@tonic-gate }
284*0Sstevel@tonic-gate
285*0Sstevel@tonic-gate /*
286*0Sstevel@tonic-gate * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up
287*0Sstevel@tonic-gate */
288*0Sstevel@tonic-gate default: {
289*0Sstevel@tonic-gate status = ddi_ctlops(dip, rdip, op, arg, result);
290*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
291*0Sstevel@tonic-gate "");
292*0Sstevel@tonic-gate return (status);
293*0Sstevel@tonic-gate }
294*0Sstevel@tonic-gate }
295*0Sstevel@tonic-gate }
296*0Sstevel@tonic-gate
297*0Sstevel@tonic-gate /*
298*0Sstevel@tonic-gate * nx1394_dma_allochdl()
299*0Sstevel@tonic-gate * Merges the ddi_dma_attr_t passed in by the target (using
300*0Sstevel@tonic-gate * ddi_dma_alloc_handle() call) with that of the hal and passes the alloc
301*0Sstevel@tonic-gate * handle request up the device by calling ddi_dma_allochdl().
302*0Sstevel@tonic-gate */
303*0Sstevel@tonic-gate static int
nx1394_dma_allochdl(dev_info_t * dip,dev_info_t * rdip,ddi_dma_attr_t * attr,int (* waitfnp)(caddr_t),caddr_t arg,ddi_dma_handle_t * handlep)304*0Sstevel@tonic-gate nx1394_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr,
305*0Sstevel@tonic-gate int (*waitfnp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
306*0Sstevel@tonic-gate {
307*0Sstevel@tonic-gate s1394_hal_t *hal;
308*0Sstevel@tonic-gate ddi_dma_attr_t *hal_attr;
309*0Sstevel@tonic-gate int status;
310*0Sstevel@tonic-gate
311*0Sstevel@tonic-gate _NOTE(SCHEME_PROTECTS_DATA("unique (per thread)", ddi_dma_attr_t))
312*0Sstevel@tonic-gate
313*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_dma_allochdl_enter, S1394_TNF_SL_NEXUS_STACK,
314*0Sstevel@tonic-gate "");
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gate /*
317*0Sstevel@tonic-gate * If hal calls ddi_dma_alloc_handle, dip == rdip == hal dip.
318*0Sstevel@tonic-gate * Unfortunately, we cannot verify this (by way of looking up for hal
319*0Sstevel@tonic-gate * dip) here because h1394_attach() may happen much later.
320*0Sstevel@tonic-gate */
321*0Sstevel@tonic-gate if (dip != rdip) {
322*0Sstevel@tonic-gate hal = s1394_dip_to_hal(ddi_get_parent(rdip));
323*0Sstevel@tonic-gate ASSERT(hal);
324*0Sstevel@tonic-gate hal_attr = &hal->halinfo.dma_attr;
325*0Sstevel@tonic-gate ASSERT(hal_attr);
326*0Sstevel@tonic-gate ddi_dma_attr_merge(attr, hal_attr);
327*0Sstevel@tonic-gate }
328*0Sstevel@tonic-gate status = ddi_dma_allochdl(dip, rdip, attr, waitfnp, arg, handlep);
329*0Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_dma_allochdl_exit, S1394_TNF_SL_NEXUS_STACK,
330*0Sstevel@tonic-gate "", tnf_int, status, status);
331*0Sstevel@tonic-gate return (status);
332*0Sstevel@tonic-gate }
333*0Sstevel@tonic-gate
334*0Sstevel@tonic-gate /*
335*0Sstevel@tonic-gate * nx1394_get_event_cookie()
336*0Sstevel@tonic-gate * Called when a child node calls ddi_get_eventcookie().
337*0Sstevel@tonic-gate * Returns event cookie corresponding to event "name".
338*0Sstevel@tonic-gate */
339*0Sstevel@tonic-gate static int
nx1394_get_event_cookie(dev_info_t * dip,dev_info_t * rdip,char * name,ddi_eventcookie_t * event_cookiep)340*0Sstevel@tonic-gate nx1394_get_event_cookie(dev_info_t *dip, dev_info_t *rdip, char *name,
341*0Sstevel@tonic-gate ddi_eventcookie_t *event_cookiep)
342*0Sstevel@tonic-gate {
343*0Sstevel@tonic-gate int ret;
344*0Sstevel@tonic-gate s1394_hal_t *hal;
345*0Sstevel@tonic-gate
346*0Sstevel@tonic-gate TNF_PROBE_1_DEBUG(nx1394_get_event_cookie_enter,
347*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, name, name);
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gate hal = s1394_dip_to_hal(dip);
350*0Sstevel@tonic-gate ASSERT(hal);
351*0Sstevel@tonic-gate
352*0Sstevel@tonic-gate ret = ndi_event_retrieve_cookie(hal->hal_ndi_event_hdl,
353*0Sstevel@tonic-gate rdip, name, event_cookiep, 0);
354*0Sstevel@tonic-gate
355*0Sstevel@tonic-gate TNF_PROBE_4_DEBUG(nx1394_get_event_cookie_exit,
356*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip, (void *)dip,
357*0Sstevel@tonic-gate tnf_opaque, requestor_dip, (void *)rdip, tnf_string, event_name,
358*0Sstevel@tonic-gate name, tnf_int, request_status, ret);
359*0Sstevel@tonic-gate
360*0Sstevel@tonic-gate return (ret);
361*0Sstevel@tonic-gate
362*0Sstevel@tonic-gate }
363*0Sstevel@tonic-gate
364*0Sstevel@tonic-gate /*
365*0Sstevel@tonic-gate * nx1394_add_eventcall()
366*0Sstevel@tonic-gate * This gets called when a child node calls ddi_add_eventcall(). Registers
367*0Sstevel@tonic-gate * the specified callback for the requested event cookie with the ndi
368*0Sstevel@tonic-gate * event framework.
369*0Sstevel@tonic-gate * dip is the hal dip. This routine calls ndi_event_add_callback(),
370*0Sstevel@tonic-gate * allowing requests for events we don't generate to pass up the tree.
371*0Sstevel@tonic-gate */
372*0Sstevel@tonic-gate static int
nx1394_add_eventcall(dev_info_t * dip,dev_info_t * rdip,ddi_eventcookie_t cookie,void (* callback)(),void * arg,ddi_callback_id_t * cb_id)373*0Sstevel@tonic-gate nx1394_add_eventcall(dev_info_t *dip, dev_info_t *rdip,
374*0Sstevel@tonic-gate ddi_eventcookie_t cookie, void (*callback)(), void *arg,
375*0Sstevel@tonic-gate ddi_callback_id_t *cb_id)
376*0Sstevel@tonic-gate {
377*0Sstevel@tonic-gate int ret;
378*0Sstevel@tonic-gate s1394_hal_t *hal;
379*0Sstevel@tonic-gate #if defined(DEBUG)
380*0Sstevel@tonic-gate char *event_name = NULL;
381*0Sstevel@tonic-gate #endif
382*0Sstevel@tonic-gate
383*0Sstevel@tonic-gate hal = s1394_dip_to_hal(dip);
384*0Sstevel@tonic-gate ASSERT(hal);
385*0Sstevel@tonic-gate
386*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_add_eventcall_enter, S1394_TNF_SL_NEXUS_STACK,
387*0Sstevel@tonic-gate "");
388*0Sstevel@tonic-gate
389*0Sstevel@tonic-gate ret = ndi_event_add_callback(hal->hal_ndi_event_hdl, rdip, cookie,
390*0Sstevel@tonic-gate callback, arg, NDI_NOSLEEP, cb_id);
391*0Sstevel@tonic-gate #if defined(DEBUG)
392*0Sstevel@tonic-gate event_name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie);
393*0Sstevel@tonic-gate if (event_name == NULL)
394*0Sstevel@tonic-gate event_name = "";
395*0Sstevel@tonic-gate #endif
396*0Sstevel@tonic-gate TNF_PROBE_4_DEBUG(nx1394_add_eventcall_exit, S1394_TNF_SL_NEXUS_STACK,
397*0Sstevel@tonic-gate "", tnf_opaque, parent_dip, (void *)dip, tnf_opaque, requestor_dip,
398*0Sstevel@tonic-gate (void *)rdip, tnf_string, event_name, event_name, tnf_int,
399*0Sstevel@tonic-gate request_status, ret);
400*0Sstevel@tonic-gate
401*0Sstevel@tonic-gate return (ret);
402*0Sstevel@tonic-gate }
403*0Sstevel@tonic-gate
404*0Sstevel@tonic-gate /*
405*0Sstevel@tonic-gate * nx1394_remove_eventcall()
406*0Sstevel@tonic-gate * Called as a result of a child node calling ddi_remove_eventcall().
407*0Sstevel@tonic-gate * Unregisters the callback corresponding to the callback id passed in.
408*0Sstevel@tonic-gate */
409*0Sstevel@tonic-gate static int
nx1394_remove_eventcall(dev_info_t * dip,ddi_callback_id_t cb_id)410*0Sstevel@tonic-gate nx1394_remove_eventcall(dev_info_t *dip, ddi_callback_id_t cb_id)
411*0Sstevel@tonic-gate {
412*0Sstevel@tonic-gate int ret;
413*0Sstevel@tonic-gate s1394_hal_t *hal;
414*0Sstevel@tonic-gate ddi_eventcookie_t cookie;
415*0Sstevel@tonic-gate #if defined(DEBUG)
416*0Sstevel@tonic-gate char *event_name = NULL;
417*0Sstevel@tonic-gate #endif
418*0Sstevel@tonic-gate
419*0Sstevel@tonic-gate ASSERT(cb_id);
420*0Sstevel@tonic-gate cookie = ((ndi_event_callbacks_t *)cb_id)->ndi_evtcb_cookie;
421*0Sstevel@tonic-gate
422*0Sstevel@tonic-gate hal = s1394_dip_to_hal(dip);
423*0Sstevel@tonic-gate ASSERT(hal);
424*0Sstevel@tonic-gate
425*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_remove_eventcall_enter,
426*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "");
427*0Sstevel@tonic-gate
428*0Sstevel@tonic-gate ret = ndi_event_remove_callback(hal->hal_ndi_event_hdl, cb_id);
429*0Sstevel@tonic-gate
430*0Sstevel@tonic-gate #if defined(DEBUG)
431*0Sstevel@tonic-gate event_name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie);
432*0Sstevel@tonic-gate if (event_name == NULL)
433*0Sstevel@tonic-gate event_name = "";
434*0Sstevel@tonic-gate
435*0Sstevel@tonic-gate TNF_PROBE_4_DEBUG(nx1394_remove_eventcall_exit,
436*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip, (void *)dip,
437*0Sstevel@tonic-gate tnf_opaque, callback_id, (void *)cb_id, tnf_string, event_name,
438*0Sstevel@tonic-gate event_name, tnf_int, request_status, ret);
439*0Sstevel@tonic-gate #endif
440*0Sstevel@tonic-gate
441*0Sstevel@tonic-gate return (ret);
442*0Sstevel@tonic-gate }
443*0Sstevel@tonic-gate
444*0Sstevel@tonic-gate /*
445*0Sstevel@tonic-gate * nx1394_post_event()
446*0Sstevel@tonic-gate * Called when a child node calls ddi_post_event. If the event is one of
447*0Sstevel@tonic-gate * the events supported by us (bus reset/insert/remove, for now), builds
448*0Sstevel@tonic-gate * a t1394_localinfo_t structure and calls ndi_event_run_callbacks(). This
449*0Sstevel@tonic-gate * will result in all registered callbacks being invoked with
450*0Sstevel@tonic-gate * t1394_localinfo_t as the impl_data. (see ddi_add_eventcall for callback
451*0Sstevel@tonic-gate * arguments.) If the event is not defined by us, the request is
452*0Sstevel@tonic-gate * propagated up the device tree by calling ndi_post_event().
453*0Sstevel@tonic-gate */
454*0Sstevel@tonic-gate static int
nx1394_post_event(dev_info_t * dip,dev_info_t * rdip,ddi_eventcookie_t cookie,void * impl_data)455*0Sstevel@tonic-gate nx1394_post_event(dev_info_t *dip, dev_info_t *rdip, ddi_eventcookie_t cookie,
456*0Sstevel@tonic-gate void *impl_data)
457*0Sstevel@tonic-gate {
458*0Sstevel@tonic-gate int ret;
459*0Sstevel@tonic-gate char *name;
460*0Sstevel@tonic-gate s1394_hal_t *hal;
461*0Sstevel@tonic-gate t1394_localinfo_t localinfo;
462*0Sstevel@tonic-gate
463*0Sstevel@tonic-gate hal = s1394_dip_to_hal(dip);
464*0Sstevel@tonic-gate ASSERT(hal);
465*0Sstevel@tonic-gate
466*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_post_event_enter, S1394_TNF_SL_NEXUS_STACK,
467*0Sstevel@tonic-gate "");
468*0Sstevel@tonic-gate
469*0Sstevel@tonic-gate name = ndi_event_cookie_to_name(hal->hal_ndi_event_hdl, cookie);
470*0Sstevel@tonic-gate /* name is NULL if we don't generate the event */
471*0Sstevel@tonic-gate if (name != NULL) {
472*0Sstevel@tonic-gate
473*0Sstevel@tonic-gate mutex_enter(&hal->topology_tree_mutex);
474*0Sstevel@tonic-gate localinfo.bus_generation = hal->generation_count;
475*0Sstevel@tonic-gate localinfo.local_nodeID = hal->node_id;
476*0Sstevel@tonic-gate mutex_exit(&hal->topology_tree_mutex);
477*0Sstevel@tonic-gate impl_data = &localinfo;
478*0Sstevel@tonic-gate
479*0Sstevel@tonic-gate ret = ndi_event_run_callbacks(hal->hal_ndi_event_hdl,
480*0Sstevel@tonic-gate rdip, cookie, impl_data);
481*0Sstevel@tonic-gate
482*0Sstevel@tonic-gate TNF_PROBE_4_DEBUG(nx1394_post_event_exit,
483*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_opaque, parent_dip,
484*0Sstevel@tonic-gate (void *)dip, tnf_opaque, requestor_dip, (void *)rdip,
485*0Sstevel@tonic-gate tnf_string, event_name, name, tnf_int, request_status, ret);
486*0Sstevel@tonic-gate return (ret);
487*0Sstevel@tonic-gate
488*0Sstevel@tonic-gate } else {
489*0Sstevel@tonic-gate ret = ndi_post_event(ddi_get_parent(dip), rdip, cookie,
490*0Sstevel@tonic-gate impl_data);
491*0Sstevel@tonic-gate TNF_PROBE_2_DEBUG(nx1394_post_event_exit,
492*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "", tnf_string, msg,
493*0Sstevel@tonic-gate "Not our event", tnf_int, ret, ret);
494*0Sstevel@tonic-gate return (ret);
495*0Sstevel@tonic-gate }
496*0Sstevel@tonic-gate }
497*0Sstevel@tonic-gate
498*0Sstevel@tonic-gate /*
499*0Sstevel@tonic-gate * nx1394_define_events()
500*0Sstevel@tonic-gate * Allocates event handle for the hal dip and binds event set to it.
501*0Sstevel@tonic-gate */
502*0Sstevel@tonic-gate int
nx1394_define_events(s1394_hal_t * hal)503*0Sstevel@tonic-gate nx1394_define_events(s1394_hal_t *hal)
504*0Sstevel@tonic-gate {
505*0Sstevel@tonic-gate int ret;
506*0Sstevel@tonic-gate
507*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_define_events_enter, S1394_TNF_SL_NEXUS_STACK,
508*0Sstevel@tonic-gate "");
509*0Sstevel@tonic-gate
510*0Sstevel@tonic-gate /* get event handle */
511*0Sstevel@tonic-gate ret = ndi_event_alloc_hdl(hal->halinfo.dip, hal->halinfo.hw_interrupt,
512*0Sstevel@tonic-gate &hal->hal_ndi_event_hdl, NDI_SLEEP);
513*0Sstevel@tonic-gate if (ret != NDI_SUCCESS) {
514*0Sstevel@tonic-gate TNF_PROBE_1(nx1394_define_events_alloc_fail,
515*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret);
516*0Sstevel@tonic-gate } else {
517*0Sstevel@tonic-gate /* and bind to it */
518*0Sstevel@tonic-gate ret = ndi_event_bind_set(hal->hal_ndi_event_hdl, &nx1394_events,
519*0Sstevel@tonic-gate NDI_SLEEP);
520*0Sstevel@tonic-gate if (ret != NDI_SUCCESS) {
521*0Sstevel@tonic-gate TNF_PROBE_1(nx1394_define_events_bind_fail,
522*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret);
523*0Sstevel@tonic-gate (void) ndi_event_free_hdl(hal->hal_ndi_event_hdl);
524*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_define_events_exit,
525*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "");
526*0Sstevel@tonic-gate return (DDI_FAILURE);
527*0Sstevel@tonic-gate }
528*0Sstevel@tonic-gate }
529*0Sstevel@tonic-gate
530*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_define_events_exit, S1394_TNF_SL_NEXUS_STACK,
531*0Sstevel@tonic-gate "");
532*0Sstevel@tonic-gate
533*0Sstevel@tonic-gate return (DDI_SUCCESS);
534*0Sstevel@tonic-gate }
535*0Sstevel@tonic-gate
536*0Sstevel@tonic-gate /*
537*0Sstevel@tonic-gate * nx1394_undefine_events()
538*0Sstevel@tonic-gate * Unbinds event set bound to the hal and frees the event handle.
539*0Sstevel@tonic-gate */
540*0Sstevel@tonic-gate void
nx1394_undefine_events(s1394_hal_t * hal)541*0Sstevel@tonic-gate nx1394_undefine_events(s1394_hal_t *hal)
542*0Sstevel@tonic-gate {
543*0Sstevel@tonic-gate int ret;
544*0Sstevel@tonic-gate
545*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_undefine_events_enter,
546*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "");
547*0Sstevel@tonic-gate
548*0Sstevel@tonic-gate ret = ndi_event_unbind_set(hal->hal_ndi_event_hdl, &nx1394_events,
549*0Sstevel@tonic-gate NDI_SLEEP);
550*0Sstevel@tonic-gate if (ret != NDI_SUCCESS) {
551*0Sstevel@tonic-gate TNF_PROBE_1(nx1394_undefine_events_unbind_fail,
552*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret);
553*0Sstevel@tonic-gate } else {
554*0Sstevel@tonic-gate ret = ndi_event_free_hdl(hal->hal_ndi_event_hdl);
555*0Sstevel@tonic-gate if (ret != NDI_SUCCESS) {
556*0Sstevel@tonic-gate TNF_PROBE_1(nx1394_undefine_events_free_hdl_fail,
557*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_ERROR, "", tnf_int, ret, ret);
558*0Sstevel@tonic-gate }
559*0Sstevel@tonic-gate }
560*0Sstevel@tonic-gate
561*0Sstevel@tonic-gate TNF_PROBE_0_DEBUG(nx1394_undefine_events_exit,
562*0Sstevel@tonic-gate S1394_TNF_SL_NEXUS_STACK, "");
563*0Sstevel@tonic-gate }
564