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 2002 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * s1394_fa.c
31 * 1394 Services Layer Fixed Address Support Routines
32 * Currently used for FCP support.
33 */
34
35 #include <sys/conf.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/cmn_err.h>
39 #include <sys/types.h>
40 #include <sys/kmem.h>
41 #include <sys/tnf_probe.h>
42
43 #include <sys/1394/t1394.h>
44 #include <sys/1394/s1394.h>
45 #include <sys/1394/h1394.h>
46
47 static void s1394_fa_completion_cb(cmd1394_cmd_t *cmd);
48
49 /*
50 * s1394_fa_claim_addr_blk()
51 * Claim fixed address block.
52 */
53 int
s1394_fa_claim_addr(s1394_hal_t * hal,s1394_fa_type_t type,s1394_fa_descr_t * descr)54 s1394_fa_claim_addr(s1394_hal_t *hal, s1394_fa_type_t type,
55 s1394_fa_descr_t *descr)
56 {
57 t1394_alloc_addr_t addr;
58 s1394_fa_hal_t *falp = &hal->hal_fa[type];
59 int ret;
60
61 TNF_PROBE_0_DEBUG(s1394_fa_claim_addr_enter, S1394_TNF_SL_FA_STACK, "");
62
63 /* Might have been claimed already */
64 if (falp->fal_addr_blk != NULL) {
65 TNF_PROBE_0_DEBUG(s1394_fa_claim_addr_exit,
66 S1394_TNF_SL_FA_STACK, "");
67 return (DDI_SUCCESS);
68 }
69
70 falp->fal_descr = descr;
71
72 bzero(&addr, sizeof (addr));
73 addr.aa_type = T1394_ADDR_FIXED;
74 addr.aa_address = descr->fd_addr;
75 addr.aa_length = descr->fd_size;
76 addr.aa_enable = descr->fd_enable;
77 addr.aa_evts = descr->fd_evts;
78 addr.aa_arg = hal;
79
80 ret = s1394_claim_addr_blk(hal, &addr);
81 if (ret != DDI_SUCCESS) {
82 TNF_PROBE_2(s1394_fa_claim_addr_error, S1394_TNF_SL_FA_ERROR,
83 "", tnf_int, type, type, tnf_int, ret, ret);
84 } else {
85 falp->fal_addr_blk = (s1394_addr_space_blk_t *)addr.aa_hdl;
86 }
87
88 TNF_PROBE_0_DEBUG(s1394_fa_claim_addr_exit, S1394_TNF_SL_FA_STACK, "");
89 return (ret);
90 }
91
92 /*
93 * s1394_fa_free_addr_blk()
94 * Free fixed address block.
95 */
96 void
s1394_fa_free_addr(s1394_hal_t * hal,s1394_fa_type_t type)97 s1394_fa_free_addr(s1394_hal_t *hal, s1394_fa_type_t type)
98 {
99 s1394_fa_hal_t *falp = &hal->hal_fa[type];
100 int ret;
101
102 TNF_PROBE_0_DEBUG(s1394_fa_free_addr_enter, S1394_TNF_SL_FA_STACK, "");
103
104 /* Might have been freed already */
105 if (falp->fal_addr_blk != NULL) {
106 ret = s1394_free_addr_blk(hal, falp->fal_addr_blk);
107 if (ret != DDI_SUCCESS) {
108 TNF_PROBE_1(s1394_fa_free_addr_error,
109 S1394_TNF_SL_FA_STACK, "", tnf_int, ret, ret);
110 }
111 falp->fal_addr_blk = NULL;
112 }
113
114 TNF_PROBE_0_DEBUG(s1394_fa_free_addr_exit, S1394_TNF_SL_FA_STACK, "");
115 }
116
117 /*
118 * s1394_fa_list_add()
119 * Add target to the list of FA clients.
120 * target_list_rwlock should be writer-held.
121 */
122 void
s1394_fa_list_add(s1394_hal_t * hal,s1394_target_t * target,s1394_fa_type_t type)123 s1394_fa_list_add(s1394_hal_t *hal, s1394_target_t *target,
124 s1394_fa_type_t type)
125 {
126 s1394_fa_hal_t *fal = &hal->hal_fa[type];
127
128 if (fal->fal_head == NULL) {
129 ASSERT(fal->fal_tail == NULL);
130 fal->fal_head = fal->fal_tail = target;
131 } else {
132 fal->fal_tail->target_fa[type].fat_next = target;
133 fal->fal_tail = target;
134 }
135 fal->fal_gen++;
136 }
137
138 /*
139 * s1394_fa_list_remove()
140 * Remove target from the list of FA clients.
141 * target_list_rwlock should be writer-held.
142 */
143 int
s1394_fa_list_remove(s1394_hal_t * hal,s1394_target_t * target,s1394_fa_type_t type)144 s1394_fa_list_remove(s1394_hal_t *hal, s1394_target_t *target,
145 s1394_fa_type_t type)
146 {
147 s1394_fa_hal_t *fal = &hal->hal_fa[type];
148 s1394_target_t *curp, **nextp, *prevp = NULL;
149
150 for (nextp = &fal->fal_head; (curp = *nextp) != NULL; ) {
151 if (curp == target) {
152 *nextp = target->target_fa[type].fat_next;
153 if (target == fal->fal_tail) {
154 fal->fal_tail = prevp;
155 }
156 fal->fal_gen++;
157 return (DDI_SUCCESS);
158 }
159 nextp = &curp->target_fa[type].fat_next;
160 prevp = curp;
161 }
162 return (DDI_FAILURE);
163 }
164
165 /*
166 * s1394_fa_list_is_empty()
167 * Returns B_TRUE if the target list is empty
168 * target_list_rwlock should be at least reader-held.
169 */
170 boolean_t
s1394_fa_list_is_empty(s1394_hal_t * hal,s1394_fa_type_t type)171 s1394_fa_list_is_empty(s1394_hal_t *hal, s1394_fa_type_t type)
172 {
173 s1394_fa_hal_t *fal = &hal->hal_fa[type];
174
175 return (fal->fal_head == NULL);
176 }
177
178 /*
179 * s1394_fa_list_gen()
180 * Returns list generation number.
181 * target_list_rwlock should be at least reader-held.
182 */
183 uint_t
s1394_fa_list_gen(s1394_hal_t * hal,s1394_fa_type_t type)184 s1394_fa_list_gen(s1394_hal_t *hal, s1394_fa_type_t type)
185 {
186 s1394_fa_hal_t *fal = &hal->hal_fa[type];
187
188 return (fal->fal_gen);
189 }
190
191 /*
192 * s1394_fa_init_cmd()
193 * initialize the FA specific part of the command
194 */
195 void
s1394_fa_init_cmd(s1394_cmd_priv_t * s_priv,s1394_fa_type_t type)196 s1394_fa_init_cmd(s1394_cmd_priv_t *s_priv, s1394_fa_type_t type)
197 {
198 s_priv->cmd_ext_type = S1394_CMD_EXT_FA;
199 s_priv->cmd_ext.fa.type = type;
200 }
201
202 /*
203 * s1394_fa_convert_cmd()
204 * convert an FA command (with a relative address) to a regular 1394 command
205 */
206 void
s1394_fa_convert_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)207 s1394_fa_convert_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
208 {
209 s1394_fa_cmd_priv_t *fa_priv = S1394_GET_FA_CMD_PRIV(cmd);
210
211 cmd->cmd_addr += hal->hal_fa[fa_priv->type].fal_descr->fd_conv_base;
212 fa_priv->completion_callback = cmd->completion_callback;
213 fa_priv->callback_arg = cmd->cmd_callback_arg;
214 cmd->completion_callback = s1394_fa_completion_cb;
215 cmd->cmd_callback_arg = hal;
216 }
217
218 /*
219 * s1394_fa_restore_cmd()
220 * opposite of s1394_fa_convert_cmd(): regular 1394 command to FA command
221 */
222 void
s1394_fa_restore_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)223 s1394_fa_restore_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
224 {
225 s1394_fa_cmd_priv_t *fa_priv = S1394_GET_FA_CMD_PRIV(cmd);
226
227 ASSERT(fa_priv->type < S1394_FA_NTYPES);
228
229 cmd->cmd_addr -= hal->hal_fa[fa_priv->type].fal_descr->fd_conv_base;
230 cmd->completion_callback = fa_priv->completion_callback;
231 cmd->cmd_callback_arg = fa_priv->callback_arg;
232 }
233
234 /*
235 * s1394_fa_check_restore_cmd()
236 * if a command has FA extension, do s1394_fa_restore_cmd()
237 */
238 void
s1394_fa_check_restore_cmd(s1394_hal_t * hal,cmd1394_cmd_t * cmd)239 s1394_fa_check_restore_cmd(s1394_hal_t *hal, cmd1394_cmd_t *cmd)
240 {
241 s1394_cmd_priv_t *s_priv = S1394_GET_CMD_PRIV(cmd);
242
243 if (s_priv->cmd_ext_type == S1394_CMD_EXT_FA) {
244 s1394_fa_restore_cmd(hal, cmd);
245 }
246 }
247
248 /*
249 * s1394_fa_completion_cb()
250 * FA completion callback: restore command and call original callback
251 */
252 static void
s1394_fa_completion_cb(cmd1394_cmd_t * cmd)253 s1394_fa_completion_cb(cmd1394_cmd_t *cmd)
254 {
255 s1394_hal_t *hal = cmd->cmd_callback_arg;
256
257 TNF_PROBE_0_DEBUG(s1394_fa_completion_cb_enter,
258 S1394_TNF_SL_FA_STACK, "");
259
260 s1394_fa_restore_cmd(hal, cmd);
261
262 if (cmd->completion_callback) {
263 cmd->completion_callback(cmd);
264 }
265
266 TNF_PROBE_0_DEBUG(s1394_fa_completion_cb_exit,
267 S1394_TNF_SL_FA_STACK, "");
268 }
269