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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef _SYS_SBP2_DRIVER_H 28 #define _SYS_SBP2_DRIVER_H 29 30 /* 31 * Serial Bus Protocol 2 (SBP-2) driver interfaces 32 */ 33 34 #include <sys/sbp2/defs.h> 35 #include <sys/sbp2/bus.h> 36 #include <sys/sysmacros.h> 37 #include <sys/note.h> 38 39 #ifdef __cplusplus 40 extern "C" { 41 #endif 42 43 /* 44 * Config ROM definitions 45 * 46 * bus info block 47 */ 48 typedef struct sbp2_cfgrom_bib { 49 int cb_len; /* info_length */ 50 uint32_t *cb_buf; /* data buffer */ 51 } sbp2_cfgrom_bib_t; 52 53 /* directory */ 54 typedef struct sbp2_cfgrom_dir { 55 struct sbp2_cfgrom_ent *cd_ent; /* array of entries */ 56 int cd_cnt; /* # of entries with data */ 57 int cd_size; /* # of allocated entries */ 58 } sbp2_cfgrom_dir_t; 59 60 /* directory entry */ 61 typedef struct sbp2_cfgrom_ent { 62 uint8_t ce_kt; /* key type */ 63 uint8_t ce_kv; /* key value */ 64 uint16_t ce_len; /* length in quadlets */ 65 uint64_t ce_offset; /* entry's CSR offset */ 66 struct sbp2_cfgrom_ent *ce_ref; /* referred entry (text leaf) */ 67 union { /* data depends on key type: */ 68 uint32_t imm; /* immediate value */ 69 uint32_t offset; /* CSR offset */ 70 uint32_t *leaf; /* leaf */ 71 sbp2_cfgrom_dir_t dir; /* directory */ 72 } ce_data; 73 } sbp2_cfgrom_ent_t; 74 75 /* entire Config ROM */ 76 typedef struct sbp2_cfgrom { 77 sbp2_cfgrom_bib_t cr_bib; /* bus info block */ 78 sbp2_cfgrom_ent_t cr_root; /* root directory */ 79 } sbp2_cfgrom_t; 80 81 _NOTE(SCHEME_PROTECTS_DATA("stable data", { 82 sbp2_cfgrom_bib sbp2_cfgrom_dir sbp2_cfgrom_ent sbp2_cfgrom })) 83 84 /* 85 * SBP-2 definitions 86 */ 87 88 /* task states */ 89 typedef enum { 90 SBP2_TASK_INIT, /* initial state */ 91 SBP2_TASK_PEND, /* put on the list, pending completion */ 92 SBP2_TASK_COMP, /* task completed */ 93 SBP2_TASK_PROC /* status being processed */ 94 } sbp2_task_state_t; 95 96 /* task errors */ 97 typedef enum { 98 SBP2_TASK_ERR_NONE, /* no error */ 99 SBP2_TASK_ERR_DEAD, /* agent dead */ 100 SBP2_TASK_ERR_BUS, /* bus error */ 101 SBP2_TASK_ERR_TIMEOUT, /* timed out */ 102 SBP2_TASK_ERR_ABORT, /* task aborted */ 103 SBP2_TASK_ERR_LUN_RESET, /* lun reset */ 104 SBP2_TASK_ERR_TGT_RESET /* target reset */ 105 } sbp2_task_error; 106 107 /* 108 * task 109 */ 110 typedef struct sbp2_task { 111 struct sbp2_task *ts_next; /* next task */ 112 struct sbp2_task *ts_prev; /* previous task */ 113 struct sbp2_ses *ts_ses; /* session we belong to */ 114 void *ts_drv_priv; /* driver private data */ 115 sbp2_bus_buf_t *ts_buf; /* bus buffer */ 116 int ts_timeout; /* task timeout in seconds */ 117 timeout_id_t ts_timeout_id; /* timeout ID */ 118 sbp2_task_state_t ts_state; /* task state */ 119 sbp2_task_error ts_error; /* error */ 120 int ts_bus_error; /* bus error */ 121 sbp2_status_t ts_status; /* status block */ 122 hrtime_t ts_time_start; 123 hrtime_t ts_time_comp; 124 } sbp2_task_t; 125 126 _NOTE(SCHEME_PROTECTS_DATA("unique per call", sbp2_task)) 127 128 /* fetch agent */ 129 typedef struct sbp2_agent { 130 struct sbp2_tgt *a_tgt; /* target we belong to */ 131 kmutex_t a_mutex; /* structure mutex */ 132 uint16_t a_state; /* current agent state */ 133 kcondvar_t a_cv; /* agent state cv */ 134 boolean_t a_acquired; /* acquired flag */ 135 136 /* commands */ 137 void *a_cmd; /* fetch agent cmd */ 138 mblk_t *a_cmd_data; /* cmd data */ 139 140 sbp2_task_t *a_active_task; /* active task */ 141 142 /* register offsets */ 143 uint64_t a_reg_agent_state; /* AGENT_STATE */ 144 uint64_t a_reg_agent_reset; /* AGENT_RESET */ 145 uint64_t a_reg_orbp; /* ORB_POINTER */ 146 uint64_t a_reg_doorbell; /* DOORBELL */ 147 uint64_t a_reg_unsol_status_enable; 148 /* UNSOLICITED_STATUS_ENABLE */ 149 } sbp2_agent_t; 150 151 _NOTE(MUTEX_PROTECTS_DATA(sbp2_agent::a_mutex, sbp2_agent)) 152 _NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_agent::{ 153 a_tgt a_reg_agent_state a_reg_agent_reset a_reg_orbp a_reg_doorbell 154 a_reg_unsol_status_enable })) 155 _NOTE(SCHEME_PROTECTS_DATA("a_acquired", sbp2_agent::{ 156 a_cmd a_cmd_data a_active_task })) 157 158 /* session is a period between login and logout */ 159 typedef struct sbp2_ses { 160 struct sbp2_tgt *s_tgt; /* target we belong to */ 161 struct sbp2_lun *s_lun; /* unit we belong to */ 162 kmutex_t s_mutex; /* structure mutex */ 163 struct sbp2_ses *s_next; /* next session */ 164 165 uint16_t s_id; /* login ID */ 166 uint64_t s_agent_offset; /* fetch agent offset */ 167 sbp2_agent_t s_agent; /* fetch agent */ 168 sbp2_bus_buf_t s_status_fifo_buf; /* status FIFO */ 169 170 /* task list (command ORB's) */ 171 kmutex_t s_task_mutex; /* protects task list */ 172 sbp2_task_t *s_task_head; /* first on the list */ 173 sbp2_task_t *s_task_tail; /* last on the list */ 174 int s_task_cnt; /* # tasks */ 175 void (*s_status_cb)(void *, sbp2_task_t *); 176 void *s_status_cb_arg; 177 } sbp2_ses_t; 178 179 _NOTE(MUTEX_PROTECTS_DATA(sbp2_ses::s_mutex, sbp2_ses)) 180 _NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_ses::{ 181 s_tgt s_lun s_id s_agent_offset s_agent s_status_fifo_buf s_status_cb 182 s_status_cb_arg })) 183 _NOTE(MUTEX_PROTECTS_DATA(sbp2_ses::s_task_mutex, sbp2_ses::{ 184 s_task_head s_task_tail s_task_cnt })) 185 _NOTE(MUTEX_PROTECTS_DATA(sbp2_ses::s_task_mutex, sbp2_task::{ 186 ts_next ts_prev })) 187 188 /* buffer list */ 189 typedef struct sbp2_buf_list { 190 kmutex_t bl_mutex; 191 int bl_len; /* number of elements */ 192 sbp2_bus_buf_t *bl_head; /* first element */ 193 sbp2_bus_buf_t *bl_tail; /* last element */ 194 } sbp2_buf_list_t; 195 196 /* logical unit */ 197 typedef struct sbp2_lun { 198 struct sbp2_tgt *l_tgt; /* target we belong to */ 199 uint16_t l_lun; /* logical unit number */ 200 uint8_t l_type; /* device type */ 201 sbp2_ses_t *l_ses; /* login sessions */ 202 sbp2_buf_list_t l_orb_freelist; /* ORB freelist */ 203 204 205 sbp2_login_resp_t l_login_resp; /* login response */ 206 boolean_t l_logged_in; /* true if logged in */ 207 boolean_t l_reconnecting; /* true if being reconnected */ 208 } sbp2_lun_t; 209 210 enum { 211 SBP2_ORB_FREELIST_MAX = 3 /* max # of elements on freelist */ 212 }; 213 214 /* per-target statistics */ 215 typedef struct sbp2_tgt_stat { 216 hrtime_t stat_cfgrom_last_parse_time; 217 uint_t stat_submit_orbp; 218 uint_t stat_submit_doorbell; 219 uint_t stat_status_dead; 220 uint_t stat_status_short; 221 uint_t stat_status_unsolicited; 222 uint_t stat_status_notask; 223 uint_t stat_status_mgt_notask; 224 uint_t stat_agent_worbp; 225 uint_t stat_agent_worbp_fail; 226 uint_t stat_agent_wreset; 227 uint_t stat_agent_wreset_fail; 228 uint_t stat_task_max; 229 } sbp2_tgt_stat_t; 230 231 /* target */ 232 typedef struct sbp2_tgt { 233 struct sbp2_bus *t_bus; /* bus */ 234 void *t_bus_hdl; /* bus handle */ 235 kmutex_t t_mutex; /* structure mutex */ 236 sbp2_lun_t *t_lun; /* logical unit array */ 237 int t_nluns; /* # logical units */ 238 int t_nluns_alloc; /* # luns allocated */ 239 240 /* congif ROM */ 241 sbp2_cfgrom_t t_cfgrom; /* parsed cfgrom */ 242 hrtime_t t_last_cfgrd; /* cfgrom timestamp */ 243 int t_orb_size; /* ORB_size */ 244 245 /* management agent */ 246 uint64_t t_mgt_agent; /* mgt agent address */ 247 int t_mot; /* mgt timeout, ms */ 248 boolean_t t_mgt_agent_acquired; /* acquired flag */ 249 kcondvar_t t_mgt_agent_cv; /* cv for busy flag */ 250 sbp2_bus_buf_t t_mgt_orb_buf; /* mgt ORB */ 251 void *t_mgt_cmd; /* command */ 252 mblk_t *t_mgt_cmd_data; /* command data */ 253 sbp2_bus_buf_t t_mgt_status_fifo_buf; /* status FIFO buf */ 254 sbp2_status_t t_mgt_status; /* status block */ 255 boolean_t t_mgt_status_rcvd; /* status received? */ 256 kcondvar_t t_mgt_status_cv; /* status FIFO cv */ 257 sbp2_bus_buf_t t_mgt_login_resp_buf; /* login response */ 258 259 sbp2_tgt_stat_t t_stat; /* statistics */ 260 } sbp2_tgt_t; 261 262 _NOTE(MUTEX_PROTECTS_DATA(sbp2_tgt::t_mutex, sbp2_tgt)) 263 _NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_tgt::{ 264 t_bus t_bus_hdl t_lun t_nluns t_nluns_alloc t_cfgrom t_last_cfgrd 265 t_orb_size t_mgt_agent t_mot })) 266 _NOTE(SCHEME_PROTECTS_DATA("t_mgt_agent_cv", sbp2_tgt::{ 267 t_mgt_orb_buf t_mgt_cmd t_mgt_cmd_data t_mgt_status_fifo_buf 268 t_mgt_status_rcvd t_mgt_login_resp_buf })) 269 _NOTE(SCHEME_PROTECTS_DATA("statistics", sbp2_tgt::t_stat)) 270 271 _NOTE(MUTEX_PROTECTS_DATA(sbp2_tgt::t_mutex, sbp2_lun)) 272 _NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_lun::{ 273 l_tgt l_lun l_type l_ses })) 274 _NOTE(SCHEME_PROTECTS_DATA("t_mgt_agent_cv", sbp2_lun::l_login_resp)) 275 276 _NOTE(LOCK_ORDER(sbp2_tgt::t_mutex sbp2_ses::s_mutex)) 277 _NOTE(LOCK_ORDER(sbp2_tgt::t_mutex sbp2_ses::s_task_mutex)) 278 _NOTE(LOCK_ORDER(sbp2_tgt::t_mutex sbp2_agent::a_mutex)) 279 280 #define SBP2_ORB_SIZE_ROUNDUP(tp, size) roundup(size, (tp)->t_orb_size) 281 282 /* walker flags */ 283 enum { 284 SBP2_WALK_DIRONLY = 0x01 /* walk directories only */ 285 }; 286 287 /* walker return codes */ 288 enum { 289 SBP2_WALK_CONTINUE, 290 SBP2_WALK_STOP 291 }; 292 293 int sbp2_tgt_init(void *, struct sbp2_bus *, int, sbp2_tgt_t **); 294 void sbp2_tgt_fini(sbp2_tgt_t *); 295 void sbp2_tgt_disconnect(sbp2_tgt_t *); 296 int sbp2_tgt_reconnect(sbp2_tgt_t *); 297 int sbp2_tgt_reset(sbp2_tgt_t *, int *); 298 int sbp2_tgt_get_cfgrom(sbp2_tgt_t *, sbp2_cfgrom_t **); 299 int sbp2_tgt_get_lun_cnt(sbp2_tgt_t *); 300 sbp2_lun_t *sbp2_tgt_get_lun(sbp2_tgt_t *, int); 301 302 int sbp2_lun_reset(sbp2_lun_t *, int *); 303 int sbp2_lun_login(sbp2_lun_t *, sbp2_ses_t **, void (*)(void *, sbp2_task_t *), 304 void *, int *); 305 int sbp2_lun_logout(sbp2_lun_t *, sbp2_ses_t **, int *, boolean_t); 306 307 int sbp2_ses_reconnect(sbp2_ses_t *, int *, uint16_t); 308 int sbp2_ses_submit_task(sbp2_ses_t *, sbp2_task_t *); 309 void sbp2_ses_nudge(sbp2_ses_t *); 310 int sbp2_ses_remove_task(sbp2_ses_t *, sbp2_task_t *); 311 sbp2_task_t *sbp2_ses_find_task_state(sbp2_ses_t *, sbp2_task_state_t); 312 sbp2_task_t *sbp2_ses_remove_first_task(sbp2_ses_t *); 313 sbp2_task_t *sbp2_ses_remove_first_task_state(sbp2_ses_t *, sbp2_task_state_t); 314 sbp2_task_t *sbp2_ses_cancel_first_task(sbp2_ses_t *); 315 int sbp2_ses_agent_reset(sbp2_ses_t *, int *); 316 int sbp2_ses_abort_task(sbp2_ses_t *, sbp2_task_t *, int *); 317 int sbp2_ses_abort_task_set(sbp2_ses_t *, int *); 318 319 int sbp2_task_orb_alloc(sbp2_lun_t *, sbp2_task_t *, int); 320 void sbp2_task_orb_free(sbp2_lun_t *, sbp2_task_t *); 321 void *sbp2_task_orb_kaddr(sbp2_task_t *); 322 void sbp2_task_orb_sync(sbp2_lun_t *, sbp2_task_t *, int); 323 324 void sbp2_swap32_buf(uint32_t *, int); 325 326 void sbp2_cfgrom_walk(sbp2_cfgrom_ent_t *, 327 int (*)(void *, sbp2_cfgrom_ent_t *, int), void *); 328 sbp2_cfgrom_ent_t *sbp2_cfgrom_ent_by_key(sbp2_cfgrom_ent_t *, int8_t, int8_t, 329 int); 330 331 332 #ifdef __cplusplus 333 } 334 #endif 335 336 #endif /* _SYS_SBP2_DRIVER_H */ 337