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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 /*
28  * hci1394_misc.c
29  *    Misc. HBA functions.  These include getinfo, open, close, shutdown, and
30  *    overall driver state control functions.
31  */
32 
33 #include <sys/conf.h>
34 #include <sys/ddi.h>
35 #include <sys/modctl.h>
36 #include <sys/sunddi.h>
37 #include <sys/types.h>
38 #include <sys/mkdev.h>
39 
40 #include <sys/1394/adapters/hci1394.h>
41 #include <sys/1394/adapters/hci1394_extern.h>
42 
43 
44 
45 /* ARGSUSED */
46 int
hci1394_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)47 hci1394_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
48 {
49 	dev_t dev;
50 	hci1394_state_t *soft_state;
51 	minor_t instance;
52 	int status;
53 
54 	switch (cmd) {
55 	case DDI_INFO_DEVT2DEVINFO:
56 		dev = (dev_t)arg;
57 		instance = getminor(dev);
58 		soft_state = ddi_get_soft_state(hci1394_statep, instance);
59 		if (soft_state == NULL) {
60 			return (DDI_FAILURE);
61 		}
62 		*result = (void *)soft_state->drvinfo.di_dip;
63 		status = DDI_SUCCESS;
64 		break;
65 
66 	case DDI_INFO_DEVT2INSTANCE:
67 		dev = (dev_t)arg;
68 		instance = getminor(dev);
69 		*result = (void *)(uintptr_t)instance;
70 		status = DDI_SUCCESS;
71 		break;
72 
73 	default:
74 		status = DDI_FAILURE;
75 	}
76 
77 	return (status);
78 }
79 
80 
81 /* ARGSUSED */
82 int
hci1394_open(dev_t * devp,int flag,int otyp,cred_t * credp)83 hci1394_open(dev_t *devp, int flag, int otyp, cred_t *credp)
84 {
85 	hci1394_state_t *soft_state;
86 
87 	soft_state = ddi_get_soft_state(hci1394_statep, getminor(*devp));
88 	if (soft_state == NULL) {
89 		return (ENXIO);
90 	}
91 
92 	return (0);
93 }
94 
95 
96 /* ARGSUSED */
97 int
hci1394_close(dev_t dev,int flag,int otyp,cred_t * credp)98 hci1394_close(dev_t dev, int flag, int otyp, cred_t *credp)
99 {
100 	return (0);
101 }
102 
103 
104 /*
105  * hci1394_shutdown()
106  *    Shutdown the HW.  Something bad that we cannot recover from happened.
107  */
108 void
hci1394_shutdown(dev_info_t * dip)109 hci1394_shutdown(dev_info_t *dip)
110 {
111 	hci1394_state_t *soft_state;
112 
113 
114 	/*
115 	 * In the debug version of the driver, we want to do an assert here so
116 	 * that we don't reset the hardware and can look and see what happened
117 	 * to cause the shutdown.
118 	 */
119 #ifndef	TEST_SHUTDOWN
120 	ASSERT(0);
121 #endif
122 
123 	soft_state = ddi_get_soft_state(hci1394_statep, ddi_get_instance(dip));
124 	if (soft_state == NULL) {
125 		return;
126 	}
127 
128 	/*
129 	 * Don't allow the HW to generate any more interrupts. Make sure we
130 	 * disable interrupts before setting the driver state to shutdown.
131 	 */
132 	hci1394_ohci_intr_master_disable(soft_state->ohci);
133 
134 	/* don't accept anymore commands from services layer */
135 	(void) hci1394_state_set(&soft_state->drvinfo, HCI1394_SHUTDOWN);
136 
137 	/* Reset the OHCI HW */
138 	(void) hci1394_ohci_soft_reset(soft_state->ohci);
139 
140 	/* Flush out async DMA Q's (cancels pendingQ timeouts too) */
141 	hci1394_async_flush(soft_state->async);
142 }
143 
144 
145 /*
146  * hci1394_state()
147  *    returns the current state of the driver
148  */
149 hci1394_statevar_t
hci1394_state(hci1394_drvinfo_t * drvinfo)150 hci1394_state(hci1394_drvinfo_t *drvinfo)
151 {
152 	hci1394_statevar_t hal_state;
153 
154 	mutex_enter(&drvinfo->di_drvstate.ds_mutex);
155 	hal_state = drvinfo->di_drvstate.ds_state;
156 	mutex_exit(&drvinfo->di_drvstate.ds_mutex);
157 
158 	return (hal_state);
159 }
160 
161 
162 /*
163  * hci1394_state_set()
164  *    Set the current state of the driver. This routine will return failure
165  *    if the driver state is currently set to HCI1394_SHUTDOWN.  We do not
166  *    allow a transition out of shutdown.
167  */
168 int
hci1394_state_set(hci1394_drvinfo_t * drvinfo,hci1394_statevar_t state)169 hci1394_state_set(hci1394_drvinfo_t *drvinfo, hci1394_statevar_t state)
170 {
171 	mutex_enter(&drvinfo->di_drvstate.ds_mutex);
172 
173 	/* Do not allow a transition out of shutdown */
174 	if (drvinfo->di_drvstate.ds_state == HCI1394_SHUTDOWN) {
175 		mutex_exit(&drvinfo->di_drvstate.ds_mutex);
176 		return (DDI_FAILURE);
177 	}
178 
179 	drvinfo->di_drvstate.ds_state = state;
180 	mutex_exit(&drvinfo->di_drvstate.ds_mutex);
181 
182 	return (DDI_SUCCESS);
183 }
184