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 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 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 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 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 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 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 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 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 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 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 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