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