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