xref: /illumos-gate/usr/src/uts/common/io/1394/targets/av1394/av1394.c (revision 9a5d73e03cd3312ddb571a748c40a63c58bd66e5)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * av1394 driver
29  */
30 
31 #include <sys/param.h>
32 #include <sys/errno.h>
33 #include <sys/cred.h>
34 #include <sys/conf.h>
35 #include <sys/modctl.h>
36 #include <sys/stat.h>
37 #include <sys/ddi.h>
38 #include <sys/sunddi.h>
39 
40 #include <sys/1394/targets/av1394/av1394_impl.h>
41 
42 /* DDI/DKI entry points */
43 static int	av1394_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
44 static int	av1394_attach(dev_info_t *, ddi_attach_cmd_t);
45 static int	av1394_detach(dev_info_t *, ddi_detach_cmd_t);
46 static int 	av1394_open(dev_t *, int, int, cred_t *);
47 static int	av1394_close(dev_t, int, int, cred_t *);
48 static int	av1394_read(dev_t, struct uio *, cred_t *);
49 static int	av1394_write(dev_t, struct uio *, cred_t *);
50 static int	av1394_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
51 static int	av1394_devmap(dev_t, devmap_cookie_t, offset_t, size_t,
52 		size_t *, uint_t);
53 static int	av1394_poll(dev_t, short, int, short *, struct pollhead **);
54 
55 /* configuration routines */
56 static void	av1394_cleanup(av1394_inst_t *, int);
57 static int	av1394_t1394_attach(av1394_inst_t *, dev_info_t *);
58 static void	av1394_t1394_detach(av1394_inst_t *);
59 static int	av1394_add_events(av1394_inst_t *);
60 static void	av1394_remove_events(av1394_inst_t *);
61 
62 /* CPR */
63 static int	av1394_cpr_suspend(av1394_inst_t *);
64 static int 	av1394_cpr_resume(av1394_inst_t *);
65 
66 /* callbacks */
67 static void	av1394_bus_reset(dev_info_t *, ddi_eventcookie_t, void *,
68 		void *);
69 static void	av1394_disconnect(dev_info_t *, ddi_eventcookie_t, void *,
70 		void *);
71 static void	av1394_reconnect(dev_info_t *, ddi_eventcookie_t, void *,
72 		void *);
73 
74 extern struct mod_ops mod_driverops;
75 
76 struct cb_ops av1394_cb_ops = {
77 	av1394_open,		/* open  */
78 	av1394_close,		/* close */
79 	nulldev,		/* strategy */
80 	nulldev,		/* print */
81 	nulldev,		/* dump */
82 	av1394_read,		/* read */
83 	av1394_write,		/* write */
84 	av1394_ioctl,		/* ioctl */
85 	av1394_devmap,		/* devmap */
86 	nulldev,		/* mmap */
87 	nulldev,		/* segmap */
88 	av1394_poll,		/* poll */
89 	ddi_prop_op,		/* cb_prop_op */
90 	NULL,			/* streamtab  */
91 	D_MP | D_NEW | D_HOTPLUG | D_DEVMAP
92 };
93 
94 static struct dev_ops av1394_ops = {
95 	DEVO_REV,		/* devo_rev */
96 	0,			/* refcnt  */
97 	av1394_getinfo,		/* getinfo */
98 	nulldev,		/* identify */
99 	nulldev,		/* probe */
100 	av1394_attach,		/* attach */
101 	av1394_detach,		/* detach */
102 	nodev,			/* reset */
103 	&av1394_cb_ops,		/* driver operations */
104 	NULL,			/* bus operations */
105 	NULL,			/* power */
106 	ddi_quiesce_not_supported,	/* devo_quiesce */
107 };
108 
109 static struct modldrv av1394_modldrv =	{
110 	&mod_driverops,
111 	"IEEE 1394 AV driver",
112 	&av1394_ops
113 };
114 
115 static struct modlinkage av1394_modlinkage = {
116 	MODREV_1,
117 	&av1394_modldrv,
118 	NULL,
119 };
120 
121 static void *av1394_statep;
122 
123 #ifndef NPROBE
124 extern int tnf_mod_load(void);
125 extern int tnf_mod_unload(struct modlinkage *mlp);
126 #endif
127 
128 #define	AV1394_INST2STATE(inst)	(ddi_get_soft_state(av1394_statep, inst))
129 #define	AV1394_DEV2STATE(dev)	\
130 		(ddi_get_soft_state(av1394_statep, AV1394_DEV2INST(dev)))
131 
132 #define	AV1394_TNF_ENTER(func)	\
133 	TNF_PROBE_0_DEBUG(func##_enter, AV1394_TNF_INST_STACK, "");
134 
135 #define	AV1394_TNF_EXIT(func)	\
136 	TNF_PROBE_0_DEBUG(func##_exit, AV1394_TNF_INST_STACK, "");
137 
138 /*
139  *
140  * --- DDI/DKI entry points
141  *
142  */
143 int
144 _init(void)
145 {
146 	int    error;
147 
148 #ifndef NPROBE
149 	(void) tnf_mod_load();
150 #endif
151 	error = ddi_soft_state_init(&av1394_statep, sizeof (av1394_inst_t), 1);
152 	if (error != 0) {
153 #ifndef NPROBE
154 		(void) tnf_mod_unload(&av1394_modlinkage);
155 #endif
156 		return (error);
157 	}
158 
159 	if ((error = mod_install(&av1394_modlinkage)) != 0) {
160 		ddi_soft_state_fini(&av1394_statep);
161 #ifndef NPROBE
162 		(void) tnf_mod_unload(&av1394_modlinkage);
163 #endif
164 	}
165 
166 	return (error);
167 }
168 
169 int
170 _fini(void)
171 {
172 	int    error;
173 
174 	if ((error = mod_remove(&av1394_modlinkage)) == 0) {
175 		ddi_soft_state_fini(&av1394_statep);
176 #ifndef NPROBE
177 		(void) tnf_mod_unload(&av1394_modlinkage);
178 #endif
179 	}
180 
181 	return (error);
182 }
183 
184 int
185 _info(struct modinfo *modinfop)
186 {
187 	return (mod_info(&av1394_modlinkage, modinfop));
188 }
189 
190 /*
191  * attach
192  */
193 static int
194 av1394_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
195 {
196 	int		instance = ddi_get_instance(dip);
197 	av1394_inst_t	*avp;
198 
199 	AV1394_TNF_ENTER(av1394_attach);
200 
201 	switch (cmd) {
202 	case DDI_ATTACH:
203 		break;
204 	case DDI_RESUME:
205 		if ((avp = AV1394_INST2STATE(instance)) == NULL) {
206 			return (DDI_FAILURE);
207 		}
208 		return (av1394_cpr_resume(avp));
209 	default:
210 		AV1394_TNF_EXIT(av1394_attach);
211 		return (DDI_FAILURE);
212 	}
213 
214 	if (ddi_soft_state_zalloc(av1394_statep, instance) != 0) {
215 		TNF_PROBE_0(av1394_attach_error_soft_state_zalloc,
216 		    AV1394_TNF_INST_ERROR, "");
217 		AV1394_TNF_EXIT(av1394_attach);
218 		return (DDI_FAILURE);
219 	}
220 	avp = AV1394_INST2STATE(instance);
221 
222 	if (av1394_t1394_attach(avp, dip) != DDI_SUCCESS) {
223 		av1394_cleanup(avp, 1);
224 		AV1394_TNF_EXIT(av1394_attach);
225 		return (DDI_FAILURE);
226 	}
227 
228 	mutex_init(&avp->av_mutex, NULL, MUTEX_DRIVER,
229 	    avp->av_attachinfo.iblock_cookie);
230 
231 #ifndef __lock_lint
232 	avp->av_dip = dip;
233 	avp->av_instance = instance;
234 #endif
235 
236 	if (av1394_add_events(avp) != DDI_SUCCESS) {
237 		av1394_cleanup(avp, 2);
238 		AV1394_TNF_EXIT(av1394_attach);
239 		return (DDI_FAILURE);
240 	}
241 
242 	if (av1394_isoch_attach(avp) != DDI_SUCCESS) {
243 		av1394_cleanup(avp, 3);
244 		AV1394_TNF_EXIT(av1394_attach);
245 		return (DDI_FAILURE);
246 	}
247 
248 	if (av1394_async_attach(avp) != DDI_SUCCESS) {
249 		av1394_cleanup(avp, 4);
250 		AV1394_TNF_EXIT(av1394_attach);
251 		return (DDI_FAILURE);
252 	}
253 
254 #ifndef __lock_lint
255 	avp->av_dev_state = AV1394_DEV_ONLINE;
256 #endif
257 
258 	ddi_report_dev(dip);
259 
260 	AV1394_TNF_EXIT(av1394_attach);
261 	return (DDI_SUCCESS);
262 }
263 
264 static int
265 av1394_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
266 {
267 	int		instance = ddi_get_instance(dip);
268 	av1394_inst_t	*avp;
269 
270 	AV1394_TNF_ENTER(av1394_detach);
271 
272 	if ((avp = AV1394_INST2STATE(instance)) == NULL) {
273 		TNF_PROBE_0(av1394_detach_error_instance,
274 		    AV1394_TNF_INST_ERROR, "");
275 		AV1394_TNF_EXIT(av1394_detach);
276 		return (DDI_FAILURE);
277 	}
278 
279 	switch (cmd) {
280 	case DDI_DETACH:
281 		av1394_cleanup(avp, AV1394_CLEANUP_LEVEL_MAX);
282 		AV1394_TNF_EXIT(av1394_detach);
283 		return (DDI_SUCCESS);
284 	case DDI_SUSPEND:
285 		return (av1394_cpr_suspend(avp));
286 	default:
287 		AV1394_TNF_EXIT(av1394_detach);
288 		return (DDI_FAILURE);
289 	}
290 }
291 
292 /*ARGSUSED*/
293 static int
294 av1394_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
295 		void **result)
296 {
297 	dev_t		dev = (dev_t)arg;
298 	av1394_inst_t	*avp;
299 	int		rval = DDI_FAILURE;
300 
301 	switch (infocmd) {
302 	case DDI_INFO_DEVT2DEVINFO:
303 		if ((avp = AV1394_DEV2STATE(dev)) != NULL) {
304 			*result = avp->av_dip;
305 			rval = DDI_SUCCESS;
306 		} else {
307 			*result = NULL;
308 		}
309 		break;
310 	case DDI_INFO_DEVT2INSTANCE:
311 		*result = (void *)(uintptr_t)AV1394_DEV2INST(dev);
312 		rval = DDI_SUCCESS;
313 		break;
314 	}
315 
316 	return (rval);
317 }
318 
319 /*ARGSUSED*/
320 static int
321 av1394_open(dev_t *dev, int flag, int otyp, cred_t *cr)
322 {
323 	av1394_inst_t	*avp = AV1394_DEV2STATE(*dev);
324 	int		ret = ENXIO;
325 
326 	AV1394_TNF_ENTER(av1394_open);
327 	if (avp != NULL) {
328 		if (AV1394_DEV_IS_ISOCH(*dev)) {
329 			ret = 0;
330 		} else if (AV1394_DEV_IS_ASYNC(*dev)) {
331 			ret = av1394_async_open(avp, flag);
332 		}
333 	}
334 	AV1394_TNF_EXIT(av1394_open);
335 	return (ret);
336 }
337 
338 /*ARGSUSED*/
339 static int
340 av1394_close(dev_t dev, int flag, int otyp, cred_t *cr)
341 {
342 	av1394_inst_t	*avp = AV1394_DEV2STATE(dev);
343 	int		ret = ENXIO;
344 
345 	AV1394_TNF_ENTER(av1394_close);
346 	if (avp != NULL) {
347 		if (AV1394_DEV_IS_ISOCH(dev)) {
348 			ret = av1394_isoch_close(avp, flag);
349 		} else if (AV1394_DEV_IS_ASYNC(dev)) {
350 			ret = av1394_async_close(avp, flag);
351 		}
352 	}
353 	AV1394_TNF_EXIT(av1394_close);
354 	return (ret);
355 }
356 
357 /*ARGSUSED*/
358 static int
359 av1394_read(dev_t dev, struct uio *uiop, cred_t *cr)
360 {
361 	av1394_inst_t	*avp = AV1394_DEV2STATE(dev);
362 	int		ret = ENXIO;
363 
364 	AV1394_TNF_ENTER(av1394_read);
365 	if (avp != NULL) {
366 		if (AV1394_DEV_IS_ISOCH(dev)) {
367 			ret = av1394_isoch_read(avp, uiop);
368 		} else if (AV1394_DEV_IS_ASYNC(dev)) {
369 			ret = av1394_async_read(avp, uiop);
370 		}
371 	}
372 	AV1394_TNF_EXIT(av1394_read);
373 	return (ret);
374 }
375 
376 /*ARGSUSED*/
377 static int
378 av1394_write(dev_t dev, struct uio *uiop, cred_t *cr)
379 {
380 	av1394_inst_t	*avp = AV1394_DEV2STATE(dev);
381 	int		ret = ENXIO;
382 
383 	AV1394_TNF_ENTER(av1394_write);
384 	if (avp != NULL) {
385 		if (AV1394_DEV_IS_ISOCH(dev)) {
386 			ret = av1394_isoch_write(avp, uiop);
387 		} else if (AV1394_DEV_IS_ASYNC(dev)) {
388 			ret = av1394_async_write(avp, uiop);
389 		}
390 	}
391 	AV1394_TNF_EXIT(av1394_write);
392 	return (ret);
393 }
394 
395 /*ARGSUSED*/
396 static int
397 av1394_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rvalp)
398 {
399 	av1394_inst_t	*avp = AV1394_DEV2STATE(dev);
400 	int		ret = ENXIO;
401 
402 	AV1394_TNF_ENTER(av1394_ioctl);
403 	if (avp != NULL) {
404 		if (AV1394_DEV_IS_ISOCH(dev)) {
405 			ret = av1394_isoch_ioctl(avp, cmd, arg, mode, rvalp);
406 		} else if (AV1394_DEV_IS_ASYNC(dev)) {
407 			ret = av1394_async_ioctl(avp, cmd, arg, mode, rvalp);
408 		}
409 	}
410 	AV1394_TNF_EXIT(av1394_ioctl);
411 	return (ret);
412 }
413 
414 /*ARGSUSED*/
415 static int
416 av1394_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
417 	size_t *maplen, uint_t model)
418 {
419 	av1394_inst_t	*avp = AV1394_DEV2STATE(dev);
420 	int		ret = ENXIO;
421 
422 	AV1394_TNF_ENTER(av1394_devmap);
423 	if ((avp != NULL) && (AV1394_DEV_IS_ISOCH(dev))) {
424 		ret = av1394_isoch_devmap(avp, dhp, off, len, maplen, model);
425 	}
426 	AV1394_TNF_EXIT(av1394_devmap);
427 	return (ret);
428 }
429 
430 static int
431 av1394_poll(dev_t dev, short events, int anyyet, short *reventsp,
432 		struct pollhead **phpp)
433 {
434 	av1394_inst_t	*avp = AV1394_DEV2STATE(dev);
435 	int		ret = ENXIO;
436 
437 	AV1394_TNF_ENTER(av1394_poll);
438 	if ((avp != NULL) && AV1394_DEV_IS_ASYNC(dev)) {
439 		ret = av1394_async_poll(avp, events, anyyet, reventsp, phpp);
440 	}
441 	AV1394_TNF_EXIT(av1394_poll);
442 	return (ret);
443 }
444 
445 
446 /*
447  *
448  * --- configuration routines
449  *
450  * av1394_cleanup()
451  *    Cleanup after attach
452  */
453 static void
454 av1394_cleanup(av1394_inst_t *avp, int level)
455 {
456 	ASSERT((level > 0) && (level <= AV1394_CLEANUP_LEVEL_MAX));
457 
458 	AV1394_TNF_ENTER(av1394_cleanup);
459 	switch (level) {
460 	default:
461 		av1394_async_detach(avp);
462 		/* FALLTHRU */
463 	case 4:
464 		av1394_isoch_detach(avp);
465 		/* FALLTHRU */
466 	case 3:
467 		av1394_remove_events(avp);
468 		/* FALLTHRU */
469 	case 2:
470 		av1394_t1394_detach(avp);
471 		mutex_destroy(&avp->av_mutex);
472 		/* FALLTHRU */
473 	case 1:
474 		ddi_soft_state_free(av1394_statep, avp->av_instance);
475 	}
476 	AV1394_TNF_EXIT(av1394_cleanup);
477 }
478 
479 static int
480 av1394_t1394_attach(av1394_inst_t *avp, dev_info_t *dip)
481 {
482 	int	ret;
483 
484 	AV1394_TNF_ENTER(av1394_t1394_attach);
485 
486 	ret = t1394_attach(dip, T1394_VERSION_V1, 0, &avp->av_attachinfo,
487 	    &avp->av_t1394_hdl);
488 
489 	if (ret != DDI_SUCCESS) {
490 		TNF_PROBE_1(av1394_t1394_attach_error, AV1394_TNF_INST_ERROR,
491 		    "", tnf_int, ret, ret);
492 	}
493 
494 	AV1394_TNF_EXIT(av1394_t1394_attach);
495 	return (ret);
496 }
497 
498 static void
499 av1394_t1394_detach(av1394_inst_t *avp)
500 {
501 	AV1394_TNF_ENTER(av1394_t1394_detach);
502 
503 	(void) t1394_detach(&avp->av_t1394_hdl, 0);
504 
505 	AV1394_TNF_EXIT(av1394_t1394_detach);
506 }
507 
508 static int
509 av1394_add_events(av1394_inst_t *avp)
510 {
511 	ddi_eventcookie_t	br_evc, rem_evc, ins_evc;
512 
513 	if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_BUS_RESET_EVENT,
514 	    &br_evc) != DDI_SUCCESS) {
515 		TNF_PROBE_0(av1394_add_events_error_bus_reset_cookie,
516 		    AV1394_TNF_INST_ERROR, "");
517 		return (DDI_FAILURE);
518 	}
519 	if (ddi_add_event_handler(avp->av_dip, br_evc, av1394_bus_reset,
520 	    avp, &avp->av_reset_cb) != DDI_SUCCESS) {
521 		TNF_PROBE_0(av1394_add_events_error_bus_reset_event,
522 		    AV1394_TNF_INST_ERROR, "");
523 		return (DDI_FAILURE);
524 	}
525 
526 	if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_REMOVE_EVENT,
527 	    &rem_evc) != DDI_SUCCESS) {
528 		(void) ddi_remove_event_handler(avp->av_reset_cb);
529 		TNF_PROBE_0(av1394_add_events_error_remove_cookie,
530 		    AV1394_TNF_INST_ERROR, "");
531 		return (DDI_FAILURE);
532 	}
533 	if (ddi_add_event_handler(avp->av_dip, rem_evc, av1394_disconnect,
534 	    avp, &avp->av_remove_cb) != DDI_SUCCESS) {
535 		(void) ddi_remove_event_handler(avp->av_reset_cb);
536 		TNF_PROBE_0(av1394_add_events_error_remove_event,
537 		    AV1394_TNF_INST_ERROR, "");
538 		return (DDI_FAILURE);
539 	}
540 
541 	if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_INSERT_EVENT,
542 	    &ins_evc) != DDI_SUCCESS) {
543 		(void) ddi_remove_event_handler(avp->av_remove_cb);
544 		(void) ddi_remove_event_handler(avp->av_reset_cb);
545 		TNF_PROBE_0(av1394_add_events_error_insert_cookie,
546 		    AV1394_TNF_INST_ERROR, "");
547 		return (DDI_FAILURE);
548 	}
549 	if (ddi_add_event_handler(avp->av_dip, ins_evc, av1394_reconnect,
550 	    avp, &avp->av_insert_cb) != DDI_SUCCESS) {
551 		(void) ddi_remove_event_handler(avp->av_remove_cb);
552 		(void) ddi_remove_event_handler(avp->av_reset_cb);
553 		TNF_PROBE_0(av1394_add_events_error_insert_event,
554 		    AV1394_TNF_INST_ERROR, "");
555 		return (DDI_FAILURE);
556 	}
557 
558 	return (DDI_SUCCESS);
559 }
560 
561 static void
562 av1394_remove_events(av1394_inst_t *avp)
563 {
564 	ddi_eventcookie_t	evc;
565 
566 	if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_INSERT_EVENT,
567 	    &evc) == DDI_SUCCESS) {
568 		(void) ddi_remove_event_handler(avp->av_insert_cb);
569 	}
570 
571 	if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_REMOVE_EVENT,
572 	    &evc) == DDI_SUCCESS) {
573 		(void) ddi_remove_event_handler(avp->av_remove_cb);
574 	}
575 
576 	if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_BUS_RESET_EVENT,
577 	    &evc) == DDI_SUCCESS) {
578 		(void) ddi_remove_event_handler(avp->av_reset_cb);
579 	}
580 }
581 
582 /*
583  *
584  * --- CPR
585  *
586  */
587 static int
588 av1394_cpr_suspend(av1394_inst_t *avp)
589 {
590 	int	ret;
591 
592 	AV1394_TNF_ENTER(av1394_cpr_suspend);
593 
594 	ret = av1394_isoch_cpr_suspend(avp);
595 
596 	if (ret == DDI_SUCCESS) {
597 		mutex_enter(&avp->av_mutex);
598 		avp->av_prev_dev_state = avp->av_dev_state;
599 		avp->av_dev_state = AV1394_DEV_SUSPENDED;
600 		mutex_exit(&avp->av_mutex);
601 	}
602 
603 	AV1394_TNF_EXIT(av1394_cpr_suspend);
604 	return (ret);
605 }
606 
607 /*
608  * CPR resume should always succeed
609  */
610 static int
611 av1394_cpr_resume(av1394_inst_t *avp)
612 {
613 	AV1394_TNF_ENTER(av1394_cpr_resume);
614 
615 	mutex_enter(&avp->av_mutex);
616 	avp->av_dev_state = avp->av_prev_dev_state;
617 	mutex_exit(&avp->av_mutex);
618 
619 	(void) av1394_async_cpr_resume(avp);
620 
621 	AV1394_TNF_EXIT(av1394_cpr_resume);
622 	return (DDI_SUCCESS);
623 }
624 
625 /*
626  *
627  * --- callbacks
628  *
629  */
630 /*ARGSUSED*/
631 static void
632 av1394_bus_reset(dev_info_t *dip, ddi_eventcookie_t evc, void *arg, void *data)
633 {
634 	av1394_inst_t	*avp = arg;
635 
636 	AV1394_TNF_ENTER(av1394_bus_reset);
637 
638 	if (avp == NULL) {
639 		AV1394_TNF_EXIT(av1394_bus_reset);
640 		return;
641 	}
642 
643 	mutex_enter(&avp->av_mutex);
644 	avp->av_attachinfo.localinfo = *(t1394_localinfo_t *)data;
645 	mutex_exit(&avp->av_mutex);
646 
647 	av1394_async_bus_reset(avp);
648 	av1394_cmp_bus_reset(avp);
649 
650 	AV1394_TNF_EXIT(av1394_bus_reset);
651 }
652 
653 /*ARGSUSED*/
654 static void
655 av1394_disconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg, void *data)
656 {
657 	av1394_inst_t	*avp = arg;
658 
659 	AV1394_TNF_ENTER(av1394_disconnect);
660 
661 	if (avp == NULL) {
662 		AV1394_TNF_EXIT(av1394_disconnect);
663 		return;
664 	}
665 
666 	mutex_enter(&avp->av_mutex);
667 	avp->av_dev_state = AV1394_DEV_DISCONNECTED;
668 	mutex_exit(&avp->av_mutex);
669 
670 	AV1394_TNF_EXIT(av1394_disconnect);
671 }
672 
673 /*ARGSUSED*/
674 static void
675 av1394_reconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg, void *data)
676 {
677 	av1394_inst_t	*avp = arg;
678 
679 	AV1394_TNF_ENTER(av1394_disconnect);
680 
681 	if (avp == NULL) {
682 		AV1394_TNF_EXIT(av1394_disconnect);
683 		return;
684 	}
685 
686 	mutex_enter(&avp->av_mutex);
687 	avp->av_dev_state = AV1394_DEV_ONLINE;
688 	avp->av_attachinfo.localinfo = *(t1394_localinfo_t *)data;
689 	mutex_exit(&avp->av_mutex);
690 
691 	av1394_async_reconnect(avp);
692 
693 	AV1394_TNF_EXIT(av1394_disconnect);
694 }
695