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 }