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  * hci1394.c
  29  *    1394 (firewire) OpenHCI 1.0 HBA driver. This file contains the driver's
  30  *    _init(), _info(), and _fini().
  31  */
  32 
  33 #include <sys/modctl.h>
  34 #include <sys/conf.h>
  35 #include <sys/ddi.h>
  36 #include <sys/sunddi.h>
  37 
  38 #include <sys/1394/ieee1394.h>
  39 #include <sys/1394/h1394.h>
  40 
  41 #include <sys/1394/adapters/hci1394.h>
  42 
  43 
  44 /* HAL State Pointer */
  45 void *hci1394_statep;
  46 
  47 /* Character/Block Operations */
  48 static struct cb_ops hci1394_cb_ops = {
  49         hci1394_open,           /* open */
  50         hci1394_close,          /* close */
  51         nodev,                  /* strategy (block) */
  52         nodev,                  /* print (block) */
  53         nodev,                  /* dump (block) */
  54         nodev,                  /* read */
  55         nodev,                  /* write */
  56         hci1394_ioctl,          /* ioctl */
  57         nodev,                  /* devmap */
  58         nodev,                  /* mmap */
  59         nodev,                  /* segmap */
  60         nochpoll,               /* chpoll */
  61         ddi_prop_op,            /* prop_op */
  62         NULL,                   /* streams */
  63         D_NEW | D_MP |
  64         D_64BIT | D_HOTPLUG,    /* flags */
  65         CB_REV                  /* rev */
  66 };
  67 
  68 /* Driver Operations */
  69 static struct dev_ops hci1394_ops = {
  70         DEVO_REV,               /* struct rev */
  71         0,                      /* refcnt */
  72         hci1394_getinfo,        /* getinfo */
  73         nulldev,                /* identify */
  74         nulldev,                /* probe */
  75         hci1394_attach,         /* attach */
  76         hci1394_detach,         /* detach */
  77         nodev,                  /* reset */
  78         &hci1394_cb_ops,    /* cb_ops */
  79         NULL,                   /* bus_ops */
  80         NULL,                   /* power */
  81         hci1394_quiesce,        /* devo_quiesce */
  82 };
  83 
  84 /* Module Driver Info */
  85 static struct modldrv hci1394_modldrv = {
  86         &mod_driverops,
  87         "1394 OpenHCI HBA driver",
  88         &hci1394_ops
  89 };
  90 
  91 /* Module Linkage */
  92 static struct modlinkage hci1394_modlinkage = {
  93         MODREV_1,
  94         &hci1394_modldrv,
  95         NULL
  96 };
  97 
  98 #ifndef NPROBE
  99 extern int tnf_mod_load(void);
 100 extern int tnf_mod_unload(struct modlinkage *mlp);
 101 #endif
 102 
 103 int
 104 _init()
 105 {
 106         int status;
 107 
 108 
 109 #ifndef NPROBE
 110         (void) tnf_mod_load();
 111 #endif
 112         TNF_PROBE_0_DEBUG(hci1394_init_enter, HCI1394_TNF_HAL_STACK, "");
 113 
 114         status = ddi_soft_state_init(&hci1394_statep, sizeof (hci1394_state_t),
 115             (size_t)HCI1394_INITIAL_STATES);
 116         if (status != 0) {
 117                 TNF_PROBE_2(hci1394_init_ssi_fail, HCI1394_TNF_HAL_ERROR, "",
 118                     tnf_string, errmsg, "failed in ddi_soft_state_init",
 119                     tnf_int, error, status);
 120                 TNF_PROBE_0_DEBUG(hci1394_init_exit, HCI1394_TNF_HAL_STACK, "");
 121 #ifndef NPROBE
 122                 (void) tnf_mod_unload(&hci1394_modlinkage);
 123 #endif
 124                 return (status);
 125         }
 126 
 127         /* Call into services layer to init bus-ops */
 128         status = h1394_init(&hci1394_modlinkage);
 129         if (status != 0) {
 130                 TNF_PROBE_2(hci1394_init_h1394_fail, HCI1394_TNF_HAL_ERROR, "",
 131                     tnf_string, errmsg, "failed in h1394_init",
 132                     tnf_int, error, status);
 133                 TNF_PROBE_0_DEBUG(hci1394_init_exit, HCI1394_TNF_HAL_STACK, "");
 134 #ifndef NPROBE
 135                 (void) tnf_mod_unload(&hci1394_modlinkage);
 136 #endif
 137                 return (status);
 138         }
 139 
 140         status = mod_install(&hci1394_modlinkage);
 141         if (status != 0) {
 142                 TNF_PROBE_2(hci1394_init_modi_fail, HCI1394_TNF_HAL_ERROR, "",
 143                     tnf_string, errmsg, "failed in mod_install",
 144                     tnf_int, error, status);
 145                 ddi_soft_state_fini(&hci1394_statep);
 146 #ifndef NPROBE
 147                 (void) tnf_mod_unload(&hci1394_modlinkage);
 148 #endif
 149                 return (status);
 150         }
 151 
 152         TNF_PROBE_0_DEBUG(hci1394_init_exit, HCI1394_TNF_HAL_STACK, "");
 153 
 154         return (status);
 155 }
 156 
 157 
 158 int
 159 _info(struct modinfo *modinfop)
 160 {
 161         int status;
 162 
 163         TNF_PROBE_0_DEBUG(hci1394_info_enter, HCI1394_TNF_HAL_STACK, "");
 164         status = mod_info(&hci1394_modlinkage, modinfop);
 165         TNF_PROBE_0_DEBUG(hci1394_info_exit, HCI1394_TNF_HAL_STACK, "");
 166 
 167         return (status);
 168 }
 169 
 170 
 171 int
 172 _fini()
 173 {
 174         int status;
 175 
 176         TNF_PROBE_0_DEBUG(hci1394_fini_enter, HCI1394_TNF_HAL_STACK, "");
 177 
 178         status = mod_remove(&hci1394_modlinkage);
 179         if (status != 0) {
 180                 TNF_PROBE_2(hci1394_fini_modr_fail, HCI1394_TNF_HAL_ERROR, "",
 181                     tnf_string, errmsg, "failed in mod_remove",
 182                     tnf_int, error, status);
 183                 TNF_PROBE_0_DEBUG(hci1394_fini_exit, HCI1394_TNF_HAL_STACK, "");
 184                 return (status);
 185         }
 186 
 187         /* Call into services layer notify about _fini */
 188         h1394_fini(&hci1394_modlinkage);
 189         ddi_soft_state_fini(&hci1394_statep);
 190 
 191         TNF_PROBE_0_DEBUG(hci1394_fini_exit, HCI1394_TNF_HAL_STACK, "");
 192 
 193 #ifndef NPROBE
 194         (void) tnf_mod_unload(&hci1394_modlinkage);
 195 #endif
 196 
 197         return (status);
 198 }