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 */
45void *hci1394_statep;
46
47/* Character/Block Operations */
48static 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 */
69static 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 */
85static struct modldrv hci1394_modldrv = {
86	&mod_driverops,
87	"1394 OpenHCI HBA driver",
88	&hci1394_ops
89};
90
91/* Module Linkage */
92static struct modlinkage hci1394_modlinkage = {
93	MODREV_1,
94	&hci1394_modldrv,
95	NULL
96};
97
98#ifndef NPROBE
99extern int tnf_mod_load(void);
100extern int tnf_mod_unload(struct modlinkage *mlp);
101#endif
102
103int
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
158int
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
171int
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}
199