linux/drivers/ieee1394/dv1394-private.h
Linus Torvalds 1da177e4c3 Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
2005-04-16 15:20:36 -07:00

588 lines
17 KiB
C

/*
* dv1394-private.h - DV input/output over IEEE 1394 on OHCI chips
* Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
* receive by Dan Dennedy <dan@dennedy.org>
*
* based on:
* video1394.h - driver for OHCI 1394 boards
* Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
* Peter Schlaile <udbz@rz.uni-karlsruhe.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _DV_1394_PRIVATE_H
#define _DV_1394_PRIVATE_H
#include "ieee1394.h"
#include "ohci1394.h"
#include "dma.h"
/* data structures private to the dv1394 driver */
/* none of this is exposed to user-space */
/*
the 8-byte CIP (Common Isochronous Packet) header that precedes
each packet of DV data.
See the IEC 61883 standard.
*/
struct CIP_header { unsigned char b[8]; };
static inline void fill_cip_header(struct CIP_header *cip,
unsigned char source_node_id,
unsigned long counter,
enum pal_or_ntsc format,
unsigned long timestamp)
{
cip->b[0] = source_node_id;
cip->b[1] = 0x78; /* packet size in quadlets (480/4) - even for empty packets! */
cip->b[2] = 0x00;
cip->b[3] = counter;
cip->b[4] = 0x80; /* const */
switch(format) {
case DV1394_PAL:
cip->b[5] = 0x80;
break;
case DV1394_NTSC:
cip->b[5] = 0x00;
break;
}
cip->b[6] = timestamp >> 8;
cip->b[7] = timestamp & 0xFF;
}
/*
DMA commands used to program the OHCI's DMA engine
See the Texas Instruments OHCI 1394 chipset documentation.
*/
struct output_more_immediate { u32 q[8]; };
struct output_more { u32 q[4]; };
struct output_last { u32 q[4]; };
struct input_more { u32 q[4]; };
struct input_last { u32 q[4]; };
/* outputs */
static inline void fill_output_more_immediate(struct output_more_immediate *omi,
unsigned char tag,
unsigned char channel,
unsigned char sync_tag,
unsigned int payload_size)
{
omi->q[0] = cpu_to_le32(0x02000000 | 8); /* OUTPUT_MORE_IMMEDIATE; 8 is the size of the IT header */
omi->q[1] = 0;
omi->q[2] = 0;
omi->q[3] = 0;
/* IT packet header */
omi->q[4] = cpu_to_le32( (0x0 << 16) /* IEEE1394_SPEED_100 */
| (tag << 14)
| (channel << 8)
| (TCODE_ISO_DATA << 4)
| (sync_tag) );
/* reserved field; mimic behavior of my Sony DSR-40 */
omi->q[5] = cpu_to_le32((payload_size << 16) | (0x7F << 8) | 0xA0);
omi->q[6] = 0;
omi->q[7] = 0;
}
static inline void fill_output_more(struct output_more *om,
unsigned int data_size,
unsigned long data_phys_addr)
{
om->q[0] = cpu_to_le32(data_size);
om->q[1] = cpu_to_le32(data_phys_addr);
om->q[2] = 0;
om->q[3] = 0;
}
static inline void fill_output_last(struct output_last *ol,
int want_timestamp,
int want_interrupt,
unsigned int data_size,
unsigned long data_phys_addr)
{
u32 temp = 0;
temp |= 1 << 28; /* OUTPUT_LAST */
if (want_timestamp) /* controller will update timestamp at DMA time */
temp |= 1 << 27;
if (want_interrupt)
temp |= 3 << 20;
temp |= 3 << 18; /* must take branch */
temp |= data_size;
ol->q[0] = cpu_to_le32(temp);
ol->q[1] = cpu_to_le32(data_phys_addr);
ol->q[2] = 0;
ol->q[3] = 0;
}
/* inputs */
static inline void fill_input_more(struct input_more *im,
int want_interrupt,
unsigned int data_size,
unsigned long data_phys_addr)
{
u32 temp = 2 << 28; /* INPUT_MORE */
temp |= 8 << 24; /* s = 1, update xferStatus and resCount */
if (want_interrupt)
temp |= 0 << 20; /* interrupts, i=0 in packet-per-buffer mode */
temp |= 0x0 << 16; /* disable branch to address for packet-per-buffer mode */
/* disable wait on sync field, not used in DV :-( */
temp |= data_size;
im->q[0] = cpu_to_le32(temp);
im->q[1] = cpu_to_le32(data_phys_addr);
im->q[2] = 0; /* branchAddress and Z not use in packet-per-buffer mode */
im->q[3] = 0; /* xferStatus & resCount, resCount must be initialize to data_size */
}
static inline void fill_input_last(struct input_last *il,
int want_interrupt,
unsigned int data_size,
unsigned long data_phys_addr)
{
u32 temp = 3 << 28; /* INPUT_LAST */
temp |= 8 << 24; /* s = 1, update xferStatus and resCount */
if (want_interrupt)
temp |= 3 << 20; /* enable interrupts */
temp |= 0xC << 16; /* enable branch to address */
/* disable wait on sync field, not used in DV :-( */
temp |= data_size;
il->q[0] = cpu_to_le32(temp);
il->q[1] = cpu_to_le32(data_phys_addr);
il->q[2] = cpu_to_le32(1); /* branchAddress (filled in later) and Z = 1 descriptor in next block */
il->q[3] = cpu_to_le32(data_size); /* xferStatus & resCount, resCount must be initialize to data_size */
}
/*
A "DMA descriptor block" consists of several contiguous DMA commands.
struct DMA_descriptor_block encapsulates all of the commands necessary
to send one packet of DV data.
There are three different types of these blocks:
1) command to send an empty packet (CIP header only, no DV data):
OUTPUT_MORE-Immediate <-- contains the iso header in-line
OUTPUT_LAST <-- points to the CIP header
2) command to send a full packet when the DV data payload does NOT
cross a page boundary:
OUTPUT_MORE-Immediate <-- contains the iso header in-line
OUTPUT_MORE <-- points to the CIP header
OUTPUT_LAST <-- points to entire DV data payload
3) command to send a full packet when the DV payload DOES cross
a page boundary:
OUTPUT_MORE-Immediate <-- contains the iso header in-line
OUTPUT_MORE <-- points to the CIP header
OUTPUT_MORE <-- points to first part of DV data payload
OUTPUT_LAST <-- points to second part of DV data payload
This struct describes all three block types using unions.
!!! It is vital that an even number of these descriptor blocks fit on one
page of memory, since a block cannot cross a page boundary !!!
*/
struct DMA_descriptor_block {
union {
struct {
/* iso header, common to all output block types */
struct output_more_immediate omi;
union {
/* empty packet */
struct {
struct output_last ol; /* CIP header */
} empty;
/* full packet */
struct {
struct output_more om; /* CIP header */
union {
/* payload does not cross page boundary */
struct {
struct output_last ol; /* data payload */
} nocross;
/* payload crosses page boundary */
struct {
struct output_more om; /* data payload */
struct output_last ol; /* data payload */
} cross;
} u;
} full;
} u;
} out;
struct {
struct input_last il;
} in;
} u;
/* ensure that PAGE_SIZE % sizeof(struct DMA_descriptor_block) == 0
by padding out to 128 bytes */
u32 __pad__[12];
};
/* struct frame contains all data associated with one frame in the
ringbuffer these are allocated when the DMA context is initialized
do_dv1394_init(). They are re-used after the card finishes
transmitting the frame. */
struct video_card; /* forward declaration */
struct frame {
/* points to the struct video_card that owns this frame */
struct video_card *video;
/* index of this frame in video_card->frames[] */
unsigned int frame_num;
/* FRAME_CLEAR - DMA program not set up, waiting for data
FRAME_READY - DMA program written, ready to transmit
Changes to these should be locked against the interrupt
*/
enum {
FRAME_CLEAR = 0,
FRAME_READY
} state;
/* whether this frame has been DMA'ed already; used only from
the IRQ handler to determine whether the frame can be reset */
int done;
/* kernel virtual pointer to the start of this frame's data in
the user ringbuffer. Use only for CPU access; to get the DMA
bus address you must go through the video->user_dma mapping */
unsigned long data;
/* Max # of packets per frame */
#define MAX_PACKETS 500
/* a PAGE_SIZE memory pool for allocating CIP headers
!header_pool must be aligned to PAGE_SIZE! */
struct CIP_header *header_pool;
dma_addr_t header_pool_dma;
/* a physically contiguous memory pool for allocating DMA
descriptor blocks; usually around 64KB in size
!descriptor_pool must be aligned to PAGE_SIZE! */
struct DMA_descriptor_block *descriptor_pool;
dma_addr_t descriptor_pool_dma;
unsigned long descriptor_pool_size;
/* # of packets allocated for this frame */
unsigned int n_packets;
/* below are several pointers (kernel virtual addresses, not
DMA bus addresses) to parts of the DMA program. These are
set each time the DMA program is written in
frame_prepare(). They are used later on, e.g. from the
interrupt handler, to check the status of the frame */
/* points to status/timestamp field of first DMA packet */
/* (we'll check it later to monitor timestamp accuracy) */
u32 *frame_begin_timestamp;
/* the timestamp we assigned to the first packet in the frame */
u32 assigned_timestamp;
/* pointer to the first packet's CIP header (where the timestamp goes) */
struct CIP_header *cip_syt1;
/* pointer to the second packet's CIP header
(only set if the first packet was empty) */
struct CIP_header *cip_syt2;
/* in order to figure out what caused an interrupt,
store pointers to the status fields of the two packets
that can cause interrupts. We'll check these from the
interrupt handler.
*/
u32 *mid_frame_timestamp;
u32 *frame_end_timestamp;
/* branch address field of final packet. This is effectively
the "tail" in the chain of DMA descriptor blocks.
We will fill it with the address of the first DMA descriptor
block in the subsequent frame, once it is ready.
*/
u32 *frame_end_branch;
/* the number of descriptors in the first descriptor block
of the frame. Needed to start DMA */
int first_n_descriptors;
};
struct packet {
u16 timestamp;
u16 invalid;
u16 iso_header;
u16 data_length;
u32 cip_h1;
u32 cip_h2;
unsigned char data[480];
unsigned char padding[16]; /* force struct size =512 for page alignment */
};
/* allocate/free a frame */
static struct frame* frame_new(unsigned int frame_num, struct video_card *video);
static void frame_delete(struct frame *f);
/* reset f so that it can be used again */
static void frame_reset(struct frame *f);
/* struct video_card contains all data associated with one instance
of the dv1394 driver
*/
enum modes {
MODE_RECEIVE,
MODE_TRANSMIT
};
struct video_card {
/* ohci card to which this instance corresponds */
struct ti_ohci *ohci;
/* OHCI card id; the link between the VFS inode and a specific video_card
(essentially the device minor number) */
int id;
/* entry in dv1394_cards */
struct list_head list;
/* OHCI card IT DMA context number, -1 if not in use */
int ohci_it_ctx;
struct ohci1394_iso_tasklet it_tasklet;
/* register offsets for current IT DMA context, 0 if not in use */
u32 ohci_IsoXmitContextControlSet;
u32 ohci_IsoXmitContextControlClear;
u32 ohci_IsoXmitCommandPtr;
/* OHCI card IR DMA context number, -1 if not in use */
struct ohci1394_iso_tasklet ir_tasklet;
int ohci_ir_ctx;
/* register offsets for current IR DMA context, 0 if not in use */
u32 ohci_IsoRcvContextControlSet;
u32 ohci_IsoRcvContextControlClear;
u32 ohci_IsoRcvCommandPtr;
u32 ohci_IsoRcvContextMatch;
/* CONCURRENCY CONTROL */
/* there are THREE levels of locking associated with video_card. */
/*
1) the 'open' flag - this prevents more than one process from
opening the device. (the driver currently assumes only one opener).
This is a regular int, but use test_and_set_bit() (on bit zero)
for atomicity.
*/
unsigned long open;
/*
2) the spinlock - this provides mutual exclusion between the interrupt
handler and process-context operations. Generally you must take the
spinlock under the following conditions:
1) DMA (and hence the interrupt handler) may be running
AND
2) you need to operate on the video_card, especially active_frame
It is OK to play with video_card without taking the spinlock if
you are certain that DMA is not running. Even if DMA is running,
it is OK to *read* active_frame with the lock, then drop it
immediately. This is safe because the interrupt handler will never
advance active_frame onto a frame that is not READY (and the spinlock
must be held while marking a frame READY).
spinlock is also used to protect ohci_it_ctx and ohci_ir_ctx,
which can be accessed from both process and interrupt context
*/
spinlock_t spinlock;
/* flag to prevent spurious interrupts (which OHCI seems to
generate a lot :) from accessing the struct */
int dma_running;
/*
3) the sleeping semaphore 'sem' - this is used from process context only,
to serialize various operations on the video_card. Even though only one
open() is allowed, we still need to prevent multiple threads of execution
from entering calls like read, write, ioctl, etc.
I honestly can't think of a good reason to use dv1394 from several threads
at once, but we need to serialize anyway to prevent oopses =).
NOTE: if you need both spinlock and sem, take sem first to avoid deadlock!
*/
struct semaphore sem;
/* people waiting for buffer space, please form a line here... */
wait_queue_head_t waitq;
/* support asynchronous I/O signals (SIGIO) */
struct fasync_struct *fasync;
/* the large, non-contiguous (rvmalloc()) ringbuffer for DV
data, exposed to user-space via mmap() */
unsigned long dv_buf_size;
struct dma_region dv_buf;
/* next byte in the ringbuffer that a write() call will fill */
size_t write_off;
struct frame *frames[DV1394_MAX_FRAMES];
/* n_frames also serves as an indicator that this struct video_card is
initialized and ready to run DMA buffers */
int n_frames;
/* this is the frame that is currently "owned" by the OHCI DMA controller
(set to -1 iff DMA is not running)
! must lock against the interrupt handler when accessing it !
RULES:
Only the interrupt handler may change active_frame if DMA
is running; if not, process may change it
If the next frame is READY, the interrupt handler will advance
active_frame when the current frame is finished.
If the next frame is CLEAR, the interrupt handler will re-transmit
the current frame, and the dropped_frames counter will be incremented.
The interrupt handler will NEVER advance active_frame to a
frame that is not READY.
*/
int active_frame;
int first_run;
/* the same locking rules apply to these three fields also: */
/* altered ONLY from process context. Must check first_clear_frame->state;
if it's READY, that means the ringbuffer is full with READY frames;
if it's CLEAR, that means one or more ringbuffer frames are CLEAR */
unsigned int first_clear_frame;
/* altered both by process and interrupt */
unsigned int n_clear_frames;
/* only altered by the interrupt */
unsigned int dropped_frames;
/* the CIP accumulator and continuity counter are properties
of the DMA stream as a whole (not a single frame), so they
are stored here in the video_card */
unsigned long cip_accum;
unsigned long cip_n, cip_d;
unsigned int syt_offset;
unsigned int continuity_counter;
enum pal_or_ntsc pal_or_ntsc;
/* redundant, but simplifies the code somewhat */
unsigned int frame_size; /* in bytes */
/* the isochronous channel to use, -1 if video card is inactive */
int channel;
/* physically contiguous packet ringbuffer for receive */
struct dma_region packet_buf;
unsigned long packet_buf_size;
unsigned int current_packet;
int first_frame; /* received first start frame marker? */
enum modes mode;
};
/*
if the video_card is not initialized, then the ONLY fields that are valid are:
ohci
open
n_frames
*/
static inline int video_card_initialized(struct video_card *v)
{
return v->n_frames > 0;
}
static int do_dv1394_init(struct video_card *video, struct dv1394_init *init);
static int do_dv1394_init_default(struct video_card *video);
static void do_dv1394_shutdown(struct video_card *video, int free_user_buf);
/* NTSC empty packet rate accurate to within 0.01%,
calibrated against a Sony DSR-40 DVCAM deck */
#define CIP_N_NTSC 68000000
#define CIP_D_NTSC 1068000000
#define CIP_N_PAL 1
#define CIP_D_PAL 16
#endif /* _DV_1394_PRIVATE_H */