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
_init(void)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
_fini(void)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
_info(struct modinfo * modinfop)185 _info(struct modinfo *modinfop)
186 {
187 return (mod_info(&av1394_modlinkage, modinfop));
188 }
189
190 /*
191 * attach
192 */
193 static int
av1394_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)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
av1394_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)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
av1394_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)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
av1394_open(dev_t * dev,int flag,int otyp,cred_t * cr)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
av1394_close(dev_t dev,int flag,int otyp,cred_t * cr)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
av1394_read(dev_t dev,struct uio * uiop,cred_t * cr)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
av1394_write(dev_t dev,struct uio * uiop,cred_t * cr)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
av1394_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * cr,int * rvalp)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
av1394_devmap(dev_t dev,devmap_cookie_t dhp,offset_t off,size_t len,size_t * maplen,uint_t model)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
av1394_poll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)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
av1394_cleanup(av1394_inst_t * avp,int level)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
av1394_t1394_attach(av1394_inst_t * avp,dev_info_t * dip)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
av1394_t1394_detach(av1394_inst_t * avp)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
av1394_add_events(av1394_inst_t * avp)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
av1394_remove_events(av1394_inst_t * avp)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
av1394_cpr_suspend(av1394_inst_t * avp)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
av1394_cpr_resume(av1394_inst_t * avp)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
av1394_bus_reset(dev_info_t * dip,ddi_eventcookie_t evc,void * arg,void * data)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
av1394_disconnect(dev_info_t * dip,ddi_eventcookie_t evc,void * arg,void * data)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
av1394_reconnect(dev_info_t * dip,ddi_eventcookie_t evc,void * arg,void * data)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