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