提交 b7d41a9f 编写于 作者: L Linus Torvalds

Merge branch 'ieee1394-removal' of...

Merge branch 'ieee1394-removal' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6

* 'ieee1394-removal' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
  ieee1394: remove the old IEEE 1394 driver stack
  ieee1394: move init_ohci1394_dma to drivers/firewire/

Fix trivial change/delete conflict: drivers/ieee1394/eth1394.c is
getting removed, but was modified by the networking merge.
What: dv1394 (a.k.a. "OHCI-DV I/O support" for FireWire)
Contact: linux1394-devel@lists.sourceforge.net
Description:
New application development should use raw1394 + userspace libraries
instead, notably libiec61883 which is functionally equivalent.
Users:
ffmpeg/libavformat (used by a variety of media players)
dvgrab v1.x (replaced by dvgrab2 on top of raw1394 and resp. libraries)
What: dv1394 (a.k.a. "OHCI-DV I/O support" for FireWire)
Date: May 2010 (scheduled), finally removed in kernel v2.6.37
Contact: linux1394-devel@lists.sourceforge.net
Description:
/dev/dv1394/* were character device files, one for each FireWire
controller and for NTSC and PAL respectively, from which DV data
could be received by read() or transmitted by write(). A few
ioctl()s allowed limited control.
This special-purpose interface has been superseded by libraw1394 +
libiec61883 which are functionally equivalent, support HDV, and
transparently work on top of the newer firewire kernel drivers.
Users:
ffmpeg/libavformat (if configured for DV1394)
What: raw1394 (a.k.a. "Raw IEEE1394 I/O support" for FireWire)
Date: May 2010 (scheduled), finally removed in kernel v2.6.37
Contact: linux1394-devel@lists.sourceforge.net
Description:
/dev/raw1394 was a character device file that allowed low-level
access to FireWire buses. Its major drawbacks were its inability
to implement sensible device security policies, and its low level
of abstraction that required userspace clients do duplicate much
of the kernel's ieee1394 core functionality.
Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
firewire-core.
Users:
libraw1394 (works with firewire-cdev too, transparent to library ABI
users)
What: legacy isochronous ABI of raw1394 (1st generation iso ABI)
Date: June 2007 (scheduled), removed in kernel v2.6.23
Contact: linux1394-devel@lists.sourceforge.net
Description:
The two request types RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN have
been deprecated for quite some time. They are very inefficient as they
come with high interrupt load and several layers of callbacks for each
packet. Because of these deficiencies, the video1394 and dv1394 drivers
and the 3rd-generation isochronous ABI in raw1394 (rawiso) were created.
Users:
libraw1394 users via the long deprecated API raw1394_iso_write,
raw1394_start_iso_write, raw1394_start_iso_rcv, raw1394_stop_iso_rcv
libdc1394, which optionally uses these old libraw1394 calls
alternatively to the more efficient video1394 ABI
What: video1394 (a.k.a. "OHCI-1394 Video support" for FireWire)
Date: May 2010 (scheduled), finally removed in kernel v2.6.37
Contact: linux1394-devel@lists.sourceforge.net
Description:
/dev/video1394/* were character device files, one for each FireWire
controller, which were used for isochronous I/O. It was added as an
alternative to raw1394's isochronous I/O functionality which had
performance issues in its first generation. Any video1394 user had
to use raw1394 + libraw1394 too because video1394 did not provide
asynchronous I/O for device discovery and configuration.
Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
firewire-core.
Users:
libdc1394 (works with firewire-cdev too, transparent to library ABI
users)
......@@ -502,16 +502,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
----------------------------
What: old ieee1394 subsystem (CONFIG_IEEE1394)
When: 2.6.37
Files: drivers/ieee1394/ except init_ohci1394_dma.c
Why: superseded by drivers/firewire/ (CONFIG_FIREWIRE) which offers more
features, better performance, and better security, all with smaller
and more modern code base
Who: Stefan Richter <stefanr@s5r6.in-berlin.de>
----------------------------
What: The acpi_sleep=s4_nonvs command line option
When: 2.6.37
Files: arch/x86/kernel/acpi/sleep.c
......
......@@ -51,7 +51,6 @@ obj-y += net/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/
obj-y += firewire/
obj-y += ieee1394/
obj-$(CONFIG_UIO) += uio/
obj-y += cdrom/
obj-y += auxdisplay/
......
......@@ -3,9 +3,6 @@ menu "IEEE 1394 (FireWire) support"
# firewire-core does not depend on PCI but is
# not useful without PCI controller driver
comment "You can enable one or both FireWire driver stacks."
comment "The newer stack is recommended."
config FIREWIRE
tristate "FireWire driver stack"
select CRC_ITU_T
......@@ -64,8 +61,6 @@ config FIREWIRE_NET
To compile this driver as a module, say M here: The module will be
called firewire-net.
source "drivers/ieee1394/Kconfig"
config FIREWIRE_NOSY
tristate "Nosy - a FireWire traffic sniffer for PCILynx cards"
depends on PCI
......
......@@ -13,3 +13,4 @@ obj-$(CONFIG_FIREWIRE_OHCI) += firewire-ohci.o
obj-$(CONFIG_FIREWIRE_SBP2) += firewire-sbp2.o
obj-$(CONFIG_FIREWIRE_NET) += firewire-net.o
obj-$(CONFIG_FIREWIRE_NOSY) += nosy.o
obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
......@@ -32,23 +32,41 @@
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/interrupt.h> /* for ohci1394.h */
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/pci.h> /* for PCI defines */
#include <linux/init_ohci1394_dma.h>
#include <linux/string.h>
#include <asm/pci-direct.h> /* for direct PCI config space access */
#include <asm/fixmap.h>
#include "ieee1394_types.h"
#include "ohci1394.h"
#include <linux/init_ohci1394_dma.h>
#include "ohci.h"
int __initdata init_ohci1394_dma_early;
struct ohci {
void __iomem *registers;
};
static inline void reg_write(const struct ohci *ohci, int offset, u32 data)
{
writel(data, ohci->registers + offset);
}
static inline u32 reg_read(const struct ohci *ohci, int offset)
{
return readl(ohci->registers + offset);
}
#define OHCI_LOOP_COUNT 100 /* Number of loops for reg read waits */
/* Reads a PHY register of an OHCI-1394 controller */
static inline u8 __init get_phy_reg(struct ti_ohci *ohci, u8 addr)
static inline u8 __init get_phy_reg(struct ohci *ohci, u8 addr)
{
int i;
quadlet_t r;
u32 r;
reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000);
......@@ -63,22 +81,22 @@ static inline u8 __init get_phy_reg(struct ti_ohci *ohci, u8 addr)
}
/* Writes to a PHY register of an OHCI-1394 controller */
static inline void __init set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
static inline void __init set_phy_reg(struct ohci *ohci, u8 addr, u8 data)
{
int i;
reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000);
for (i = 0; i < OHCI_LOOP_COUNT; i++) {
u32 r = reg_read(ohci, OHCI1394_PhyControl);
if (!(r & 0x00004000))
if (!(reg_read(ohci, OHCI1394_PhyControl) & 0x00004000))
break;
mdelay(1);
}
}
/* Resets an OHCI-1394 controller (for sane state before initialization) */
static inline void __init init_ohci1394_soft_reset(struct ti_ohci *ohci) {
static inline void __init init_ohci1394_soft_reset(struct ohci *ohci)
{
int i;
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
......@@ -91,10 +109,14 @@ static inline void __init init_ohci1394_soft_reset(struct ti_ohci *ohci) {
}
}
#define OHCI1394_MAX_AT_REQ_RETRIES 0xf
#define OHCI1394_MAX_AT_RESP_RETRIES 0x2
#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
/* Basic OHCI-1394 register and port inititalization */
static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
static inline void __init init_ohci1394_initialize(struct ohci *ohci)
{
quadlet_t bus_options;
u32 bus_options;
int num_ports, i;
/* Put some defaults to these undefined bus options */
......@@ -116,7 +138,7 @@ static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
/* enable phys */
reg_write(ohci, OHCI1394_LinkControlSet,
OHCI1394_LinkControl_RcvPhyPkt);
OHCI1394_LinkControl_rcvPhyPkt);
/* Don't accept phy packets into AR request context */
reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
......@@ -128,7 +150,7 @@ static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
/* Accept asyncronous transfer requests from all nodes for now */
reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);
reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
/* Specify asyncronous transfer retries */
reg_write(ohci, OHCI1394_ATRetries,
......@@ -137,7 +159,8 @@ static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
(OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
/* We don't want hardware swapping */
reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);
reg_write(ohci, OHCI1394_HCControlClear,
OHCI1394_HCControl_noByteSwapData);
/* Enable link */
reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
......@@ -164,11 +187,11 @@ static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
* has to be enabled after each bus reset when needed. We resort
* to polling here because on early boot, we have no interrupts.
*/
static inline void __init init_ohci1394_wait_for_busresets(struct ti_ohci *ohci)
static inline void __init init_ohci1394_wait_for_busresets(struct ohci *ohci)
{
int i, events;
for (i=0; i < 9; i++) {
for (i = 0; i < 9; i++) {
mdelay(200);
events = reg_read(ohci, OHCI1394_IntEventSet);
if (events & OHCI1394_busReset)
......@@ -182,18 +205,18 @@ static inline void __init init_ohci1394_wait_for_busresets(struct ti_ohci *ohci)
* This enables remote DMA access over IEEE1394 from every host for the low
* 4GB of address space. DMA accesses above 4GB are not available currently.
*/
static inline void __init init_ohci1394_enable_physical_dma(struct ti_ohci *hci)
static inline void __init init_ohci1394_enable_physical_dma(struct ohci *ohci)
{
reg_write(hci, OHCI1394_PhyReqFilterHiSet, 0xffffffff);
reg_write(hci, OHCI1394_PhyReqFilterLoSet, 0xffffffff);
reg_write(hci, OHCI1394_PhyUpperBound, 0xffff0000);
reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 0xffffffff);
reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 0xffffffff);
reg_write(ohci, OHCI1394_PhyUpperBound, 0xffff0000);
}
/**
* init_ohci1394_reset_and_init_dma - init controller and enable DMA
* This initializes the given controller and enables physical DMA engine in it.
*/
static inline void __init init_ohci1394_reset_and_init_dma(struct ti_ohci *ohci)
static inline void __init init_ohci1394_reset_and_init_dma(struct ohci *ohci)
{
/* Start off with a soft reset, clears everything to a sane state. */
init_ohci1394_soft_reset(ohci);
......@@ -225,7 +248,7 @@ static inline void __init init_ohci1394_reset_and_init_dma(struct ti_ohci *ohci)
static inline void __init init_ohci1394_controller(int num, int slot, int func)
{
unsigned long ohci_base;
struct ti_ohci ohci;
struct ohci ohci;
printk(KERN_INFO "init_ohci1394_dma: initializing OHCI-1394"
" at %02x:%02x.%x\n", num, slot, func);
......@@ -235,7 +258,7 @@ static inline void __init init_ohci1394_controller(int num, int slot, int func)
set_fixmap_nocache(FIX_OHCI1394_BASE, ohci_base);
ohci.registers = (void *)fix_to_virt(FIX_OHCI1394_BASE);
ohci.registers = (void __iomem *)fix_to_virt(FIX_OHCI1394_BASE);
init_ohci1394_reset_and_init_dma(&ohci);
}
......@@ -247,6 +270,7 @@ static inline void __init init_ohci1394_controller(int num, int slot, int func)
void __init init_ohci1394_dma_on_all_controllers(void)
{
int num, slot, func;
u32 class;
if (!early_pci_allowed())
return;
......@@ -255,9 +279,9 @@ void __init init_ohci1394_dma_on_all_controllers(void)
for (num = 0; num < 32; num++) {
for (slot = 0; slot < 32; slot++) {
for (func = 0; func < 8; func++) {
u32 class = read_pci_config(num,slot,func,
class = read_pci_config(num, slot, func,
PCI_CLASS_REVISION);
if ((class == 0xffffffff))
if (class == 0xffffffff)
continue; /* No device at this func */
if (class>>8 != PCI_CLASS_SERIAL_FIREWIRE_OHCI)
......
config IEEE1394
tristate "Legacy alternative FireWire driver stack"
depends on PCI || BROKEN
help
IEEE 1394 describes a high performance serial bus, which is also
known as FireWire(tm) or i.Link(tm) and is used for connecting all
sorts of devices (most notably digital video cameras) to your
computer.
If you have FireWire hardware and want to use it, say Y here. This
is the core support only, you will also need to select a driver for
your IEEE 1394 adapter.
To compile this driver as a module, say M here: the module will be
called ieee1394.
NOTE:
ieee1394 is superseded by the newer firewire-core driver. See
http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
further information on how to switch to the new FireWire drivers.
config IEEE1394_OHCI1394
tristate "OHCI-1394 controllers"
depends on PCI && IEEE1394
help
Enable this driver if you have an IEEE 1394 controller based on the
OHCI-1394 specification. The current driver is only tested with OHCI
chipsets made by Texas Instruments and NEC. Most third-party vendors
use one of these chipsets. It should work with any OHCI-1394
compliant card, however.
To compile this driver as a module, say M here: the module will be
called ohci1394.
NOTE:
ohci1394 is superseded by the newer firewire-ohci driver. See
http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
further information on how to switch to the new FireWire drivers.
If you want to install firewire-ohci and ohci1394 together, you
should configure them only as modules and blacklist the driver(s)
which you don't want to have auto-loaded. Add either
blacklist ohci1394
blacklist video1394
blacklist dv1394
or
blacklist firewire-ohci
to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf
depending on your distribution.
comment "PCILynx controller requires I2C"
depends on IEEE1394 && I2C=n
config IEEE1394_PCILYNX
tristate "PCILynx controller"
depends on PCI && IEEE1394 && I2C
select I2C_ALGOBIT
help
Say Y here if you have an IEEE-1394 controller with the Texas
Instruments PCILynx chip. Note: this driver is written for revision
2 of this chip and may not work with revision 0.
To compile this driver as a module, say M here: the module will be
called pcilynx.
Only some old and now very rare PCI and CardBus cards and
PowerMacs G3 B&W contain the PCILynx controller. Therefore
almost everybody can say N here.
comment "SBP-2 support (for storage devices) requires SCSI"
depends on IEEE1394 && SCSI=n
config IEEE1394_SBP2
tristate "Storage devices (SBP-2 protocol)"
depends on IEEE1394 && SCSI
help
This option enables you to use SBP-2 devices connected to an IEEE
1394 bus. SBP-2 devices include storage devices like harddisks and
DVD drives, also some other FireWire devices like scanners.
You should also enable support for disks, CD-ROMs, etc. in the SCSI
configuration section.
To compile this driver as a module, say M here: the module will be
called sbp2.
NOTE:
sbp2 is superseded by the newer firewire-sbp2 driver. See
http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
further information on how to switch to the new FireWire drivers.
config IEEE1394_SBP2_PHYS_DMA
bool "Enable replacement for physical DMA in SBP2"
depends on IEEE1394_SBP2 && VIRT_TO_BUS && EXPERIMENTAL
help
This builds sbp2 for use with non-OHCI host adapters which do not
support physical DMA or for when ohci1394 is run with phys_dma=0.
Physical DMA is data movement without assistance of the drivers'
interrupt handlers. This option includes the interrupt handlers
that are required in absence of this hardware feature.
This option is buggy and currently broken on some architectures.
If unsure, say N.
config IEEE1394_ETH1394_ROM_ENTRY
depends on IEEE1394
bool
default n
config IEEE1394_ETH1394
tristate "IP networking over 1394 (experimental)"
depends on IEEE1394 && EXPERIMENTAL && INET
select IEEE1394_ETH1394_ROM_ENTRY
help
This driver implements a functional majority of RFC 2734: IPv4 over
1394. It will provide IP connectivity with implementations of RFC
2734 found on other operating systems. It will not communicate with
older versions of this driver found in stock kernels prior to 2.6.3.
This driver is still considered experimental. It does not yet support
MCAP, therefore multicast support is significantly limited.
The module is called eth1394 although it does not emulate Ethernet.
NOTE:
eth1394 is superseded by the newer firewire-net driver. See
http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
further information on how to switch to the new FireWire drivers.
config IEEE1394_RAWIO
tristate "raw1394 userspace interface"
depends on IEEE1394
help
This option adds support for the raw1394 device file which enables
direct communication of user programs with IEEE 1394 devices
(isochronous and asynchronous). Almost all application programs
which access FireWire require this option.
To compile this driver as a module, say M here: the module will be
called raw1394.
NOTE:
raw1394 is superseded by the newer firewire-core driver. See
http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
further information on how to switch to the new FireWire drivers.
config IEEE1394_VIDEO1394
tristate "video1394 userspace interface"
depends on IEEE1394 && IEEE1394_OHCI1394
help
This option adds support for the video1394 device files which enable
isochronous communication of user programs with IEEE 1394 devices,
especially video capture or export. This interface is used by all
libdc1394 based programs and by several other programs, in addition to
the raw1394 interface. It is generally not required for DV capture.
To compile this driver as a module, say M here: the module will be
called video1394.
NOTE:
video1394 is superseded by the newer firewire-core driver. See
http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
further information on how to switch to the new FireWire drivers.
config IEEE1394_DV1394
tristate "dv1394 userspace interface (deprecated)"
depends on IEEE1394 && IEEE1394_OHCI1394
help
The dv1394 driver is unsupported and may be removed from Linux in a
future release. Its functionality is now provided by either
raw1394 or firewire-core together with libraries such as libiec61883.
config IEEE1394_VERBOSEDEBUG
bool "Excessive debugging output"
depends on IEEE1394
help
If you say Y here, you will get very verbose debugging logs from the
ieee1394 drivers, including sent and received packet headers. This
will quickly result in large amounts of data sent to the system log.
Say Y if you really need the debugging output. Everyone else says N.
#
# Makefile for the Linux IEEE 1394 implementation
#
ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
highlevel.o csr.o nodemgr.o dma.o iso.o \
csr1212.o config_roms.o
obj-$(CONFIG_IEEE1394) += ieee1394.o
obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
obj-$(CONFIG_IEEE1394_OHCI1394) += ohci1394.o
obj-$(CONFIG_IEEE1394_VIDEO1394) += video1394.o
obj-$(CONFIG_IEEE1394_RAWIO) += raw1394.o
obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
/*
* IEEE 1394 for Linux
*
* ConfigROM entries
*
* Copyright (C) 2004 Ben Collins
*
* This code is licensed under the GPL. See the file COPYING in the root
* directory of the kernel sources for details.
*/
#include <linux/types.h>
#include "csr1212.h"
#include "ieee1394.h"
#include "ieee1394_types.h"
#include "hosts.h"
#include "ieee1394_core.h"
#include "highlevel.h"
#include "csr.h"
#include "config_roms.h"
struct hpsb_config_rom_entry {
const char *name;
/* Base initialization, called at module load */
int (*init)(void);
/* Cleanup called at module exit */
void (*cleanup)(void);
/* The flag added to host->config_roms */
unsigned int flag;
};
/* The default host entry. This must succeed. */
int hpsb_default_host_entry(struct hpsb_host *host)
{
struct csr1212_keyval *root;
struct csr1212_keyval *vend_id = NULL;
struct csr1212_keyval *text = NULL;
char csr_name[128];
int ret;
sprintf(csr_name, "Linux - %s", host->driver->name);
root = host->csr.rom->root_kv;
vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR, host->csr.guid_hi >> 8);
text = csr1212_new_string_descriptor_leaf(csr_name);
if (!vend_id || !text) {
if (vend_id)
csr1212_release_keyval(vend_id);
if (text)
csr1212_release_keyval(text);
csr1212_destroy_csr(host->csr.rom);
return -ENOMEM;
}
csr1212_associate_keyval(vend_id, text);
csr1212_release_keyval(text);
ret = csr1212_attach_keyval_to_directory(root, vend_id);
csr1212_release_keyval(vend_id);
if (ret != CSR1212_SUCCESS) {
csr1212_destroy_csr(host->csr.rom);
return -ENOMEM;
}
host->update_config_rom = 1;
return 0;
}
#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
#include "eth1394.h"
static struct csr1212_keyval *ip1394_ud;
static int config_rom_ip1394_init(void)
{
struct csr1212_keyval *spec_id = NULL;
struct csr1212_keyval *spec_desc = NULL;
struct csr1212_keyval *ver = NULL;
struct csr1212_keyval *ver_desc = NULL;
int ret = -ENOMEM;
ip1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT);
spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID,
ETHER1394_GASP_SPECIFIER_ID);
spec_desc = csr1212_new_string_descriptor_leaf("IANA");
ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION,
ETHER1394_GASP_VERSION);
ver_desc = csr1212_new_string_descriptor_leaf("IPv4");
if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc)
goto ip1394_fail;
csr1212_associate_keyval(spec_id, spec_desc);
csr1212_associate_keyval(ver, ver_desc);
if (csr1212_attach_keyval_to_directory(ip1394_ud, spec_id)
== CSR1212_SUCCESS &&
csr1212_attach_keyval_to_directory(ip1394_ud, ver)
== CSR1212_SUCCESS)
ret = 0;
ip1394_fail:
if (ret && ip1394_ud) {
csr1212_release_keyval(ip1394_ud);
ip1394_ud = NULL;
}
if (spec_id)
csr1212_release_keyval(spec_id);
if (spec_desc)
csr1212_release_keyval(spec_desc);
if (ver)
csr1212_release_keyval(ver);
if (ver_desc)
csr1212_release_keyval(ver_desc);
return ret;
}
static void config_rom_ip1394_cleanup(void)
{
if (ip1394_ud) {
csr1212_release_keyval(ip1394_ud);
ip1394_ud = NULL;
}
}
int hpsb_config_rom_ip1394_add(struct hpsb_host *host)
{
if (!ip1394_ud)
return -ENODEV;
if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv,
ip1394_ud) != CSR1212_SUCCESS)
return -ENOMEM;
host->config_roms |= HPSB_CONFIG_ROM_ENTRY_IP1394;
host->update_config_rom = 1;
return 0;
}
EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_add);
void hpsb_config_rom_ip1394_remove(struct hpsb_host *host)
{
csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud);
host->config_roms &= ~HPSB_CONFIG_ROM_ENTRY_IP1394;
host->update_config_rom = 1;
}
EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_remove);
static struct hpsb_config_rom_entry ip1394_entry = {
.name = "ip1394",
.init = config_rom_ip1394_init,
.cleanup = config_rom_ip1394_cleanup,
.flag = HPSB_CONFIG_ROM_ENTRY_IP1394,
};
#endif /* CONFIG_IEEE1394_ETH1394_ROM_ENTRY */
static struct hpsb_config_rom_entry *const config_rom_entries[] = {
#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
&ip1394_entry,
#endif
};
/* Initialize all config roms */
int hpsb_init_config_roms(void)
{
int i, error = 0;
for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
if (config_rom_entries[i]->init()) {
HPSB_ERR("Failed to initialize config rom entry `%s'",
config_rom_entries[i]->name);
error = -1;
}
return error;
}
/* Cleanup all config roms */
void hpsb_cleanup_config_roms(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
config_rom_entries[i]->cleanup();
}
#ifndef _IEEE1394_CONFIG_ROMS_H
#define _IEEE1394_CONFIG_ROMS_H
struct hpsb_host;
int hpsb_default_host_entry(struct hpsb_host *host);
int hpsb_init_config_roms(void);
void hpsb_cleanup_config_roms(void);
/* List of flags to check if a host contains a certain extra config rom
* entry. Available in the host->config_roms member. */
#define HPSB_CONFIG_ROM_ENTRY_IP1394 0x00000001
#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
int hpsb_config_rom_ip1394_add(struct hpsb_host *host);
void hpsb_config_rom_ip1394_remove(struct hpsb_host *host);
#endif
#endif /* _IEEE1394_CONFIG_ROMS_H */
此差异已折叠。
#ifndef _IEEE1394_CSR_H
#define _IEEE1394_CSR_H
#include <linux/spinlock_types.h>
#include "csr1212.h"
#include "ieee1394_types.h"
#define CSR_REGISTER_BASE 0xfffff0000000ULL
/* register offsets relative to CSR_REGISTER_BASE */
#define CSR_STATE_CLEAR 0x0
#define CSR_STATE_SET 0x4
#define CSR_NODE_IDS 0x8
#define CSR_RESET_START 0xc
#define CSR_SPLIT_TIMEOUT_HI 0x18
#define CSR_SPLIT_TIMEOUT_LO 0x1c
#define CSR_CYCLE_TIME 0x200
#define CSR_BUS_TIME 0x204
#define CSR_BUSY_TIMEOUT 0x210
#define CSR_BUS_MANAGER_ID 0x21c
#define CSR_BANDWIDTH_AVAILABLE 0x220
#define CSR_CHANNELS_AVAILABLE 0x224
#define CSR_CHANNELS_AVAILABLE_HI 0x224
#define CSR_CHANNELS_AVAILABLE_LO 0x228
#define CSR_BROADCAST_CHANNEL 0x234
#define CSR_CONFIG_ROM 0x400
#define CSR_CONFIG_ROM_END 0x800
#define CSR_FCP_COMMAND 0xB00
#define CSR_FCP_RESPONSE 0xD00
#define CSR_FCP_END 0xF00
#define CSR_TOPOLOGY_MAP 0x1000
#define CSR_TOPOLOGY_MAP_END 0x1400
#define CSR_SPEED_MAP 0x2000
#define CSR_SPEED_MAP_END 0x3000
/* IEEE 1394 bus specific Configuration ROM Key IDs */
#define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30)
/* IEEE 1394 Bus Information Block specifics */
#define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t))
#define CSR_IRMC_SHIFT 31
#define CSR_CMC_SHIFT 30
#define CSR_ISC_SHIFT 29
#define CSR_BMC_SHIFT 28
#define CSR_PMC_SHIFT 27
#define CSR_CYC_CLK_ACC_SHIFT 16
#define CSR_MAX_REC_SHIFT 12
#define CSR_MAX_ROM_SHIFT 8
#define CSR_GENERATION_SHIFT 4
static inline void csr_set_bus_info_generation(struct csr1212_csr *csr, u8 gen)
{
csr->bus_info_data[2] &= ~cpu_to_be32(0xf << CSR_GENERATION_SHIFT);
csr->bus_info_data[2] |= cpu_to_be32((u32)gen << CSR_GENERATION_SHIFT);
}
struct csr_control {
spinlock_t lock;
quadlet_t state;
quadlet_t node_ids;
quadlet_t split_timeout_hi, split_timeout_lo;
unsigned long expire; /* Calculated from split_timeout */
quadlet_t cycle_time;
quadlet_t bus_time;
quadlet_t bus_manager_id;
quadlet_t bandwidth_available;
quadlet_t channels_available_hi, channels_available_lo;
quadlet_t broadcast_channel;
/* Bus Info */
quadlet_t guid_hi, guid_lo;
u8 cyc_clk_acc;
u8 max_rec;
u8 max_rom;
u8 generation; /* Only use values between 0x2 and 0xf */
u8 lnk_spd;
unsigned long gen_timestamp[16];
struct csr1212_csr *rom;
quadlet_t topology_map[256];
quadlet_t speed_map[1024];
};
extern struct csr1212_bus_ops csr_bus_ops;
int init_csr(void);
void cleanup_csr(void);
/* hpsb_update_config_rom() is deprecated */
struct hpsb_host;
int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
size_t size, unsigned char rom_version);
#endif /* _IEEE1394_CSR_H */
此差异已折叠。
/*
* csr1212.h -- IEEE 1212 Control and Status Register support for Linux
*
* Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
* Steve Kinneberg <kinnebergsteve@acmsystems.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __CSR1212_H__
#define __CSR1212_H__
#include <linux/types.h>
#include <linux/slab.h>
#include <asm/atomic.h>
#define CSR1212_MALLOC(size) kmalloc((size), GFP_KERNEL)
#define CSR1212_FREE(ptr) kfree(ptr)
#define CSR1212_SUCCESS (0)
/* CSR 1212 key types */
#define CSR1212_KV_TYPE_IMMEDIATE 0
#define CSR1212_KV_TYPE_CSR_OFFSET 1
#define CSR1212_KV_TYPE_LEAF 2
#define CSR1212_KV_TYPE_DIRECTORY 3
/* CSR 1212 key ids */
#define CSR1212_KV_ID_DESCRIPTOR 0x01
#define CSR1212_KV_ID_BUS_DEPENDENT_INFO 0x02
#define CSR1212_KV_ID_VENDOR 0x03
#define CSR1212_KV_ID_HARDWARE_VERSION 0x04
#define CSR1212_KV_ID_MODULE 0x07
#define CSR1212_KV_ID_NODE_CAPABILITIES 0x0C
#define CSR1212_KV_ID_EUI_64 0x0D
#define CSR1212_KV_ID_UNIT 0x11
#define CSR1212_KV_ID_SPECIFIER_ID 0x12
#define CSR1212_KV_ID_VERSION 0x13
#define CSR1212_KV_ID_DEPENDENT_INFO 0x14
#define CSR1212_KV_ID_UNIT_LOCATION 0x15
#define CSR1212_KV_ID_MODEL 0x17
#define CSR1212_KV_ID_INSTANCE 0x18
#define CSR1212_KV_ID_KEYWORD 0x19
#define CSR1212_KV_ID_FEATURE 0x1A
#define CSR1212_KV_ID_EXTENDED_ROM 0x1B
#define CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID 0x1C
#define CSR1212_KV_ID_EXTENDED_KEY 0x1D
#define CSR1212_KV_ID_EXTENDED_DATA 0x1E
#define CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR 0x1F
#define CSR1212_KV_ID_DIRECTORY_ID 0x20
#define CSR1212_KV_ID_REVISION 0x21
/* IEEE 1212 Address space map */
#define CSR1212_ALL_SPACE_BASE (0x000000000000ULL)
#define CSR1212_ALL_SPACE_SIZE (1ULL << 48)
#define CSR1212_ALL_SPACE_END (CSR1212_ALL_SPACE_BASE + CSR1212_ALL_SPACE_SIZE)
#define CSR1212_MEMORY_SPACE_BASE (0x000000000000ULL)
#define CSR1212_MEMORY_SPACE_SIZE ((256ULL * (1ULL << 40)) - (512ULL * (1ULL << 20)))
#define CSR1212_MEMORY_SPACE_END (CSR1212_MEMORY_SPACE_BASE + CSR1212_MEMORY_SPACE_SIZE)
#define CSR1212_PRIVATE_SPACE_BASE (0xffffe0000000ULL)
#define CSR1212_PRIVATE_SPACE_SIZE (256ULL * (1ULL << 20))
#define CSR1212_PRIVATE_SPACE_END (CSR1212_PRIVATE_SPACE_BASE + CSR1212_PRIVATE_SPACE_SIZE)
#define CSR1212_REGISTER_SPACE_BASE (0xfffff0000000ULL)
#define CSR1212_REGISTER_SPACE_SIZE (256ULL * (1ULL << 20))
#define CSR1212_REGISTER_SPACE_END (CSR1212_REGISTER_SPACE_BASE + CSR1212_REGISTER_SPACE_SIZE)
#define CSR1212_CSR_ARCH_REG_SPACE_BASE (0xfffff0000000ULL)
#define CSR1212_CSR_ARCH_REG_SPACE_SIZE (512)
#define CSR1212_CSR_ARCH_REG_SPACE_END (CSR1212_CSR_ARCH_REG_SPACE_BASE + CSR1212_CSR_ARCH_REG_SPACE_SIZE)
#define CSR1212_CSR_ARCH_REG_SPACE_OFFSET (CSR1212_CSR_ARCH_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
#define CSR1212_CSR_BUS_DEP_REG_SPACE_BASE (0xfffff0000200ULL)
#define CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE (512)
#define CSR1212_CSR_BUS_DEP_REG_SPACE_END (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE + CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE)
#define CSR1212_CSR_BUS_DEP_REG_SPACE_OFFSET (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
#define CSR1212_CONFIG_ROM_SPACE_BASE (0xfffff0000400ULL)
#define CSR1212_CONFIG_ROM_SPACE_SIZE (1024)
#define CSR1212_CONFIG_ROM_SPACE_END (CSR1212_CONFIG_ROM_SPACE_BASE + CSR1212_CONFIG_ROM_SPACE_SIZE)
#define CSR1212_CONFIG_ROM_SPACE_OFFSET (CSR1212_CONFIG_ROM_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
#define CSR1212_UNITS_SPACE_BASE (0xfffff0000800ULL)
#define CSR1212_UNITS_SPACE_SIZE ((256ULL * (1ULL << 20)) - 2048)
#define CSR1212_UNITS_SPACE_END (CSR1212_UNITS_SPACE_BASE + CSR1212_UNITS_SPACE_SIZE)
#define CSR1212_UNITS_SPACE_OFFSET (CSR1212_UNITS_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
#define CSR1212_INVALID_ADDR_SPACE -1
/* Config ROM image structures */
struct csr1212_bus_info_block_img {
u8 length;
u8 crc_length;
u16 crc;
/* Must be last */
u32 data[0]; /* older gcc can't handle [] which is standard */
};
struct csr1212_leaf {
int len;
u32 *data;
};
struct csr1212_dentry {
struct csr1212_dentry *next, *prev;
struct csr1212_keyval *kv;
};
struct csr1212_directory {
int len;
struct csr1212_dentry *dentries_head, *dentries_tail;
};
struct csr1212_keyval {
struct {
u8 type;
u8 id;
} key;
union {
u32 immediate;
u32 csr_offset;
struct csr1212_leaf leaf;
struct csr1212_directory directory;
} value;
struct csr1212_keyval *associate;
atomic_t refcnt;
/* used in generating and/or parsing CSR image */
struct csr1212_keyval *next, *prev; /* flat list of CSR elements */
u32 offset; /* position in CSR from 0xffff f000 0000 */
u8 valid; /* flag indicating keyval has valid data*/
};
struct csr1212_cache_region {
struct csr1212_cache_region *next, *prev;
u32 offset_start; /* inclusive */
u32 offset_end; /* exclusive */
};
struct csr1212_csr_rom_cache {
struct csr1212_csr_rom_cache *next, *prev;
struct csr1212_cache_region *filled_head, *filled_tail;
struct csr1212_keyval *layout_head, *layout_tail;
size_t size;
u32 offset;
struct csr1212_keyval *ext_rom;
size_t len;
/* Must be last */
u32 data[0]; /* older gcc can't handle [] which is standard */
};
struct csr1212_csr {
size_t bus_info_len; /* bus info block length in bytes */
size_t crc_len; /* crc length in bytes */
__be32 *bus_info_data; /* bus info data incl bus name and EUI */
void *private; /* private, bus specific data */
struct csr1212_bus_ops *ops;
struct csr1212_keyval *root_kv;
int max_rom; /* max bytes readable in Config ROM region */
/* Items below used for image parsing and generation */
struct csr1212_csr_rom_cache *cache_head, *cache_tail;
};
struct csr1212_bus_ops {
/* This function is used by csr1212 to read additional information
* from remote nodes when parsing a Config ROM (i.e., read Config ROM
* entries located in the Units Space. Must return 0 on success
* anything else indicates an error. */
int (*bus_read) (struct csr1212_csr *csr, u64 addr,
void *buffer, void *private);
/* This function is used by csr1212 to allocate a region in units space
* in the event that Config ROM entries don't all fit in the predefined
* 1K region. The void *private parameter is private member of struct
* csr1212_csr. */
u64 (*allocate_addr_range) (u64 size, u32 alignment, void *private);
/* This function is used by csr1212 to release a region in units space
* that is no longer needed. */
void (*release_addr) (u64 addr, void *private);
};
/* Descriptor Leaf manipulation macros */
#define CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT 24
#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK 0xffffff
#define CSR1212_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u32))
#define CSR1212_DESCRIPTOR_LEAF_TYPE(kv) \
(be32_to_cpu((kv)->value.leaf.data[0]) >> \
CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)
#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) \
(be32_to_cpu((kv)->value.leaf.data[0]) & \
CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)
/* Text Descriptor Leaf manipulation macros */
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT 28
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK 0xf /* after shift */
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT 16
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK 0xfff /* after shift */
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u32))
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) \
(be32_to_cpu((kv)->value.leaf.data[1]) >> \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT)
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) \
((be32_to_cpu((kv)->value.leaf.data[1]) >> \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT) & \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK)
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) \
(be32_to_cpu((kv)->value.leaf.data[1]) & \
CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK)
#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv) \
(&((kv)->value.leaf.data[2]))
/* The following 2 function are for creating new Configuration ROM trees. The
* first function is used for both creating local trees and parsing remote
* trees. The second function adds pertinent information to local Configuration
* ROM trees - namely data for the bus information block. */
extern struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
size_t bus_info_size,
void *private);
extern void csr1212_init_local_csr(struct csr1212_csr *csr,
const u32 *bus_info_data, int max_rom);
/* Destroy a Configuration ROM tree and release all memory taken by the tree. */
extern void csr1212_destroy_csr(struct csr1212_csr *csr);
/* The following set of functions are fore creating new keyvals for placement in
* a Configuration ROM tree. Code that creates new keyvals with these functions
* must release those keyvals with csr1212_release_keyval() when they are no
* longer needed. */
extern struct csr1212_keyval *csr1212_new_immediate(u8 key, u32 value);
extern struct csr1212_keyval *csr1212_new_directory(u8 key);
extern struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s);
/* The following function manages association between keyvals. Typically,
* Descriptor Leaves and Directories will be associated with another keyval and
* it is desirable for the Descriptor keyval to be place immediately after the
* keyval that it is associated with.
* Take care with subsequent ROM modifications: There is no function to remove
* previously specified associations.
*/
extern void csr1212_associate_keyval(struct csr1212_keyval *kv,
struct csr1212_keyval *associate);
/* The following functions manage the association of a keyval and directories.
* A keyval may be attached to more than one directory. */
extern int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
struct csr1212_keyval *kv);
extern void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
struct csr1212_keyval *kv);
/* Creates a complete Configuration ROM image in the list of caches available
* via csr->cache_head. */
extern int csr1212_generate_csr_image(struct csr1212_csr *csr);
/* This is a convience function for reading a block of data out of one of the
* caches in the csr->cache_head list. */
extern int csr1212_read(struct csr1212_csr *csr, u32 offset, void *buffer,
u32 len);
/* The following functions are in place for parsing Configuration ROM images.
* csr1212_parse_keyval() is used should there be a need to directly parse a
* Configuration ROM directly. */
extern int csr1212_parse_keyval(struct csr1212_keyval *kv,
struct csr1212_csr_rom_cache *cache);
extern int csr1212_parse_csr(struct csr1212_csr *csr);
/* This function allocates a new cache which may be used for either parsing or
* generating sub-sets of Configuration ROM images. */
static inline struct csr1212_csr_rom_cache *
csr1212_rom_cache_malloc(u32 offset, size_t size)
{
struct csr1212_csr_rom_cache *cache;
cache = CSR1212_MALLOC(sizeof(*cache) + size);
if (!cache)
return NULL;
cache->next = NULL;
cache->prev = NULL;
cache->filled_head = NULL;
cache->filled_tail = NULL;
cache->layout_head = NULL;
cache->layout_tail = NULL;
cache->offset = offset;
cache->size = size;
cache->ext_rom = NULL;
return cache;
}
/* This function ensures that a keyval contains data when referencing a keyval
* created by parsing a Configuration ROM. */
extern struct csr1212_keyval *
csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv);
/* This function increments the reference count for a keyval should there be a
* need for code to retain a keyval that has been parsed. */
static inline void csr1212_keep_keyval(struct csr1212_keyval *kv)
{
atomic_inc(&kv->refcnt);
smp_mb__after_atomic_inc();
}
/* This function decrements a keyval's reference count and will destroy the
* keyval when there are no more users of the keyval. This should be called by
* any code that calls csr1212_keep_keyval() or any of the keyval creation
* routines csr1212_new_*(). */
extern void csr1212_release_keyval(struct csr1212_keyval *kv);
/*
* This macro allows for looping over the keyval entries in a directory and it
* ensures that keyvals from remote ConfigROMs are parsed properly.
*
* struct csr1212_csr *_csr points to the CSR associated with dir.
* struct csr1212_keyval *_kv points to the current keyval (loop index).
* struct csr1212_keyval *_dir points to the directory to be looped.
* struct csr1212_dentry *_pos is used internally for indexing.
*
* kv will be NULL upon exit of the loop.
*/
#define csr1212_for_each_dir_entry(_csr, _kv, _dir, _pos) \
for (csr1212_get_keyval((_csr), (_dir)), \
_pos = (_dir)->value.directory.dentries_head, \
_kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : NULL;\
(_kv) && (_pos); \
(_kv->associate == NULL) ? \
((_pos = _pos->next), (_kv = (_pos) ? \
csr1212_get_keyval((_csr), _pos->kv) : \
NULL)) : \
(_kv = csr1212_get_keyval((_csr), _kv->associate)))
#endif /* __CSR1212_H__ */
/*
* DMA region bookkeeping routines
*
* Copyright (C) 2002 Maas Digital LLC
*
* This code is licensed under the GPL. See the file COPYING in the root
* directory of the kernel sources for details.
*/
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/scatterlist.h>
#include "dma.h"
/* dma_prog_region */
void dma_prog_region_init(struct dma_prog_region *prog)
{
prog->kvirt = NULL;
prog->dev = NULL;
prog->n_pages = 0;
prog->bus_addr = 0;
}
int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
struct pci_dev *dev)
{
/* round up to page size */
n_bytes = PAGE_ALIGN(n_bytes);
prog->n_pages = n_bytes >> PAGE_SHIFT;
prog->kvirt = pci_alloc_consistent(dev, n_bytes, &prog->bus_addr);
if (!prog->kvirt) {
printk(KERN_ERR
"dma_prog_region_alloc: pci_alloc_consistent() failed\n");
dma_prog_region_free(prog);
return -ENOMEM;
}
prog->dev = dev;
return 0;
}
void dma_prog_region_free(struct dma_prog_region *prog)
{
if (prog->kvirt) {
pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT,
prog->kvirt, prog->bus_addr);
}
prog->kvirt = NULL;
prog->dev = NULL;
prog->n_pages = 0;
prog->bus_addr = 0;
}
/* dma_region */
/**
* dma_region_init - clear out all fields but do not allocate anything
*/
void dma_region_init(struct dma_region *dma)
{
dma->kvirt = NULL;
dma->dev = NULL;
dma->n_pages = 0;
dma->n_dma_pages = 0;
dma->sglist = NULL;
}
/**
* dma_region_alloc - allocate the buffer and map it to the IOMMU
*/
int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
struct pci_dev *dev, int direction)
{
unsigned int i;
/* round up to page size */
n_bytes = PAGE_ALIGN(n_bytes);
dma->n_pages = n_bytes >> PAGE_SHIFT;
dma->kvirt = vmalloc_32(n_bytes);
if (!dma->kvirt) {
printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n");
goto err;
}
/* Clear the ram out, no junk to the user */
memset(dma->kvirt, 0, n_bytes);
/* allocate scatter/gather list */
dma->sglist = vmalloc(dma->n_pages * sizeof(*dma->sglist));
if (!dma->sglist) {
printk(KERN_ERR "dma_region_alloc: vmalloc(sglist) failed\n");
goto err;
}
sg_init_table(dma->sglist, dma->n_pages);
/* fill scatter/gather list with pages */
for (i = 0; i < dma->n_pages; i++) {
unsigned long va =
(unsigned long)dma->kvirt + (i << PAGE_SHIFT);
sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va),
PAGE_SIZE, 0);
}
/* map sglist to the IOMMU */
dma->n_dma_pages =
pci_map_sg(dev, dma->sglist, dma->n_pages, direction);
if (dma->n_dma_pages == 0) {
printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n");
goto err;
}
dma->dev = dev;
dma->direction = direction;
return 0;
err:
dma_region_free(dma);
return -ENOMEM;
}
/**
* dma_region_free - unmap and free the buffer
*/
void dma_region_free(struct dma_region *dma)
{
if (dma->n_dma_pages) {
pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages,
dma->direction);
dma->n_dma_pages = 0;
dma->dev = NULL;
}
vfree(dma->sglist);
dma->sglist = NULL;
vfree(dma->kvirt);
dma->kvirt = NULL;
dma->n_pages = 0;
}
/* find the scatterlist index and remaining offset corresponding to a
given offset from the beginning of the buffer */
static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
unsigned int start, unsigned long *rem)
{
int i;
unsigned long off = offset;
for (i = start; i < dma->n_dma_pages; i++) {
if (off < sg_dma_len(&dma->sglist[i])) {
*rem = off;
break;
}
off -= sg_dma_len(&dma->sglist[i]);
}
BUG_ON(i >= dma->n_dma_pages);
return i;
}
/**
* dma_region_offset_to_bus - get bus address of an offset within a DMA region
*
* Returns the DMA bus address of the byte with the given @offset relative to
* the beginning of the @dma.
*/
dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
unsigned long offset)
{
unsigned long rem = 0;
struct scatterlist *sg =
&dma->sglist[dma_region_find(dma, offset, 0, &rem)];
return sg_dma_address(sg) + rem;
}
/**
* dma_region_sync_for_cpu - sync the CPU's view of the buffer
*/
void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
unsigned long len)
{
int first, last;
unsigned long rem = 0;
if (!len)
len = 1;
first = dma_region_find(dma, offset, 0, &rem);
last = dma_region_find(dma, rem + len - 1, first, &rem);
pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1,
dma->direction);
}
/**
* dma_region_sync_for_device - sync the IO bus' view of the buffer
*/
void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
unsigned long len)
{
int first, last;
unsigned long rem = 0;
if (!len)
len = 1;
first = dma_region_find(dma, offset, 0, &rem);
last = dma_region_find(dma, rem + len - 1, first, &rem);
pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first],
last - first + 1, dma->direction);
}
#ifdef CONFIG_MMU
static int dma_region_pagefault(struct vm_area_struct *vma,
struct vm_fault *vmf)
{
struct dma_region *dma = (struct dma_region *)vma->vm_private_data;
if (!dma->kvirt)
return VM_FAULT_SIGBUS;
if (vmf->pgoff >= dma->n_pages)
return VM_FAULT_SIGBUS;
vmf->page = vmalloc_to_page(dma->kvirt + (vmf->pgoff << PAGE_SHIFT));
get_page(vmf->page);
return 0;
}
static const struct vm_operations_struct dma_region_vm_ops = {
.fault = dma_region_pagefault,
};
/**
* dma_region_mmap - map the buffer into a user space process
*/
int dma_region_mmap(struct dma_region *dma, struct file *file,
struct vm_area_struct *vma)
{
unsigned long size;
if (!dma->kvirt)
return -EINVAL;
/* must be page-aligned (XXX: comment is wrong, we could allow pgoff) */
if (vma->vm_pgoff != 0)
return -EINVAL;
/* check the length */
size = vma->vm_end - vma->vm_start;
if (size > (dma->n_pages << PAGE_SHIFT))
return -EINVAL;
vma->vm_ops = &dma_region_vm_ops;
vma->vm_private_data = dma;
vma->vm_file = file;
vma->vm_flags |= VM_RESERVED | VM_ALWAYSDUMP;
return 0;
}
#else /* CONFIG_MMU */
int dma_region_mmap(struct dma_region *dma, struct file *file,
struct vm_area_struct *vma)
{
return -EINVAL;
}
#endif /* CONFIG_MMU */
/*
* DMA region bookkeeping routines
*
* Copyright (C) 2002 Maas Digital LLC
*
* This code is licensed under the GPL. See the file COPYING in the root
* directory of the kernel sources for details.
*/
#ifndef IEEE1394_DMA_H
#define IEEE1394_DMA_H
#include <asm/types.h>
struct file;
struct pci_dev;
struct scatterlist;
struct vm_area_struct;
/**
* struct dma_prog_region - small contiguous DMA buffer
* @kvirt: kernel virtual address
* @dev: PCI device
* @n_pages: number of kernel pages
* @bus_addr: base bus address
*
* a small, physically contiguous DMA buffer with random-access, synchronous
* usage characteristics
*/
struct dma_prog_region {
unsigned char *kvirt;
struct pci_dev *dev;
unsigned int n_pages;
dma_addr_t bus_addr;
};
/* clear out all fields but do not allocate any memory */
void dma_prog_region_init(struct dma_prog_region *prog);
int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
struct pci_dev *dev);
void dma_prog_region_free(struct dma_prog_region *prog);
static inline dma_addr_t dma_prog_region_offset_to_bus(
struct dma_prog_region *prog, unsigned long offset)
{
return prog->bus_addr + offset;
}
/**
* struct dma_region - large non-contiguous DMA buffer
* @virt: kernel virtual address
* @dev: PCI device
* @n_pages: number of kernel pages
* @n_dma_pages: number of IOMMU pages
* @sglist: IOMMU mapping
* @direction: PCI_DMA_TODEVICE, etc.
*
* a large, non-physically-contiguous DMA buffer with streaming, asynchronous
* usage characteristics
*/
struct dma_region {
unsigned char *kvirt;
struct pci_dev *dev;
unsigned int n_pages;
unsigned int n_dma_pages;
struct scatterlist *sglist;
int direction;
};
void dma_region_init(struct dma_region *dma);
int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
struct pci_dev *dev, int direction);
void dma_region_free(struct dma_region *dma);
void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
unsigned long len);
void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
unsigned long len);
int dma_region_mmap(struct dma_region *dma, struct file *file,
struct vm_area_struct *vma);
dma_addr_t dma_region_offset_to_bus(struct dma_region *dma,
unsigned long offset);
/**
* dma_region_i - macro to index into a DMA region (or dma_prog_region)
*/
#define dma_region_i(_dma, _type, _index) \
( ((_type*) ((_dma)->kvirt)) + (_index) )
#endif /* IEEE1394_DMA_H */
/*
* 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 { __le32 q[8]; };
struct output_more { __le32 q[4]; };
struct output_last { __le32 q[4]; };
struct input_more { __le32 q[4]; };
struct input_last { __le32 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] = cpu_to_le32(0);
omi->q[2] = cpu_to_le32(0);
omi->q[3] = cpu_to_le32(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] = cpu_to_le32(0);
omi->q[7] = cpu_to_le32(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] = cpu_to_le32(0);
om->q[3] = cpu_to_le32(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] = cpu_to_le32(0);
ol->q[3] = cpu_to_le32(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] = cpu_to_le32(0); /* branchAddress and Z not use in packet-per-buffer mode */
im->q[3] = cpu_to_le32(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) */
__le32 *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.
*/
__le32 *mid_frame_timestamp;
__le32 *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.
*/
__le32 *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 {
__le16 timestamp;
u16 invalid;
u16 iso_header;
__le16 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 mutex 'mtx' - 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 mtx, take mtx first to avoid deadlock!
*/
struct mutex mtx;
/* 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 */
此差异已折叠。
/*
* dv1394.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_H
#define _DV_1394_H
/* This is the public user-space interface. Try not to break it. */
#define DV1394_API_VERSION 0x20011127
/* ********************
** **
** DV1394 API **
** **
********************
There are two methods of operating the DV1394 DV output device.
1)
The simplest is an interface based on write(): simply write
full DV frames of data to the device, and they will be transmitted
as quickly as possible. The FD may be set for non-blocking I/O,
in which case you can use select() or poll() to wait for output
buffer space.
To set the DV output parameters (e.g. whether you want NTSC or PAL
video), use the DV1394_INIT ioctl, passing in the parameters you
want in a struct dv1394_init.
Example 1:
To play a raw .DV file: cat foo.DV > /dev/dv1394
(cat will use write() internally)
Example 2:
static struct dv1394_init init = {
0x63, (broadcast channel)
4, (four-frame ringbuffer)
DV1394_NTSC, (send NTSC video)
0, 0 (default empty packet rate)
}
ioctl(fd, DV1394_INIT, &init);
while (1) {
read( <a raw DV file>, buf, DV1394_NTSC_FRAME_SIZE );
write( <the dv1394 FD>, buf, DV1394_NTSC_FRAME_SIZE );
}
2)
For more control over buffering, and to avoid unnecessary copies
of the DV data, you can use the more sophisticated the mmap() interface.
First, call the DV1394_INIT ioctl to specify your parameters,
including the number of frames in the ringbuffer. Then, calling mmap()
on the dv1394 device will give you direct access to the ringbuffer
from which the DV card reads your frame data.
The ringbuffer is simply one large, contiguous region of memory
containing two or more frames of packed DV data. Each frame of DV data
is 120000 bytes (NTSC) or 144000 bytes (PAL).
Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES
ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl
or select()/poll() to wait until the frames are transmitted. Next, you'll
need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer
frames are clear (ready to be filled with new DV data). Finally, use
DV1394_SUBMIT_FRAMES again to send the new data to the DV output.
Example: here is what a four-frame ringbuffer might look like
during DV transmission:
frame 0 frame 1 frame 2 frame 3
*--------------------------------------*
| CLEAR | DV data | DV data | CLEAR |
*--------------------------------------*
<ACTIVE>
transmission goes in this direction --->>>
The DV hardware is currently transmitting the data in frame 1.
Once frame 1 is finished, it will automatically transmit frame 2.
(if frame 2 finishes before frame 3 is submitted, the device
will continue to transmit frame 2, and will increase the dropped_frames
counter each time it repeats the transmission).
If you called DV1394_GET_STATUS at this instant, you would
receive the following values:
n_frames = 4
active_frame = 1
first_clear_frame = 3
n_clear_frames = 2
At this point, you should write new DV data into frame 3 and optionally
frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that
it may transmit the new frames.
ERROR HANDLING
An error (buffer underflow/overflow or a break in the DV stream due
to a 1394 bus reset) can be detected by checking the dropped_frames
field of struct dv1394_status (obtained through the
DV1394_GET_STATUS ioctl).
The best way to recover from such an error is to re-initialize
dv1394, either by using the DV1394_INIT ioctl call, or closing the
file descriptor and opening it again. (note that you must unmap all
ringbuffer mappings when closing the file descriptor, or else
dv1394 will still be considered 'in use').
MAIN LOOP
For maximum efficiency and robustness against bus errors, you are
advised to model the main loop of your application after the
following pseudo-code example:
(checks of system call return values omitted for brevity; always
check return values in your code!)
while ( frames left ) {
struct pollfd *pfd = ...;
pfd->fd = dv1394_fd;
pfd->revents = 0;
pfd->events = POLLOUT | POLLIN; (OUT for transmit, IN for receive)
(add other sources of I/O here)
poll(pfd, 1, -1); (or select(); add a timeout if you want)
if (pfd->revents) {
struct dv1394_status status;
ioctl(dv1394_fd, DV1394_GET_STATUS, &status);
if (status.dropped_frames > 0) {
reset_dv1394();
} else {
for (int i = 0; i < status.n_clear_frames; i++) {
copy_DV_frame();
}
}
}
}
where copy_DV_frame() reads or writes on the dv1394 file descriptor
(read/write mode) or copies data to/from the mmap ringbuffer and
then calls ioctl(DV1394_SUBMIT_FRAMES) to notify dv1394 that new
frames are availble (mmap mode).
reset_dv1394() is called in the event of a buffer
underflow/overflow or a halt in the DV stream (e.g. due to a 1394
bus reset). To guarantee recovery from the error, this function
should close the dv1394 file descriptor (and munmap() all
ringbuffer mappings, if you are using them), then re-open the
dv1394 device (and re-map the ringbuffer).
*/
/* maximum number of frames in the ringbuffer */
#define DV1394_MAX_FRAMES 32
/* number of *full* isochronous packets per DV frame */
#define DV1394_NTSC_PACKETS_PER_FRAME 250
#define DV1394_PAL_PACKETS_PER_FRAME 300
/* size of one frame's worth of DV data, in bytes */
#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME)
#define DV1394_PAL_FRAME_SIZE (480 * DV1394_PAL_PACKETS_PER_FRAME)
/* ioctl() commands */
#include "ieee1394-ioctl.h"
enum pal_or_ntsc {
DV1394_NTSC = 0,
DV1394_PAL
};
/* this is the argument to DV1394_INIT */
struct dv1394_init {
/* DV1394_API_VERSION */
unsigned int api_version;
/* isochronous transmission channel to use */
unsigned int channel;
/* number of frames in the ringbuffer. Must be at least 2
and at most DV1394_MAX_FRAMES. */
unsigned int n_frames;
/* send/receive PAL or NTSC video format */
enum pal_or_ntsc format;
/* the following are used only for transmission */
/* set these to zero unless you want a
non-default empty packet rate (see below) */
unsigned long cip_n;
unsigned long cip_d;
/* set this to zero unless you want a
non-default SYT cycle offset (default = 3 cycles) */
unsigned int syt_offset;
};
/* NOTE: you may only allocate the DV frame ringbuffer once each time
you open the dv1394 device. DV1394_INIT will fail if you call it a
second time with different 'n_frames' or 'format' arguments (which
would imply a different size for the ringbuffer). If you need a
different buffer size, simply close and re-open the device, then
initialize it with your new settings. */
/* Q: What are cip_n and cip_d? */
/*
A: DV video streams do not utilize 100% of the potential bandwidth offered
by IEEE 1394 (FireWire). To achieve the correct rate of data transmission,
DV devices must periodically insert empty packets into the 1394 data stream.
Typically there is one empty packet per 14-16 data-carrying packets.
Some DV devices will accept a wide range of empty packet rates, while others
require a precise rate. If the dv1394 driver produces empty packets at
a rate that your device does not accept, you may see ugly patterns on the
DV output, or even no output at all.
The default empty packet insertion rate seems to work for many people; if
your DV output is stable, you can simply ignore this discussion. However,
we have exposed the empty packet rate as a parameter to support devices that
do not work with the default rate.
The decision to insert an empty packet is made with a numerator/denominator
algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D.
You can alter the empty packet rate by passing non-zero values for cip_n
and cip_d to the INIT ioctl.
*/
struct dv1394_status {
/* this embedded init struct returns the current dv1394
parameters in use */
struct dv1394_init init;
/* the ringbuffer frame that is currently being
displayed. (-1 if the device is not transmitting anything) */
int active_frame;
/* index of the first buffer (ahead of active_frame) that
is ready to be filled with data */
unsigned int first_clear_frame;
/* how many buffers, including first_clear_buffer, are
ready to be filled with data */
unsigned int n_clear_frames;
/* how many times the DV stream has underflowed, overflowed,
or otherwise encountered an error, since the previous call
to DV1394_GET_STATUS */
unsigned int dropped_frames;
/* N.B. The dropped_frames counter is only a lower bound on the actual
number of dropped frames, with the special case that if dropped_frames
is zero, then it is guaranteed that NO frames have been dropped
since the last call to DV1394_GET_STATUS.
*/
};
#endif /* _DV_1394_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
#ifndef IEEE1394_HIGHLEVEL_H
#define IEEE1394_HIGHLEVEL_H
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/types.h>
struct module;
#include "ieee1394_types.h"
struct hpsb_host;
/* internal to ieee1394 core */
struct hpsb_address_serve {
struct list_head host_list; /* per host list */
struct list_head hl_list; /* hpsb_highlevel list */
const struct hpsb_address_ops *op;
struct hpsb_host *host;
u64 start; /* first address handled, quadlet aligned */
u64 end; /* first address behind, quadlet aligned */
};
/* Only the following structures are of interest to actual highlevel drivers. */
struct hpsb_highlevel {
const char *name;
/* Any of the following pointers can legally be NULL. */
/* New host initialized. Will also be called during
* hpsb_register_highlevel for all hosts already installed. */
void (*add_host)(struct hpsb_host *host);
/* Host about to be removed. Will also be called during
* hpsb_unregister_highlevel once for each host. */
void (*remove_host)(struct hpsb_host *host);
/* Host experienced bus reset with possible configuration changes.
* Note that this one may occur during interrupt/bottom half handling.
* You can not expect to be able to do stock hpsb_reads. */
void (*host_reset)(struct hpsb_host *host);
/* A write request was received on either the FCP_COMMAND (direction =
* 0) or the FCP_RESPONSE (direction = 1) register. The cts arg
* contains the cts field (first byte of data). */
void (*fcp_request)(struct hpsb_host *host, int nodeid, int direction,
int cts, u8 *data, size_t length);
/* These are initialized by the subsystem when the
* hpsb_higlevel is registered. */
struct list_head hl_list;
struct list_head irq_list;
struct list_head addr_list;
struct list_head host_info_list;
rwlock_t host_info_lock;
};
struct hpsb_address_ops {
/*
* Null function pointers will make the respective operation complete
* with RCODE_TYPE_ERROR. Makes for easy to implement read-only
* registers (just leave everything but read NULL).
*
* All functions shall return appropriate IEEE 1394 rcodes.
*/
/* These functions have to implement block reads for themselves.
*
* These functions either return a response code or a negative number.
* In the first case a response will be generated. In the latter case,
* no response will be sent and the driver which handled the request
* will send the response itself. */
int (*read)(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
u64 addr, size_t length, u16 flags);
int (*write)(struct hpsb_host *host, int nodeid, int destid,
quadlet_t *data, u64 addr, size_t length, u16 flags);
/* Lock transactions: write results of ext_tcode operation into
* *store. */
int (*lock)(struct hpsb_host *host, int nodeid, quadlet_t *store,
u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
u16 flags);
int (*lock64)(struct hpsb_host *host, int nodeid, octlet_t *store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags);
};
void highlevel_add_host(struct hpsb_host *host);
void highlevel_remove_host(struct hpsb_host *host);
void highlevel_host_reset(struct hpsb_host *host);
int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
unsigned int length, u16 flags);
int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
u64 addr, unsigned int length, u16 flags);
int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
u16 flags);
int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
u16 flags);
void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
void *data, size_t length);
/**
* hpsb_init_highlevel - initialize a struct hpsb_highlevel
*
* This is only necessary if hpsb_get_hostinfo_bykey can be called
* before hpsb_register_highlevel.
*/
static inline void hpsb_init_highlevel(struct hpsb_highlevel *hl)
{
rwlock_init(&hl->host_info_lock);
INIT_LIST_HEAD(&hl->host_info_list);
}
void hpsb_register_highlevel(struct hpsb_highlevel *hl);
void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
struct hpsb_host *host,
const struct hpsb_address_ops *ops,
u64 size, u64 alignment,
u64 start, u64 end);
int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
const struct hpsb_address_ops *ops,
u64 start, u64 end);
int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
u64 start);
void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
size_t data_size);
void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned long key);
void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key);
int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
void *data);
#endif /* IEEE1394_HIGHLEVEL_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
#ifndef _IEEE1394_HOTPLUG_H
#define _IEEE1394_HOTPLUG_H
/* Unit spec id and sw version entry for some protocols */
#define AVC_UNIT_SPEC_ID_ENTRY 0x0000A02D
#define AVC_SW_VERSION_ENTRY 0x00010001
#define CAMERA_UNIT_SPEC_ID_ENTRY 0x0000A02D
#define CAMERA_SW_VERSION_ENTRY 0x00000100
/* /include/linux/mod_devicetable.h defines:
* IEEE1394_MATCH_VENDOR_ID
* IEEE1394_MATCH_MODEL_ID
* IEEE1394_MATCH_SPECIFIER_ID
* IEEE1394_MATCH_VERSION
* struct ieee1394_device_id
*/
#include <linux/mod_devicetable.h>
#endif /* _IEEE1394_HOTPLUG_H */
此差异已折叠。
#ifndef _IEEE1394_TRANSACTIONS_H
#define _IEEE1394_TRANSACTIONS_H
#include <linux/types.h>
#include "ieee1394_types.h"
struct hpsb_packet;
struct hpsb_host;
int hpsb_get_tlabel(struct hpsb_packet *packet);
void hpsb_free_tlabel(struct hpsb_packet *packet);
struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
u64 addr, size_t length);
struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
u64 addr, int extcode, quadlet_t *data,
quadlet_t arg);
struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
nodeid_t node, u64 addr, int extcode,
octlet_t *data, octlet_t arg);
struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
nodeid_t node, u64 addr,
quadlet_t *buffer, size_t length);
struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer,
int length, int channel, int tag,
int sync);
int hpsb_packet_success(struct hpsb_packet *packet);
int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t *buffer, size_t length);
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t *buffer, size_t length);
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
#ifdef HPSB_DEBUG_TLABELS
extern spinlock_t hpsb_tlabel_lock;
#endif
#endif /* _IEEE1394_TRANSACTIONS_H */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册