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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _SYS_1394_TARGETS_AV1394_IMPL_H 27 #define _SYS_1394_TARGETS_AV1394_IMPL_H 28 29 /* 30 * av1394 driver definitions 31 */ 32 33 #include <sys/note.h> 34 #include <sys/ddi.h> 35 #include <sys/sunddi.h> 36 #include <sys/strsun.h> 37 #include <sys/mkdev.h> 38 #include <sys/tnf_probe.h> 39 #include <sys/av/iec61883.h> 40 #include <sys/1394/t1394.h> 41 #include <sys/1394/targets/av1394/av1394_isoch.h> 42 43 #ifdef __cplusplus 44 extern "C" { 45 #endif 46 47 /* 48 * byte swapping support, stolen from SBP2 49 */ 50 #ifdef _LITTLE_ENDIAN 51 #define AV_SWAP16(data) \ 52 ((((data) & 0xff) << 8) | ((data) >> 8)) 53 54 #define AV_SWAP32(data) \ 55 (((uint32_t)AV_SWAP16((uint16_t)((data) & 0xffff)) << 16) | \ 56 (uint32_t)AV_SWAP16((uint16_t)((data) >> 16))) 57 #else 58 #define AV_SWAP16(data) (data) 59 #define AV_SWAP32(data) (data) 60 #endif 61 62 63 /* 64 * double-linked list 65 */ 66 typedef struct av1394_list_item_s { 67 struct av1394_list_item_s *i_next; 68 struct av1394_list_item_s *i_prev; 69 } av1394_list_item_t; 70 71 typedef struct av1394_list_s { 72 av1394_list_item_t *l_head; /* first item */ 73 av1394_list_item_t *l_tail; /* last item */ 74 int l_cnt; /* number of items */ 75 } av1394_list_t; 76 77 78 /* 79 * queue 80 */ 81 typedef struct av1394_queue_s { 82 kmutex_t q_mutex; /* mutex */ 83 av1394_list_t q_list; /* list of mblk's */ 84 int q_size; /* current data size */ 85 int q_max; /* max data size */ 86 kcondvar_t q_cv; /* data cv */ 87 } av1394_queue_t; 88 89 _NOTE(MUTEX_PROTECTS_DATA(av1394_queue_s::q_mutex, av1394_queue_s)) 90 91 #define AV1394_ENTERQ(q) mutex_enter(&(q)->q_mutex) 92 #define AV1394_LEAVEQ(q) mutex_exit(&(q)->q_mutex) 93 94 95 /* 96 * asynchronous module definitions 97 * 98 * 99 * command structure 100 */ 101 typedef struct av1394_fcp_cmd_s { 102 cmd1394_cmd_t *fc_cmd; /* 1394 command */ 103 boolean_t fc_busy; /* command is in use */ 104 kcondvar_t fc_busy_cv; /* busy cv */ 105 boolean_t fc_xmit; /* transmit in progress */ 106 kcondvar_t fc_xmit_cv; /* transmit completion cv */ 107 } av1394_fcp_cmd_t; 108 109 /* 110 * per-instance FCP structure 111 */ 112 typedef struct av1394_fcp_s { 113 av1394_fcp_cmd_t fcp_cmd; /* outgoing FCP command */ 114 av1394_fcp_cmd_t fcp_resp; /* outgoing FCP response */ 115 } av1394_fcp_t; 116 117 enum { 118 AV1394_FCP_ARQ_LEN_MAX = 0x200 /* maximum FCP ARQ length */ 119 }; 120 121 122 /* 123 * configuration ROM 124 */ 125 #define AV1394_CFGROM_INFO_LEN_ADDR (IEEE1394_CONFIG_ROM_ADDR + 0x00) 126 #define AV1394_CFGROM_BUS_NAME_ADDR (IEEE1394_CONFIG_ROM_ADDR + 0x04) 127 #define AV1394_CFGROM_EUI64_HI_ADDR (IEEE1394_CONFIG_ROM_ADDR + 0x0c) 128 #define AV1394_CFGROM_EUI64_LO_ADDR (IEEE1394_CONFIG_ROM_ADDR + 0x10) 129 130 /* offsets in quadlets */ 131 #define AV1394_CFGROM_BUS_NAME_OFF 1 132 #define AV1394_CFGROM_EUI64_HI_OFF 3 133 #define AV1394_CFGROM_EUI64_LO_OFF 4 134 135 typedef struct av1394_cfgrom_text_leaf_s { 136 uint64_t tl_addr; /* leaf entry address */ 137 uint32_t tl_desc_entry; /* entry described by this leaf */ 138 } av1394_cfgrom_text_leaf_t; 139 140 typedef struct av1394_cfgrom_parsed_dir_s { 141 av1394_cfgrom_text_leaf_t *pd_tl; /* text leaf array */ 142 int pd_tl_size; /* total # of array entries */ 143 int pd_tl_next; /* first unused entry index */ 144 } av1394_cfgrom_parsed_dir_t; 145 146 typedef struct av1394_cfgrom_parse_arg_s { 147 int pa_depth; /* parser depth */ 148 uint32_t pa_desc_entry; /* described entry */ 149 uint8_t pa_parent_k; /* parent entry's key value */ 150 uint64_t pa_addr; /* directory address */ 151 uint16_t pa_len; /* directory length */ 152 av1394_cfgrom_parsed_dir_t *pa_dir; /* current directory */ 153 } av1394_cfgrom_parse_arg_t; 154 155 enum { 156 AV1394_CFGROM_PARSE_MAX_DEPTH = 5 /* maximum parse depth */ 157 }; 158 159 typedef struct av1394_cfgrom_s { 160 krwlock_t cr_rwlock; /* structure lock */ 161 boolean_t cr_parsed; /* node ConfigROM was parsed */ 162 av1394_cfgrom_parsed_dir_t cr_root_dir; /* root directory */ 163 av1394_cfgrom_parsed_dir_t cr_unit_dir; /* unit directory */ 164 } av1394_cfgrom_t; 165 166 167 /* 168 * async command 169 */ 170 typedef struct av1394_async_cmd_s { 171 kmutex_t ac_mutex; 172 boolean_t ac_busy; 173 kcondvar_t ac_cv; 174 cmd1394_cmd_t *ac_cmd; 175 } av1394_async_cmd_t; 176 177 /* 178 * per-instance soft state structure 179 */ 180 typedef struct av1394_async_s { 181 kmutex_t a_mutex; /* structure mutex */ 182 int a_nopen; /* number of opens */ 183 int a_oflag; /* open flags */ 184 t1394_targetinfo_t a_targetinfo; /* target info */ 185 uint_t a_bus_generation; /* bus generation */ 186 av1394_fcp_t a_fcp; /* FCP module */ 187 av1394_cfgrom_t a_cfgrom; /* config ROM module */ 188 av1394_queue_t a_rq; /* read queue */ 189 struct pollhead a_pollhead; /* poll(2) support */ 190 short a_pollevents; /* polled events */ 191 } av1394_async_t; 192 193 _NOTE(MUTEX_PROTECTS_DATA(av1394_async_s::a_mutex, av1394_async_s)) 194 _NOTE(DATA_READABLE_WITHOUT_LOCK(av1394_async_s::{ 195 a_oflag 196 })) 197 198 199 /* we use special message types for the read queue */ 200 enum { 201 AV1394_M_FCP_RESP = 0x01, /* FCP response */ 202 AV1394_M_FCP_CMD = 0x02, /* FCP command */ 203 AV1394_M_BUS_RESET = 0x03, /* bus reset event */ 204 /* 205 * For efficiency, we only store 1394 request data on the read queue. 206 * ARQ headers (iec61883_arq_t) are generated when an application 207 * calls read(2). Because applications may read header separately 208 * from the data, we need to mark each mblk when its header was read 209 * but not the data - the following flag is used for this purpose. 210 */ 211 AV1394_M_NOHDR = 0x80 212 }; 213 214 #define AV1394_DBTYPE(bp) (DB_TYPE(bp) & ~AV1394_M_NOHDR) 215 #define AV1394_MARK_NOHDR(bp) (DB_TYPE(bp) |= AV1394_M_NOHDR) 216 #define AV1394_IS_NOHDR(bp) (DB_TYPE(bp) & AV1394_M_NOHDR) 217 218 219 /* 220 * device state: 221 * 222 * AV1394_DEV_DISCONNECTED 223 * | | ^ 224 * | | | 225 * detach reconnect disconnect 226 * | | | 227 * v v | 228 * AV1394_DEV_INIT ----attach---> AV1394_DEV_ONLINE 229 * (initial state) <---detach--- | ^ 230 * | | 231 * cpr suspend cpr resume 232 * | | 233 * v | 234 * AV1394_DEV_SUSPENDED 235 */ 236 typedef enum { 237 AV1394_DEV_INIT = 0, 238 AV1394_DEV_ONLINE, 239 AV1394_DEV_SUSPENDED, 240 AV1394_DEV_DISCONNECTED 241 } av1394_dev_state_t; 242 243 /* 244 * per-instance soft state structure 245 */ 246 typedef struct av1394_inst_s { 247 kmutex_t av_mutex; /* structure mutex */ 248 dev_info_t *av_dip; /* device information */ 249 int av_instance; /* instance number */ 250 av1394_dev_state_t av_dev_state; /* device state */ 251 av1394_dev_state_t av_prev_dev_state; /* previous device state */ 252 t1394_attachinfo_t av_attachinfo; /* 1394 attach info */ 253 t1394_handle_t av_t1394_hdl; /* 1394 handle */ 254 av1394_async_t av_a; /* asynchronous module */ 255 av1394_isoch_t av_i; /* isochronous module */ 256 ddi_callback_id_t av_reset_cb; /* reset event cb id */ 257 ddi_callback_id_t av_remove_cb; /* remove event cb id */ 258 ddi_callback_id_t av_insert_cb; /* insert event cb id */ 259 } av1394_inst_t; 260 261 _NOTE(MUTEX_PROTECTS_DATA(av1394_inst_s::av_mutex, av1394_inst_s::{ 262 av_dip 263 av_instance 264 av_attachinfo 265 av_t1394_hdl 266 })) 267 /* these are set during attach (single-threaded) and don't change afterwards */ 268 _NOTE(DATA_READABLE_WITHOUT_LOCK(av1394_inst_s::{ 269 av_dip 270 av_instance 271 av_attachinfo 272 av_t1394_hdl 273 })) 274 275 _NOTE(SCHEME_PROTECTS_DATA("one per call", msgb datab cmd1394_cmd 276 iec61883_arq_t iec61883_isoch_init_t iec61883_plug_init_t)) 277 278 /* 279 * minor <-> instance mapping 280 */ 281 #define AV1394_MINOR_TYPE_MASK (1 << (NBITSMINOR32 - 1)) 282 #define AV1394_ISOCH_INST2MINOR(inst) (inst) 283 #define AV1394_ASYNC_INST2MINOR(inst) ((inst) | AV1394_MINOR_TYPE_MASK) 284 #define AV1394_DEV_IS_ISOCH(dev) \ 285 ((getminor(dev) & AV1394_MINOR_TYPE_MASK) == 0) 286 #define AV1394_DEV_IS_ASYNC(dev) \ 287 ((getminor(dev) & AV1394_MINOR_TYPE_MASK) != 0) 288 #define AV1394_DEV2INST(dev) \ 289 ((getminor(dev)) & ~AV1394_MINOR_TYPE_MASK) 290 291 /* misc constants */ 292 enum { 293 AV1394_CLEANUP_LEVEL_MAX = 256 294 }; 295 296 /* current interface version */ 297 #define AV1394_IEC61883_VER IEC61883_V1_0 298 299 /* TNF probes */ 300 #define AV1394_TNF_FCP "1394 av1394 fcp " 301 #define AV1394_TNF_FCP_STACK "1394 av1394 fcp stacktrace " 302 #define AV1394_TNF_FCP_ERROR "1394 av1394 fcp error " 303 #define AV1394_TNF_ASYNC "1394 av1394 async " 304 #define AV1394_TNF_ASYNC_STACK "1394 av1394 async stacktrace " 305 #define AV1394_TNF_ASYNC_ERROR "1394 av1394 async error " 306 #define AV1394_TNF_INST "1394 av1394 inst " 307 #define AV1394_TNF_INST_STACK "1394 av1394 inst stacktrace " 308 #define AV1394_TNF_INST_ERROR "1394 av1394 inst error " 309 310 /* misc */ 311 #define NELEM(a) (sizeof (a) / sizeof (*(a))) 312 313 314 /* double-linked list */ 315 void av1394_list_init(av1394_list_t *lp); 316 void *av1394_list_head(av1394_list_t *lp); 317 void av1394_list_put_tail(av1394_list_t *lp, void *item); 318 void av1394_list_put_head(av1394_list_t *lp, void *item); 319 void *av1394_list_get_head(av1394_list_t *lp); 320 321 /* queue */ 322 void av1394_initq(av1394_queue_t *q, ddi_iblock_cookie_t ibc, int max); 323 void av1394_destroyq(av1394_queue_t *q); 324 void av1394_setmaxq(av1394_queue_t *q, int max); 325 int av1394_getmaxq(av1394_queue_t *q); 326 void av1394_flushq(av1394_queue_t *q); 327 int av1394_putq(av1394_queue_t *q, mblk_t *bp); 328 int av1394_putbq(av1394_queue_t *q, mblk_t *bp); 329 mblk_t *av1394_getq(av1394_queue_t *q); 330 mblk_t *av1394_peekq(av1394_queue_t *q); 331 mblk_t *av1394_peekq_locked(av1394_queue_t *q); 332 int av1394_qwait_sig(av1394_queue_t *q); 333 334 /* FCP */ 335 int av1394_fcp_attach(av1394_inst_t *); 336 void av1394_fcp_detach(av1394_inst_t *); 337 int av1394_fcp_open(av1394_inst_t *, int); 338 int av1394_fcp_close(av1394_inst_t *, int); 339 int av1394_fcp_write(av1394_inst_t *, iec61883_arq_t *, struct uio *); 340 341 /* config ROM */ 342 int av1394_cfgrom_init(av1394_inst_t *); 343 void av1394_cfgrom_fini(av1394_inst_t *); 344 void av1394_cfgrom_close(av1394_inst_t *); 345 int av1394_ioctl_node_get_bus_name(av1394_inst_t *, void *, int); 346 int av1394_ioctl_node_get_uid(av1394_inst_t *, void *, int); 347 int av1394_ioctl_node_get_text_leaf(av1394_inst_t *, void *, int); 348 349 /* async module */ 350 int av1394_async_attach(av1394_inst_t *); 351 void av1394_async_detach(av1394_inst_t *); 352 int av1394_async_cpr_suspend(av1394_inst_t *); 353 int av1394_async_cpr_resume(av1394_inst_t *); 354 void av1394_async_bus_reset(av1394_inst_t *); 355 void av1394_async_disconnect(av1394_inst_t *); 356 void av1394_async_reconnect(av1394_inst_t *); 357 int av1394_async_open(av1394_inst_t *, int); 358 int av1394_async_close(av1394_inst_t *, int); 359 int av1394_async_read(av1394_inst_t *, struct uio *); 360 int av1394_async_write(av1394_inst_t *, struct uio *); 361 int av1394_async_ioctl(av1394_inst_t *, int, intptr_t, int, int *); 362 int av1394_async_poll(av1394_inst_t *, short, int, short *, 363 struct pollhead **); 364 void av1394_async_putq_rq(av1394_inst_t *, mblk_t *); 365 366 #ifdef __cplusplus 367 } 368 #endif 369 370 #endif /* _SYS_1394_TARGETS_AV1394_IMPL_H */ 371