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         avp->av_dip = dip;
 232         avp->av_instance = instance;
 233 
 234         if (av1394_add_events(avp) != DDI_SUCCESS) {
 235                 av1394_cleanup(avp, 2);
 236                 AV1394_TNF_EXIT(av1394_attach);
 237                 return (DDI_FAILURE);
 238         }
 239 
 240         if (av1394_isoch_attach(avp) != DDI_SUCCESS) {
 241                 av1394_cleanup(avp, 3);
 242                 AV1394_TNF_EXIT(av1394_attach);
 243                 return (DDI_FAILURE);
 244         }
 245 
 246         if (av1394_async_attach(avp) != DDI_SUCCESS) {
 247                 av1394_cleanup(avp, 4);
 248                 AV1394_TNF_EXIT(av1394_attach);
 249                 return (DDI_FAILURE);
 250         }
 251 
 252         avp->av_dev_state = AV1394_DEV_ONLINE;
 253 
 254         ddi_report_dev(dip);
 255 
 256         AV1394_TNF_EXIT(av1394_attach);
 257         return (DDI_SUCCESS);
 258 }
 259 
 260 static int
 261 av1394_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 262 {
 263         int             instance = ddi_get_instance(dip);
 264         av1394_inst_t   *avp;
 265 
 266         AV1394_TNF_ENTER(av1394_detach);
 267 
 268         if ((avp = AV1394_INST2STATE(instance)) == NULL) {
 269                 TNF_PROBE_0(av1394_detach_error_instance,
 270                     AV1394_TNF_INST_ERROR, "");
 271                 AV1394_TNF_EXIT(av1394_detach);
 272                 return (DDI_FAILURE);
 273         }
 274 
 275         switch (cmd) {
 276         case DDI_DETACH:
 277                 av1394_cleanup(avp, AV1394_CLEANUP_LEVEL_MAX);
 278                 AV1394_TNF_EXIT(av1394_detach);
 279                 return (DDI_SUCCESS);
 280         case DDI_SUSPEND:
 281                 return (av1394_cpr_suspend(avp));
 282         default:
 283                 AV1394_TNF_EXIT(av1394_detach);
 284                 return (DDI_FAILURE);
 285         }
 286 }
 287 
 288 /*ARGSUSED*/
 289 static int
 290 av1394_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
 291                 void **result)
 292 {
 293         dev_t           dev = (dev_t)arg;
 294         av1394_inst_t   *avp;
 295         int             rval = DDI_FAILURE;
 296 
 297         switch (infocmd) {
 298         case DDI_INFO_DEVT2DEVINFO:
 299                 if ((avp = AV1394_DEV2STATE(dev)) != NULL) {
 300                         *result = avp->av_dip;
 301                         rval = DDI_SUCCESS;
 302                 } else {
 303                         *result = NULL;
 304                 }
 305                 break;
 306         case DDI_INFO_DEVT2INSTANCE:
 307                 *result = (void *)(uintptr_t)AV1394_DEV2INST(dev);
 308                 rval = DDI_SUCCESS;
 309                 break;
 310         }
 311 
 312         return (rval);
 313 }
 314 
 315 /*ARGSUSED*/
 316 static int
 317 av1394_open(dev_t *dev, int flag, int otyp, cred_t *cr)
 318 {
 319         av1394_inst_t   *avp = AV1394_DEV2STATE(*dev);
 320         int             ret = ENXIO;
 321 
 322         AV1394_TNF_ENTER(av1394_open);
 323         if (avp != NULL) {
 324                 if (AV1394_DEV_IS_ISOCH(*dev)) {
 325                         ret = 0;
 326                 } else if (AV1394_DEV_IS_ASYNC(*dev)) {
 327                         ret = av1394_async_open(avp, flag);
 328                 }
 329         }
 330         AV1394_TNF_EXIT(av1394_open);
 331         return (ret);
 332 }
 333 
 334 /*ARGSUSED*/
 335 static int
 336 av1394_close(dev_t dev, int flag, int otyp, cred_t *cr)
 337 {
 338         av1394_inst_t   *avp = AV1394_DEV2STATE(dev);
 339         int             ret = ENXIO;
 340 
 341         AV1394_TNF_ENTER(av1394_close);
 342         if (avp != NULL) {
 343                 if (AV1394_DEV_IS_ISOCH(dev)) {
 344                         ret = av1394_isoch_close(avp, flag);
 345                 } else if (AV1394_DEV_IS_ASYNC(dev)) {
 346                         ret = av1394_async_close(avp, flag);
 347                 }
 348         }
 349         AV1394_TNF_EXIT(av1394_close);
 350         return (ret);
 351 }
 352 
 353 /*ARGSUSED*/
 354 static int
 355 av1394_read(dev_t dev, struct uio *uiop, cred_t *cr)
 356 {
 357         av1394_inst_t   *avp = AV1394_DEV2STATE(dev);
 358         int             ret = ENXIO;
 359 
 360         AV1394_TNF_ENTER(av1394_read);
 361         if (avp != NULL) {
 362                 if (AV1394_DEV_IS_ISOCH(dev)) {
 363                         ret = av1394_isoch_read(avp, uiop);
 364                 } else if (AV1394_DEV_IS_ASYNC(dev)) {
 365                         ret = av1394_async_read(avp, uiop);
 366                 }
 367         }
 368         AV1394_TNF_EXIT(av1394_read);
 369         return (ret);
 370 }
 371 
 372 /*ARGSUSED*/
 373 static int
 374 av1394_write(dev_t dev, struct uio *uiop, cred_t *cr)
 375 {
 376         av1394_inst_t   *avp = AV1394_DEV2STATE(dev);
 377         int             ret = ENXIO;
 378 
 379         AV1394_TNF_ENTER(av1394_write);
 380         if (avp != NULL) {
 381                 if (AV1394_DEV_IS_ISOCH(dev)) {
 382                         ret = av1394_isoch_write(avp, uiop);
 383                 } else if (AV1394_DEV_IS_ASYNC(dev)) {
 384                         ret = av1394_async_write(avp, uiop);
 385                 }
 386         }
 387         AV1394_TNF_EXIT(av1394_write);
 388         return (ret);
 389 }
 390 
 391 /*ARGSUSED*/
 392 static int
 393 av1394_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rvalp)
 394 {
 395         av1394_inst_t   *avp = AV1394_DEV2STATE(dev);
 396         int             ret = ENXIO;
 397 
 398         AV1394_TNF_ENTER(av1394_ioctl);
 399         if (avp != NULL) {
 400                 if (AV1394_DEV_IS_ISOCH(dev)) {
 401                         ret = av1394_isoch_ioctl(avp, cmd, arg, mode, rvalp);
 402                 } else if (AV1394_DEV_IS_ASYNC(dev)) {
 403                         ret = av1394_async_ioctl(avp, cmd, arg, mode, rvalp);
 404                 }
 405         }
 406         AV1394_TNF_EXIT(av1394_ioctl);
 407         return (ret);
 408 }
 409 
 410 /*ARGSUSED*/
 411 static int
 412 av1394_devmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
 413         size_t *maplen, uint_t model)
 414 {
 415         av1394_inst_t   *avp = AV1394_DEV2STATE(dev);
 416         int             ret = ENXIO;
 417 
 418         AV1394_TNF_ENTER(av1394_devmap);
 419         if ((avp != NULL) && (AV1394_DEV_IS_ISOCH(dev))) {
 420                 ret = av1394_isoch_devmap(avp, dhp, off, len, maplen, model);
 421         }
 422         AV1394_TNF_EXIT(av1394_devmap);
 423         return (ret);
 424 }
 425 
 426 static int
 427 av1394_poll(dev_t dev, short events, int anyyet, short *reventsp,
 428                 struct pollhead **phpp)
 429 {
 430         av1394_inst_t   *avp = AV1394_DEV2STATE(dev);
 431         int             ret = ENXIO;
 432 
 433         AV1394_TNF_ENTER(av1394_poll);
 434         if ((avp != NULL) && AV1394_DEV_IS_ASYNC(dev)) {
 435                 ret = av1394_async_poll(avp, events, anyyet, reventsp, phpp);
 436         }
 437         AV1394_TNF_EXIT(av1394_poll);
 438         return (ret);
 439 }
 440 
 441 
 442 /*
 443  *
 444  * --- configuration routines
 445  *
 446  * av1394_cleanup()
 447  *    Cleanup after attach
 448  */
 449 static void
 450 av1394_cleanup(av1394_inst_t *avp, int level)
 451 {
 452         ASSERT((level > 0) && (level <= AV1394_CLEANUP_LEVEL_MAX));
 453 
 454         AV1394_TNF_ENTER(av1394_cleanup);
 455         switch (level) {
 456         default:
 457                 av1394_async_detach(avp);
 458                 /* FALLTHRU */
 459         case 4:
 460                 av1394_isoch_detach(avp);
 461                 /* FALLTHRU */
 462         case 3:
 463                 av1394_remove_events(avp);
 464                 /* FALLTHRU */
 465         case 2:
 466                 av1394_t1394_detach(avp);
 467                 mutex_destroy(&avp->av_mutex);
 468                 /* FALLTHRU */
 469         case 1:
 470                 ddi_soft_state_free(av1394_statep, avp->av_instance);
 471         }
 472         AV1394_TNF_EXIT(av1394_cleanup);
 473 }
 474 
 475 static int
 476 av1394_t1394_attach(av1394_inst_t *avp, dev_info_t *dip)
 477 {
 478         int     ret;
 479 
 480         AV1394_TNF_ENTER(av1394_t1394_attach);
 481 
 482         ret = t1394_attach(dip, T1394_VERSION_V1, 0, &avp->av_attachinfo,
 483             &avp->av_t1394_hdl);
 484 
 485         if (ret != DDI_SUCCESS) {
 486                 TNF_PROBE_1(av1394_t1394_attach_error, AV1394_TNF_INST_ERROR,
 487                     "", tnf_int, ret, ret);
 488         }
 489 
 490         AV1394_TNF_EXIT(av1394_t1394_attach);
 491         return (ret);
 492 }
 493 
 494 static void
 495 av1394_t1394_detach(av1394_inst_t *avp)
 496 {
 497         AV1394_TNF_ENTER(av1394_t1394_detach);
 498 
 499         (void) t1394_detach(&avp->av_t1394_hdl, 0);
 500 
 501         AV1394_TNF_EXIT(av1394_t1394_detach);
 502 }
 503 
 504 static int
 505 av1394_add_events(av1394_inst_t *avp)
 506 {
 507         ddi_eventcookie_t       br_evc, rem_evc, ins_evc;
 508 
 509         if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_BUS_RESET_EVENT,
 510             &br_evc) != DDI_SUCCESS) {
 511                 TNF_PROBE_0(av1394_add_events_error_bus_reset_cookie,
 512                     AV1394_TNF_INST_ERROR, "");
 513                 return (DDI_FAILURE);
 514         }
 515         if (ddi_add_event_handler(avp->av_dip, br_evc, av1394_bus_reset,
 516             avp, &avp->av_reset_cb) != DDI_SUCCESS) {
 517                 TNF_PROBE_0(av1394_add_events_error_bus_reset_event,
 518                     AV1394_TNF_INST_ERROR, "");
 519                 return (DDI_FAILURE);
 520         }
 521 
 522         if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_REMOVE_EVENT,
 523             &rem_evc) != DDI_SUCCESS) {
 524                 (void) ddi_remove_event_handler(avp->av_reset_cb);
 525                 TNF_PROBE_0(av1394_add_events_error_remove_cookie,
 526                     AV1394_TNF_INST_ERROR, "");
 527                 return (DDI_FAILURE);
 528         }
 529         if (ddi_add_event_handler(avp->av_dip, rem_evc, av1394_disconnect,
 530             avp, &avp->av_remove_cb) != DDI_SUCCESS) {
 531                 (void) ddi_remove_event_handler(avp->av_reset_cb);
 532                 TNF_PROBE_0(av1394_add_events_error_remove_event,
 533                     AV1394_TNF_INST_ERROR, "");
 534                 return (DDI_FAILURE);
 535         }
 536 
 537         if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_INSERT_EVENT,
 538             &ins_evc) != DDI_SUCCESS) {
 539                 (void) ddi_remove_event_handler(avp->av_remove_cb);
 540                 (void) ddi_remove_event_handler(avp->av_reset_cb);
 541                 TNF_PROBE_0(av1394_add_events_error_insert_cookie,
 542                     AV1394_TNF_INST_ERROR, "");
 543                 return (DDI_FAILURE);
 544         }
 545         if (ddi_add_event_handler(avp->av_dip, ins_evc, av1394_reconnect,
 546             avp, &avp->av_insert_cb) != DDI_SUCCESS) {
 547                 (void) ddi_remove_event_handler(avp->av_remove_cb);
 548                 (void) ddi_remove_event_handler(avp->av_reset_cb);
 549                 TNF_PROBE_0(av1394_add_events_error_insert_event,
 550                     AV1394_TNF_INST_ERROR, "");
 551                 return (DDI_FAILURE);
 552         }
 553 
 554         return (DDI_SUCCESS);
 555 }
 556 
 557 static void
 558 av1394_remove_events(av1394_inst_t *avp)
 559 {
 560         ddi_eventcookie_t       evc;
 561 
 562         if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_INSERT_EVENT,
 563             &evc) == DDI_SUCCESS) {
 564                 (void) ddi_remove_event_handler(avp->av_insert_cb);
 565         }
 566 
 567         if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_REMOVE_EVENT,
 568             &evc) == DDI_SUCCESS) {
 569                 (void) ddi_remove_event_handler(avp->av_remove_cb);
 570         }
 571 
 572         if (ddi_get_eventcookie(avp->av_dip, DDI_DEVI_BUS_RESET_EVENT,
 573             &evc) == DDI_SUCCESS) {
 574                 (void) ddi_remove_event_handler(avp->av_reset_cb);
 575         }
 576 }
 577 
 578 /*
 579  *
 580  * --- CPR
 581  *
 582  */
 583 static int
 584 av1394_cpr_suspend(av1394_inst_t *avp)
 585 {
 586         int     ret;
 587 
 588         AV1394_TNF_ENTER(av1394_cpr_suspend);
 589 
 590         ret = av1394_isoch_cpr_suspend(avp);
 591 
 592         if (ret == DDI_SUCCESS) {
 593                 mutex_enter(&avp->av_mutex);
 594                 avp->av_prev_dev_state = avp->av_dev_state;
 595                 avp->av_dev_state = AV1394_DEV_SUSPENDED;
 596                 mutex_exit(&avp->av_mutex);
 597         }
 598 
 599         AV1394_TNF_EXIT(av1394_cpr_suspend);
 600         return (ret);
 601 }
 602 
 603 /*
 604  * CPR resume should always succeed
 605  */
 606 static int
 607 av1394_cpr_resume(av1394_inst_t *avp)
 608 {
 609         AV1394_TNF_ENTER(av1394_cpr_resume);
 610 
 611         mutex_enter(&avp->av_mutex);
 612         avp->av_dev_state = avp->av_prev_dev_state;
 613         mutex_exit(&avp->av_mutex);
 614 
 615         (void) av1394_async_cpr_resume(avp);
 616 
 617         AV1394_TNF_EXIT(av1394_cpr_resume);
 618         return (DDI_SUCCESS);
 619 }
 620 
 621 /*
 622  *
 623  * --- callbacks
 624  *
 625  */
 626 /*ARGSUSED*/
 627 static void
 628 av1394_bus_reset(dev_info_t *dip, ddi_eventcookie_t evc, void *arg, void *data)
 629 {
 630         av1394_inst_t   *avp = arg;
 631 
 632         AV1394_TNF_ENTER(av1394_bus_reset);
 633 
 634         if (avp == NULL) {
 635                 AV1394_TNF_EXIT(av1394_bus_reset);
 636                 return;
 637         }
 638 
 639         mutex_enter(&avp->av_mutex);
 640         avp->av_attachinfo.localinfo = *(t1394_localinfo_t *)data;
 641         mutex_exit(&avp->av_mutex);
 642 
 643         av1394_async_bus_reset(avp);
 644         av1394_cmp_bus_reset(avp);
 645 
 646         AV1394_TNF_EXIT(av1394_bus_reset);
 647 }
 648 
 649 /*ARGSUSED*/
 650 static void
 651 av1394_disconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg, void *data)
 652 {
 653         av1394_inst_t   *avp = arg;
 654 
 655         AV1394_TNF_ENTER(av1394_disconnect);
 656 
 657         if (avp == NULL) {
 658                 AV1394_TNF_EXIT(av1394_disconnect);
 659                 return;
 660         }
 661 
 662         mutex_enter(&avp->av_mutex);
 663         avp->av_dev_state = AV1394_DEV_DISCONNECTED;
 664         mutex_exit(&avp->av_mutex);
 665 
 666         AV1394_TNF_EXIT(av1394_disconnect);
 667 }
 668 
 669 /*ARGSUSED*/
 670 static void
 671 av1394_reconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg, void *data)
 672 {
 673         av1394_inst_t   *avp = arg;
 674 
 675         AV1394_TNF_ENTER(av1394_disconnect);
 676 
 677         if (avp == NULL) {
 678                 AV1394_TNF_EXIT(av1394_disconnect);
 679                 return;
 680         }
 681 
 682         mutex_enter(&avp->av_mutex);
 683         avp->av_dev_state = AV1394_DEV_ONLINE;
 684         avp->av_attachinfo.localinfo = *(t1394_localinfo_t *)data;
 685         mutex_exit(&avp->av_mutex);
 686 
 687         av1394_async_reconnect(avp);
 688 
 689         AV1394_TNF_EXIT(av1394_disconnect);
 690 }