/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* routines common to isoch receive and isoch transmit
*/
/* configuration routines */
/* callbacks */
/* tunables */
extern int av1394_rate_n_dv_ntsc;
extern int av1394_rate_d_dv_ntsc;
extern int av1394_rate_n_dv_pal;
extern int av1394_rate_d_dv_pal;
/*ARGSUSED*/
int
{
int i;
/* cleanup channels in case application didn't */
(void) av1394_ic_stop(icp);
}
}
return (0);
}
/*
* av1394_ic_init()
* Channel allocation and initialization.
*/
int
av1394_ic_t **icpp)
{
int num;
int ret;
ii->ii_frame_rcnt = 0;
ii->ii_rchannel = 0;
return (ret);
}
/* allocate channel structure */
/* allocate isoch channel and bandwidth, except for broadcast */
num = 63;
} else {
if (ret != DDI_SUCCESS) {
return (EINVAL);
}
}
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
/* do direction specific initialization */
} else {
}
if (ret != 0) {
return (ret);
}
/* allocate mmap space */
return (0);
}
void
{
}
/*
*
* --- configuration routines
*
*/
static void
{
switch (level) {
default:
} else {
}
/* FALLTHRU */
case 3:
/* FALLTHRU */
case 2:
/* FALLTHRU */
case 1:
}
}
static int
{
int framesz;
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
if (framesz > AV1394_IC_FRAME_SIZE_MAX) {
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
if (ii->ii_channel == 0) {
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
/* the rest are xmit only */
return (0);
}
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
AV1394_TNF_ISOCH_ERROR, "");
return (EINVAL);
}
return (0);
}
static void
{
case IEC61883_RATE_N_DV_NTSC:
break;
case IEC61883_RATE_N_DV_PAL:
break;
default:
ASSERT(0); /* can't happen */
}
} else {
}
}
}
static int
{
/* allocate isoch channel */
if (ret != DDI_SUCCESS) {
} else {
}
return (ret);
}
static void
{
}
}
/*
*
* --- memory allocation and mapping routines
*
* av1394_ic_alloc_pool()
* Allocate isoch pool for at least 'mincnt' and at most 'cnt' frames
* 'framesz' bytes each. The strategy is to allocate segments of reasonably
* large size, to avoid fragmentation and use resources efficiently in case
* of a large number of very small frames.
*
* amount of buffer space (AV1394_IXL_BUFSZ_MAX), and if segment size and
* buffer size are not aligned, it can make much harder to build IXL chains.
* To simplify things, segments shall always contain full frames.
*
* Function returns number of frames the resulting pool can hold.
*/
int
int mincnt)
{
int nsegs;
int i;
int ret;
/* request should be reasonable */
AV1394_TNF_ISOCH_ERROR, "");
return (0);
}
/* calculate segment size and number of segments */
nsegs++; /* remainder in non-full segment */
}
/* allocate segment array */
/* allocate page-aligned user-mappable memory for each segment */
pool->ip_umem_size = 0;
for (i = 0; i < nsegs; i++) {
AV1394_TNF_ISOCH_ERROR, "");
break;
}
}
/* number of frames the pool can hold */
AV1394_TNF_ISOCH_ERROR, "");
ret = 0;
}
return (ret);
}
void
{
int i;
}
}
}
int
{
int ret;
int i;
int j;
/*
* Alloc and bind a DMA handle for each segment.
* Note that we need packet size alignment, but since ddi_umem_alloc'ed
* memory is page-aligned and our packets are less than page size (yet)
* we don't need to do anything special here.
*/
&isp->is_dma_hdl);
if (ret != DDI_SUCCESS) {
AV1394_TNF_ISOCH_ERROR, "");
return (ret);
}
if (ret != DDI_DMA_MAPPED) {
AV1394_TNF_ISOCH_ERROR, "");
return (DDI_FAILURE);
}
AV1394_TNF_ISOCH_ERROR, "");
return (DDI_FAILURE);
}
&isp->is_dma_cookie[j]);
}
return (DDI_SUCCESS);
}
/*ARGSUSED*/
void
{
int i;
if (seg->is_dma_ncookies > 0) {
}
}
}
}
/*
* sync frames for CPU access
*/
void
{
for (;;) {
--nsegs;
if (nsegs == 0)
break;
++seg;
seg = 0; /* wrap segment index */
}
}
/*
*
* --- transfer
*
*/
int
{
return (av1394_ir_start(icp));
} else {
return (av1394_it_start(icp));
}
}
int
{
return (av1394_ir_stop(icp));
} else {
return (av1394_it_stop(icp));
}
}
/*
*
* --- callbacks
*
*/
/*ARGSUSED*/
static void
{
/* XXX this could be handled more gracefully */
" after bus reset\n");
}
/*
*
* --- misc
*
*
* av1394_ic_ixl_seg_decomp()
* Calculate the best decomposition of a segment into buffers.
* Return number of buffers, buffer and tail buffer sizes.
*
* We are looking to divide a segment evenly into equally-sized or almost
* equally-sized buffers. Maximum buffer size is AV1394_IXL_BUFSZ_MAX.
* Algorithm:
* 1. If segment size divides evenly by maximum size, terminate.
* 2. n = number of maximum-size buffers than fits into the segment.
* 3. Divide the segment by n+1, calculate buffer size and tail
* (remainder) size.
* 4. If the tail can be appended to the last buffer and the resulting
* buffer is still less than maximum size, terminate.
* 5. Repeat steps 3-5 for n+2, n+3, ... until division is too small.
*
* Since all sizes are packet-aligned, we scale them down (divide by
* packet size) in the beginning, do all calculations and scale them up
* in the end.
*/
int
{
}
do {
nbufs++;
nbufs--;
return (nbufs);
}
void
{
while (cmd) {
switch (cmd->ixl_opcode) {
case IXL1394_OP_LABEL:
break;
case IXL1394_OP_RECV_BUF:
case IXL1394_OP_RECV_BUF_U:
break;
case IXL1394_OP_SEND_BUF:
case IXL1394_OP_SEND_BUF_U:
break;
case IXL1394_OP_SEND_PKT_ST:
break;
case IXL1394_OP_CALLBACK:
case IXL1394_OP_CALLBACK_U:
break;
case IXL1394_OP_JUMP:
break;
case IXL1394_OP_JUMP_U:
break;
break;
default:
}
}
}
/*
* trigger a soft interrupt, if not already, for a given channel and type
*/
void
{
}
}
/*
* reverse bits in a 64-bit word
*/
{
x = (((x >> 1) & 0x5555555555555555) | ((x & 0x5555555555555555) << 1));
x = (((x >> 2) & 0x3333333333333333) | ((x & 0x3333333333333333) << 2));
x = (((x >> 4) & 0x0f0f0f0f0f0f0f0f) | ((x & 0x0f0f0f0f0f0f0f0f) << 4));
x = (((x >> 8) & 0x00ff00ff00ff00ff) | ((x & 0x00ff00ff00ff00ff) << 8));
x = (((x >> 16) & 0x0000ffff0000ffff) |
((x & 0x0000ffff0000ffff) << 16));
return ((x >> 32) | (x << 32));
}
/*
* return B_TRUE if a 64-bit value has only one bit set to 1
*/
{
return (((~i + 1) | ~i) == 0xFFFFFFFFFFFFFFFF);
}