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_ISOCH_H 27 #define _SYS_1394_TARGETS_AV1394_ISOCH_H 28 29 /* 30 * isoch module definitions 31 */ 32 33 #include <sys/note.h> 34 35 #ifdef __cplusplus 36 extern "C" { 37 #endif 38 39 #define COOKIES 100 40 41 /* 42 * isoch DMA memory management: segments and pools 43 * 44 * isoch segment - a contiguous chunk of kernel memory 45 */ 46 typedef struct av1394_isoch_seg_s { 47 caddr_t is_kaddr; /* segment kernel virt addr */ 48 int is_size; /* segment size */ 49 ddi_umem_cookie_t is_umem_cookie; /* umem cookie */ 50 size_t is_umem_size; /* umem size (page-aligned) */ 51 ddi_dma_handle_t is_dma_hdl; /* bind handle */ 52 ddi_dma_cookie_t is_dma_cookie[COOKIES]; 53 /* dma cookie */ 54 uint_t is_dma_ncookies; 55 /* # of cookies */ 56 } av1394_isoch_seg_t; 57 58 /* 59 * isoch pool - a set of one or more isoch segments 60 */ 61 typedef struct av1394_isoch_pool_s { 62 av1394_isoch_seg_t *ip_seg; /* array of segments */ 63 int ip_nsegs; /* # of valid segments */ 64 int ip_alloc_size; /* array alloc'd size */ 65 int ip_size; /* total pool size */ 66 int ip_umem_size; /* total alloc'd memory size */ 67 } av1394_isoch_pool_t; 68 69 /* 70 * many members are protected because they are modified during channel 71 * initialization or/and during isoch transfer, both of which are 72 * single-threaded processes. after that these members remain read-only. 73 */ 74 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_isoch_seg_s)) 75 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_isoch_pool_s)) 76 77 /* 78 * IXL receive data block (one or more RECV_BUF commands will follow the label) 79 */ 80 typedef struct av1394_ir_ixl_data_s { 81 ixl1394_label_t rd_label; 82 ixl1394_callback_t rd_cb; /* buffer completion callback */ 83 ixl1394_jump_t rd_jump; /* next command */ 84 } av1394_ir_ixl_data_t; 85 86 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_ir_ixl_data_s)) 87 88 /* 89 * isoch receive structure 90 */ 91 typedef struct av1394_ir_s { 92 av1394_isoch_pool_t ir_data_pool; /* pool for data packets */ 93 /* IXL */ 94 ixl1394_command_t *ir_ixlp; /* IXL chain */ 95 av1394_ir_ixl_data_t *ir_ixl_data; /* data block array */ 96 ixl1394_xfer_buf_t *ir_ixl_buf; /* RECV_BUF command array */ 97 int ir_ixl_nbufs; /* # of commands in array */ 98 size_t ir_ixl_bpf; /* # of buffers per frame - 1 */ 99 size_t ir_ixl_bufsz; /* buffer size */ 100 size_t ir_ixl_tailsz; /* tail buffer size */ 101 /* xfer */ 102 int ir_nfull; /* # of full frames */ 103 int ir_first_full; /* first full frame */ 104 int ir_nempty; /* # of empty frames */ 105 int ir_last_empty; /* last produced frame */ 106 int ir_hiwat; /* high water mark */ 107 int ir_lowat; /* low water mark */ 108 int ir_overflow_idx; /* overflow frame index */ 109 /* read() support */ 110 int ir_read_idx; /* first full frame */ 111 int ir_read_cnt; /* number of full frames */ 112 off_t ir_read_off; /* offset into the frame */ 113 } av1394_ir_t; 114 115 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_ir_s::{ 116 ir_ixlp 117 ir_ixl_buf 118 ir_ixl_nbufs 119 ir_ixl_bpf 120 ir_ixl_bufsz 121 ir_ixl_tailsz 122 })) 123 124 /* 125 * IXL transmit begin block, used to get a starting point for timestamping 126 */ 127 enum { AV1394_IT_IXL_BEGIN_NPOST = 3 }; 128 129 typedef struct av1394_it_ixl_begin_s { 130 ixl1394_label_t be_label; 131 ixl1394_xfer_pkt_t be_empty_pre; /* needed for next command */ 132 ixl1394_store_timestamp_t be_store_ts; /* store timestamp */ 133 ixl1394_callback_t be_cb; /* timestamp handling */ 134 ixl1394_xfer_pkt_t be_empty_post[AV1394_IT_IXL_BEGIN_NPOST]; 135 ixl1394_jump_t be_jump; /* next command */ 136 } av1394_it_ixl_begin_t; 137 138 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_ixl_begin_s)) 139 140 /* 141 * common part of transmit commands that are in a linked list 142 */ 143 typedef struct av1394_it_ixl_common_s { 144 struct av1394_it_ixl_common_s *tc_next; /* next in the list */ 145 int tc_size; /* structure size */ 146 } av1394_it_ixl_common_t; 147 148 /* 149 * IXL transmit data block 150 */ 151 typedef struct av1394_it_ixl_buf_s { 152 av1394_it_ixl_common_t tb_common; 153 int tb_flags; 154 int tb_framenum; /* frame number */ 155 struct av1394_ic_s *tb_icp; 156 ixl1394_label_t tb_label; 157 ixl1394_xfer_buf_t tb_buf; /* transmit packets */ 158 ixl1394_store_timestamp_t tb_store_ts; /* cycle time feedback */ 159 ixl1394_callback_t tb_cb; /* callback */ 160 ixl1394_jump_t tb_jump; /* next command */ 161 } av1394_it_ixl_buf_t; 162 163 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_ixl_buf_s)) 164 165 /* tb_flags */ 166 enum { 167 AV1394_IT_IXL_BUF_NEXT_EMPTY = 0x01, /* followed by empty CIP */ 168 AV1394_IT_IXL_BUF_SOF = 0x02, /* start of frame */ 169 AV1394_IT_IXL_BUF_EOF = 0x04 /* end of frame */ 170 }; 171 172 /* 173 * empty CIP 174 */ 175 typedef struct av1394_it_ixl_empty_cip_s { 176 av1394_it_ixl_common_t te_common; 177 ixl1394_label_t te_label; 178 ixl1394_xfer_pkt_t te_pkt; 179 ixl1394_jump_t te_jump; /* next command */ 180 } av1394_it_ixl_empty_cip_t; 181 182 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_ixl_empty_cip_s)) 183 184 /* 185 * per-frame information 186 */ 187 typedef struct av1394_it_frame_info_s { 188 caddr_t fi_ts_off; /* where to put a timestamp */ 189 int fi_ncycs; /* # of bus cycles */ 190 av1394_it_ixl_buf_t *fi_first_buf; /* first IXL buffer */ 191 av1394_it_ixl_buf_t *fi_last_buf; /* last IXL buffer */ 192 } av1394_it_frame_info_t; 193 194 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_frame_info_s)) 195 196 /* 197 * timestamp type 198 */ 199 typedef union av1394_it_ts { 200 uint16_t ts_syt; /* SYT timestamp */ 201 } av1394_it_ts_t; 202 203 /* 204 * isoch transmit structure 205 */ 206 typedef struct av1394_it_s { 207 av1394_isoch_pool_t it_data_pool; /* pool for data packets */ 208 /* IXL */ 209 ixl1394_command_t *it_ixlp; /* IXL chain */ 210 av1394_it_ixl_begin_t it_ixl_begin; /* begin block */ 211 av1394_it_ixl_common_t *it_ixl_data; /* data block */ 212 av1394_it_frame_info_t *it_frame_info; /* frame info array */ 213 av1394_it_ixl_empty_cip_t *it_skipped_cip; /* last skipped CIP */ 214 /* xfer */ 215 int it_first_empty; /* first empty frame # */ 216 int it_nempty; /* # of empty frames */ 217 int it_last_full; /* last full frame # */ 218 int it_nfull; /* # of full frames */ 219 int it_hiwat; /* high water mark */ 220 int it_lowat; /* low water mark */ 221 int it_start_thre; /* xfer start threshold */ 222 av1394_it_ts_t it_ts_init; /* initial timestamp */ 223 /* underrun data */ 224 int it_underrun_idx; /* underrun frame index */ 225 ixl1394_command_t *it_saved_label; /* saved buffer label */ 226 /* write() support */ 227 int it_write_idx; /* first empty frame */ 228 int it_write_cnt; /* # of empty frames */ 229 off_t it_write_off; /* offset into the frame */ 230 } av1394_it_t; 231 232 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_it_s::{ 233 it_ixlp 234 it_ixl_begin 235 it_ixl_data 236 it_frame_info 237 it_ts_init 238 it_skipped_cip 239 })) 240 241 /* misc channel parameters */ 242 typedef struct av1394_ic_param_s { 243 int cp_bus_speed; /* bus speed */ 244 int cp_dbs; /* DBS */ 245 int cp_fn; /* FN */ 246 int cp_n; /* rate numerator */ 247 int cp_d; /* rate denominator */ 248 int cp_ts_mode; /* timestamp mode */ 249 } av1394_ic_param_t; 250 251 /* channel state */ 252 typedef enum { 253 AV1394_IC_IDLE, /* nothing happens */ 254 AV1394_IC_STARTED, /* channel has been started */ 255 AV1394_IC_DMA, /* DMA transfer is in progress */ 256 AV1394_IC_SUSPENDED /* transfer on the channel suspended */ 257 } av1394_ic_state_t; 258 259 /* 260 * isoch channel structure, common for both recv and xmit 261 */ 262 typedef struct av1394_ic_s { 263 kmutex_t ic_mutex; /* structure mutex */ 264 struct av1394_inst_s *ic_avp; /* backpointer to instance */ 265 int ic_num; /* channel # */ 266 int ic_dir; /* xfer direction */ 267 av1394_ic_state_t ic_state; /* state */ 268 int ic_pktsz; /* packet size */ 269 int ic_npkts; /* # of packets/frame */ 270 size_t ic_framesz; /* frame size (pktsz * npkts) */ 271 int ic_nframes; /* # of frames */ 272 av1394_ic_param_t ic_param; /* misc parameters */ 273 size_t ic_mmap_sz; /* mmap size */ 274 off_t ic_mmap_off; /* mmap offset */ 275 t1394_isoch_single_handle_t ic_sii_hdl; /* isoch single handle */ 276 t1394_isoch_dma_handle_t ic_isoch_hdl; /* 1394 isoch handle */ 277 kcondvar_t ic_xfer_cv; /* xfer cv */ 278 int ic_preq; /* postponed request */ 279 av1394_ir_t ic_ir; /* recv */ 280 av1394_it_t ic_it; /* xmit */ 281 } av1394_ic_t; 282 283 _NOTE(MUTEX_PROTECTS_DATA(av1394_ic_s::ic_mutex, av1394_ic_s)) 284 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_ic_s::{ 285 ic_avp 286 ic_num 287 ic_dir 288 ic_sii_hdl 289 ic_isoch_hdl 290 ic_pktsz 291 ic_npkts 292 ic_framesz 293 ic_nframes 294 ic_param 295 ic_mmap_sz 296 ic_mmap_off 297 })) 298 299 /* xfer directions */ 300 enum { 301 AV1394_IR, 302 AV1394_IT 303 }; 304 305 /* CIP type */ 306 enum { 307 AV1394_CIP_FULL, 308 AV1394_CIP_EMPTY 309 }; 310 311 /* misc constants */ 312 enum { 313 AV1394_IC_FRAME_SIZE_MAX = 1024 * 1024, /* max frame size */ 314 AV1394_MEM_MAX_PERCENT = (100/10), /* max percent of physmem */ 315 AV1394_SEGSZ_MAX_SHIFT = 16, /* maximum segment size */ 316 AV1394_SEGSZ_MAX = (1UL << AV1394_SEGSZ_MAX_SHIFT), 317 AV1394_SEGSZ_MAX_OFFSET = AV1394_SEGSZ_MAX - 1, 318 AV1394_IXL_BUFSZ_MAX = 57344, /* max buf size (uint16_t) */ 319 /* 57344 is ptob(btop(65535)) */ 320 AV1394_IR_NFRAMES_MIN = 3, /* minimum frame count */ 321 AV1394_IT_NFRAMES_MIN = 3, /* minimum frame count */ 322 AV1394_CIPSZ = 8, /* CIP header size */ 323 AV1394_DV_NTSC_FRAMESZ = 250, /* DV-NTSC frame size in pkts */ 324 AV1394_DV_PAL_FRAMESZ = 300 /* DV-PAL frame size in pkts */ 325 }; 326 327 #define AV1394_TS_MODE_GET_OFF(mode) ((mode) & 0xff) 328 #define AV1394_TS_MODE_GET_SIZE(mode) (((mode) >> 8) & 0xff) 329 330 /* private ISOCH_INIT flag */ 331 #define IEC61883_PRIV_ISOCH_NOALLOC 0x40000000 332 333 /* 334 * autoxmit (isoch xmit via write(2)) support 335 */ 336 typedef struct av1394_isoch_autoxmit_s { 337 uchar_t ax_ciph[AV1394_CIPSZ]; /* first CIP hdr */ 338 boolean_t ax_copy_ciph; /* need to copy hdr */ 339 int ax_fmt; /* data format */ 340 } av1394_isoch_autoxmit_t; 341 342 /* autoxmit formats */ 343 enum { 344 AV1394_ISOCH_AUTOXMIT_DV = 0x10, 345 AV1394_ISOCH_AUTOXMIT_UNKNOWN = 0, 346 AV1394_ISOCH_AUTOXMIT_DV_NTSC = 1 | AV1394_ISOCH_AUTOXMIT_DV, 347 AV1394_ISOCH_AUTOXMIT_DV_PAL = 2 | AV1394_ISOCH_AUTOXMIT_DV 348 }; 349 350 351 /* 352 * User processes calling mmap(2) pass the 'offset' and 'len' arguments, 353 * returned by IEC61883_ISOCH_INIT ioctl. These arguments uniquely identify 354 * the DMA buffer associated with a channel. For each isochronous channel 355 * a part of this "address space" should be allocated to prevent conflicts 356 * with other channels. 357 */ 358 typedef struct av1394_as_s { 359 off_t as_end; /* address space end */ 360 } av1394_as_t; 361 362 363 /* 364 * CMP (Connection Management Procedures) 365 * 366 * PCR address map (Ref: IEC 61883-1 Fig 14) 367 */ 368 #define AV1394_PCR_ADDR_START 0xFFFFF0000900 369 #define AV1394_PCR_ADDR_OMPR 0xFFFFF0000900 370 #define AV1394_PCR_ADDR_OPCR0 0xFFFFF0000904 371 #define AV1394_PCR_ADDR_NOPCR 31 372 #define AV1394_PCR_ADDR_IMPR 0xFFFFF0000980 373 #define AV1394_PCR_ADDR_IPCR0 0xFFFFF0000984 374 #define AV1394_PCR_ADDR_NIPCR 31 375 376 /* initial values and bus reset masks (Ref: IEC 61883-1 Fig 10-13) */ 377 #define AV1394_OMPR_INIT_VAL 0xBFFFFF00 378 #define AV1394_IMPR_INIT_VAL 0x80FFFF00 379 #define AV1394_PCR_INIT_VAL 0x00000000 /* both iPCR and oPCR */ 380 #define AV1394_OPCR_BR_CLEAR_MASK 0x7FC03C00 381 #define AV1394_IPCR_BR_CLEAR_MASK 0x7FC0FFFF 382 383 /* 384 * local plug control register 385 */ 386 typedef struct av1394_pcr_s { 387 uint32_t pcr_val; /* value */ 388 t1394_addr_handle_t pcr_addr_hdl; /* address handle */ 389 } av1394_pcr_t; 390 391 enum { 392 AV1394_OMPR_IDX = 0, /* oMPR index */ 393 AV1394_OPCR0_IDX = 1, /* oPCR0 index */ 394 AV1394_IMPR_IDX = 32, /* iMPR index */ 395 AV1394_IPCR0_IDX = 33, /* iPCR0 index */ 396 AV1394_NPCR = 64 /* total number of PCRs */ 397 }; 398 399 /* plug handle manipulation */ 400 enum { 401 AV1394_PCR_REMOTE = 0x40000000 402 }; 403 404 /* 405 * per-instance CMP structure 406 */ 407 typedef struct av1394_cmp_s { 408 krwlock_t cmp_pcr_rwlock; /* rwlock for PCRs */ 409 av1394_pcr_t *cmp_pcr[AV1394_NPCR]; /* array of PCRs */ 410 } av1394_cmp_t; 411 412 _NOTE(SCHEME_PROTECTS_DATA("cmp_pcr_rwlock", av1394_cmp_s::cmp_pcr)) 413 414 415 /* 416 * per-instance soft state structure 417 */ 418 typedef struct av1394_isoch_s { 419 kmutex_t i_mutex; /* structure mutex */ 420 int i_nopen; /* number of opens */ 421 av1394_cmp_t i_cmp; /* CMP information */ 422 av1394_ic_t *i_ic[64]; /* array of channels */ 423 av1394_as_t i_mmap_as; /* mmap virtual addr space */ 424 ddi_softintr_t i_softintr_id; /* soft interrupt id */ 425 uint64_t i_softintr_ch; /* channels to service */ 426 av1394_isoch_autoxmit_t i_autoxmit; /* autoxmit support */ 427 } av1394_isoch_t; 428 429 _NOTE(MUTEX_PROTECTS_DATA(av1394_isoch_s::i_mutex, av1394_isoch_s)) 430 _NOTE(DATA_READABLE_WITHOUT_LOCK(av1394_isoch_s::{ 431 i_ic 432 i_softintr_id 433 })) 434 _NOTE(SCHEME_PROTECTS_DATA("single-threaded", av1394_isoch_autoxmit_s)) 435 436 _NOTE(LOCK_ORDER(av1394_isoch_s::i_mutex av1394_ic_s::ic_mutex)) 437 438 /* postponed request types */ 439 enum { 440 AV1394_PREQ_IR_OVERFLOW = 0x01, 441 AV1394_PREQ_IT_UNDERRUN = 0x02 442 }; 443 444 /* isoch channel */ 445 int av1394_ic_open(struct av1394_inst_s *, int); 446 int av1394_ic_close(struct av1394_inst_s *, int); 447 int av1394_ic_init(struct av1394_inst_s *avp, iec61883_isoch_init_t *ii, 448 av1394_ic_t **icpp); 449 void av1394_ic_fini(av1394_ic_t *icp); 450 int av1394_ic_alloc_pool(av1394_isoch_pool_t *pool, size_t segsz, int cnt, 451 int mincnt); 452 void av1394_ic_free_pool(av1394_isoch_pool_t *pool); 453 int av1394_ic_dma_setup(av1394_ic_t *icp, av1394_isoch_pool_t *pool); 454 void av1394_ic_dma_cleanup(av1394_ic_t *icp, av1394_isoch_pool_t *pool); 455 int av1394_ic_ixl_seg_decomp(size_t segsz, size_t pktsz, size_t *bufszp, 456 size_t *tailszp); 457 void av1394_ic_dma_sync_frames(av1394_ic_t *icp, int idx, int cnt, 458 av1394_isoch_pool_t *pool, uint_t type); 459 int av1394_ic_start(av1394_ic_t *icp); 460 int av1394_ic_stop(av1394_ic_t *icp); 461 void av1394_ic_ixl_dump(ixl1394_command_t *cmd); 462 void av1394_ic_trigger_softintr(av1394_ic_t *icp, int num, int preq); 463 464 /* isoch receive */ 465 int av1394_ir_init(av1394_ic_t *icp, int *error); 466 void av1394_ir_fini(av1394_ic_t *icp); 467 int av1394_ir_start(av1394_ic_t *icp); 468 int av1394_ir_stop(av1394_ic_t *icp); 469 int av1394_ir_recv(av1394_ic_t *icp, iec61883_recv_t *recv); 470 int av1394_ir_read(av1394_ic_t *icp, struct uio *uiop); 471 void av1394_ir_overflow(av1394_ic_t *icp); 472 473 /* isoch transmit */ 474 int av1394_it_init(av1394_ic_t *icp, int *error); 475 void av1394_it_fini(av1394_ic_t *icp); 476 int av1394_it_start(av1394_ic_t *icp); 477 int av1394_it_stop(av1394_ic_t *icp); 478 int av1394_it_xmit(av1394_ic_t *icp, iec61883_xmit_t *xmit); 479 int av1394_it_write(av1394_ic_t *icp, struct uio *uiop); 480 void av1394_it_underrun(av1394_ic_t *icp); 481 482 /* address space for mmap(2) */ 483 void av1394_as_init(av1394_as_t *as); 484 void av1394_as_fini(av1394_as_t *as); 485 off_t av1394_as_alloc(av1394_as_t *as, size_t size); 486 void av1394_as_free(av1394_as_t *as, off_t); 487 488 /* CMP */ 489 int av1394_cmp_init(struct av1394_inst_s *avp); 490 void av1394_cmp_fini(struct av1394_inst_s *avp); 491 void av1394_cmp_bus_reset(struct av1394_inst_s *avp); 492 void av1394_cmp_close(struct av1394_inst_s *avp); 493 int av1394_ioctl_plug_init(struct av1394_inst_s *, void *, int); 494 int av1394_ioctl_plug_fini(struct av1394_inst_s *, void *, int); 495 int av1394_ioctl_plug_reg_read(struct av1394_inst_s *, void *, int); 496 int av1394_ioctl_plug_reg_cas(struct av1394_inst_s *, void *, int); 497 498 /* isoch common */ 499 int av1394_isoch_attach(struct av1394_inst_s *); 500 void av1394_isoch_detach(struct av1394_inst_s *); 501 int av1394_isoch_cpr_suspend(struct av1394_inst_s *); 502 int av1394_isoch_cpr_resume(struct av1394_inst_s *); 503 void av1394_isoch_bus_reset(struct av1394_inst_s *); 504 void av1394_isoch_disconnect(struct av1394_inst_s *); 505 void av1394_isoch_reconnect(struct av1394_inst_s *); 506 int av1394_isoch_open(struct av1394_inst_s *, int); 507 int av1394_isoch_close(struct av1394_inst_s *, int); 508 int av1394_isoch_read(struct av1394_inst_s *, struct uio *); 509 int av1394_isoch_write(struct av1394_inst_s *, struct uio *); 510 int av1394_isoch_ioctl(struct av1394_inst_s *, int, intptr_t, int, int *); 511 int av1394_isoch_devmap(struct av1394_inst_s *, devmap_cookie_t, offset_t, 512 size_t, size_t *, uint_t); 513 514 #ifdef __cplusplus 515 } 516 #endif 517 518 #endif /* _SYS_1394_TARGETS_AV1394_ISOCH_H */ 519