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