diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 15:05:29 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 15:05:29 (GMT) |
commit | b7d41a9fbb364c67d91c3588e117eba547e2d4bf (patch) | |
tree | abf95ce77eaa8b7aed30fded4d3592b4af152a99 | |
parent | da47c19e5c746829042933c8f945a71e2b62d6fc (diff) | |
parent | 66fa12c571d35e3cd62574c65f1785a460105397 (diff) | |
download | linux-b7d41a9fbb364c67d91c3588e117eba547e2d4bf.tar.xz |
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.
52 files changed, 96 insertions, 29325 deletions
diff --git a/Documentation/ABI/obsolete/dv1394 b/Documentation/ABI/obsolete/dv1394 deleted file mode 100644 index 2ee3686..0000000 --- a/Documentation/ABI/obsolete/dv1394 +++ /dev/null @@ -1,9 +0,0 @@ -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) diff --git a/Documentation/ABI/removed/dv1394 b/Documentation/ABI/removed/dv1394 new file mode 100644 index 0000000..c2310b6 --- /dev/null +++ b/Documentation/ABI/removed/dv1394 @@ -0,0 +1,14 @@ +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) diff --git a/Documentation/ABI/removed/raw1394 b/Documentation/ABI/removed/raw1394 new file mode 100644 index 0000000..490aa1e --- /dev/null +++ b/Documentation/ABI/removed/raw1394 @@ -0,0 +1,15 @@ +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) diff --git a/Documentation/ABI/removed/raw1394_legacy_isochronous b/Documentation/ABI/removed/raw1394_legacy_isochronous deleted file mode 100644 index 1b62962..0000000 --- a/Documentation/ABI/removed/raw1394_legacy_isochronous +++ /dev/null @@ -1,16 +0,0 @@ -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 diff --git a/Documentation/ABI/removed/video1394 b/Documentation/ABI/removed/video1394 new file mode 100644 index 0000000..c39c25a --- /dev/null +++ b/Documentation/ABI/removed/video1394 @@ -0,0 +1,16 @@ +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) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 9961f15..e833c8c 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -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 diff --git a/drivers/Makefile b/drivers/Makefile index 167af31..14cf907 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -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/ diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index fcf3ea2..40a222e 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig @@ -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 diff --git a/drivers/firewire/Makefile b/drivers/firewire/Makefile index 3c6a7fb..e3870d5 100644 --- a/drivers/firewire/Makefile +++ b/drivers/firewire/Makefile @@ -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 diff --git a/drivers/ieee1394/init_ohci1394_dma.c b/drivers/firewire/init_ohci1394_dma.c index ddaab6e..a9a347a 100644 --- a/drivers/ieee1394/init_ohci1394_dma.c +++ b/drivers/firewire/init_ohci1394_dma.c @@ -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) diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig deleted file mode 100644 index e02096c..0000000 --- a/drivers/ieee1394/Kconfig +++ /dev/null @@ -1,182 +0,0 @@ -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. diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile deleted file mode 100644 index 1f8153b..0000000 --- a/drivers/ieee1394/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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 diff --git a/drivers/ieee1394/config_roms.c b/drivers/ieee1394/config_roms.c deleted file mode 100644 index 1b98120..0000000 --- a/drivers/ieee1394/config_roms.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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(); -} diff --git a/drivers/ieee1394/config_roms.h b/drivers/ieee1394/config_roms.h deleted file mode 100644 index 1f5cd1f..0000000 --- a/drivers/ieee1394/config_roms.h +++ /dev/null @@ -1,19 +0,0 @@ -#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 */ diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c deleted file mode 100644 index d696f69..0000000 --- a/drivers/ieee1394/csr.c +++ /dev/null @@ -1,843 +0,0 @@ -/* - * IEEE 1394 for Linux - * - * CSR implementation, iso/bus manager implementation. - * - * Copyright (C) 1999 Andreas E. Bombe - * 2002 Manfred Weihs <weihs@ict.tuwien.ac.at> - * - * This code is licensed under the GPL. See the file COPYING in the root - * directory of the kernel sources for details. - * - * - * Contributions: - * - * Manfred Weihs <weihs@ict.tuwien.ac.at> - * configuration ROM manipulation - * - */ - -#include <linux/jiffies.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/param.h> -#include <linux/spinlock.h> -#include <linux/string.h> - -#include "csr1212.h" -#include "ieee1394_types.h" -#include "hosts.h" -#include "ieee1394.h" -#include "highlevel.h" -#include "ieee1394_core.h" - -/* Module Parameters */ -/* this module parameter can be used to disable mapping of the FCP registers */ - -static int fcp = 1; -module_param(fcp, int, 0444); -MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0)."); - -static struct csr1212_keyval *node_cap = NULL; - -static void add_host(struct hpsb_host *host); -static void remove_host(struct hpsb_host *host); -static void host_reset(struct hpsb_host *host); -static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, size_t length, u16 fl); -static int write_fcp(struct hpsb_host *host, int nodeid, int dest, - quadlet_t *data, u64 addr, size_t length, u16 flags); -static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf, - u64 addr, size_t length, u16 flags); -static int write_regs(struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, size_t length, u16 flags); -static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl); -static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store, - u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl); -static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, size_t length, u16 fl); -static u64 allocate_addr_range(u64 size, u32 alignment, void *__host); -static void release_addr_range(u64 addr, void *__host); - -static struct hpsb_highlevel csr_highlevel = { - .name = "standard registers", - .add_host = add_host, - .remove_host = remove_host, - .host_reset = host_reset, -}; - -static const struct hpsb_address_ops map_ops = { - .read = read_maps, -}; - -static const struct hpsb_address_ops fcp_ops = { - .write = write_fcp, -}; - -static const struct hpsb_address_ops reg_ops = { - .read = read_regs, - .write = write_regs, - .lock = lock_regs, - .lock64 = lock64_regs, -}; - -static const struct hpsb_address_ops config_rom_ops = { - .read = read_config_rom, -}; - -struct csr1212_bus_ops csr_bus_ops = { - .allocate_addr_range = allocate_addr_range, - .release_addr = release_addr_range, -}; - - -static u16 csr_crc16(unsigned *data, int length) -{ - int check=0, i; - int shift, sum, next=0; - - for (i = length; i; i--) { - for (next = check, shift = 28; shift >= 0; shift -= 4 ) { - sum = ((next >> 12) ^ (be32_to_cpu(*data) >> shift)) & 0xf; - next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); - } - check = next & 0xffff; - data++; - } - - return check; -} - -static void host_reset(struct hpsb_host *host) -{ - host->csr.state &= 0x300; - - host->csr.bus_manager_id = 0x3f; - host->csr.bandwidth_available = 4915; - host->csr.channels_available_hi = 0xfffffffe; /* pre-alloc ch 31 per 1394a-2000 */ - host->csr.channels_available_lo = ~0; - host->csr.broadcast_channel = 0x80000000 | 31; - - if (host->is_irm) { - if (host->driver->hw_csr_reg) { - host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0); - } - } - - host->csr.node_ids = host->node_id << 16; - - if (!host->is_root) { - /* clear cmstr bit */ - host->csr.state &= ~0x100; - } - - be32_add_cpu(&host->csr.topology_map[1], 1); - host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16 - | host->selfid_count); - host->csr.topology_map[0] = - cpu_to_be32((host->selfid_count + 2) << 16 - | csr_crc16(host->csr.topology_map + 1, - host->selfid_count + 2)); - - be32_add_cpu(&host->csr.speed_map[1], 1); - host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16 - | csr_crc16(host->csr.speed_map+1, - 0x3f1)); -} - -/* - * HI == seconds (bits 0:2) - * LO == fractions of a second in units of 125usec (bits 19:31) - * - * Convert SPLIT_TIMEOUT to jiffies. - * The default and minimum as per 1394a-2000 clause 8.3.2.2.6 is 100ms. - */ -static inline void calculate_expire(struct csr_control *csr) -{ - unsigned int usecs = (csr->split_timeout_hi & 7) * 1000000 + - (csr->split_timeout_lo >> 19) * 125; - - csr->expire = usecs_to_jiffies(usecs > 100000 ? usecs : 100000); - HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ); -} - - -static void add_host(struct hpsb_host *host) -{ - struct csr1212_keyval *root; - quadlet_t bus_info[CSR_BUS_INFO_SIZE]; - - hpsb_register_addrspace(&csr_highlevel, host, ®_ops, - CSR_REGISTER_BASE, - CSR_REGISTER_BASE + CSR_CONFIG_ROM); - hpsb_register_addrspace(&csr_highlevel, host, &config_rom_ops, - CSR_REGISTER_BASE + CSR_CONFIG_ROM, - CSR_REGISTER_BASE + CSR_CONFIG_ROM_END); - if (fcp) { - hpsb_register_addrspace(&csr_highlevel, host, &fcp_ops, - CSR_REGISTER_BASE + CSR_FCP_COMMAND, - CSR_REGISTER_BASE + CSR_FCP_END); - } - hpsb_register_addrspace(&csr_highlevel, host, &map_ops, - CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP, - CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END); - hpsb_register_addrspace(&csr_highlevel, host, &map_ops, - CSR_REGISTER_BASE + CSR_SPEED_MAP, - CSR_REGISTER_BASE + CSR_SPEED_MAP_END); - - spin_lock_init(&host->csr.lock); - - host->csr.state = 0; - host->csr.node_ids = 0; - host->csr.split_timeout_hi = 0; - host->csr.split_timeout_lo = 800 << 19; - calculate_expire(&host->csr); - host->csr.cycle_time = 0; - host->csr.bus_time = 0; - host->csr.bus_manager_id = 0x3f; - host->csr.bandwidth_available = 4915; - host->csr.channels_available_hi = 0xfffffffe; /* pre-alloc ch 31 per 1394a-2000 */ - host->csr.channels_available_lo = ~0; - host->csr.broadcast_channel = 0x80000000 | 31; - - if (host->is_irm) { - if (host->driver->hw_csr_reg) { - host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0); - } - } - - if (host->csr.max_rec >= 9) - host->csr.max_rom = 2; - else if (host->csr.max_rec >= 5) - host->csr.max_rom = 1; - else - host->csr.max_rom = 0; - - host->csr.generation = 2; - - bus_info[1] = IEEE1394_BUSID_MAGIC; - bus_info[2] = cpu_to_be32((hpsb_disable_irm ? 0 : 1 << CSR_IRMC_SHIFT) | - (1 << CSR_CMC_SHIFT) | - (1 << CSR_ISC_SHIFT) | - (0 << CSR_BMC_SHIFT) | - (0 << CSR_PMC_SHIFT) | - (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) | - (host->csr.max_rec << CSR_MAX_REC_SHIFT) | - (host->csr.max_rom << CSR_MAX_ROM_SHIFT) | - (host->csr.generation << CSR_GENERATION_SHIFT) | - host->csr.lnk_spd); - - bus_info[3] = cpu_to_be32(host->csr.guid_hi); - bus_info[4] = cpu_to_be32(host->csr.guid_lo); - - /* The hardware copy of the bus info block will be set later when a - * bus reset is issued. */ - - csr1212_init_local_csr(host->csr.rom, bus_info, host->csr.max_rom); - - root = host->csr.rom->root_kv; - - if(csr1212_attach_keyval_to_directory(root, node_cap) != CSR1212_SUCCESS) { - HPSB_ERR("Failed to attach Node Capabilities to root directory"); - } - - host->update_config_rom = 1; -} - -static void remove_host(struct hpsb_host *host) -{ - quadlet_t bus_info[CSR_BUS_INFO_SIZE]; - - bus_info[1] = IEEE1394_BUSID_MAGIC; - bus_info[2] = cpu_to_be32((0 << CSR_IRMC_SHIFT) | - (0 << CSR_CMC_SHIFT) | - (0 << CSR_ISC_SHIFT) | - (0 << CSR_BMC_SHIFT) | - (0 << CSR_PMC_SHIFT) | - (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) | - (host->csr.max_rec << CSR_MAX_REC_SHIFT) | - (0 << CSR_MAX_ROM_SHIFT) | - (0 << CSR_GENERATION_SHIFT) | - host->csr.lnk_spd); - - bus_info[3] = cpu_to_be32(host->csr.guid_hi); - bus_info[4] = cpu_to_be32(host->csr.guid_lo); - - csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, node_cap); - - csr1212_init_local_csr(host->csr.rom, bus_info, 0); - host->update_config_rom = 1; -} - - -int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom, - size_t buffersize, unsigned char rom_version) -{ - unsigned long flags; - int ret; - - HPSB_NOTICE("hpsb_update_config_rom() is deprecated"); - - spin_lock_irqsave(&host->csr.lock, flags); - if (rom_version != host->csr.generation) - ret = -1; - else if (buffersize > host->csr.rom->cache_head->size) - ret = -2; - else { - /* Just overwrite the generated ConfigROM image with new data, - * it can be regenerated later. */ - memcpy(host->csr.rom->cache_head->data, new_rom, buffersize); - host->csr.rom->cache_head->len = buffersize; - - if (host->driver->set_hw_config_rom) - host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data); - /* Increment the generation number to keep some sort of sync - * with the newer ConfigROM manipulation method. */ - host->csr.generation++; - if (host->csr.generation > 0xf || host->csr.generation < 2) - host->csr.generation = 2; - ret=0; - } - spin_unlock_irqrestore(&host->csr.lock, flags); - return ret; -} - - -/* Read topology / speed maps and configuration ROM */ -static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, size_t length, u16 fl) -{ - unsigned long flags; - int csraddr = addr - CSR_REGISTER_BASE; - const char *src; - - spin_lock_irqsave(&host->csr.lock, flags); - - if (csraddr < CSR_SPEED_MAP) { - src = ((char *)host->csr.topology_map) + csraddr - - CSR_TOPOLOGY_MAP; - } else { - src = ((char *)host->csr.speed_map) + csraddr - CSR_SPEED_MAP; - } - - memcpy(buffer, src, length); - spin_unlock_irqrestore(&host->csr.lock, flags); - return RCODE_COMPLETE; -} - - -#define out if (--length == 0) break - -static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf, - u64 addr, size_t length, u16 flags) -{ - int csraddr = addr - CSR_REGISTER_BASE; - int oldcycle; - quadlet_t ret; - - if ((csraddr | length) & 0x3) - return RCODE_TYPE_ERROR; - - length /= 4; - - switch (csraddr) { - case CSR_STATE_CLEAR: - *(buf++) = cpu_to_be32(host->csr.state); - out; - case CSR_STATE_SET: - *(buf++) = cpu_to_be32(host->csr.state); - out; - case CSR_NODE_IDS: - *(buf++) = cpu_to_be32(host->csr.node_ids); - out; - - case CSR_RESET_START: - return RCODE_TYPE_ERROR; - - /* address gap - handled by default below */ - - case CSR_SPLIT_TIMEOUT_HI: - *(buf++) = cpu_to_be32(host->csr.split_timeout_hi); - out; - case CSR_SPLIT_TIMEOUT_LO: - *(buf++) = cpu_to_be32(host->csr.split_timeout_lo); - out; - - /* address gap */ - return RCODE_ADDRESS_ERROR; - - case CSR_CYCLE_TIME: - oldcycle = host->csr.cycle_time; - host->csr.cycle_time = - host->driver->devctl(host, GET_CYCLE_COUNTER, 0); - - if (oldcycle > host->csr.cycle_time) { - /* cycle time wrapped around */ - host->csr.bus_time += 1 << 7; - } - *(buf++) = cpu_to_be32(host->csr.cycle_time); - out; - case CSR_BUS_TIME: - oldcycle = host->csr.cycle_time; - host->csr.cycle_time = - host->driver->devctl(host, GET_CYCLE_COUNTER, 0); - - if (oldcycle > host->csr.cycle_time) { - /* cycle time wrapped around */ - host->csr.bus_time += (1 << 7); - } - *(buf++) = cpu_to_be32(host->csr.bus_time - | (host->csr.cycle_time >> 25)); - out; - - /* address gap */ - return RCODE_ADDRESS_ERROR; - - case CSR_BUSY_TIMEOUT: - /* not yet implemented */ - return RCODE_ADDRESS_ERROR; - - case CSR_BUS_MANAGER_ID: - if (host->driver->hw_csr_reg) - ret = host->driver->hw_csr_reg(host, 0, 0, 0); - else - ret = host->csr.bus_manager_id; - - *(buf++) = cpu_to_be32(ret); - out; - case CSR_BANDWIDTH_AVAILABLE: - if (host->driver->hw_csr_reg) - ret = host->driver->hw_csr_reg(host, 1, 0, 0); - else - ret = host->csr.bandwidth_available; - - *(buf++) = cpu_to_be32(ret); - out; - case CSR_CHANNELS_AVAILABLE_HI: - if (host->driver->hw_csr_reg) - ret = host->driver->hw_csr_reg(host, 2, 0, 0); - else - ret = host->csr.channels_available_hi; - - *(buf++) = cpu_to_be32(ret); - out; - case CSR_CHANNELS_AVAILABLE_LO: - if (host->driver->hw_csr_reg) - ret = host->driver->hw_csr_reg(host, 3, 0, 0); - else - ret = host->csr.channels_available_lo; - - *(buf++) = cpu_to_be32(ret); - out; - - case CSR_BROADCAST_CHANNEL: - *(buf++) = cpu_to_be32(host->csr.broadcast_channel); - out; - - /* address gap to end - fall through to default */ - default: - return RCODE_ADDRESS_ERROR; - } - - return RCODE_COMPLETE; -} - -static int write_regs(struct hpsb_host *host, int nodeid, int destid, - quadlet_t *data, u64 addr, size_t length, u16 flags) -{ - int csraddr = addr - CSR_REGISTER_BASE; - - if ((csraddr | length) & 0x3) - return RCODE_TYPE_ERROR; - - length /= 4; - - switch (csraddr) { - case CSR_STATE_CLEAR: - /* FIXME FIXME FIXME */ - printk("doh, someone wants to mess with state clear\n"); - out; - case CSR_STATE_SET: - printk("doh, someone wants to mess with state set\n"); - out; - - case CSR_NODE_IDS: - host->csr.node_ids &= NODE_MASK << 16; - host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16); - host->node_id = host->csr.node_ids >> 16; - host->driver->devctl(host, SET_BUS_ID, host->node_id >> 6); - out; - - case CSR_RESET_START: - /* FIXME - perform command reset */ - out; - - /* address gap */ - return RCODE_ADDRESS_ERROR; - - case CSR_SPLIT_TIMEOUT_HI: - host->csr.split_timeout_hi = - be32_to_cpu(*(data++)) & 0x00000007; - calculate_expire(&host->csr); - out; - case CSR_SPLIT_TIMEOUT_LO: - host->csr.split_timeout_lo = - be32_to_cpu(*(data++)) & 0xfff80000; - calculate_expire(&host->csr); - out; - - /* address gap */ - return RCODE_ADDRESS_ERROR; - - case CSR_CYCLE_TIME: - /* should only be set by cycle start packet, automatically */ - host->csr.cycle_time = be32_to_cpu(*data); - host->driver->devctl(host, SET_CYCLE_COUNTER, - be32_to_cpu(*(data++))); - out; - case CSR_BUS_TIME: - host->csr.bus_time = be32_to_cpu(*(data++)) & 0xffffff80; - out; - - /* address gap */ - return RCODE_ADDRESS_ERROR; - - case CSR_BUSY_TIMEOUT: - /* not yet implemented */ - return RCODE_ADDRESS_ERROR; - - case CSR_BUS_MANAGER_ID: - case CSR_BANDWIDTH_AVAILABLE: - case CSR_CHANNELS_AVAILABLE_HI: - case CSR_CHANNELS_AVAILABLE_LO: - /* these are not writable, only lockable */ - return RCODE_TYPE_ERROR; - - case CSR_BROADCAST_CHANNEL: - /* only the valid bit can be written */ - host->csr.broadcast_channel = (host->csr.broadcast_channel & ~0x40000000) - | (be32_to_cpu(*data) & 0x40000000); - out; - - /* address gap to end - fall through */ - default: - return RCODE_ADDRESS_ERROR; - } - - return RCODE_COMPLETE; -} - -#undef out - - -static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store, - u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl) -{ - int csraddr = addr - CSR_REGISTER_BASE; - unsigned long flags; - quadlet_t *regptr = NULL; - - if (csraddr & 0x3) - return RCODE_TYPE_ERROR; - - if (csraddr < CSR_BUS_MANAGER_ID || csraddr > CSR_CHANNELS_AVAILABLE_LO - || extcode != EXTCODE_COMPARE_SWAP) - goto unsupported_lockreq; - - data = be32_to_cpu(data); - arg = be32_to_cpu(arg); - - /* Is somebody releasing the broadcast_channel on us? */ - if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x1)) { - /* Note: this is may not be the right way to handle - * the problem, so we should look into the proper way - * eventually. */ - HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release " - "broadcast channel 31. Ignoring.", - NODE_BUS_ARGS(host, nodeid)); - - data &= ~0x1; /* keep broadcast channel allocated */ - } - - if (host->driver->hw_csr_reg) { - quadlet_t old; - - old = host->driver-> - hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2, - data, arg); - - *store = cpu_to_be32(old); - return RCODE_COMPLETE; - } - - spin_lock_irqsave(&host->csr.lock, flags); - - switch (csraddr) { - case CSR_BUS_MANAGER_ID: - regptr = &host->csr.bus_manager_id; - *store = cpu_to_be32(*regptr); - if (*regptr == arg) - *regptr = data; - break; - - case CSR_BANDWIDTH_AVAILABLE: - { - quadlet_t bandwidth; - quadlet_t old; - quadlet_t new; - - regptr = &host->csr.bandwidth_available; - old = *regptr; - - /* bandwidth available algorithm adapted from IEEE 1394a-2000 spec */ - if (arg > 0x1fff) { - *store = cpu_to_be32(old); /* change nothing */ - break; - } - data &= 0x1fff; - if (arg >= data) { - /* allocate bandwidth */ - bandwidth = arg - data; - if (old >= bandwidth) { - new = old - bandwidth; - *store = cpu_to_be32(arg); - *regptr = new; - } else { - *store = cpu_to_be32(old); - } - } else { - /* deallocate bandwidth */ - bandwidth = data - arg; - if (old + bandwidth < 0x2000) { - new = old + bandwidth; - *store = cpu_to_be32(arg); - *regptr = new; - } else { - *store = cpu_to_be32(old); - } - } - break; - } - - case CSR_CHANNELS_AVAILABLE_HI: - { - /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */ - quadlet_t affected_channels = arg ^ data; - - regptr = &host->csr.channels_available_hi; - - if ((arg & affected_channels) == (*regptr & affected_channels)) { - *regptr ^= affected_channels; - *store = cpu_to_be32(arg); - } else { - *store = cpu_to_be32(*regptr); - } - - break; - } - - case CSR_CHANNELS_AVAILABLE_LO: - { - /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */ - quadlet_t affected_channels = arg ^ data; - - regptr = &host->csr.channels_available_lo; - - if ((arg & affected_channels) == (*regptr & affected_channels)) { - *regptr ^= affected_channels; - *store = cpu_to_be32(arg); - } else { - *store = cpu_to_be32(*regptr); - } - break; - } - } - - spin_unlock_irqrestore(&host->csr.lock, flags); - - return RCODE_COMPLETE; - - unsupported_lockreq: - switch (csraddr) { - case CSR_STATE_CLEAR: - case CSR_STATE_SET: - case CSR_RESET_START: - case CSR_NODE_IDS: - case CSR_SPLIT_TIMEOUT_HI: - case CSR_SPLIT_TIMEOUT_LO: - case CSR_CYCLE_TIME: - case CSR_BUS_TIME: - case CSR_BROADCAST_CHANNEL: - return RCODE_TYPE_ERROR; - - case CSR_BUSY_TIMEOUT: - /* not yet implemented - fall through */ - default: - return RCODE_ADDRESS_ERROR; - } -} - -static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store, - u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl) -{ - int csraddr = addr - CSR_REGISTER_BASE; - unsigned long flags; - - data = be64_to_cpu(data); - arg = be64_to_cpu(arg); - - if (csraddr & 0x3) - return RCODE_TYPE_ERROR; - - if (csraddr != CSR_CHANNELS_AVAILABLE - || extcode != EXTCODE_COMPARE_SWAP) - goto unsupported_lock64req; - - /* Is somebody releasing the broadcast_channel on us? */ - if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x100000000ULL)) { - /* Note: this is may not be the right way to handle - * the problem, so we should look into the proper way - * eventually. */ - HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release " - "broadcast channel 31. Ignoring.", - NODE_BUS_ARGS(host, nodeid)); - - data &= ~0x100000000ULL; /* keep broadcast channel allocated */ - } - - if (host->driver->hw_csr_reg) { - quadlet_t data_hi, data_lo; - quadlet_t arg_hi, arg_lo; - quadlet_t old_hi, old_lo; - - data_hi = data >> 32; - data_lo = data & 0xFFFFFFFF; - arg_hi = arg >> 32; - arg_lo = arg & 0xFFFFFFFF; - - old_hi = host->driver->hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2, - data_hi, arg_hi); - - old_lo = host->driver->hw_csr_reg(host, ((csraddr + 4) - CSR_BUS_MANAGER_ID) >> 2, - data_lo, arg_lo); - - *store = cpu_to_be64(((octlet_t)old_hi << 32) | old_lo); - } else { - octlet_t old; - octlet_t affected_channels = arg ^ data; - - spin_lock_irqsave(&host->csr.lock, flags); - - old = ((octlet_t)host->csr.channels_available_hi << 32) | host->csr.channels_available_lo; - - if ((arg & affected_channels) == (old & affected_channels)) { - host->csr.channels_available_hi ^= (affected_channels >> 32); - host->csr.channels_available_lo ^= (affected_channels & 0xffffffff); - *store = cpu_to_be64(arg); - } else { - *store = cpu_to_be64(old); - } - - spin_unlock_irqrestore(&host->csr.lock, flags); - } - - /* Is somebody erroneously releasing the broadcast_channel on us? */ - if (host->csr.channels_available_hi & 0x1) - host->csr.channels_available_hi &= ~0x1; - - return RCODE_COMPLETE; - - unsupported_lock64req: - switch (csraddr) { - case CSR_STATE_CLEAR: - case CSR_STATE_SET: - case CSR_RESET_START: - case CSR_NODE_IDS: - case CSR_SPLIT_TIMEOUT_HI: - case CSR_SPLIT_TIMEOUT_LO: - case CSR_CYCLE_TIME: - case CSR_BUS_TIME: - case CSR_BUS_MANAGER_ID: - case CSR_BROADCAST_CHANNEL: - case CSR_BUSY_TIMEOUT: - case CSR_BANDWIDTH_AVAILABLE: - return RCODE_TYPE_ERROR; - - default: - return RCODE_ADDRESS_ERROR; - } -} - -static int write_fcp(struct hpsb_host *host, int nodeid, int dest, - quadlet_t *data, u64 addr, size_t length, u16 flags) -{ - int csraddr = addr - CSR_REGISTER_BASE; - - if (length > 512) - return RCODE_TYPE_ERROR; - - switch (csraddr) { - case CSR_FCP_COMMAND: - highlevel_fcp_request(host, nodeid, 0, (u8 *)data, length); - break; - case CSR_FCP_RESPONSE: - highlevel_fcp_request(host, nodeid, 1, (u8 *)data, length); - break; - default: - return RCODE_TYPE_ERROR; - } - - return RCODE_COMPLETE; -} - -static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer, - u64 addr, size_t length, u16 fl) -{ - u32 offset = addr - CSR1212_REGISTER_SPACE_BASE; - - if (csr1212_read(host->csr.rom, offset, buffer, length) == CSR1212_SUCCESS) - return RCODE_COMPLETE; - else - return RCODE_ADDRESS_ERROR; -} - -static u64 allocate_addr_range(u64 size, u32 alignment, void *__host) -{ - struct hpsb_host *host = (struct hpsb_host*)__host; - - return hpsb_allocate_and_register_addrspace(&csr_highlevel, - host, - &config_rom_ops, - size, alignment, - CSR1212_UNITS_SPACE_BASE, - CSR1212_UNITS_SPACE_END); -} - -static void release_addr_range(u64 addr, void *__host) -{ - struct hpsb_host *host = (struct hpsb_host*)__host; - hpsb_unregister_addrspace(&csr_highlevel, host, addr); -} - - -int init_csr(void) -{ - node_cap = csr1212_new_immediate(CSR1212_KV_ID_NODE_CAPABILITIES, 0x0083c0); - if (!node_cap) { - HPSB_ERR("Failed to allocate memory for Node Capabilties ConfigROM entry!"); - return -ENOMEM; - } - - hpsb_register_highlevel(&csr_highlevel); - - return 0; -} - -void cleanup_csr(void) -{ - if (node_cap) - csr1212_release_keyval(node_cap); - hpsb_unregister_highlevel(&csr_highlevel); -} diff --git a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h deleted file mode 100644 index 90fb3f2..0000000 --- a/drivers/ieee1394/csr.h +++ /dev/null @@ -1,99 +0,0 @@ -#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 */ diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c deleted file mode 100644 index e76cac6..0000000 --- a/drivers/ieee1394/csr1212.c +++ /dev/null @@ -1,1467 +0,0 @@ -/* - * csr1212.c -- 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. - */ - - -/* TODO List: - * - Verify interface consistency: i.e., public functions that take a size - * parameter expect size to be in bytes. - */ - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/kmemcheck.h> -#include <linux/string.h> -#include <asm/bug.h> -#include <asm/byteorder.h> - -#include "csr1212.h" - - -/* Permitted key type for each key id */ -#define __I (1 << CSR1212_KV_TYPE_IMMEDIATE) -#define __C (1 << CSR1212_KV_TYPE_CSR_OFFSET) -#define __D (1 << CSR1212_KV_TYPE_DIRECTORY) -#define __L (1 << CSR1212_KV_TYPE_LEAF) -static const u8 csr1212_key_id_type_map[0x30] = { - __C, /* used by Apple iSight */ - __D | __L, /* Descriptor */ - __I | __D | __L, /* Bus_Dependent_Info */ - __I | __D | __L, /* Vendor */ - __I, /* Hardware_Version */ - 0, 0, /* Reserved */ - __D | __L | __I, /* Module */ - __I, 0, 0, 0, /* used by Apple iSight, Reserved */ - __I, /* Node_Capabilities */ - __L, /* EUI_64 */ - 0, 0, 0, /* Reserved */ - __D, /* Unit */ - __I, /* Specifier_ID */ - __I, /* Version */ - __I | __C | __D | __L, /* Dependent_Info */ - __L, /* Unit_Location */ - 0, /* Reserved */ - __I, /* Model */ - __D, /* Instance */ - __L, /* Keyword */ - __D, /* Feature */ - __L, /* Extended_ROM */ - __I, /* Extended_Key_Specifier_ID */ - __I, /* Extended_Key */ - __I | __C | __D | __L, /* Extended_Data */ - __L, /* Modifiable_Descriptor */ - __I, /* Directory_ID */ - __I, /* Revision */ -}; -#undef __I -#undef __C -#undef __D -#undef __L - - -#define quads_to_bytes(_q) ((_q) * sizeof(u32)) -#define bytes_to_quads(_b) DIV_ROUND_UP(_b, sizeof(u32)) - -static void free_keyval(struct csr1212_keyval *kv) -{ - if ((kv->key.type == CSR1212_KV_TYPE_LEAF) && - (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)) - CSR1212_FREE(kv->value.leaf.data); - - CSR1212_FREE(kv); -} - -static u16 csr1212_crc16(const u32 *buffer, size_t length) -{ - int shift; - u32 data; - u16 sum, crc = 0; - - for (; length; length--) { - data = be32_to_cpu(*buffer); - buffer++; - for (shift = 28; shift >= 0; shift -= 4 ) { - sum = ((crc >> 12) ^ (data >> shift)) & 0xf; - crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); - } - crc &= 0xffff; - } - - return cpu_to_be16(crc); -} - -/* Microsoft computes the CRC with the bytes in reverse order. */ -static u16 csr1212_msft_crc16(const u32 *buffer, size_t length) -{ - int shift; - u32 data; - u16 sum, crc = 0; - - for (; length; length--) { - data = le32_to_cpu(*buffer); - buffer++; - for (shift = 28; shift >= 0; shift -= 4 ) { - sum = ((crc >> 12) ^ (data >> shift)) & 0xf; - crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum); - } - crc &= 0xffff; - } - - return cpu_to_be16(crc); -} - -static struct csr1212_dentry * -csr1212_find_keyval(struct csr1212_keyval *dir, struct csr1212_keyval *kv) -{ - struct csr1212_dentry *pos; - - for (pos = dir->value.directory.dentries_head; - pos != NULL; pos = pos->next) - if (pos->kv == kv) - return pos; - return NULL; -} - -static struct csr1212_keyval * -csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, u32 offset) -{ - struct csr1212_keyval *kv; - - for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) - if (kv->offset == offset) - return kv; - return NULL; -} - - -/* Creation Routines */ - -struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, - size_t bus_info_size, void *private) -{ - struct csr1212_csr *csr; - - csr = CSR1212_MALLOC(sizeof(*csr)); - if (!csr) - return NULL; - - csr->cache_head = - csr1212_rom_cache_malloc(CSR1212_CONFIG_ROM_SPACE_OFFSET, - CSR1212_CONFIG_ROM_SPACE_SIZE); - if (!csr->cache_head) { - CSR1212_FREE(csr); - return NULL; - } - - /* The keyval key id is not used for the root node, but a valid key id - * that can be used for a directory needs to be passed to - * csr1212_new_directory(). */ - csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR); - if (!csr->root_kv) { - CSR1212_FREE(csr->cache_head); - CSR1212_FREE(csr); - return NULL; - } - - csr->bus_info_data = csr->cache_head->data; - csr->bus_info_len = bus_info_size; - csr->crc_len = bus_info_size; - csr->ops = ops; - csr->private = private; - csr->cache_tail = csr->cache_head; - - return csr; -} - -void csr1212_init_local_csr(struct csr1212_csr *csr, - const u32 *bus_info_data, int max_rom) -{ - static const int mr_map[] = { 4, 64, 1024, 0 }; - - BUG_ON(max_rom & ~0x3); - csr->max_rom = mr_map[max_rom]; - memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len); -} - -static struct csr1212_keyval *csr1212_new_keyval(u8 type, u8 key) -{ - struct csr1212_keyval *kv; - - if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0)) - return NULL; - - kv = CSR1212_MALLOC(sizeof(*kv)); - if (!kv) - return NULL; - - atomic_set(&kv->refcnt, 1); - kv->key.type = type; - kv->key.id = key; - kv->associate = NULL; - kv->next = NULL; - kv->prev = NULL; - kv->offset = 0; - kv->valid = 0; - return kv; -} - -struct csr1212_keyval *csr1212_new_immediate(u8 key, u32 value) -{ - struct csr1212_keyval *kv; - - kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key); - if (!kv) - return NULL; - - kv->value.immediate = value; - kv->valid = 1; - return kv; -} - -static struct csr1212_keyval * -csr1212_new_leaf(u8 key, const void *data, size_t data_len) -{ - struct csr1212_keyval *kv; - - kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key); - if (!kv) - return NULL; - - if (data_len > 0) { - kv->value.leaf.data = CSR1212_MALLOC(data_len); - if (!kv->value.leaf.data) { - CSR1212_FREE(kv); - return NULL; - } - - if (data) - memcpy(kv->value.leaf.data, data, data_len); - } else { - kv->value.leaf.data = NULL; - } - - kv->value.leaf.len = bytes_to_quads(data_len); - kv->offset = 0; - kv->valid = 1; - - return kv; -} - -static struct csr1212_keyval * -csr1212_new_csr_offset(u8 key, u32 csr_offset) -{ - struct csr1212_keyval *kv; - - kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key); - if (!kv) - return NULL; - - kv->value.csr_offset = csr_offset; - - kv->offset = 0; - kv->valid = 1; - return kv; -} - -struct csr1212_keyval *csr1212_new_directory(u8 key) -{ - struct csr1212_keyval *kv; - - kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key); - if (!kv) - return NULL; - - kv->value.directory.len = 0; - kv->offset = 0; - kv->value.directory.dentries_head = NULL; - kv->value.directory.dentries_tail = NULL; - kv->valid = 1; - return kv; -} - -void csr1212_associate_keyval(struct csr1212_keyval *kv, - struct csr1212_keyval *associate) -{ - BUG_ON(!kv || !associate || kv->key.id == CSR1212_KV_ID_DESCRIPTOR || - (associate->key.id != CSR1212_KV_ID_DESCRIPTOR && - associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO && - associate->key.id != CSR1212_KV_ID_EXTENDED_KEY && - associate->key.id != CSR1212_KV_ID_EXTENDED_DATA && - associate->key.id < 0x30) || - (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID && - associate->key.id != CSR1212_KV_ID_EXTENDED_KEY) || - (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY && - associate->key.id != CSR1212_KV_ID_EXTENDED_DATA) || - (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY && - kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) || - (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA && - kv->key.id != CSR1212_KV_ID_EXTENDED_KEY)); - - if (kv->associate) - csr1212_release_keyval(kv->associate); - - csr1212_keep_keyval(associate); - kv->associate = associate; -} - -static int __csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, - struct csr1212_keyval *kv, - bool keep_keyval) -{ - struct csr1212_dentry *dentry; - - BUG_ON(!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY); - - dentry = CSR1212_MALLOC(sizeof(*dentry)); - if (!dentry) - return -ENOMEM; - - if (keep_keyval) - csr1212_keep_keyval(kv); - dentry->kv = kv; - - dentry->next = NULL; - dentry->prev = dir->value.directory.dentries_tail; - - if (!dir->value.directory.dentries_head) - dir->value.directory.dentries_head = dentry; - - if (dir->value.directory.dentries_tail) - dir->value.directory.dentries_tail->next = dentry; - dir->value.directory.dentries_tail = dentry; - - return CSR1212_SUCCESS; -} - -int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, - struct csr1212_keyval *kv) -{ - return __csr1212_attach_keyval_to_directory(dir, kv, true); -} - -#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \ - (&((kv)->value.leaf.data[1])) - -#define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \ - ((kv)->value.leaf.data[0] = \ - cpu_to_be32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \ - ((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT))) -#define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \ - ((kv)->value.leaf.data[0] = \ - cpu_to_be32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \ - CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \ - ((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK))) - -static struct csr1212_keyval * -csr1212_new_descriptor_leaf(u8 dtype, u32 specifier_id, - const void *data, size_t data_len) -{ - struct csr1212_keyval *kv; - - kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL, - data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD); - if (!kv) - return NULL; - - kmemcheck_annotate_variable(kv->value.leaf.data[0]); - CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype); - CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id); - - if (data) - memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len); - - return kv; -} - -/* Check if string conforms to minimal ASCII as per IEEE 1212 clause 7.4 */ -static int csr1212_check_minimal_ascii(const char *s) -{ - static const char minimal_ascii_table[] = { - /* 1 2 4 8 16 32 64 128 */ - 128, /* --, --, --, --, --, --, --, 07, */ - 4 + 16 + 32, /* --, --, 0a, --, 0C, 0D, --, --, */ - 0, /* --, --, --, --, --, --, --, --, */ - 0, /* --, --, --, --, --, --, --, --, */ - 255 - 8 - 16, /* 20, 21, 22, --, --, 25, 26, 27, */ - 255, /* 28, 29, 2a, 2b, 2c, 2d, 2e, 2f, */ - 255, /* 30, 31, 32, 33, 34, 35, 36, 37, */ - 255, /* 38, 39, 3a, 3b, 3c, 3d, 3e, 3f, */ - 255, /* 40, 41, 42, 43, 44, 45, 46, 47, */ - 255, /* 48, 49, 4a, 4b, 4c, 4d, 4e, 4f, */ - 255, /* 50, 51, 52, 53, 54, 55, 56, 57, */ - 1 + 2 + 4 + 128, /* 58, 59, 5a, --, --, --, --, 5f, */ - 255 - 1, /* --, 61, 62, 63, 64, 65, 66, 67, */ - 255, /* 68, 69, 6a, 6b, 6c, 6d, 6e, 6f, */ - 255, /* 70, 71, 72, 73, 74, 75, 76, 77, */ - 1 + 2 + 4, /* 78, 79, 7a, --, --, --, --, --, */ - }; - int i, j; - - for (; *s; s++) { - i = *s >> 3; /* i = *s / 8; */ - j = 1 << (*s & 3); /* j = 1 << (*s % 8); */ - - if (i >= ARRAY_SIZE(minimal_ascii_table) || - !(minimal_ascii_table[i] & j)) - return -EINVAL; - } - return 0; -} - -/* IEEE 1212 clause 7.5.4.1 textual descriptors (English, minimal ASCII) */ -struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s) -{ - struct csr1212_keyval *kv; - u32 *text; - size_t str_len, quads; - - if (!s || !*s || csr1212_check_minimal_ascii(s)) - return NULL; - - str_len = strlen(s); - quads = bytes_to_quads(str_len); - kv = csr1212_new_descriptor_leaf(0, 0, NULL, quads_to_bytes(quads) + - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD); - if (!kv) - return NULL; - - kv->value.leaf.data[1] = 0; /* width, character_set, language */ - text = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv); - text[quads - 1] = 0; /* padding */ - memcpy(text, s, str_len); - - return kv; -} - - -/* Destruction Routines */ - -void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir, - struct csr1212_keyval *kv) -{ - struct csr1212_dentry *dentry; - - if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY) - return; - - dentry = csr1212_find_keyval(dir, kv); - - if (!dentry) - return; - - if (dentry->prev) - dentry->prev->next = dentry->next; - if (dentry->next) - dentry->next->prev = dentry->prev; - if (dir->value.directory.dentries_head == dentry) - dir->value.directory.dentries_head = dentry->next; - if (dir->value.directory.dentries_tail == dentry) - dir->value.directory.dentries_tail = dentry->prev; - - CSR1212_FREE(dentry); - - csr1212_release_keyval(kv); -} - -/* This function is used to free the memory taken by a keyval. If the given - * keyval is a directory type, then any keyvals contained in that directory - * will be destroyed as well if noone holds a reference on them. By means of - * list manipulation, this routine will descend a directory structure in a - * non-recursive manner. */ -void csr1212_release_keyval(struct csr1212_keyval *kv) -{ - struct csr1212_keyval *k, *a; - struct csr1212_dentry dentry; - struct csr1212_dentry *head, *tail; - - if (!atomic_dec_and_test(&kv->refcnt)) - return; - - dentry.kv = kv; - dentry.next = NULL; - dentry.prev = NULL; - - head = &dentry; - tail = head; - - while (head) { - k = head->kv; - - while (k) { - /* must not dec_and_test kv->refcnt again */ - if (k != kv && !atomic_dec_and_test(&k->refcnt)) - break; - - a = k->associate; - - if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) { - /* If the current entry is a directory, move all - * the entries to the destruction list. */ - if (k->value.directory.dentries_head) { - tail->next = - k->value.directory.dentries_head; - k->value.directory.dentries_head->prev = - tail; - tail = k->value.directory.dentries_tail; - } - } - free_keyval(k); - k = a; - } - - head = head->next; - if (head) { - if (head->prev && head->prev != &dentry) - CSR1212_FREE(head->prev); - head->prev = NULL; - } else if (tail != &dentry) { - CSR1212_FREE(tail); - } - } -} - -void csr1212_destroy_csr(struct csr1212_csr *csr) -{ - struct csr1212_csr_rom_cache *c, *oc; - struct csr1212_cache_region *cr, *ocr; - - csr1212_release_keyval(csr->root_kv); - - c = csr->cache_head; - while (c) { - oc = c; - cr = c->filled_head; - while (cr) { - ocr = cr; - cr = cr->next; - CSR1212_FREE(ocr); - } - c = c->next; - CSR1212_FREE(oc); - } - - CSR1212_FREE(csr); -} - - -/* CSR Image Creation */ - -static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize) -{ - struct csr1212_csr_rom_cache *cache; - u64 csr_addr; - - BUG_ON(!csr || !csr->ops || !csr->ops->allocate_addr_range || - !csr->ops->release_addr || csr->max_rom < 1); - - /* ROM size must be a multiple of csr->max_rom */ - romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1); - - csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, - csr->private); - if (csr_addr == CSR1212_INVALID_ADDR_SPACE) - return -ENOMEM; - - if (csr_addr < CSR1212_REGISTER_SPACE_BASE) { - /* Invalid address returned from allocate_addr_range(). */ - csr->ops->release_addr(csr_addr, csr->private); - return -ENOMEM; - } - - cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, - romsize); - if (!cache) { - csr->ops->release_addr(csr_addr, csr->private); - return -ENOMEM; - } - - cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, - CSR1212_KV_ID_EXTENDED_ROM); - if (!cache->ext_rom) { - csr->ops->release_addr(csr_addr, csr->private); - CSR1212_FREE(cache); - return -ENOMEM; - } - - if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) != - CSR1212_SUCCESS) { - csr1212_release_keyval(cache->ext_rom); - csr->ops->release_addr(csr_addr, csr->private); - CSR1212_FREE(cache); - return -ENOMEM; - } - cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE; - cache->ext_rom->value.leaf.len = -1; - cache->ext_rom->value.leaf.data = cache->data; - - /* Add cache to tail of cache list */ - cache->prev = csr->cache_tail; - csr->cache_tail->next = cache; - csr->cache_tail = cache; - return CSR1212_SUCCESS; -} - -static void csr1212_remove_cache(struct csr1212_csr *csr, - struct csr1212_csr_rom_cache *cache) -{ - if (csr->cache_head == cache) - csr->cache_head = cache->next; - if (csr->cache_tail == cache) - csr->cache_tail = cache->prev; - - if (cache->prev) - cache->prev->next = cache->next; - if (cache->next) - cache->next->prev = cache->prev; - - if (cache->ext_rom) { - csr1212_detach_keyval_from_directory(csr->root_kv, - cache->ext_rom); - csr1212_release_keyval(cache->ext_rom); - } - - CSR1212_FREE(cache); -} - -static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir, - struct csr1212_keyval **layout_tail) -{ - struct csr1212_dentry *dentry; - struct csr1212_keyval *dkv; - struct csr1212_keyval *last_extkey_spec = NULL; - struct csr1212_keyval *last_extkey = NULL; - int num_entries = 0; - - for (dentry = dir->value.directory.dentries_head; dentry; - dentry = dentry->next) { - for (dkv = dentry->kv; dkv; dkv = dkv->associate) { - /* Special Case: Extended Key Specifier_ID */ - if (dkv->key.id == - CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) { - if (last_extkey_spec == NULL) - last_extkey_spec = dkv; - else if (dkv->value.immediate != - last_extkey_spec->value.immediate) - last_extkey_spec = dkv; - else - continue; - /* Special Case: Extended Key */ - } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) { - if (last_extkey == NULL) - last_extkey = dkv; - else if (dkv->value.immediate != - last_extkey->value.immediate) - last_extkey = dkv; - else - continue; - } - - num_entries += 1; - - switch (dkv->key.type) { - default: - case CSR1212_KV_TYPE_IMMEDIATE: - case CSR1212_KV_TYPE_CSR_OFFSET: - break; - case CSR1212_KV_TYPE_LEAF: - case CSR1212_KV_TYPE_DIRECTORY: - /* Remove from list */ - if (dkv->prev && (dkv->prev->next == dkv)) - dkv->prev->next = dkv->next; - if (dkv->next && (dkv->next->prev == dkv)) - dkv->next->prev = dkv->prev; - //if (dkv == *layout_tail) - // *layout_tail = dkv->prev; - - /* Special case: Extended ROM leafs */ - if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) { - dkv->value.leaf.len = -1; - /* Don't add Extended ROM leafs in the - * layout list, they are handled - * differently. */ - break; - } - - /* Add to tail of list */ - dkv->next = NULL; - dkv->prev = *layout_tail; - (*layout_tail)->next = dkv; - *layout_tail = dkv; - break; - } - } - } - return num_entries; -} - -static size_t csr1212_generate_layout_order(struct csr1212_keyval *kv) -{ - struct csr1212_keyval *ltail = kv; - size_t agg_size = 0; - - while (kv) { - switch (kv->key.type) { - case CSR1212_KV_TYPE_LEAF: - /* Add 1 quadlet for crc/len field */ - agg_size += kv->value.leaf.len + 1; - break; - - case CSR1212_KV_TYPE_DIRECTORY: - kv->value.directory.len = - csr1212_generate_layout_subdir(kv, <ail); - /* Add 1 quadlet for crc/len field */ - agg_size += kv->value.directory.len + 1; - break; - } - kv = kv->next; - } - return quads_to_bytes(agg_size); -} - -static struct csr1212_keyval * -csr1212_generate_positions(struct csr1212_csr_rom_cache *cache, - struct csr1212_keyval *start_kv, int start_pos) -{ - struct csr1212_keyval *kv = start_kv; - struct csr1212_keyval *okv = start_kv; - int pos = start_pos; - int kv_len = 0, okv_len = 0; - - cache->layout_head = kv; - - while (kv && pos < cache->size) { - /* Special case: Extended ROM leafs */ - if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) - kv->offset = cache->offset + pos; - - switch (kv->key.type) { - case CSR1212_KV_TYPE_LEAF: - kv_len = kv->value.leaf.len; - break; - - case CSR1212_KV_TYPE_DIRECTORY: - kv_len = kv->value.directory.len; - break; - - default: - /* Should never get here */ - WARN_ON(1); - break; - } - - pos += quads_to_bytes(kv_len + 1); - - if (pos <= cache->size) { - okv = kv; - okv_len = kv_len; - kv = kv->next; - } - } - - cache->layout_tail = okv; - cache->len = okv->offset - cache->offset + quads_to_bytes(okv_len + 1); - - return kv; -} - -#define CSR1212_KV_KEY_SHIFT 24 -#define CSR1212_KV_KEY_TYPE_SHIFT 6 -#define CSR1212_KV_KEY_ID_MASK 0x3f -#define CSR1212_KV_KEY_TYPE_MASK 0x3 /* after shift */ - -static void -csr1212_generate_tree_subdir(struct csr1212_keyval *dir, u32 *data_buffer) -{ - struct csr1212_dentry *dentry; - struct csr1212_keyval *last_extkey_spec = NULL; - struct csr1212_keyval *last_extkey = NULL; - int index = 0; - - for (dentry = dir->value.directory.dentries_head; - dentry; - dentry = dentry->next) { - struct csr1212_keyval *a; - - for (a = dentry->kv; a; a = a->associate) { - u32 value = 0; - - /* Special Case: Extended Key Specifier_ID */ - if (a->key.id == - CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) { - if (last_extkey_spec == NULL) - last_extkey_spec = a; - else if (a->value.immediate != - last_extkey_spec->value.immediate) - last_extkey_spec = a; - else - continue; - - /* Special Case: Extended Key */ - } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) { - if (last_extkey == NULL) - last_extkey = a; - else if (a->value.immediate != - last_extkey->value.immediate) - last_extkey = a; - else - continue; - } - - switch (a->key.type) { - case CSR1212_KV_TYPE_IMMEDIATE: - value = a->value.immediate; - break; - case CSR1212_KV_TYPE_CSR_OFFSET: - value = a->value.csr_offset; - break; - case CSR1212_KV_TYPE_LEAF: - value = a->offset; - value -= dir->offset + quads_to_bytes(1+index); - value = bytes_to_quads(value); - break; - case CSR1212_KV_TYPE_DIRECTORY: - value = a->offset; - value -= dir->offset + quads_to_bytes(1+index); - value = bytes_to_quads(value); - break; - default: - /* Should never get here */ - WARN_ON(1); - break; - } - - value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) << - CSR1212_KV_KEY_SHIFT; - value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) << - (CSR1212_KV_KEY_SHIFT + - CSR1212_KV_KEY_TYPE_SHIFT); - data_buffer[index] = cpu_to_be32(value); - index++; - } - } -} - -struct csr1212_keyval_img { - u16 length; - u16 crc; - - /* Must be last */ - u32 data[0]; /* older gcc can't handle [] which is standard */ -}; - -static void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache) -{ - struct csr1212_keyval *kv, *nkv; - struct csr1212_keyval_img *kvi; - - for (kv = cache->layout_head; - kv != cache->layout_tail->next; - kv = nkv) { - kvi = (struct csr1212_keyval_img *)(cache->data + - bytes_to_quads(kv->offset - cache->offset)); - switch (kv->key.type) { - default: - case CSR1212_KV_TYPE_IMMEDIATE: - case CSR1212_KV_TYPE_CSR_OFFSET: - /* Should never get here */ - WARN_ON(1); - break; - - case CSR1212_KV_TYPE_LEAF: - /* Don't copy over Extended ROM areas, they are - * already filled out! */ - if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) - memcpy(kvi->data, kv->value.leaf.data, - quads_to_bytes(kv->value.leaf.len)); - - kvi->length = cpu_to_be16(kv->value.leaf.len); - kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len); - break; - - case CSR1212_KV_TYPE_DIRECTORY: - csr1212_generate_tree_subdir(kv, kvi->data); - - kvi->length = cpu_to_be16(kv->value.directory.len); - kvi->crc = csr1212_crc16(kvi->data, - kv->value.directory.len); - break; - } - - nkv = kv->next; - if (kv->prev) - kv->prev->next = NULL; - if (kv->next) - kv->next->prev = NULL; - kv->prev = NULL; - kv->next = NULL; - } -} - -/* This size is arbitrarily chosen. - * The struct overhead is subtracted for more economic allocations. */ -#define CSR1212_EXTENDED_ROM_SIZE (2048 - sizeof(struct csr1212_csr_rom_cache)) - -int csr1212_generate_csr_image(struct csr1212_csr *csr) -{ - struct csr1212_bus_info_block_img *bi; - struct csr1212_csr_rom_cache *cache; - struct csr1212_keyval *kv; - size_t agg_size; - int ret; - int init_offset; - - BUG_ON(!csr); - - cache = csr->cache_head; - - bi = (struct csr1212_bus_info_block_img*)cache->data; - - bi->length = bytes_to_quads(csr->bus_info_len) - 1; - bi->crc_length = bi->length; - bi->crc = csr1212_crc16(bi->data, bi->crc_length); - - csr->root_kv->next = NULL; - csr->root_kv->prev = NULL; - - agg_size = csr1212_generate_layout_order(csr->root_kv); - - init_offset = csr->bus_info_len; - - for (kv = csr->root_kv, cache = csr->cache_head; - kv; - cache = cache->next) { - if (!cache) { - /* Estimate approximate number of additional cache - * regions needed (it assumes that the cache holding - * the first 1K Config ROM space always exists). */ - int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE - - (2 * sizeof(u32))) + 1; - - /* Add additional cache regions, extras will be - * removed later */ - for (; est_c; est_c--) { - ret = csr1212_append_new_cache(csr, - CSR1212_EXTENDED_ROM_SIZE); - if (ret != CSR1212_SUCCESS) - return ret; - } - /* Need to re-layout for additional cache regions */ - agg_size = csr1212_generate_layout_order(csr->root_kv); - kv = csr->root_kv; - cache = csr->cache_head; - init_offset = csr->bus_info_len; - } - kv = csr1212_generate_positions(cache, kv, init_offset); - agg_size -= cache->len; - init_offset = sizeof(u32); - } - - /* Remove unused, excess cache regions */ - while (cache) { - struct csr1212_csr_rom_cache *oc = cache; - - cache = cache->next; - csr1212_remove_cache(csr, oc); - } - - /* Go through the list backward so that when done, the correct CRC - * will be calculated for the Extended ROM areas. */ - for (cache = csr->cache_tail; cache; cache = cache->prev) { - /* Only Extended ROM caches should have this set. */ - if (cache->ext_rom) { - int leaf_size; - - /* Make sure the Extended ROM leaf is a multiple of - * max_rom in size. */ - BUG_ON(csr->max_rom < 1); - leaf_size = (cache->len + (csr->max_rom - 1)) & - ~(csr->max_rom - 1); - - /* Zero out the unused ROM region */ - memset(cache->data + bytes_to_quads(cache->len), 0x00, - leaf_size - cache->len); - - /* Subtract leaf header */ - leaf_size -= sizeof(u32); - - /* Update the Extended ROM leaf length */ - cache->ext_rom->value.leaf.len = - bytes_to_quads(leaf_size); - } else { - /* Zero out the unused ROM region */ - memset(cache->data + bytes_to_quads(cache->len), 0x00, - cache->size - cache->len); - } - - /* Copy the data into the cache buffer */ - csr1212_fill_cache(cache); - - if (cache != csr->cache_head) { - /* Set the length and CRC of the extended ROM. */ - struct csr1212_keyval_img *kvi = - (struct csr1212_keyval_img*)cache->data; - u16 len = bytes_to_quads(cache->len) - 1; - - kvi->length = cpu_to_be16(len); - kvi->crc = csr1212_crc16(kvi->data, len); - } - } - - return CSR1212_SUCCESS; -} - -int csr1212_read(struct csr1212_csr *csr, u32 offset, void *buffer, u32 len) -{ - struct csr1212_csr_rom_cache *cache; - - for (cache = csr->cache_head; cache; cache = cache->next) - if (offset >= cache->offset && - (offset + len) <= (cache->offset + cache->size)) { - memcpy(buffer, &cache->data[ - bytes_to_quads(offset - cache->offset)], - len); - return CSR1212_SUCCESS; - } - - return -ENOENT; -} - -/* - * Apparently there are many different wrong implementations of the CRC - * algorithm. We don't fail, we just warn... approximately once per GUID. - */ -static void -csr1212_check_crc(const u32 *buffer, size_t length, u16 crc, __be32 *guid) -{ - static u64 last_bad_eui64; - u64 eui64 = ((u64)be32_to_cpu(guid[0]) << 32) | be32_to_cpu(guid[1]); - - if (csr1212_crc16(buffer, length) == crc || - csr1212_msft_crc16(buffer, length) == crc || - eui64 == last_bad_eui64) - return; - - printk(KERN_DEBUG "ieee1394: config ROM CRC error\n"); - last_bad_eui64 = eui64; -} - -/* Parse a chunk of data as a Config ROM */ - -static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) -{ - struct csr1212_bus_info_block_img *bi; - struct csr1212_cache_region *cr; - int i; - int ret; - - for (i = 0; i < csr->bus_info_len; i += sizeof(u32)) { - ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, - &csr->cache_head->data[bytes_to_quads(i)], - csr->private); - if (ret != CSR1212_SUCCESS) - return ret; - - /* check ROM header's info_length */ - if (i == 0 && - be32_to_cpu(csr->cache_head->data[0]) >> 24 != - bytes_to_quads(csr->bus_info_len) - 1) - return -EINVAL; - } - - bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data; - csr->crc_len = quads_to_bytes(bi->crc_length); - - /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that - * is not always the case, so read the rest of the crc area 1 quadlet at - * a time. */ - for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(u32)) { - ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i, - &csr->cache_head->data[bytes_to_quads(i)], - csr->private); - if (ret != CSR1212_SUCCESS) - return ret; - } - - csr1212_check_crc(bi->data, bi->crc_length, bi->crc, - &csr->bus_info_data[3]); - - cr = CSR1212_MALLOC(sizeof(*cr)); - if (!cr) - return -ENOMEM; - - cr->next = NULL; - cr->prev = NULL; - cr->offset_start = 0; - cr->offset_end = csr->crc_len + 4; - - csr->cache_head->filled_head = cr; - csr->cache_head->filled_tail = cr; - - return CSR1212_SUCCESS; -} - -#define CSR1212_KV_KEY(q) (be32_to_cpu(q) >> CSR1212_KV_KEY_SHIFT) -#define CSR1212_KV_KEY_TYPE(q) (CSR1212_KV_KEY(q) >> CSR1212_KV_KEY_TYPE_SHIFT) -#define CSR1212_KV_KEY_ID(q) (CSR1212_KV_KEY(q) & CSR1212_KV_KEY_ID_MASK) -#define CSR1212_KV_VAL_MASK 0xffffff -#define CSR1212_KV_VAL(q) (be32_to_cpu(q) & CSR1212_KV_VAL_MASK) - -static int -csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos) -{ - int ret = CSR1212_SUCCESS; - struct csr1212_keyval *k = NULL; - u32 offset; - bool keep_keyval = true; - - switch (CSR1212_KV_KEY_TYPE(ki)) { - case CSR1212_KV_TYPE_IMMEDIATE: - k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki), - CSR1212_KV_VAL(ki)); - if (!k) { - ret = -ENOMEM; - goto out; - } - /* Don't keep local reference when parsing. */ - keep_keyval = false; - break; - - case CSR1212_KV_TYPE_CSR_OFFSET: - k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki), - CSR1212_KV_VAL(ki)); - if (!k) { - ret = -ENOMEM; - goto out; - } - /* Don't keep local reference when parsing. */ - keep_keyval = false; - break; - - default: - /* Compute the offset from 0xffff f000 0000. */ - offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos; - if (offset == kv_pos) { - /* Uh-oh. Can't have a relative offset of 0 for Leaves - * or Directories. The Config ROM image is most likely - * messed up, so we'll just abort here. */ - ret = -EIO; - goto out; - } - - k = csr1212_find_keyval_offset(dir, offset); - - if (k) - break; /* Found it. */ - - if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) - k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki)); - else - k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0); - - if (!k) { - ret = -ENOMEM; - goto out; - } - /* Don't keep local reference when parsing. */ - keep_keyval = false; - /* Contents not read yet so it's not valid. */ - k->valid = 0; - k->offset = offset; - - k->prev = dir; - k->next = dir->next; - dir->next->prev = k; - dir->next = k; - } - ret = __csr1212_attach_keyval_to_directory(dir, k, keep_keyval); -out: - if (ret != CSR1212_SUCCESS && k != NULL) - free_keyval(k); - return ret; -} - -int csr1212_parse_keyval(struct csr1212_keyval *kv, - struct csr1212_csr_rom_cache *cache) -{ - struct csr1212_keyval_img *kvi; - int i; - int ret = CSR1212_SUCCESS; - int kvi_len; - - kvi = (struct csr1212_keyval_img*) - &cache->data[bytes_to_quads(kv->offset - cache->offset)]; - kvi_len = be16_to_cpu(kvi->length); - - /* GUID is wrong in here in case of extended ROM. We don't care. */ - csr1212_check_crc(kvi->data, kvi_len, kvi->crc, &cache->data[3]); - - switch (kv->key.type) { - case CSR1212_KV_TYPE_DIRECTORY: - for (i = 0; i < kvi_len; i++) { - u32 ki = kvi->data[i]; - - /* Some devices put null entries in their unit - * directories. If we come across such an entry, - * then skip it. */ - if (ki == 0x0) - continue; - ret = csr1212_parse_dir_entry(kv, ki, - kv->offset + quads_to_bytes(i + 1)); - } - kv->value.directory.len = kvi_len; - break; - - case CSR1212_KV_TYPE_LEAF: - if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) { - size_t size = quads_to_bytes(kvi_len); - - kv->value.leaf.data = CSR1212_MALLOC(size); - if (!kv->value.leaf.data) { - ret = -ENOMEM; - goto out; - } - - kv->value.leaf.len = kvi_len; - memcpy(kv->value.leaf.data, kvi->data, size); - } - break; - } - - kv->valid = 1; -out: - return ret; -} - -static int -csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) -{ - struct csr1212_cache_region *cr, *ncr, *newcr = NULL; - struct csr1212_keyval_img *kvi = NULL; - struct csr1212_csr_rom_cache *cache; - int cache_index; - u64 addr; - u32 *cache_ptr; - u16 kv_len = 0; - - BUG_ON(!csr || !kv || csr->max_rom < 1); - - /* First find which cache the data should be in (or go in if not read - * yet). */ - for (cache = csr->cache_head; cache; cache = cache->next) - if (kv->offset >= cache->offset && - kv->offset < (cache->offset + cache->size)) - break; - - if (!cache) { - u32 q, cache_size; - - /* Only create a new cache for Extended ROM leaves. */ - if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) - return -EINVAL; - - if (csr->ops->bus_read(csr, - CSR1212_REGISTER_SPACE_BASE + kv->offset, - &q, csr->private)) - return -EIO; - - kv->value.leaf.len = be32_to_cpu(q) >> 16; - - cache_size = (quads_to_bytes(kv->value.leaf.len + 1) + - (csr->max_rom - 1)) & ~(csr->max_rom - 1); - - cache = csr1212_rom_cache_malloc(kv->offset, cache_size); - if (!cache) - return -ENOMEM; - - kv->value.leaf.data = &cache->data[1]; - csr->cache_tail->next = cache; - cache->prev = csr->cache_tail; - cache->next = NULL; - csr->cache_tail = cache; - cache->filled_head = - CSR1212_MALLOC(sizeof(*cache->filled_head)); - if (!cache->filled_head) - return -ENOMEM; - - cache->filled_head->offset_start = 0; - cache->filled_head->offset_end = sizeof(u32); - cache->filled_tail = cache->filled_head; - cache->filled_head->next = NULL; - cache->filled_head->prev = NULL; - cache->data[0] = q; - - /* Don't read the entire extended ROM now. Pieces of it will - * be read when entries inside it are read. */ - return csr1212_parse_keyval(kv, cache); - } - - cache_index = kv->offset - cache->offset; - - /* Now seach read portions of the cache to see if it is there. */ - for (cr = cache->filled_head; cr; cr = cr->next) { - if (cache_index < cr->offset_start) { - newcr = CSR1212_MALLOC(sizeof(*newcr)); - if (!newcr) - return -ENOMEM; - - newcr->offset_start = cache_index & ~(csr->max_rom - 1); - newcr->offset_end = newcr->offset_start; - newcr->next = cr; - newcr->prev = cr->prev; - cr->prev = newcr; - cr = newcr; - break; - } else if ((cache_index >= cr->offset_start) && - (cache_index < cr->offset_end)) { - kvi = (struct csr1212_keyval_img*) - (&cache->data[bytes_to_quads(cache_index)]); - kv_len = quads_to_bytes(be16_to_cpu(kvi->length) + 1); - break; - } else if (cache_index == cr->offset_end) { - break; - } - } - - if (!cr) { - cr = cache->filled_tail; - newcr = CSR1212_MALLOC(sizeof(*newcr)); - if (!newcr) - return -ENOMEM; - - newcr->offset_start = cache_index & ~(csr->max_rom - 1); - newcr->offset_end = newcr->offset_start; - newcr->prev = cr; - newcr->next = cr->next; - cr->next = newcr; - cr = newcr; - cache->filled_tail = newcr; - } - - while(!kvi || cr->offset_end < cache_index + kv_len) { - cache_ptr = &cache->data[bytes_to_quads(cr->offset_end & - ~(csr->max_rom - 1))]; - - addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset + - cr->offset_end) & ~(csr->max_rom - 1); - - if (csr->ops->bus_read(csr, addr, cache_ptr, csr->private)) - return -EIO; - - cr->offset_end += csr->max_rom - (cr->offset_end & - (csr->max_rom - 1)); - - if (!kvi && (cr->offset_end > cache_index)) { - kvi = (struct csr1212_keyval_img*) - (&cache->data[bytes_to_quads(cache_index)]); - kv_len = quads_to_bytes(be16_to_cpu(kvi->length) + 1); - } - - if ((kv_len + (kv->offset - cache->offset)) > cache->size) { - /* The Leaf or Directory claims its length extends - * beyond the ConfigROM image region and thus beyond the - * end of our cache region. Therefore, we abort now - * rather than seg faulting later. */ - return -EIO; - } - - ncr = cr->next; - - if (ncr && (cr->offset_end >= ncr->offset_start)) { - /* consolidate region entries */ - ncr->offset_start = cr->offset_start; - - if (cr->prev) - cr->prev->next = cr->next; - ncr->prev = cr->prev; - if (cache->filled_head == cr) - cache->filled_head = ncr; - CSR1212_FREE(cr); - cr = ncr; - } - } - - return csr1212_parse_keyval(kv, cache); -} - -struct csr1212_keyval * -csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) -{ - if (!kv) - return NULL; - if (!kv->valid) - if (csr1212_read_keyval(csr, kv) != CSR1212_SUCCESS) - return NULL; - return kv; -} - -int csr1212_parse_csr(struct csr1212_csr *csr) -{ - struct csr1212_dentry *dentry; - int ret; - - BUG_ON(!csr || !csr->ops || !csr->ops->bus_read); - - ret = csr1212_parse_bus_info_block(csr); - if (ret != CSR1212_SUCCESS) - return ret; - - /* - * There has been a buggy firmware with bus_info_block.max_rom > 0 - * spotted which actually only supported quadlet read requests to the - * config ROM. Therefore read everything quadlet by quadlet regardless - * of what the bus info block says. - */ - csr->max_rom = 4; - - csr->cache_head->layout_head = csr->root_kv; - csr->cache_head->layout_tail = csr->root_kv; - - csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) + - csr->bus_info_len; - - csr->root_kv->valid = 0; - csr->root_kv->next = csr->root_kv; - csr->root_kv->prev = csr->root_kv; - ret = csr1212_read_keyval(csr, csr->root_kv); - if (ret != CSR1212_SUCCESS) - return ret; - - /* Scan through the Root directory finding all extended ROM regions - * and make cache regions for them */ - for (dentry = csr->root_kv->value.directory.dentries_head; - dentry; dentry = dentry->next) { - if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM && - !dentry->kv->valid) { - ret = csr1212_read_keyval(csr, dentry->kv); - if (ret != CSR1212_SUCCESS) - return ret; - } - } - - return CSR1212_SUCCESS; -} diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h deleted file mode 100644 index a892d92..0000000 --- a/drivers/ieee1394/csr1212.h +++ /dev/null @@ -1,383 +0,0 @@ -/* - * 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__ */ diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c deleted file mode 100644 index d178699..0000000 --- a/drivers/ieee1394/dma.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * 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 */ diff --git a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h deleted file mode 100644 index 467373c..0000000 --- a/drivers/ieee1394/dma.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 */ diff --git a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h deleted file mode 100644 index 18b92cb..0000000 --- a/drivers/ieee1394/dv1394-private.h +++ /dev/null @@ -1,587 +0,0 @@ -/* - * 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 */ - diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c deleted file mode 100644 index c5a031b..0000000 --- a/drivers/ieee1394/dv1394.c +++ /dev/null @@ -1,2584 +0,0 @@ -/* - * dv1394.c - 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.c - video driver for OHCI 1394 boards - * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au> - * - * 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. - */ - -/* - OVERVIEW - - I designed dv1394 as a "pipe" that you can use to shoot DV onto a - FireWire bus. In transmission mode, dv1394 does the following: - - 1. accepts contiguous frames of DV data from user-space, via write() - or mmap() (see dv1394.h for the complete API) - 2. wraps IEC 61883 packets around the DV data, inserting - empty synchronization packets as necessary - 3. assigns accurate SYT timestamps to the outgoing packets - 4. shoots them out using the OHCI card's IT DMA engine - - Thanks to Dan Dennedy, we now have a receive mode that does the following: - - 1. accepts raw IEC 61883 packets from the OHCI card - 2. re-assembles the DV data payloads into contiguous frames, - discarding empty packets - 3. sends the DV data to user-space via read() or mmap() -*/ - -/* - TODO: - - - tunable frame-drop behavior: either loop last frame, or halt transmission - - - use a scatter/gather buffer for DMA programs (f->descriptor_pool) - so that we don't rely on allocating 64KB of contiguous kernel memory - via pci_alloc_consistent() - - DONE: - - during reception, better handling of dropped frames and continuity errors - - during reception, prevent DMA from bypassing the irq tasklets - - reduce irq rate during reception (1/250 packets). - - add many more internal buffers during reception with scatter/gather dma. - - add dbc (continuity) checking on receive, increment status.dropped_frames - if not continuous. - - restart IT DMA after a bus reset - - safely obtain and release ISO Tx channels in cooperation with OHCI driver - - map received DIF blocks to their proper location in DV frame (ensure - recovery if dropped packet) - - handle bus resets gracefully (OHCI card seems to take care of this itself(!)) - - do not allow resizing the user_buf once allocated; eliminate nuke_buffer_mappings - - eliminated #ifdef DV1394_DEBUG_LEVEL by inventing macros debug_printk and irq_printk - - added wmb() and mb() to places where PCI read/write ordering needs to be enforced - - set video->id correctly - - store video_cards in an array indexed by OHCI card ID, rather than a list - - implement DMA context allocation to cooperate with other users of the OHCI - - fix all XXX showstoppers - - disable IR/IT DMA interrupts on shutdown - - flush pci writes to the card by issuing a read - - character device dispatching - - switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!) - - keep all video_cards in a list (for open() via chardev), set file->private_data = video - - dv1394_poll should indicate POLLIN when receiving buffers are available - - add proc fs interface to set cip_n, cip_d, syt_offset, and video signal - - expose xmit and recv as separate devices (not exclusive) - - expose NTSC and PAL as separate devices (can be overridden) - -*/ - -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/fs.h> -#include <linux/poll.h> -#include <linux/mutex.h> -#include <linux/bitops.h> -#include <asm/byteorder.h> -#include <asm/atomic.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <linux/delay.h> -#include <asm/pgtable.h> -#include <asm/page.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/vmalloc.h> -#include <linux/string.h> -#include <linux/compat.h> -#include <linux/cdev.h> - -#include "dv1394.h" -#include "dv1394-private.h" -#include "highlevel.h" -#include "hosts.h" -#include "ieee1394.h" -#include "ieee1394_core.h" -#include "ieee1394_hotplug.h" -#include "ieee1394_types.h" -#include "nodemgr.h" -#include "ohci1394.h" - -/* DEBUG LEVELS: - 0 - no debugging messages - 1 - some debugging messages, but none during DMA frame transmission - 2 - lots of messages, including during DMA frame transmission - (will cause underflows if your machine is too slow!) -*/ - -#define DV1394_DEBUG_LEVEL 0 - -/* for debugging use ONLY: allow more than one open() of the device */ -/* #define DV1394_ALLOW_MORE_THAN_ONE_OPEN 1 */ - -#if DV1394_DEBUG_LEVEL >= 2 -#define irq_printk( args... ) printk( args ) -#else -#define irq_printk( args... ) do {} while (0) -#endif - -#if DV1394_DEBUG_LEVEL >= 1 -#define debug_printk( args... ) printk( args) -#else -#define debug_printk( args... ) do {} while (0) -#endif - -/* issue a dummy PCI read to force the preceding write - to be posted to the PCI bus immediately */ - -static inline void flush_pci_write(struct ti_ohci *ohci) -{ - mb(); - reg_read(ohci, OHCI1394_IsochronousCycleTimer); -} - -static void it_tasklet_func(unsigned long data); -static void ir_tasklet_func(unsigned long data); - -#ifdef CONFIG_COMPAT -static long dv1394_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg); -#endif - -/* GLOBAL DATA */ - -/* list of all video_cards */ -static LIST_HEAD(dv1394_cards); -static DEFINE_SPINLOCK(dv1394_cards_lock); - -/* translate from a struct file* to the corresponding struct video_card* */ - -static inline struct video_card* file_to_video_card(struct file *file) -{ - return file->private_data; -} - -/*** FRAME METHODS *********************************************************/ - -static void frame_reset(struct frame *f) -{ - f->state = FRAME_CLEAR; - f->done = 0; - f->n_packets = 0; - f->frame_begin_timestamp = NULL; - f->assigned_timestamp = 0; - f->cip_syt1 = NULL; - f->cip_syt2 = NULL; - f->mid_frame_timestamp = NULL; - f->frame_end_timestamp = NULL; - f->frame_end_branch = NULL; -} - -static struct frame* frame_new(unsigned int frame_num, struct video_card *video) -{ - struct frame *f = kmalloc(sizeof(*f), GFP_KERNEL); - if (!f) - return NULL; - - f->video = video; - f->frame_num = frame_num; - - f->header_pool = pci_alloc_consistent(f->video->ohci->dev, PAGE_SIZE, &f->header_pool_dma); - if (!f->header_pool) { - printk(KERN_ERR "dv1394: failed to allocate CIP header pool\n"); - kfree(f); - return NULL; - } - - debug_printk("dv1394: frame_new: allocated CIP header pool at virt 0x%08lx (contig) dma 0x%08lx size %ld\n", - (unsigned long) f->header_pool, (unsigned long) f->header_pool_dma, PAGE_SIZE); - - f->descriptor_pool_size = MAX_PACKETS * sizeof(struct DMA_descriptor_block); - /* make it an even # of pages */ - f->descriptor_pool_size += PAGE_SIZE - (f->descriptor_pool_size%PAGE_SIZE); - - f->descriptor_pool = pci_alloc_consistent(f->video->ohci->dev, - f->descriptor_pool_size, - &f->descriptor_pool_dma); - if (!f->descriptor_pool) { - pci_free_consistent(f->video->ohci->dev, PAGE_SIZE, f->header_pool, f->header_pool_dma); - kfree(f); - return NULL; - } - - debug_printk("dv1394: frame_new: allocated DMA program memory at virt 0x%08lx (contig) dma 0x%08lx size %ld\n", - (unsigned long) f->descriptor_pool, (unsigned long) f->descriptor_pool_dma, f->descriptor_pool_size); - - f->data = 0; - frame_reset(f); - - return f; -} - -static void frame_delete(struct frame *f) -{ - pci_free_consistent(f->video->ohci->dev, PAGE_SIZE, f->header_pool, f->header_pool_dma); - pci_free_consistent(f->video->ohci->dev, f->descriptor_pool_size, f->descriptor_pool, f->descriptor_pool_dma); - kfree(f); -} - - - - -/* - frame_prepare() - build the DMA program for transmitting - - Frame_prepare() must be called OUTSIDE the video->spinlock. - However, frame_prepare() must still be serialized, so - it should be called WITH the video->mtx taken. - */ - -static void frame_prepare(struct video_card *video, unsigned int this_frame) -{ - struct frame *f = video->frames[this_frame]; - int last_frame; - - struct DMA_descriptor_block *block; - dma_addr_t block_dma; - struct CIP_header *cip; - dma_addr_t cip_dma; - - unsigned int n_descriptors, full_packets, packets_per_frame, payload_size; - - /* these flags denote packets that need special attention */ - int empty_packet, first_packet, last_packet, mid_packet; - - __le32 *branch_address, *last_branch_address = NULL; - unsigned long data_p; - int first_packet_empty = 0; - u32 cycleTimer, ct_sec, ct_cyc, ct_off; - unsigned long irq_flags; - - irq_printk("frame_prepare( %d ) ---------------------\n", this_frame); - - full_packets = 0; - - - - if (video->pal_or_ntsc == DV1394_PAL) - packets_per_frame = DV1394_PAL_PACKETS_PER_FRAME; - else - packets_per_frame = DV1394_NTSC_PACKETS_PER_FRAME; - - while ( full_packets < packets_per_frame ) { - empty_packet = first_packet = last_packet = mid_packet = 0; - - data_p = f->data + full_packets * 480; - - /************************************************/ - /* allocate a descriptor block and a CIP header */ - /************************************************/ - - /* note: these should NOT cross a page boundary (DMA restriction) */ - - if (f->n_packets >= MAX_PACKETS) { - printk(KERN_ERR "dv1394: FATAL ERROR: max packet count exceeded\n"); - return; - } - - /* the block surely won't cross a page boundary, - since an even number of descriptor_blocks fit on a page */ - block = &(f->descriptor_pool[f->n_packets]); - - /* DMA address of the block = offset of block relative - to the kernel base address of the descriptor pool - + DMA base address of the descriptor pool */ - block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; - - - /* the whole CIP pool fits on one page, so no worries about boundaries */ - if ( ((unsigned long) &(f->header_pool[f->n_packets]) - (unsigned long) f->header_pool) - > PAGE_SIZE) { - printk(KERN_ERR "dv1394: FATAL ERROR: no room to allocate CIP header\n"); - return; - } - - cip = &(f->header_pool[f->n_packets]); - - /* DMA address of the CIP header = offset of cip - relative to kernel base address of the header pool - + DMA base address of the header pool */ - cip_dma = (unsigned long) cip % PAGE_SIZE + f->header_pool_dma; - - /* is this an empty packet? */ - - if (video->cip_accum > (video->cip_d - video->cip_n)) { - empty_packet = 1; - payload_size = 8; - video->cip_accum -= (video->cip_d - video->cip_n); - } else { - payload_size = 488; - video->cip_accum += video->cip_n; - } - - /* there are three important packets each frame: - - the first packet in the frame - we ask the card to record the timestamp when - this packet is actually sent, so we can monitor - how accurate our timestamps are. Also, the first - packet serves as a semaphore to let us know that - it's OK to free the *previous* frame's DMA buffer - - the last packet in the frame - this packet is used to detect buffer underflows. - if this is the last ready frame, the last DMA block - will have a branch back to the beginning of the frame - (so that the card will re-send the frame on underflow). - if this branch gets taken, we know that at least one - frame has been dropped. When the next frame is ready, - the branch is pointed to its first packet, and the - semaphore is disabled. - - a "mid" packet slightly before the end of the frame - this packet should trigger - an interrupt so we can go and assign a timestamp to the first packet - in the next frame. We don't use the very last packet in the frame - for this purpose, because that would leave very little time to set - the timestamp before DMA starts on the next frame. - */ - - if (f->n_packets == 0) { - first_packet = 1; - } else if ( full_packets == (packets_per_frame-1) ) { - last_packet = 1; - } else if (f->n_packets == packets_per_frame) { - mid_packet = 1; - } - - - /********************/ - /* setup CIP header */ - /********************/ - - /* the timestamp will be written later from the - mid-frame interrupt handler. For now we just - store the address of the CIP header(s) that - need a timestamp. */ - - /* first packet in the frame needs a timestamp */ - if (first_packet) { - f->cip_syt1 = cip; - if (empty_packet) - first_packet_empty = 1; - - } else if (first_packet_empty && (f->n_packets == 1) ) { - /* if the first packet was empty, the second - packet's CIP header also needs a timestamp */ - f->cip_syt2 = cip; - } - - fill_cip_header(cip, - /* the node ID number of the OHCI card */ - reg_read(video->ohci, OHCI1394_NodeID) & 0x3F, - video->continuity_counter, - video->pal_or_ntsc, - 0xFFFF /* the timestamp is filled in later */); - - /* advance counter, only for full packets */ - if ( ! empty_packet ) - video->continuity_counter++; - - /******************************/ - /* setup DMA descriptor block */ - /******************************/ - - /* first descriptor - OUTPUT_MORE_IMMEDIATE, for the controller's IT header */ - fill_output_more_immediate( &(block->u.out.omi), 1, video->channel, 0, payload_size); - - if (empty_packet) { - /* second descriptor - OUTPUT_LAST for CIP header */ - fill_output_last( &(block->u.out.u.empty.ol), - - /* want completion status on all interesting packets */ - (first_packet || mid_packet || last_packet) ? 1 : 0, - - /* want interrupts on all interesting packets */ - (first_packet || mid_packet || last_packet) ? 1 : 0, - - sizeof(struct CIP_header), /* data size */ - cip_dma); - - if (first_packet) - f->frame_begin_timestamp = &(block->u.out.u.empty.ol.q[3]); - else if (mid_packet) - f->mid_frame_timestamp = &(block->u.out.u.empty.ol.q[3]); - else if (last_packet) { - f->frame_end_timestamp = &(block->u.out.u.empty.ol.q[3]); - f->frame_end_branch = &(block->u.out.u.empty.ol.q[2]); - } - - branch_address = &(block->u.out.u.empty.ol.q[2]); - n_descriptors = 3; - if (first_packet) - f->first_n_descriptors = n_descriptors; - - } else { /* full packet */ - - /* second descriptor - OUTPUT_MORE for CIP header */ - fill_output_more( &(block->u.out.u.full.om), - sizeof(struct CIP_header), /* data size */ - cip_dma); - - - /* third (and possibly fourth) descriptor - for DV data */ - /* the 480-byte payload can cross a page boundary; if so, - we need to split it into two DMA descriptors */ - - /* does the 480-byte data payload cross a page boundary? */ - if ( (PAGE_SIZE- ((unsigned long)data_p % PAGE_SIZE) ) < 480 ) { - - /* page boundary crossed */ - - fill_output_more( &(block->u.out.u.full.u.cross.om), - /* data size - how much of data_p fits on the first page */ - PAGE_SIZE - (data_p % PAGE_SIZE), - - /* DMA address of data_p */ - dma_region_offset_to_bus(&video->dv_buf, - data_p - (unsigned long) video->dv_buf.kvirt)); - - fill_output_last( &(block->u.out.u.full.u.cross.ol), - - /* want completion status on all interesting packets */ - (first_packet || mid_packet || last_packet) ? 1 : 0, - - /* want interrupt on all interesting packets */ - (first_packet || mid_packet || last_packet) ? 1 : 0, - - /* data size - remaining portion of data_p */ - 480 - (PAGE_SIZE - (data_p % PAGE_SIZE)), - - /* DMA address of data_p + PAGE_SIZE - (data_p % PAGE_SIZE) */ - dma_region_offset_to_bus(&video->dv_buf, - data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) video->dv_buf.kvirt)); - - if (first_packet) - f->frame_begin_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); - else if (mid_packet) - f->mid_frame_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); - else if (last_packet) { - f->frame_end_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); - f->frame_end_branch = &(block->u.out.u.full.u.cross.ol.q[2]); - } - - branch_address = &(block->u.out.u.full.u.cross.ol.q[2]); - - n_descriptors = 5; - if (first_packet) - f->first_n_descriptors = n_descriptors; - - full_packets++; - - } else { - /* fits on one page */ - - fill_output_last( &(block->u.out.u.full.u.nocross.ol), - - /* want completion status on all interesting packets */ - (first_packet || mid_packet || last_packet) ? 1 : 0, - - /* want interrupt on all interesting packets */ - (first_packet || mid_packet || last_packet) ? 1 : 0, - - 480, /* data size (480 bytes of DV data) */ - - - /* DMA address of data_p */ - dma_region_offset_to_bus(&video->dv_buf, - data_p - (unsigned long) video->dv_buf.kvirt)); - - if (first_packet) - f->frame_begin_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); - else if (mid_packet) - f->mid_frame_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); - else if (last_packet) { - f->frame_end_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); - f->frame_end_branch = &(block->u.out.u.full.u.nocross.ol.q[2]); - } - - branch_address = &(block->u.out.u.full.u.nocross.ol.q[2]); - - n_descriptors = 4; - if (first_packet) - f->first_n_descriptors = n_descriptors; - - full_packets++; - } - } - - /* link this descriptor block into the DMA program by filling in - the branch address of the previous block */ - - /* note: we are not linked into the active DMA chain yet */ - - if (last_branch_address) { - *(last_branch_address) = cpu_to_le32(block_dma | n_descriptors); - } - - last_branch_address = branch_address; - - - f->n_packets++; - - } - - /* when we first assemble a new frame, set the final branch - to loop back up to the top */ - *(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors); - - /* make the latest version of this frame visible to the PCI card */ - dma_region_sync_for_device(&video->dv_buf, f->data - (unsigned long) video->dv_buf.kvirt, video->frame_size); - - /* lock against DMA interrupt */ - spin_lock_irqsave(&video->spinlock, irq_flags); - - f->state = FRAME_READY; - - video->n_clear_frames--; - - last_frame = video->first_clear_frame - 1; - if (last_frame == -1) - last_frame = video->n_frames-1; - - video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; - - irq_printk(" frame %d prepared, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n last=%d\n", - this_frame, video->active_frame, video->n_clear_frames, video->first_clear_frame, last_frame); - - irq_printk(" begin_ts %08lx mid_ts %08lx end_ts %08lx end_br %08lx\n", - (unsigned long) f->frame_begin_timestamp, - (unsigned long) f->mid_frame_timestamp, - (unsigned long) f->frame_end_timestamp, - (unsigned long) f->frame_end_branch); - - if (video->active_frame != -1) { - - /* if DMA is already active, we are almost done */ - /* just link us onto the active DMA chain */ - if (video->frames[last_frame]->frame_end_branch) { - u32 temp; - - /* point the previous frame's tail to this frame's head */ - *(video->frames[last_frame]->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors); - - /* this write MUST precede the next one, or we could silently drop frames */ - wmb(); - - /* disable the want_status semaphore on the last packet */ - temp = le32_to_cpu(*(video->frames[last_frame]->frame_end_branch - 2)); - temp &= 0xF7CFFFFF; - *(video->frames[last_frame]->frame_end_branch - 2) = cpu_to_le32(temp); - - /* flush these writes to memory ASAP */ - flush_pci_write(video->ohci); - - /* NOTE: - ideally the writes should be "atomic": if - the OHCI card reads the want_status flag in - between them, we'll falsely report a - dropped frame. Hopefully this window is too - small to really matter, and the consequence - is rather harmless. */ - - - irq_printk(" new frame %d linked onto DMA chain\n", this_frame); - - } else { - printk(KERN_ERR "dv1394: last frame not ready???\n"); - } - - } else { - - u32 transmit_sec, transmit_cyc; - u32 ts_cyc; - - /* DMA is stopped, so this is the very first frame */ - video->active_frame = this_frame; - - /* set CommandPtr to address and size of first descriptor block */ - reg_write(video->ohci, video->ohci_IsoXmitCommandPtr, - video->frames[video->active_frame]->descriptor_pool_dma | - f->first_n_descriptors); - - /* assign a timestamp based on the current cycle time... - We'll tell the card to begin DMA 100 cycles from now, - and assign a timestamp 103 cycles from now */ - - cycleTimer = reg_read(video->ohci, OHCI1394_IsochronousCycleTimer); - - ct_sec = cycleTimer >> 25; - ct_cyc = (cycleTimer >> 12) & 0x1FFF; - ct_off = cycleTimer & 0xFFF; - - transmit_sec = ct_sec; - transmit_cyc = ct_cyc + 100; - - transmit_sec += transmit_cyc/8000; - transmit_cyc %= 8000; - - ts_cyc = transmit_cyc + 3; - ts_cyc %= 8000; - - f->assigned_timestamp = (ts_cyc&0xF) << 12; - - /* now actually write the timestamp into the appropriate CIP headers */ - if (f->cip_syt1) { - f->cip_syt1->b[6] = f->assigned_timestamp >> 8; - f->cip_syt1->b[7] = f->assigned_timestamp & 0xFF; - } - if (f->cip_syt2) { - f->cip_syt2->b[6] = f->assigned_timestamp >> 8; - f->cip_syt2->b[7] = f->assigned_timestamp & 0xFF; - } - - /* --- start DMA --- */ - - /* clear all bits in ContextControl register */ - - reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, 0xFFFFFFFF); - wmb(); - - /* the OHCI card has the ability to start ISO transmission on a - particular cycle (start-on-cycle). This way we can ensure that - the first DV frame will have an accurate timestamp. - - However, start-on-cycle only appears to work if the OHCI card - is cycle master! Since the consequences of messing up the first - timestamp are minimal*, just disable start-on-cycle for now. - - * my DV deck drops the first few frames before it "locks in;" - so the first frame having an incorrect timestamp is inconsequential. - */ - -#if 0 - reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, - (1 << 31) /* enable start-on-cycle */ - | ( (transmit_sec & 0x3) << 29) - | (transmit_cyc << 16)); - wmb(); -#endif - - video->dma_running = 1; - - /* set the 'run' bit */ - reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, 0x8000); - flush_pci_write(video->ohci); - - /* --- DMA should be running now --- */ - - debug_printk(" Cycle = %4u ContextControl = %08x CmdPtr = %08x\n", - (reg_read(video->ohci, OHCI1394_IsochronousCycleTimer) >> 12) & 0x1FFF, - reg_read(video->ohci, video->ohci_IsoXmitContextControlSet), - reg_read(video->ohci, video->ohci_IsoXmitCommandPtr)); - - debug_printk(" DMA start - current cycle %4u, transmit cycle %4u (%2u), assigning ts cycle %2u\n", - ct_cyc, transmit_cyc, transmit_cyc & 0xF, ts_cyc & 0xF); - -#if DV1394_DEBUG_LEVEL >= 2 - { - /* check if DMA is really running */ - int i = 0; - while (i < 20) { - mb(); - mdelay(1); - if (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) { - printk("DMA ACTIVE after %d msec\n", i); - break; - } - i++; - } - - printk("set = %08x, cmdPtr = %08x\n", - reg_read(video->ohci, video->ohci_IsoXmitContextControlSet), - reg_read(video->ohci, video->ohci_IsoXmitCommandPtr) - ); - - if ( ! (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) { - printk("DMA did NOT go active after 20ms, event = %x\n", - reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & 0x1F); - } else - printk("DMA is RUNNING!\n"); - } -#endif - - } - - - spin_unlock_irqrestore(&video->spinlock, irq_flags); -} - - - -/*** RECEIVE FUNCTIONS *****************************************************/ - -/* - frame method put_packet - - map and copy the packet data to its location in the frame - based upon DIF section and sequence -*/ - -static void inline -frame_put_packet (struct frame *f, struct packet *p) -{ - int section_type = p->data[0] >> 5; /* section type is in bits 5 - 7 */ - int dif_sequence = p->data[1] >> 4; /* dif sequence number is in bits 4 - 7 */ - int dif_block = p->data[2]; - - /* sanity check */ - if (dif_sequence > 11 || dif_block > 149) return; - - switch (section_type) { - case 0: /* 1 Header block */ - memcpy( (void *) f->data + dif_sequence * 150 * 80, p->data, 480); - break; - - case 1: /* 2 Subcode blocks */ - memcpy( (void *) f->data + dif_sequence * 150 * 80 + (1 + dif_block) * 80, p->data, 480); - break; - - case 2: /* 3 VAUX blocks */ - memcpy( (void *) f->data + dif_sequence * 150 * 80 + (3 + dif_block) * 80, p->data, 480); - break; - - case 3: /* 9 Audio blocks interleaved with video */ - memcpy( (void *) f->data + dif_sequence * 150 * 80 + (6 + dif_block * 16) * 80, p->data, 480); - break; - - case 4: /* 135 Video blocks interleaved with audio */ - memcpy( (void *) f->data + dif_sequence * 150 * 80 + (7 + (dif_block / 15) + dif_block) * 80, p->data, 480); - break; - - default: /* we can not handle any other data */ - break; - } -} - - -static void start_dma_receive(struct video_card *video) -{ - if (video->first_run == 1) { - video->first_run = 0; - - /* start DMA once all of the frames are READY */ - video->n_clear_frames = 0; - video->first_clear_frame = -1; - video->current_packet = 0; - video->active_frame = 0; - - /* reset iso recv control register */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF); - wmb(); - - /* clear bufferFill, set isochHeader and speed (0=100) */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000); - - /* match on all tags, listen on channel */ - reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | video->channel); - - /* address and first descriptor block + Z=1 */ - reg_write(video->ohci, video->ohci_IsoRcvCommandPtr, - video->frames[0]->descriptor_pool_dma | 1); /* Z=1 */ - wmb(); - - video->dma_running = 1; - - /* run */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000); - flush_pci_write(video->ohci); - - debug_printk("dv1394: DMA started\n"); - -#if DV1394_DEBUG_LEVEL >= 2 - { - int i; - - for (i = 0; i < 1000; ++i) { - mdelay(1); - if (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) { - printk("DMA ACTIVE after %d msec\n", i); - break; - } - } - if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { - printk("DEAD, event = %x\n", - reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); - } else - printk("RUNNING!\n"); - } -#endif - } else if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { - debug_printk("DEAD, event = %x\n", - reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); - - /* wake */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); - } -} - - -/* - receive_packets() - build the DMA program for receiving -*/ - -static void receive_packets(struct video_card *video) -{ - struct DMA_descriptor_block *block = NULL; - dma_addr_t block_dma = 0; - struct packet *data = NULL; - dma_addr_t data_dma = 0; - __le32 *last_branch_address = NULL; - unsigned long irq_flags; - int want_interrupt = 0; - struct frame *f = NULL; - int i, j; - - spin_lock_irqsave(&video->spinlock, irq_flags); - - for (j = 0; j < video->n_frames; j++) { - - /* connect frames */ - if (j > 0 && f != NULL && f->frame_end_branch != NULL) - *(f->frame_end_branch) = cpu_to_le32(video->frames[j]->descriptor_pool_dma | 1); /* set Z=1 */ - - f = video->frames[j]; - - for (i = 0; i < MAX_PACKETS; i++) { - /* locate a descriptor block and packet from the buffer */ - block = &(f->descriptor_pool[i]); - block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; - - data = ((struct packet*)video->packet_buf.kvirt) + f->frame_num * MAX_PACKETS + i; - data_dma = dma_region_offset_to_bus( &video->packet_buf, - ((unsigned long) data - (unsigned long) video->packet_buf.kvirt) ); - - /* setup DMA descriptor block */ - want_interrupt = ((i % (MAX_PACKETS/2)) == 0 || i == (MAX_PACKETS-1)); - fill_input_last( &(block->u.in.il), want_interrupt, 512, data_dma); - - /* link descriptors */ - last_branch_address = f->frame_end_branch; - - if (last_branch_address != NULL) - *(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */ - - f->frame_end_branch = &(block->u.in.il.q[2]); - } - - } /* next j */ - - spin_unlock_irqrestore(&video->spinlock, irq_flags); - -} - - - -/*** MANAGEMENT FUNCTIONS **************************************************/ - -static int do_dv1394_init(struct video_card *video, struct dv1394_init *init) -{ - unsigned long flags, new_buf_size; - int i; - u64 chan_mask; - int retval = -EINVAL; - - debug_printk("dv1394: initialising %d\n", video->id); - if (init->api_version != DV1394_API_VERSION) - return -EINVAL; - - /* first sanitize all the parameters */ - if ( (init->n_frames < 2) || (init->n_frames > DV1394_MAX_FRAMES) ) - return -EINVAL; - - if ( (init->format != DV1394_NTSC) && (init->format != DV1394_PAL) ) - return -EINVAL; - - if ( (init->syt_offset == 0) || (init->syt_offset > 50) ) - /* default SYT offset is 3 cycles */ - init->syt_offset = 3; - - if (init->channel > 63) - init->channel = 63; - - chan_mask = (u64)1 << init->channel; - - /* calculate what size DMA buffer is needed */ - if (init->format == DV1394_NTSC) - new_buf_size = DV1394_NTSC_FRAME_SIZE * init->n_frames; - else - new_buf_size = DV1394_PAL_FRAME_SIZE * init->n_frames; - - /* round up to PAGE_SIZE */ - if (new_buf_size % PAGE_SIZE) new_buf_size += PAGE_SIZE - (new_buf_size % PAGE_SIZE); - - /* don't allow the user to allocate the DMA buffer more than once */ - if (video->dv_buf.kvirt && video->dv_buf_size != new_buf_size) { - printk("dv1394: re-sizing the DMA buffer is not allowed\n"); - return -EINVAL; - } - - /* shutdown the card if it's currently active */ - /* (the card should not be reset if the parameters are screwy) */ - - do_dv1394_shutdown(video, 0); - - /* try to claim the ISO channel */ - spin_lock_irqsave(&video->ohci->IR_channel_lock, flags); - if (video->ohci->ISO_channel_usage & chan_mask) { - spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags); - retval = -EBUSY; - goto err; - } - video->ohci->ISO_channel_usage |= chan_mask; - spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags); - - video->channel = init->channel; - - /* initialize misc. fields of video */ - video->n_frames = init->n_frames; - video->pal_or_ntsc = init->format; - - video->cip_accum = 0; - video->continuity_counter = 0; - - video->active_frame = -1; - video->first_clear_frame = 0; - video->n_clear_frames = video->n_frames; - video->dropped_frames = 0; - - video->write_off = 0; - - video->first_run = 1; - video->current_packet = -1; - video->first_frame = 0; - - if (video->pal_or_ntsc == DV1394_NTSC) { - video->cip_n = init->cip_n != 0 ? init->cip_n : CIP_N_NTSC; - video->cip_d = init->cip_d != 0 ? init->cip_d : CIP_D_NTSC; - video->frame_size = DV1394_NTSC_FRAME_SIZE; - } else { - video->cip_n = init->cip_n != 0 ? init->cip_n : CIP_N_PAL; - video->cip_d = init->cip_d != 0 ? init->cip_d : CIP_D_PAL; - video->frame_size = DV1394_PAL_FRAME_SIZE; - } - - video->syt_offset = init->syt_offset; - - /* find and claim DMA contexts on the OHCI card */ - - if (video->ohci_it_ctx == -1) { - ohci1394_init_iso_tasklet(&video->it_tasklet, OHCI_ISO_TRANSMIT, - it_tasklet_func, (unsigned long) video); - - if (ohci1394_register_iso_tasklet(video->ohci, &video->it_tasklet) < 0) { - printk(KERN_ERR "dv1394: could not find an available IT DMA context\n"); - retval = -EBUSY; - goto err; - } - - video->ohci_it_ctx = video->it_tasklet.context; - debug_printk("dv1394: claimed IT DMA context %d\n", video->ohci_it_ctx); - } - - if (video->ohci_ir_ctx == -1) { - ohci1394_init_iso_tasklet(&video->ir_tasklet, OHCI_ISO_RECEIVE, - ir_tasklet_func, (unsigned long) video); - - if (ohci1394_register_iso_tasklet(video->ohci, &video->ir_tasklet) < 0) { - printk(KERN_ERR "dv1394: could not find an available IR DMA context\n"); - retval = -EBUSY; - goto err; - } - video->ohci_ir_ctx = video->ir_tasklet.context; - debug_printk("dv1394: claimed IR DMA context %d\n", video->ohci_ir_ctx); - } - - /* allocate struct frames */ - for (i = 0; i < init->n_frames; i++) { - video->frames[i] = frame_new(i, video); - - if (!video->frames[i]) { - printk(KERN_ERR "dv1394: Cannot allocate frame structs\n"); - retval = -ENOMEM; - goto err; - } - } - - if (!video->dv_buf.kvirt) { - /* allocate the ringbuffer */ - retval = dma_region_alloc(&video->dv_buf, new_buf_size, video->ohci->dev, PCI_DMA_TODEVICE); - if (retval) - goto err; - - video->dv_buf_size = new_buf_size; - - debug_printk("dv1394: Allocated %d frame buffers, total %u pages (%u DMA pages), %lu bytes\n", - video->n_frames, video->dv_buf.n_pages, - video->dv_buf.n_dma_pages, video->dv_buf_size); - } - - /* set up the frame->data pointers */ - for (i = 0; i < video->n_frames; i++) - video->frames[i]->data = (unsigned long) video->dv_buf.kvirt + i * video->frame_size; - - if (!video->packet_buf.kvirt) { - /* allocate packet buffer */ - video->packet_buf_size = sizeof(struct packet) * video->n_frames * MAX_PACKETS; - if (video->packet_buf_size % PAGE_SIZE) - video->packet_buf_size += PAGE_SIZE - (video->packet_buf_size % PAGE_SIZE); - - retval = dma_region_alloc(&video->packet_buf, video->packet_buf_size, - video->ohci->dev, PCI_DMA_FROMDEVICE); - if (retval) - goto err; - - debug_printk("dv1394: Allocated %d packets in buffer, total %u pages (%u DMA pages), %lu bytes\n", - video->n_frames*MAX_PACKETS, video->packet_buf.n_pages, - video->packet_buf.n_dma_pages, video->packet_buf_size); - } - - /* set up register offsets for IT context */ - /* IT DMA context registers are spaced 16 bytes apart */ - video->ohci_IsoXmitContextControlSet = OHCI1394_IsoXmitContextControlSet+16*video->ohci_it_ctx; - video->ohci_IsoXmitContextControlClear = OHCI1394_IsoXmitContextControlClear+16*video->ohci_it_ctx; - video->ohci_IsoXmitCommandPtr = OHCI1394_IsoXmitCommandPtr+16*video->ohci_it_ctx; - - /* enable interrupts for IT context */ - reg_write(video->ohci, OHCI1394_IsoXmitIntMaskSet, (1 << video->ohci_it_ctx)); - debug_printk("dv1394: interrupts enabled for IT context %d\n", video->ohci_it_ctx); - - /* set up register offsets for IR context */ - /* IR DMA context registers are spaced 32 bytes apart */ - video->ohci_IsoRcvContextControlSet = OHCI1394_IsoRcvContextControlSet+32*video->ohci_ir_ctx; - video->ohci_IsoRcvContextControlClear = OHCI1394_IsoRcvContextControlClear+32*video->ohci_ir_ctx; - video->ohci_IsoRcvCommandPtr = OHCI1394_IsoRcvCommandPtr+32*video->ohci_ir_ctx; - video->ohci_IsoRcvContextMatch = OHCI1394_IsoRcvContextMatch+32*video->ohci_ir_ctx; - - /* enable interrupts for IR context */ - reg_write(video->ohci, OHCI1394_IsoRecvIntMaskSet, (1 << video->ohci_ir_ctx) ); - debug_printk("dv1394: interrupts enabled for IR context %d\n", video->ohci_ir_ctx); - - return 0; - -err: - do_dv1394_shutdown(video, 1); - return retval; -} - -/* if the user doesn't bother to call ioctl(INIT) before starting - mmap() or read()/write(), just give him some default values */ - -static int do_dv1394_init_default(struct video_card *video) -{ - struct dv1394_init init; - - init.api_version = DV1394_API_VERSION; - init.n_frames = DV1394_MAX_FRAMES / 4; - init.channel = video->channel; - init.format = video->pal_or_ntsc; - init.cip_n = video->cip_n; - init.cip_d = video->cip_d; - init.syt_offset = video->syt_offset; - - return do_dv1394_init(video, &init); -} - -/* do NOT call from interrupt context */ -static void stop_dma(struct video_card *video) -{ - unsigned long flags; - int i; - - /* no interrupts */ - spin_lock_irqsave(&video->spinlock, flags); - - video->dma_running = 0; - - if ( (video->ohci_it_ctx == -1) && (video->ohci_ir_ctx == -1) ) - goto out; - - /* stop DMA if in progress */ - if ( (video->active_frame != -1) || - (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || - (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { - - /* clear the .run bits */ - reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, (1 << 15)); - reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, (1 << 15)); - flush_pci_write(video->ohci); - - video->active_frame = -1; - video->first_run = 1; - - /* wait until DMA really stops */ - i = 0; - while (i < 1000) { - - /* wait 0.1 millisecond */ - udelay(100); - - if ( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || - (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { - /* still active */ - debug_printk("dv1394: stop_dma: DMA not stopped yet\n" ); - mb(); - } else { - debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10); - break; - } - - i++; - } - - if (i == 1000) { - printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10); - } - } - else - debug_printk("dv1394: stop_dma: already stopped.\n"); - -out: - spin_unlock_irqrestore(&video->spinlock, flags); -} - - - -static void do_dv1394_shutdown(struct video_card *video, int free_dv_buf) -{ - int i; - - debug_printk("dv1394: shutdown...\n"); - - /* stop DMA if in progress */ - stop_dma(video); - - /* release the DMA contexts */ - if (video->ohci_it_ctx != -1) { - video->ohci_IsoXmitContextControlSet = 0; - video->ohci_IsoXmitContextControlClear = 0; - video->ohci_IsoXmitCommandPtr = 0; - - /* disable interrupts for IT context */ - reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx)); - - /* remove tasklet */ - ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet); - debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx); - video->ohci_it_ctx = -1; - } - - if (video->ohci_ir_ctx != -1) { - video->ohci_IsoRcvContextControlSet = 0; - video->ohci_IsoRcvContextControlClear = 0; - video->ohci_IsoRcvCommandPtr = 0; - video->ohci_IsoRcvContextMatch = 0; - - /* disable interrupts for IR context */ - reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx)); - - /* remove tasklet */ - ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet); - debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx); - video->ohci_ir_ctx = -1; - } - - /* release the ISO channel */ - if (video->channel != -1) { - u64 chan_mask; - unsigned long flags; - - chan_mask = (u64)1 << video->channel; - - spin_lock_irqsave(&video->ohci->IR_channel_lock, flags); - video->ohci->ISO_channel_usage &= ~(chan_mask); - spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags); - - video->channel = -1; - } - - /* free the frame structs */ - for (i = 0; i < DV1394_MAX_FRAMES; i++) { - if (video->frames[i]) - frame_delete(video->frames[i]); - video->frames[i] = NULL; - } - - video->n_frames = 0; - - /* we can't free the DMA buffer unless it is guaranteed that - no more user-space mappings exist */ - - if (free_dv_buf) { - dma_region_free(&video->dv_buf); - video->dv_buf_size = 0; - } - - /* free packet buffer */ - dma_region_free(&video->packet_buf); - video->packet_buf_size = 0; - - debug_printk("dv1394: shutdown OK\n"); -} - -/* - ********************************** - *** MMAP() THEORY OF OPERATION *** - ********************************** - - The ringbuffer cannot be re-allocated or freed while - a user program maintains a mapping of it. (note that a mapping - can persist even after the device fd is closed!) - - So, only let the user process allocate the DMA buffer once. - To resize or deallocate it, you must close the device file - and open it again. - - Previously Dan M. hacked out a scheme that allowed the DMA - buffer to change by forcefully unmapping it from the user's - address space. It was prone to error because it's very hard to - track all the places the buffer could have been mapped (we - would have had to walk the vma list of every process in the - system to be sure we found all the mappings!). Instead, we - force the user to choose one buffer size and stick with - it. This small sacrifice is worth the huge reduction in - error-prone code in dv1394. -*/ - -static int dv1394_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct video_card *video = file_to_video_card(file); - int retval = -EINVAL; - - /* - * We cannot use the blocking variant mutex_lock here because .mmap - * is called with mmap_sem held, while .ioctl, .read, .write acquire - * video->mtx and subsequently call copy_to/from_user which will - * grab mmap_sem in case of a page fault. - */ - if (!mutex_trylock(&video->mtx)) - return -EAGAIN; - - if ( ! video_card_initialized(video) ) { - retval = do_dv1394_init_default(video); - if (retval) - goto out; - } - - retval = dma_region_mmap(&video->dv_buf, file, vma); -out: - mutex_unlock(&video->mtx); - return retval; -} - -/*** DEVICE FILE INTERFACE *************************************************/ - -/* no need to serialize, multiple threads OK */ -static unsigned int dv1394_poll(struct file *file, struct poll_table_struct *wait) -{ - struct video_card *video = file_to_video_card(file); - unsigned int mask = 0; - unsigned long flags; - - poll_wait(file, &video->waitq, wait); - - spin_lock_irqsave(&video->spinlock, flags); - if ( video->n_frames == 0 ) { - - } else if ( video->active_frame == -1 ) { - /* nothing going on */ - mask |= POLLOUT; - } else { - /* any clear/ready buffers? */ - if (video->n_clear_frames >0) - mask |= POLLOUT | POLLIN; - } - spin_unlock_irqrestore(&video->spinlock, flags); - - return mask; -} - -static int dv1394_fasync(int fd, struct file *file, int on) -{ - /* I just copied this code verbatim from Alan Cox's mouse driver example - (Documentation/DocBook/) */ - - struct video_card *video = file_to_video_card(file); - - return fasync_helper(fd, file, on, &video->fasync); -} - -static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) -{ - struct video_card *video = file_to_video_card(file); - DECLARE_WAITQUEUE(wait, current); - ssize_t ret; - size_t cnt; - unsigned long flags; - int target_frame; - - /* serialize this to prevent multi-threaded mayhem */ - if (file->f_flags & O_NONBLOCK) { - if (!mutex_trylock(&video->mtx)) - return -EAGAIN; - } else { - if (mutex_lock_interruptible(&video->mtx)) - return -ERESTARTSYS; - } - - if ( !video_card_initialized(video) ) { - ret = do_dv1394_init_default(video); - if (ret) { - mutex_unlock(&video->mtx); - return ret; - } - } - - ret = 0; - add_wait_queue(&video->waitq, &wait); - - while (count > 0) { - - /* must set TASK_INTERRUPTIBLE *before* checking for free - buffers; otherwise we could miss a wakeup if the interrupt - fires between the check and the schedule() */ - - set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irqsave(&video->spinlock, flags); - - target_frame = video->first_clear_frame; - - spin_unlock_irqrestore(&video->spinlock, flags); - - if (video->frames[target_frame]->state == FRAME_CLEAR) { - - /* how much room is left in the target frame buffer */ - cnt = video->frame_size - (video->write_off - target_frame * video->frame_size); - - } else { - /* buffer is already used */ - cnt = 0; - } - - if (cnt > count) - cnt = count; - - if (cnt <= 0) { - /* no room left, gotta wait */ - if (file->f_flags & O_NONBLOCK) { - if (!ret) - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { - if (!ret) - ret = -ERESTARTSYS; - break; - } - - schedule(); - - continue; /* start over from 'while(count > 0)...' */ - } - - if (copy_from_user(video->dv_buf.kvirt + video->write_off, buffer, cnt)) { - if (!ret) - ret = -EFAULT; - break; - } - - video->write_off = (video->write_off + cnt) % (video->n_frames * video->frame_size); - - count -= cnt; - buffer += cnt; - ret += cnt; - - if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) - frame_prepare(video, target_frame); - } - - remove_wait_queue(&video->waitq, &wait); - set_current_state(TASK_RUNNING); - mutex_unlock(&video->mtx); - return ret; -} - - -static ssize_t dv1394_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) -{ - struct video_card *video = file_to_video_card(file); - DECLARE_WAITQUEUE(wait, current); - ssize_t ret; - size_t cnt; - unsigned long flags; - int target_frame; - - /* serialize this to prevent multi-threaded mayhem */ - if (file->f_flags & O_NONBLOCK) { - if (!mutex_trylock(&video->mtx)) - return -EAGAIN; - } else { - if (mutex_lock_interruptible(&video->mtx)) - return -ERESTARTSYS; - } - - if ( !video_card_initialized(video) ) { - ret = do_dv1394_init_default(video); - if (ret) { - mutex_unlock(&video->mtx); - return ret; - } - video->continuity_counter = -1; - - receive_packets(video); - - start_dma_receive(video); - } - - ret = 0; - add_wait_queue(&video->waitq, &wait); - - while (count > 0) { - - /* must set TASK_INTERRUPTIBLE *before* checking for free - buffers; otherwise we could miss a wakeup if the interrupt - fires between the check and the schedule() */ - - set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irqsave(&video->spinlock, flags); - - target_frame = video->first_clear_frame; - - spin_unlock_irqrestore(&video->spinlock, flags); - - if (target_frame >= 0 && - video->n_clear_frames > 0 && - video->frames[target_frame]->state == FRAME_CLEAR) { - - /* how much room is left in the target frame buffer */ - cnt = video->frame_size - (video->write_off - target_frame * video->frame_size); - - } else { - /* buffer is already used */ - cnt = 0; - } - - if (cnt > count) - cnt = count; - - if (cnt <= 0) { - /* no room left, gotta wait */ - if (file->f_flags & O_NONBLOCK) { - if (!ret) - ret = -EAGAIN; - break; - } - if (signal_pending(current)) { - if (!ret) - ret = -ERESTARTSYS; - break; - } - - schedule(); - - continue; /* start over from 'while(count > 0)...' */ - } - - if (copy_to_user(buffer, video->dv_buf.kvirt + video->write_off, cnt)) { - if (!ret) - ret = -EFAULT; - break; - } - - video->write_off = (video->write_off + cnt) % (video->n_frames * video->frame_size); - - count -= cnt; - buffer += cnt; - ret += cnt; - - if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) { - spin_lock_irqsave(&video->spinlock, flags); - video->n_clear_frames--; - video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; - spin_unlock_irqrestore(&video->spinlock, flags); - } - } - - remove_wait_queue(&video->waitq, &wait); - set_current_state(TASK_RUNNING); - mutex_unlock(&video->mtx); - return ret; -} - - -/*** DEVICE IOCTL INTERFACE ************************************************/ - -static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct video_card *video = file_to_video_card(file); - unsigned long flags; - int ret = -EINVAL; - void __user *argp = (void __user *)arg; - - DECLARE_WAITQUEUE(wait, current); - - /* serialize this to prevent multi-threaded mayhem */ - if (file->f_flags & O_NONBLOCK) { - if (!mutex_trylock(&video->mtx)) - return -EAGAIN; - } else { - if (mutex_lock_interruptible(&video->mtx)) - return -ERESTARTSYS; - } - - switch(cmd) - { - case DV1394_IOC_SUBMIT_FRAMES: { - unsigned int n_submit; - - if ( !video_card_initialized(video) ) { - ret = do_dv1394_init_default(video); - if (ret) - goto out; - } - - n_submit = (unsigned int) arg; - - if (n_submit > video->n_frames) { - ret = -EINVAL; - goto out; - } - - while (n_submit > 0) { - - add_wait_queue(&video->waitq, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irqsave(&video->spinlock, flags); - - /* wait until video->first_clear_frame is really CLEAR */ - while (video->frames[video->first_clear_frame]->state != FRAME_CLEAR) { - - spin_unlock_irqrestore(&video->spinlock, flags); - - if (signal_pending(current)) { - remove_wait_queue(&video->waitq, &wait); - set_current_state(TASK_RUNNING); - ret = -EINTR; - goto out; - } - - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irqsave(&video->spinlock, flags); - } - spin_unlock_irqrestore(&video->spinlock, flags); - - remove_wait_queue(&video->waitq, &wait); - set_current_state(TASK_RUNNING); - - frame_prepare(video, video->first_clear_frame); - - n_submit--; - } - - ret = 0; - break; - } - - case DV1394_IOC_WAIT_FRAMES: { - unsigned int n_wait; - - if ( !video_card_initialized(video) ) { - ret = -EINVAL; - goto out; - } - - n_wait = (unsigned int) arg; - - /* since we re-run the last frame on underflow, we will - never actually have n_frames clear frames; at most only - n_frames - 1 */ - - if (n_wait > (video->n_frames-1) ) { - ret = -EINVAL; - goto out; - } - - add_wait_queue(&video->waitq, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irqsave(&video->spinlock, flags); - - while (video->n_clear_frames < n_wait) { - - spin_unlock_irqrestore(&video->spinlock, flags); - - if (signal_pending(current)) { - remove_wait_queue(&video->waitq, &wait); - set_current_state(TASK_RUNNING); - ret = -EINTR; - goto out; - } - - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irqsave(&video->spinlock, flags); - } - - spin_unlock_irqrestore(&video->spinlock, flags); - - remove_wait_queue(&video->waitq, &wait); - set_current_state(TASK_RUNNING); - ret = 0; - break; - } - - case DV1394_IOC_RECEIVE_FRAMES: { - unsigned int n_recv; - - if ( !video_card_initialized(video) ) { - ret = -EINVAL; - goto out; - } - - n_recv = (unsigned int) arg; - - /* at least one frame must be active */ - if (n_recv > (video->n_frames-1) ) { - ret = -EINVAL; - goto out; - } - - spin_lock_irqsave(&video->spinlock, flags); - - /* release the clear frames */ - video->n_clear_frames -= n_recv; - - /* advance the clear frame cursor */ - video->first_clear_frame = (video->first_clear_frame + n_recv) % video->n_frames; - - /* reset dropped_frames */ - video->dropped_frames = 0; - - spin_unlock_irqrestore(&video->spinlock, flags); - - ret = 0; - break; - } - - case DV1394_IOC_START_RECEIVE: { - if ( !video_card_initialized(video) ) { - ret = do_dv1394_init_default(video); - if (ret) - goto out; - } - - video->continuity_counter = -1; - - receive_packets(video); - - start_dma_receive(video); - - ret = 0; - break; - } - - case DV1394_IOC_INIT: { - struct dv1394_init init; - if (!argp) { - ret = do_dv1394_init_default(video); - } else { - if (copy_from_user(&init, argp, sizeof(init))) { - ret = -EFAULT; - goto out; - } - ret = do_dv1394_init(video, &init); - } - break; - } - - case DV1394_IOC_SHUTDOWN: - do_dv1394_shutdown(video, 0); - ret = 0; - break; - - - case DV1394_IOC_GET_STATUS: { - struct dv1394_status status; - - if ( !video_card_initialized(video) ) { - ret = -EINVAL; - goto out; - } - - status.init.api_version = DV1394_API_VERSION; - status.init.channel = video->channel; - status.init.n_frames = video->n_frames; - status.init.format = video->pal_or_ntsc; - status.init.cip_n = video->cip_n; - status.init.cip_d = video->cip_d; - status.init.syt_offset = video->syt_offset; - - status.first_clear_frame = video->first_clear_frame; - - /* the rest of the fields need to be locked against the interrupt */ - spin_lock_irqsave(&video->spinlock, flags); - - status.active_frame = video->active_frame; - status.n_clear_frames = video->n_clear_frames; - - status.dropped_frames = video->dropped_frames; - - /* reset dropped_frames */ - video->dropped_frames = 0; - - spin_unlock_irqrestore(&video->spinlock, flags); - - if (copy_to_user(argp, &status, sizeof(status))) { - ret = -EFAULT; - goto out; - } - - ret = 0; - break; - } - - default: - break; - } - - out: - mutex_unlock(&video->mtx); - return ret; -} - -/*** DEVICE FILE INTERFACE CONTINUED ***************************************/ - -static int dv1394_open(struct inode *inode, struct file *file) -{ - struct video_card *video = NULL; - - if (file->private_data) { - video = file->private_data; - - } else { - /* look up the card by ID */ - unsigned long flags; - int idx = ieee1394_file_to_instance(file); - - spin_lock_irqsave(&dv1394_cards_lock, flags); - if (!list_empty(&dv1394_cards)) { - struct video_card *p; - list_for_each_entry(p, &dv1394_cards, list) { - if ((p->id) == idx) { - video = p; - break; - } - } - } - spin_unlock_irqrestore(&dv1394_cards_lock, flags); - - if (!video) { - debug_printk("dv1394: OHCI card %d not found", idx); - return -ENODEV; - } - - file->private_data = (void*) video; - } - -#ifndef DV1394_ALLOW_MORE_THAN_ONE_OPEN - - if ( test_and_set_bit(0, &video->open) ) { - /* video is already open by someone else */ - return -EBUSY; - } - -#endif - - printk(KERN_INFO "%s: NOTE, the dv1394 interface is unsupported " - "and will not be available in the new firewire driver stack. " - "Try libraw1394 based programs instead.\n", current->comm); - - return nonseekable_open(inode, file); -} - - -static int dv1394_release(struct inode *inode, struct file *file) -{ - struct video_card *video = file_to_video_card(file); - - /* OK to free the DMA buffer, no more mappings can exist */ - do_dv1394_shutdown(video, 1); - - /* give someone else a turn */ - clear_bit(0, &video->open); - - return 0; -} - - -/*** DEVICE DRIVER HANDLERS ************************************************/ - -static void it_tasklet_func(unsigned long data) -{ - int wake = 0; - struct video_card *video = (struct video_card*) data; - - spin_lock(&video->spinlock); - - if (!video->dma_running) - goto out; - - irq_printk("ContextControl = %08x, CommandPtr = %08x\n", - reg_read(video->ohci, video->ohci_IsoXmitContextControlSet), - reg_read(video->ohci, video->ohci_IsoXmitCommandPtr) - ); - - - if ( (video->ohci_it_ctx != -1) && - (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) { - - struct frame *f; - unsigned int frame, i; - - - if (video->active_frame == -1) - frame = 0; - else - frame = video->active_frame; - - /* check all the DMA-able frames */ - for (i = 0; i < video->n_frames; i++, frame = (frame+1) % video->n_frames) { - - irq_printk("IRQ checking frame %d...", frame); - f = video->frames[frame]; - if (f->state != FRAME_READY) { - irq_printk("clear, skipping\n"); - /* we don't own this frame */ - continue; - } - - irq_printk("DMA\n"); - - /* check the frame begin semaphore to see if we can free the previous frame */ - if ( *(f->frame_begin_timestamp) ) { - int prev_frame; - struct frame *prev_f; - - - - /* don't reset, need this later *(f->frame_begin_timestamp) = 0; */ - irq_printk(" BEGIN\n"); - - prev_frame = frame - 1; - if (prev_frame == -1) - prev_frame += video->n_frames; - prev_f = video->frames[prev_frame]; - - /* make sure we can actually garbage collect - this frame */ - if ( (prev_f->state == FRAME_READY) && - prev_f->done && (!f->done) ) - { - frame_reset(prev_f); - video->n_clear_frames++; - wake = 1; - video->active_frame = frame; - - irq_printk(" BEGIN - freeing previous frame %d, new active frame is %d\n", prev_frame, frame); - } else { - irq_printk(" BEGIN - can't free yet\n"); - } - - f->done = 1; - } - - - /* see if we need to set the timestamp for the next frame */ - if ( *(f->mid_frame_timestamp) ) { - struct frame *next_frame; - u32 begin_ts, ts_cyc, ts_off; - - *(f->mid_frame_timestamp) = 0; - - begin_ts = le32_to_cpu(*(f->frame_begin_timestamp)); - - irq_printk(" MIDDLE - first packet was sent at cycle %4u (%2u), assigned timestamp was (%2u) %4u\n", - begin_ts & 0x1FFF, begin_ts & 0xF, - f->assigned_timestamp >> 12, f->assigned_timestamp & 0xFFF); - - /* prepare next frame and assign timestamp */ - next_frame = video->frames[ (frame+1) % video->n_frames ]; - - if (next_frame->state == FRAME_READY) { - irq_printk(" MIDDLE - next frame is ready, good\n"); - } else { - debug_printk("dv1394: Underflow! At least one frame has been dropped.\n"); - next_frame = f; - } - - /* set the timestamp to the timestamp of the last frame sent, - plus the length of the last frame sent, plus the syt latency */ - ts_cyc = begin_ts & 0xF; - /* advance one frame, plus syt latency (typically 2-3) */ - ts_cyc += f->n_packets + video->syt_offset ; - - ts_off = 0; - - ts_cyc += ts_off/3072; - ts_off %= 3072; - - next_frame->assigned_timestamp = ((ts_cyc&0xF) << 12) + ts_off; - if (next_frame->cip_syt1) { - next_frame->cip_syt1->b[6] = next_frame->assigned_timestamp >> 8; - next_frame->cip_syt1->b[7] = next_frame->assigned_timestamp & 0xFF; - } - if (next_frame->cip_syt2) { - next_frame->cip_syt2->b[6] = next_frame->assigned_timestamp >> 8; - next_frame->cip_syt2->b[7] = next_frame->assigned_timestamp & 0xFF; - } - - } - - /* see if the frame looped */ - if ( *(f->frame_end_timestamp) ) { - - *(f->frame_end_timestamp) = 0; - - debug_printk(" END - the frame looped at least once\n"); - - video->dropped_frames++; - } - - } /* for (each frame) */ - } - - if (wake) { - kill_fasync(&video->fasync, SIGIO, POLL_OUT); - - /* wake readers/writers/ioctl'ers */ - wake_up_interruptible(&video->waitq); - } - -out: - spin_unlock(&video->spinlock); -} - -static void ir_tasklet_func(unsigned long data) -{ - int wake = 0; - struct video_card *video = (struct video_card*) data; - - spin_lock(&video->spinlock); - - if (!video->dma_running) - goto out; - - if ( (video->ohci_ir_ctx != -1) && - (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) { - - int sof=0; /* start-of-frame flag */ - struct frame *f; - u16 packet_length; - int i, dbc=0; - struct DMA_descriptor_block *block = NULL; - u16 xferstatus; - - int next_i, prev_i; - struct DMA_descriptor_block *next = NULL; - dma_addr_t next_dma = 0; - struct DMA_descriptor_block *prev = NULL; - - /* loop over all descriptors in all frames */ - for (i = 0; i < video->n_frames*MAX_PACKETS; i++) { - struct packet *p = dma_region_i(&video->packet_buf, struct packet, video->current_packet); - - /* make sure we are seeing the latest changes to p */ - dma_region_sync_for_cpu(&video->packet_buf, - (unsigned long) p - (unsigned long) video->packet_buf.kvirt, - sizeof(struct packet)); - - packet_length = le16_to_cpu(p->data_length); - - /* get the descriptor based on packet_buffer cursor */ - f = video->frames[video->current_packet / MAX_PACKETS]; - block = &(f->descriptor_pool[video->current_packet % MAX_PACKETS]); - xferstatus = le32_to_cpu(block->u.in.il.q[3]) >> 16; - xferstatus &= 0x1F; - irq_printk("ir_tasklet_func: xferStatus/resCount [%d] = 0x%08x\n", i, le32_to_cpu(block->u.in.il.q[3]) ); - - /* get the current frame */ - f = video->frames[video->active_frame]; - - /* exclude empty packet */ - if (packet_length > 8 && xferstatus == 0x11) { - /* check for start of frame */ - /* DRD> Changed to check section type ([0]>>5==0) - and dif sequence ([1]>>4==0) */ - sof = ( (p->data[0] >> 5) == 0 && (p->data[1] >> 4) == 0); - - dbc = (int) (p->cip_h1 >> 24); - if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) ) - { - printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" ); - video->dropped_frames += video->n_clear_frames + 1; - video->first_frame = 0; - video->n_clear_frames = 0; - video->first_clear_frame = -1; - } - video->continuity_counter = dbc; - - if (!video->first_frame) { - if (sof) { - video->first_frame = 1; - } - - } else if (sof) { - /* close current frame */ - frame_reset(f); /* f->state = STATE_CLEAR */ - video->n_clear_frames++; - if (video->n_clear_frames > video->n_frames) { - video->dropped_frames++; - printk(KERN_WARNING "dv1394: dropped a frame during reception\n" ); - video->n_clear_frames = video->n_frames-1; - video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; - } - if (video->first_clear_frame == -1) - video->first_clear_frame = video->active_frame; - - /* get the next frame */ - video->active_frame = (video->active_frame + 1) % video->n_frames; - f = video->frames[video->active_frame]; - irq_printk(" frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n", - video->active_frame, video->n_clear_frames, video->first_clear_frame); - } - if (video->first_frame) { - if (sof) { - /* open next frame */ - f->state = FRAME_READY; - } - - /* copy to buffer */ - if (f->n_packets > (video->frame_size / 480)) { - printk(KERN_ERR "frame buffer overflow during receive\n"); - } - - frame_put_packet(f, p); - - } /* first_frame */ - } - - /* stop, end of ready packets */ - else if (xferstatus == 0) { - break; - } - - /* reset xferStatus & resCount */ - block->u.in.il.q[3] = cpu_to_le32(512); - - /* terminate dma chain at this (next) packet */ - next_i = video->current_packet; - f = video->frames[next_i / MAX_PACKETS]; - next = &(f->descriptor_pool[next_i % MAX_PACKETS]); - next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma; - next->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */ - next->u.in.il.q[2] = cpu_to_le32(0); /* disable branch */ - - /* link previous to next */ - prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1); - f = video->frames[prev_i / MAX_PACKETS]; - prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]); - if (prev_i % (MAX_PACKETS/2)) { - prev->u.in.il.q[0] &= ~cpu_to_le32(3 << 20); /* no interrupt */ - } else { - prev->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */ - } - prev->u.in.il.q[2] = cpu_to_le32(next_dma | 1); /* set Z=1 */ - wmb(); - - /* wake up DMA in case it fell asleep */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); - - /* advance packet_buffer cursor */ - video->current_packet = (video->current_packet + 1) % (MAX_PACKETS * video->n_frames); - - } /* for all packets */ - - wake = 1; /* why the hell not? */ - - } /* receive interrupt */ - - if (wake) { - kill_fasync(&video->fasync, SIGIO, POLL_IN); - - /* wake readers/writers/ioctl'ers */ - wake_up_interruptible(&video->waitq); - } - -out: - spin_unlock(&video->spinlock); -} - -static struct cdev dv1394_cdev; -static const struct file_operations dv1394_fops= -{ - .owner = THIS_MODULE, - .poll = dv1394_poll, - .unlocked_ioctl = dv1394_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = dv1394_compat_ioctl, -#endif - .mmap = dv1394_mmap, - .open = dv1394_open, - .write = dv1394_write, - .read = dv1394_read, - .release = dv1394_release, - .fasync = dv1394_fasync, - .llseek = no_llseek, -}; - - -/*** HOTPLUG STUFF **********************************************************/ -/* - * Export information about protocols/devices supported by this driver. - */ -#ifdef MODULE -static const struct ieee1394_device_id dv1394_id_table[] = { - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = AVC_SW_VERSION_ENTRY & 0xffffff - }, - { } -}; - -MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table); -#endif /* MODULE */ - -static struct hpsb_protocol_driver dv1394_driver = { - .name = "dv1394", -}; - - -/*** IEEE1394 HPSB CALLBACKS ***********************************************/ - -static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes mode) -{ - struct video_card *video; - unsigned long flags; - int i; - - video = kzalloc(sizeof(*video), GFP_KERNEL); - if (!video) { - printk(KERN_ERR "dv1394: cannot allocate video_card\n"); - return -1; - } - - video->ohci = ohci; - /* lower 2 bits of id indicate which of four "plugs" - per host */ - video->id = ohci->host->id << 2; - if (format == DV1394_NTSC) - video->id |= mode; - else - video->id |= 2 + mode; - - video->ohci_it_ctx = -1; - video->ohci_ir_ctx = -1; - - video->ohci_IsoXmitContextControlSet = 0; - video->ohci_IsoXmitContextControlClear = 0; - video->ohci_IsoXmitCommandPtr = 0; - - video->ohci_IsoRcvContextControlSet = 0; - video->ohci_IsoRcvContextControlClear = 0; - video->ohci_IsoRcvCommandPtr = 0; - video->ohci_IsoRcvContextMatch = 0; - - video->n_frames = 0; /* flag that video is not initialized */ - video->channel = 63; /* default to broadcast channel */ - video->active_frame = -1; - - /* initialize the following */ - video->pal_or_ntsc = format; - video->cip_n = 0; /* 0 = use builtin default */ - video->cip_d = 0; - video->syt_offset = 0; - video->mode = mode; - - for (i = 0; i < DV1394_MAX_FRAMES; i++) - video->frames[i] = NULL; - - dma_region_init(&video->dv_buf); - video->dv_buf_size = 0; - dma_region_init(&video->packet_buf); - video->packet_buf_size = 0; - - clear_bit(0, &video->open); - spin_lock_init(&video->spinlock); - video->dma_running = 0; - mutex_init(&video->mtx); - init_waitqueue_head(&video->waitq); - video->fasync = NULL; - - spin_lock_irqsave(&dv1394_cards_lock, flags); - INIT_LIST_HEAD(&video->list); - list_add_tail(&video->list, &dv1394_cards); - spin_unlock_irqrestore(&dv1394_cards_lock, flags); - - debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id); - return 0; -} - -static void dv1394_remove_host(struct hpsb_host *host) -{ - struct video_card *video, *tmp_video; - unsigned long flags; - int found_ohci_card = 0; - - do { - video = NULL; - spin_lock_irqsave(&dv1394_cards_lock, flags); - list_for_each_entry(tmp_video, &dv1394_cards, list) { - if ((tmp_video->id >> 2) == host->id) { - list_del(&tmp_video->list); - video = tmp_video; - found_ohci_card = 1; - break; - } - } - spin_unlock_irqrestore(&dv1394_cards_lock, flags); - - if (video) { - do_dv1394_shutdown(video, 1); - kfree(video); - } - } while (video); - - if (found_ohci_card) - device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2))); -} - -static void dv1394_add_host(struct hpsb_host *host) -{ - struct ti_ohci *ohci; - int id = host->id; - - /* We only work with the OHCI-1394 driver */ - if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) - return; - - ohci = (struct ti_ohci *)host->hostdata; - - device_create(hpsb_protocol_class, NULL, - MKDEV(IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), - NULL, "dv1394-%d", id); - - dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); - dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT); - dv1394_init(ohci, DV1394_PAL, MODE_RECEIVE); - dv1394_init(ohci, DV1394_PAL, MODE_TRANSMIT); -} - - -/* Bus reset handler. In the event of a bus reset, we may need to - re-start the DMA contexts - otherwise the user program would - end up waiting forever. -*/ - -static void dv1394_host_reset(struct hpsb_host *host) -{ - struct video_card *video = NULL, *tmp_vid; - unsigned long flags; - - /* We only work with the OHCI-1394 driver */ - if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) - return; - - /* find the corresponding video_cards */ - spin_lock_irqsave(&dv1394_cards_lock, flags); - list_for_each_entry(tmp_vid, &dv1394_cards, list) { - if ((tmp_vid->id >> 2) == host->id) { - video = tmp_vid; - break; - } - } - spin_unlock_irqrestore(&dv1394_cards_lock, flags); - - if (!video) - return; - - - spin_lock_irqsave(&video->spinlock, flags); - - if (!video->dma_running) - goto out; - - /* check IT context */ - if (video->ohci_it_ctx != -1) { - u32 ctx; - - ctx = reg_read(video->ohci, video->ohci_IsoXmitContextControlSet); - - /* if (RUN but not ACTIVE) */ - if ( (ctx & (1<<15)) && - !(ctx & (1<<10)) ) { - - debug_printk("dv1394: IT context stopped due to bus reset; waking it up\n"); - - /* to be safe, assume a frame has been dropped. User-space programs - should handle this condition like an underflow. */ - video->dropped_frames++; - - /* for some reason you must clear, then re-set the RUN bit to restart DMA */ - - /* clear RUN */ - reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, (1 << 15)); - flush_pci_write(video->ohci); - - /* set RUN */ - reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, (1 << 15)); - flush_pci_write(video->ohci); - - /* set the WAKE bit (just in case; this isn't strictly necessary) */ - reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, (1 << 12)); - flush_pci_write(video->ohci); - - irq_printk("dv1394: AFTER IT restart ctx 0x%08x ptr 0x%08x\n", - reg_read(video->ohci, video->ohci_IsoXmitContextControlSet), - reg_read(video->ohci, video->ohci_IsoXmitCommandPtr)); - } - } - - /* check IR context */ - if (video->ohci_ir_ctx != -1) { - u32 ctx; - - ctx = reg_read(video->ohci, video->ohci_IsoRcvContextControlSet); - - /* if (RUN but not ACTIVE) */ - if ( (ctx & (1<<15)) && - !(ctx & (1<<10)) ) { - - debug_printk("dv1394: IR context stopped due to bus reset; waking it up\n"); - - /* to be safe, assume a frame has been dropped. User-space programs - should handle this condition like an overflow. */ - video->dropped_frames++; - - /* for some reason you must clear, then re-set the RUN bit to restart DMA */ - /* XXX this doesn't work for me, I can't get IR DMA to restart :[ */ - - /* clear RUN */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, (1 << 15)); - flush_pci_write(video->ohci); - - /* set RUN */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 15)); - flush_pci_write(video->ohci); - - /* set the WAKE bit (just in case; this isn't strictly necessary) */ - reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12)); - flush_pci_write(video->ohci); - - irq_printk("dv1394: AFTER IR restart ctx 0x%08x ptr 0x%08x\n", - reg_read(video->ohci, video->ohci_IsoRcvContextControlSet), - reg_read(video->ohci, video->ohci_IsoRcvCommandPtr)); - } - } - -out: - spin_unlock_irqrestore(&video->spinlock, flags); - - /* wake readers/writers/ioctl'ers */ - wake_up_interruptible(&video->waitq); -} - -static struct hpsb_highlevel dv1394_highlevel = { - .name = "dv1394", - .add_host = dv1394_add_host, - .remove_host = dv1394_remove_host, - .host_reset = dv1394_host_reset, -}; - -#ifdef CONFIG_COMPAT - -#define DV1394_IOC32_INIT _IOW('#', 0x06, struct dv1394_init32) -#define DV1394_IOC32_GET_STATUS _IOR('#', 0x0c, struct dv1394_status32) - -struct dv1394_init32 { - u32 api_version; - u32 channel; - u32 n_frames; - u32 format; - u32 cip_n; - u32 cip_d; - u32 syt_offset; -}; - -struct dv1394_status32 { - struct dv1394_init32 init; - s32 active_frame; - u32 first_clear_frame; - u32 n_clear_frames; - u32 dropped_frames; -}; - -/* RED-PEN: this should use compat_alloc_userspace instead */ - -static int handle_dv1394_init(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct dv1394_init32 dv32; - struct dv1394_init dv; - mm_segment_t old_fs; - int ret; - - if (file->f_op->unlocked_ioctl != dv1394_ioctl) - return -EFAULT; - - if (copy_from_user(&dv32, (void __user *)arg, sizeof(dv32))) - return -EFAULT; - - dv.api_version = dv32.api_version; - dv.channel = dv32.channel; - dv.n_frames = dv32.n_frames; - dv.format = dv32.format; - dv.cip_n = (unsigned long)dv32.cip_n; - dv.cip_d = (unsigned long)dv32.cip_d; - dv.syt_offset = dv32.syt_offset; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = dv1394_ioctl(file, DV1394_IOC_INIT, (unsigned long)&dv); - set_fs(old_fs); - - return ret; -} - -static int handle_dv1394_get_status(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct dv1394_status32 dv32; - struct dv1394_status dv; - mm_segment_t old_fs; - int ret; - - if (file->f_op->unlocked_ioctl != dv1394_ioctl) - return -EFAULT; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = dv1394_ioctl(file, DV1394_IOC_GET_STATUS, (unsigned long)&dv); - set_fs(old_fs); - - if (!ret) { - dv32.init.api_version = dv.init.api_version; - dv32.init.channel = dv.init.channel; - dv32.init.n_frames = dv.init.n_frames; - dv32.init.format = dv.init.format; - dv32.init.cip_n = (u32)dv.init.cip_n; - dv32.init.cip_d = (u32)dv.init.cip_d; - dv32.init.syt_offset = dv.init.syt_offset; - dv32.active_frame = dv.active_frame; - dv32.first_clear_frame = dv.first_clear_frame; - dv32.n_clear_frames = dv.n_clear_frames; - dv32.dropped_frames = dv.dropped_frames; - - if (copy_to_user((struct dv1394_status32 __user *)arg, &dv32, sizeof(dv32))) - ret = -EFAULT; - } - - return ret; -} - - - -static long dv1394_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - switch (cmd) { - case DV1394_IOC_SHUTDOWN: - case DV1394_IOC_SUBMIT_FRAMES: - case DV1394_IOC_WAIT_FRAMES: - case DV1394_IOC_RECEIVE_FRAMES: - case DV1394_IOC_START_RECEIVE: - return dv1394_ioctl(file, cmd, arg); - - case DV1394_IOC32_INIT: - return handle_dv1394_init(file, cmd, arg); - case DV1394_IOC32_GET_STATUS: - return handle_dv1394_get_status(file, cmd, arg); - default: - return -ENOIOCTLCMD; - } -} - -#endif /* CONFIG_COMPAT */ - - -/*** KERNEL MODULE HANDLERS ************************************************/ - -MODULE_AUTHOR("Dan Maas <dmaas@dcine.com>, Dan Dennedy <dan@dennedy.org>"); -MODULE_DESCRIPTION("driver for DV input/output on OHCI board"); -MODULE_SUPPORTED_DEVICE("dv1394"); -MODULE_LICENSE("GPL"); - -static void __exit dv1394_exit_module(void) -{ - hpsb_unregister_protocol(&dv1394_driver); - hpsb_unregister_highlevel(&dv1394_highlevel); - cdev_del(&dv1394_cdev); -} - -static int __init dv1394_init_module(void) -{ - int ret; - - cdev_init(&dv1394_cdev, &dv1394_fops); - dv1394_cdev.owner = THIS_MODULE; - ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16); - if (ret) { - printk(KERN_ERR "dv1394: unable to register character device\n"); - return ret; - } - - hpsb_register_highlevel(&dv1394_highlevel); - - ret = hpsb_register_protocol(&dv1394_driver); - if (ret) { - printk(KERN_ERR "dv1394: failed to register protocol\n"); - hpsb_unregister_highlevel(&dv1394_highlevel); - cdev_del(&dv1394_cdev); - return ret; - } - - return 0; -} - -module_init(dv1394_init_module); -module_exit(dv1394_exit_module); diff --git a/drivers/ieee1394/dv1394.h b/drivers/ieee1394/dv1394.h deleted file mode 100644 index 5807f52..0000000 --- a/drivers/ieee1394/dv1394.h +++ /dev/null @@ -1,305 +0,0 @@ -/* - * 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 */ diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c deleted file mode 100644 index 6340382..0000000 --- a/drivers/ieee1394/eth1394.c +++ /dev/null @@ -1,1720 +0,0 @@ -/* - * eth1394.c -- IPv4 driver for Linux IEEE-1394 Subsystem - * - * Copyright (C) 2001-2003 Ben Collins <bcollins@debian.org> - * 2000 Bonin Franck <boninf@free.fr> - * 2003 Steve Kinneberg <kinnebergsteve@acmsystems.com> - * - * Mainly based on work by Emanuel Pirker and Andreas E. Bombe - * - * 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. - */ - -/* - * This driver intends to support RFC 2734, which describes a method for - * transporting IPv4 datagrams over IEEE-1394 serial busses. - * - * TODO: - * RFC 2734 related: - * - Add MCAP. Limited Multicast exists only to 224.0.0.1 and 224.0.0.2. - * - * Non-RFC 2734 related: - * - Handle fragmented skb's coming from the networking layer. - * - Move generic GASP reception to core 1394 code - * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead - * - Stability improvements - * - Performance enhancements - * - Consider garbage collecting old partial datagrams after X amount of time - */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/workqueue.h> - -#include <linux/netdevice.h> -#include <linux/inetdevice.h> -#include <linux/if_arp.h> -#include <linux/if_ether.h> -#include <linux/ip.h> -#include <linux/in.h> -#include <linux/tcp.h> -#include <linux/skbuff.h> -#include <linux/bitops.h> -#include <asm/uaccess.h> -#include <asm/delay.h> -#include <asm/unaligned.h> -#include <net/arp.h> - -#include "config_roms.h" -#include "csr1212.h" -#include "eth1394.h" -#include "highlevel.h" -#include "ieee1394.h" -#include "ieee1394_core.h" -#include "ieee1394_hotplug.h" -#include "ieee1394_transactions.h" -#include "ieee1394_types.h" -#include "iso.h" -#include "nodemgr.h" - -#define ETH1394_PRINT_G(level, fmt, args...) \ - printk(level "%s: " fmt, driver_name, ## args) - -#define ETH1394_PRINT(level, dev_name, fmt, args...) \ - printk(level "%s: %s: " fmt, driver_name, dev_name, ## args) - -struct fragment_info { - struct list_head list; - int offset; - int len; -}; - -struct partial_datagram { - struct list_head list; - u16 dgl; - u16 dg_size; - __be16 ether_type; - struct sk_buff *skb; - char *pbuf; - struct list_head frag_info; -}; - -struct pdg_list { - struct list_head list; /* partial datagram list per node */ - unsigned int sz; /* partial datagram list size per node */ - spinlock_t lock; /* partial datagram lock */ -}; - -struct eth1394_host_info { - struct hpsb_host *host; - struct net_device *dev; -}; - -struct eth1394_node_ref { - struct unit_directory *ud; - struct list_head list; -}; - -struct eth1394_node_info { - u16 maxpayload; /* max payload */ - u8 sspd; /* max speed */ - u64 fifo; /* FIFO address */ - struct pdg_list pdg; /* partial RX datagram lists */ - int dgl; /* outgoing datagram label */ -}; - -static const char driver_name[] = "eth1394"; - -static struct kmem_cache *packet_task_cache; - -static struct hpsb_highlevel eth1394_highlevel; - -/* Use common.lf to determine header len */ -static const int hdr_type_len[] = { - sizeof(struct eth1394_uf_hdr), - sizeof(struct eth1394_ff_hdr), - sizeof(struct eth1394_sf_hdr), - sizeof(struct eth1394_sf_hdr) -}; - -static const u16 eth1394_speedto_maxpayload[] = { -/* S100, S200, S400, S800, S1600, S3200 */ - 512, 1024, 2048, 4096, 4096, 4096 -}; - -MODULE_AUTHOR("Ben Collins (bcollins@debian.org)"); -MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)"); -MODULE_LICENSE("GPL"); - -/* - * The max_partial_datagrams parameter is the maximum number of fragmented - * datagrams per node that eth1394 will keep in memory. Providing an upper - * bound allows us to limit the amount of memory that partial datagrams - * consume in the event that some partial datagrams are never completed. - */ -static int max_partial_datagrams = 25; -module_param(max_partial_datagrams, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(max_partial_datagrams, - "Maximum number of partially received fragmented datagrams " - "(default = 25)."); - - -static int ether1394_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, const void *daddr, - const void *saddr, unsigned len); -static int ether1394_rebuild_header(struct sk_buff *skb); -static int ether1394_header_parse(const struct sk_buff *skb, - unsigned char *haddr); -static int ether1394_header_cache(const struct neighbour *neigh, - struct hh_cache *hh); -static void ether1394_header_cache_update(struct hh_cache *hh, - const struct net_device *dev, - const unsigned char *haddr); -static netdev_tx_t ether1394_tx(struct sk_buff *skb, - struct net_device *dev); -static void ether1394_iso(struct hpsb_iso *iso); - -static int ether1394_write(struct hpsb_host *host, int srcid, int destid, - quadlet_t *data, u64 addr, size_t len, u16 flags); -static void ether1394_add_host(struct hpsb_host *host); -static void ether1394_remove_host(struct hpsb_host *host); -static void ether1394_host_reset(struct hpsb_host *host); - -/* Function for incoming 1394 packets */ -static const struct hpsb_address_ops addr_ops = { - .write = ether1394_write, -}; - -/* Ieee1394 highlevel driver functions */ -static struct hpsb_highlevel eth1394_highlevel = { - .name = driver_name, - .add_host = ether1394_add_host, - .remove_host = ether1394_remove_host, - .host_reset = ether1394_host_reset, -}; - -static int ether1394_recv_init(struct eth1394_priv *priv) -{ - unsigned int iso_buf_size; - - /* FIXME: rawiso limits us to PAGE_SIZE */ - iso_buf_size = min((unsigned int)PAGE_SIZE, - 2 * (1U << (priv->host->csr.max_rec + 1))); - - priv->iso = hpsb_iso_recv_init(priv->host, - ETHER1394_GASP_BUFFERS * iso_buf_size, - ETHER1394_GASP_BUFFERS, - priv->broadcast_channel, - HPSB_ISO_DMA_PACKET_PER_BUFFER, - 1, ether1394_iso); - if (priv->iso == NULL) { - ETH1394_PRINT_G(KERN_ERR, "Failed to allocate IR context\n"); - priv->bc_state = ETHER1394_BC_ERROR; - return -EAGAIN; - } - - if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) - priv->bc_state = ETHER1394_BC_STOPPED; - else - priv->bc_state = ETHER1394_BC_RUNNING; - return 0; -} - -/* This is called after an "ifup" */ -static int ether1394_open(struct net_device *dev) -{ - struct eth1394_priv *priv = netdev_priv(dev); - int ret; - - if (priv->bc_state == ETHER1394_BC_ERROR) { - ret = ether1394_recv_init(priv); - if (ret) - return ret; - } - netif_start_queue(dev); - return 0; -} - -/* This is called after an "ifdown" */ -static int ether1394_stop(struct net_device *dev) -{ - /* flush priv->wake */ - flush_scheduled_work(); - - netif_stop_queue(dev); - return 0; -} - -/* FIXME: What to do if we timeout? I think a host reset is probably in order, - * so that's what we do. Should we increment the stat counters too? */ -static void ether1394_tx_timeout(struct net_device *dev) -{ - struct hpsb_host *host = - ((struct eth1394_priv *)netdev_priv(dev))->host; - - ETH1394_PRINT(KERN_ERR, dev->name, "Timeout, resetting host\n"); - ether1394_host_reset(host); -} - -static inline int ether1394_max_mtu(struct hpsb_host* host) -{ - return (1 << (host->csr.max_rec + 1)) - - sizeof(union eth1394_hdr) - ETHER1394_GASP_OVERHEAD; -} - -static int ether1394_change_mtu(struct net_device *dev, int new_mtu) -{ - int max_mtu; - - if (new_mtu < 68) - return -EINVAL; - - max_mtu = ether1394_max_mtu( - ((struct eth1394_priv *)netdev_priv(dev))->host); - if (new_mtu > max_mtu) { - ETH1394_PRINT(KERN_INFO, dev->name, - "Local node constrains MTU to %d\n", max_mtu); - return -ERANGE; - } - - dev->mtu = new_mtu; - return 0; -} - -static void purge_partial_datagram(struct list_head *old) -{ - struct partial_datagram *pd; - struct list_head *lh, *n; - struct fragment_info *fi; - - pd = list_entry(old, struct partial_datagram, list); - - list_for_each_safe(lh, n, &pd->frag_info) { - fi = list_entry(lh, struct fragment_info, list); - list_del(lh); - kfree(fi); - } - list_del(old); - kfree_skb(pd->skb); - kfree(pd); -} - -/****************************************** - * 1394 bus activity functions - ******************************************/ - -static struct eth1394_node_ref *eth1394_find_node(struct list_head *inl, - struct unit_directory *ud) -{ - struct eth1394_node_ref *node; - - list_for_each_entry(node, inl, list) - if (node->ud == ud) - return node; - - return NULL; -} - -static struct eth1394_node_ref *eth1394_find_node_guid(struct list_head *inl, - u64 guid) -{ - struct eth1394_node_ref *node; - - list_for_each_entry(node, inl, list) - if (node->ud->ne->guid == guid) - return node; - - return NULL; -} - -static struct eth1394_node_ref *eth1394_find_node_nodeid(struct list_head *inl, - nodeid_t nodeid) -{ - struct eth1394_node_ref *node; - - list_for_each_entry(node, inl, list) - if (node->ud->ne->nodeid == nodeid) - return node; - - return NULL; -} - -static int eth1394_new_node(struct eth1394_host_info *hi, - struct unit_directory *ud) -{ - struct eth1394_priv *priv; - struct eth1394_node_ref *new_node; - struct eth1394_node_info *node_info; - - new_node = kmalloc(sizeof(*new_node), GFP_KERNEL); - if (!new_node) - return -ENOMEM; - - node_info = kmalloc(sizeof(*node_info), GFP_KERNEL); - if (!node_info) { - kfree(new_node); - return -ENOMEM; - } - - spin_lock_init(&node_info->pdg.lock); - INIT_LIST_HEAD(&node_info->pdg.list); - node_info->pdg.sz = 0; - node_info->fifo = CSR1212_INVALID_ADDR_SPACE; - - dev_set_drvdata(&ud->device, node_info); - new_node->ud = ud; - - priv = netdev_priv(hi->dev); - list_add_tail(&new_node->list, &priv->ip_node_list); - return 0; -} - -static int eth1394_probe(struct device *dev) -{ - struct unit_directory *ud; - struct eth1394_host_info *hi; - - ud = container_of(dev, struct unit_directory, device); - hi = hpsb_get_hostinfo(ð1394_highlevel, ud->ne->host); - if (!hi) - return -ENOENT; - - return eth1394_new_node(hi, ud); -} - -static int eth1394_remove(struct device *dev) -{ - struct unit_directory *ud; - struct eth1394_host_info *hi; - struct eth1394_priv *priv; - struct eth1394_node_ref *old_node; - struct eth1394_node_info *node_info; - struct list_head *lh, *n; - unsigned long flags; - - ud = container_of(dev, struct unit_directory, device); - hi = hpsb_get_hostinfo(ð1394_highlevel, ud->ne->host); - if (!hi) - return -ENOENT; - - priv = netdev_priv(hi->dev); - - old_node = eth1394_find_node(&priv->ip_node_list, ud); - if (!old_node) - return 0; - - list_del(&old_node->list); - kfree(old_node); - - node_info = dev_get_drvdata(&ud->device); - - spin_lock_irqsave(&node_info->pdg.lock, flags); - /* The partial datagram list should be empty, but we'll just - * make sure anyway... */ - list_for_each_safe(lh, n, &node_info->pdg.list) - purge_partial_datagram(lh); - spin_unlock_irqrestore(&node_info->pdg.lock, flags); - - kfree(node_info); - dev_set_drvdata(&ud->device, NULL); - return 0; -} - -static int eth1394_update(struct unit_directory *ud) -{ - struct eth1394_host_info *hi; - struct eth1394_priv *priv; - struct eth1394_node_ref *node; - - hi = hpsb_get_hostinfo(ð1394_highlevel, ud->ne->host); - if (!hi) - return -ENOENT; - - priv = netdev_priv(hi->dev); - node = eth1394_find_node(&priv->ip_node_list, ud); - if (node) - return 0; - - return eth1394_new_node(hi, ud); -} - -static const struct ieee1394_device_id eth1394_id_table[] = { - { - .match_flags = (IEEE1394_MATCH_SPECIFIER_ID | - IEEE1394_MATCH_VERSION), - .specifier_id = ETHER1394_GASP_SPECIFIER_ID, - .version = ETHER1394_GASP_VERSION, - }, - {} -}; - -MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table); - -static struct hpsb_protocol_driver eth1394_proto_driver = { - .name = driver_name, - .id_table = eth1394_id_table, - .update = eth1394_update, - .driver = { - .probe = eth1394_probe, - .remove = eth1394_remove, - }, -}; - -static void ether1394_reset_priv(struct net_device *dev, int set_mtu) -{ - unsigned long flags; - int i; - struct eth1394_priv *priv = netdev_priv(dev); - struct hpsb_host *host = priv->host; - u64 guid = get_unaligned((u64 *)&(host->csr.rom->bus_info_data[3])); - int max_speed = IEEE1394_SPEED_MAX; - - spin_lock_irqsave(&priv->lock, flags); - - memset(priv->ud_list, 0, sizeof(priv->ud_list)); - priv->bc_maxpayload = 512; - - /* Determine speed limit */ - /* FIXME: This is broken for nodes with link speed < PHY speed, - * and it is suboptimal for S200B...S800B hardware. - * The result of nodemgr's speed probe should be used somehow. */ - for (i = 0; i < host->node_count; i++) { - /* take care of S100B...S400B PHY ports */ - if (host->speed[i] == SELFID_SPEED_UNKNOWN) { - max_speed = IEEE1394_SPEED_100; - break; - } - if (max_speed > host->speed[i]) - max_speed = host->speed[i]; - } - priv->bc_sspd = max_speed; - - if (set_mtu) { - /* Use the RFC 2734 default 1500 octets or the maximum payload - * as initial MTU */ - dev->mtu = min(1500, ether1394_max_mtu(host)); - - /* Set our hardware address while we're at it */ - memcpy(dev->dev_addr, &guid, sizeof(u64)); - memset(dev->broadcast, 0xff, sizeof(u64)); - } - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static const struct header_ops ether1394_header_ops = { - .create = ether1394_header, - .rebuild = ether1394_rebuild_header, - .cache = ether1394_header_cache, - .cache_update = ether1394_header_cache_update, - .parse = ether1394_header_parse, -}; - -static const struct net_device_ops ether1394_netdev_ops = { - .ndo_open = ether1394_open, - .ndo_stop = ether1394_stop, - .ndo_start_xmit = ether1394_tx, - .ndo_tx_timeout = ether1394_tx_timeout, - .ndo_change_mtu = ether1394_change_mtu, -}; - -static void ether1394_init_dev(struct net_device *dev) -{ - - dev->header_ops = ðer1394_header_ops; - dev->netdev_ops = ðer1394_netdev_ops; - - dev->watchdog_timeo = ETHER1394_TIMEOUT; - dev->flags = IFF_BROADCAST | IFF_MULTICAST; - dev->features = NETIF_F_HIGHDMA; - dev->addr_len = ETH1394_ALEN; - dev->hard_header_len = ETH1394_HLEN; - dev->type = ARPHRD_IEEE1394; - - /* FIXME: This value was copied from ether_setup(). Is it too much? */ - dev->tx_queue_len = 1000; -} - -/* - * Wake the queue up after commonly encountered transmit failure conditions are - * hopefully over. Currently only tlabel exhaustion is accounted for. - */ -static void ether1394_wake_queue(struct work_struct *work) -{ - struct eth1394_priv *priv; - struct hpsb_packet *packet; - - priv = container_of(work, struct eth1394_priv, wake); - packet = hpsb_alloc_packet(0); - - /* This is really bad, but unjam the queue anyway. */ - if (!packet) - goto out; - - packet->host = priv->host; - packet->node_id = priv->wake_node; - /* - * A transaction label is all we really want. If we get one, it almost - * always means we can get a lot more because the ieee1394 core recycled - * a whole batch of tlabels, at last. - */ - if (hpsb_get_tlabel(packet) == 0) - hpsb_free_tlabel(packet); - - hpsb_free_packet(packet); -out: - netif_wake_queue(priv->wake_dev); -} - -/* - * This function is called every time a card is found. It is generally called - * when the module is installed. This is where we add all of our ethernet - * devices. One for each host. - */ -static void ether1394_add_host(struct hpsb_host *host) -{ - struct eth1394_host_info *hi = NULL; - struct net_device *dev = NULL; - struct eth1394_priv *priv; - u64 fifo_addr; - - if (hpsb_config_rom_ip1394_add(host) != 0) { - ETH1394_PRINT_G(KERN_ERR, "Can't add IP-over-1394 ROM entry\n"); - return; - } - - fifo_addr = hpsb_allocate_and_register_addrspace( - ð1394_highlevel, host, &addr_ops, - ETHER1394_REGION_ADDR_LEN, ETHER1394_REGION_ADDR_LEN, - CSR1212_INVALID_ADDR_SPACE, CSR1212_INVALID_ADDR_SPACE); - if (fifo_addr == CSR1212_INVALID_ADDR_SPACE) { - ETH1394_PRINT_G(KERN_ERR, "Cannot register CSR space\n"); - hpsb_config_rom_ip1394_remove(host); - return; - } - - dev = alloc_netdev(sizeof(*priv), "eth%d", ether1394_init_dev); - if (dev == NULL) { - ETH1394_PRINT_G(KERN_ERR, "Out of memory\n"); - goto out; - } - - SET_NETDEV_DEV(dev, &host->device); - - priv = netdev_priv(dev); - INIT_LIST_HEAD(&priv->ip_node_list); - spin_lock_init(&priv->lock); - priv->host = host; - priv->local_fifo = fifo_addr; - INIT_WORK(&priv->wake, ether1394_wake_queue); - priv->wake_dev = dev; - - hi = hpsb_create_hostinfo(ð1394_highlevel, host, sizeof(*hi)); - if (hi == NULL) { - ETH1394_PRINT_G(KERN_ERR, "Out of memory\n"); - goto out; - } - - ether1394_reset_priv(dev, 1); - - if (register_netdev(dev)) { - ETH1394_PRINT_G(KERN_ERR, "Cannot register the driver\n"); - goto out; - } - - ETH1394_PRINT(KERN_INFO, dev->name, "IPv4 over IEEE 1394 (fw-host%d)\n", - host->id); - - hi->host = host; - hi->dev = dev; - - /* Ignore validity in hopes that it will be set in the future. It'll - * be checked when the eth device is opened. */ - priv->broadcast_channel = host->csr.broadcast_channel & 0x3f; - - ether1394_recv_init(priv); - return; -out: - if (dev) - free_netdev(dev); - if (hi) - hpsb_destroy_hostinfo(ð1394_highlevel, host); - hpsb_unregister_addrspace(ð1394_highlevel, host, fifo_addr); - hpsb_config_rom_ip1394_remove(host); -} - -/* Remove a card from our list */ -static void ether1394_remove_host(struct hpsb_host *host) -{ - struct eth1394_host_info *hi; - struct eth1394_priv *priv; - - hi = hpsb_get_hostinfo(ð1394_highlevel, host); - if (!hi) - return; - priv = netdev_priv(hi->dev); - hpsb_unregister_addrspace(ð1394_highlevel, host, priv->local_fifo); - hpsb_config_rom_ip1394_remove(host); - if (priv->iso) - hpsb_iso_shutdown(priv->iso); - unregister_netdev(hi->dev); - free_netdev(hi->dev); -} - -/* A bus reset happened */ -static void ether1394_host_reset(struct hpsb_host *host) -{ - struct eth1394_host_info *hi; - struct eth1394_priv *priv; - struct net_device *dev; - struct list_head *lh, *n; - struct eth1394_node_ref *node; - struct eth1394_node_info *node_info; - unsigned long flags; - - hi = hpsb_get_hostinfo(ð1394_highlevel, host); - - /* This can happen for hosts that we don't use */ - if (!hi) - return; - - dev = hi->dev; - priv = netdev_priv(dev); - - /* Reset our private host data, but not our MTU */ - netif_stop_queue(dev); - ether1394_reset_priv(dev, 0); - - list_for_each_entry(node, &priv->ip_node_list, list) { - node_info = dev_get_drvdata(&node->ud->device); - - spin_lock_irqsave(&node_info->pdg.lock, flags); - - list_for_each_safe(lh, n, &node_info->pdg.list) - purge_partial_datagram(lh); - - INIT_LIST_HEAD(&(node_info->pdg.list)); - node_info->pdg.sz = 0; - - spin_unlock_irqrestore(&node_info->pdg.lock, flags); - } - - netif_wake_queue(dev); -} - -/****************************************** - * HW Header net device functions - ******************************************/ -/* These functions have been adapted from net/ethernet/eth.c */ - -/* Create a fake MAC header for an arbitrary protocol layer. - * saddr=NULL means use device source address - * daddr=NULL means leave destination address (eg unresolved arp). */ -static int ether1394_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, const void *daddr, - const void *saddr, unsigned len) -{ - struct eth1394hdr *eth = - (struct eth1394hdr *)skb_push(skb, ETH1394_HLEN); - - eth->h_proto = htons(type); - - if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - memset(eth->h_dest, 0, dev->addr_len); - return dev->hard_header_len; - } - - if (daddr) { - memcpy(eth->h_dest, daddr, dev->addr_len); - return dev->hard_header_len; - } - - return -dev->hard_header_len; -} - -/* Rebuild the faked MAC header. This is called after an ARP - * (or in future other address resolution) has completed on this - * sk_buff. We now let ARP fill in the other fields. - * - * This routine CANNOT use cached dst->neigh! - * Really, it is used only when dst->neigh is wrong. - */ -static int ether1394_rebuild_header(struct sk_buff *skb) -{ - struct eth1394hdr *eth = (struct eth1394hdr *)skb->data; - - if (eth->h_proto == htons(ETH_P_IP)) - return arp_find((unsigned char *)ð->h_dest, skb); - - ETH1394_PRINT(KERN_DEBUG, skb->dev->name, - "unable to resolve type %04x addresses\n", - ntohs(eth->h_proto)); - return 0; -} - -static int ether1394_header_parse(const struct sk_buff *skb, - unsigned char *haddr) -{ - memcpy(haddr, skb->dev->dev_addr, ETH1394_ALEN); - return ETH1394_ALEN; -} - -static int ether1394_header_cache(const struct neighbour *neigh, - struct hh_cache *hh) -{ - __be16 type = hh->hh_type; - struct net_device *dev = neigh->dev; - struct eth1394hdr *eth = - (struct eth1394hdr *)((u8 *)hh->hh_data + 16 - ETH1394_HLEN); - - if (type == htons(ETH_P_802_3)) - return -1; - - eth->h_proto = type; - memcpy(eth->h_dest, neigh->ha, dev->addr_len); - - hh->hh_len = ETH1394_HLEN; - return 0; -} - -/* Called by Address Resolution module to notify changes in address. */ -static void ether1394_header_cache_update(struct hh_cache *hh, - const struct net_device *dev, - const unsigned char * haddr) -{ - memcpy((u8 *)hh->hh_data + 16 - ETH1394_HLEN, haddr, dev->addr_len); -} - -/****************************************** - * Datagram reception code - ******************************************/ - -/* Copied from net/ethernet/eth.c */ -static __be16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev) -{ - struct eth1394hdr *eth; - unsigned char *rawp; - - skb_reset_mac_header(skb); - skb_pull(skb, ETH1394_HLEN); - eth = eth1394_hdr(skb); - - if (*eth->h_dest & 1) { - if (memcmp(eth->h_dest, dev->broadcast, dev->addr_len) == 0) - skb->pkt_type = PACKET_BROADCAST; -#if 0 - else - skb->pkt_type = PACKET_MULTICAST; -#endif - } else { - if (memcmp(eth->h_dest, dev->dev_addr, dev->addr_len)) - skb->pkt_type = PACKET_OTHERHOST; - } - - if (ntohs(eth->h_proto) >= 1536) - return eth->h_proto; - - rawp = skb->data; - - if (*(unsigned short *)rawp == 0xFFFF) - return htons(ETH_P_802_3); - - return htons(ETH_P_802_2); -} - -/* Parse an encapsulated IP1394 header into an ethernet frame packet. - * We also perform ARP translation here, if need be. */ -static __be16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev, - nodeid_t srcid, nodeid_t destid, - __be16 ether_type) -{ - struct eth1394_priv *priv = netdev_priv(dev); - __be64 dest_hw; - __be16 ret = 0; - - /* Setup our hw addresses. We use these to build the ethernet header. */ - if (destid == (LOCAL_BUS | ALL_NODES)) - dest_hw = ~cpu_to_be64(0); /* broadcast */ - else - dest_hw = cpu_to_be64((u64)priv->host->csr.guid_hi << 32 | - priv->host->csr.guid_lo); - - /* If this is an ARP packet, convert it. First, we want to make - * use of some of the fields, since they tell us a little bit - * about the sending machine. */ - if (ether_type == htons(ETH_P_ARP)) { - struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data; - struct arphdr *arp = (struct arphdr *)skb->data; - unsigned char *arp_ptr = (unsigned char *)(arp + 1); - u64 fifo_addr = (u64)ntohs(arp1394->fifo_hi) << 32 | - ntohl(arp1394->fifo_lo); - u8 max_rec = min(priv->host->csr.max_rec, - (u8)(arp1394->max_rec)); - int sspd = arp1394->sspd; - u16 maxpayload; - struct eth1394_node_ref *node; - struct eth1394_node_info *node_info; - __be64 guid; - - /* Sanity check. MacOSX seems to be sending us 131 in this - * field (atleast on my Panther G5). Not sure why. */ - if (sspd > 5 || sspd < 0) - sspd = 0; - - maxpayload = min(eth1394_speedto_maxpayload[sspd], - (u16)(1 << (max_rec + 1))); - - guid = get_unaligned(&arp1394->s_uniq_id); - node = eth1394_find_node_guid(&priv->ip_node_list, - be64_to_cpu(guid)); - if (!node) - return cpu_to_be16(0); - - node_info = dev_get_drvdata(&node->ud->device); - - /* Update our speed/payload/fifo_offset table */ - node_info->maxpayload = maxpayload; - node_info->sspd = sspd; - node_info->fifo = fifo_addr; - - /* Now that we're done with the 1394 specific stuff, we'll - * need to alter some of the data. Believe it or not, all - * that needs to be done is sender_IP_address needs to be - * moved, the destination hardware address get stuffed - * in and the hardware address length set to 8. - * - * IMPORTANT: The code below overwrites 1394 specific data - * needed above so keep the munging of the data for the - * higher level IP stack last. */ - - arp->ar_hln = 8; - arp_ptr += arp->ar_hln; /* skip over sender unique id */ - *(u32 *)arp_ptr = arp1394->sip; /* move sender IP addr */ - arp_ptr += arp->ar_pln; /* skip over sender IP addr */ - - if (arp->ar_op == htons(ARPOP_REQUEST)) - memset(arp_ptr, 0, sizeof(u64)); - else - memcpy(arp_ptr, dev->dev_addr, sizeof(u64)); - } - - /* Now add the ethernet header. */ - if (dev_hard_header(skb, dev, ntohs(ether_type), &dest_hw, NULL, - skb->len) >= 0) - ret = ether1394_type_trans(skb, dev); - - return ret; -} - -static int fragment_overlap(struct list_head *frag_list, int offset, int len) -{ - struct fragment_info *fi; - int end = offset + len; - - list_for_each_entry(fi, frag_list, list) - if (offset < fi->offset + fi->len && end > fi->offset) - return 1; - - return 0; -} - -static struct list_head *find_partial_datagram(struct list_head *pdgl, int dgl) -{ - struct partial_datagram *pd; - - list_for_each_entry(pd, pdgl, list) - if (pd->dgl == dgl) - return &pd->list; - - return NULL; -} - -/* Assumes that new fragment does not overlap any existing fragments */ -static int new_fragment(struct list_head *frag_info, int offset, int len) -{ - struct list_head *lh; - struct fragment_info *fi, *fi2, *new; - - list_for_each(lh, frag_info) { - fi = list_entry(lh, struct fragment_info, list); - if (fi->offset + fi->len == offset) { - /* The new fragment can be tacked on to the end */ - fi->len += len; - /* Did the new fragment plug a hole? */ - fi2 = list_entry(lh->next, struct fragment_info, list); - if (fi->offset + fi->len == fi2->offset) { - /* glue fragments together */ - fi->len += fi2->len; - list_del(lh->next); - kfree(fi2); - } - return 0; - } else if (offset + len == fi->offset) { - /* The new fragment can be tacked on to the beginning */ - fi->offset = offset; - fi->len += len; - /* Did the new fragment plug a hole? */ - fi2 = list_entry(lh->prev, struct fragment_info, list); - if (fi2->offset + fi2->len == fi->offset) { - /* glue fragments together */ - fi2->len += fi->len; - list_del(lh); - kfree(fi); - } - return 0; - } else if (offset > fi->offset + fi->len) { - break; - } else if (offset + len < fi->offset) { - lh = lh->prev; - break; - } - } - - new = kmalloc(sizeof(*new), GFP_ATOMIC); - if (!new) - return -ENOMEM; - - new->offset = offset; - new->len = len; - - list_add(&new->list, lh); - return 0; -} - -static int new_partial_datagram(struct net_device *dev, struct list_head *pdgl, - int dgl, int dg_size, char *frag_buf, - int frag_off, int frag_len) -{ - struct partial_datagram *new; - - new = kmalloc(sizeof(*new), GFP_ATOMIC); - if (!new) - return -ENOMEM; - - INIT_LIST_HEAD(&new->frag_info); - - if (new_fragment(&new->frag_info, frag_off, frag_len) < 0) { - kfree(new); - return -ENOMEM; - } - - new->dgl = dgl; - new->dg_size = dg_size; - - new->skb = dev_alloc_skb(dg_size + dev->hard_header_len + 15); - if (!new->skb) { - struct fragment_info *fi = list_entry(new->frag_info.next, - struct fragment_info, - list); - kfree(fi); - kfree(new); - return -ENOMEM; - } - - skb_reserve(new->skb, (dev->hard_header_len + 15) & ~15); - new->pbuf = skb_put(new->skb, dg_size); - memcpy(new->pbuf + frag_off, frag_buf, frag_len); - - list_add(&new->list, pdgl); - return 0; -} - -static int update_partial_datagram(struct list_head *pdgl, struct list_head *lh, - char *frag_buf, int frag_off, int frag_len) -{ - struct partial_datagram *pd = - list_entry(lh, struct partial_datagram, list); - - if (new_fragment(&pd->frag_info, frag_off, frag_len) < 0) - return -ENOMEM; - - memcpy(pd->pbuf + frag_off, frag_buf, frag_len); - - /* Move list entry to beginnig of list so that oldest partial - * datagrams percolate to the end of the list */ - list_move(lh, pdgl); - return 0; -} - -static int is_datagram_complete(struct list_head *lh, int dg_size) -{ - struct partial_datagram *pd; - struct fragment_info *fi; - - pd = list_entry(lh, struct partial_datagram, list); - fi = list_entry(pd->frag_info.next, struct fragment_info, list); - - return (fi->len == dg_size); -} - -/* Packet reception. We convert the IP1394 encapsulation header to an - * ethernet header, and fill it with some of our other fields. This is - * an incoming packet from the 1394 bus. */ -static int ether1394_data_handler(struct net_device *dev, int srcid, int destid, - char *buf, int len) -{ - struct sk_buff *skb; - unsigned long flags; - struct eth1394_priv *priv = netdev_priv(dev); - union eth1394_hdr *hdr = (union eth1394_hdr *)buf; - __be16 ether_type = cpu_to_be16(0); /* initialized to clear warning */ - int hdr_len; - struct unit_directory *ud = priv->ud_list[NODEID_TO_NODE(srcid)]; - struct eth1394_node_info *node_info; - - if (!ud) { - struct eth1394_node_ref *node; - node = eth1394_find_node_nodeid(&priv->ip_node_list, srcid); - if (unlikely(!node)) { - HPSB_PRINT(KERN_ERR, "ether1394 rx: sender nodeid " - "lookup failure: " NODE_BUS_FMT, - NODE_BUS_ARGS(priv->host, srcid)); - dev->stats.rx_dropped++; - return -1; - } - ud = node->ud; - - priv->ud_list[NODEID_TO_NODE(srcid)] = ud; - } - - node_info = dev_get_drvdata(&ud->device); - - /* First, did we receive a fragmented or unfragmented datagram? */ - hdr->words.word1 = ntohs(hdr->words.word1); - - hdr_len = hdr_type_len[hdr->common.lf]; - - if (hdr->common.lf == ETH1394_HDR_LF_UF) { - /* An unfragmented datagram has been received by the ieee1394 - * bus. Build an skbuff around it so we can pass it to the - * high level network layer. */ - - skb = dev_alloc_skb(len + dev->hard_header_len + 15); - if (unlikely(!skb)) { - ETH1394_PRINT_G(KERN_ERR, "Out of memory\n"); - dev->stats.rx_dropped++; - return -1; - } - skb_reserve(skb, (dev->hard_header_len + 15) & ~15); - memcpy(skb_put(skb, len - hdr_len), buf + hdr_len, - len - hdr_len); - ether_type = hdr->uf.ether_type; - } else { - /* A datagram fragment has been received, now the fun begins. */ - - struct list_head *pdgl, *lh; - struct partial_datagram *pd; - int fg_off; - int fg_len = len - hdr_len; - int dg_size; - int dgl; - int retval; - struct pdg_list *pdg = &(node_info->pdg); - - hdr->words.word3 = ntohs(hdr->words.word3); - /* The 4th header word is reserved so no need to do ntohs() */ - - if (hdr->common.lf == ETH1394_HDR_LF_FF) { - ether_type = hdr->ff.ether_type; - dgl = hdr->ff.dgl; - dg_size = hdr->ff.dg_size + 1; - fg_off = 0; - } else { - hdr->words.word2 = ntohs(hdr->words.word2); - dgl = hdr->sf.dgl; - dg_size = hdr->sf.dg_size + 1; - fg_off = hdr->sf.fg_off; - } - spin_lock_irqsave(&pdg->lock, flags); - - pdgl = &(pdg->list); - lh = find_partial_datagram(pdgl, dgl); - - if (lh == NULL) { - while (pdg->sz >= max_partial_datagrams) { - /* remove the oldest */ - purge_partial_datagram(pdgl->prev); - pdg->sz--; - } - - retval = new_partial_datagram(dev, pdgl, dgl, dg_size, - buf + hdr_len, fg_off, - fg_len); - if (retval < 0) { - spin_unlock_irqrestore(&pdg->lock, flags); - goto bad_proto; - } - pdg->sz++; - lh = find_partial_datagram(pdgl, dgl); - } else { - pd = list_entry(lh, struct partial_datagram, list); - - if (fragment_overlap(&pd->frag_info, fg_off, fg_len)) { - /* Overlapping fragments, obliterate old - * datagram and start new one. */ - purge_partial_datagram(lh); - retval = new_partial_datagram(dev, pdgl, dgl, - dg_size, - buf + hdr_len, - fg_off, fg_len); - if (retval < 0) { - pdg->sz--; - spin_unlock_irqrestore(&pdg->lock, flags); - goto bad_proto; - } - } else { - retval = update_partial_datagram(pdgl, lh, - buf + hdr_len, - fg_off, fg_len); - if (retval < 0) { - /* Couldn't save off fragment anyway - * so might as well obliterate the - * datagram now. */ - purge_partial_datagram(lh); - pdg->sz--; - spin_unlock_irqrestore(&pdg->lock, flags); - goto bad_proto; - } - } /* fragment overlap */ - } /* new datagram or add to existing one */ - - pd = list_entry(lh, struct partial_datagram, list); - - if (hdr->common.lf == ETH1394_HDR_LF_FF) - pd->ether_type = ether_type; - - if (is_datagram_complete(lh, dg_size)) { - ether_type = pd->ether_type; - pdg->sz--; - skb = skb_get(pd->skb); - purge_partial_datagram(lh); - spin_unlock_irqrestore(&pdg->lock, flags); - } else { - /* Datagram is not complete, we're done for the - * moment. */ - spin_unlock_irqrestore(&pdg->lock, flags); - return 0; - } - } /* unframgented datagram or fragmented one */ - - /* Write metadata, and then pass to the receive level */ - skb->dev = dev; - skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ - - /* Parse the encapsulation header. This actually does the job of - * converting to an ethernet frame header, aswell as arp - * conversion if needed. ARP conversion is easier in this - * direction, since we are using ethernet as our backend. */ - skb->protocol = ether1394_parse_encap(skb, dev, srcid, destid, - ether_type); - - spin_lock_irqsave(&priv->lock, flags); - - if (!skb->protocol) { - dev->stats.rx_errors++; - dev->stats.rx_dropped++; - dev_kfree_skb_any(skb); - } else if (netif_rx(skb) == NET_RX_DROP) { - dev->stats.rx_errors++; - dev->stats.rx_dropped++; - } else { - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - } - - spin_unlock_irqrestore(&priv->lock, flags); - -bad_proto: - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); - - return 0; -} - -static int ether1394_write(struct hpsb_host *host, int srcid, int destid, - quadlet_t *data, u64 addr, size_t len, u16 flags) -{ - struct eth1394_host_info *hi; - - hi = hpsb_get_hostinfo(ð1394_highlevel, host); - if (unlikely(!hi)) { - ETH1394_PRINT_G(KERN_ERR, "No net device at fw-host%d\n", - host->id); - return RCODE_ADDRESS_ERROR; - } - - if (ether1394_data_handler(hi->dev, srcid, destid, (char*)data, len)) - return RCODE_ADDRESS_ERROR; - else - return RCODE_COMPLETE; -} - -static void ether1394_iso(struct hpsb_iso *iso) -{ - __be32 *data; - char *buf; - struct eth1394_host_info *hi; - struct net_device *dev; - unsigned int len; - u32 specifier_id; - u16 source_id; - int i; - int nready; - - hi = hpsb_get_hostinfo(ð1394_highlevel, iso->host); - if (unlikely(!hi)) { - ETH1394_PRINT_G(KERN_ERR, "No net device at fw-host%d\n", - iso->host->id); - return; - } - - dev = hi->dev; - - nready = hpsb_iso_n_ready(iso); - for (i = 0; i < nready; i++) { - struct hpsb_iso_packet_info *info = - &iso->infos[(iso->first_packet + i) % iso->buf_packets]; - data = (__be32 *)(iso->data_buf.kvirt + info->offset); - - /* skip over GASP header */ - buf = (char *)data + 8; - len = info->len - 8; - - specifier_id = (be32_to_cpu(data[0]) & 0xffff) << 8 | - (be32_to_cpu(data[1]) & 0xff000000) >> 24; - source_id = be32_to_cpu(data[0]) >> 16; - - if (info->channel != (iso->host->csr.broadcast_channel & 0x3f) - || specifier_id != ETHER1394_GASP_SPECIFIER_ID) { - /* This packet is not for us */ - continue; - } - ether1394_data_handler(dev, source_id, LOCAL_BUS | ALL_NODES, - buf, len); - } - - hpsb_iso_recv_release_packets(iso, i); - -} - -/****************************************** - * Datagram transmission code - ******************************************/ - -/* Convert a standard ARP packet to 1394 ARP. The first 8 bytes (the entire - * arphdr) is the same format as the ip1394 header, so they overlap. The rest - * needs to be munged a bit. The remainder of the arphdr is formatted based - * on hwaddr len and ipaddr len. We know what they'll be, so it's easy to - * judge. - * - * Now that the EUI is used for the hardware address all we need to do to make - * this work for 1394 is to insert 2 quadlets that contain max_rec size, - * speed, and unicast FIFO address information between the sender_unique_id - * and the IP addresses. - */ -static void ether1394_arp_to_1394arp(struct sk_buff *skb, - struct net_device *dev) -{ - struct eth1394_priv *priv = netdev_priv(dev); - struct arphdr *arp = (struct arphdr *)skb->data; - unsigned char *arp_ptr = (unsigned char *)(arp + 1); - struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data; - - arp1394->hw_addr_len = 16; - arp1394->sip = *(u32*)(arp_ptr + ETH1394_ALEN); - arp1394->max_rec = priv->host->csr.max_rec; - arp1394->sspd = priv->host->csr.lnk_spd; - arp1394->fifo_hi = htons(priv->local_fifo >> 32); - arp1394->fifo_lo = htonl(priv->local_fifo & ~0x0); -} - -/* We need to encapsulate the standard header with our own. We use the - * ethernet header's proto for our own. */ -static unsigned int ether1394_encapsulate_prep(unsigned int max_payload, - __be16 proto, - union eth1394_hdr *hdr, - u16 dg_size, u16 dgl) -{ - unsigned int adj_max_payload = - max_payload - hdr_type_len[ETH1394_HDR_LF_UF]; - - /* Does it all fit in one packet? */ - if (dg_size <= adj_max_payload) { - hdr->uf.lf = ETH1394_HDR_LF_UF; - hdr->uf.ether_type = proto; - } else { - hdr->ff.lf = ETH1394_HDR_LF_FF; - hdr->ff.ether_type = proto; - hdr->ff.dg_size = dg_size - 1; - hdr->ff.dgl = dgl; - adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF]; - } - return DIV_ROUND_UP(dg_size, adj_max_payload); -} - -static unsigned int ether1394_encapsulate(struct sk_buff *skb, - unsigned int max_payload, - union eth1394_hdr *hdr) -{ - union eth1394_hdr *bufhdr; - int ftype = hdr->common.lf; - int hdrsz = hdr_type_len[ftype]; - unsigned int adj_max_payload = max_payload - hdrsz; - - switch (ftype) { - case ETH1394_HDR_LF_UF: - bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz); - bufhdr->words.word1 = htons(hdr->words.word1); - bufhdr->words.word2 = hdr->words.word2; - break; - - case ETH1394_HDR_LF_FF: - bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz); - bufhdr->words.word1 = htons(hdr->words.word1); - bufhdr->words.word2 = hdr->words.word2; - bufhdr->words.word3 = htons(hdr->words.word3); - bufhdr->words.word4 = 0; - - /* Set frag type here for future interior fragments */ - hdr->common.lf = ETH1394_HDR_LF_IF; - hdr->sf.fg_off = 0; - break; - - default: - hdr->sf.fg_off += adj_max_payload; - bufhdr = (union eth1394_hdr *)skb_pull(skb, adj_max_payload); - if (max_payload >= skb->len) - hdr->common.lf = ETH1394_HDR_LF_LF; - bufhdr->words.word1 = htons(hdr->words.word1); - bufhdr->words.word2 = htons(hdr->words.word2); - bufhdr->words.word3 = htons(hdr->words.word3); - bufhdr->words.word4 = 0; - } - return min(max_payload, skb->len); -} - -static struct hpsb_packet *ether1394_alloc_common_packet(struct hpsb_host *host) -{ - struct hpsb_packet *p; - - p = hpsb_alloc_packet(0); - if (p) { - p->host = host; - p->generation = get_hpsb_generation(host); - p->type = hpsb_async; - } - return p; -} - -static int ether1394_prep_write_packet(struct hpsb_packet *p, - struct hpsb_host *host, nodeid_t node, - u64 addr, void *data, int tx_len) -{ - p->node_id = node; - - if (hpsb_get_tlabel(p)) - return -EAGAIN; - - p->tcode = TCODE_WRITEB; - p->header_size = 16; - p->expect_response = 1; - p->header[0] = - p->node_id << 16 | p->tlabel << 10 | 1 << 8 | TCODE_WRITEB << 4; - p->header[1] = host->node_id << 16 | addr >> 32; - p->header[2] = addr & 0xffffffff; - p->header[3] = tx_len << 16; - p->data_size = (tx_len + 3) & ~3; - p->data = data; - - return 0; -} - -static void ether1394_prep_gasp_packet(struct hpsb_packet *p, - struct eth1394_priv *priv, - struct sk_buff *skb, int length) -{ - p->header_size = 4; - p->tcode = TCODE_STREAM_DATA; - - p->header[0] = length << 16 | 3 << 14 | priv->broadcast_channel << 8 | - TCODE_STREAM_DATA << 4; - p->data_size = length; - p->data = (quadlet_t *)skb->data - 2; - p->data[0] = cpu_to_be32(priv->host->node_id << 16 | - ETHER1394_GASP_SPECIFIER_ID_HI); - p->data[1] = cpu_to_be32(ETHER1394_GASP_SPECIFIER_ID_LO << 24 | - ETHER1394_GASP_VERSION); - - p->speed_code = priv->bc_sspd; - - /* prevent hpsb_send_packet() from overriding our speed code */ - p->node_id = LOCAL_BUS | ALL_NODES; -} - -static void ether1394_free_packet(struct hpsb_packet *packet) -{ - if (packet->tcode != TCODE_STREAM_DATA) - hpsb_free_tlabel(packet); - hpsb_free_packet(packet); -} - -static void ether1394_complete_cb(void *__ptask); - -static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len) -{ - struct eth1394_priv *priv = ptask->priv; - struct hpsb_packet *packet = NULL; - - packet = ether1394_alloc_common_packet(priv->host); - if (!packet) - return -ENOMEM; - - if (ptask->tx_type == ETH1394_GASP) { - int length = tx_len + 2 * sizeof(quadlet_t); - - ether1394_prep_gasp_packet(packet, priv, ptask->skb, length); - } else if (ether1394_prep_write_packet(packet, priv->host, - ptask->dest_node, - ptask->addr, ptask->skb->data, - tx_len)) { - hpsb_free_packet(packet); - return -EAGAIN; - } - - ptask->packet = packet; - hpsb_set_packet_complete_task(ptask->packet, ether1394_complete_cb, - ptask); - - if (hpsb_send_packet(packet) < 0) { - ether1394_free_packet(packet); - return -EIO; - } - - return 0; -} - -/* Task function to be run when a datagram transmission is completed */ -static void ether1394_dg_complete(struct packet_task *ptask, int fail) -{ - struct sk_buff *skb = ptask->skb; - struct net_device *dev = skb->dev; - struct eth1394_priv *priv = netdev_priv(dev); - unsigned long flags; - - /* Statistics */ - spin_lock_irqsave(&priv->lock, flags); - if (fail) { - dev->stats.tx_dropped++; - dev->stats.tx_errors++; - } else { - dev->stats.tx_bytes += skb->len; - dev->stats.tx_packets++; - } - spin_unlock_irqrestore(&priv->lock, flags); - - dev_kfree_skb_any(skb); - kmem_cache_free(packet_task_cache, ptask); -} - -/* Callback for when a packet has been sent and the status of that packet is - * known */ -static void ether1394_complete_cb(void *__ptask) -{ - struct packet_task *ptask = (struct packet_task *)__ptask; - struct hpsb_packet *packet = ptask->packet; - int fail = 0; - - if (packet->tcode != TCODE_STREAM_DATA) - fail = hpsb_packet_success(packet); - - ether1394_free_packet(packet); - - ptask->outstanding_pkts--; - if (ptask->outstanding_pkts > 0 && !fail) { - int tx_len, err; - - /* Add the encapsulation header to the fragment */ - tx_len = ether1394_encapsulate(ptask->skb, ptask->max_payload, - &ptask->hdr); - err = ether1394_send_packet(ptask, tx_len); - if (err) { - if (err == -EAGAIN) - ETH1394_PRINT_G(KERN_ERR, "Out of tlabels\n"); - - ether1394_dg_complete(ptask, 1); - } - } else { - ether1394_dg_complete(ptask, fail); - } -} - -/* Transmit a packet (called by kernel) */ -static netdev_tx_t ether1394_tx(struct sk_buff *skb, - struct net_device *dev) -{ - struct eth1394hdr hdr_buf; - struct eth1394_priv *priv = netdev_priv(dev); - __be16 proto; - unsigned long flags; - nodeid_t dest_node; - eth1394_tx_type tx_type; - unsigned int tx_len; - unsigned int max_payload; - u16 dg_size; - u16 dgl; - struct packet_task *ptask; - struct eth1394_node_ref *node; - struct eth1394_node_info *node_info = NULL; - - ptask = kmem_cache_alloc(packet_task_cache, GFP_ATOMIC); - if (ptask == NULL) - goto fail; - - /* XXX Ignore this for now. Noticed that when MacOSX is the IRM, - * it does not set our validity bit. We need to compensate for - * that somewhere else, but not in eth1394. */ -#if 0 - if ((priv->host->csr.broadcast_channel & 0xc0000000) != 0xc0000000) - goto fail; -#endif - - skb = skb_share_check(skb, GFP_ATOMIC); - if (!skb) - goto fail; - - /* Get rid of the fake eth1394 header, but first make a copy. - * We might need to rebuild the header on tx failure. */ - memcpy(&hdr_buf, skb->data, sizeof(hdr_buf)); - skb_pull(skb, ETH1394_HLEN); - - proto = hdr_buf.h_proto; - dg_size = skb->len; - - /* Set the transmission type for the packet. ARP packets and IP - * broadcast packets are sent via GASP. */ - if (memcmp(hdr_buf.h_dest, dev->broadcast, ETH1394_ALEN) == 0 || - proto == htons(ETH_P_ARP) || - (proto == htons(ETH_P_IP) && - IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) { - tx_type = ETH1394_GASP; - dest_node = LOCAL_BUS | ALL_NODES; - max_payload = priv->bc_maxpayload - ETHER1394_GASP_OVERHEAD; - BUG_ON(max_payload < 512 - ETHER1394_GASP_OVERHEAD); - dgl = priv->bc_dgl; - if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) - priv->bc_dgl++; - } else { - __be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest); - - node = eth1394_find_node_guid(&priv->ip_node_list, - be64_to_cpu(guid)); - if (!node) - goto fail; - - node_info = dev_get_drvdata(&node->ud->device); - if (node_info->fifo == CSR1212_INVALID_ADDR_SPACE) - goto fail; - - dest_node = node->ud->ne->nodeid; - max_payload = node_info->maxpayload; - BUG_ON(max_payload < 512 - ETHER1394_GASP_OVERHEAD); - - dgl = node_info->dgl; - if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) - node_info->dgl++; - tx_type = ETH1394_WRREQ; - } - - /* If this is an ARP packet, convert it */ - if (proto == htons(ETH_P_ARP)) - ether1394_arp_to_1394arp(skb, dev); - - ptask->hdr.words.word1 = 0; - ptask->hdr.words.word2 = 0; - ptask->hdr.words.word3 = 0; - ptask->hdr.words.word4 = 0; - ptask->skb = skb; - ptask->priv = priv; - ptask->tx_type = tx_type; - - if (tx_type != ETH1394_GASP) { - u64 addr; - - spin_lock_irqsave(&priv->lock, flags); - addr = node_info->fifo; - spin_unlock_irqrestore(&priv->lock, flags); - - ptask->addr = addr; - ptask->dest_node = dest_node; - } - - ptask->tx_type = tx_type; - ptask->max_payload = max_payload; - ptask->outstanding_pkts = ether1394_encapsulate_prep(max_payload, - proto, &ptask->hdr, dg_size, dgl); - - /* Add the encapsulation header to the fragment */ - tx_len = ether1394_encapsulate(skb, max_payload, &ptask->hdr); - dev->trans_start = jiffies; - if (ether1394_send_packet(ptask, tx_len)) { - if (dest_node == (LOCAL_BUS | ALL_NODES)) - goto fail; - - /* At this point we want to restore the packet. When we return - * here with NETDEV_TX_BUSY we will get another entrance in this - * routine with the same skb and we need it to look the same. - * So we pull 4 more bytes, then build the header again. */ - skb_pull(skb, 4); - ether1394_header(skb, dev, ntohs(hdr_buf.h_proto), - hdr_buf.h_dest, NULL, 0); - - /* Most failures of ether1394_send_packet are recoverable. */ - netif_stop_queue(dev); - priv->wake_node = dest_node; - schedule_work(&priv->wake); - kmem_cache_free(packet_task_cache, ptask); - return NETDEV_TX_BUSY; - } - - return NETDEV_TX_OK; -fail: - if (ptask) - kmem_cache_free(packet_task_cache, ptask); - - if (skb != NULL) - dev_kfree_skb(skb); - - spin_lock_irqsave(&priv->lock, flags); - dev->stats.tx_dropped++; - dev->stats.tx_errors++; - spin_unlock_irqrestore(&priv->lock, flags); - - return NETDEV_TX_OK; -} - -static int __init ether1394_init_module(void) -{ - int err; - - packet_task_cache = kmem_cache_create("packet_task", - sizeof(struct packet_task), - 0, 0, NULL); - if (!packet_task_cache) - return -ENOMEM; - - hpsb_register_highlevel(ð1394_highlevel); - err = hpsb_register_protocol(ð1394_proto_driver); - if (err) { - hpsb_unregister_highlevel(ð1394_highlevel); - kmem_cache_destroy(packet_task_cache); - } - return err; -} - -static void __exit ether1394_exit_module(void) -{ - hpsb_unregister_protocol(ð1394_proto_driver); - hpsb_unregister_highlevel(ð1394_highlevel); - kmem_cache_destroy(packet_task_cache); -} - -module_init(ether1394_init_module); -module_exit(ether1394_exit_module); diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h deleted file mode 100644 index d53bac4..0000000 --- a/drivers/ieee1394/eth1394.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * eth1394.h -- Ethernet driver for Linux IEEE-1394 Subsystem - * - * Copyright (C) 2000 Bonin Franck <boninf@free.fr> - * (C) 2001 Ben Collins <bcollins@debian.org> - * - * Mainly based on work by Emanuel Pirker and Andreas E. Bombe - * - * 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 __ETH1394_H -#define __ETH1394_H - -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <asm/byteorder.h> - -#include "ieee1394.h" -#include "ieee1394_types.h" - -/* Register for incoming packets. This is 4096 bytes, which supports up to - * S3200 (per Table 16-3 of IEEE 1394b-2002). */ -#define ETHER1394_REGION_ADDR_LEN 4096 - -/* GASP identifier numbers for IPv4 over IEEE 1394 */ -#define ETHER1394_GASP_SPECIFIER_ID 0x00005E -#define ETHER1394_GASP_SPECIFIER_ID_HI ((0x00005E >> 8) & 0xffff) -#define ETHER1394_GASP_SPECIFIER_ID_LO (0x00005E & 0xff) -#define ETHER1394_GASP_VERSION 1 - -#define ETHER1394_GASP_OVERHEAD (2 * sizeof(quadlet_t)) /* for GASP header */ - -#define ETHER1394_GASP_BUFFERS 16 - -#define NODE_SET (ALL_NODES + 1) /* Node set == 64 */ - -enum eth1394_bc_states { ETHER1394_BC_ERROR, - ETHER1394_BC_RUNNING, - ETHER1394_BC_STOPPED }; - - -/* Private structure for our ethernet driver */ -struct eth1394_priv { - struct hpsb_host *host; /* The card for this dev */ - u16 bc_maxpayload; /* Max broadcast payload */ - u8 bc_sspd; /* Max broadcast speed */ - u64 local_fifo; /* Local FIFO Address */ - spinlock_t lock; /* Private lock */ - int broadcast_channel; /* Async stream Broadcast Channel */ - enum eth1394_bc_states bc_state; /* broadcast channel state */ - struct hpsb_iso *iso; /* Async stream recv handle */ - int bc_dgl; /* Outgoing broadcast datagram label */ - struct list_head ip_node_list; /* List of IP capable nodes */ - struct unit_directory *ud_list[ALL_NODES]; /* Cached unit dir list */ - - struct work_struct wake; /* Wake up after xmit failure */ - struct net_device *wake_dev; /* Stupid backlink for .wake */ - nodeid_t wake_node; /* Destination of failed xmit */ -}; - - -/* Define a fake hardware header format for the networking core. Note that - * header size cannot exceed 16 bytes as that is the size of the header cache. - * Also, we do not need the source address in the header so we omit it and - * keep the header to under 16 bytes */ -#define ETH1394_ALEN (8) -#define ETH1394_HLEN (10) - -struct eth1394hdr { - unsigned char h_dest[ETH1394_ALEN]; /* destination eth1394 addr */ - __be16 h_proto; /* packet type ID field */ -} __attribute__((packed)); - -static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb) -{ - return (struct eth1394hdr *)skb_mac_header(skb); -} - -typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type; - -/* IP1394 headers */ - -/* Unfragmented */ -#if defined __BIG_ENDIAN_BITFIELD -struct eth1394_uf_hdr { - u16 lf:2; - u16 res:14; - __be16 ether_type; /* Ethernet packet type */ -} __attribute__((packed)); -#elif defined __LITTLE_ENDIAN_BITFIELD -struct eth1394_uf_hdr { - u16 res:14; - u16 lf:2; - __be16 ether_type; -} __attribute__((packed)); -#else -#error Unknown bit field type -#endif - -/* First fragment */ -#if defined __BIG_ENDIAN_BITFIELD -struct eth1394_ff_hdr { - u16 lf:2; - u16 res1:2; - u16 dg_size:12; /* Datagram size */ - __be16 ether_type; /* Ethernet packet type */ - u16 dgl; /* Datagram label */ - u16 res2; -} __attribute__((packed)); -#elif defined __LITTLE_ENDIAN_BITFIELD -struct eth1394_ff_hdr { - u16 dg_size:12; - u16 res1:2; - u16 lf:2; - __be16 ether_type; - u16 dgl; - u16 res2; -} __attribute__((packed)); -#else -#error Unknown bit field type -#endif - -/* XXX: Subsequent fragments, including last */ -#if defined __BIG_ENDIAN_BITFIELD -struct eth1394_sf_hdr { - u16 lf:2; - u16 res1:2; - u16 dg_size:12; /* Datagram size */ - u16 res2:4; - u16 fg_off:12; /* Fragment offset */ - u16 dgl; /* Datagram label */ - u16 res3; -} __attribute__((packed)); -#elif defined __LITTLE_ENDIAN_BITFIELD -struct eth1394_sf_hdr { - u16 dg_size:12; - u16 res1:2; - u16 lf:2; - u16 fg_off:12; - u16 res2:4; - u16 dgl; - u16 res3; -} __attribute__((packed)); -#else -#error Unknown bit field type -#endif - -#if defined __BIG_ENDIAN_BITFIELD -struct eth1394_common_hdr { - u16 lf:2; - u16 pad1:14; -} __attribute__((packed)); -#elif defined __LITTLE_ENDIAN_BITFIELD -struct eth1394_common_hdr { - u16 pad1:14; - u16 lf:2; -} __attribute__((packed)); -#else -#error Unknown bit field type -#endif - -struct eth1394_hdr_words { - u16 word1; - u16 word2; - u16 word3; - u16 word4; -}; - -union eth1394_hdr { - struct eth1394_common_hdr common; - struct eth1394_uf_hdr uf; - struct eth1394_ff_hdr ff; - struct eth1394_sf_hdr sf; - struct eth1394_hdr_words words; -}; - -/* End of IP1394 headers */ - -/* Fragment types */ -#define ETH1394_HDR_LF_UF 0 /* unfragmented */ -#define ETH1394_HDR_LF_FF 1 /* first fragment */ -#define ETH1394_HDR_LF_LF 2 /* last fragment */ -#define ETH1394_HDR_LF_IF 3 /* interior fragment */ - -#define IP1394_HW_ADDR_LEN 16 /* As per RFC */ - -/* Our arp packet (ARPHRD_IEEE1394) */ -struct eth1394_arp { - u16 hw_type; /* 0x0018 */ - u16 proto_type; /* 0x0806 */ - u8 hw_addr_len; /* 16 */ - u8 ip_addr_len; /* 4 */ - u16 opcode; /* ARP Opcode */ - /* Above is exactly the same format as struct arphdr */ - - __be64 s_uniq_id; /* Sender's 64bit EUI */ - u8 max_rec; /* Sender's max packet size */ - u8 sspd; /* Sender's max speed */ - __be16 fifo_hi; /* hi 16bits of sender's FIFO addr */ - __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */ - u32 sip; /* Sender's IP Address */ - u32 tip; /* IP Address of requested hw addr */ -}; - -/* Network timeout */ -#define ETHER1394_TIMEOUT 100000 - -/* This is our task struct. It's used for the packet complete callback. */ -struct packet_task { - struct sk_buff *skb; - int outstanding_pkts; - eth1394_tx_type tx_type; - int max_payload; - struct hpsb_packet *packet; - struct eth1394_priv *priv; - union eth1394_hdr hdr; - u64 addr; - u16 dest_node; -}; - -#endif /* __ETH1394_H */ diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c deleted file mode 100644 index 4bc4435..0000000 --- a/drivers/ieee1394/highlevel.c +++ /dev/null @@ -1,691 +0,0 @@ -/* - * IEEE 1394 for Linux - * - * Copyright (C) 1999 Andreas E. Bombe - * - * This code is licensed under the GPL. See the file COPYING in the root - * directory of the kernel sources for details. - * - * - * Contributions: - * - * Christian Toegel <christian.toegel@gmx.at> - * unregister address space - * - * Manfred Weihs <weihs@ict.tuwien.ac.at> - * unregister address space - * - */ - -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/bitops.h> - -#include "ieee1394.h" -#include "ieee1394_types.h" -#include "hosts.h" -#include "ieee1394_core.h" -#include "highlevel.h" -#include "nodemgr.h" - - -struct hl_host_info { - struct list_head list; - struct hpsb_host *host; - size_t size; - unsigned long key; - void *data; -}; - - -static LIST_HEAD(hl_drivers); -static DECLARE_RWSEM(hl_drivers_sem); - -static LIST_HEAD(hl_irqs); -static DEFINE_RWLOCK(hl_irqs_lock); - -static DEFINE_RWLOCK(addr_space_lock); - - -static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl, - struct hpsb_host *host) -{ - struct hl_host_info *hi = NULL; - - if (!hl || !host) - return NULL; - - read_lock(&hl->host_info_lock); - list_for_each_entry(hi, &hl->host_info_list, list) { - if (hi->host == host) { - read_unlock(&hl->host_info_lock); - return hi; - } - } - read_unlock(&hl->host_info_lock); - return NULL; -} - -/** - * hpsb_get_hostinfo - retrieve a hostinfo pointer bound to this driver/host - * - * Returns a per @host and @hl driver data structure that was previously stored - * by hpsb_create_hostinfo. - */ -void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) -{ - struct hl_host_info *hi = hl_get_hostinfo(hl, host); - - return hi ? hi->data : NULL; -} - -/** - * hpsb_create_hostinfo - allocate a hostinfo pointer bound to this driver/host - * - * Allocate a hostinfo pointer backed by memory with @data_size and bind it to - * to this @hl driver and @host. If @data_size is zero, then the return here is - * only valid for error checking. - */ -void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, - size_t data_size) -{ - struct hl_host_info *hi; - void *data; - unsigned long flags; - - hi = hl_get_hostinfo(hl, host); - if (hi) { - HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already" - " exists", hl->name); - return NULL; - } - - hi = kzalloc(sizeof(*hi) + data_size, GFP_ATOMIC); - if (!hi) - return NULL; - - if (data_size) { - data = hi->data = hi + 1; - hi->size = data_size; - } else - data = hi; - - hi->host = host; - - write_lock_irqsave(&hl->host_info_lock, flags); - list_add_tail(&hi->list, &hl->host_info_list); - write_unlock_irqrestore(&hl->host_info_lock, flags); - - return data; -} - -/** - * hpsb_set_hostinfo - set the hostinfo pointer to something useful - * - * Usually follows a call to hpsb_create_hostinfo, where the size is 0. - */ -int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, - void *data) -{ - struct hl_host_info *hi; - - hi = hl_get_hostinfo(hl, host); - if (hi) { - if (!hi->size && !hi->data) { - hi->data = data; - return 0; - } else - HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo " - "already has data", hl->name); - } else - HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists", - hl->name); - return -EINVAL; -} - -/** - * hpsb_destroy_hostinfo - free and remove a hostinfo pointer - * - * Free and remove the hostinfo pointer bound to this @hl driver and @host. - */ -void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host) -{ - struct hl_host_info *hi; - - hi = hl_get_hostinfo(hl, host); - if (hi) { - unsigned long flags; - write_lock_irqsave(&hl->host_info_lock, flags); - list_del(&hi->list); - write_unlock_irqrestore(&hl->host_info_lock, flags); - kfree(hi); - } - return; -} - -/** - * hpsb_set_hostinfo_key - set an alternate lookup key for an hostinfo - * - * Sets an alternate lookup key for the hostinfo bound to this @hl driver and - * @host. - */ -void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, - unsigned long key) -{ - struct hl_host_info *hi; - - hi = hl_get_hostinfo(hl, host); - if (hi) - hi->key = key; - return; -} - -/** - * hpsb_get_hostinfo_bykey - retrieve a hostinfo pointer by its alternate key - */ -void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key) -{ - struct hl_host_info *hi; - void *data = NULL; - - if (!hl) - return NULL; - - read_lock(&hl->host_info_lock); - list_for_each_entry(hi, &hl->host_info_list, list) { - if (hi->key == key) { - data = hi->data; - break; - } - } - read_unlock(&hl->host_info_lock); - return data; -} - -static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data) -{ - struct hpsb_highlevel *hl = __data; - - hl->add_host(host); - - if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0) - HPSB_ERR("Failed to generate Configuration ROM image for host " - "%s-%d", hl->name, host->id); - return 0; -} - -/** - * hpsb_register_highlevel - register highlevel driver - * - * The name pointer in @hl has to stay valid at all times because the string is - * not copied. - */ -void hpsb_register_highlevel(struct hpsb_highlevel *hl) -{ - unsigned long flags; - - hpsb_init_highlevel(hl); - INIT_LIST_HEAD(&hl->addr_list); - - down_write(&hl_drivers_sem); - list_add_tail(&hl->hl_list, &hl_drivers); - up_write(&hl_drivers_sem); - - write_lock_irqsave(&hl_irqs_lock, flags); - list_add_tail(&hl->irq_list, &hl_irqs); - write_unlock_irqrestore(&hl_irqs_lock, flags); - - if (hl->add_host) - nodemgr_for_each_host(hl, highlevel_for_each_host_reg); - return; -} - -static void __delete_addr(struct hpsb_address_serve *as) -{ - list_del(&as->host_list); - list_del(&as->hl_list); - kfree(as); -} - -static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, - int update_cr) -{ - unsigned long flags; - struct list_head *lh, *next; - struct hpsb_address_serve *as; - - /* First, let the highlevel driver unreg */ - if (hl->remove_host) - hl->remove_host(host); - - /* Remove any addresses that are matched for this highlevel driver - * and this particular host. */ - write_lock_irqsave(&addr_space_lock, flags); - list_for_each_safe (lh, next, &hl->addr_list) { - as = list_entry(lh, struct hpsb_address_serve, hl_list); - if (as->host == host) - __delete_addr(as); - } - write_unlock_irqrestore(&addr_space_lock, flags); - - /* Now update the config-rom to reflect anything removed by the - * highlevel driver. */ - if (update_cr && host->update_config_rom && - hpsb_update_config_rom_image(host) < 0) - HPSB_ERR("Failed to generate Configuration ROM image for host " - "%s-%d", hl->name, host->id); - - /* Finally remove all the host info associated between these two. */ - hpsb_destroy_hostinfo(hl, host); -} - -static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data) -{ - struct hpsb_highlevel *hl = __data; - - __unregister_host(hl, host, 1); - return 0; -} - -/** - * hpsb_unregister_highlevel - unregister highlevel driver - */ -void hpsb_unregister_highlevel(struct hpsb_highlevel *hl) -{ - unsigned long flags; - - write_lock_irqsave(&hl_irqs_lock, flags); - list_del(&hl->irq_list); - write_unlock_irqrestore(&hl_irqs_lock, flags); - - down_write(&hl_drivers_sem); - list_del(&hl->hl_list); - up_write(&hl_drivers_sem); - - nodemgr_for_each_host(hl, highlevel_for_each_host_unreg); -} - -/** - * hpsb_allocate_and_register_addrspace - alloc' and reg' a host address space - * - * @start and @end are 48 bit pointers and have to be quadlet aligned. - * @end points to the first address behind the handled addresses. This - * function can be called multiple times for a single hpsb_highlevel @hl to - * implement sparse register sets. The requested region must not overlap any - * previously allocated region, otherwise registering will fail. - * - * It returns true for successful allocation. Address spaces can be - * unregistered with hpsb_unregister_addrspace. All remaining address spaces - * are automatically deallocated together with the 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) -{ - struct hpsb_address_serve *as, *a1, *a2; - struct list_head *entry; - u64 retval = CSR1212_INVALID_ADDR_SPACE; - unsigned long flags; - u64 align_mask = ~(alignment - 1); - - if ((alignment & 3) || (alignment > 0x800000000000ULL) || - (hweight64(alignment) != 1)) { - HPSB_ERR("%s called with invalid alignment: 0x%048llx", - __func__, (unsigned long long)alignment); - return retval; - } - - /* default range, - * avoids controller's posted write area (see OHCI 1.1 clause 1.5) */ - if (start == CSR1212_INVALID_ADDR_SPACE && - end == CSR1212_INVALID_ADDR_SPACE) { - start = host->middle_addr_space; - end = CSR1212_ALL_SPACE_END; - } - - if (((start|end) & ~align_mask) || (start >= end) || - (end > CSR1212_ALL_SPACE_END)) { - HPSB_ERR("%s called with invalid addresses " - "(start = %012Lx end = %012Lx)", __func__, - (unsigned long long)start,(unsigned long long)end); - return retval; - } - - as = kmalloc(sizeof(*as), GFP_KERNEL); - if (!as) - return retval; - - INIT_LIST_HEAD(&as->host_list); - INIT_LIST_HEAD(&as->hl_list); - as->op = ops; - as->host = host; - - write_lock_irqsave(&addr_space_lock, flags); - list_for_each(entry, &host->addr_space) { - u64 a1sa, a1ea; - u64 a2sa, a2ea; - - a1 = list_entry(entry, struct hpsb_address_serve, host_list); - a2 = list_entry(entry->next, struct hpsb_address_serve, - host_list); - - a1sa = a1->start & align_mask; - a1ea = (a1->end + alignment -1) & align_mask; - a2sa = a2->start & align_mask; - a2ea = (a2->end + alignment -1) & align_mask; - - if ((a2sa - a1ea >= size) && (a2sa - start >= size) && - (a2sa > start)) { - as->start = max(start, a1ea); - as->end = as->start + size; - list_add(&as->host_list, entry); - list_add_tail(&as->hl_list, &hl->addr_list); - retval = as->start; - break; - } - } - write_unlock_irqrestore(&addr_space_lock, flags); - - if (retval == CSR1212_INVALID_ADDR_SPACE) - kfree(as); - return retval; -} - -/** - * hpsb_register_addrspace - register a host address space - * - * @start and @end are 48 bit pointers and have to be quadlet aligned. - * @end points to the first address behind the handled addresses. This - * function can be called multiple times for a single hpsb_highlevel @hl to - * implement sparse register sets. The requested region must not overlap any - * previously allocated region, otherwise registering will fail. - * - * It returns true for successful allocation. Address spaces can be - * unregistered with hpsb_unregister_addrspace. All remaining address spaces - * are automatically deallocated together with the hpsb_highlevel @hl. - */ -int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, - const struct hpsb_address_ops *ops, - u64 start, u64 end) -{ - struct hpsb_address_serve *as; - struct list_head *lh; - int retval = 0; - unsigned long flags; - - if (((start|end) & 3) || (start >= end) || - (end > CSR1212_ALL_SPACE_END)) { - HPSB_ERR("%s called with invalid addresses", __func__); - return 0; - } - - as = kmalloc(sizeof(*as), GFP_KERNEL); - if (!as) - return 0; - - INIT_LIST_HEAD(&as->host_list); - INIT_LIST_HEAD(&as->hl_list); - as->op = ops; - as->start = start; - as->end = end; - as->host = host; - - write_lock_irqsave(&addr_space_lock, flags); - list_for_each(lh, &host->addr_space) { - struct hpsb_address_serve *as_this = - list_entry(lh, struct hpsb_address_serve, host_list); - struct hpsb_address_serve *as_next = - list_entry(lh->next, struct hpsb_address_serve, - host_list); - - if (as_this->end > as->start) - break; - - if (as_next->start >= as->end) { - list_add(&as->host_list, lh); - list_add_tail(&as->hl_list, &hl->addr_list); - retval = 1; - break; - } - } - write_unlock_irqrestore(&addr_space_lock, flags); - - if (retval == 0) - kfree(as); - return retval; -} - -int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host, - u64 start) -{ - int retval = 0; - struct hpsb_address_serve *as; - struct list_head *lh, *next; - unsigned long flags; - - write_lock_irqsave(&addr_space_lock, flags); - list_for_each_safe (lh, next, &hl->addr_list) { - as = list_entry(lh, struct hpsb_address_serve, hl_list); - if (as->start == start && as->host == host) { - __delete_addr(as); - retval = 1; - break; - } - } - write_unlock_irqrestore(&addr_space_lock, flags); - return retval; -} - -static const struct hpsb_address_ops dummy_ops; - -/* dummy address spaces as lower and upper bounds of the host's a.s. list */ -static void init_hpsb_highlevel(struct hpsb_host *host) -{ - INIT_LIST_HEAD(&host->dummy_zero_addr.host_list); - INIT_LIST_HEAD(&host->dummy_zero_addr.hl_list); - INIT_LIST_HEAD(&host->dummy_max_addr.host_list); - INIT_LIST_HEAD(&host->dummy_max_addr.hl_list); - - host->dummy_zero_addr.op = host->dummy_max_addr.op = &dummy_ops; - - host->dummy_zero_addr.start = host->dummy_zero_addr.end = 0; - host->dummy_max_addr.start = host->dummy_max_addr.end = ((u64) 1) << 48; - - list_add_tail(&host->dummy_zero_addr.host_list, &host->addr_space); - list_add_tail(&host->dummy_max_addr.host_list, &host->addr_space); -} - -void highlevel_add_host(struct hpsb_host *host) -{ - struct hpsb_highlevel *hl; - - init_hpsb_highlevel(host); - - down_read(&hl_drivers_sem); - list_for_each_entry(hl, &hl_drivers, hl_list) { - if (hl->add_host) - hl->add_host(host); - } - up_read(&hl_drivers_sem); - if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0) - HPSB_ERR("Failed to generate Configuration ROM image for host " - "%s-%d", hl->name, host->id); -} - -void highlevel_remove_host(struct hpsb_host *host) -{ - struct hpsb_highlevel *hl; - - down_read(&hl_drivers_sem); - list_for_each_entry(hl, &hl_drivers, hl_list) - __unregister_host(hl, host, 0); - up_read(&hl_drivers_sem); -} - -void highlevel_host_reset(struct hpsb_host *host) -{ - unsigned long flags; - struct hpsb_highlevel *hl; - - read_lock_irqsave(&hl_irqs_lock, flags); - list_for_each_entry(hl, &hl_irqs, irq_list) { - if (hl->host_reset) - hl->host_reset(host); - } - read_unlock_irqrestore(&hl_irqs_lock, flags); -} - -void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction, - void *data, size_t length) -{ - unsigned long flags; - struct hpsb_highlevel *hl; - int cts = ((quadlet_t *)data)[0] >> 4; - - read_lock_irqsave(&hl_irqs_lock, flags); - list_for_each_entry(hl, &hl_irqs, irq_list) { - if (hl->fcp_request) - hl->fcp_request(host, nodeid, direction, cts, data, - length); - } - read_unlock_irqrestore(&hl_irqs_lock, flags); -} - -/* - * highlevel_read, highlevel_write, highlevel_lock, highlevel_lock64: - * - * These functions are called to handle transactions. They are called when a - * packet arrives. The flags argument contains the second word of the first - * header quadlet of the incoming packet (containing transaction label, retry - * code, transaction code and priority). 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 highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr, - unsigned int length, u16 flags) -{ - struct hpsb_address_serve *as; - unsigned int partlength; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); - list_for_each_entry(as, &host->addr_space, host_list) { - if (as->start > addr) - break; - - if (as->end > addr) { - partlength = min(as->end - addr, (u64) length); - - if (as->op->read) - rcode = as->op->read(host, nodeid, data, - addr, partlength, flags); - else - rcode = RCODE_TYPE_ERROR; - - data += partlength; - length -= partlength; - addr += partlength; - - if ((rcode != RCODE_COMPLETE) || !length) - break; - } - } - read_unlock(&addr_space_lock); - - if (length && (rcode == RCODE_COMPLETE)) - rcode = RCODE_ADDRESS_ERROR; - return rcode; -} - -int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data, - u64 addr, unsigned int length, u16 flags) -{ - struct hpsb_address_serve *as; - unsigned int partlength; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); - list_for_each_entry(as, &host->addr_space, host_list) { - if (as->start > addr) - break; - - if (as->end > addr) { - partlength = min(as->end - addr, (u64) length); - - if (as->op->write) - rcode = as->op->write(host, nodeid, destid, - data, addr, partlength, - flags); - else - rcode = RCODE_TYPE_ERROR; - - data += partlength; - length -= partlength; - addr += partlength; - - if ((rcode != RCODE_COMPLETE) || !length) - break; - } - } - read_unlock(&addr_space_lock); - - if (length && (rcode == RCODE_COMPLETE)) - rcode = RCODE_ADDRESS_ERROR; - return rcode; -} - -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) -{ - struct hpsb_address_serve *as; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); - list_for_each_entry(as, &host->addr_space, host_list) { - if (as->start > addr) - break; - - if (as->end > addr) { - if (as->op->lock) - rcode = as->op->lock(host, nodeid, store, addr, - data, arg, ext_tcode, - flags); - else - rcode = RCODE_TYPE_ERROR; - break; - } - } - read_unlock(&addr_space_lock); - return rcode; -} - -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) -{ - struct hpsb_address_serve *as; - int rcode = RCODE_ADDRESS_ERROR; - - read_lock(&addr_space_lock); - - list_for_each_entry(as, &host->addr_space, host_list) { - if (as->start > addr) - break; - - if (as->end > addr) { - if (as->op->lock64) - rcode = as->op->lock64(host, nodeid, store, - addr, data, arg, - ext_tcode, flags); - else - rcode = RCODE_TYPE_ERROR; - break; - } - } - read_unlock(&addr_space_lock); - return rcode; -} diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h deleted file mode 100644 index 9dba89f..0000000 --- a/drivers/ieee1394/highlevel.h +++ /dev/null @@ -1,141 +0,0 @@ -#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 */ diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c deleted file mode 100644 index e947d8f..0000000 --- a/drivers/ieee1394/hosts.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * IEEE 1394 for Linux - * - * Low level (host adapter) management. - * - * Copyright (C) 1999 Andreas E. Bombe - * Copyright (C) 1999 Emanuel Pirker - * - * This code is licensed under the GPL. See the file COPYING in the root - * directory of the kernel sources for details. - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/list.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/timer.h> -#include <linux/jiffies.h> -#include <linux/mutex.h> - -#include "csr1212.h" -#include "ieee1394.h" -#include "ieee1394_types.h" -#include "hosts.h" -#include "ieee1394_core.h" -#include "highlevel.h" -#include "nodemgr.h" -#include "csr.h" -#include "config_roms.h" - - -static void delayed_reset_bus(struct work_struct *work) -{ - struct hpsb_host *host = - container_of(work, struct hpsb_host, delayed_reset.work); - u8 generation = host->csr.generation + 1; - - /* The generation field rolls over to 2 rather than 0 per IEEE - * 1394a-2000. */ - if (generation > 0xf || generation < 2) - generation = 2; - - csr_set_bus_info_generation(host->csr.rom, generation); - if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) { - /* CSR image creation failed. - * Reset generation field and do not issue a bus reset. */ - csr_set_bus_info_generation(host->csr.rom, - host->csr.generation); - return; - } - - host->csr.generation = generation; - - host->update_config_rom = 0; - if (host->driver->set_hw_config_rom) - host->driver->set_hw_config_rom(host, - host->csr.rom->bus_info_data); - - host->csr.gen_timestamp[host->csr.generation] = jiffies; - hpsb_reset_bus(host, SHORT_RESET); -} - -static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p) -{ - return 0; -} - -static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg) -{ - return -1; -} - -static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, - unsigned long arg) -{ - return -1; -} - -static struct hpsb_host_driver dummy_driver = { - .transmit_packet = dummy_transmit_packet, - .devctl = dummy_devctl, - .isoctl = dummy_isoctl -}; - -static int alloc_hostnum_cb(struct hpsb_host *host, void *__data) -{ - int *hostnum = __data; - - if (host->id == *hostnum) - return 1; - - return 0; -} - -static DEFINE_MUTEX(host_num_alloc); - -/** - * hpsb_alloc_host - allocate a new host controller. - * @drv: the driver that will manage the host controller - * @extra: number of extra bytes to allocate for the driver - * - * Allocate a &hpsb_host and initialize the general subsystem specific - * fields. If the driver needs to store per host data, as drivers - * usually do, the amount of memory required can be specified by the - * @extra parameter. Once allocated, the driver should initialize the - * driver specific parts, enable the controller and make it available - * to the general subsystem using hpsb_add_host(). - * - * Return Value: a pointer to the &hpsb_host if successful, %NULL if - * no memory was available. - */ -struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, - struct device *dev) -{ - struct hpsb_host *h; - int i; - int hostnum = 0; - - h = kzalloc(sizeof(*h) + extra, GFP_KERNEL); - if (!h) - return NULL; - - h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h); - if (!h->csr.rom) - goto fail; - - h->hostdata = h + 1; - h->driver = drv; - - INIT_LIST_HEAD(&h->pending_packets); - INIT_LIST_HEAD(&h->addr_space); - - for (i = 2; i < 16; i++) - h->csr.gen_timestamp[i] = jiffies - 60 * HZ; - - atomic_set(&h->generation, 0); - - INIT_DELAYED_WORK(&h->delayed_reset, delayed_reset_bus); - - init_timer(&h->timeout); - h->timeout.data = (unsigned long) h; - h->timeout.function = abort_timedouts; - h->timeout_interval = HZ / 20; /* 50ms, half of minimum SPLIT_TIMEOUT */ - - h->topology_map = h->csr.topology_map + 3; - h->speed_map = (u8 *)(h->csr.speed_map + 2); - - mutex_lock(&host_num_alloc); - while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb)) - hostnum++; - mutex_unlock(&host_num_alloc); - h->id = hostnum; - - memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device)); - h->device.parent = dev; - set_dev_node(&h->device, dev_to_node(dev)); - dev_set_name(&h->device, "fw-host%d", h->id); - - h->host_dev.parent = &h->device; - h->host_dev.class = &hpsb_host_class; - dev_set_name(&h->host_dev, "fw-host%d", h->id); - - if (device_register(&h->device)) - goto fail; - if (device_register(&h->host_dev)) { - device_unregister(&h->device); - goto fail; - } - get_device(&h->device); - - return h; - -fail: - kfree(h); - return NULL; -} - -int hpsb_add_host(struct hpsb_host *host) -{ - if (hpsb_default_host_entry(host)) - return -ENOMEM; - - highlevel_add_host(host); - return 0; -} - -void hpsb_resume_host(struct hpsb_host *host) -{ - if (host->driver->set_hw_config_rom) - host->driver->set_hw_config_rom(host, - host->csr.rom->bus_info_data); - host->driver->devctl(host, RESET_BUS, SHORT_RESET); -} - -void hpsb_remove_host(struct hpsb_host *host) -{ - host->is_shutdown = 1; - - cancel_delayed_work(&host->delayed_reset); - flush_scheduled_work(); - - host->driver = &dummy_driver; - highlevel_remove_host(host); - - device_unregister(&host->host_dev); - device_unregister(&host->device); -} - -/** - * hpsb_update_config_rom_image - updates configuration ROM image of a host - * - * Updates the configuration ROM image of a host. rom_version must be the - * current version, otherwise it will fail with return value -1. If this - * host does not support config-rom-update, it will return -%EINVAL. - * Return value 0 indicates success. - */ -int hpsb_update_config_rom_image(struct hpsb_host *host) -{ - unsigned long reset_delay; - int next_gen = host->csr.generation + 1; - - if (!host->update_config_rom) - return -EINVAL; - - if (next_gen > 0xf) - next_gen = 2; - - /* Stop the delayed interrupt, we're about to change the config rom and - * it would be a waste to do a bus reset twice. */ - cancel_delayed_work(&host->delayed_reset); - - /* IEEE 1394a-2000 prohibits using the same generation number - * twice in a 60 second period. */ - if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ)) - /* Wait 60 seconds from the last time this generation number was - * used. */ - reset_delay = - (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies; - else - /* Wait 1 second in case some other code wants to change the - * Config ROM in the near future. */ - reset_delay = HZ; - - PREPARE_DELAYED_WORK(&host->delayed_reset, delayed_reset_bus); - schedule_delayed_work(&host->delayed_reset, reset_delay); - - return 0; -} diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h deleted file mode 100644 index 49c3590..0000000 --- a/drivers/ieee1394/hosts.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef _IEEE1394_HOSTS_H -#define _IEEE1394_HOSTS_H - -#include <linux/device.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/types.h> -#include <linux/workqueue.h> -#include <asm/atomic.h> - -struct pci_dev; -struct module; - -#include "ieee1394_types.h" -#include "csr.h" -#include "highlevel.h" - -struct hpsb_packet; -struct hpsb_iso; - -struct hpsb_host { - struct list_head host_list; - - void *hostdata; - - atomic_t generation; - - struct list_head pending_packets; - struct timer_list timeout; - unsigned long timeout_interval; - - int node_count; /* number of identified nodes on this bus */ - int selfid_count; /* total number of SelfIDs received */ - int nodes_active; /* number of nodes with active link layer */ - - nodeid_t node_id; /* node ID of this host */ - nodeid_t irm_id; /* ID of this bus' isochronous resource manager */ - nodeid_t busmgr_id; /* ID of this bus' bus manager */ - - /* this nodes state */ - unsigned in_bus_reset:1; - unsigned is_shutdown:1; - unsigned resume_packet_sent:1; - - /* this nodes' duties on the bus */ - unsigned is_root:1; - unsigned is_cycmst:1; - unsigned is_irm:1; - unsigned is_busmgr:1; - - int reset_retries; - quadlet_t *topology_map; - u8 *speed_map; - - int id; - struct hpsb_host_driver *driver; - struct pci_dev *pdev; - struct device device; - struct device host_dev; - - struct delayed_work delayed_reset; - unsigned config_roms:31; - unsigned update_config_rom:1; - - struct list_head addr_space; - u64 low_addr_space; /* upper bound of physical DMA area */ - u64 middle_addr_space; /* upper bound of posted write area */ - - u8 speed[ALL_NODES]; /* speed between each node and local node */ - - /* per node tlabel allocation */ - u8 next_tl[ALL_NODES]; - struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES]; - - struct csr_control csr; - - struct hpsb_address_serve dummy_zero_addr; - struct hpsb_address_serve dummy_max_addr; -}; - -enum devctl_cmd { - /* Host is requested to reset its bus and cancel all outstanding async - * requests. If arg == 1, it shall also attempt to become root on the - * bus. Return void. */ - RESET_BUS, - - /* Arg is void, return value is the hardware cycle counter value. */ - GET_CYCLE_COUNTER, - - /* Set the hardware cycle counter to the value in arg, return void. - * FIXME - setting is probably not required. */ - SET_CYCLE_COUNTER, - - /* Configure hardware for new bus ID in arg, return void. */ - SET_BUS_ID, - - /* If arg true, start sending cycle start packets, stop if arg == 0. - * Return void. */ - ACT_CYCLE_MASTER, - - /* Cancel all outstanding async requests without resetting the bus. - * Return void. */ - CANCEL_REQUESTS, -}; - -enum isoctl_cmd { - /* rawiso API - see iso.h for the meanings of these commands - * (they correspond exactly to the hpsb_iso_* API functions) - * INIT = allocate resources - * START = begin transmission/reception - * STOP = halt transmission/reception - * QUEUE/RELEASE = produce/consume packets - * SHUTDOWN = deallocate resources - */ - - XMIT_INIT, - XMIT_START, - XMIT_STOP, - XMIT_QUEUE, - XMIT_SHUTDOWN, - - RECV_INIT, - RECV_LISTEN_CHANNEL, /* multi-channel only */ - RECV_UNLISTEN_CHANNEL, /* multi-channel only */ - RECV_SET_CHANNEL_MASK, /* multi-channel only; arg is a *u64 */ - RECV_START, - RECV_STOP, - RECV_RELEASE, - RECV_SHUTDOWN, - RECV_FLUSH -}; - -enum reset_types { - /* 166 microsecond reset -- only type of reset available on - non-1394a capable controllers */ - LONG_RESET, - - /* Short (arbitrated) reset -- only available on 1394a capable - controllers */ - SHORT_RESET, - - /* Variants that set force_root before issueing the bus reset */ - LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT, - - /* Variants that clear force_root before issueing the bus reset */ - LONG_RESET_NO_FORCE_ROOT, SHORT_RESET_NO_FORCE_ROOT -}; - -struct hpsb_host_driver { - struct module *owner; - const char *name; - - /* The hardware driver may optionally support a function that is used - * to set the hardware ConfigROM if the hardware supports handling - * reads to the ConfigROM on its own. */ - void (*set_hw_config_rom)(struct hpsb_host *host, - __be32 *config_rom); - - /* This function shall implement packet transmission based on - * packet->type. It shall CRC both parts of the packet (unless - * packet->type == raw) and do byte-swapping as necessary or instruct - * the hardware to do so. It can return immediately after the packet - * was queued for sending. After sending, hpsb_sent_packet() has to be - * called. Return 0 on success, negative errno on failure. - * NOTE: The function must be callable in interrupt context. - */ - int (*transmit_packet)(struct hpsb_host *host, - struct hpsb_packet *packet); - - /* This function requests miscellanous services from the driver, see - * above for command codes and expected actions. Return -1 for unknown - * command, though that should never happen. - */ - int (*devctl)(struct hpsb_host *host, enum devctl_cmd command, int arg); - - /* ISO transmission/reception functions. Return 0 on success, -1 - * (or -EXXX errno code) on failure. If the low-level driver does not - * support the new ISO API, set isoctl to NULL. - */ - int (*isoctl)(struct hpsb_iso *iso, enum isoctl_cmd command, - unsigned long arg); - - /* This function is mainly to redirect local CSR reads/locks to the iso - * management registers (bus manager id, bandwidth available, channels - * available) to the hardware registers in OHCI. reg is 0,1,2,3 for bus - * mgr, bwdth avail, ch avail hi, ch avail lo respectively (the same ids - * as OHCI uses). data and compare are the new data and expected data - * respectively, return value is the old value. - */ - quadlet_t (*hw_csr_reg) (struct hpsb_host *host, int reg, - quadlet_t data, quadlet_t compare); -}; - -struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra, - struct device *dev); -int hpsb_add_host(struct hpsb_host *host); -void hpsb_resume_host(struct hpsb_host *host); -void hpsb_remove_host(struct hpsb_host *host); -int hpsb_update_config_rom_image(struct hpsb_host *host); - -#endif /* _IEEE1394_HOSTS_H */ diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h deleted file mode 100644 index 46878fe..0000000 --- a/drivers/ieee1394/ieee1394-ioctl.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Base file for all ieee1394 ioctl's. - * Linux-1394 has allocated base '#' with a range of 0x00-0x3f. - */ - -#ifndef __IEEE1394_IOCTL_H -#define __IEEE1394_IOCTL_H - -#include <linux/ioctl.h> -#include <linux/types.h> - -/* DV1394 Gets 10 */ - -/* Get the driver ready to transmit video. pass a struct dv1394_init* as - * the parameter (see below), or NULL to get default parameters */ -#define DV1394_IOC_INIT _IOW('#', 0x06, struct dv1394_init) - -/* Stop transmitting video and free the ringbuffer */ -#define DV1394_IOC_SHUTDOWN _IO ('#', 0x07) - -/* Submit N new frames to be transmitted, where the index of the first new - * frame is first_clear_buffer, and the index of the last new frame is - * (first_clear_buffer + N) % n_frames */ -#define DV1394_IOC_SUBMIT_FRAMES _IO ('#', 0x08) - -/* Block until N buffers are clear (pass N as the parameter) Because we - * re-transmit the last frame on underrun, there will at most be n_frames - * - 1 clear frames at any time */ -#define DV1394_IOC_WAIT_FRAMES _IO ('#', 0x09) - -/* Capture new frames that have been received, where the index of the - * first new frame is first_clear_buffer, and the index of the last new - * frame is (first_clear_buffer + N) % n_frames */ -#define DV1394_IOC_RECEIVE_FRAMES _IO ('#', 0x0a) - -/* Tell card to start receiving DMA */ -#define DV1394_IOC_START_RECEIVE _IO ('#', 0x0b) - -/* Pass a struct dv1394_status* as the parameter */ -#define DV1394_IOC_GET_STATUS _IOR('#', 0x0c, struct dv1394_status) - - -/* Video1394 Gets 10 */ - -#define VIDEO1394_IOC_LISTEN_CHANNEL \ - _IOWR('#', 0x10, struct video1394_mmap) -#define VIDEO1394_IOC_UNLISTEN_CHANNEL \ - _IOW ('#', 0x11, int) -#define VIDEO1394_IOC_LISTEN_QUEUE_BUFFER \ - _IOW ('#', 0x12, struct video1394_wait) -#define VIDEO1394_IOC_LISTEN_WAIT_BUFFER \ - _IOWR('#', 0x13, struct video1394_wait) -#define VIDEO1394_IOC_TALK_CHANNEL \ - _IOWR('#', 0x14, struct video1394_mmap) -#define VIDEO1394_IOC_UNTALK_CHANNEL \ - _IOW ('#', 0x15, int) -/* - * This one is broken: it really wanted - * "sizeof (struct video1394_wait) + sizeof (struct video1394_queue_variable)" - * but got just a "size_t" - */ -#define VIDEO1394_IOC_TALK_QUEUE_BUFFER \ - _IOW ('#', 0x16, size_t) -#define VIDEO1394_IOC_TALK_WAIT_BUFFER \ - _IOW ('#', 0x17, struct video1394_wait) -#define VIDEO1394_IOC_LISTEN_POLL_BUFFER \ - _IOWR('#', 0x18, struct video1394_wait) - - -/* Raw1394's ISO interface */ -#define RAW1394_IOC_ISO_XMIT_INIT \ - _IOW ('#', 0x1a, struct raw1394_iso_status) -#define RAW1394_IOC_ISO_RECV_INIT \ - _IOWR('#', 0x1b, struct raw1394_iso_status) -#define RAW1394_IOC_ISO_RECV_START \ - _IOC (_IOC_WRITE, '#', 0x1c, sizeof(int) * 3) -#define RAW1394_IOC_ISO_XMIT_START \ - _IOC (_IOC_WRITE, '#', 0x1d, sizeof(int) * 2) -#define RAW1394_IOC_ISO_XMIT_RECV_STOP \ - _IO ('#', 0x1e) -#define RAW1394_IOC_ISO_GET_STATUS \ - _IOR ('#', 0x1f, struct raw1394_iso_status) -#define RAW1394_IOC_ISO_SHUTDOWN \ - _IO ('#', 0x20) -#define RAW1394_IOC_ISO_QUEUE_ACTIVITY \ - _IO ('#', 0x21) -#define RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL \ - _IOW ('#', 0x22, unsigned char) -#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL \ - _IOW ('#', 0x23, unsigned char) -#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK \ - _IOW ('#', 0x24, __u64) -#define RAW1394_IOC_ISO_RECV_PACKETS \ - _IOW ('#', 0x25, struct raw1394_iso_packets) -#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS \ - _IOW ('#', 0x26, unsigned int) -#define RAW1394_IOC_ISO_XMIT_PACKETS \ - _IOW ('#', 0x27, struct raw1394_iso_packets) -#define RAW1394_IOC_ISO_XMIT_SYNC \ - _IO ('#', 0x28) -#define RAW1394_IOC_ISO_RECV_FLUSH \ - _IO ('#', 0x29) -#define RAW1394_IOC_GET_CYCLE_TIMER \ - _IOR ('#', 0x30, struct raw1394_cycle_timer) - -#endif /* __IEEE1394_IOCTL_H */ diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h deleted file mode 100644 index af320e2..0000000 --- a/drivers/ieee1394/ieee1394.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Generic IEEE 1394 definitions - */ - -#ifndef _IEEE1394_IEEE1394_H -#define _IEEE1394_IEEE1394_H - -#define TCODE_WRITEQ 0x0 -#define TCODE_WRITEB 0x1 -#define TCODE_WRITE_RESPONSE 0x2 -#define TCODE_READQ 0x4 -#define TCODE_READB 0x5 -#define TCODE_READQ_RESPONSE 0x6 -#define TCODE_READB_RESPONSE 0x7 -#define TCODE_CYCLE_START 0x8 -#define TCODE_LOCK_REQUEST 0x9 -#define TCODE_ISO_DATA 0xa -#define TCODE_STREAM_DATA 0xa -#define TCODE_LOCK_RESPONSE 0xb - -#define RCODE_COMPLETE 0x0 -#define RCODE_CONFLICT_ERROR 0x4 -#define RCODE_DATA_ERROR 0x5 -#define RCODE_TYPE_ERROR 0x6 -#define RCODE_ADDRESS_ERROR 0x7 - -#define EXTCODE_MASK_SWAP 0x1 -#define EXTCODE_COMPARE_SWAP 0x2 -#define EXTCODE_FETCH_ADD 0x3 -#define EXTCODE_LITTLE_ADD 0x4 -#define EXTCODE_BOUNDED_ADD 0x5 -#define EXTCODE_WRAP_ADD 0x6 - -#define ACK_COMPLETE 0x1 -#define ACK_PENDING 0x2 -#define ACK_BUSY_X 0x4 -#define ACK_BUSY_A 0x5 -#define ACK_BUSY_B 0x6 -#define ACK_TARDY 0xb -#define ACK_CONFLICT_ERROR 0xc -#define ACK_DATA_ERROR 0xd -#define ACK_TYPE_ERROR 0xe -#define ACK_ADDRESS_ERROR 0xf - -/* Non-standard "ACK codes" for internal use */ -#define ACKX_NONE (-1) -#define ACKX_SEND_ERROR (-2) -#define ACKX_ABORTED (-3) -#define ACKX_TIMEOUT (-4) - -#define IEEE1394_SPEED_100 0x00 -#define IEEE1394_SPEED_200 0x01 -#define IEEE1394_SPEED_400 0x02 -#define IEEE1394_SPEED_800 0x03 -#define IEEE1394_SPEED_1600 0x04 -#define IEEE1394_SPEED_3200 0x05 -#define IEEE1394_SPEED_MAX IEEE1394_SPEED_3200 - -/* Maps speed values above to a string representation */ -extern const char *hpsb_speedto_str[]; - -/* 1394a cable PHY packets */ -#define SELFID_PWRCL_NO_POWER 0x0 -#define SELFID_PWRCL_PROVIDE_15W 0x1 -#define SELFID_PWRCL_PROVIDE_30W 0x2 -#define SELFID_PWRCL_PROVIDE_45W 0x3 -#define SELFID_PWRCL_USE_1W 0x4 -#define SELFID_PWRCL_USE_3W 0x5 -#define SELFID_PWRCL_USE_6W 0x6 -#define SELFID_PWRCL_USE_10W 0x7 - -#define SELFID_PORT_CHILD 0x3 -#define SELFID_PORT_PARENT 0x2 -#define SELFID_PORT_NCONN 0x1 -#define SELFID_PORT_NONE 0x0 - -#define SELFID_SPEED_UNKNOWN 0x3 /* 1394b PHY */ - -#define PHYPACKET_LINKON 0x40000000 -#define PHYPACKET_PHYCONFIG_R 0x00800000 -#define PHYPACKET_PHYCONFIG_T 0x00400000 -#define EXTPHYPACKET_TYPE_PING 0x00000000 -#define EXTPHYPACKET_TYPE_REMOTEACCESS_BASE 0x00040000 -#define EXTPHYPACKET_TYPE_REMOTEACCESS_PAGED 0x00140000 -#define EXTPHYPACKET_TYPE_REMOTEREPLY_BASE 0x000C0000 -#define EXTPHYPACKET_TYPE_REMOTEREPLY_PAGED 0x001C0000 -#define EXTPHYPACKET_TYPE_REMOTECOMMAND 0x00200000 -#define EXTPHYPACKET_TYPE_REMOTECONFIRMATION 0x00280000 -#define EXTPHYPACKET_TYPE_RESUME 0x003C0000 - -#define EXTPHYPACKET_TYPEMASK 0xC0FC0000 - -#define PHYPACKET_PORT_SHIFT 24 -#define PHYPACKET_GAPCOUNT_SHIFT 16 - -/* 1394a PHY register map bitmasks */ -#define PHY_00_PHYSICAL_ID 0xFC -#define PHY_00_R 0x02 /* Root */ -#define PHY_00_PS 0x01 /* Power Status*/ -#define PHY_01_RHB 0x80 /* Root Hold-Off */ -#define PHY_01_IBR 0x80 /* Initiate Bus Reset */ -#define PHY_01_GAP_COUNT 0x3F -#define PHY_02_EXTENDED 0xE0 /* 0x7 for 1394a-compliant PHY */ -#define PHY_02_TOTAL_PORTS 0x1F -#define PHY_03_MAX_SPEED 0xE0 -#define PHY_03_DELAY 0x0F -#define PHY_04_LCTRL 0x80 /* Link Active Report Control */ -#define PHY_04_CONTENDER 0x40 -#define PHY_04_JITTER 0x38 -#define PHY_04_PWR_CLASS 0x07 /* Power Class */ -#define PHY_05_WATCHDOG 0x80 -#define PHY_05_ISBR 0x40 /* Initiate Short Bus Reset */ -#define PHY_05_LOOP 0x20 /* Loop Detect */ -#define PHY_05_PWR_FAIL 0x10 /* Cable Power Failure Detect */ -#define PHY_05_TIMEOUT 0x08 /* Arbitration State Machine Timeout */ -#define PHY_05_PORT_EVENT 0x04 /* Port Event Detect */ -#define PHY_05_ENAB_ACCEL 0x02 /* Enable Arbitration Acceleration */ -#define PHY_05_ENAB_MULTI 0x01 /* Ena. Multispeed Packet Concatenation */ - -#include <asm/byteorder.h> - -/* '1' '3' '9' '4' in ASCII */ -#define IEEE1394_BUSID_MAGIC cpu_to_be32(0x31333934) - -#ifdef __BIG_ENDIAN_BITFIELD - -struct selfid { - u32 packet_identifier:2; /* always binary 10 */ - u32 phy_id:6; - /* byte */ - u32 extended:1; /* if true is struct ext_selfid */ - u32 link_active:1; - u32 gap_count:6; - /* byte */ - u32 speed:2; - u32 phy_delay:2; - u32 contender:1; - u32 power_class:3; - /* byte */ - u32 port0:2; - u32 port1:2; - u32 port2:2; - u32 initiated_reset:1; - u32 more_packets:1; -} __attribute__((packed)); - -struct ext_selfid { - u32 packet_identifier:2; /* always binary 10 */ - u32 phy_id:6; - /* byte */ - u32 extended:1; /* if false is struct selfid */ - u32 seq_nr:3; - u32 reserved:2; - u32 porta:2; - /* byte */ - u32 portb:2; - u32 portc:2; - u32 portd:2; - u32 porte:2; - /* byte */ - u32 portf:2; - u32 portg:2; - u32 porth:2; - u32 reserved2:1; - u32 more_packets:1; -} __attribute__((packed)); - -#elif defined __LITTLE_ENDIAN_BITFIELD /* __BIG_ENDIAN_BITFIELD */ - -/* - * Note: these mean to be bit fields of a big endian SelfID as seen on a little - * endian machine. Without swapping. - */ - -struct selfid { - u32 phy_id:6; - u32 packet_identifier:2; /* always binary 10 */ - /* byte */ - u32 gap_count:6; - u32 link_active:1; - u32 extended:1; /* if true is struct ext_selfid */ - /* byte */ - u32 power_class:3; - u32 contender:1; - u32 phy_delay:2; - u32 speed:2; - /* byte */ - u32 more_packets:1; - u32 initiated_reset:1; - u32 port2:2; - u32 port1:2; - u32 port0:2; -} __attribute__((packed)); - -struct ext_selfid { - u32 phy_id:6; - u32 packet_identifier:2; /* always binary 10 */ - /* byte */ - u32 porta:2; - u32 reserved:2; - u32 seq_nr:3; - u32 extended:1; /* if false is struct selfid */ - /* byte */ - u32 porte:2; - u32 portd:2; - u32 portc:2; - u32 portb:2; - /* byte */ - u32 more_packets:1; - u32 reserved2:1; - u32 porth:2; - u32 portg:2; - u32 portf:2; -} __attribute__((packed)); - -#else -#error What? PDP endian? -#endif /* __BIG_ENDIAN_BITFIELD */ - -#endif /* _IEEE1394_IEEE1394_H */ diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c deleted file mode 100644 index 8723380..0000000 --- a/drivers/ieee1394/ieee1394_core.c +++ /dev/null @@ -1,1380 +0,0 @@ -/* - * IEEE 1394 for Linux - * - * Core support: hpsb_packet management, packet handling and forwarding to - * highlevel or lowlevel code - * - * Copyright (C) 1999, 2000 Andreas E. Bombe - * 2002 Manfred Weihs <weihs@ict.tuwien.ac.at> - * - * This code is licensed under the GPL. See the file COPYING in the root - * directory of the kernel sources for details. - * - * - * Contributions: - * - * Manfred Weihs <weihs@ict.tuwien.ac.at> - * loopback functionality in hpsb_send_packet - * allow highlevel drivers to disable automatic response generation - * and to generate responses themselves (deferred) - * - */ - -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/bitops.h> -#include <linux/kdev_t.h> -#include <linux/freezer.h> -#include <linux/suspend.h> -#include <linux/kthread.h> -#include <linux/preempt.h> -#include <linux/time.h> - -#include <asm/system.h> -#include <asm/byteorder.h> - -#include "ieee1394_types.h" -#include "ieee1394.h" -#include "hosts.h" -#include "ieee1394_core.h" -#include "highlevel.h" -#include "ieee1394_transactions.h" -#include "csr.h" -#include "nodemgr.h" -#include "dma.h" -#include "iso.h" -#include "config_roms.h" - -/* - * Disable the nodemgr detection and config rom reading functionality. - */ -static int disable_nodemgr; -module_param(disable_nodemgr, int, 0444); -MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality."); - -/* Disable Isochronous Resource Manager functionality */ -int hpsb_disable_irm = 0; -module_param_named(disable_irm, hpsb_disable_irm, bool, 0444); -MODULE_PARM_DESC(disable_irm, - "Disable Isochronous Resource Manager functionality."); - -/* We are GPL, so treat us special */ -MODULE_LICENSE("GPL"); - -/* Some globals used */ -const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" }; -struct class *hpsb_protocol_class; - -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG -static void dump_packet(const char *text, quadlet_t *data, int size, int speed) -{ - int i; - - size /= 4; - size = (size > 4 ? 4 : size); - - printk(KERN_DEBUG "ieee1394: %s", text); - if (speed > -1 && speed < 6) - printk(" at %s", hpsb_speedto_str[speed]); - printk(":"); - for (i = 0; i < size; i++) - printk(" %08x", data[i]); - printk("\n"); -} -#else -#define dump_packet(a,b,c,d) do {} while (0) -#endif - -static void abort_requests(struct hpsb_host *host); -static void queue_packet_complete(struct hpsb_packet *packet); - - -/** - * hpsb_set_packet_complete_task - set task that runs when a packet completes - * @packet: the packet whose completion we want the task added to - * @routine: function to call - * @data: data (if any) to pass to the above function - * - * Set the task that runs when a packet completes. You cannot call this more - * than once on a single packet before it is sent. - * - * Typically, the complete @routine is responsible to call hpsb_free_packet(). - */ -void hpsb_set_packet_complete_task(struct hpsb_packet *packet, - void (*routine)(void *), void *data) -{ - WARN_ON(packet->complete_routine != NULL); - packet->complete_routine = routine; - packet->complete_data = data; - return; -} - -/** - * hpsb_alloc_packet - allocate new packet structure - * @data_size: size of the data block to be allocated, in bytes - * - * This function allocates, initializes and returns a new &struct hpsb_packet. - * It can be used in interrupt context. A header block is always included and - * initialized with zeros. Its size is big enough to contain all possible 1394 - * headers. The data block is only allocated if @data_size is not zero. - * - * For packets for which responses will be received the @data_size has to be big - * enough to contain the response's data block since no further allocation - * occurs at response matching time. - * - * The packet's generation value will be set to the current generation number - * for ease of use. Remember to overwrite it with your own recorded generation - * number if you can not be sure that your code will not race with a bus reset. - * - * Return value: A pointer to a &struct hpsb_packet or NULL on allocation - * failure. - */ -struct hpsb_packet *hpsb_alloc_packet(size_t data_size) -{ - struct hpsb_packet *packet; - - data_size = ((data_size + 3) & ~3); - - packet = kzalloc(sizeof(*packet) + data_size, GFP_ATOMIC); - if (!packet) - return NULL; - - packet->state = hpsb_unused; - packet->generation = -1; - INIT_LIST_HEAD(&packet->driver_list); - INIT_LIST_HEAD(&packet->queue); - atomic_set(&packet->refcnt, 1); - - if (data_size) { - packet->data = packet->embedded_data; - packet->allocated_data_size = data_size; - } - return packet; -} - -/** - * hpsb_free_packet - free packet and data associated with it - * @packet: packet to free (is NULL safe) - * - * Frees @packet->data only if it was allocated through hpsb_alloc_packet(). - */ -void hpsb_free_packet(struct hpsb_packet *packet) -{ - if (packet && atomic_dec_and_test(&packet->refcnt)) { - BUG_ON(!list_empty(&packet->driver_list) || - !list_empty(&packet->queue)); - kfree(packet); - } -} - -/** - * hpsb_reset_bus - initiate bus reset on the given host - * @host: host controller whose bus to reset - * @type: one of enum reset_types - * - * Returns 1 if bus reset already in progress, 0 otherwise. - */ -int hpsb_reset_bus(struct hpsb_host *host, int type) -{ - if (!host->in_bus_reset) { - host->driver->devctl(host, RESET_BUS, type); - return 0; - } else { - return 1; - } -} - -/** - * hpsb_read_cycle_timer - read cycle timer register and system time - * @host: host whose isochronous cycle timer register is read - * @cycle_timer: address of bitfield to return the register contents - * @local_time: address to return the system time - * - * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This - * format is also read from non-OHCI controllers. * @local_time contains the - * system time in microseconds since the Epoch, read at the moment when the - * cycle timer was read. - * - * Return value: 0 for success or error number otherwise. - */ -int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer, - u64 *local_time) -{ - int ctr; - struct timeval tv; - unsigned long flags; - - if (!host || !cycle_timer || !local_time) - return -EINVAL; - - preempt_disable(); - local_irq_save(flags); - - ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0); - if (ctr) - do_gettimeofday(&tv); - - local_irq_restore(flags); - preempt_enable(); - - if (!ctr) - return -EIO; - *cycle_timer = ctr; - *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec; - return 0; -} - -/** - * hpsb_bus_reset - notify a bus reset to the core - * - * For host driver module usage. Safe to use in interrupt context, although - * quite complex; so you may want to run it in the bottom rather than top half. - * - * Returns 1 if bus reset already in progress, 0 otherwise. - */ -int hpsb_bus_reset(struct hpsb_host *host) -{ - if (host->in_bus_reset) { - HPSB_NOTICE("%s called while bus reset already in progress", - __func__); - return 1; - } - - abort_requests(host); - host->in_bus_reset = 1; - host->irm_id = -1; - host->is_irm = 0; - host->busmgr_id = -1; - host->is_busmgr = 0; - host->is_cycmst = 0; - host->node_count = 0; - host->selfid_count = 0; - - return 0; -} - - -/* - * Verify num_of_selfids SelfIDs and return number of nodes. Return zero in - * case verification failed. - */ -static int check_selfids(struct hpsb_host *host) -{ - int nodeid = -1; - int rest_of_selfids = host->selfid_count; - struct selfid *sid = (struct selfid *)host->topology_map; - struct ext_selfid *esid; - int esid_seq = 23; - - host->nodes_active = 0; - - while (rest_of_selfids--) { - if (!sid->extended) { - nodeid++; - esid_seq = 0; - - if (sid->phy_id != nodeid) { - HPSB_INFO("SelfIDs failed monotony check with " - "%d", sid->phy_id); - return 0; - } - - if (sid->link_active) { - host->nodes_active++; - if (sid->contender) - host->irm_id = LOCAL_BUS | sid->phy_id; - } - } else { - esid = (struct ext_selfid *)sid; - - if ((esid->phy_id != nodeid) - || (esid->seq_nr != esid_seq)) { - HPSB_INFO("SelfIDs failed monotony check with " - "%d/%d", esid->phy_id, esid->seq_nr); - return 0; - } - esid_seq++; - } - sid++; - } - - esid = (struct ext_selfid *)(sid - 1); - while (esid->extended) { - if ((esid->porta == SELFID_PORT_PARENT) || - (esid->portb == SELFID_PORT_PARENT) || - (esid->portc == SELFID_PORT_PARENT) || - (esid->portd == SELFID_PORT_PARENT) || - (esid->porte == SELFID_PORT_PARENT) || - (esid->portf == SELFID_PORT_PARENT) || - (esid->portg == SELFID_PORT_PARENT) || - (esid->porth == SELFID_PORT_PARENT)) { - HPSB_INFO("SelfIDs failed root check on " - "extended SelfID"); - return 0; - } - esid--; - } - - sid = (struct selfid *)esid; - if ((sid->port0 == SELFID_PORT_PARENT) || - (sid->port1 == SELFID_PORT_PARENT) || - (sid->port2 == SELFID_PORT_PARENT)) { - HPSB_INFO("SelfIDs failed root check"); - return 0; - } - - host->node_count = nodeid + 1; - return 1; -} - -static void build_speed_map(struct hpsb_host *host, int nodecount) -{ - u8 cldcnt[nodecount]; - u8 *map = host->speed_map; - u8 *speedcap = host->speed; - u8 local_link_speed = host->csr.lnk_spd; - struct selfid *sid; - struct ext_selfid *esid; - int i, j, n; - - for (i = 0; i < (nodecount * 64); i += 64) { - for (j = 0; j < nodecount; j++) { - map[i+j] = IEEE1394_SPEED_MAX; - } - } - - for (i = 0; i < nodecount; i++) { - cldcnt[i] = 0; - } - - /* find direct children count and speed */ - for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1], - n = nodecount - 1; - (void *)sid >= (void *)host->topology_map; sid--) { - if (sid->extended) { - esid = (struct ext_selfid *)sid; - - if (esid->porta == SELFID_PORT_CHILD) cldcnt[n]++; - if (esid->portb == SELFID_PORT_CHILD) cldcnt[n]++; - if (esid->portc == SELFID_PORT_CHILD) cldcnt[n]++; - if (esid->portd == SELFID_PORT_CHILD) cldcnt[n]++; - if (esid->porte == SELFID_PORT_CHILD) cldcnt[n]++; - if (esid->portf == SELFID_PORT_CHILD) cldcnt[n]++; - if (esid->portg == SELFID_PORT_CHILD) cldcnt[n]++; - if (esid->porth == SELFID_PORT_CHILD) cldcnt[n]++; - } else { - if (sid->port0 == SELFID_PORT_CHILD) cldcnt[n]++; - if (sid->port1 == SELFID_PORT_CHILD) cldcnt[n]++; - if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++; - - speedcap[n] = sid->speed; - if (speedcap[n] > local_link_speed) - speedcap[n] = local_link_speed; - n--; - } - } - - /* set self mapping */ - for (i = 0; i < nodecount; i++) { - map[64*i + i] = speedcap[i]; - } - - /* fix up direct children count to total children count; - * also fix up speedcaps for sibling and parent communication */ - for (i = 1; i < nodecount; i++) { - for (j = cldcnt[i], n = i - 1; j > 0; j--) { - cldcnt[i] += cldcnt[n]; - speedcap[n] = min(speedcap[n], speedcap[i]); - n -= cldcnt[n] + 1; - } - } - - for (n = 0; n < nodecount; n++) { - for (i = n - cldcnt[n]; i <= n; i++) { - for (j = 0; j < (n - cldcnt[n]); j++) { - map[j*64 + i] = map[i*64 + j] = - min(map[i*64 + j], speedcap[n]); - } - for (j = n + 1; j < nodecount; j++) { - map[j*64 + i] = map[i*64 + j] = - min(map[i*64 + j], speedcap[n]); - } - } - } - - /* assume a maximum speed for 1394b PHYs, nodemgr will correct it */ - if (local_link_speed > SELFID_SPEED_UNKNOWN) - for (i = 0; i < nodecount; i++) - if (speedcap[i] == SELFID_SPEED_UNKNOWN) - speedcap[i] = local_link_speed; -} - - -/** - * hpsb_selfid_received - hand over received selfid packet to the core - * - * For host driver module usage. Safe to use in interrupt context. - * - * The host driver should have done a successful complement check (second - * quadlet is complement of first) beforehand. - */ -void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid) -{ - if (host->in_bus_reset) { - HPSB_VERBOSE("Including SelfID 0x%x", sid); - host->topology_map[host->selfid_count++] = sid; - } else { - HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d", - sid, NODEID_TO_BUS(host->node_id)); - } -} - -/** - * hpsb_selfid_complete - notify completion of SelfID stage to the core - * - * For host driver module usage. Safe to use in interrupt context, although - * quite complex; so you may want to run it in the bottom rather than top half. - * - * Notify completion of SelfID stage to the core and report new physical ID - * and whether host is root now. - */ -void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) -{ - if (!host->in_bus_reset) - HPSB_NOTICE("SelfID completion called outside of bus reset!"); - - host->node_id = LOCAL_BUS | phyid; - host->is_root = isroot; - - if (!check_selfids(host)) { - if (host->reset_retries++ < 20) { - /* selfid stage did not complete without error */ - HPSB_NOTICE("Error in SelfID stage, resetting"); - host->in_bus_reset = 0; - /* this should work from ohci1394 now... */ - hpsb_reset_bus(host, LONG_RESET); - return; - } else { - HPSB_NOTICE("Stopping out-of-control reset loop"); - HPSB_NOTICE("Warning - topology map and speed map will not be valid"); - host->reset_retries = 0; - } - } else { - host->reset_retries = 0; - build_speed_map(host, host->node_count); - } - - HPSB_VERBOSE("selfid_complete called with successful SelfID stage " - "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id); - - /* irm_id is kept up to date by check_selfids() */ - if (host->irm_id == host->node_id) { - host->is_irm = 1; - } else { - host->is_busmgr = 0; - host->is_irm = 0; - } - - if (isroot) { - host->driver->devctl(host, ACT_CYCLE_MASTER, 1); - host->is_cycmst = 1; - } - atomic_inc(&host->generation); - host->in_bus_reset = 0; - highlevel_host_reset(host); -} - -static DEFINE_SPINLOCK(pending_packets_lock); - -/** - * hpsb_packet_sent - notify core of sending a packet - * - * For host driver module usage. Safe to call from within a transmit packet - * routine. - * - * Notify core of sending a packet. Ackcode is the ack code returned for async - * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE - * for other cases (internal errors that don't justify a panic). - */ -void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, - int ackcode) -{ - unsigned long flags; - - spin_lock_irqsave(&pending_packets_lock, flags); - - packet->ack_code = ackcode; - - if (packet->no_waiter || packet->state == hpsb_complete) { - /* if packet->no_waiter, must not have a tlabel allocated */ - spin_unlock_irqrestore(&pending_packets_lock, flags); - hpsb_free_packet(packet); - return; - } - - atomic_dec(&packet->refcnt); /* drop HC's reference */ - /* here the packet must be on the host->pending_packets queue */ - - if (ackcode != ACK_PENDING || !packet->expect_response) { - packet->state = hpsb_complete; - list_del_init(&packet->queue); - spin_unlock_irqrestore(&pending_packets_lock, flags); - queue_packet_complete(packet); - return; - } - - packet->state = hpsb_pending; - packet->sendtime = jiffies; - - spin_unlock_irqrestore(&pending_packets_lock, flags); - - mod_timer(&host->timeout, jiffies + host->timeout_interval); -} - -/** - * hpsb_send_phy_config - transmit a PHY configuration packet on the bus - * @host: host that PHY config packet gets sent through - * @rootid: root whose force_root bit should get set (-1 = don't set force_root) - * @gapcnt: gap count value to set (-1 = don't set gap count) - * - * This function sends a PHY config packet on the bus through the specified - * host. - * - * Return value: 0 for success or negative error number otherwise. - */ -int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt) -{ - struct hpsb_packet *packet; - quadlet_t d = 0; - int retval = 0; - - if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 || - (rootid == -1 && gapcnt == -1)) { - HPSB_DEBUG("Invalid Parameter: rootid = %d gapcnt = %d", - rootid, gapcnt); - return -EINVAL; - } - - if (rootid != -1) - d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT; - if (gapcnt != -1) - d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT; - - packet = hpsb_make_phypacket(host, d); - if (!packet) - return -ENOMEM; - - packet->generation = get_hpsb_generation(host); - retval = hpsb_send_packet_and_wait(packet); - hpsb_free_packet(packet); - - return retval; -} - -/** - * hpsb_send_packet - transmit a packet on the bus - * @packet: packet to send - * - * The packet is sent through the host specified in the packet->host field. - * Before sending, the packet's transmit speed is automatically determined - * using the local speed map when it is an async, non-broadcast packet. - * - * Possibilities for failure are that host is either not initialized, in bus - * reset, the packet's generation number doesn't match the current generation - * number or the host reports a transmit error. - * - * Return value: 0 on success, negative errno on failure. - */ -int hpsb_send_packet(struct hpsb_packet *packet) -{ - struct hpsb_host *host = packet->host; - - if (host->is_shutdown) - return -EINVAL; - if (host->in_bus_reset || - (packet->generation != get_hpsb_generation(host))) - return -EAGAIN; - - packet->state = hpsb_queued; - - /* This just seems silly to me */ - WARN_ON(packet->no_waiter && packet->expect_response); - - if (!packet->no_waiter || packet->expect_response) { - unsigned long flags; - - atomic_inc(&packet->refcnt); - /* Set the initial "sendtime" to 10 seconds from now, to - prevent premature expiry. If a packet takes more than - 10 seconds to hit the wire, we have bigger problems :) */ - packet->sendtime = jiffies + 10 * HZ; - spin_lock_irqsave(&pending_packets_lock, flags); - list_add_tail(&packet->queue, &host->pending_packets); - spin_unlock_irqrestore(&pending_packets_lock, flags); - } - - if (packet->node_id == host->node_id) { - /* it is a local request, so handle it locally */ - - quadlet_t *data; - size_t size = packet->data_size + packet->header_size; - - data = kmalloc(size, GFP_ATOMIC); - if (!data) { - HPSB_ERR("unable to allocate memory for concatenating header and data"); - return -ENOMEM; - } - - memcpy(data, packet->header, packet->header_size); - - if (packet->data_size) - memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size); - - dump_packet("send packet local", packet->header, packet->header_size, -1); - - hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE); - hpsb_packet_received(host, data, size, 0); - - kfree(data); - - return 0; - } - - if (packet->type == hpsb_async && - NODEID_TO_NODE(packet->node_id) != ALL_NODES) - packet->speed_code = - host->speed[NODEID_TO_NODE(packet->node_id)]; - - dump_packet("send packet", packet->header, packet->header_size, packet->speed_code); - - return host->driver->transmit_packet(host, packet); -} - -/* We could just use complete() directly as the packet complete - * callback, but this is more typesafe, in the sense that we get a - * compiler error if the prototype for complete() changes. */ - -static void complete_packet(void *data) -{ - complete((struct completion *) data); -} - -/** - * hpsb_send_packet_and_wait - enqueue packet, block until transaction completes - * @packet: packet to send - * - * Return value: 0 on success, negative errno on failure. - */ -int hpsb_send_packet_and_wait(struct hpsb_packet *packet) -{ - struct completion done; - int retval; - - init_completion(&done); - hpsb_set_packet_complete_task(packet, complete_packet, &done); - retval = hpsb_send_packet(packet); - if (retval == 0) - wait_for_completion(&done); - - return retval; -} - -static void send_packet_nocare(struct hpsb_packet *packet) -{ - if (hpsb_send_packet(packet) < 0) { - hpsb_free_packet(packet); - } -} - -static size_t packet_size_to_data_size(size_t packet_size, size_t header_size, - size_t buffer_size, int tcode) -{ - size_t ret = packet_size <= header_size ? 0 : packet_size - header_size; - - if (unlikely(ret > buffer_size)) - ret = buffer_size; - - if (unlikely(ret + header_size != packet_size)) - HPSB_ERR("unexpected packet size %zd (tcode %d), bug?", - packet_size, tcode); - return ret; -} - -static void handle_packet_response(struct hpsb_host *host, int tcode, - quadlet_t *data, size_t size) -{ - struct hpsb_packet *packet; - int tlabel = (data[0] >> 10) & 0x3f; - size_t header_size; - unsigned long flags; - - spin_lock_irqsave(&pending_packets_lock, flags); - - list_for_each_entry(packet, &host->pending_packets, queue) - if (packet->tlabel == tlabel && - packet->node_id == (data[1] >> 16)) - goto found; - - spin_unlock_irqrestore(&pending_packets_lock, flags); - HPSB_DEBUG("unsolicited response packet received - %s", - "no tlabel match"); - dump_packet("contents", data, 16, -1); - return; - -found: - switch (packet->tcode) { - case TCODE_WRITEQ: - case TCODE_WRITEB: - if (unlikely(tcode != TCODE_WRITE_RESPONSE)) - break; - header_size = 12; - size = 0; - goto dequeue; - - case TCODE_READQ: - if (unlikely(tcode != TCODE_READQ_RESPONSE)) - break; - header_size = 16; - size = 0; - goto dequeue; - - case TCODE_READB: - if (unlikely(tcode != TCODE_READB_RESPONSE)) - break; - header_size = 16; - size = packet_size_to_data_size(size, header_size, - packet->allocated_data_size, - tcode); - goto dequeue; - - case TCODE_LOCK_REQUEST: - if (unlikely(tcode != TCODE_LOCK_RESPONSE)) - break; - header_size = 16; - size = packet_size_to_data_size(min(size, (size_t)(16 + 8)), - header_size, - packet->allocated_data_size, - tcode); - goto dequeue; - } - - spin_unlock_irqrestore(&pending_packets_lock, flags); - HPSB_DEBUG("unsolicited response packet received - %s", - "tcode mismatch"); - dump_packet("contents", data, 16, -1); - return; - -dequeue: - list_del_init(&packet->queue); - spin_unlock_irqrestore(&pending_packets_lock, flags); - - if (packet->state == hpsb_queued) { - packet->sendtime = jiffies; - packet->ack_code = ACK_PENDING; - } - packet->state = hpsb_complete; - - memcpy(packet->header, data, header_size); - if (size) - memcpy(packet->data, data + 4, size); - - queue_packet_complete(packet); -} - - -static struct hpsb_packet *create_reply_packet(struct hpsb_host *host, - quadlet_t *data, size_t dsize) -{ - struct hpsb_packet *p; - - p = hpsb_alloc_packet(dsize); - if (unlikely(p == NULL)) { - /* FIXME - send data_error response */ - HPSB_ERR("out of memory, cannot send response packet"); - return NULL; - } - - p->type = hpsb_async; - p->state = hpsb_unused; - p->host = host; - p->node_id = data[1] >> 16; - p->tlabel = (data[0] >> 10) & 0x3f; - p->no_waiter = 1; - - p->generation = get_hpsb_generation(host); - - if (dsize % 4) - p->data[dsize / 4] = 0; - - return p; -} - -#define PREP_ASYNC_HEAD_RCODE(tc) \ - packet->tcode = tc; \ - packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \ - | (1 << 8) | (tc << 4); \ - packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \ - packet->header[2] = 0 - -static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode, - quadlet_t data) -{ - PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE); - packet->header[3] = data; - packet->header_size = 16; - packet->data_size = 0; -} - -static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, - int length) -{ - if (rcode != RCODE_COMPLETE) - length = 0; - - PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE); - packet->header[3] = length << 16; - packet->header_size = 16; - packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0); -} - -static void fill_async_write_resp(struct hpsb_packet *packet, int rcode) -{ - PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE); - packet->header_size = 12; - packet->data_size = 0; -} - -static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode, - int length) -{ - if (rcode != RCODE_COMPLETE) - length = 0; - - PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE); - packet->header[3] = (length << 16) | extcode; - packet->header_size = 16; - packet->data_size = length; -} - -static void handle_incoming_packet(struct hpsb_host *host, int tcode, - quadlet_t *data, size_t size, - int write_acked) -{ - struct hpsb_packet *packet; - int length, rcode, extcode; - quadlet_t buffer; - nodeid_t source = data[1] >> 16; - nodeid_t dest = data[0] >> 16; - u16 flags = (u16) data[0]; - u64 addr; - - /* FIXME? - * Out-of-bounds lengths are left for highlevel_read|write to cap. */ - - switch (tcode) { - case TCODE_WRITEQ: - addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_write(host, source, dest, data + 3, - addr, 4, flags); - goto handle_write_request; - - case TCODE_WRITEB: - addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_write(host, source, dest, data + 4, - addr, data[3] >> 16, flags); -handle_write_request: - if (rcode < 0 || write_acked || - NODEID_TO_NODE(data[0] >> 16) == NODE_MASK) - return; - /* not a broadcast write, reply */ - packet = create_reply_packet(host, data, 0); - if (packet) { - fill_async_write_resp(packet, rcode); - send_packet_nocare(packet); - } - return; - - case TCODE_READQ: - addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_read(host, source, &buffer, addr, 4, flags); - if (rcode < 0) - return; - - packet = create_reply_packet(host, data, 0); - if (packet) { - fill_async_readquad_resp(packet, rcode, buffer); - send_packet_nocare(packet); - } - return; - - case TCODE_READB: - length = data[3] >> 16; - packet = create_reply_packet(host, data, length); - if (!packet) - return; - - addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_read(host, source, packet->data, addr, - length, flags); - if (rcode < 0) { - hpsb_free_packet(packet); - return; - } - fill_async_readblock_resp(packet, rcode, length); - send_packet_nocare(packet); - return; - - case TCODE_LOCK_REQUEST: - length = data[3] >> 16; - extcode = data[3] & 0xffff; - addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - - packet = create_reply_packet(host, data, 8); - if (!packet) - return; - - if (extcode == 0 || extcode >= 7) { - /* let switch default handle error */ - length = 0; - } - - switch (length) { - case 4: - rcode = highlevel_lock(host, source, packet->data, addr, - data[4], 0, extcode, flags); - fill_async_lock_resp(packet, rcode, extcode, 4); - break; - case 8: - if (extcode != EXTCODE_FETCH_ADD && - extcode != EXTCODE_LITTLE_ADD) { - rcode = highlevel_lock(host, source, - packet->data, addr, - data[5], data[4], - extcode, flags); - fill_async_lock_resp(packet, rcode, extcode, 4); - } else { - rcode = highlevel_lock64(host, source, - (octlet_t *)packet->data, addr, - *(octlet_t *)(data + 4), 0ULL, - extcode, flags); - fill_async_lock_resp(packet, rcode, extcode, 8); - } - break; - case 16: - rcode = highlevel_lock64(host, source, - (octlet_t *)packet->data, addr, - *(octlet_t *)(data + 6), - *(octlet_t *)(data + 4), - extcode, flags); - fill_async_lock_resp(packet, rcode, extcode, 8); - break; - default: - rcode = RCODE_TYPE_ERROR; - fill_async_lock_resp(packet, rcode, extcode, 0); - } - - if (rcode < 0) - hpsb_free_packet(packet); - else - send_packet_nocare(packet); - return; - } -} - -/** - * hpsb_packet_received - hand over received packet to the core - * - * For host driver module usage. - * - * The contents of data are expected to be the full packet but with the CRCs - * left out (data block follows header immediately), with the header (i.e. the - * first four quadlets) in machine byte order and the data block in big endian. - * *@data can be safely overwritten after this call. - * - * If the packet is a write request, @write_acked is to be set to true if it was - * ack_complete'd already, false otherwise. This argument is ignored for any - * other packet type. - */ -void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, - int write_acked) -{ - int tcode; - - if (unlikely(host->in_bus_reset)) { - HPSB_DEBUG("received packet during reset; ignoring"); - return; - } - - dump_packet("received packet", data, size, -1); - - tcode = (data[0] >> 4) & 0xf; - - switch (tcode) { - case TCODE_WRITE_RESPONSE: - case TCODE_READQ_RESPONSE: - case TCODE_READB_RESPONSE: - case TCODE_LOCK_RESPONSE: - handle_packet_response(host, tcode, data, size); - break; - - case TCODE_WRITEQ: - case TCODE_WRITEB: - case TCODE_READQ: - case TCODE_READB: - case TCODE_LOCK_REQUEST: - handle_incoming_packet(host, tcode, data, size, write_acked); - break; - - case TCODE_CYCLE_START: - /* simply ignore this packet if it is passed on */ - break; - - default: - HPSB_DEBUG("received packet with bogus transaction code %d", - tcode); - break; - } -} - -static void abort_requests(struct hpsb_host *host) -{ - struct hpsb_packet *packet, *p; - struct list_head tmp; - unsigned long flags; - - host->driver->devctl(host, CANCEL_REQUESTS, 0); - - INIT_LIST_HEAD(&tmp); - spin_lock_irqsave(&pending_packets_lock, flags); - list_splice_init(&host->pending_packets, &tmp); - spin_unlock_irqrestore(&pending_packets_lock, flags); - - list_for_each_entry_safe(packet, p, &tmp, queue) { - list_del_init(&packet->queue); - packet->state = hpsb_complete; - packet->ack_code = ACKX_ABORTED; - queue_packet_complete(packet); - } -} - -void abort_timedouts(unsigned long __opaque) -{ - struct hpsb_host *host = (struct hpsb_host *)__opaque; - struct hpsb_packet *packet, *p; - struct list_head tmp; - unsigned long flags, expire, j; - - spin_lock_irqsave(&host->csr.lock, flags); - expire = host->csr.expire; - spin_unlock_irqrestore(&host->csr.lock, flags); - - j = jiffies; - INIT_LIST_HEAD(&tmp); - spin_lock_irqsave(&pending_packets_lock, flags); - - list_for_each_entry_safe(packet, p, &host->pending_packets, queue) { - if (time_before(packet->sendtime + expire, j)) - list_move_tail(&packet->queue, &tmp); - else - /* Since packets are added to the tail, the oldest - * ones are first, always. When we get to one that - * isn't timed out, the rest aren't either. */ - break; - } - if (!list_empty(&host->pending_packets)) - mod_timer(&host->timeout, j + host->timeout_interval); - - spin_unlock_irqrestore(&pending_packets_lock, flags); - - list_for_each_entry_safe(packet, p, &tmp, queue) { - list_del_init(&packet->queue); - packet->state = hpsb_complete; - packet->ack_code = ACKX_TIMEOUT; - queue_packet_complete(packet); - } -} - -static struct task_struct *khpsbpkt_thread; -static LIST_HEAD(hpsbpkt_queue); - -static void queue_packet_complete(struct hpsb_packet *packet) -{ - unsigned long flags; - - if (packet->no_waiter) { - hpsb_free_packet(packet); - return; - } - if (packet->complete_routine != NULL) { - spin_lock_irqsave(&pending_packets_lock, flags); - list_add_tail(&packet->queue, &hpsbpkt_queue); - spin_unlock_irqrestore(&pending_packets_lock, flags); - wake_up_process(khpsbpkt_thread); - } - return; -} - -/* - * Kernel thread which handles packets that are completed. This way the - * packet's "complete" function is asynchronously run in process context. - * Only packets which have a "complete" function may be sent here. - */ -static int hpsbpkt_thread(void *__hi) -{ - struct hpsb_packet *packet, *p; - struct list_head tmp; - int may_schedule; - - while (!kthread_should_stop()) { - - INIT_LIST_HEAD(&tmp); - spin_lock_irq(&pending_packets_lock); - list_splice_init(&hpsbpkt_queue, &tmp); - spin_unlock_irq(&pending_packets_lock); - - list_for_each_entry_safe(packet, p, &tmp, queue) { - list_del_init(&packet->queue); - packet->complete_routine(packet->complete_data); - } - - set_current_state(TASK_INTERRUPTIBLE); - spin_lock_irq(&pending_packets_lock); - may_schedule = list_empty(&hpsbpkt_queue); - spin_unlock_irq(&pending_packets_lock); - if (may_schedule) - schedule(); - __set_current_state(TASK_RUNNING); - } - return 0; -} - -static int __init ieee1394_init(void) -{ - int i, ret; - - /* non-fatal error */ - if (hpsb_init_config_roms()) { - HPSB_ERR("Failed to initialize some config rom entries.\n"); - HPSB_ERR("Some features may not be available\n"); - } - - khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt"); - if (IS_ERR(khpsbpkt_thread)) { - HPSB_ERR("Failed to start hpsbpkt thread!\n"); - ret = PTR_ERR(khpsbpkt_thread); - goto exit_cleanup_config_roms; - } - - if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) { - HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR); - ret = -ENODEV; - goto exit_release_kernel_thread; - } - - ret = bus_register(&ieee1394_bus_type); - if (ret < 0) { - HPSB_INFO("bus register failed"); - goto release_chrdev; - } - - for (i = 0; fw_bus_attrs[i]; i++) { - ret = bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]); - if (ret < 0) { - while (i >= 0) { - bus_remove_file(&ieee1394_bus_type, - fw_bus_attrs[i--]); - } - bus_unregister(&ieee1394_bus_type); - goto release_chrdev; - } - } - - ret = class_register(&hpsb_host_class); - if (ret < 0) - goto release_all_bus; - - hpsb_protocol_class = class_create(THIS_MODULE, "ieee1394_protocol"); - if (IS_ERR(hpsb_protocol_class)) { - ret = PTR_ERR(hpsb_protocol_class); - goto release_class_host; - } - - ret = init_csr(); - if (ret) { - HPSB_INFO("init csr failed"); - ret = -ENOMEM; - goto release_class_protocol; - } - - if (disable_nodemgr) { - HPSB_INFO("nodemgr and IRM functionality disabled"); - /* We shouldn't contend for IRM with nodemgr disabled, since - nodemgr implements functionality required of ieee1394a-2000 - IRMs */ - hpsb_disable_irm = 1; - - return 0; - } - - if (hpsb_disable_irm) { - HPSB_INFO("IRM functionality disabled"); - } - - ret = init_ieee1394_nodemgr(); - if (ret < 0) { - HPSB_INFO("init nodemgr failed"); - goto cleanup_csr; - } - - return 0; - -cleanup_csr: - cleanup_csr(); -release_class_protocol: - class_destroy(hpsb_protocol_class); -release_class_host: - class_unregister(&hpsb_host_class); -release_all_bus: - for (i = 0; fw_bus_attrs[i]; i++) - bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); - bus_unregister(&ieee1394_bus_type); -release_chrdev: - unregister_chrdev_region(IEEE1394_CORE_DEV, 256); -exit_release_kernel_thread: - kthread_stop(khpsbpkt_thread); -exit_cleanup_config_roms: - hpsb_cleanup_config_roms(); - return ret; -} - -static void __exit ieee1394_cleanup(void) -{ - int i; - - if (!disable_nodemgr) - cleanup_ieee1394_nodemgr(); - - cleanup_csr(); - - class_destroy(hpsb_protocol_class); - class_unregister(&hpsb_host_class); - for (i = 0; fw_bus_attrs[i]; i++) - bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]); - bus_unregister(&ieee1394_bus_type); - - kthread_stop(khpsbpkt_thread); - - hpsb_cleanup_config_roms(); - - unregister_chrdev_region(IEEE1394_CORE_DEV, 256); -} - -fs_initcall(ieee1394_init); -module_exit(ieee1394_cleanup); - -/* Exported symbols */ - -/** hosts.c **/ -EXPORT_SYMBOL(hpsb_alloc_host); -EXPORT_SYMBOL(hpsb_add_host); -EXPORT_SYMBOL(hpsb_resume_host); -EXPORT_SYMBOL(hpsb_remove_host); -EXPORT_SYMBOL(hpsb_update_config_rom_image); - -/** ieee1394_core.c **/ -EXPORT_SYMBOL(hpsb_speedto_str); -EXPORT_SYMBOL(hpsb_protocol_class); -EXPORT_SYMBOL(hpsb_set_packet_complete_task); -EXPORT_SYMBOL(hpsb_alloc_packet); -EXPORT_SYMBOL(hpsb_free_packet); -EXPORT_SYMBOL(hpsb_send_packet); -EXPORT_SYMBOL(hpsb_reset_bus); -EXPORT_SYMBOL(hpsb_read_cycle_timer); -EXPORT_SYMBOL(hpsb_bus_reset); -EXPORT_SYMBOL(hpsb_selfid_received); -EXPORT_SYMBOL(hpsb_selfid_complete); -EXPORT_SYMBOL(hpsb_packet_sent); -EXPORT_SYMBOL(hpsb_packet_received); -EXPORT_SYMBOL_GPL(hpsb_disable_irm); - -/** ieee1394_transactions.c **/ -EXPORT_SYMBOL(hpsb_get_tlabel); -EXPORT_SYMBOL(hpsb_free_tlabel); -EXPORT_SYMBOL(hpsb_make_readpacket); -EXPORT_SYMBOL(hpsb_make_writepacket); -EXPORT_SYMBOL(hpsb_make_streampacket); -EXPORT_SYMBOL(hpsb_make_lockpacket); -EXPORT_SYMBOL(hpsb_make_lock64packet); -EXPORT_SYMBOL(hpsb_make_phypacket); -EXPORT_SYMBOL(hpsb_read); -EXPORT_SYMBOL(hpsb_write); -EXPORT_SYMBOL(hpsb_lock); -EXPORT_SYMBOL(hpsb_packet_success); - -/** highlevel.c **/ -EXPORT_SYMBOL(hpsb_register_highlevel); -EXPORT_SYMBOL(hpsb_unregister_highlevel); -EXPORT_SYMBOL(hpsb_register_addrspace); -EXPORT_SYMBOL(hpsb_unregister_addrspace); -EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace); -EXPORT_SYMBOL(hpsb_get_hostinfo); -EXPORT_SYMBOL(hpsb_create_hostinfo); -EXPORT_SYMBOL(hpsb_destroy_hostinfo); -EXPORT_SYMBOL(hpsb_set_hostinfo_key); -EXPORT_SYMBOL(hpsb_get_hostinfo_bykey); -EXPORT_SYMBOL(hpsb_set_hostinfo); - -/** nodemgr.c **/ -EXPORT_SYMBOL(hpsb_node_fill_packet); -EXPORT_SYMBOL(hpsb_node_write); -EXPORT_SYMBOL(__hpsb_register_protocol); -EXPORT_SYMBOL(hpsb_unregister_protocol); - -/** csr.c **/ -EXPORT_SYMBOL(hpsb_update_config_rom); - -/** dma.c **/ -EXPORT_SYMBOL(dma_prog_region_init); -EXPORT_SYMBOL(dma_prog_region_alloc); -EXPORT_SYMBOL(dma_prog_region_free); -EXPORT_SYMBOL(dma_region_init); -EXPORT_SYMBOL(dma_region_alloc); -EXPORT_SYMBOL(dma_region_free); -EXPORT_SYMBOL(dma_region_sync_for_cpu); -EXPORT_SYMBOL(dma_region_sync_for_device); -EXPORT_SYMBOL(dma_region_mmap); -EXPORT_SYMBOL(dma_region_offset_to_bus); - -/** iso.c **/ -EXPORT_SYMBOL(hpsb_iso_xmit_init); -EXPORT_SYMBOL(hpsb_iso_recv_init); -EXPORT_SYMBOL(hpsb_iso_xmit_start); -EXPORT_SYMBOL(hpsb_iso_recv_start); -EXPORT_SYMBOL(hpsb_iso_recv_listen_channel); -EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel); -EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask); -EXPORT_SYMBOL(hpsb_iso_stop); -EXPORT_SYMBOL(hpsb_iso_shutdown); -EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet); -EXPORT_SYMBOL(hpsb_iso_xmit_sync); -EXPORT_SYMBOL(hpsb_iso_recv_release_packets); -EXPORT_SYMBOL(hpsb_iso_n_ready); -EXPORT_SYMBOL(hpsb_iso_packet_sent); -EXPORT_SYMBOL(hpsb_iso_packet_received); -EXPORT_SYMBOL(hpsb_iso_wake); -EXPORT_SYMBOL(hpsb_iso_recv_flush); - -/** csr1212.c **/ -EXPORT_SYMBOL(csr1212_attach_keyval_to_directory); -EXPORT_SYMBOL(csr1212_detach_keyval_from_directory); -EXPORT_SYMBOL(csr1212_get_keyval); -EXPORT_SYMBOL(csr1212_new_directory); -EXPORT_SYMBOL(csr1212_parse_keyval); -EXPORT_SYMBOL(csr1212_read); -EXPORT_SYMBOL(csr1212_release_keyval); diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h deleted file mode 100644 index 28b9f58..0000000 --- a/drivers/ieee1394/ieee1394_core.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef _IEEE1394_CORE_H -#define _IEEE1394_CORE_H - -#include <linux/device.h> -#include <linux/fs.h> -#include <linux/list.h> -#include <linux/types.h> -#include <linux/cdev.h> -#include <asm/atomic.h> - -#include "hosts.h" -#include "ieee1394_types.h" - -struct hpsb_packet { - /* This struct is basically read-only for hosts with the exception of - * the data buffer contents and driver_list. */ - - /* This can be used for host driver internal linking. - * - * NOTE: This must be left in init state when the driver is done - * with it (e.g. by using list_del_init()), since the core does - * some sanity checks to make sure the packet is not on a - * driver_list when free'ing it. */ - struct list_head driver_list; - - nodeid_t node_id; - - /* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */ - enum { hpsb_async, hpsb_raw } __attribute__((packed)) type; - - /* Okay, this is core internal and a no care for hosts. - * queued = queued for sending - * pending = sent, waiting for response - * complete = processing completed, successful or not - */ - enum { - hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete - } __attribute__((packed)) state; - - /* These are core-internal. */ - signed char tlabel; - signed char ack_code; - unsigned char tcode; - - unsigned expect_response:1; - unsigned no_waiter:1; - - /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */ - unsigned speed_code:2; - - struct hpsb_host *host; - unsigned int generation; - - atomic_t refcnt; - struct list_head queue; - - /* Function (and possible data to pass to it) to call when this - * packet is completed. */ - void (*complete_routine)(void *); - void *complete_data; - - /* Store jiffies for implementing bus timeouts. */ - unsigned long sendtime; - - /* Core-internal. */ - size_t allocated_data_size; /* as allocated */ - - /* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */ - size_t data_size; /* as filled in */ - size_t header_size; /* as filled in, not counting the CRC */ - - /* Buffers */ - quadlet_t *data; /* can be DMA-mapped */ - quadlet_t header[5]; - quadlet_t embedded_data[0]; /* keep as last member */ -}; - -void hpsb_set_packet_complete_task(struct hpsb_packet *packet, - void (*routine)(void *), void *data); -static inline struct hpsb_packet *driver_packet(struct list_head *l) -{ - return list_entry(l, struct hpsb_packet, driver_list); -} -void abort_timedouts(unsigned long __opaque); -struct hpsb_packet *hpsb_alloc_packet(size_t data_size); -void hpsb_free_packet(struct hpsb_packet *packet); - -/** - * get_hpsb_generation - generation counter for the complete 1394 subsystem - * - * Generation gets incremented on every change in the subsystem (notably on bus - * resets). Use the functions, not the variable. - */ -static inline unsigned int get_hpsb_generation(struct hpsb_host *host) -{ - return atomic_read(&host->generation); -} - -int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt); -int hpsb_send_packet(struct hpsb_packet *packet); -int hpsb_send_packet_and_wait(struct hpsb_packet *packet); -int hpsb_reset_bus(struct hpsb_host *host, int type); -int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer, - u64 *local_time); - -int hpsb_bus_reset(struct hpsb_host *host); -void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid); -void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot); -void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, - int ackcode); -void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, - int write_acked); - -/* - * CHARACTER DEVICE DISPATCHING - * - * All ieee1394 character device drivers share the same major number - * (major 171). The 256 minor numbers are allocated to the various - * task-specific interfaces (raw1394, video1394, dv1394, etc) in - * blocks of 16. - * - * The core ieee1394.o module allocates the device number region - * 171:0-255, the various drivers must then cdev_add() their cdev - * objects to handle their respective sub-regions. - * - * Minor device number block allocations: - * - * Block 0 ( 0- 15) raw1394 - * Block 1 ( 16- 31) video1394 - * Block 2 ( 32- 47) dv1394 - * - * Blocks 3-14 free for future allocation - * - * Block 15 (240-255) reserved for drivers under development, etc. - */ - -#define IEEE1394_MAJOR 171 - -#define IEEE1394_MINOR_BLOCK_RAW1394 0 -#define IEEE1394_MINOR_BLOCK_VIDEO1394 1 -#define IEEE1394_MINOR_BLOCK_DV1394 2 -#define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15 - -#define IEEE1394_CORE_DEV MKDEV(IEEE1394_MAJOR, 0) -#define IEEE1394_RAW1394_DEV MKDEV(IEEE1394_MAJOR, \ - IEEE1394_MINOR_BLOCK_RAW1394 * 16) -#define IEEE1394_VIDEO1394_DEV MKDEV(IEEE1394_MAJOR, \ - IEEE1394_MINOR_BLOCK_VIDEO1394 * 16) -#define IEEE1394_DV1394_DEV MKDEV(IEEE1394_MAJOR, \ - IEEE1394_MINOR_BLOCK_DV1394 * 16) -#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, \ - IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16) - -/** - * ieee1394_file_to_instance - get the index within a minor number block - */ -static inline unsigned char ieee1394_file_to_instance(struct file *file) -{ - int idx = cdev_index(file->f_path.dentry->d_inode); - if (idx < 0) - idx = 0; - return idx; -} - -extern int hpsb_disable_irm; - -/* Our sysfs bus entry */ -extern struct bus_type ieee1394_bus_type; -extern struct class hpsb_host_class; -extern struct class *hpsb_protocol_class; - -#endif /* _IEEE1394_CORE_H */ diff --git a/drivers/ieee1394/ieee1394_hotplug.h b/drivers/ieee1394/ieee1394_hotplug.h deleted file mode 100644 index dd5500e..0000000 --- a/drivers/ieee1394/ieee1394_hotplug.h +++ /dev/null @@ -1,19 +0,0 @@ -#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 */ diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c deleted file mode 100644 index 675b313..0000000 --- a/drivers/ieee1394/ieee1394_transactions.c +++ /dev/null @@ -1,595 +0,0 @@ -/* - * IEEE 1394 for Linux - * - * Transaction support. - * - * Copyright (C) 1999 Andreas E. Bombe - * - * This code is licensed under the GPL. See the file COPYING in the root - * directory of the kernel sources for details. - */ - -#include <linux/bitops.h> -#include <linux/compiler.h> -#include <linux/hardirq.h> -#include <linux/spinlock.h> -#include <linux/string.h> -#include <linux/sched.h> /* because linux/wait.h is broken if CONFIG_SMP=n */ -#include <linux/wait.h> - -#include <asm/bug.h> -#include <asm/errno.h> -#include <asm/system.h> - -#include "ieee1394.h" -#include "ieee1394_types.h" -#include "hosts.h" -#include "ieee1394_core.h" -#include "ieee1394_transactions.h" - -#define PREP_ASYNC_HEAD_ADDRESS(tc) \ - packet->tcode = tc; \ - packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \ - | (1 << 8) | (tc << 4); \ - packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \ - packet->header[2] = addr & 0xffffffff - -#ifndef HPSB_DEBUG_TLABELS -static -#endif -DEFINE_SPINLOCK(hpsb_tlabel_lock); - -static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq); - -static void fill_async_readquad(struct hpsb_packet *packet, u64 addr) -{ - PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ); - packet->header_size = 12; - packet->data_size = 0; - packet->expect_response = 1; -} - -static void fill_async_readblock(struct hpsb_packet *packet, u64 addr, - int length) -{ - PREP_ASYNC_HEAD_ADDRESS(TCODE_READB); - packet->header[3] = length << 16; - packet->header_size = 16; - packet->data_size = 0; - packet->expect_response = 1; -} - -static void fill_async_writequad(struct hpsb_packet *packet, u64 addr, - quadlet_t data) -{ - PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ); - packet->header[3] = data; - packet->header_size = 16; - packet->data_size = 0; - packet->expect_response = 1; -} - -static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, - int length) -{ - PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB); - packet->header[3] = length << 16; - packet->header_size = 16; - packet->expect_response = 1; - packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0); -} - -static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode, - int length) -{ - PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST); - packet->header[3] = (length << 16) | extcode; - packet->header_size = 16; - packet->data_size = length; - packet->expect_response = 1; -} - -static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data) -{ - packet->header[0] = data; - packet->header[1] = ~data; - packet->header_size = 8; - packet->data_size = 0; - packet->expect_response = 0; - packet->type = hpsb_raw; /* No CRC added */ - packet->speed_code = IEEE1394_SPEED_100; /* Force speed to be 100Mbps */ -} - -static void fill_async_stream_packet(struct hpsb_packet *packet, int length, - int channel, int tag, int sync) -{ - packet->header[0] = (length << 16) | (tag << 14) | (channel << 8) - | (TCODE_STREAM_DATA << 4) | sync; - - packet->header_size = 4; - packet->data_size = length; - packet->type = hpsb_async; - packet->tcode = TCODE_ISO_DATA; -} - -/* same as hpsb_get_tlabel, except that it returns immediately */ -static int hpsb_get_tlabel_atomic(struct hpsb_packet *packet) -{ - unsigned long flags, *tp; - u8 *next; - int tlabel, n = NODEID_TO_NODE(packet->node_id); - - /* Broadcast transactions are complete once the request has been sent. - * Use the same transaction label for all broadcast transactions. */ - if (unlikely(n == ALL_NODES)) { - packet->tlabel = 0; - return 0; - } - tp = packet->host->tl_pool[n].map; - next = &packet->host->next_tl[n]; - - spin_lock_irqsave(&hpsb_tlabel_lock, flags); - tlabel = find_next_zero_bit(tp, 64, *next); - if (tlabel > 63) - tlabel = find_first_zero_bit(tp, 64); - if (tlabel > 63) { - spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); - return -EAGAIN; - } - __set_bit(tlabel, tp); - *next = (tlabel + 1) & 63; - spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); - - packet->tlabel = tlabel; - return 0; -} - -/** - * hpsb_get_tlabel - allocate a transaction label - * @packet: the packet whose tlabel and tl_pool we set - * - * Every asynchronous transaction on the 1394 bus needs a transaction - * label to match the response to the request. This label has to be - * different from any other transaction label in an outstanding request to - * the same node to make matching possible without ambiguity. - * - * There are 64 different tlabels, so an allocated tlabel has to be freed - * with hpsb_free_tlabel() after the transaction is complete (unless it's - * reused again for the same target node). - * - * Return value: Zero on success, otherwise non-zero. A non-zero return - * generally means there are no available tlabels. If this is called out - * of interrupt or atomic context, then it will sleep until can return a - * tlabel or a signal is received. - */ -int hpsb_get_tlabel(struct hpsb_packet *packet) -{ - if (irqs_disabled() || in_atomic()) - return hpsb_get_tlabel_atomic(packet); - - /* NB: The macro wait_event_interruptible() is called with a condition - * argument with side effect. This is only possible because the side - * effect does not occur until the condition became true, and - * wait_event_interruptible() won't evaluate the condition again after - * that. */ - return wait_event_interruptible(tlabel_wq, - !hpsb_get_tlabel_atomic(packet)); -} - -/** - * hpsb_free_tlabel - free an allocated transaction label - * @packet: packet whose tlabel and tl_pool needs to be cleared - * - * Frees the transaction label allocated with hpsb_get_tlabel(). The - * tlabel has to be freed after the transaction is complete (i.e. response - * was received for a split transaction or packet was sent for a unified - * transaction). - * - * A tlabel must not be freed twice. - */ -void hpsb_free_tlabel(struct hpsb_packet *packet) -{ - unsigned long flags, *tp; - int tlabel, n = NODEID_TO_NODE(packet->node_id); - - if (unlikely(n == ALL_NODES)) - return; - tp = packet->host->tl_pool[n].map; - tlabel = packet->tlabel; - BUG_ON(tlabel > 63 || tlabel < 0); - - spin_lock_irqsave(&hpsb_tlabel_lock, flags); - BUG_ON(!__test_and_clear_bit(tlabel, tp)); - spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); - - wake_up_interruptible(&tlabel_wq); -} - -/** - * hpsb_packet_success - Make sense of the ack and reply codes - * - * Make sense of the ack and reply codes and return more convenient error codes: - * 0 = success. -%EBUSY = node is busy, try again. -%EAGAIN = error which can - * probably resolved by retry. -%EREMOTEIO = node suffers from an internal - * error. -%EACCES = this transaction is not allowed on requested address. - * -%EINVAL = invalid address at node. - */ -int hpsb_packet_success(struct hpsb_packet *packet) -{ - switch (packet->ack_code) { - case ACK_PENDING: - switch ((packet->header[1] >> 12) & 0xf) { - case RCODE_COMPLETE: - return 0; - case RCODE_CONFLICT_ERROR: - return -EAGAIN; - case RCODE_DATA_ERROR: - return -EREMOTEIO; - case RCODE_TYPE_ERROR: - return -EACCES; - case RCODE_ADDRESS_ERROR: - return -EINVAL; - default: - HPSB_ERR("received reserved rcode %d from node %d", - (packet->header[1] >> 12) & 0xf, - packet->node_id); - return -EAGAIN; - } - - case ACK_BUSY_X: - case ACK_BUSY_A: - case ACK_BUSY_B: - return -EBUSY; - - case ACK_TYPE_ERROR: - return -EACCES; - - case ACK_COMPLETE: - if (packet->tcode == TCODE_WRITEQ - || packet->tcode == TCODE_WRITEB) { - return 0; - } else { - HPSB_ERR("impossible ack_complete from node %d " - "(tcode %d)", packet->node_id, packet->tcode); - return -EAGAIN; - } - - case ACK_DATA_ERROR: - if (packet->tcode == TCODE_WRITEB - || packet->tcode == TCODE_LOCK_REQUEST) { - return -EAGAIN; - } else { - HPSB_ERR("impossible ack_data_error from node %d " - "(tcode %d)", packet->node_id, packet->tcode); - return -EAGAIN; - } - - case ACK_ADDRESS_ERROR: - return -EINVAL; - - case ACK_TARDY: - case ACK_CONFLICT_ERROR: - case ACKX_NONE: - case ACKX_SEND_ERROR: - case ACKX_ABORTED: - case ACKX_TIMEOUT: - /* error while sending */ - return -EAGAIN; - - default: - HPSB_ERR("got invalid ack %d from node %d (tcode %d)", - packet->ack_code, packet->node_id, packet->tcode); - return -EAGAIN; - } -} - -struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node, - u64 addr, size_t length) -{ - struct hpsb_packet *packet; - - if (length == 0) - return NULL; - - packet = hpsb_alloc_packet(length); - if (!packet) - return NULL; - - packet->host = host; - packet->node_id = node; - - if (hpsb_get_tlabel(packet)) { - hpsb_free_packet(packet); - return NULL; - } - - if (length == 4) - fill_async_readquad(packet, addr); - else - fill_async_readblock(packet, addr, length); - - return packet; -} - -struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host, nodeid_t node, - u64 addr, quadlet_t * buffer, - size_t length) -{ - struct hpsb_packet *packet; - - if (length == 0) - return NULL; - - packet = hpsb_alloc_packet(length); - if (!packet) - return NULL; - - if (length % 4) { /* zero padding bytes */ - packet->data[length >> 2] = 0; - } - packet->host = host; - packet->node_id = node; - - if (hpsb_get_tlabel(packet)) { - hpsb_free_packet(packet); - return NULL; - } - - if (length == 4) { - fill_async_writequad(packet, addr, buffer ? *buffer : 0); - } else { - fill_async_writeblock(packet, addr, length); - if (buffer) - memcpy(packet->data, buffer, length); - } - - return packet; -} - -struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer, - int length, int channel, int tag, - int sync) -{ - struct hpsb_packet *packet; - - if (length == 0) - return NULL; - - packet = hpsb_alloc_packet(length); - if (!packet) - return NULL; - - if (length % 4) { /* zero padding bytes */ - packet->data[length >> 2] = 0; - } - packet->host = host; - - /* Because it is too difficult to determine all PHY speeds and link - * speeds here, we use S100... */ - packet->speed_code = IEEE1394_SPEED_100; - - /* ...and prevent hpsb_send_packet() from overriding it. */ - packet->node_id = LOCAL_BUS | ALL_NODES; - - if (hpsb_get_tlabel(packet)) { - hpsb_free_packet(packet); - return NULL; - } - - fill_async_stream_packet(packet, length, channel, tag, sync); - if (buffer) - memcpy(packet->data, buffer, length); - - return packet; -} - -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 *p; - u32 length; - - p = hpsb_alloc_packet(8); - if (!p) - return NULL; - - p->host = host; - p->node_id = node; - if (hpsb_get_tlabel(p)) { - hpsb_free_packet(p); - return NULL; - } - - switch (extcode) { - case EXTCODE_FETCH_ADD: - case EXTCODE_LITTLE_ADD: - length = 4; - if (data) - p->data[0] = *data; - break; - default: - length = 8; - if (data) { - p->data[0] = arg; - p->data[1] = *data; - } - break; - } - fill_async_lock(p, addr, extcode, length); - - return p; -} - -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 *p; - u32 length; - - p = hpsb_alloc_packet(16); - if (!p) - return NULL; - - p->host = host; - p->node_id = node; - if (hpsb_get_tlabel(p)) { - hpsb_free_packet(p); - return NULL; - } - - switch (extcode) { - case EXTCODE_FETCH_ADD: - case EXTCODE_LITTLE_ADD: - length = 8; - if (data) { - p->data[0] = *data >> 32; - p->data[1] = *data & 0xffffffff; - } - break; - default: - length = 16; - if (data) { - p->data[0] = arg >> 32; - p->data[1] = arg & 0xffffffff; - p->data[2] = *data >> 32; - p->data[3] = *data & 0xffffffff; - } - break; - } - fill_async_lock(p, addr, extcode, length); - - return p; -} - -struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data) -{ - struct hpsb_packet *p; - - p = hpsb_alloc_packet(0); - if (!p) - return NULL; - - p->host = host; - fill_phy_packet(p, data); - - return p; -} - -/* - * FIXME - these functions should probably read from / write to user space to - * avoid in kernel buffers for user space callers - */ - -/** - * hpsb_read - generic read function - * - * Recognizes the local node ID and act accordingly. Automatically uses a - * quadlet read request if @length == 4 and and a block read request otherwise. - * It does not yet support lengths that are not a multiple of 4. - * - * You must explicitly specifiy the @generation for which the node ID is valid, - * to avoid sending packets to the wrong nodes when we race with a bus reset. - */ -int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation, - u64 addr, quadlet_t * buffer, size_t length) -{ - struct hpsb_packet *packet; - int retval = 0; - - if (length == 0) - return -EINVAL; - - packet = hpsb_make_readpacket(host, node, addr, length); - - if (!packet) { - return -ENOMEM; - } - - packet->generation = generation; - retval = hpsb_send_packet_and_wait(packet); - if (retval < 0) - goto hpsb_read_fail; - - retval = hpsb_packet_success(packet); - - if (retval == 0) { - if (length == 4) { - *buffer = packet->header[3]; - } else { - memcpy(buffer, packet->data, length); - } - } - - hpsb_read_fail: - hpsb_free_tlabel(packet); - hpsb_free_packet(packet); - - return retval; -} - -/** - * hpsb_write - generic write function - * - * Recognizes the local node ID and act accordingly. Automatically uses a - * quadlet write request if @length == 4 and and a block write request - * otherwise. It does not yet support lengths that are not a multiple of 4. - * - * You must explicitly specifiy the @generation for which the node ID is valid, - * to avoid sending packets to the wrong nodes when we race with a bus reset. - */ -int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation, - u64 addr, quadlet_t * buffer, size_t length) -{ - struct hpsb_packet *packet; - int retval; - - if (length == 0) - return -EINVAL; - - packet = hpsb_make_writepacket(host, node, addr, buffer, length); - - if (!packet) - return -ENOMEM; - - packet->generation = generation; - retval = hpsb_send_packet_and_wait(packet); - if (retval < 0) - goto hpsb_write_fail; - - retval = hpsb_packet_success(packet); - - hpsb_write_fail: - hpsb_free_tlabel(packet); - hpsb_free_packet(packet); - - return retval; -} - -int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation, - u64 addr, int extcode, quadlet_t *data, quadlet_t arg) -{ - struct hpsb_packet *packet; - int retval = 0; - - packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg); - if (!packet) - return -ENOMEM; - - packet->generation = generation; - retval = hpsb_send_packet_and_wait(packet); - if (retval < 0) - goto hpsb_lock_fail; - - retval = hpsb_packet_success(packet); - - if (retval == 0) - *data = packet->data[0]; - -hpsb_lock_fail: - hpsb_free_tlabel(packet); - hpsb_free_packet(packet); - - return retval; -} diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h deleted file mode 100644 index 20b693b..0000000 --- a/drivers/ieee1394/ieee1394_transactions.h +++ /dev/null @@ -1,40 +0,0 @@ -#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 */ diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h deleted file mode 100644 index 9803aaa..0000000 --- a/drivers/ieee1394/ieee1394_types.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _IEEE1394_TYPES_H -#define _IEEE1394_TYPES_H - -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/types.h> -#include <asm/byteorder.h> - -typedef u32 quadlet_t; -typedef u64 octlet_t; -typedef u16 nodeid_t; - -typedef u8 byte_t; -typedef u64 nodeaddr_t; -typedef u16 arm_length_t; - -#define BUS_MASK 0xffc0 -#define BUS_SHIFT 6 -#define NODE_MASK 0x003f -#define LOCAL_BUS 0xffc0 -#define ALL_NODES 0x003f - -#define NODEID_TO_BUS(nodeid) ((nodeid & BUS_MASK) >> BUS_SHIFT) -#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK) - -/* Can be used to consistently print a node/bus ID. */ -#define NODE_BUS_FMT "%d-%02d:%04d" -#define NODE_BUS_ARGS(__host, __nodeid) \ - __host->id, NODEID_TO_NODE(__nodeid), NODEID_TO_BUS(__nodeid) - -#define HPSB_PRINT(level, fmt, args...) \ - printk(level "ieee1394: " fmt "\n" , ## args) - -#define HPSB_DEBUG(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) -#define HPSB_INFO(fmt, args...) HPSB_PRINT(KERN_INFO, fmt , ## args) -#define HPSB_NOTICE(fmt, args...) HPSB_PRINT(KERN_NOTICE, fmt , ## args) -#define HPSB_WARN(fmt, args...) HPSB_PRINT(KERN_WARNING, fmt , ## args) -#define HPSB_ERR(fmt, args...) HPSB_PRINT(KERN_ERR, fmt , ## args) - -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG -#define HPSB_VERBOSE(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args) -#define HPSB_DEBUG_TLABELS -#else -#define HPSB_VERBOSE(fmt, args...) do {} while (0) -#endif - -#ifdef __BIG_ENDIAN - -static inline void *memcpy_le32(u32 *dest, const u32 *__src, size_t count) -{ - void *tmp = dest; - u32 *src = (u32 *)__src; - - count /= 4; - while (count--) - *dest++ = swab32p(src++); - return tmp; -} - -#else - -static __inline__ void *memcpy_le32(u32 *dest, const u32 *src, size_t count) -{ - return memcpy(dest, src, count); -} - -#endif /* __BIG_ENDIAN */ - -#endif /* _IEEE1394_TYPES_H */ diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c deleted file mode 100644 index 1cf6487..0000000 --- a/drivers/ieee1394/iso.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * IEEE 1394 for Linux - * - * kernel ISO transmission/reception - * - * 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/pci.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/slab.h> - -#include "hosts.h" -#include "iso.h" - -/** - * hpsb_iso_stop - stop DMA - */ -void hpsb_iso_stop(struct hpsb_iso *iso) -{ - if (!(iso->flags & HPSB_ISO_DRIVER_STARTED)) - return; - - iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? - XMIT_STOP : RECV_STOP, 0); - iso->flags &= ~HPSB_ISO_DRIVER_STARTED; -} - -/** - * hpsb_iso_shutdown - deallocate buffer and DMA context - */ -void hpsb_iso_shutdown(struct hpsb_iso *iso) -{ - if (iso->flags & HPSB_ISO_DRIVER_INIT) { - hpsb_iso_stop(iso); - iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? - XMIT_SHUTDOWN : RECV_SHUTDOWN, 0); - iso->flags &= ~HPSB_ISO_DRIVER_INIT; - } - - dma_region_free(&iso->data_buf); - kfree(iso); -} - -static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host, - enum hpsb_iso_type type, - unsigned int data_buf_size, - unsigned int buf_packets, - int channel, int dma_mode, - int irq_interval, - void (*callback) (struct hpsb_iso - *)) -{ - struct hpsb_iso *iso; - int dma_direction; - - /* make sure driver supports the ISO API */ - if (!host->driver->isoctl) { - printk(KERN_INFO - "ieee1394: host driver '%s' does not support the rawiso API\n", - host->driver->name); - return NULL; - } - - /* sanitize parameters */ - - if (buf_packets < 2) - buf_packets = 2; - - if ((dma_mode < HPSB_ISO_DMA_DEFAULT) - || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER)) - dma_mode = HPSB_ISO_DMA_DEFAULT; - - if ((irq_interval < 0) || (irq_interval > buf_packets / 4)) - irq_interval = buf_packets / 4; - if (irq_interval == 0) /* really interrupt for each packet */ - irq_interval = 1; - - if (channel < -1 || channel >= 64) - return NULL; - - /* channel = -1 is OK for multi-channel recv but not for xmit */ - if (type == HPSB_ISO_XMIT && channel < 0) - return NULL; - - /* allocate and write the struct hpsb_iso */ - - iso = - kmalloc(sizeof(*iso) + - buf_packets * sizeof(struct hpsb_iso_packet_info), - GFP_KERNEL); - if (!iso) - return NULL; - - iso->infos = (struct hpsb_iso_packet_info *)(iso + 1); - - iso->type = type; - iso->host = host; - iso->hostdata = NULL; - iso->callback = callback; - init_waitqueue_head(&iso->waitq); - iso->channel = channel; - iso->irq_interval = irq_interval; - iso->dma_mode = dma_mode; - dma_region_init(&iso->data_buf); - iso->buf_size = PAGE_ALIGN(data_buf_size); - iso->buf_packets = buf_packets; - iso->pkt_dma = 0; - iso->first_packet = 0; - spin_lock_init(&iso->lock); - - if (iso->type == HPSB_ISO_XMIT) { - iso->n_ready_packets = iso->buf_packets; - dma_direction = PCI_DMA_TODEVICE; - } else { - iso->n_ready_packets = 0; - dma_direction = PCI_DMA_FROMDEVICE; - } - - atomic_set(&iso->overflows, 0); - iso->bytes_discarded = 0; - iso->flags = 0; - iso->prebuffer = 0; - - /* allocate the packet buffer */ - if (dma_region_alloc - (&iso->data_buf, iso->buf_size, host->pdev, dma_direction)) - goto err; - - return iso; - - err: - hpsb_iso_shutdown(iso); - return NULL; -} - -/** - * hpsb_iso_n_ready - returns number of packets ready to send or receive - */ -int hpsb_iso_n_ready(struct hpsb_iso *iso) -{ - unsigned long flags; - int val; - - spin_lock_irqsave(&iso->lock, flags); - val = iso->n_ready_packets; - spin_unlock_irqrestore(&iso->lock, flags); - - return val; -} - -/** - * hpsb_iso_xmit_init - allocate the buffer and DMA context - */ -struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host, - unsigned int data_buf_size, - unsigned int buf_packets, - int channel, - int speed, - int irq_interval, - void (*callback) (struct hpsb_iso *)) -{ - struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT, - data_buf_size, buf_packets, - channel, - HPSB_ISO_DMA_DEFAULT, - irq_interval, callback); - if (!iso) - return NULL; - - iso->speed = speed; - - /* tell the driver to start working */ - if (host->driver->isoctl(iso, XMIT_INIT, 0)) - goto err; - - iso->flags |= HPSB_ISO_DRIVER_INIT; - return iso; - - err: - hpsb_iso_shutdown(iso); - return NULL; -} - -/** - * hpsb_iso_recv_init - allocate the buffer and DMA context - * - * Note, if channel = -1, multi-channel receive is enabled. - */ -struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host, - unsigned int data_buf_size, - unsigned int buf_packets, - int channel, - int dma_mode, - int irq_interval, - void (*callback) (struct hpsb_iso *)) -{ - struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV, - data_buf_size, buf_packets, - channel, dma_mode, - irq_interval, callback); - if (!iso) - return NULL; - - /* tell the driver to start working */ - if (host->driver->isoctl(iso, RECV_INIT, 0)) - goto err; - - iso->flags |= HPSB_ISO_DRIVER_INIT; - return iso; - - err: - hpsb_iso_shutdown(iso); - return NULL; -} - -/** - * hpsb_iso_recv_listen_channel - * - * multi-channel only - */ -int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel) -{ - if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) - return -EINVAL; - return iso->host->driver->isoctl(iso, RECV_LISTEN_CHANNEL, channel); -} - -/** - * hpsb_iso_recv_unlisten_channel - * - * multi-channel only - */ -int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel) -{ - if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) - return -EINVAL; - return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel); -} - -/** - * hpsb_iso_recv_set_channel_mask - * - * multi-channel only - */ -int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask) -{ - if (iso->type != HPSB_ISO_RECV || iso->channel != -1) - return -EINVAL; - return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, - (unsigned long)&mask); -} - -/** - * hpsb_iso_recv_flush - check for arrival of new packets - * - * check for arrival of new packets immediately (even if irq_interval - * has not yet been reached) - */ -int hpsb_iso_recv_flush(struct hpsb_iso *iso) -{ - if (iso->type != HPSB_ISO_RECV) - return -EINVAL; - return iso->host->driver->isoctl(iso, RECV_FLUSH, 0); -} - -static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle) -{ - int retval = iso->host->driver->isoctl(iso, XMIT_START, cycle); - if (retval) - return retval; - - iso->flags |= HPSB_ISO_DRIVER_STARTED; - return retval; -} - -/** - * hpsb_iso_xmit_start - start DMA - */ -int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer) -{ - if (iso->type != HPSB_ISO_XMIT) - return -1; - - if (iso->flags & HPSB_ISO_DRIVER_STARTED) - return 0; - - if (cycle < -1) - cycle = -1; - else if (cycle >= 8000) - cycle %= 8000; - - iso->xmit_cycle = cycle; - - if (prebuffer < 0) - prebuffer = iso->buf_packets - 1; - else if (prebuffer == 0) - prebuffer = 1; - - if (prebuffer >= iso->buf_packets) - prebuffer = iso->buf_packets - 1; - - iso->prebuffer = prebuffer; - - /* remember the starting cycle; DMA will commence from xmit_queue_packets() - once enough packets have been buffered */ - iso->start_cycle = cycle; - - return 0; -} - -/** - * hpsb_iso_recv_start - start DMA - */ -int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) -{ - int retval = 0; - int isoctl_args[3]; - - if (iso->type != HPSB_ISO_RECV) - return -1; - - if (iso->flags & HPSB_ISO_DRIVER_STARTED) - return 0; - - if (cycle < -1) - cycle = -1; - else if (cycle >= 8000) - cycle %= 8000; - - isoctl_args[0] = cycle; - - if (tag_mask < 0) - /* match all tags */ - tag_mask = 0xF; - isoctl_args[1] = tag_mask; - - isoctl_args[2] = sync; - - retval = - iso->host->driver->isoctl(iso, RECV_START, - (unsigned long)&isoctl_args[0]); - if (retval) - return retval; - - iso->flags |= HPSB_ISO_DRIVER_STARTED; - return retval; -} - -/* check to make sure the user has not supplied bogus values of offset/len - * that would cause the kernel to access memory outside the buffer */ -static int hpsb_iso_check_offset_len(struct hpsb_iso *iso, - unsigned int offset, unsigned short len, - unsigned int *out_offset, - unsigned short *out_len) -{ - if (offset >= iso->buf_size) - return -EFAULT; - - /* make sure the packet does not go beyond the end of the buffer */ - if (offset + len > iso->buf_size) - return -EFAULT; - - /* check for wrap-around */ - if (offset + len < offset) - return -EFAULT; - - /* now we can trust 'offset' and 'length' */ - *out_offset = offset; - *out_len = len; - - return 0; -} - -/** - * hpsb_iso_xmit_queue_packet - queue a packet for transmission. - * - * @offset is relative to the beginning of the DMA buffer, where the packet's - * data payload should already have been placed. - */ -int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, - u8 tag, u8 sy) -{ - struct hpsb_iso_packet_info *info; - unsigned long flags; - int rv; - - if (iso->type != HPSB_ISO_XMIT) - return -EINVAL; - - /* is there space in the buffer? */ - if (iso->n_ready_packets <= 0) { - return -EBUSY; - } - - info = &iso->infos[iso->first_packet]; - - /* check for bogus offset/length */ - if (hpsb_iso_check_offset_len - (iso, offset, len, &info->offset, &info->len)) - return -EFAULT; - - info->tag = tag; - info->sy = sy; - - spin_lock_irqsave(&iso->lock, flags); - - rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long)info); - if (rv) - goto out; - - /* increment cursors */ - iso->first_packet = (iso->first_packet + 1) % iso->buf_packets; - iso->xmit_cycle = (iso->xmit_cycle + 1) % 8000; - iso->n_ready_packets--; - - if (iso->prebuffer != 0) { - iso->prebuffer--; - if (iso->prebuffer <= 0) { - iso->prebuffer = 0; - rv = do_iso_xmit_start(iso, iso->start_cycle); - } - } - - out: - spin_unlock_irqrestore(&iso->lock, flags); - return rv; -} - -/** - * hpsb_iso_xmit_sync - wait until all queued packets have been transmitted - */ -int hpsb_iso_xmit_sync(struct hpsb_iso *iso) -{ - if (iso->type != HPSB_ISO_XMIT) - return -EINVAL; - - return wait_event_interruptible(iso->waitq, - hpsb_iso_n_ready(iso) == - iso->buf_packets); -} - -/** - * hpsb_iso_packet_sent - * - * Available to low-level drivers. - * - * Call after a packet has been transmitted to the bus (interrupt context is - * OK). @cycle is the _exact_ cycle the packet was sent on. @error should be - * non-zero if some sort of error occurred when sending the packet. - */ -void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error) -{ - unsigned long flags; - spin_lock_irqsave(&iso->lock, flags); - - /* predict the cycle of the next packet to be queued */ - - /* jump ahead by the number of packets that are already buffered */ - cycle += iso->buf_packets - iso->n_ready_packets; - cycle %= 8000; - - iso->xmit_cycle = cycle; - iso->n_ready_packets++; - iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets; - - if (iso->n_ready_packets == iso->buf_packets || error != 0) { - /* the buffer has run empty! */ - atomic_inc(&iso->overflows); - } - - spin_unlock_irqrestore(&iso->lock, flags); -} - -/** - * hpsb_iso_packet_received - * - * Available to low-level drivers. - * - * Call after a packet has been received (interrupt context is OK). - */ -void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, - u16 total_len, u16 cycle, u8 channel, u8 tag, - u8 sy) -{ - unsigned long flags; - spin_lock_irqsave(&iso->lock, flags); - - if (iso->n_ready_packets == iso->buf_packets) { - /* overflow! */ - atomic_inc(&iso->overflows); - /* Record size of this discarded packet */ - iso->bytes_discarded += total_len; - } else { - struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma]; - info->offset = offset; - info->len = len; - info->total_len = total_len; - info->cycle = cycle; - info->channel = channel; - info->tag = tag; - info->sy = sy; - - iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets; - iso->n_ready_packets++; - } - - spin_unlock_irqrestore(&iso->lock, flags); -} - -/** - * hpsb_iso_recv_release_packets - release packets, reuse buffer - * - * @n_packets have been read out of the buffer, re-use the buffer space - */ -int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets) -{ - unsigned long flags; - unsigned int i; - int rv = 0; - - if (iso->type != HPSB_ISO_RECV) - return -1; - - spin_lock_irqsave(&iso->lock, flags); - for (i = 0; i < n_packets; i++) { - rv = iso->host->driver->isoctl(iso, RECV_RELEASE, - (unsigned long)&iso->infos[iso-> - first_packet]); - if (rv) - break; - - iso->first_packet = (iso->first_packet + 1) % iso->buf_packets; - iso->n_ready_packets--; - - /* release memory from packets discarded when queue was full */ - if (iso->n_ready_packets == 0) { /* Release only after all prior packets handled */ - if (iso->bytes_discarded != 0) { - struct hpsb_iso_packet_info inf; - inf.total_len = iso->bytes_discarded; - iso->host->driver->isoctl(iso, RECV_RELEASE, - (unsigned long)&inf); - iso->bytes_discarded = 0; - } - } - } - spin_unlock_irqrestore(&iso->lock, flags); - return rv; -} - -/** - * hpsb_iso_wake - * - * Available to low-level drivers. - * - * Call to wake waiting processes after buffer space has opened up. - */ -void hpsb_iso_wake(struct hpsb_iso *iso) -{ - wake_up_interruptible(&iso->waitq); - - if (iso->callback) - iso->callback(iso); -} diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h deleted file mode 100644 index c2089c0..0000000 --- a/drivers/ieee1394/iso.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * IEEE 1394 for Linux - * - * kernel ISO transmission/reception - * - * 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_ISO_H -#define IEEE1394_ISO_H - -#include <linux/spinlock_types.h> -#include <linux/wait.h> -#include <asm/atomic.h> -#include <asm/types.h> - -#include "dma.h" - -struct hpsb_host; - -/* high-level ISO interface */ - -/* - * This API sends and receives isochronous packets on a large, - * virtually-contiguous kernel memory buffer. The buffer may be mapped - * into a user-space process for zero-copy transmission and reception. - * - * There are no explicit boundaries between packets in the buffer. A - * packet may be transmitted or received at any location. However, - * low-level drivers may impose certain restrictions on alignment or - * size of packets. (e.g. in OHCI no packet may cross a page boundary, - * and packets should be quadlet-aligned) - */ - -/* Packet descriptor - the API maintains a ring buffer of these packet - * descriptors in kernel memory (hpsb_iso.infos[]). */ -struct hpsb_iso_packet_info { - /* offset of data payload relative to the first byte of the buffer */ - __u32 offset; - - /* length of the data payload, in bytes (not including the isochronous - * header) */ - __u16 len; - - /* (recv only) the cycle number (mod 8000) on which the packet was - * received */ - __u16 cycle; - - /* (recv only) channel on which the packet was received */ - __u8 channel; - - /* 2-bit 'tag' and 4-bit 'sy' fields of the isochronous header */ - __u8 tag; - __u8 sy; - - /* length in bytes of the packet including header/trailer. - * MUST be at structure end, since the first part of this structure is - * also defined in raw1394.h (i.e. struct raw1394_iso_packet_info), is - * copied to userspace and is accessed there through libraw1394. */ - __u16 total_len; -}; - -enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 }; - -/* The mode of the dma when receiving iso data. Must be supported by chip */ -enum raw1394_iso_dma_recv_mode { - HPSB_ISO_DMA_DEFAULT = -1, - HPSB_ISO_DMA_OLD_ABI = 0, - HPSB_ISO_DMA_BUFFERFILL = 1, - HPSB_ISO_DMA_PACKET_PER_BUFFER = 2 -}; - -struct hpsb_iso { - enum hpsb_iso_type type; - - /* pointer to low-level driver and its private data */ - struct hpsb_host *host; - void *hostdata; - - /* a function to be called (from interrupt context) after - * outgoing packets have been sent, or incoming packets have - * arrived */ - void (*callback)(struct hpsb_iso*); - - /* wait for buffer space */ - wait_queue_head_t waitq; - - int speed; /* IEEE1394_SPEED_100, 200, or 400 */ - int channel; /* -1 if multichannel */ - int dma_mode; /* dma receive mode */ - - - /* greatest # of packets between interrupts - controls - * the maximum latency of the buffer */ - int irq_interval; - - /* the buffer for packet data payloads */ - struct dma_region data_buf; - - /* size of data_buf, in bytes (always a multiple of PAGE_SIZE) */ - unsigned int buf_size; - - /* # of packets in the ringbuffer */ - unsigned int buf_packets; - - /* protects packet cursors */ - spinlock_t lock; - - /* the index of the next packet that will be produced - or consumed by the user */ - int first_packet; - - /* the index of the next packet that will be transmitted - or received by the 1394 hardware */ - int pkt_dma; - - /* how many packets, starting at first_packet: - * (transmit) are ready to be filled with data - * (receive) contain received data */ - int n_ready_packets; - - /* how many times the buffer has overflowed or underflowed */ - atomic_t overflows; - /* how many cycles were skipped for a given context */ - atomic_t skips; - - /* Current number of bytes lost in discarded packets */ - int bytes_discarded; - - /* private flags to track initialization progress */ -#define HPSB_ISO_DRIVER_INIT (1<<0) -#define HPSB_ISO_DRIVER_STARTED (1<<1) - unsigned int flags; - - /* # of packets left to prebuffer (xmit only) */ - int prebuffer; - - /* starting cycle for DMA (xmit only) */ - int start_cycle; - - /* cycle at which next packet will be transmitted, - * -1 if not known */ - int xmit_cycle; - - /* ringbuffer of packet descriptors in regular kernel memory - * XXX Keep this last, since we use over-allocated memory from - * this entry to fill this field. */ - struct hpsb_iso_packet_info *infos; -}; - -/* functions available to high-level drivers (e.g. raw1394) */ - -struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, - unsigned int data_buf_size, - unsigned int buf_packets, - int channel, - int speed, - int irq_interval, - void (*callback)(struct hpsb_iso*)); -struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, - unsigned int data_buf_size, - unsigned int buf_packets, - int channel, - int dma_mode, - int irq_interval, - void (*callback)(struct hpsb_iso*)); -int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel); -int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel); -int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask); -int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, - int prebuffer); -int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, - int tag_mask, int sync); -void hpsb_iso_stop(struct hpsb_iso *iso); -void hpsb_iso_shutdown(struct hpsb_iso *iso); -int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, - u8 tag, u8 sy); -int hpsb_iso_xmit_sync(struct hpsb_iso *iso); -int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, - unsigned int n_packets); -int hpsb_iso_recv_flush(struct hpsb_iso *iso); -int hpsb_iso_n_ready(struct hpsb_iso *iso); - -/* the following are callbacks available to low-level drivers */ - -void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error); -void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len, - u16 total_len, u16 cycle, u8 channel, u8 tag, - u8 sy); -void hpsb_iso_wake(struct hpsb_iso *iso); - -#endif /* IEEE1394_ISO_H */ diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c deleted file mode 100644 index 1835021..0000000 --- a/drivers/ieee1394/nodemgr.c +++ /dev/null @@ -1,1901 +0,0 @@ -/* - * Node information (ConfigROM) collection and management. - * - * Copyright (C) 2000 Andreas E. Bombe - * 2001-2003 Ben Collins <bcollins@debian.net> - * - * This code is licensed under the GPL. See the file COPYING in the root - * directory of the kernel sources for details. - */ - -#include <linux/bitmap.h> -#include <linux/kernel.h> -#include <linux/kmemcheck.h> -#include <linux/list.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/kthread.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/mutex.h> -#include <linux/freezer.h> -#include <asm/atomic.h> - -#include "csr.h" -#include "highlevel.h" -#include "hosts.h" -#include "ieee1394.h" -#include "ieee1394_core.h" -#include "ieee1394_hotplug.h" -#include "ieee1394_types.h" -#include "ieee1394_transactions.h" -#include "nodemgr.h" - -static int ignore_drivers; -module_param(ignore_drivers, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ignore_drivers, "Disable automatic probing for drivers."); - -struct nodemgr_csr_info { - struct hpsb_host *host; - nodeid_t nodeid; - unsigned int generation; - - kmemcheck_bitfield_begin(flags); - unsigned int speed_unverified:1; - kmemcheck_bitfield_end(flags); -}; - - -/* - * Correct the speed map entry. This is necessary - * - for nodes with link speed < phy speed, - * - for 1394b nodes with negotiated phy port speed < IEEE1394_SPEED_MAX. - * A possible speed is determined by trial and error, using quadlet reads. - */ -static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr, - quadlet_t *buffer) -{ - quadlet_t q; - u8 i, *speed, old_speed, good_speed; - int error; - - speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]); - old_speed = *speed; - good_speed = IEEE1394_SPEED_MAX + 1; - - /* Try every speed from S100 to old_speed. - * If we did it the other way around, a too low speed could be caught - * if the retry succeeded for some other reason, e.g. because the link - * just finished its initialization. */ - for (i = IEEE1394_SPEED_100; i <= old_speed; i++) { - *speed = i; - error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, - &q, 4); - if (error) - break; - *buffer = q; - good_speed = i; - } - if (good_speed <= IEEE1394_SPEED_MAX) { - HPSB_DEBUG("Speed probe of node " NODE_BUS_FMT " yields %s", - NODE_BUS_ARGS(ci->host, ci->nodeid), - hpsb_speedto_str[good_speed]); - *speed = good_speed; - ci->speed_unverified = 0; - return 0; - } - *speed = old_speed; - return error; -} - -static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, - void *buffer, void *__ci) -{ - struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci; - int i, error; - - for (i = 1; ; i++) { - error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr, - buffer, 4); - if (!error) { - ci->speed_unverified = 0; - break; - } - /* Give up after 3rd failure. */ - if (i == 3) - break; - - /* The ieee1394_core guessed the node's speed capability from - * the self ID. Check whether a lower speed works. */ - if (ci->speed_unverified) { - error = nodemgr_check_speed(ci, addr, buffer); - if (!error) - break; - } - if (msleep_interruptible(334)) - return -EINTR; - } - return error; -} - -static struct csr1212_bus_ops nodemgr_csr_ops = { - .bus_read = nodemgr_bus_read, -}; - - -/* - * Basically what we do here is start off retrieving the bus_info block. - * From there will fill in some info about the node, verify it is of IEEE - * 1394 type, and that the crc checks out ok. After that we start off with - * the root directory, and subdirectories. To do this, we retrieve the - * quadlet header for a directory, find out the length, and retrieve the - * complete directory entry (be it a leaf or a directory). We then process - * it and add the info to our structure for that particular node. - * - * We verify CRC's along the way for each directory/block/leaf. The entire - * node structure is generic, and simply stores the information in a way - * that's easy to parse by the protocol interface. - */ - -/* - * The nodemgr relies heavily on the Driver Model for device callbacks and - * driver/device mappings. The old nodemgr used to handle all this itself, - * but now we are much simpler because of the LDM. - */ - -struct host_info { - struct hpsb_host *host; - struct list_head list; - struct task_struct *thread; -}; - -static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); -static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env); - -struct bus_type ieee1394_bus_type = { - .name = "ieee1394", - .match = nodemgr_bus_match, -}; - -static void host_cls_release(struct device *dev) -{ - put_device(&container_of((dev), struct hpsb_host, host_dev)->device); -} - -struct class hpsb_host_class = { - .name = "ieee1394_host", - .dev_release = host_cls_release, -}; - -static void ne_cls_release(struct device *dev) -{ - put_device(&container_of((dev), struct node_entry, node_dev)->device); -} - -static struct class nodemgr_ne_class = { - .name = "ieee1394_node", - .dev_release = ne_cls_release, -}; - -static void ud_cls_release(struct device *dev) -{ - put_device(&container_of((dev), struct unit_directory, unit_dev)->device); -} - -/* The name here is only so that unit directory hotplug works with old - * style hotplug, which only ever did unit directories anyway. - */ -static struct class nodemgr_ud_class = { - .name = "ieee1394", - .dev_release = ud_cls_release, - .dev_uevent = nodemgr_uevent, -}; - -static struct hpsb_highlevel nodemgr_highlevel; - - -static void nodemgr_release_ud(struct device *dev) -{ - struct unit_directory *ud = container_of(dev, struct unit_directory, device); - - if (ud->vendor_name_kv) - csr1212_release_keyval(ud->vendor_name_kv); - if (ud->model_name_kv) - csr1212_release_keyval(ud->model_name_kv); - - kfree(ud); -} - -static void nodemgr_release_ne(struct device *dev) -{ - struct node_entry *ne = container_of(dev, struct node_entry, device); - - if (ne->vendor_name_kv) - csr1212_release_keyval(ne->vendor_name_kv); - - kfree(ne); -} - - -static void nodemgr_release_host(struct device *dev) -{ - struct hpsb_host *host = container_of(dev, struct hpsb_host, device); - - csr1212_destroy_csr(host->csr.rom); - - kfree(host); -} - -static int nodemgr_ud_platform_data; - -static struct device nodemgr_dev_template_ud = { - .bus = &ieee1394_bus_type, - .release = nodemgr_release_ud, - .platform_data = &nodemgr_ud_platform_data, -}; - -static struct device nodemgr_dev_template_ne = { - .bus = &ieee1394_bus_type, - .release = nodemgr_release_ne, -}; - -/* This dummy driver prevents the host devices from being scanned. We have no - * useful drivers for them yet, and there would be a deadlock possible if the - * driver core scans the host device while the host's low-level driver (i.e. - * the host's parent device) is being removed. */ -static struct device_driver nodemgr_mid_layer_driver = { - .bus = &ieee1394_bus_type, - .name = "nodemgr", - .owner = THIS_MODULE, -}; - -struct device nodemgr_dev_template_host = { - .bus = &ieee1394_bus_type, - .release = nodemgr_release_host, -}; - - -#define fw_attr(class, class_type, field, type, format_string) \ -static ssize_t fw_show_##class##_##field (struct device *dev, struct device_attribute *attr, char *buf)\ -{ \ - class_type *class; \ - class = container_of(dev, class_type, device); \ - return sprintf(buf, format_string, (type)class->field); \ -} \ -static struct device_attribute dev_attr_##class##_##field = { \ - .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ - .show = fw_show_##class##_##field, \ -}; - -#define fw_attr_td(class, class_type, td_kv) \ -static ssize_t fw_show_##class##_##td_kv (struct device *dev, struct device_attribute *attr, char *buf)\ -{ \ - int len; \ - class_type *class = container_of(dev, class_type, device); \ - len = (class->td_kv->value.leaf.len - 2) * sizeof(quadlet_t); \ - memcpy(buf, \ - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(class->td_kv), \ - len); \ - while (buf[len - 1] == '\0') \ - len--; \ - buf[len++] = '\n'; \ - buf[len] = '\0'; \ - return len; \ -} \ -static struct device_attribute dev_attr_##class##_##td_kv = { \ - .attr = {.name = __stringify(td_kv), .mode = S_IRUGO }, \ - .show = fw_show_##class##_##td_kv, \ -}; - - -#define fw_drv_attr(field, type, format_string) \ -static ssize_t fw_drv_show_##field (struct device_driver *drv, char *buf) \ -{ \ - struct hpsb_protocol_driver *driver; \ - driver = container_of(drv, struct hpsb_protocol_driver, driver); \ - return sprintf(buf, format_string, (type)driver->field);\ -} \ -static struct driver_attribute driver_attr_drv_##field = { \ - .attr = {.name = __stringify(field), .mode = S_IRUGO }, \ - .show = fw_drv_show_##field, \ -}; - - -static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct node_entry *ne = container_of(dev, struct node_entry, device); - - return sprintf(buf, "IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d) " - "LSPD(%d) MAX_REC(%d) MAX_ROM(%d) CYC_CLK_ACC(%d)\n", - ne->busopt.irmc, - ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc, - ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd, - ne->busopt.max_rec, - ne->busopt.max_rom, - ne->busopt.cyc_clk_acc); -} -static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL); - - -#ifdef HPSB_DEBUG_TLABELS -static ssize_t fw_show_ne_tlabels_free(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct node_entry *ne = container_of(dev, struct node_entry, device); - unsigned long flags; - unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map; - int tf; - - spin_lock_irqsave(&hpsb_tlabel_lock, flags); - tf = 64 - bitmap_weight(tp, 64); - spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); - - return sprintf(buf, "%d\n", tf); -} -static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL); - - -static ssize_t fw_show_ne_tlabels_mask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct node_entry *ne = container_of(dev, struct node_entry, device); - unsigned long flags; - unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map; - u64 tm; - - spin_lock_irqsave(&hpsb_tlabel_lock, flags); -#if (BITS_PER_LONG <= 32) - tm = ((u64)tp[0] << 32) + tp[1]; -#else - tm = tp[0]; -#endif - spin_unlock_irqrestore(&hpsb_tlabel_lock, flags); - - return sprintf(buf, "0x%016llx\n", (unsigned long long)tm); -} -static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL); -#endif /* HPSB_DEBUG_TLABELS */ - - -static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct unit_directory *ud = container_of(dev, struct unit_directory, device); - int state = simple_strtoul(buf, NULL, 10); - - if (state == 1) { - ud->ignore_driver = 1; - device_release_driver(dev); - } else if (state == 0) - ud->ignore_driver = 0; - - return count; -} -static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct unit_directory *ud = container_of(dev, struct unit_directory, device); - - return sprintf(buf, "%d\n", ud->ignore_driver); -} -static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver); - - -static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf, - size_t count) -{ - int error = 0; - - if (simple_strtoul(buf, NULL, 10) == 1) - error = bus_rescan_devices(&ieee1394_bus_type); - return error ? error : count; -} -static ssize_t fw_get_rescan(struct bus_type *bus, char *buf) -{ - return sprintf(buf, "You can force a rescan of the bus for " - "drivers by writing a 1 to this file\n"); -} -static BUS_ATTR(rescan, S_IWUSR | S_IRUGO, fw_get_rescan, fw_set_rescan); - - -static ssize_t fw_set_ignore_drivers(struct bus_type *bus, const char *buf, size_t count) -{ - int state = simple_strtoul(buf, NULL, 10); - - if (state == 1) - ignore_drivers = 1; - else if (state == 0) - ignore_drivers = 0; - - return count; -} -static ssize_t fw_get_ignore_drivers(struct bus_type *bus, char *buf) -{ - return sprintf(buf, "%d\n", ignore_drivers); -} -static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set_ignore_drivers); - - -struct bus_attribute *const fw_bus_attrs[] = { - &bus_attr_rescan, - &bus_attr_ignore_drivers, - NULL -}; - - -fw_attr(ne, struct node_entry, capabilities, unsigned int, "0x%06x\n") -fw_attr(ne, struct node_entry, nodeid, unsigned int, "0x%04x\n") - -fw_attr(ne, struct node_entry, vendor_id, unsigned int, "0x%06x\n") -fw_attr_td(ne, struct node_entry, vendor_name_kv) - -fw_attr(ne, struct node_entry, guid, unsigned long long, "0x%016Lx\n") -fw_attr(ne, struct node_entry, guid_vendor_id, unsigned int, "0x%06x\n") -fw_attr(ne, struct node_entry, in_limbo, int, "%d\n"); - -static struct device_attribute *const fw_ne_attrs[] = { - &dev_attr_ne_guid, - &dev_attr_ne_guid_vendor_id, - &dev_attr_ne_capabilities, - &dev_attr_ne_vendor_id, - &dev_attr_ne_nodeid, - &dev_attr_bus_options, -#ifdef HPSB_DEBUG_TLABELS - &dev_attr_tlabels_free, - &dev_attr_tlabels_mask, -#endif -}; - - - -fw_attr(ud, struct unit_directory, address, unsigned long long, "0x%016Lx\n") -fw_attr(ud, struct unit_directory, length, int, "%d\n") -/* These are all dependent on the value being provided */ -fw_attr(ud, struct unit_directory, vendor_id, unsigned int, "0x%06x\n") -fw_attr(ud, struct unit_directory, model_id, unsigned int, "0x%06x\n") -fw_attr(ud, struct unit_directory, specifier_id, unsigned int, "0x%06x\n") -fw_attr(ud, struct unit_directory, version, unsigned int, "0x%06x\n") -fw_attr_td(ud, struct unit_directory, vendor_name_kv) -fw_attr_td(ud, struct unit_directory, model_name_kv) - -static struct device_attribute *const fw_ud_attrs[] = { - &dev_attr_ud_address, - &dev_attr_ud_length, - &dev_attr_ignore_driver, -}; - - -fw_attr(host, struct hpsb_host, node_count, int, "%d\n") -fw_attr(host, struct hpsb_host, selfid_count, int, "%d\n") -fw_attr(host, struct hpsb_host, nodes_active, int, "%d\n") -fw_attr(host, struct hpsb_host, in_bus_reset, int, "%d\n") -fw_attr(host, struct hpsb_host, is_root, int, "%d\n") -fw_attr(host, struct hpsb_host, is_cycmst, int, "%d\n") -fw_attr(host, struct hpsb_host, is_irm, int, "%d\n") -fw_attr(host, struct hpsb_host, is_busmgr, int, "%d\n") - -static struct device_attribute *const fw_host_attrs[] = { - &dev_attr_host_node_count, - &dev_attr_host_selfid_count, - &dev_attr_host_nodes_active, - &dev_attr_host_in_bus_reset, - &dev_attr_host_is_root, - &dev_attr_host_is_cycmst, - &dev_attr_host_is_irm, - &dev_attr_host_is_busmgr, -}; - - -static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf) -{ - struct hpsb_protocol_driver *driver; - const struct ieee1394_device_id *id; - int length = 0; - char *scratch = buf; - - driver = container_of(drv, struct hpsb_protocol_driver, driver); - id = driver->id_table; - if (!id) - return 0; - - for (; id->match_flags != 0; id++) { - int need_coma = 0; - - if (id->match_flags & IEEE1394_MATCH_VENDOR_ID) { - length += sprintf(scratch, "vendor_id=0x%06x", id->vendor_id); - scratch = buf + length; - need_coma++; - } - - if (id->match_flags & IEEE1394_MATCH_MODEL_ID) { - length += sprintf(scratch, "%smodel_id=0x%06x", - need_coma++ ? "," : "", - id->model_id); - scratch = buf + length; - } - - if (id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) { - length += sprintf(scratch, "%sspecifier_id=0x%06x", - need_coma++ ? "," : "", - id->specifier_id); - scratch = buf + length; - } - - if (id->match_flags & IEEE1394_MATCH_VERSION) { - length += sprintf(scratch, "%sversion=0x%06x", - need_coma++ ? "," : "", - id->version); - scratch = buf + length; - } - - if (need_coma) { - *scratch++ = '\n'; - length++; - } - } - - return length; -} -static DRIVER_ATTR(device_ids,S_IRUGO,fw_show_drv_device_ids,NULL); - - -fw_drv_attr(name, const char *, "%s\n") - -static struct driver_attribute *const fw_drv_attrs[] = { - &driver_attr_drv_name, - &driver_attr_device_ids, -}; - - -static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver) -{ - struct device_driver *drv = &driver->driver; - int i; - - for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++) - if (driver_create_file(drv, fw_drv_attrs[i])) - goto fail; - return; -fail: - HPSB_ERR("Failed to add sysfs attribute"); -} - - -static void nodemgr_remove_drv_files(struct hpsb_protocol_driver *driver) -{ - struct device_driver *drv = &driver->driver; - int i; - - for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++) - driver_remove_file(drv, fw_drv_attrs[i]); -} - - -static void nodemgr_create_ne_dev_files(struct node_entry *ne) -{ - struct device *dev = &ne->device; - int i; - - for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++) - if (device_create_file(dev, fw_ne_attrs[i])) - goto fail; - return; -fail: - HPSB_ERR("Failed to add sysfs attribute"); -} - - -static void nodemgr_create_host_dev_files(struct hpsb_host *host) -{ - struct device *dev = &host->device; - int i; - - for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++) - if (device_create_file(dev, fw_host_attrs[i])) - goto fail; - return; -fail: - HPSB_ERR("Failed to add sysfs attribute"); -} - - -static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, - nodeid_t nodeid); - -static void nodemgr_update_host_dev_links(struct hpsb_host *host) -{ - struct device *dev = &host->device; - struct node_entry *ne; - - sysfs_remove_link(&dev->kobj, "irm_id"); - sysfs_remove_link(&dev->kobj, "busmgr_id"); - sysfs_remove_link(&dev->kobj, "host_id"); - - if ((ne = find_entry_by_nodeid(host, host->irm_id)) && - sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id")) - goto fail; - if ((ne = find_entry_by_nodeid(host, host->busmgr_id)) && - sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id")) - goto fail; - if ((ne = find_entry_by_nodeid(host, host->node_id)) && - sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id")) - goto fail; - return; -fail: - HPSB_ERR("Failed to update sysfs attributes for host %d", host->id); -} - -static void nodemgr_create_ud_dev_files(struct unit_directory *ud) -{ - struct device *dev = &ud->device; - int i; - - for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++) - if (device_create_file(dev, fw_ud_attrs[i])) - goto fail; - if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) - if (device_create_file(dev, &dev_attr_ud_specifier_id)) - goto fail; - if (ud->flags & UNIT_DIRECTORY_VERSION) - if (device_create_file(dev, &dev_attr_ud_version)) - goto fail; - if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) { - if (device_create_file(dev, &dev_attr_ud_vendor_id)) - goto fail; - if (ud->vendor_name_kv && - device_create_file(dev, &dev_attr_ud_vendor_name_kv)) - goto fail; - } - if (ud->flags & UNIT_DIRECTORY_MODEL_ID) { - if (device_create_file(dev, &dev_attr_ud_model_id)) - goto fail; - if (ud->model_name_kv && - device_create_file(dev, &dev_attr_ud_model_name_kv)) - goto fail; - } - return; -fail: - HPSB_ERR("Failed to add sysfs attribute"); -} - - -static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) -{ - struct hpsb_protocol_driver *driver; - struct unit_directory *ud; - const struct ieee1394_device_id *id; - - /* We only match unit directories */ - if (dev->platform_data != &nodemgr_ud_platform_data) - return 0; - - ud = container_of(dev, struct unit_directory, device); - if (ud->ne->in_limbo || ud->ignore_driver) - return 0; - - /* We only match drivers of type hpsb_protocol_driver */ - if (drv == &nodemgr_mid_layer_driver) - return 0; - - driver = container_of(drv, struct hpsb_protocol_driver, driver); - id = driver->id_table; - if (!id) - return 0; - - for (; id->match_flags != 0; id++) { - if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && - id->vendor_id != ud->vendor_id) - continue; - - if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) && - id->model_id != ud->model_id) - continue; - - if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) && - id->specifier_id != ud->specifier_id) - continue; - - if ((id->match_flags & IEEE1394_MATCH_VERSION) && - id->version != ud->version) - continue; - - return 1; - } - - return 0; -} - - -static DEFINE_MUTEX(nodemgr_serialize_remove_uds); - -static int match_ne(struct device *dev, void *data) -{ - struct unit_directory *ud; - struct node_entry *ne = data; - - ud = container_of(dev, struct unit_directory, unit_dev); - return ud->ne == ne; -} - -static void nodemgr_remove_uds(struct node_entry *ne) -{ - struct device *dev; - struct unit_directory *ud; - - /* Use class_find device to iterate the devices. Since this code - * may be called from other contexts besides the knodemgrds, - * protect it by nodemgr_serialize_remove_uds. - */ - mutex_lock(&nodemgr_serialize_remove_uds); - for (;;) { - dev = class_find_device(&nodemgr_ud_class, NULL, ne, match_ne); - if (!dev) - break; - ud = container_of(dev, struct unit_directory, unit_dev); - put_device(dev); - device_unregister(&ud->unit_dev); - device_unregister(&ud->device); - } - mutex_unlock(&nodemgr_serialize_remove_uds); -} - - -static void nodemgr_remove_ne(struct node_entry *ne) -{ - struct device *dev; - - dev = get_device(&ne->device); - if (!dev) - return; - - HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", - NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); - nodemgr_remove_uds(ne); - - device_unregister(&ne->node_dev); - device_unregister(dev); - - put_device(dev); -} - -static int remove_host_dev(struct device *dev, void *data) -{ - if (dev->bus == &ieee1394_bus_type) - nodemgr_remove_ne(container_of(dev, struct node_entry, - device)); - return 0; -} - -static void nodemgr_remove_host_dev(struct device *dev) -{ - device_for_each_child(dev, NULL, remove_host_dev); - sysfs_remove_link(&dev->kobj, "irm_id"); - sysfs_remove_link(&dev->kobj, "busmgr_id"); - sysfs_remove_link(&dev->kobj, "host_id"); -} - - -static void nodemgr_update_bus_options(struct node_entry *ne) -{ -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - static const u16 mr[] = { 4, 64, 1024, 0}; -#endif - quadlet_t busoptions = be32_to_cpu(ne->csr->bus_info_data[2]); - - ne->busopt.irmc = (busoptions >> 31) & 1; - ne->busopt.cmc = (busoptions >> 30) & 1; - ne->busopt.isc = (busoptions >> 29) & 1; - ne->busopt.bmc = (busoptions >> 28) & 1; - ne->busopt.pmc = (busoptions >> 27) & 1; - ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff; - ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1); - ne->busopt.max_rom = (busoptions >> 8) & 0x3; - ne->busopt.generation = (busoptions >> 4) & 0xf; - ne->busopt.lnkspd = busoptions & 0x7; - - HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d " - "cyc_clk_acc=%d max_rec=%d max_rom=%d gen=%d lspd=%d", - busoptions, ne->busopt.irmc, ne->busopt.cmc, - ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc, - ne->busopt.cyc_clk_acc, ne->busopt.max_rec, - mr[ne->busopt.max_rom], - ne->busopt.generation, ne->busopt.lnkspd); -} - - -static struct node_entry *nodemgr_create_node(octlet_t guid, - struct csr1212_csr *csr, struct hpsb_host *host, - nodeid_t nodeid, unsigned int generation) -{ - struct node_entry *ne; - - ne = kzalloc(sizeof(*ne), GFP_KERNEL); - if (!ne) - goto fail_alloc; - - ne->host = host; - ne->nodeid = nodeid; - ne->generation = generation; - ne->needs_probe = true; - - ne->guid = guid; - ne->guid_vendor_id = (guid >> 40) & 0xffffff; - ne->csr = csr; - - memcpy(&ne->device, &nodemgr_dev_template_ne, - sizeof(ne->device)); - ne->device.parent = &host->device; - dev_set_name(&ne->device, "%016Lx", (unsigned long long)(ne->guid)); - - ne->node_dev.parent = &ne->device; - ne->node_dev.class = &nodemgr_ne_class; - dev_set_name(&ne->node_dev, "%016Lx", (unsigned long long)(ne->guid)); - - if (device_register(&ne->device)) - goto fail_devreg; - if (device_register(&ne->node_dev)) - goto fail_classdevreg; - get_device(&ne->device); - - nodemgr_create_ne_dev_files(ne); - - nodemgr_update_bus_options(ne); - - HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", - (host->node_id == nodeid) ? "Host" : "Node", - NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid); - - return ne; - -fail_classdevreg: - device_unregister(&ne->device); -fail_devreg: - kfree(ne); -fail_alloc: - HPSB_ERR("Failed to create node ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", - NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid); - - return NULL; -} - -static int match_ne_guid(struct device *dev, void *data) -{ - struct node_entry *ne; - u64 *guid = data; - - ne = container_of(dev, struct node_entry, node_dev); - return ne->guid == *guid; -} - -static struct node_entry *find_entry_by_guid(u64 guid) -{ - struct device *dev; - struct node_entry *ne; - - dev = class_find_device(&nodemgr_ne_class, NULL, &guid, match_ne_guid); - if (!dev) - return NULL; - ne = container_of(dev, struct node_entry, node_dev); - put_device(dev); - - return ne; -} - -struct match_nodeid_parameter { - struct hpsb_host *host; - nodeid_t nodeid; -}; - -static int match_ne_nodeid(struct device *dev, void *data) -{ - int found = 0; - struct node_entry *ne; - struct match_nodeid_parameter *p = data; - - if (!dev) - goto ret; - ne = container_of(dev, struct node_entry, node_dev); - if (ne->host == p->host && ne->nodeid == p->nodeid) - found = 1; -ret: - return found; -} - -static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, - nodeid_t nodeid) -{ - struct device *dev; - struct node_entry *ne; - struct match_nodeid_parameter p; - - p.host = host; - p.nodeid = nodeid; - - dev = class_find_device(&nodemgr_ne_class, NULL, &p, match_ne_nodeid); - if (!dev) - return NULL; - ne = container_of(dev, struct node_entry, node_dev); - put_device(dev); - - return ne; -} - - -static void nodemgr_register_device(struct node_entry *ne, - struct unit_directory *ud, struct device *parent) -{ - memcpy(&ud->device, &nodemgr_dev_template_ud, - sizeof(ud->device)); - - ud->device.parent = parent; - - dev_set_name(&ud->device, "%s-%u", dev_name(&ne->device), ud->id); - - ud->unit_dev.parent = &ud->device; - ud->unit_dev.class = &nodemgr_ud_class; - dev_set_name(&ud->unit_dev, "%s-%u", dev_name(&ne->device), ud->id); - - if (device_register(&ud->device)) - goto fail_devreg; - if (device_register(&ud->unit_dev)) - goto fail_classdevreg; - get_device(&ud->device); - - nodemgr_create_ud_dev_files(ud); - - return; - -fail_classdevreg: - device_unregister(&ud->device); -fail_devreg: - HPSB_ERR("Failed to create unit %s", dev_name(&ud->device)); -} - - -/* This implementation currently only scans the config rom and its - * immediate unit directories looking for software_id and - * software_version entries, in order to get driver autoloading working. */ -static struct unit_directory *nodemgr_process_unit_directory - (struct node_entry *ne, struct csr1212_keyval *ud_kv, - unsigned int *id, struct unit_directory *parent) -{ - struct unit_directory *ud; - struct unit_directory *ud_child = NULL; - struct csr1212_dentry *dentry; - struct csr1212_keyval *kv; - u8 last_key_id = 0; - - ud = kzalloc(sizeof(*ud), GFP_KERNEL); - if (!ud) - goto unit_directory_error; - - ud->ne = ne; - ud->ignore_driver = ignore_drivers; - ud->address = ud_kv->offset + CSR1212_REGISTER_SPACE_BASE; - ud->directory_id = ud->address & 0xffffff; - ud->ud_kv = ud_kv; - ud->id = (*id)++; - - /* inherit vendor_id from root directory if none exists in unit dir */ - ud->vendor_id = ne->vendor_id; - - csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) { - switch (kv->key.id) { - case CSR1212_KV_ID_VENDOR: - if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) { - ud->vendor_id = kv->value.immediate; - ud->flags |= UNIT_DIRECTORY_VENDOR_ID; - } - break; - - case CSR1212_KV_ID_MODEL: - ud->model_id = kv->value.immediate; - ud->flags |= UNIT_DIRECTORY_MODEL_ID; - break; - - case CSR1212_KV_ID_SPECIFIER_ID: - ud->specifier_id = kv->value.immediate; - ud->flags |= UNIT_DIRECTORY_SPECIFIER_ID; - break; - - case CSR1212_KV_ID_VERSION: - ud->version = kv->value.immediate; - ud->flags |= UNIT_DIRECTORY_VERSION; - break; - - case CSR1212_KV_ID_DESCRIPTOR: - if (kv->key.type == CSR1212_KV_TYPE_LEAF && - CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 && - CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 && - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 && - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 && - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { - switch (last_key_id) { - case CSR1212_KV_ID_VENDOR: - csr1212_keep_keyval(kv); - ud->vendor_name_kv = kv; - break; - - case CSR1212_KV_ID_MODEL: - csr1212_keep_keyval(kv); - ud->model_name_kv = kv; - break; - - } - } /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */ - break; - - case CSR1212_KV_ID_DEPENDENT_INFO: - /* Logical Unit Number */ - if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) { - if (ud->flags & UNIT_DIRECTORY_HAS_LUN) { - ud_child = kmemdup(ud, sizeof(*ud_child), GFP_KERNEL); - if (!ud_child) - goto unit_directory_error; - nodemgr_register_device(ne, ud_child, &ne->device); - ud_child = NULL; - - ud->id = (*id)++; - } - ud->lun = kv->value.immediate; - ud->flags |= UNIT_DIRECTORY_HAS_LUN; - - /* Logical Unit Directory */ - } else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) { - /* This should really be done in SBP2 as this is - * doing SBP2 specific parsing. - */ - - /* first register the parent unit */ - ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY; - if (ud->device.bus != &ieee1394_bus_type) - nodemgr_register_device(ne, ud, &ne->device); - - /* process the child unit */ - ud_child = nodemgr_process_unit_directory(ne, kv, id, ud); - - if (ud_child == NULL) - break; - - /* inherit unspecified values, the driver core picks it up */ - if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) && - !(ud_child->flags & UNIT_DIRECTORY_MODEL_ID)) - { - ud_child->flags |= UNIT_DIRECTORY_MODEL_ID; - ud_child->model_id = ud->model_id; - } - if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) && - !(ud_child->flags & UNIT_DIRECTORY_SPECIFIER_ID)) - { - ud_child->flags |= UNIT_DIRECTORY_SPECIFIER_ID; - ud_child->specifier_id = ud->specifier_id; - } - if ((ud->flags & UNIT_DIRECTORY_VERSION) && - !(ud_child->flags & UNIT_DIRECTORY_VERSION)) - { - ud_child->flags |= UNIT_DIRECTORY_VERSION; - ud_child->version = ud->version; - } - - /* register the child unit */ - ud_child->flags |= UNIT_DIRECTORY_LUN_DIRECTORY; - nodemgr_register_device(ne, ud_child, &ud->device); - } - - break; - - case CSR1212_KV_ID_DIRECTORY_ID: - ud->directory_id = kv->value.immediate; - break; - - default: - break; - } - last_key_id = kv->key.id; - } - - /* do not process child units here and only if not already registered */ - if (!parent && ud->device.bus != &ieee1394_bus_type) - nodemgr_register_device(ne, ud, &ne->device); - - return ud; - -unit_directory_error: - kfree(ud); - return NULL; -} - - -static void nodemgr_process_root_directory(struct node_entry *ne) -{ - unsigned int ud_id = 0; - struct csr1212_dentry *dentry; - struct csr1212_keyval *kv, *vendor_name_kv = NULL; - u8 last_key_id = 0; - - ne->needs_probe = false; - - csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) { - switch (kv->key.id) { - case CSR1212_KV_ID_VENDOR: - ne->vendor_id = kv->value.immediate; - break; - - case CSR1212_KV_ID_NODE_CAPABILITIES: - ne->capabilities = kv->value.immediate; - break; - - case CSR1212_KV_ID_UNIT: - nodemgr_process_unit_directory(ne, kv, &ud_id, NULL); - break; - - case CSR1212_KV_ID_DESCRIPTOR: - if (last_key_id == CSR1212_KV_ID_VENDOR) { - if (kv->key.type == CSR1212_KV_TYPE_LEAF && - CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 && - CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 && - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 && - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 && - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { - csr1212_keep_keyval(kv); - vendor_name_kv = kv; - } - } - break; - } - last_key_id = kv->key.id; - } - - if (ne->vendor_name_kv) { - kv = ne->vendor_name_kv; - ne->vendor_name_kv = vendor_name_kv; - csr1212_release_keyval(kv); - } else if (vendor_name_kv) { - ne->vendor_name_kv = vendor_name_kv; - if (device_create_file(&ne->device, - &dev_attr_ne_vendor_name_kv) != 0) - HPSB_ERR("Failed to add sysfs attribute"); - } -} - -#ifdef CONFIG_HOTPLUG - -static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct unit_directory *ud; - int retval = 0; - /* ieee1394:venNmoNspNverN */ - char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; - - if (!dev) - return -ENODEV; - - ud = container_of(dev, struct unit_directory, unit_dev); - - if (ud->ne->in_limbo || ud->ignore_driver) - return -ENODEV; - -#define PUT_ENVP(fmt,val) \ -do { \ - retval = add_uevent_var(env, fmt, val); \ - if (retval) \ - return retval; \ -} while (0) - - PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id); - PUT_ENVP("MODEL_ID=%06x", ud->model_id); - PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid); - PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id); - PUT_ENVP("VERSION=%06x", ud->version); - snprintf(buf, sizeof(buf), "ieee1394:ven%08Xmo%08Xsp%08Xver%08X", - ud->vendor_id, - ud->model_id, - ud->specifier_id, - ud->version); - PUT_ENVP("MODALIAS=%s", buf); - -#undef PUT_ENVP - - return 0; -} - -#else - -static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - return -ENODEV; -} - -#endif /* CONFIG_HOTPLUG */ - - -int __hpsb_register_protocol(struct hpsb_protocol_driver *drv, - struct module *owner) -{ - int error; - - drv->driver.bus = &ieee1394_bus_type; - drv->driver.owner = owner; - drv->driver.name = drv->name; - - /* This will cause a probe for devices */ - error = driver_register(&drv->driver); - if (!error) - nodemgr_create_drv_files(drv); - return error; -} - -void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver) -{ - nodemgr_remove_drv_files(driver); - /* This will subsequently disconnect all devices that our driver - * is attached to. */ - driver_unregister(&driver->driver); -} - - -/* - * This function updates nodes that were present on the bus before the - * reset and still are after the reset. The nodeid and the config rom - * may have changed, and the drivers managing this device must be - * informed that this device just went through a bus reset, to allow - * the to take whatever actions required. - */ -static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, - nodeid_t nodeid, unsigned int generation) -{ - if (ne->nodeid != nodeid) { - HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT, - NODE_BUS_ARGS(ne->host, ne->nodeid), - NODE_BUS_ARGS(ne->host, nodeid)); - ne->nodeid = nodeid; - } - - if (ne->busopt.generation != ((be32_to_cpu(csr->bus_info_data[2]) >> 4) & 0xf)) { - kfree(ne->csr->private); - csr1212_destroy_csr(ne->csr); - ne->csr = csr; - - /* If the node's configrom generation has changed, we - * unregister all the unit directories. */ - nodemgr_remove_uds(ne); - - nodemgr_update_bus_options(ne); - - /* Mark the node as new, so it gets re-probed */ - ne->needs_probe = true; - } else { - /* old cache is valid, so update its generation */ - struct nodemgr_csr_info *ci = ne->csr->private; - ci->generation = generation; - /* free the partially filled now unneeded new cache */ - kfree(csr->private); - csr1212_destroy_csr(csr); - } - - /* Finally, mark the node current */ - smp_wmb(); - ne->generation = generation; - - if (ne->in_limbo) { - device_remove_file(&ne->device, &dev_attr_ne_in_limbo); - ne->in_limbo = false; - - HPSB_DEBUG("Node reactivated: " - "ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", - NODE_BUS_ARGS(ne->host, ne->nodeid), - (unsigned long long)ne->guid); - } -} - -static void nodemgr_node_scan_one(struct hpsb_host *host, - nodeid_t nodeid, int generation) -{ - struct node_entry *ne; - octlet_t guid; - struct csr1212_csr *csr; - struct nodemgr_csr_info *ci; - u8 *speed; - - ci = kmalloc(sizeof(*ci), GFP_KERNEL); - kmemcheck_annotate_bitfield(ci, flags); - if (!ci) - return; - - ci->host = host; - ci->nodeid = nodeid; - ci->generation = generation; - - /* Prepare for speed probe which occurs when reading the ROM */ - speed = &(host->speed[NODEID_TO_NODE(nodeid)]); - if (*speed > host->csr.lnk_spd) - *speed = host->csr.lnk_spd; - ci->speed_unverified = *speed > IEEE1394_SPEED_100; - - /* We need to detect when the ConfigROM's generation has changed, - * so we only update the node's info when it needs to be. */ - - csr = csr1212_create_csr(&nodemgr_csr_ops, 5 * sizeof(quadlet_t), ci); - if (!csr || csr1212_parse_csr(csr) != CSR1212_SUCCESS) { - HPSB_ERR("Error parsing configrom for node " NODE_BUS_FMT, - NODE_BUS_ARGS(host, nodeid)); - if (csr) - csr1212_destroy_csr(csr); - kfree(ci); - return; - } - - if (csr->bus_info_data[1] != IEEE1394_BUSID_MAGIC) { - /* This isn't a 1394 device, but we let it slide. There - * was a report of a device with broken firmware which - * reported '2394' instead of '1394', which is obviously a - * mistake. One would hope that a non-1394 device never - * gets connected to Firewire bus. If someone does, we - * shouldn't be held responsible, so we'll allow it with a - * warning. */ - HPSB_WARN("Node " NODE_BUS_FMT " has invalid busID magic [0x%08x]", - NODE_BUS_ARGS(host, nodeid), csr->bus_info_data[1]); - } - - guid = ((u64)be32_to_cpu(csr->bus_info_data[3]) << 32) | be32_to_cpu(csr->bus_info_data[4]); - ne = find_entry_by_guid(guid); - - if (ne && ne->host != host && ne->in_limbo) { - /* Must have moved this device from one host to another */ - nodemgr_remove_ne(ne); - ne = NULL; - } - - if (!ne) - nodemgr_create_node(guid, csr, host, nodeid, generation); - else - nodemgr_update_node(ne, csr, nodeid, generation); -} - - -static void nodemgr_node_scan(struct hpsb_host *host, int generation) -{ - int count; - struct selfid *sid = (struct selfid *)host->topology_map; - nodeid_t nodeid = LOCAL_BUS; - - /* Scan each node on the bus */ - for (count = host->selfid_count; count; count--, sid++) { - if (sid->extended) - continue; - - if (!sid->link_active) { - nodeid++; - continue; - } - nodemgr_node_scan_one(host, nodeid++, generation); - } -} - -static void nodemgr_pause_ne(struct node_entry *ne) -{ - HPSB_DEBUG("Node paused: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", - NODE_BUS_ARGS(ne->host, ne->nodeid), - (unsigned long long)ne->guid); - - ne->in_limbo = true; - WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); -} - -static int update_pdrv(struct device *dev, void *data) -{ - struct unit_directory *ud; - struct device_driver *drv; - struct hpsb_protocol_driver *pdrv; - struct node_entry *ne = data; - int error; - - ud = container_of(dev, struct unit_directory, unit_dev); - if (ud->ne == ne) { - drv = get_driver(ud->device.driver); - if (drv) { - error = 0; - pdrv = container_of(drv, struct hpsb_protocol_driver, - driver); - if (pdrv->update) { - device_lock(&ud->device); - error = pdrv->update(ud); - device_unlock(&ud->device); - } - if (error) - device_release_driver(&ud->device); - put_driver(drv); - } - } - - return 0; -} - -static void nodemgr_update_pdrv(struct node_entry *ne) -{ - class_for_each_device(&nodemgr_ud_class, NULL, ne, update_pdrv); -} - -/* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3. This - * seems like an optional service but in the end it is practically mandatory - * as a consequence of these clauses. - * - * Note that we cannot do a broadcast write to all nodes at once because some - * pre-1394a devices would hang. */ -static void nodemgr_irm_write_bc(struct node_entry *ne, int generation) -{ - const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL); - quadlet_t bc_remote, bc_local; - int error; - - if (!ne->host->is_irm || ne->generation != generation || - ne->nodeid == ne->host->node_id) - return; - - bc_local = cpu_to_be32(ne->host->csr.broadcast_channel); - - /* Check if the register is implemented and 1394a compliant. */ - error = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote, - sizeof(bc_remote)); - if (!error && bc_remote & cpu_to_be32(0x80000000) && - bc_remote != bc_local) - hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local)); -} - - -static void nodemgr_probe_ne(struct hpsb_host *host, struct node_entry *ne, - int generation) -{ - struct device *dev; - - if (ne->host != host || ne->in_limbo) - return; - - dev = get_device(&ne->device); - if (!dev) - return; - - nodemgr_irm_write_bc(ne, generation); - - /* If "needs_probe", then this is either a new or changed node we - * rescan totally. If the generation matches for an existing node - * (one that existed prior to the bus reset) we send update calls - * down to the drivers. Otherwise, this is a dead node and we - * suspend it. */ - if (ne->needs_probe) - nodemgr_process_root_directory(ne); - else if (ne->generation == generation) - nodemgr_update_pdrv(ne); - else - nodemgr_pause_ne(ne); - - put_device(dev); -} - -struct node_probe_parameter { - struct hpsb_host *host; - int generation; - bool probe_now; -}; - -static int node_probe(struct device *dev, void *data) -{ - struct node_probe_parameter *p = data; - struct node_entry *ne; - - if (p->generation != get_hpsb_generation(p->host)) - return -EAGAIN; - - ne = container_of(dev, struct node_entry, node_dev); - if (ne->needs_probe == p->probe_now) - nodemgr_probe_ne(p->host, ne, p->generation); - return 0; -} - -static int nodemgr_node_probe(struct hpsb_host *host, int generation) -{ - struct node_probe_parameter p; - - p.host = host; - p.generation = generation; - /* - * Do some processing of the nodes we've probed. This pulls them - * into the sysfs layer if needed, and can result in processing of - * unit-directories, or just updating the node and it's - * unit-directories. - * - * Run updates before probes. Usually, updates are time-critical - * while probes are time-consuming. - * - * Meanwhile, another bus reset may have happened. In this case we - * skip everything here and let the next bus scan handle it. - * Otherwise we may prematurely remove nodes which are still there. - */ - p.probe_now = false; - if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) - return 0; - - p.probe_now = true; - if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) - return 0; - /* - * Now let's tell the bus to rescan our devices. This may seem - * like overhead, but the driver-model core will only scan a - * device for a driver when either the device is added, or when a - * new driver is added. A bus reset is a good reason to rescan - * devices that were there before. For example, an sbp2 device - * may become available for login, if the host that held it was - * just removed. - */ - if (bus_rescan_devices(&ieee1394_bus_type) != 0) - HPSB_DEBUG("bus_rescan_devices had an error"); - - return 1; -} - -static int remove_nodes_in_limbo(struct device *dev, void *data) -{ - struct node_entry *ne; - - if (dev->bus != &ieee1394_bus_type) - return 0; - - ne = container_of(dev, struct node_entry, device); - if (ne->in_limbo) - nodemgr_remove_ne(ne); - - return 0; -} - -static void nodemgr_remove_nodes_in_limbo(struct hpsb_host *host) -{ - device_for_each_child(&host->device, NULL, remove_nodes_in_limbo); -} - -static int nodemgr_send_resume_packet(struct hpsb_host *host) -{ - struct hpsb_packet *packet; - int error = -ENOMEM; - - packet = hpsb_make_phypacket(host, - EXTPHYPACKET_TYPE_RESUME | - NODEID_TO_NODE(host->node_id) << PHYPACKET_PORT_SHIFT); - if (packet) { - packet->no_waiter = 1; - packet->generation = get_hpsb_generation(host); - error = hpsb_send_packet(packet); - } - if (error) - HPSB_WARN("fw-host%d: Failed to broadcast resume packet", - host->id); - return error; -} - -/* Perform a few high-level IRM responsibilities. */ -static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles) -{ - quadlet_t bc; - - /* if irm_id == -1 then there is no IRM on this bus */ - if (!host->is_irm || host->irm_id == (nodeid_t)-1) - return 1; - - /* We are a 1394a-2000 compliant IRM. Set the validity bit. */ - host->csr.broadcast_channel |= 0x40000000; - - /* If there is no bus manager then we should set the root node's - * force_root bit to promote bus stability per the 1394 - * spec. (8.4.2.6) */ - if (host->busmgr_id == 0xffff && host->node_count > 1) - { - u16 root_node = host->node_count - 1; - - /* get cycle master capability flag from root node */ - if (host->is_cycmst || - (!hpsb_read(host, LOCAL_BUS | root_node, get_hpsb_generation(host), - (CSR_REGISTER_BASE + CSR_CONFIG_ROM + 2 * sizeof(quadlet_t)), - &bc, sizeof(quadlet_t)) && - be32_to_cpu(bc) & 1 << CSR_CMC_SHIFT)) - hpsb_send_phy_config(host, root_node, -1); - else { - HPSB_DEBUG("The root node is not cycle master capable; " - "selecting a new root node and resetting..."); - - if (cycles >= 5) { - /* Oh screw it! Just leave the bus as it is */ - HPSB_DEBUG("Stopping reset loop for IRM sanity"); - return 1; - } - - hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1); - hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); - - return 0; - } - } - - /* Some devices suspend their ports while being connected to an inactive - * host adapter, i.e. if connected before the low-level driver is - * loaded. They become visible either when physically unplugged and - * replugged, or when receiving a resume packet. Send one once. */ - if (!host->resume_packet_sent && !nodemgr_send_resume_packet(host)) - host->resume_packet_sent = 1; - - return 1; -} - -/* We need to ensure that if we are not the IRM, that the IRM node is capable of - * everything we can do, otherwise issue a bus reset and try to become the IRM - * ourselves. */ -static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles) -{ - quadlet_t bc; - int status; - - if (hpsb_disable_irm || host->is_irm) - return 1; - - status = hpsb_read(host, LOCAL_BUS | (host->irm_id), - get_hpsb_generation(host), - (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL), - &bc, sizeof(quadlet_t)); - - if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) { - /* The current irm node does not have a valid BROADCAST_CHANNEL - * register and we do, so reset the bus with force_root set */ - HPSB_DEBUG("Current remote IRM is not 1394a-2000 compliant, resetting..."); - - if (cycles >= 5) { - /* Oh screw it! Just leave the bus as it is */ - HPSB_DEBUG("Stopping reset loop for IRM sanity"); - return 1; - } - - hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1); - hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); - - return 0; - } - - return 1; -} - -static int nodemgr_host_thread(void *data) -{ - struct hpsb_host *host = data; - unsigned int g, generation = 0; - int i, reset_cycles = 0; - - set_freezable(); - /* Setup our device-model entries */ - nodemgr_create_host_dev_files(host); - - for (;;) { - /* Sleep until next bus reset */ - set_current_state(TASK_INTERRUPTIBLE); - if (get_hpsb_generation(host) == generation && - !kthread_should_stop()) - schedule(); - __set_current_state(TASK_RUNNING); - - /* Thread may have been woken up to freeze or to exit */ - if (try_to_freeze()) - continue; - if (kthread_should_stop()) - goto exit; - - /* Pause for 1/4 second in 1/16 second intervals, - * to make sure things settle down. */ - g = get_hpsb_generation(host); - for (i = 0; i < 4 ; i++) { - msleep_interruptible(63); - try_to_freeze(); - if (kthread_should_stop()) - goto exit; - - /* Now get the generation in which the node ID's we collect - * are valid. During the bus scan we will use this generation - * for the read transactions, so that if another reset occurs - * during the scan the transactions will fail instead of - * returning bogus data. */ - generation = get_hpsb_generation(host); - - /* If we get a reset before we are done waiting, then - * start the waiting over again */ - if (generation != g) - g = generation, i = 0; - } - - if (!nodemgr_check_irm_capability(host, reset_cycles) || - !nodemgr_do_irm_duties(host, reset_cycles)) { - reset_cycles++; - continue; - } - reset_cycles = 0; - - /* Scan our nodes to get the bus options and create node - * entries. This does not do the sysfs stuff, since that - * would trigger uevents and such, which is a bad idea at - * this point. */ - nodemgr_node_scan(host, generation); - - /* This actually does the full probe, with sysfs - * registration. */ - if (!nodemgr_node_probe(host, generation)) - continue; - - /* Update some of our sysfs symlinks */ - nodemgr_update_host_dev_links(host); - - /* Sleep 3 seconds */ - for (i = 3000/200; i; i--) { - msleep_interruptible(200); - try_to_freeze(); - if (kthread_should_stop()) - goto exit; - - if (generation != get_hpsb_generation(host)) - break; - } - /* Remove nodes which are gone, unless a bus reset happened */ - if (!i) - nodemgr_remove_nodes_in_limbo(host); - } -exit: - HPSB_VERBOSE("NodeMgr: Exiting thread"); - return 0; -} - -struct per_host_parameter { - void *data; - int (*cb)(struct hpsb_host *, void *); -}; - -static int per_host(struct device *dev, void *data) -{ - struct hpsb_host *host; - struct per_host_parameter *p = data; - - host = container_of(dev, struct hpsb_host, host_dev); - return p->cb(host, p->data); -} - -/** - * nodemgr_for_each_host - call a function for each IEEE 1394 host - * @data: an address to supply to the callback - * @cb: function to call for each host - * - * Iterate the hosts, calling a given function with supplied data for each host. - * If the callback fails on a host, i.e. if it returns a non-zero value, the - * iteration is stopped. - * - * Return value: 0 on success, non-zero on failure (same as returned by last run - * of the callback). - */ -int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)) -{ - struct per_host_parameter p; - - p.cb = cb; - p.data = data; - return class_for_each_device(&hpsb_host_class, NULL, &p, per_host); -} - -/* The following two convenience functions use a struct node_entry - * for addressing a node on the bus. They are intended for use by any - * process context, not just the nodemgr thread, so we need to be a - * little careful when reading out the node ID and generation. The - * thing that can go wrong is that we get the node ID, then a bus - * reset occurs, and then we read the generation. The node ID is - * possibly invalid, but the generation is current, and we end up - * sending a packet to a the wrong node. - * - * The solution is to make sure we read the generation first, so that - * if a reset occurs in the process, we end up with a stale generation - * and the transactions will fail instead of silently using wrong node - * ID's. - */ - -/** - * hpsb_node_fill_packet - fill some destination information into a packet - * @ne: destination node - * @packet: packet to fill in - * - * This will fill in the given, pre-initialised hpsb_packet with the current - * information from the node entry (host, node ID, bus generation number). - */ -void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet) -{ - packet->host = ne->host; - packet->generation = ne->generation; - smp_rmb(); - packet->node_id = ne->nodeid; -} - -int hpsb_node_write(struct node_entry *ne, u64 addr, - quadlet_t *buffer, size_t length) -{ - unsigned int generation = ne->generation; - - smp_rmb(); - return hpsb_write(ne->host, ne->nodeid, generation, - addr, buffer, length); -} - -static void nodemgr_add_host(struct hpsb_host *host) -{ - struct host_info *hi; - - hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi)); - if (!hi) { - HPSB_ERR("NodeMgr: out of memory in add host"); - return; - } - hi->host = host; - hi->thread = kthread_run(nodemgr_host_thread, host, "knodemgrd_%d", - host->id); - if (IS_ERR(hi->thread)) { - HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id); - hpsb_destroy_hostinfo(&nodemgr_highlevel, host); - } -} - -static void nodemgr_host_reset(struct hpsb_host *host) -{ - struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); - - if (hi) { - HPSB_VERBOSE("NodeMgr: Processing reset for host %d", host->id); - wake_up_process(hi->thread); - } -} - -static void nodemgr_remove_host(struct hpsb_host *host) -{ - struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host); - - if (hi) { - kthread_stop(hi->thread); - nodemgr_remove_host_dev(&host->device); - } -} - -static struct hpsb_highlevel nodemgr_highlevel = { - .name = "Node manager", - .add_host = nodemgr_add_host, - .host_reset = nodemgr_host_reset, - .remove_host = nodemgr_remove_host, -}; - -int init_ieee1394_nodemgr(void) -{ - int error; - - error = class_register(&nodemgr_ne_class); - if (error) - goto fail_ne; - error = class_register(&nodemgr_ud_class); - if (error) - goto fail_ud; - error = driver_register(&nodemgr_mid_layer_driver); - if (error) - goto fail_ml; - /* This driver is not used if nodemgr is off (disable_nodemgr=1). */ - nodemgr_dev_template_host.driver = &nodemgr_mid_layer_driver; - - hpsb_register_highlevel(&nodemgr_highlevel); - return 0; - -fail_ml: - class_unregister(&nodemgr_ud_class); -fail_ud: - class_unregister(&nodemgr_ne_class); -fail_ne: - return error; -} - -void cleanup_ieee1394_nodemgr(void) -{ - hpsb_unregister_highlevel(&nodemgr_highlevel); - driver_unregister(&nodemgr_mid_layer_driver); - class_unregister(&nodemgr_ud_class); - class_unregister(&nodemgr_ne_class); -} diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h deleted file mode 100644 index 749b271..0000000 --- a/drivers/ieee1394/nodemgr.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2000 Andreas E. Bombe - * 2001 Ben Collins <bcollins@debian.org> - * - * 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 _IEEE1394_NODEMGR_H -#define _IEEE1394_NODEMGR_H - -#include <linux/device.h> -#include <asm/system.h> -#include <asm/types.h> - -#include "ieee1394_core.h" -#include "ieee1394_transactions.h" -#include "ieee1394_types.h" - -struct csr1212_csr; -struct csr1212_keyval; -struct hpsb_host; -struct ieee1394_device_id; - -/* This is the start of a Node entry structure. It should be a stable API - * for which to gather info from the Node Manager about devices attached - * to the bus. */ -struct bus_options { - u8 irmc; /* Iso Resource Manager Capable */ - u8 cmc; /* Cycle Master Capable */ - u8 isc; /* Iso Capable */ - u8 bmc; /* Bus Master Capable */ - u8 pmc; /* Power Manager Capable (PNP spec) */ - u8 cyc_clk_acc; /* Cycle clock accuracy */ - u8 max_rom; /* Maximum block read supported in the CSR */ - u8 generation; /* Incremented when configrom changes */ - u8 lnkspd; /* Link speed */ - u16 max_rec; /* Maximum packet size node can receive */ -}; - -#define UNIT_DIRECTORY_VENDOR_ID 0x01 -#define UNIT_DIRECTORY_MODEL_ID 0x02 -#define UNIT_DIRECTORY_SPECIFIER_ID 0x04 -#define UNIT_DIRECTORY_VERSION 0x08 -#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY 0x10 -#define UNIT_DIRECTORY_LUN_DIRECTORY 0x20 -#define UNIT_DIRECTORY_HAS_LUN 0x40 - -/* - * A unit directory corresponds to a protocol supported by the - * node. If a node supports eg. IP/1394 and AV/C, its config rom has a - * unit directory for each of these protocols. - */ -struct unit_directory { - struct node_entry *ne; /* The node which this directory belongs to */ - octlet_t address; /* Address of the unit directory on the node */ - u8 flags; /* Indicates which entries were read */ - - quadlet_t vendor_id; - struct csr1212_keyval *vendor_name_kv; - - quadlet_t model_id; - struct csr1212_keyval *model_name_kv; - quadlet_t specifier_id; - quadlet_t version; - quadlet_t directory_id; - - unsigned int id; - - int ignore_driver; - - int length; /* Number of quadlets */ - - struct device device; - struct device unit_dev; - - struct csr1212_keyval *ud_kv; - u32 lun; /* logical unit number immediate value */ -}; - -struct node_entry { - u64 guid; /* GUID of this node */ - u32 guid_vendor_id; /* Top 24bits of guid */ - - struct hpsb_host *host; /* Host this node is attached to */ - nodeid_t nodeid; /* NodeID */ - struct bus_options busopt; /* Bus Options */ - bool needs_probe; - unsigned int generation; /* Synced with hpsb generation */ - - /* The following is read from the config rom */ - u32 vendor_id; - struct csr1212_keyval *vendor_name_kv; - - u32 capabilities; - - struct device device; - struct device node_dev; - - /* Means this node is not attached anymore */ - bool in_limbo; - - struct csr1212_csr *csr; -}; - -struct hpsb_protocol_driver { - /* The name of the driver, e.g. SBP2 or IP1394 */ - const char *name; - - /* - * The device id table describing the protocols and/or devices - * supported by this driver. This is used by the nodemgr to - * decide if a driver could support a given node, but the - * probe function below can implement further protocol - * dependent or vendor dependent checking. - */ - const struct ieee1394_device_id *id_table; - - /* - * The update function is called when the node has just - * survived a bus reset, i.e. it is still present on the bus. - * However, it may be necessary to reestablish the connection - * or login into the node again, depending on the protocol. If the - * probe fails (returns non-zero), we unbind the driver from this - * device. - */ - int (*update)(struct unit_directory *ud); - - /* Our LDM structure */ - struct device_driver driver; -}; - -int __hpsb_register_protocol(struct hpsb_protocol_driver *, struct module *); -static inline int hpsb_register_protocol(struct hpsb_protocol_driver *driver) -{ - return __hpsb_register_protocol(driver, THIS_MODULE); -} - -void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver); - -static inline int hpsb_node_entry_valid(struct node_entry *ne) -{ - return ne->generation == get_hpsb_generation(ne->host); -} -void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet); -int hpsb_node_write(struct node_entry *ne, u64 addr, - quadlet_t *buffer, size_t length); -static inline int hpsb_node_read(struct node_entry *ne, u64 addr, - quadlet_t *buffer, size_t length) -{ - unsigned int g = ne->generation; - - smp_rmb(); - return hpsb_read(ne->host, ne->nodeid, g, addr, buffer, length); -} -static inline int hpsb_node_lock(struct node_entry *ne, u64 addr, int extcode, - quadlet_t *buffer, quadlet_t arg) -{ - unsigned int g = ne->generation; - - smp_rmb(); - return hpsb_lock(ne->host, ne->nodeid, g, addr, extcode, buffer, arg); -} -int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)); - -int init_ieee1394_nodemgr(void); -void cleanup_ieee1394_nodemgr(void); - -/* The template for a host device */ -extern struct device nodemgr_dev_template_host; - -/* Bus attributes we export */ -extern struct bus_attribute *const fw_bus_attrs[]; - -#endif /* _IEEE1394_NODEMGR_H */ diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c deleted file mode 100644 index 5081502..0000000 --- a/drivers/ieee1394/ohci1394.c +++ /dev/null @@ -1,3590 +0,0 @@ -/* - * ohci1394.c - driver for OHCI 1394 boards - * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au> - * Gord Peters <GordPeters@smarttech.com> - * 2001 Ben Collins <bcollins@debian.org> - * - * 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. - */ - -/* - * Things known to be working: - * . Async Request Transmit - * . Async Response Receive - * . Async Request Receive - * . Async Response Transmit - * . Iso Receive - * . DMA mmap for iso receive - * . Config ROM generation - * - * Things implemented, but still in test phase: - * . Iso Transmit - * . Async Stream Packets Transmit (Receive done via Iso interface) - * - * Things not implemented: - * . DMA error recovery - * - * Known bugs: - * . devctl BUS_RESET arg confusion (reset type or root holdoff?) - * added LONG_RESET_ROOT and SHORT_RESET_ROOT for root holdoff --kk - */ - -/* - * Acknowledgments: - * - * Adam J Richter <adam@yggdrasil.com> - * . Use of pci_class to find device - * - * Emilie Chung <emilie.chung@axis.com> - * . Tip on Async Request Filter - * - * Pascal Drolet <pascal.drolet@informission.ca> - * . Various tips for optimization and functionnalities - * - * Robert Ficklin <rficklin@westengineering.com> - * . Loop in irq_handler - * - * James Goodwin <jamesg@Filanet.com> - * . Various tips on initialization, self-id reception, etc. - * - * Albrecht Dress <ad@mpifr-bonn.mpg.de> - * . Apple PowerBook detection - * - * Daniel Kobras <daniel.kobras@student.uni-tuebingen.de> - * . Reset the board properly before leaving + misc cleanups - * - * Leon van Stuivenberg <leonvs@iae.nl> - * . Bug fixes - * - * Ben Collins <bcollins@debian.org> - * . Working big-endian support - * . Updated to 2.4.x module scheme (PCI aswell) - * . Config ROM generation - * - * Manfred Weihs <weihs@ict.tuwien.ac.at> - * . Reworked code for initiating bus resets - * (long, short, with or without hold-off) - * - * Nandu Santhi <contactnandu@users.sourceforge.net> - * . Added support for nVidia nForce2 onboard Firewire chipset - * - */ - -#include <linux/bitops.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/pci.h> -#include <linux/fs.h> -#include <linux/poll.h> -#include <asm/byteorder.h> -#include <asm/atomic.h> -#include <asm/uaccess.h> -#include <linux/delay.h> -#include <linux/spinlock.h> - -#include <asm/pgtable.h> -#include <asm/page.h> -#include <asm/irq.h> -#include <linux/types.h> -#include <linux/vmalloc.h> -#include <linux/init.h> - -#ifdef CONFIG_PPC_PMAC -#include <asm/machdep.h> -#include <asm/pmac_feature.h> -#include <asm/prom.h> -#include <asm/pci-bridge.h> -#endif - -#include "csr1212.h" -#include "ieee1394.h" -#include "ieee1394_types.h" -#include "hosts.h" -#include "dma.h" -#include "iso.h" -#include "ieee1394_core.h" -#include "highlevel.h" -#include "ohci1394.h" - -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG -#define OHCI1394_DEBUG -#endif - -#ifdef DBGMSG -#undef DBGMSG -#endif - -#ifdef OHCI1394_DEBUG -#define DBGMSG(fmt, args...) \ -printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args) -#else -#define DBGMSG(fmt, args...) do {} while (0) -#endif - -/* print general (card independent) information */ -#define PRINT_G(level, fmt, args...) \ -printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args) - -/* print card specific information */ -#define PRINT(level, fmt, args...) \ -printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args) - -/* Module Parameters */ -static int phys_dma = 1; -module_param(phys_dma, int, 0444); -MODULE_PARM_DESC(phys_dma, "Enable physical DMA (default = 1)."); - -static void dma_trm_tasklet(unsigned long data); -static void dma_trm_reset(struct dma_trm_ctx *d); - -static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, - enum context_type type, int ctx, int num_desc, - int buf_size, int split_buf_size, int context_base); -static void free_dma_rcv_ctx(struct dma_rcv_ctx *d); - -static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, - enum context_type type, int ctx, int num_desc, - int context_base); - -static void ohci1394_pci_remove(struct pci_dev *pdev); - -#ifndef __LITTLE_ENDIAN -static const size_t hdr_sizes[] = { - 3, /* TCODE_WRITEQ */ - 4, /* TCODE_WRITEB */ - 3, /* TCODE_WRITE_RESPONSE */ - 0, /* reserved */ - 3, /* TCODE_READQ */ - 4, /* TCODE_READB */ - 3, /* TCODE_READQ_RESPONSE */ - 4, /* TCODE_READB_RESPONSE */ - 1, /* TCODE_CYCLE_START */ - 4, /* TCODE_LOCK_REQUEST */ - 2, /* TCODE_ISO_DATA */ - 4, /* TCODE_LOCK_RESPONSE */ - /* rest is reserved or link-internal */ -}; - -static inline void header_le32_to_cpu(quadlet_t *data, unsigned char tcode) -{ - size_t size; - - if (unlikely(tcode >= ARRAY_SIZE(hdr_sizes))) - return; - - size = hdr_sizes[tcode]; - while (size--) - data[size] = le32_to_cpu(data[size]); -} -#else -#define header_le32_to_cpu(w,x) do {} while (0) -#endif /* !LITTLE_ENDIAN */ - -/*********************************** - * IEEE-1394 functionality section * - ***********************************/ - -static u8 get_phy_reg(struct ti_ohci *ohci, u8 addr) -{ - int i; - unsigned long flags; - quadlet_t r; - - spin_lock_irqsave (&ohci->phy_reg_lock, flags); - - reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000); - - for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000) - break; - - mdelay(1); - } - - r = reg_read(ohci, OHCI1394_PhyControl); - - if (i >= OHCI_LOOP_COUNT) - PRINT (KERN_ERR, "Get PHY Reg timeout [0x%08x/0x%08x/%d]", - r, r & 0x80000000, i); - - spin_unlock_irqrestore (&ohci->phy_reg_lock, flags); - - return (r & 0x00ff0000) >> 16; -} - -static void set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data) -{ - int i; - unsigned long flags; - u32 r = 0; - - spin_lock_irqsave (&ohci->phy_reg_lock, flags); - - reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000); - - for (i = 0; i < OHCI_LOOP_COUNT; i++) { - r = reg_read(ohci, OHCI1394_PhyControl); - if (!(r & 0x00004000)) - break; - - mdelay(1); - } - - if (i == OHCI_LOOP_COUNT) - PRINT (KERN_ERR, "Set PHY Reg timeout [0x%08x/0x%08x/%d]", - r, r & 0x00004000, i); - - spin_unlock_irqrestore (&ohci->phy_reg_lock, flags); - - return; -} - -/* Or's our value into the current value */ -static void set_phy_reg_mask(struct ti_ohci *ohci, u8 addr, u8 data) -{ - u8 old; - - old = get_phy_reg (ohci, addr); - old |= data; - set_phy_reg (ohci, addr, old); - - return; -} - -static void handle_selfid(struct ti_ohci *ohci, struct hpsb_host *host, - int phyid, int isroot) -{ - quadlet_t *q = ohci->selfid_buf_cpu; - quadlet_t self_id_count=reg_read(ohci, OHCI1394_SelfIDCount); - size_t size; - quadlet_t q0, q1; - - /* Check status of self-id reception */ - - if (ohci->selfid_swap) - q0 = le32_to_cpu(q[0]); - else - q0 = q[0]; - - if ((self_id_count & 0x80000000) || - ((self_id_count & 0x00FF0000) != (q0 & 0x00FF0000))) { - PRINT(KERN_ERR, - "Error in reception of SelfID packets [0x%08x/0x%08x] (count: %d)", - self_id_count, q0, ohci->self_id_errors); - - /* Tip by James Goodwin <jamesg@Filanet.com>: - * We had an error, generate another bus reset in response. */ - if (ohci->self_id_errors<OHCI1394_MAX_SELF_ID_ERRORS) { - set_phy_reg_mask (ohci, 1, 0x40); - ohci->self_id_errors++; - } else { - PRINT(KERN_ERR, - "Too many errors on SelfID error reception, giving up!"); - } - return; - } - - /* SelfID Ok, reset error counter. */ - ohci->self_id_errors = 0; - - size = ((self_id_count & 0x00001FFC) >> 2) - 1; - q++; - - while (size > 0) { - if (ohci->selfid_swap) { - q0 = le32_to_cpu(q[0]); - q1 = le32_to_cpu(q[1]); - } else { - q0 = q[0]; - q1 = q[1]; - } - - if (q0 == ~q1) { - DBGMSG ("SelfID packet 0x%x received", q0); - hpsb_selfid_received(host, cpu_to_be32(q0)); - if (((q0 & 0x3f000000) >> 24) == phyid) - DBGMSG ("SelfID for this node is 0x%08x", q0); - } else { - PRINT(KERN_ERR, - "SelfID is inconsistent [0x%08x/0x%08x]", q0, q1); - } - q += 2; - size -= 2; - } - - DBGMSG("SelfID complete"); - - return; -} - -static void ohci_soft_reset(struct ti_ohci *ohci) { - int i; - - reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset); - - for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if (!(reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_softReset)) - break; - mdelay(1); - } - DBGMSG ("Soft reset finished"); -} - - -/* Generate the dma receive prgs and start the context */ -static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d, int generate_irq) -{ - struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); - int i; - - ohci1394_stop_context(ohci, d->ctrlClear, NULL); - - for (i=0; i<d->num_desc; i++) { - u32 c; - - c = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_BRANCH; - if (generate_irq) - c |= DMA_CTL_IRQ; - - d->prg_cpu[i]->control = cpu_to_le32(c | d->buf_size); - - /* End of descriptor list? */ - if (i + 1 < d->num_desc) { - d->prg_cpu[i]->branchAddress = - cpu_to_le32((d->prg_bus[i+1] & 0xfffffff0) | 0x1); - } else { - d->prg_cpu[i]->branchAddress = - cpu_to_le32((d->prg_bus[0] & 0xfffffff0)); - } - - d->prg_cpu[i]->address = cpu_to_le32(d->buf_bus[i]); - d->prg_cpu[i]->status = cpu_to_le32(d->buf_size); - } - - d->buf_ind = 0; - d->buf_offset = 0; - - if (d->type == DMA_CTX_ISO) { - /* Clear contextControl */ - reg_write(ohci, d->ctrlClear, 0xffffffff); - - /* Set bufferFill, isochHeader, multichannel for IR context */ - reg_write(ohci, d->ctrlSet, 0xd0000000); - - /* Set the context match register to match on all tags */ - reg_write(ohci, d->ctxtMatch, 0xf0000000); - - /* Clear the multi channel mask high and low registers */ - reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff); - reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff); - - /* Set up isoRecvIntMask to generate interrupts */ - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << d->ctx); - } - - /* Tell the controller where the first AR program is */ - reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1); - - /* Run context */ - reg_write(ohci, d->ctrlSet, 0x00008000); - - DBGMSG("Receive DMA ctx=%d initialized", d->ctx); -} - -/* Initialize the dma transmit context */ -static void initialize_dma_trm_ctx(struct dma_trm_ctx *d) -{ - struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); - - /* Stop the context */ - ohci1394_stop_context(ohci, d->ctrlClear, NULL); - - d->prg_ind = 0; - d->sent_ind = 0; - d->free_prgs = d->num_desc; - d->branchAddrPtr = NULL; - INIT_LIST_HEAD(&d->fifo_list); - INIT_LIST_HEAD(&d->pending_list); - - if (d->type == DMA_CTX_ISO) { - /* enable interrupts */ - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx); - } - - DBGMSG("Transmit DMA ctx=%d initialized", d->ctx); -} - -/* Count the number of available iso contexts */ -static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg) -{ - u32 tmp; - - reg_write(ohci, reg, 0xffffffff); - tmp = reg_read(ohci, reg); - - DBGMSG("Iso contexts reg: %08x implemented: %08x", reg, tmp); - - /* Count the number of contexts */ - return hweight32(tmp); -} - -/* Global initialization */ -static void ohci_initialize(struct ti_ohci *ohci) -{ - quadlet_t buf; - int num_ports, i; - - spin_lock_init(&ohci->phy_reg_lock); - - /* Put some defaults to these undefined bus options */ - buf = reg_read(ohci, OHCI1394_BusOptions); - buf |= 0x60000000; /* Enable CMC and ISC */ - if (hpsb_disable_irm) - buf &= ~0x80000000; - else - buf |= 0x80000000; /* Enable IRMC */ - buf &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */ - buf &= ~0x18000000; /* Disable PMC and BMC */ - reg_write(ohci, OHCI1394_BusOptions, buf); - - /* Set the bus number */ - reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0); - - /* Enable posted writes */ - reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable); - - /* Clear link control register */ - reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); - - /* Enable cycle timer and cycle master and set the IRM - * contender bit in our self ID packets if appropriate. */ - reg_write(ohci, OHCI1394_LinkControlSet, - OHCI1394_LinkControl_CycleTimerEnable | - OHCI1394_LinkControl_CycleMaster); - i = get_phy_reg(ohci, 4) | PHY_04_LCTRL; - if (hpsb_disable_irm) - i &= ~PHY_04_CONTENDER; - else - i |= PHY_04_CONTENDER; - set_phy_reg(ohci, 4, i); - - /* Set up self-id dma buffer */ - reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus); - - /* enable self-id */ - reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_RcvSelfID); - - /* Set the Config ROM mapping register */ - reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus); - - /* Now get our max packet size */ - ohci->max_packet_size = - 1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1); - - /* Clear the interrupt mask */ - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); - - /* Clear the interrupt mask */ - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); - - /* Initialize AR dma */ - initialize_dma_rcv_ctx(&ohci->ar_req_context, 0); - initialize_dma_rcv_ctx(&ohci->ar_resp_context, 0); - - /* Initialize AT dma */ - initialize_dma_trm_ctx(&ohci->at_req_context); - initialize_dma_trm_ctx(&ohci->at_resp_context); - - /* Accept AR requests from all nodes */ - reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000); - - /* Set the address range of the physical response unit. - * Most controllers do not implement it as a writable register though. - * They will keep a hardwired offset of 0x00010000 and show 0x0 as - * register content. - * To actually enable physical responses is the job of our interrupt - * handler which programs the physical request filter. */ - reg_write(ohci, OHCI1394_PhyUpperBound, - OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED >> 16); - - DBGMSG("physUpperBoundOffset=%08x", - reg_read(ohci, OHCI1394_PhyUpperBound)); - - /* Specify AT retries */ - reg_write(ohci, OHCI1394_ATRetries, - OHCI1394_MAX_AT_REQ_RETRIES | - (OHCI1394_MAX_AT_RESP_RETRIES<<4) | - (OHCI1394_MAX_PHYS_RESP_RETRIES<<8)); - - /* We don't want hardware swapping */ - reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap); - - /* Enable interrupts */ - reg_write(ohci, OHCI1394_IntMaskSet, - OHCI1394_unrecoverableError | - OHCI1394_masterIntEnable | - OHCI1394_busReset | - OHCI1394_selfIDComplete | - OHCI1394_RSPkt | - OHCI1394_RQPkt | - OHCI1394_respTxComplete | - OHCI1394_reqTxComplete | - OHCI1394_isochRx | - OHCI1394_isochTx | - OHCI1394_postedWriteErr | - OHCI1394_cycleTooLong | - OHCI1394_cycleInconsistent); - - /* Enable link */ - reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable); - - buf = reg_read(ohci, OHCI1394_Version); - PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d] " - "MMIO=[%llx-%llx] Max Packet=[%d] IR/IT contexts=[%d/%d]", - ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10), - ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq, - (unsigned long long)pci_resource_start(ohci->dev, 0), - (unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1, - ohci->max_packet_size, - ohci->nb_iso_rcv_ctx, ohci->nb_iso_xmit_ctx); - - /* Check all of our ports to make sure that if anything is - * connected, we enable that port. */ - num_ports = get_phy_reg(ohci, 2) & 0xf; - for (i = 0; i < num_ports; i++) { - unsigned int status; - - set_phy_reg(ohci, 7, i); - status = get_phy_reg(ohci, 8); - - if (status & 0x20) - set_phy_reg(ohci, 8, status & ~1); - } - - /* Serial EEPROM Sanity check. */ - if ((ohci->max_packet_size < 512) || - (ohci->max_packet_size > 4096)) { - /* Serial EEPROM contents are suspect, set a sane max packet - * size and print the raw contents for bug reports if verbose - * debug is enabled. */ -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - int i; -#endif - - PRINT(KERN_DEBUG, "Serial EEPROM has suspicious values, " - "attempting to set max_packet_size to 512 bytes"); - reg_write(ohci, OHCI1394_BusOptions, - (reg_read(ohci, OHCI1394_BusOptions) & 0xf007) | 0x8002); - ohci->max_packet_size = 512; -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG - PRINT(KERN_DEBUG, " EEPROM Present: %d", - (reg_read(ohci, OHCI1394_Version) >> 24) & 0x1); - reg_write(ohci, OHCI1394_GUID_ROM, 0x80000000); - - for (i = 0; - ((i < 1000) && - (reg_read(ohci, OHCI1394_GUID_ROM) & 0x80000000)); i++) - udelay(10); - - for (i = 0; i < 0x20; i++) { - reg_write(ohci, OHCI1394_GUID_ROM, 0x02000000); - PRINT(KERN_DEBUG, " EEPROM %02x: %02x", i, - (reg_read(ohci, OHCI1394_GUID_ROM) >> 16) & 0xff); - } -#endif - } -} - -/* - * Insert a packet in the DMA fifo and generate the DMA prg - * FIXME: rewrite the program in order to accept packets crossing - * page boundaries. - * check also that a single dma descriptor doesn't cross a - * page boundary. - */ -static void insert_packet(struct ti_ohci *ohci, - struct dma_trm_ctx *d, struct hpsb_packet *packet) -{ - u32 cycleTimer; - int idx = d->prg_ind; - - DBGMSG("Inserting packet for node " NODE_BUS_FMT - ", tlabel=%d, tcode=0x%x, speed=%d", - NODE_BUS_ARGS(ohci->host, packet->node_id), packet->tlabel, - packet->tcode, packet->speed_code); - - d->prg_cpu[idx]->begin.address = 0; - d->prg_cpu[idx]->begin.branchAddress = 0; - - if (d->type == DMA_CTX_ASYNC_RESP) { - /* - * For response packets, we need to put a timeout value in - * the 16 lower bits of the status... let's try 1 sec timeout - */ - cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - d->prg_cpu[idx]->begin.status = cpu_to_le32( - (((((cycleTimer>>25)&0x7)+1)&0x7)<<13) | - ((cycleTimer&0x01fff000)>>12)); - - DBGMSG("cycleTimer: %08x timeStamp: %08x", - cycleTimer, d->prg_cpu[idx]->begin.status); - } else - d->prg_cpu[idx]->begin.status = 0; - - if ( (packet->type == hpsb_async) || (packet->type == hpsb_raw) ) { - - if (packet->type == hpsb_raw) { - d->prg_cpu[idx]->data[0] = cpu_to_le32(OHCI1394_TCODE_PHY<<4); - d->prg_cpu[idx]->data[1] = cpu_to_le32(packet->header[0]); - d->prg_cpu[idx]->data[2] = cpu_to_le32(packet->header[1]); - } else { - d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | - (packet->header[0] & 0xFFFF); - - if (packet->tcode == TCODE_ISO_DATA) { - /* Sending an async stream packet */ - d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000; - } else { - /* Sending a normal async request or response */ - d->prg_cpu[idx]->data[1] = - (packet->header[1] & 0xFFFF) | - (packet->header[0] & 0xFFFF0000); - d->prg_cpu[idx]->data[2] = packet->header[2]; - d->prg_cpu[idx]->data[3] = packet->header[3]; - } - header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode); - } - - if (packet->data_size) { /* block transmit */ - if (packet->tcode == TCODE_STREAM_DATA){ - d->prg_cpu[idx]->begin.control = - cpu_to_le32(DMA_CTL_OUTPUT_MORE | - DMA_CTL_IMMEDIATE | 0x8); - } else { - d->prg_cpu[idx]->begin.control = - cpu_to_le32(DMA_CTL_OUTPUT_MORE | - DMA_CTL_IMMEDIATE | 0x10); - } - d->prg_cpu[idx]->end.control = - cpu_to_le32(DMA_CTL_OUTPUT_LAST | - DMA_CTL_IRQ | - DMA_CTL_BRANCH | - packet->data_size); - /* - * Check that the packet data buffer - * does not cross a page boundary. - * - * XXX Fix this some day. eth1394 seems to trigger - * it, but ignoring it doesn't seem to cause a - * problem. - */ -#if 0 - if (cross_bound((unsigned long)packet->data, - packet->data_size)>0) { - /* FIXME: do something about it */ - PRINT(KERN_ERR, - "%s: packet data addr: %p size %Zd bytes " - "cross page boundary", __func__, - packet->data, packet->data_size); - } -#endif - d->prg_cpu[idx]->end.address = cpu_to_le32( - pci_map_single(ohci->dev, packet->data, - packet->data_size, - PCI_DMA_TODEVICE)); - - d->prg_cpu[idx]->end.branchAddress = 0; - d->prg_cpu[idx]->end.status = 0; - if (d->branchAddrPtr) - *(d->branchAddrPtr) = - cpu_to_le32(d->prg_bus[idx] | 0x3); - d->branchAddrPtr = - &(d->prg_cpu[idx]->end.branchAddress); - } else { /* quadlet transmit */ - if (packet->type == hpsb_raw) - d->prg_cpu[idx]->begin.control = - cpu_to_le32(DMA_CTL_OUTPUT_LAST | - DMA_CTL_IMMEDIATE | - DMA_CTL_IRQ | - DMA_CTL_BRANCH | - (packet->header_size + 4)); - else - d->prg_cpu[idx]->begin.control = - cpu_to_le32(DMA_CTL_OUTPUT_LAST | - DMA_CTL_IMMEDIATE | - DMA_CTL_IRQ | - DMA_CTL_BRANCH | - packet->header_size); - - if (d->branchAddrPtr) - *(d->branchAddrPtr) = - cpu_to_le32(d->prg_bus[idx] | 0x2); - d->branchAddrPtr = - &(d->prg_cpu[idx]->begin.branchAddress); - } - - } else { /* iso packet */ - d->prg_cpu[idx]->data[0] = packet->speed_code<<16 | - (packet->header[0] & 0xFFFF); - d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000; - header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode); - - d->prg_cpu[idx]->begin.control = - cpu_to_le32(DMA_CTL_OUTPUT_MORE | - DMA_CTL_IMMEDIATE | 0x8); - d->prg_cpu[idx]->end.control = - cpu_to_le32(DMA_CTL_OUTPUT_LAST | - DMA_CTL_UPDATE | - DMA_CTL_IRQ | - DMA_CTL_BRANCH | - packet->data_size); - d->prg_cpu[idx]->end.address = cpu_to_le32( - pci_map_single(ohci->dev, packet->data, - packet->data_size, PCI_DMA_TODEVICE)); - - d->prg_cpu[idx]->end.branchAddress = 0; - d->prg_cpu[idx]->end.status = 0; - DBGMSG("Iso xmit context info: header[%08x %08x]\n" - " begin=%08x %08x %08x %08x\n" - " %08x %08x %08x %08x\n" - " end =%08x %08x %08x %08x", - d->prg_cpu[idx]->data[0], d->prg_cpu[idx]->data[1], - d->prg_cpu[idx]->begin.control, - d->prg_cpu[idx]->begin.address, - d->prg_cpu[idx]->begin.branchAddress, - d->prg_cpu[idx]->begin.status, - d->prg_cpu[idx]->data[0], - d->prg_cpu[idx]->data[1], - d->prg_cpu[idx]->data[2], - d->prg_cpu[idx]->data[3], - d->prg_cpu[idx]->end.control, - d->prg_cpu[idx]->end.address, - d->prg_cpu[idx]->end.branchAddress, - d->prg_cpu[idx]->end.status); - if (d->branchAddrPtr) - *(d->branchAddrPtr) = cpu_to_le32(d->prg_bus[idx] | 0x3); - d->branchAddrPtr = &(d->prg_cpu[idx]->end.branchAddress); - } - d->free_prgs--; - - /* queue the packet in the appropriate context queue */ - list_add_tail(&packet->driver_list, &d->fifo_list); - d->prg_ind = (d->prg_ind + 1) % d->num_desc; -} - -/* - * This function fills the FIFO with the (eventual) pending packets - * and runs or wakes up the DMA prg if necessary. - * - * The function MUST be called with the d->lock held. - */ -static void dma_trm_flush(struct ti_ohci *ohci, struct dma_trm_ctx *d) -{ - struct hpsb_packet *packet, *ptmp; - int idx = d->prg_ind; - int z = 0; - - /* insert the packets into the dma fifo */ - list_for_each_entry_safe(packet, ptmp, &d->pending_list, driver_list) { - if (!d->free_prgs) - break; - - /* For the first packet only */ - if (!z) - z = (packet->data_size) ? 3 : 2; - - /* Insert the packet */ - list_del_init(&packet->driver_list); - insert_packet(ohci, d, packet); - } - - /* Nothing must have been done, either no free_prgs or no packets */ - if (z == 0) - return; - - /* Is the context running ? (should be unless it is - the first packet to be sent in this context) */ - if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) { - u32 nodeId = reg_read(ohci, OHCI1394_NodeID); - - DBGMSG("Starting transmit DMA ctx=%d",d->ctx); - reg_write(ohci, d->cmdPtr, d->prg_bus[idx] | z); - - /* Check that the node id is valid, and not 63 */ - if (!(nodeId & 0x80000000) || (nodeId & 0x3f) == 63) - PRINT(KERN_ERR, "Running dma failed because Node ID is not valid"); - else - reg_write(ohci, d->ctrlSet, 0x8000); - } else { - /* Wake up the dma context if necessary */ - if (!(reg_read(ohci, d->ctrlSet) & 0x400)) - DBGMSG("Waking transmit DMA ctx=%d",d->ctx); - - /* do this always, to avoid race condition */ - reg_write(ohci, d->ctrlSet, 0x1000); - } - - return; -} - -/* Transmission of an async or iso packet */ -static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet) -{ - struct ti_ohci *ohci = host->hostdata; - struct dma_trm_ctx *d; - unsigned long flags; - - if (packet->data_size > ohci->max_packet_size) { - PRINT(KERN_ERR, - "Transmit packet size %Zd is too big", - packet->data_size); - return -EOVERFLOW; - } - - if (packet->type == hpsb_raw) - d = &ohci->at_req_context; - else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA)) - d = &ohci->at_resp_context; - else - d = &ohci->at_req_context; - - spin_lock_irqsave(&d->lock,flags); - - list_add_tail(&packet->driver_list, &d->pending_list); - - dma_trm_flush(ohci, d); - - spin_unlock_irqrestore(&d->lock,flags); - - return 0; -} - -static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) -{ - struct ti_ohci *ohci = host->hostdata; - int retval = 0, phy_reg; - - switch (cmd) { - case RESET_BUS: - switch (arg) { - case SHORT_RESET: - phy_reg = get_phy_reg(ohci, 5); - phy_reg |= 0x40; - set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ - break; - case LONG_RESET: - phy_reg = get_phy_reg(ohci, 1); - phy_reg |= 0x40; - set_phy_reg(ohci, 1, phy_reg); /* set IBR */ - break; - case SHORT_RESET_NO_FORCE_ROOT: - phy_reg = get_phy_reg(ohci, 1); - if (phy_reg & 0x80) { - phy_reg &= ~0x80; - set_phy_reg(ohci, 1, phy_reg); /* clear RHB */ - } - - phy_reg = get_phy_reg(ohci, 5); - phy_reg |= 0x40; - set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ - break; - case LONG_RESET_NO_FORCE_ROOT: - phy_reg = get_phy_reg(ohci, 1); - phy_reg &= ~0x80; - phy_reg |= 0x40; - set_phy_reg(ohci, 1, phy_reg); /* clear RHB, set IBR */ - break; - case SHORT_RESET_FORCE_ROOT: - phy_reg = get_phy_reg(ohci, 1); - if (!(phy_reg & 0x80)) { - phy_reg |= 0x80; - set_phy_reg(ohci, 1, phy_reg); /* set RHB */ - } - - phy_reg = get_phy_reg(ohci, 5); - phy_reg |= 0x40; - set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ - break; - case LONG_RESET_FORCE_ROOT: - phy_reg = get_phy_reg(ohci, 1); - phy_reg |= 0xc0; - set_phy_reg(ohci, 1, phy_reg); /* set RHB and IBR */ - break; - default: - retval = -1; - } - break; - - case GET_CYCLE_COUNTER: - retval = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - break; - - case SET_CYCLE_COUNTER: - reg_write(ohci, OHCI1394_IsochronousCycleTimer, arg); - break; - - case SET_BUS_ID: - PRINT(KERN_ERR, "devctl command SET_BUS_ID err"); - break; - - case ACT_CYCLE_MASTER: - if (arg) { - /* check if we are root and other nodes are present */ - u32 nodeId = reg_read(ohci, OHCI1394_NodeID); - if ((nodeId & (1<<30)) && (nodeId & 0x3f)) { - /* - * enable cycleTimer, cycleMaster - */ - DBGMSG("Cycle master enabled"); - reg_write(ohci, OHCI1394_LinkControlSet, - OHCI1394_LinkControl_CycleTimerEnable | - OHCI1394_LinkControl_CycleMaster); - } - } else { - /* disable cycleTimer, cycleMaster, cycleSource */ - reg_write(ohci, OHCI1394_LinkControlClear, - OHCI1394_LinkControl_CycleTimerEnable | - OHCI1394_LinkControl_CycleMaster | - OHCI1394_LinkControl_CycleSource); - } - break; - - case CANCEL_REQUESTS: - DBGMSG("Cancel request received"); - dma_trm_reset(&ohci->at_req_context); - dma_trm_reset(&ohci->at_resp_context); - break; - - default: - PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet", - cmd); - break; - } - return retval; -} - -/*********************************** - * rawiso ISO reception * - ***********************************/ - -/* - We use either buffer-fill or packet-per-buffer DMA mode. The DMA - buffer is split into "blocks" (regions described by one DMA - descriptor). Each block must be one page or less in size, and - must not cross a page boundary. - - There is one little wrinkle with buffer-fill mode: a packet that - starts in the final block may wrap around into the first block. But - the user API expects all packets to be contiguous. Our solution is - to keep the very last page of the DMA buffer in reserve - if a - packet spans the gap, we copy its tail into this page. -*/ - -struct ohci_iso_recv { - struct ti_ohci *ohci; - - struct ohci1394_iso_tasklet task; - int task_active; - - enum { BUFFER_FILL_MODE = 0, - PACKET_PER_BUFFER_MODE = 1 } dma_mode; - - /* memory and PCI mapping for the DMA descriptors */ - struct dma_prog_region prog; - struct dma_cmd *block; /* = (struct dma_cmd*) prog.virt */ - - /* how many DMA blocks fit in the buffer */ - unsigned int nblocks; - - /* stride of DMA blocks */ - unsigned int buf_stride; - - /* number of blocks to batch between interrupts */ - int block_irq_interval; - - /* block that DMA will finish next */ - int block_dma; - - /* (buffer-fill only) block that the reader will release next */ - int block_reader; - - /* (buffer-fill only) bytes of buffer the reader has released, - less than one block */ - int released_bytes; - - /* (buffer-fill only) buffer offset at which the next packet will appear */ - int dma_offset; - - /* OHCI DMA context control registers */ - u32 ContextControlSet; - u32 ContextControlClear; - u32 CommandPtr; - u32 ContextMatch; -}; - -static void ohci_iso_recv_task(unsigned long data); -static void ohci_iso_recv_stop(struct hpsb_iso *iso); -static void ohci_iso_recv_shutdown(struct hpsb_iso *iso); -static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync); -static void ohci_iso_recv_program(struct hpsb_iso *iso); - -static int ohci_iso_recv_init(struct hpsb_iso *iso) -{ - struct ti_ohci *ohci = iso->host->hostdata; - struct ohci_iso_recv *recv; - int ctx; - int ret = -ENOMEM; - - recv = kmalloc(sizeof(*recv), GFP_KERNEL); - if (!recv) - return -ENOMEM; - - iso->hostdata = recv; - recv->ohci = ohci; - recv->task_active = 0; - dma_prog_region_init(&recv->prog); - recv->block = NULL; - - /* use buffer-fill mode, unless irq_interval is 1 - (note: multichannel requires buffer-fill) */ - - if (((iso->irq_interval == 1 && iso->dma_mode == HPSB_ISO_DMA_OLD_ABI) || - iso->dma_mode == HPSB_ISO_DMA_PACKET_PER_BUFFER) && iso->channel != -1) { - recv->dma_mode = PACKET_PER_BUFFER_MODE; - } else { - recv->dma_mode = BUFFER_FILL_MODE; - } - - /* set nblocks, buf_stride, block_irq_interval */ - - if (recv->dma_mode == BUFFER_FILL_MODE) { - recv->buf_stride = PAGE_SIZE; - - /* one block per page of data in the DMA buffer, minus the final guard page */ - recv->nblocks = iso->buf_size/PAGE_SIZE - 1; - if (recv->nblocks < 3) { - DBGMSG("ohci_iso_recv_init: DMA buffer too small"); - goto err; - } - - /* iso->irq_interval is in packets - translate that to blocks */ - if (iso->irq_interval == 1) - recv->block_irq_interval = 1; - else - recv->block_irq_interval = iso->irq_interval * - ((recv->nblocks+1)/iso->buf_packets); - if (recv->block_irq_interval*4 > recv->nblocks) - recv->block_irq_interval = recv->nblocks/4; - if (recv->block_irq_interval < 1) - recv->block_irq_interval = 1; - - } else { - int max_packet_size; - - recv->nblocks = iso->buf_packets; - recv->block_irq_interval = iso->irq_interval; - if (recv->block_irq_interval * 4 > iso->buf_packets) - recv->block_irq_interval = iso->buf_packets / 4; - if (recv->block_irq_interval < 1) - recv->block_irq_interval = 1; - - /* choose a buffer stride */ - /* must be a power of 2, and <= PAGE_SIZE */ - - max_packet_size = iso->buf_size / iso->buf_packets; - - for (recv->buf_stride = 8; recv->buf_stride < max_packet_size; - recv->buf_stride *= 2); - - if (recv->buf_stride*iso->buf_packets > iso->buf_size || - recv->buf_stride > PAGE_SIZE) { - /* this shouldn't happen, but anyway... */ - DBGMSG("ohci_iso_recv_init: problem choosing a buffer stride"); - goto err; - } - } - - recv->block_reader = 0; - recv->released_bytes = 0; - recv->block_dma = 0; - recv->dma_offset = 0; - - /* size of DMA program = one descriptor per block */ - if (dma_prog_region_alloc(&recv->prog, - sizeof(struct dma_cmd) * recv->nblocks, - recv->ohci->dev)) - goto err; - - recv->block = (struct dma_cmd*) recv->prog.kvirt; - - ohci1394_init_iso_tasklet(&recv->task, - iso->channel == -1 ? OHCI_ISO_MULTICHANNEL_RECEIVE : - OHCI_ISO_RECEIVE, - ohci_iso_recv_task, (unsigned long) iso); - - if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) { - ret = -EBUSY; - goto err; - } - - recv->task_active = 1; - - /* recv context registers are spaced 32 bytes apart */ - ctx = recv->task.context; - recv->ContextControlSet = OHCI1394_IsoRcvContextControlSet + 32 * ctx; - recv->ContextControlClear = OHCI1394_IsoRcvContextControlClear + 32 * ctx; - recv->CommandPtr = OHCI1394_IsoRcvCommandPtr + 32 * ctx; - recv->ContextMatch = OHCI1394_IsoRcvContextMatch + 32 * ctx; - - if (iso->channel == -1) { - /* clear multi-channel selection mask */ - reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, 0xFFFFFFFF); - reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, 0xFFFFFFFF); - } - - /* write the DMA program */ - ohci_iso_recv_program(iso); - - DBGMSG("ohci_iso_recv_init: %s mode, DMA buffer is %lu pages" - " (%u bytes), using %u blocks, buf_stride %u, block_irq_interval %d", - recv->dma_mode == BUFFER_FILL_MODE ? - "buffer-fill" : "packet-per-buffer", - iso->buf_size/PAGE_SIZE, iso->buf_size, - recv->nblocks, recv->buf_stride, recv->block_irq_interval); - - return 0; - -err: - ohci_iso_recv_shutdown(iso); - return ret; -} - -static void ohci_iso_recv_stop(struct hpsb_iso *iso) -{ - struct ohci_iso_recv *recv = iso->hostdata; - - /* disable interrupts */ - reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << recv->task.context); - - /* halt DMA */ - ohci1394_stop_context(recv->ohci, recv->ContextControlClear, NULL); -} - -static void ohci_iso_recv_shutdown(struct hpsb_iso *iso) -{ - struct ohci_iso_recv *recv = iso->hostdata; - - if (recv->task_active) { - ohci_iso_recv_stop(iso); - ohci1394_unregister_iso_tasklet(recv->ohci, &recv->task); - recv->task_active = 0; - } - - dma_prog_region_free(&recv->prog); - kfree(recv); - iso->hostdata = NULL; -} - -/* set up a "gapped" ring buffer DMA program */ -static void ohci_iso_recv_program(struct hpsb_iso *iso) -{ - struct ohci_iso_recv *recv = iso->hostdata; - int blk; - - /* address of 'branch' field in previous DMA descriptor */ - u32 *prev_branch = NULL; - - for (blk = 0; blk < recv->nblocks; blk++) { - u32 control; - - /* the DMA descriptor */ - struct dma_cmd *cmd = &recv->block[blk]; - - /* offset of the DMA descriptor relative to the DMA prog buffer */ - unsigned long prog_offset = blk * sizeof(struct dma_cmd); - - /* offset of this packet's data within the DMA buffer */ - unsigned long buf_offset = blk * recv->buf_stride; - - if (recv->dma_mode == BUFFER_FILL_MODE) { - control = 2 << 28; /* INPUT_MORE */ - } else { - control = 3 << 28; /* INPUT_LAST */ - } - - control |= 8 << 24; /* s = 1, update xferStatus and resCount */ - - /* interrupt on last block, and at intervals */ - if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) { - control |= 3 << 20; /* want interrupt */ - } - - control |= 3 << 18; /* enable branch to address */ - control |= recv->buf_stride; - - cmd->control = cpu_to_le32(control); - cmd->address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, buf_offset)); - cmd->branchAddress = 0; /* filled in on next loop */ - cmd->status = cpu_to_le32(recv->buf_stride); - - /* link the previous descriptor to this one */ - if (prev_branch) { - *prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1); - } - - prev_branch = &cmd->branchAddress; - } - - /* the final descriptor's branch address and Z should be left at 0 */ -} - -/* listen or unlisten to a specific channel (multi-channel mode only) */ -static void ohci_iso_recv_change_channel(struct hpsb_iso *iso, unsigned char channel, int listen) -{ - struct ohci_iso_recv *recv = iso->hostdata; - int reg, i; - - if (channel < 32) { - reg = listen ? OHCI1394_IRMultiChanMaskLoSet : OHCI1394_IRMultiChanMaskLoClear; - i = channel; - } else { - reg = listen ? OHCI1394_IRMultiChanMaskHiSet : OHCI1394_IRMultiChanMaskHiClear; - i = channel - 32; - } - - reg_write(recv->ohci, reg, (1 << i)); - - /* issue a dummy read to force all PCI writes to be posted immediately */ - mb(); - reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); -} - -static void ohci_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask) -{ - struct ohci_iso_recv *recv = iso->hostdata; - int i; - - for (i = 0; i < 64; i++) { - if (mask & (1ULL << i)) { - if (i < 32) - reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoSet, (1 << i)); - else - reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiSet, (1 << (i-32))); - } else { - if (i < 32) - reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, (1 << i)); - else - reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, (1 << (i-32))); - } - } - - /* issue a dummy read to force all PCI writes to be posted immediately */ - mb(); - reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); -} - -static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync) -{ - struct ohci_iso_recv *recv = iso->hostdata; - struct ti_ohci *ohci = recv->ohci; - u32 command, contextMatch; - - reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF); - wmb(); - - /* always keep ISO headers */ - command = (1 << 30); - - if (recv->dma_mode == BUFFER_FILL_MODE) - command |= (1 << 31); - - reg_write(recv->ohci, recv->ContextControlSet, command); - - /* match on specified tags */ - contextMatch = tag_mask << 28; - - if (iso->channel == -1) { - /* enable multichannel reception */ - reg_write(recv->ohci, recv->ContextControlSet, (1 << 28)); - } else { - /* listen on channel */ - contextMatch |= iso->channel; - } - - if (cycle != -1) { - u32 seconds; - - /* enable cycleMatch */ - reg_write(recv->ohci, recv->ContextControlSet, (1 << 29)); - - /* set starting cycle */ - cycle &= 0x1FFF; - - /* 'cycle' is only mod 8000, but we also need two 'seconds' bits - - just snarf them from the current time */ - seconds = reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer) >> 25; - - /* advance one second to give some extra time for DMA to start */ - seconds += 1; - - cycle |= (seconds & 3) << 13; - - contextMatch |= cycle << 12; - } - - if (sync != -1) { - /* set sync flag on first DMA descriptor */ - struct dma_cmd *cmd = &recv->block[recv->block_dma]; - cmd->control |= cpu_to_le32(DMA_CTL_WAIT); - - /* match sync field */ - contextMatch |= (sync&0xf)<<8; - } - - reg_write(recv->ohci, recv->ContextMatch, contextMatch); - - /* address of first descriptor block */ - command = dma_prog_region_offset_to_bus(&recv->prog, - recv->block_dma * sizeof(struct dma_cmd)); - command |= 1; /* Z=1 */ - - reg_write(recv->ohci, recv->CommandPtr, command); - - /* enable interrupts */ - reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskSet, 1 << recv->task.context); - - wmb(); - - /* run */ - reg_write(recv->ohci, recv->ContextControlSet, 0x8000); - - /* issue a dummy read of the cycle timer register to force - all PCI writes to be posted immediately */ - mb(); - reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); - - /* check RUN */ - if (!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) { - PRINT(KERN_ERR, - "Error starting IR DMA (ContextControl 0x%08x)\n", - reg_read(recv->ohci, recv->ContextControlSet)); - return -1; - } - - return 0; -} - -static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block) -{ - /* re-use the DMA descriptor for the block */ - /* by linking the previous descriptor to it */ - - int next_i = block; - int prev_i = (next_i == 0) ? (recv->nblocks - 1) : (next_i - 1); - - struct dma_cmd *next = &recv->block[next_i]; - struct dma_cmd *prev = &recv->block[prev_i]; - - /* ignore out-of-range requests */ - if ((block < 0) || (block > recv->nblocks)) - return; - - /* 'next' becomes the new end of the DMA chain, - so disable branch and enable interrupt */ - next->branchAddress = 0; - next->control |= cpu_to_le32(3 << 20); - next->status = cpu_to_le32(recv->buf_stride); - - /* link prev to next */ - prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, - sizeof(struct dma_cmd) * next_i) - | 1); /* Z=1 */ - - /* disable interrupt on previous DMA descriptor, except at intervals */ - if ((prev_i % recv->block_irq_interval) == 0) { - prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */ - } else { - prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */ - } - wmb(); - - /* wake up DMA in case it fell asleep */ - reg_write(recv->ohci, recv->ContextControlSet, (1 << 12)); -} - -static void ohci_iso_recv_bufferfill_release(struct ohci_iso_recv *recv, - struct hpsb_iso_packet_info *info) -{ - /* release the memory where the packet was */ - recv->released_bytes += info->total_len; - - /* have we released enough memory for one block? */ - while (recv->released_bytes > recv->buf_stride) { - ohci_iso_recv_release_block(recv, recv->block_reader); - recv->block_reader = (recv->block_reader + 1) % recv->nblocks; - recv->released_bytes -= recv->buf_stride; - } -} - -static inline void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) -{ - struct ohci_iso_recv *recv = iso->hostdata; - if (recv->dma_mode == BUFFER_FILL_MODE) { - ohci_iso_recv_bufferfill_release(recv, info); - } else { - ohci_iso_recv_release_block(recv, info - iso->infos); - } -} - -/* parse all packets from blocks that have been fully received */ -static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso_recv *recv) -{ - int wake = 0; - int runaway = 0; - struct ti_ohci *ohci = recv->ohci; - - while (1) { - /* we expect the next parsable packet to begin at recv->dma_offset */ - /* note: packet layout is as shown in section 10.6.1.1 of the OHCI spec */ - - unsigned int offset; - unsigned short len, cycle, total_len; - unsigned char channel, tag, sy; - - unsigned char *p = iso->data_buf.kvirt; - - unsigned int this_block = recv->dma_offset/recv->buf_stride; - - /* don't loop indefinitely */ - if (runaway++ > 100000) { - atomic_inc(&iso->overflows); - PRINT(KERN_ERR, - "IR DMA error - Runaway during buffer parsing!\n"); - break; - } - - /* stop parsing once we arrive at block_dma (i.e. don't get ahead of DMA) */ - if (this_block == recv->block_dma) - break; - - wake = 1; - - /* parse data length, tag, channel, and sy */ - - /* note: we keep our own local copies of 'len' and 'offset' - so the user can't mess with them by poking in the mmap area */ - - len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8); - - if (len > 4096) { - PRINT(KERN_ERR, - "IR DMA error - bogus 'len' value %u\n", len); - } - - channel = p[recv->dma_offset+1] & 0x3F; - tag = p[recv->dma_offset+1] >> 6; - sy = p[recv->dma_offset+0] & 0xF; - - /* advance to data payload */ - recv->dma_offset += 4; - - /* check for wrap-around */ - if (recv->dma_offset >= recv->buf_stride*recv->nblocks) { - recv->dma_offset -= recv->buf_stride*recv->nblocks; - } - - /* dma_offset now points to the first byte of the data payload */ - offset = recv->dma_offset; - - /* advance to xferStatus/timeStamp */ - recv->dma_offset += len; - - total_len = len + 8; /* 8 bytes header+trailer in OHCI packet */ - /* payload is padded to 4 bytes */ - if (len % 4) { - recv->dma_offset += 4 - (len%4); - total_len += 4 - (len%4); - } - - /* check for wrap-around */ - if (recv->dma_offset >= recv->buf_stride*recv->nblocks) { - /* uh oh, the packet data wraps from the last - to the first DMA block - make the packet - contiguous by copying its "tail" into the - guard page */ - - int guard_off = recv->buf_stride*recv->nblocks; - int tail_len = len - (guard_off - offset); - - if (tail_len > 0 && tail_len < recv->buf_stride) { - memcpy(iso->data_buf.kvirt + guard_off, - iso->data_buf.kvirt, - tail_len); - } - - recv->dma_offset -= recv->buf_stride*recv->nblocks; - } - - /* parse timestamp */ - cycle = p[recv->dma_offset+0] | (p[recv->dma_offset+1]<<8); - cycle &= 0x1FFF; - - /* advance to next packet */ - recv->dma_offset += 4; - - /* check for wrap-around */ - if (recv->dma_offset >= recv->buf_stride*recv->nblocks) { - recv->dma_offset -= recv->buf_stride*recv->nblocks; - } - - hpsb_iso_packet_received(iso, offset, len, total_len, cycle, channel, tag, sy); - } - - if (wake) - hpsb_iso_wake(iso); -} - -static void ohci_iso_recv_bufferfill_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv) -{ - int loop; - struct ti_ohci *ohci = recv->ohci; - - /* loop over all blocks */ - for (loop = 0; loop < recv->nblocks; loop++) { - - /* check block_dma to see if it's done */ - struct dma_cmd *im = &recv->block[recv->block_dma]; - - /* check the DMA descriptor for new writes to xferStatus */ - u16 xferstatus = le32_to_cpu(im->status) >> 16; - - /* rescount is the number of bytes *remaining to be written* in the block */ - u16 rescount = le32_to_cpu(im->status) & 0xFFFF; - - unsigned char event = xferstatus & 0x1F; - - if (!event) { - /* nothing has happened to this block yet */ - break; - } - - if (event != 0x11) { - atomic_inc(&iso->overflows); - PRINT(KERN_ERR, - "IR DMA error - OHCI error code 0x%02x\n", event); - } - - if (rescount != 0) { - /* the card is still writing to this block; - we can't touch it until it's done */ - break; - } - - /* OK, the block is finished... */ - - /* sync our view of the block */ - dma_region_sync_for_cpu(&iso->data_buf, recv->block_dma*recv->buf_stride, recv->buf_stride); - - /* reset the DMA descriptor */ - im->status = recv->buf_stride; - - /* advance block_dma */ - recv->block_dma = (recv->block_dma + 1) % recv->nblocks; - - if ((recv->block_dma+1) % recv->nblocks == recv->block_reader) { - atomic_inc(&iso->overflows); - DBGMSG("ISO reception overflow - " - "ran out of DMA blocks"); - } - } - - /* parse any packets that have arrived */ - ohci_iso_recv_bufferfill_parse(iso, recv); -} - -static void ohci_iso_recv_packetperbuf_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv) -{ - int count; - int wake = 0; - struct ti_ohci *ohci = recv->ohci; - - /* loop over the entire buffer */ - for (count = 0; count < recv->nblocks; count++) { - u32 packet_len = 0; - - /* pointer to the DMA descriptor */ - struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma; - - /* check the DMA descriptor for new writes to xferStatus */ - u16 xferstatus = le32_to_cpu(il->status) >> 16; - u16 rescount = le32_to_cpu(il->status) & 0xFFFF; - - unsigned char event = xferstatus & 0x1F; - - if (!event) { - /* this packet hasn't come in yet; we are done for now */ - goto out; - } - - if (event == 0x11) { - /* packet received successfully! */ - - /* rescount is the number of bytes *remaining* in the packet buffer, - after the packet was written */ - packet_len = recv->buf_stride - rescount; - - } else if (event == 0x02) { - PRINT(KERN_ERR, "IR DMA error - packet too long for buffer\n"); - } else if (event) { - PRINT(KERN_ERR, "IR DMA error - OHCI error code 0x%02x\n", event); - } - - /* sync our view of the buffer */ - dma_region_sync_for_cpu(&iso->data_buf, iso->pkt_dma * recv->buf_stride, recv->buf_stride); - - /* record the per-packet info */ - { - /* iso header is 8 bytes ahead of the data payload */ - unsigned char *hdr; - - unsigned int offset; - unsigned short cycle; - unsigned char channel, tag, sy; - - offset = iso->pkt_dma * recv->buf_stride; - hdr = iso->data_buf.kvirt + offset; - - /* skip iso header */ - offset += 8; - packet_len -= 8; - - cycle = (hdr[0] | (hdr[1] << 8)) & 0x1FFF; - channel = hdr[5] & 0x3F; - tag = hdr[5] >> 6; - sy = hdr[4] & 0xF; - - hpsb_iso_packet_received(iso, offset, packet_len, - recv->buf_stride, cycle, channel, tag, sy); - } - - /* reset the DMA descriptor */ - il->status = recv->buf_stride; - - wake = 1; - recv->block_dma = iso->pkt_dma; - } - -out: - if (wake) - hpsb_iso_wake(iso); -} - -static void ohci_iso_recv_task(unsigned long data) -{ - struct hpsb_iso *iso = (struct hpsb_iso*) data; - struct ohci_iso_recv *recv = iso->hostdata; - - if (recv->dma_mode == BUFFER_FILL_MODE) - ohci_iso_recv_bufferfill_task(iso, recv); - else - ohci_iso_recv_packetperbuf_task(iso, recv); -} - -/*********************************** - * rawiso ISO transmission * - ***********************************/ - -struct ohci_iso_xmit { - struct ti_ohci *ohci; - struct dma_prog_region prog; - struct ohci1394_iso_tasklet task; - int task_active; - int last_cycle; - atomic_t skips; - - u32 ContextControlSet; - u32 ContextControlClear; - u32 CommandPtr; -}; - -/* transmission DMA program: - one OUTPUT_MORE_IMMEDIATE for the IT header - one OUTPUT_LAST for the buffer data */ - -struct iso_xmit_cmd { - struct dma_cmd output_more_immediate; - u8 iso_hdr[8]; - u32 unused[2]; - struct dma_cmd output_last; -}; - -static int ohci_iso_xmit_init(struct hpsb_iso *iso); -static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle); -static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso); -static void ohci_iso_xmit_task(unsigned long data); - -static int ohci_iso_xmit_init(struct hpsb_iso *iso) -{ - struct ohci_iso_xmit *xmit; - unsigned int prog_size; - int ctx; - int ret = -ENOMEM; - - xmit = kmalloc(sizeof(*xmit), GFP_KERNEL); - if (!xmit) - return -ENOMEM; - - iso->hostdata = xmit; - xmit->ohci = iso->host->hostdata; - xmit->task_active = 0; - xmit->last_cycle = -1; - atomic_set(&iso->skips, 0); - - dma_prog_region_init(&xmit->prog); - - prog_size = sizeof(struct iso_xmit_cmd) * iso->buf_packets; - - if (dma_prog_region_alloc(&xmit->prog, prog_size, xmit->ohci->dev)) - goto err; - - ohci1394_init_iso_tasklet(&xmit->task, OHCI_ISO_TRANSMIT, - ohci_iso_xmit_task, (unsigned long) iso); - - if (ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0) { - ret = -EBUSY; - goto err; - } - - xmit->task_active = 1; - - /* xmit context registers are spaced 16 bytes apart */ - ctx = xmit->task.context; - xmit->ContextControlSet = OHCI1394_IsoXmitContextControlSet + 16 * ctx; - xmit->ContextControlClear = OHCI1394_IsoXmitContextControlClear + 16 * ctx; - xmit->CommandPtr = OHCI1394_IsoXmitCommandPtr + 16 * ctx; - - return 0; - -err: - ohci_iso_xmit_shutdown(iso); - return ret; -} - -static void ohci_iso_xmit_stop(struct hpsb_iso *iso) -{ - struct ohci_iso_xmit *xmit = iso->hostdata; - struct ti_ohci *ohci = xmit->ohci; - - /* disable interrupts */ - reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context); - - /* halt DMA */ - if (ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) { - /* XXX the DMA context will lock up if you try to send too much data! */ - PRINT(KERN_ERR, - "you probably exceeded the OHCI card's bandwidth limit - " - "reload the module and reduce xmit bandwidth"); - } -} - -static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso) -{ - struct ohci_iso_xmit *xmit = iso->hostdata; - - if (xmit->task_active) { - ohci_iso_xmit_stop(iso); - ohci1394_unregister_iso_tasklet(xmit->ohci, &xmit->task); - xmit->task_active = 0; - } - - dma_prog_region_free(&xmit->prog); - kfree(xmit); - iso->hostdata = NULL; -} - -static void ohci_iso_xmit_task(unsigned long data) -{ - struct hpsb_iso *iso = (struct hpsb_iso*) data; - struct ohci_iso_xmit *xmit = iso->hostdata; - struct ti_ohci *ohci = xmit->ohci; - int wake = 0; - int count; - - /* check the whole buffer if necessary, starting at pkt_dma */ - for (count = 0; count < iso->buf_packets; count++) { - int cycle; - - /* DMA descriptor */ - struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma); - - /* check for new writes to xferStatus */ - u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16; - u8 event = xferstatus & 0x1F; - - if (!event) { - /* packet hasn't been sent yet; we are done for now */ - break; - } - - if (event != 0x11) - PRINT(KERN_ERR, - "IT DMA error - OHCI error code 0x%02x\n", event); - - /* at least one packet went out, so wake up the writer */ - wake = 1; - - /* parse cycle */ - cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF; - - if (xmit->last_cycle > -1) { - int cycle_diff = cycle - xmit->last_cycle; - int skip; - - /* unwrap */ - if (cycle_diff < 0) { - cycle_diff += 8000; - if (cycle_diff < 0) - PRINT(KERN_ERR, "bogus cycle diff %d\n", - cycle_diff); - } - - skip = cycle_diff - 1; - if (skip > 0) { - DBGMSG("skipped %d cycles without packet loss", skip); - atomic_add(skip, &iso->skips); - } - } - xmit->last_cycle = cycle; - - /* tell the subsystem the packet has gone out */ - hpsb_iso_packet_sent(iso, cycle, event != 0x11); - - /* reset the DMA descriptor for next time */ - cmd->output_last.status = 0; - } - - if (wake) - hpsb_iso_wake(iso); -} - -static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) -{ - struct ohci_iso_xmit *xmit = iso->hostdata; - struct ti_ohci *ohci = xmit->ohci; - - int next_i, prev_i; - struct iso_xmit_cmd *next, *prev; - - unsigned int offset; - unsigned short len; - unsigned char tag, sy; - - /* check that the packet doesn't cross a page boundary - (we could allow this if we added OUTPUT_MORE descriptor support) */ - if (cross_bound(info->offset, info->len)) { - PRINT(KERN_ERR, - "rawiso xmit: packet %u crosses a page boundary", - iso->first_packet); - return -EINVAL; - } - - offset = info->offset; - len = info->len; - tag = info->tag; - sy = info->sy; - - /* sync up the card's view of the buffer */ - dma_region_sync_for_device(&iso->data_buf, offset, len); - - /* append first_packet to the DMA chain */ - /* by linking the previous descriptor to it */ - /* (next will become the new end of the DMA chain) */ - - next_i = iso->first_packet; - prev_i = (next_i == 0) ? (iso->buf_packets - 1) : (next_i - 1); - - next = dma_region_i(&xmit->prog, struct iso_xmit_cmd, next_i); - prev = dma_region_i(&xmit->prog, struct iso_xmit_cmd, prev_i); - - /* set up the OUTPUT_MORE_IMMEDIATE descriptor */ - memset(next, 0, sizeof(struct iso_xmit_cmd)); - next->output_more_immediate.control = cpu_to_le32(0x02000008); - - /* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */ - - /* tcode = 0xA, and sy */ - next->iso_hdr[0] = 0xA0 | (sy & 0xF); - - /* tag and channel number */ - next->iso_hdr[1] = (tag << 6) | (iso->channel & 0x3F); - - /* transmission speed */ - next->iso_hdr[2] = iso->speed & 0x7; - - /* payload size */ - next->iso_hdr[6] = len & 0xFF; - next->iso_hdr[7] = len >> 8; - - /* set up the OUTPUT_LAST */ - next->output_last.control = cpu_to_le32(1 << 28); - next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */ - next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */ - next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */ - next->output_last.control |= cpu_to_le32(len); - - /* payload bus address */ - next->output_last.address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, offset)); - - /* leave branchAddress at zero for now */ - - /* re-write the previous DMA descriptor to chain to this one */ - - /* set prev branch address to point to next (Z=3) */ - prev->output_last.branchAddress = cpu_to_le32( - dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3); - - /* - * Link the skip address to this descriptor itself. This causes a - * context to skip a cycle whenever lost cycles or FIFO overruns occur, - * without dropping the data at that point the application should then - * decide whether this is an error condition or not. Some protocols - * can deal with this by dropping some rate-matching padding packets. - */ - next->output_more_immediate.branchAddress = - prev->output_last.branchAddress; - - /* disable interrupt, unless required by the IRQ interval */ - if (prev_i % iso->irq_interval) { - prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */ - } else { - prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */ - } - - wmb(); - - /* wake DMA in case it is sleeping */ - reg_write(xmit->ohci, xmit->ContextControlSet, 1 << 12); - - /* issue a dummy read of the cycle timer to force all PCI - writes to be posted immediately */ - mb(); - reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer); - - return 0; -} - -static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle) -{ - struct ohci_iso_xmit *xmit = iso->hostdata; - struct ti_ohci *ohci = xmit->ohci; - - /* clear out the control register */ - reg_write(xmit->ohci, xmit->ContextControlClear, 0xFFFFFFFF); - wmb(); - - /* address and length of first descriptor block (Z=3) */ - reg_write(xmit->ohci, xmit->CommandPtr, - dma_prog_region_offset_to_bus(&xmit->prog, iso->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3); - - /* cycle match */ - if (cycle != -1) { - u32 start = cycle & 0x1FFF; - - /* 'cycle' is only mod 8000, but we also need two 'seconds' bits - - just snarf them from the current time */ - u32 seconds = reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer) >> 25; - - /* advance one second to give some extra time for DMA to start */ - seconds += 1; - - start |= (seconds & 3) << 13; - - reg_write(xmit->ohci, xmit->ContextControlSet, 0x80000000 | (start << 16)); - } - - /* enable interrupts */ - reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskSet, 1 << xmit->task.context); - - /* run */ - reg_write(xmit->ohci, xmit->ContextControlSet, 0x8000); - mb(); - - /* wait 100 usec to give the card time to go active */ - udelay(100); - - /* check the RUN bit */ - if (!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) { - PRINT(KERN_ERR, "Error starting IT DMA (ContextControl 0x%08x)\n", - reg_read(xmit->ohci, xmit->ContextControlSet)); - return -1; - } - - return 0; -} - -static int ohci_isoctl(struct hpsb_iso *iso, enum isoctl_cmd cmd, unsigned long arg) -{ - - switch(cmd) { - case XMIT_INIT: - return ohci_iso_xmit_init(iso); - case XMIT_START: - return ohci_iso_xmit_start(iso, arg); - case XMIT_STOP: - ohci_iso_xmit_stop(iso); - return 0; - case XMIT_QUEUE: - return ohci_iso_xmit_queue(iso, (struct hpsb_iso_packet_info*) arg); - case XMIT_SHUTDOWN: - ohci_iso_xmit_shutdown(iso); - return 0; - - case RECV_INIT: - return ohci_iso_recv_init(iso); - case RECV_START: { - int *args = (int*) arg; - return ohci_iso_recv_start(iso, args[0], args[1], args[2]); - } - case RECV_STOP: - ohci_iso_recv_stop(iso); - return 0; - case RECV_RELEASE: - ohci_iso_recv_release(iso, (struct hpsb_iso_packet_info*) arg); - return 0; - case RECV_FLUSH: - ohci_iso_recv_task((unsigned long) iso); - return 0; - case RECV_SHUTDOWN: - ohci_iso_recv_shutdown(iso); - return 0; - case RECV_LISTEN_CHANNEL: - ohci_iso_recv_change_channel(iso, arg, 1); - return 0; - case RECV_UNLISTEN_CHANNEL: - ohci_iso_recv_change_channel(iso, arg, 0); - return 0; - case RECV_SET_CHANNEL_MASK: - ohci_iso_recv_set_channel_mask(iso, *((u64*) arg)); - return 0; - - default: - PRINT_G(KERN_ERR, "ohci_isoctl cmd %d not implemented yet", - cmd); - break; - } - return -EINVAL; -} - -/*************************************** - * IEEE-1394 functionality section END * - ***************************************/ - - -/******************************************************** - * Global stuff (interrupt handler, init/shutdown code) * - ********************************************************/ - -static void dma_trm_reset(struct dma_trm_ctx *d) -{ - unsigned long flags; - LIST_HEAD(packet_list); - struct ti_ohci *ohci = d->ohci; - struct hpsb_packet *packet, *ptmp; - - ohci1394_stop_context(ohci, d->ctrlClear, NULL); - - /* Lock the context, reset it and release it. Move the packets - * that were pending in the context to packet_list and free - * them after releasing the lock. */ - - spin_lock_irqsave(&d->lock, flags); - - list_splice_init(&d->fifo_list, &packet_list); - list_splice_init(&d->pending_list, &packet_list); - - d->branchAddrPtr = NULL; - d->sent_ind = d->prg_ind; - d->free_prgs = d->num_desc; - - spin_unlock_irqrestore(&d->lock, flags); - - if (list_empty(&packet_list)) - return; - - PRINT(KERN_INFO, "AT dma reset ctx=%d, aborting transmission", d->ctx); - - /* Now process subsystem callbacks for the packets from this - * context. */ - list_for_each_entry_safe(packet, ptmp, &packet_list, driver_list) { - list_del_init(&packet->driver_list); - hpsb_packet_sent(ohci->host, packet, ACKX_ABORTED); - } -} - -static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci, - quadlet_t rx_event, - quadlet_t tx_event) -{ - struct ohci1394_iso_tasklet *t; - unsigned long mask; - unsigned long flags; - - spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags); - - list_for_each_entry(t, &ohci->iso_tasklet_list, link) { - mask = 1 << t->context; - - if (t->type == OHCI_ISO_TRANSMIT) { - if (tx_event & mask) - tasklet_schedule(&t->tasklet); - } else { - /* OHCI_ISO_RECEIVE or OHCI_ISO_MULTICHANNEL_RECEIVE */ - if (rx_event & mask) - tasklet_schedule(&t->tasklet); - } - } - - spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags); -} - -static irqreturn_t ohci_irq_handler(int irq, void *dev_id) -{ - quadlet_t event, node_id; - struct ti_ohci *ohci = (struct ti_ohci *)dev_id; - struct hpsb_host *host = ohci->host; - int phyid = -1, isroot = 0; - unsigned long flags; - - /* Read and clear the interrupt event register. Don't clear - * the busReset event, though. This is done when we get the - * selfIDComplete interrupt. */ - spin_lock_irqsave(&ohci->event_lock, flags); - event = reg_read(ohci, OHCI1394_IntEventClear); - reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset); - spin_unlock_irqrestore(&ohci->event_lock, flags); - - if (!event) - return IRQ_NONE; - - /* If event is ~(u32)0 cardbus card was ejected. In this case - * we just return, and clean up in the ohci1394_pci_remove - * function. */ - if (event == ~(u32) 0) { - DBGMSG("Device removed."); - return IRQ_NONE; - } - - DBGMSG("IntEvent: %08x", event); - - if (event & OHCI1394_unrecoverableError) { - int ctx; - PRINT(KERN_ERR, "Unrecoverable error!"); - - if (reg_read(ohci, OHCI1394_AsReqTrContextControlSet) & 0x800) - PRINT(KERN_ERR, "Async Req Tx Context died: " - "ctrl[%08x] cmdptr[%08x]", - reg_read(ohci, OHCI1394_AsReqTrContextControlSet), - reg_read(ohci, OHCI1394_AsReqTrCommandPtr)); - - if (reg_read(ohci, OHCI1394_AsRspTrContextControlSet) & 0x800) - PRINT(KERN_ERR, "Async Rsp Tx Context died: " - "ctrl[%08x] cmdptr[%08x]", - reg_read(ohci, OHCI1394_AsRspTrContextControlSet), - reg_read(ohci, OHCI1394_AsRspTrCommandPtr)); - - if (reg_read(ohci, OHCI1394_AsReqRcvContextControlSet) & 0x800) - PRINT(KERN_ERR, "Async Req Rcv Context died: " - "ctrl[%08x] cmdptr[%08x]", - reg_read(ohci, OHCI1394_AsReqRcvContextControlSet), - reg_read(ohci, OHCI1394_AsReqRcvCommandPtr)); - - if (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) & 0x800) - PRINT(KERN_ERR, "Async Rsp Rcv Context died: " - "ctrl[%08x] cmdptr[%08x]", - reg_read(ohci, OHCI1394_AsRspRcvContextControlSet), - reg_read(ohci, OHCI1394_AsRspRcvCommandPtr)); - - for (ctx = 0; ctx < ohci->nb_iso_xmit_ctx; ctx++) { - if (reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)) & 0x800) - PRINT(KERN_ERR, "Iso Xmit %d Context died: " - "ctrl[%08x] cmdptr[%08x]", ctx, - reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)), - reg_read(ohci, OHCI1394_IsoXmitCommandPtr + (16 * ctx))); - } - - for (ctx = 0; ctx < ohci->nb_iso_rcv_ctx; ctx++) { - if (reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)) & 0x800) - PRINT(KERN_ERR, "Iso Recv %d Context died: " - "ctrl[%08x] cmdptr[%08x] match[%08x]", ctx, - reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)), - reg_read(ohci, OHCI1394_IsoRcvCommandPtr + (32 * ctx)), - reg_read(ohci, OHCI1394_IsoRcvContextMatch + (32 * ctx))); - } - - event &= ~OHCI1394_unrecoverableError; - } - if (event & OHCI1394_postedWriteErr) { - PRINT(KERN_ERR, "physical posted write error"); - /* no recovery strategy yet, had to involve protocol drivers */ - event &= ~OHCI1394_postedWriteErr; - } - if (event & OHCI1394_cycleTooLong) { - if(printk_ratelimit()) - PRINT(KERN_WARNING, "isochronous cycle too long"); - else - DBGMSG("OHCI1394_cycleTooLong"); - reg_write(ohci, OHCI1394_LinkControlSet, - OHCI1394_LinkControl_CycleMaster); - event &= ~OHCI1394_cycleTooLong; - } - if (event & OHCI1394_cycleInconsistent) { - /* We subscribe to the cycleInconsistent event only to - * clear the corresponding event bit... otherwise, - * isochronous cycleMatch DMA won't work. */ - DBGMSG("OHCI1394_cycleInconsistent"); - event &= ~OHCI1394_cycleInconsistent; - } - if (event & OHCI1394_busReset) { - /* The busReset event bit can't be cleared during the - * selfID phase, so we disable busReset interrupts, to - * avoid burying the cpu in interrupt requests. */ - spin_lock_irqsave(&ohci->event_lock, flags); - reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset); - - if (ohci->check_busreset) { - int loop_count = 0; - - udelay(10); - - while (reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) { - reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); - - spin_unlock_irqrestore(&ohci->event_lock, flags); - udelay(10); - spin_lock_irqsave(&ohci->event_lock, flags); - - /* The loop counter check is to prevent the driver - * from remaining in this state forever. For the - * initial bus reset, the loop continues for ever - * and the system hangs, until some device is plugged-in - * or out manually into a port! The forced reset seems - * to solve this problem. This mainly effects nForce2. */ - if (loop_count > 10000) { - ohci_devctl(host, RESET_BUS, LONG_RESET); - DBGMSG("Detected bus-reset loop. Forced a bus reset!"); - loop_count = 0; - } - - loop_count++; - } - } - spin_unlock_irqrestore(&ohci->event_lock, flags); - if (!host->in_bus_reset) { - DBGMSG("irq_handler: Bus reset requested"); - - /* Subsystem call */ - hpsb_bus_reset(ohci->host); - } - event &= ~OHCI1394_busReset; - } - if (event & OHCI1394_reqTxComplete) { - struct dma_trm_ctx *d = &ohci->at_req_context; - DBGMSG("Got reqTxComplete interrupt " - "status=0x%08X", reg_read(ohci, d->ctrlSet)); - if (reg_read(ohci, d->ctrlSet) & 0x800) - ohci1394_stop_context(ohci, d->ctrlClear, - "reqTxComplete"); - else - dma_trm_tasklet((unsigned long)d); - //tasklet_schedule(&d->task); - event &= ~OHCI1394_reqTxComplete; - } - if (event & OHCI1394_respTxComplete) { - struct dma_trm_ctx *d = &ohci->at_resp_context; - DBGMSG("Got respTxComplete interrupt " - "status=0x%08X", reg_read(ohci, d->ctrlSet)); - if (reg_read(ohci, d->ctrlSet) & 0x800) - ohci1394_stop_context(ohci, d->ctrlClear, - "respTxComplete"); - else - tasklet_schedule(&d->task); - event &= ~OHCI1394_respTxComplete; - } - if (event & OHCI1394_RQPkt) { - struct dma_rcv_ctx *d = &ohci->ar_req_context; - DBGMSG("Got RQPkt interrupt status=0x%08X", - reg_read(ohci, d->ctrlSet)); - if (reg_read(ohci, d->ctrlSet) & 0x800) - ohci1394_stop_context(ohci, d->ctrlClear, "RQPkt"); - else - tasklet_schedule(&d->task); - event &= ~OHCI1394_RQPkt; - } - if (event & OHCI1394_RSPkt) { - struct dma_rcv_ctx *d = &ohci->ar_resp_context; - DBGMSG("Got RSPkt interrupt status=0x%08X", - reg_read(ohci, d->ctrlSet)); - if (reg_read(ohci, d->ctrlSet) & 0x800) - ohci1394_stop_context(ohci, d->ctrlClear, "RSPkt"); - else - tasklet_schedule(&d->task); - event &= ~OHCI1394_RSPkt; - } - if (event & OHCI1394_isochRx) { - quadlet_t rx_event; - - rx_event = reg_read(ohci, OHCI1394_IsoRecvIntEventSet); - reg_write(ohci, OHCI1394_IsoRecvIntEventClear, rx_event); - ohci_schedule_iso_tasklets(ohci, rx_event, 0); - event &= ~OHCI1394_isochRx; - } - if (event & OHCI1394_isochTx) { - quadlet_t tx_event; - - tx_event = reg_read(ohci, OHCI1394_IsoXmitIntEventSet); - reg_write(ohci, OHCI1394_IsoXmitIntEventClear, tx_event); - ohci_schedule_iso_tasklets(ohci, 0, tx_event); - event &= ~OHCI1394_isochTx; - } - if (event & OHCI1394_selfIDComplete) { - if (host->in_bus_reset) { - node_id = reg_read(ohci, OHCI1394_NodeID); - - if (!(node_id & 0x80000000)) { - PRINT(KERN_ERR, - "SelfID received, but NodeID invalid " - "(probably new bus reset occurred): %08X", - node_id); - goto selfid_not_valid; - } - - phyid = node_id & 0x0000003f; - isroot = (node_id & 0x40000000) != 0; - - DBGMSG("SelfID interrupt received " - "(phyid %d, %s)", phyid, - (isroot ? "root" : "not root")); - - handle_selfid(ohci, host, phyid, isroot); - - /* Clear the bus reset event and re-enable the - * busReset interrupt. */ - spin_lock_irqsave(&ohci->event_lock, flags); - reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset); - reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); - spin_unlock_irqrestore(&ohci->event_lock, flags); - - /* Turn on phys dma reception. - * - * TODO: Enable some sort of filtering management. - */ - if (phys_dma) { - reg_write(ohci, OHCI1394_PhyReqFilterHiSet, - 0xffffffff); - reg_write(ohci, OHCI1394_PhyReqFilterLoSet, - 0xffffffff); - } - - DBGMSG("PhyReqFilter=%08x%08x", - reg_read(ohci, OHCI1394_PhyReqFilterHiSet), - reg_read(ohci, OHCI1394_PhyReqFilterLoSet)); - - hpsb_selfid_complete(host, phyid, isroot); - } else - PRINT(KERN_ERR, - "SelfID received outside of bus reset sequence"); - -selfid_not_valid: - event &= ~OHCI1394_selfIDComplete; - } - - /* Make sure we handle everything, just in case we accidentally - * enabled an interrupt that we didn't write a handler for. */ - if (event) - PRINT(KERN_ERR, "Unhandled interrupt(s) 0x%08x", - event); - - return IRQ_HANDLED; -} - -/* Put the buffer back into the dma context */ -static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx) -{ - struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); - DBGMSG("Inserting dma buf ctx=%d idx=%d", d->ctx, idx); - - d->prg_cpu[idx]->status = cpu_to_le32(d->buf_size); - d->prg_cpu[idx]->branchAddress &= le32_to_cpu(0xfffffff0); - idx = (idx + d->num_desc - 1 ) % d->num_desc; - d->prg_cpu[idx]->branchAddress |= le32_to_cpu(0x00000001); - - /* To avoid a race, ensure 1394 interface hardware sees the inserted - * context program descriptors before it sees the wakeup bit set. */ - wmb(); - - /* wake up the dma context if necessary */ - if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - PRINT(KERN_INFO, - "Waking dma ctx=%d ... processing is probably too slow", - d->ctx); - } - - /* do this always, to avoid race condition */ - reg_write(ohci, d->ctrlSet, 0x1000); -} - -#define cond_le32_to_cpu(data, noswap) \ - (noswap ? data : le32_to_cpu(data)) - -static const int TCODE_SIZE[16] = {20, 0, 16, -1, 16, 20, 20, 0, - -1, 0, -1, 0, -1, -1, 16, -1}; - -/* - * Determine the length of a packet in the buffer - * Optimization suggested by Pascal Drolet <pascal.drolet@informission.ca> - */ -static inline int packet_length(struct dma_rcv_ctx *d, int idx, - quadlet_t *buf_ptr, int offset, - unsigned char tcode, int noswap) -{ - int length = -1; - - if (d->type == DMA_CTX_ASYNC_REQ || d->type == DMA_CTX_ASYNC_RESP) { - length = TCODE_SIZE[tcode]; - if (length == 0) { - if (offset + 12 >= d->buf_size) { - length = (cond_le32_to_cpu(d->buf_cpu[(idx + 1) % d->num_desc] - [3 - ((d->buf_size - offset) >> 2)], noswap) >> 16); - } else { - length = (cond_le32_to_cpu(buf_ptr[3], noswap) >> 16); - } - length += 20; - } - } else if (d->type == DMA_CTX_ISO) { - /* Assumption: buffer fill mode with header/trailer */ - length = (cond_le32_to_cpu(buf_ptr[0], noswap) >> 16) + 8; - } - - if (length > 0 && length % 4) - length += 4 - (length % 4); - - return length; -} - -/* Tasklet that processes dma receive buffers */ -static void dma_rcv_tasklet (unsigned long data) -{ - struct dma_rcv_ctx *d = (struct dma_rcv_ctx*)data; - struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); - unsigned int split_left, idx, offset, rescount; - unsigned char tcode; - int length, bytes_left, ack; - unsigned long flags; - quadlet_t *buf_ptr; - char *split_ptr; - char msg[256]; - - spin_lock_irqsave(&d->lock, flags); - - idx = d->buf_ind; - offset = d->buf_offset; - buf_ptr = d->buf_cpu[idx] + offset/4; - - rescount = le32_to_cpu(d->prg_cpu[idx]->status) & 0xffff; - bytes_left = d->buf_size - rescount - offset; - - while (bytes_left > 0) { - tcode = (cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming) >> 4) & 0xf; - - /* packet_length() will return < 4 for an error */ - length = packet_length(d, idx, buf_ptr, offset, tcode, ohci->no_swap_incoming); - - if (length < 4) { /* something is wrong */ - sprintf(msg,"Unexpected tcode 0x%x(0x%08x) in AR ctx=%d, length=%d", - tcode, cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming), - d->ctx, length); - ohci1394_stop_context(ohci, d->ctrlClear, msg); - spin_unlock_irqrestore(&d->lock, flags); - return; - } - - /* The first case is where we have a packet that crosses - * over more than one descriptor. The next case is where - * it's all in the first descriptor. */ - if ((offset + length) > d->buf_size) { - DBGMSG("Split packet rcv'd"); - if (length > d->split_buf_size) { - ohci1394_stop_context(ohci, d->ctrlClear, - "Split packet size exceeded"); - d->buf_ind = idx; - d->buf_offset = offset; - spin_unlock_irqrestore(&d->lock, flags); - return; - } - - if (le32_to_cpu(d->prg_cpu[(idx+1)%d->num_desc]->status) - == d->buf_size) { - /* Other part of packet not written yet. - * this should never happen I think - * anyway we'll get it on the next call. */ - PRINT(KERN_INFO, - "Got only half a packet!"); - d->buf_ind = idx; - d->buf_offset = offset; - spin_unlock_irqrestore(&d->lock, flags); - return; - } - - split_left = length; - split_ptr = (char *)d->spb; - memcpy(split_ptr,buf_ptr,d->buf_size-offset); - split_left -= d->buf_size-offset; - split_ptr += d->buf_size-offset; - insert_dma_buffer(d, idx); - idx = (idx+1) % d->num_desc; - buf_ptr = d->buf_cpu[idx]; - offset=0; - - while (split_left >= d->buf_size) { - memcpy(split_ptr,buf_ptr,d->buf_size); - split_ptr += d->buf_size; - split_left -= d->buf_size; - insert_dma_buffer(d, idx); - idx = (idx+1) % d->num_desc; - buf_ptr = d->buf_cpu[idx]; - } - - if (split_left > 0) { - memcpy(split_ptr, buf_ptr, split_left); - offset = split_left; - buf_ptr += offset/4; - } - } else { - DBGMSG("Single packet rcv'd"); - memcpy(d->spb, buf_ptr, length); - offset += length; - buf_ptr += length/4; - if (offset==d->buf_size) { - insert_dma_buffer(d, idx); - idx = (idx+1) % d->num_desc; - buf_ptr = d->buf_cpu[idx]; - offset=0; - } - } - - /* We get one phy packet to the async descriptor for each - * bus reset. We always ignore it. */ - if (tcode != OHCI1394_TCODE_PHY) { - if (!ohci->no_swap_incoming) - header_le32_to_cpu(d->spb, tcode); - DBGMSG("Packet received from node" - " %d ack=0x%02X spd=%d tcode=0x%X" - " length=%d ctx=%d tlabel=%d", - (d->spb[1]>>16)&0x3f, - (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f, - (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>21)&0x3, - tcode, length, d->ctx, - (d->spb[0]>>10)&0x3f); - - ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f) - == 0x11) ? 1 : 0; - - hpsb_packet_received(ohci->host, d->spb, - length-4, ack); - } -#ifdef OHCI1394_DEBUG - else - PRINT (KERN_DEBUG, "Got phy packet ctx=%d ... discarded", - d->ctx); -#endif - - rescount = le32_to_cpu(d->prg_cpu[idx]->status) & 0xffff; - - bytes_left = d->buf_size - rescount - offset; - - } - - d->buf_ind = idx; - d->buf_offset = offset; - - spin_unlock_irqrestore(&d->lock, flags); -} - -/* Bottom half that processes sent packets */ -static void dma_trm_tasklet (unsigned long data) -{ - struct dma_trm_ctx *d = (struct dma_trm_ctx*)data; - struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci); - struct hpsb_packet *packet, *ptmp; - unsigned long flags; - u32 status, ack; - size_t datasize; - - spin_lock_irqsave(&d->lock, flags); - - list_for_each_entry_safe(packet, ptmp, &d->fifo_list, driver_list) { - datasize = packet->data_size; - if (datasize && packet->type != hpsb_raw) - status = le32_to_cpu( - d->prg_cpu[d->sent_ind]->end.status) >> 16; - else - status = le32_to_cpu( - d->prg_cpu[d->sent_ind]->begin.status) >> 16; - - if (status == 0) - /* this packet hasn't been sent yet*/ - break; - -#ifdef OHCI1394_DEBUG - if (datasize) - if (((le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf) == 0xa) - DBGMSG("Stream packet sent to channel %d tcode=0x%X " - "ack=0x%X spd=%d dataLength=%d ctx=%d", - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>8)&0x3f, - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf, - status&0x1f, (status>>5)&0x3, - le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16, - d->ctx); - else - DBGMSG("Packet sent to node %d tcode=0x%X tLabel=" - "%d ack=0x%X spd=%d dataLength=%d ctx=%d", - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16)&0x3f, - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf, - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>10)&0x3f, - status&0x1f, (status>>5)&0x3, - le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3])>>16, - d->ctx); - else - DBGMSG("Packet sent to node %d tcode=0x%X tLabel=" - "%d ack=0x%X spd=%d data=0x%08X ctx=%d", - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1]) - >>16)&0x3f, - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) - >>4)&0xf, - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) - >>10)&0x3f, - status&0x1f, (status>>5)&0x3, - le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]), - d->ctx); -#endif - - if (status & 0x10) { - ack = status & 0xf; - } else { - switch (status & 0x1f) { - case EVT_NO_STATUS: /* that should never happen */ - case EVT_RESERVED_A: /* that should never happen */ - case EVT_LONG_PACKET: /* that should never happen */ - PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f); - ack = ACKX_SEND_ERROR; - break; - case EVT_MISSING_ACK: - ack = ACKX_TIMEOUT; - break; - case EVT_UNDERRUN: - ack = ACKX_SEND_ERROR; - break; - case EVT_OVERRUN: /* that should never happen */ - PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f); - ack = ACKX_SEND_ERROR; - break; - case EVT_DESCRIPTOR_READ: - case EVT_DATA_READ: - case EVT_DATA_WRITE: - ack = ACKX_SEND_ERROR; - break; - case EVT_BUS_RESET: /* that should never happen */ - PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f); - ack = ACKX_SEND_ERROR; - break; - case EVT_TIMEOUT: - ack = ACKX_TIMEOUT; - break; - case EVT_TCODE_ERR: - ack = ACKX_SEND_ERROR; - break; - case EVT_RESERVED_B: /* that should never happen */ - case EVT_RESERVED_C: /* that should never happen */ - PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f); - ack = ACKX_SEND_ERROR; - break; - case EVT_UNKNOWN: - case EVT_FLUSHED: - ack = ACKX_SEND_ERROR; - break; - default: - PRINT(KERN_ERR, "Unhandled OHCI evt_* error 0x%x", status & 0x1f); - ack = ACKX_SEND_ERROR; - BUG(); - } - } - - list_del_init(&packet->driver_list); - hpsb_packet_sent(ohci->host, packet, ack); - - if (datasize) - pci_unmap_single(ohci->dev, - cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address), - datasize, PCI_DMA_TODEVICE); - - d->sent_ind = (d->sent_ind+1)%d->num_desc; - d->free_prgs++; - } - - dma_trm_flush(ohci, d); - - spin_unlock_irqrestore(&d->lock, flags); -} - -static void free_dma_rcv_ctx(struct dma_rcv_ctx *d) -{ - int i; - struct ti_ohci *ohci = d->ohci; - - if (ohci == NULL) - return; - - DBGMSG("Freeing dma_rcv_ctx %d", d->ctx); - - if (d->buf_cpu) { - for (i=0; i<d->num_desc; i++) - if (d->buf_cpu[i] && d->buf_bus[i]) - pci_free_consistent( - ohci->dev, d->buf_size, - d->buf_cpu[i], d->buf_bus[i]); - kfree(d->buf_cpu); - kfree(d->buf_bus); - } - if (d->prg_cpu) { - for (i=0; i<d->num_desc; i++) - if (d->prg_cpu[i] && d->prg_bus[i]) - pci_pool_free(d->prg_pool, d->prg_cpu[i], - d->prg_bus[i]); - pci_pool_destroy(d->prg_pool); - kfree(d->prg_cpu); - kfree(d->prg_bus); - } - kfree(d->spb); - - /* Mark this context as freed. */ - d->ohci = NULL; -} - -static int -alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d, - enum context_type type, int ctx, int num_desc, - int buf_size, int split_buf_size, int context_base) -{ - int i, len; - static int num_allocs; - static char pool_name[20]; - - d->ohci = ohci; - d->type = type; - d->ctx = ctx; - - d->num_desc = num_desc; - d->buf_size = buf_size; - d->split_buf_size = split_buf_size; - - d->ctrlSet = 0; - d->ctrlClear = 0; - d->cmdPtr = 0; - - d->buf_cpu = kzalloc(d->num_desc * sizeof(*d->buf_cpu), GFP_ATOMIC); - d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC); - - if (d->buf_cpu == NULL || d->buf_bus == NULL) { - PRINT(KERN_ERR, "Failed to allocate %s", "DMA buffer"); - free_dma_rcv_ctx(d); - return -ENOMEM; - } - - d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_ATOMIC); - d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC); - - if (d->prg_cpu == NULL || d->prg_bus == NULL) { - PRINT(KERN_ERR, "Failed to allocate %s", "DMA prg"); - free_dma_rcv_ctx(d); - return -ENOMEM; - } - - d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC); - - if (d->spb == NULL) { - PRINT(KERN_ERR, "Failed to allocate %s", "split buffer"); - free_dma_rcv_ctx(d); - return -ENOMEM; - } - - len = sprintf(pool_name, "ohci1394_rcv_prg"); - sprintf(pool_name+len, "%d", num_allocs); - d->prg_pool = pci_pool_create(pool_name, ohci->dev, - sizeof(struct dma_cmd), 4, 0); - if(d->prg_pool == NULL) - { - PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name); - free_dma_rcv_ctx(d); - return -ENOMEM; - } - num_allocs++; - - for (i=0; i<d->num_desc; i++) { - d->buf_cpu[i] = pci_alloc_consistent(ohci->dev, - d->buf_size, - d->buf_bus+i); - - if (d->buf_cpu[i] != NULL) { - memset(d->buf_cpu[i], 0, d->buf_size); - } else { - PRINT(KERN_ERR, - "Failed to allocate %s", "DMA buffer"); - free_dma_rcv_ctx(d); - return -ENOMEM; - } - - d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i); - - if (d->prg_cpu[i] != NULL) { - memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd)); - } else { - PRINT(KERN_ERR, - "Failed to allocate %s", "DMA prg"); - free_dma_rcv_ctx(d); - return -ENOMEM; - } - } - - spin_lock_init(&d->lock); - - d->ctrlSet = context_base + OHCI1394_ContextControlSet; - d->ctrlClear = context_base + OHCI1394_ContextControlClear; - d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; - - tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d); - return 0; -} - -static void free_dma_trm_ctx(struct dma_trm_ctx *d) -{ - int i; - struct ti_ohci *ohci = d->ohci; - - if (ohci == NULL) - return; - - DBGMSG("Freeing dma_trm_ctx %d", d->ctx); - - if (d->prg_cpu) { - for (i=0; i<d->num_desc; i++) - if (d->prg_cpu[i] && d->prg_bus[i]) - pci_pool_free(d->prg_pool, d->prg_cpu[i], - d->prg_bus[i]); - pci_pool_destroy(d->prg_pool); - kfree(d->prg_cpu); - kfree(d->prg_bus); - } - - /* Mark this context as freed. */ - d->ohci = NULL; -} - -static int -alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d, - enum context_type type, int ctx, int num_desc, - int context_base) -{ - int i, len; - static char pool_name[20]; - static int num_allocs=0; - - d->ohci = ohci; - d->type = type; - d->ctx = ctx; - d->num_desc = num_desc; - d->ctrlSet = 0; - d->ctrlClear = 0; - d->cmdPtr = 0; - - d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_KERNEL); - d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL); - - if (d->prg_cpu == NULL || d->prg_bus == NULL) { - PRINT(KERN_ERR, "Failed to allocate %s", "AT DMA prg"); - free_dma_trm_ctx(d); - return -ENOMEM; - } - - len = sprintf(pool_name, "ohci1394_trm_prg"); - sprintf(pool_name+len, "%d", num_allocs); - d->prg_pool = pci_pool_create(pool_name, ohci->dev, - sizeof(struct at_dma_prg), 4, 0); - if (d->prg_pool == NULL) { - PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name); - free_dma_trm_ctx(d); - return -ENOMEM; - } - num_allocs++; - - for (i = 0; i < d->num_desc; i++) { - d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i); - - if (d->prg_cpu[i] != NULL) { - memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg)); - } else { - PRINT(KERN_ERR, - "Failed to allocate %s", "AT DMA prg"); - free_dma_trm_ctx(d); - return -ENOMEM; - } - } - - spin_lock_init(&d->lock); - - /* initialize tasklet */ - d->ctrlSet = context_base + OHCI1394_ContextControlSet; - d->ctrlClear = context_base + OHCI1394_ContextControlClear; - d->cmdPtr = context_base + OHCI1394_ContextCommandPtr; - tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d); - return 0; -} - -static void ohci_set_hw_config_rom(struct hpsb_host *host, __be32 *config_rom) -{ - struct ti_ohci *ohci = host->hostdata; - - reg_write(ohci, OHCI1394_ConfigROMhdr, be32_to_cpu(config_rom[0])); - reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(config_rom[2])); - - memcpy(ohci->csr_config_rom_cpu, config_rom, OHCI_CONFIG_ROM_LEN); -} - - -static quadlet_t ohci_hw_csr_reg(struct hpsb_host *host, int reg, - quadlet_t data, quadlet_t compare) -{ - struct ti_ohci *ohci = host->hostdata; - int i; - - reg_write(ohci, OHCI1394_CSRData, data); - reg_write(ohci, OHCI1394_CSRCompareData, compare); - reg_write(ohci, OHCI1394_CSRControl, reg & 0x3); - - for (i = 0; i < OHCI_LOOP_COUNT; i++) { - if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) - break; - - mdelay(1); - } - - return reg_read(ohci, OHCI1394_CSRData); -} - -static struct hpsb_host_driver ohci1394_driver = { - .owner = THIS_MODULE, - .name = OHCI1394_DRIVER_NAME, - .set_hw_config_rom = ohci_set_hw_config_rom, - .transmit_packet = ohci_transmit, - .devctl = ohci_devctl, - .isoctl = ohci_isoctl, - .hw_csr_reg = ohci_hw_csr_reg, -}; - -/*********************************** - * PCI Driver Interface functions * - ***********************************/ - -#ifdef CONFIG_PPC_PMAC -static void ohci1394_pmac_on(struct pci_dev *dev) -{ - if (machine_is(powermac)) { - struct device_node *ofn = pci_device_to_OF_node(dev); - - if (ofn) { - pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1); - pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1); - } - } -} - -static void ohci1394_pmac_off(struct pci_dev *dev) -{ - if (machine_is(powermac)) { - struct device_node *ofn = pci_device_to_OF_node(dev); - - if (ofn) { - pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0); - pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0); - } - } -} -#else -#define ohci1394_pmac_on(dev) -#define ohci1394_pmac_off(dev) -#endif /* CONFIG_PPC_PMAC */ - -static int __devinit ohci1394_pci_probe(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - struct hpsb_host *host; - struct ti_ohci *ohci; /* shortcut to currently handled device */ - resource_size_t ohci_base; - int err = -ENOMEM; - - ohci1394_pmac_on(dev); - if (pci_enable_device(dev)) { - PRINT_G(KERN_ERR, "Failed to enable OHCI hardware"); - err = -ENXIO; - goto err; - } - pci_set_master(dev); - - host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci), &dev->dev); - if (!host) { - PRINT_G(KERN_ERR, "Failed to allocate %s", "host structure"); - goto err; - } - ohci = host->hostdata; - ohci->dev = dev; - ohci->host = host; - ohci->init_state = OHCI_INIT_ALLOC_HOST; - host->pdev = dev; - pci_set_drvdata(dev, ohci); - - /* We don't want hardware swapping */ - pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0); - - /* Some oddball Apple controllers do not order the selfid - * properly, so we make up for it here. */ -#ifndef __LITTLE_ENDIAN - /* XXX: Need a better way to check this. I'm wondering if we can - * read the values of the OHCI1394_PCI_HCI_Control and the - * noByteSwapData registers to see if they were not cleared to - * zero. Should this work? Obviously it's not defined what these - * registers will read when they aren't supported. Bleh! */ - if (dev->vendor == PCI_VENDOR_ID_APPLE && - dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) { - ohci->no_swap_incoming = 1; - ohci->selfid_swap = 0; - } else - ohci->selfid_swap = 1; -#endif - - -#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_FW -#define PCI_DEVICE_ID_NVIDIA_NFORCE2_FW 0x006e -#endif - - /* These chipsets require a bit of extra care when checking after - * a busreset. */ - if ((dev->vendor == PCI_VENDOR_ID_APPLE && - dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) || - (dev->vendor == PCI_VENDOR_ID_NVIDIA && - dev->device == PCI_DEVICE_ID_NVIDIA_NFORCE2_FW)) - ohci->check_busreset = 1; - - /* We hardwire the MMIO length, since some CardBus adaptors - * fail to report the right length. Anyway, the ohci spec - * clearly says it's 2kb, so this shouldn't be a problem. */ - ohci_base = pci_resource_start(dev, 0); - if (pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE) - PRINT(KERN_WARNING, "PCI resource length of 0x%llx too small!", - (unsigned long long)pci_resource_len(dev, 0)); - - if (!request_mem_region(ohci_base, OHCI1394_REGISTER_SIZE, - OHCI1394_DRIVER_NAME)) { - PRINT_G(KERN_ERR, "MMIO resource (0x%llx - 0x%llx) unavailable", - (unsigned long long)ohci_base, - (unsigned long long)ohci_base + OHCI1394_REGISTER_SIZE); - goto err; - } - ohci->init_state = OHCI_INIT_HAVE_MEM_REGION; - - ohci->registers = ioremap(ohci_base, OHCI1394_REGISTER_SIZE); - if (ohci->registers == NULL) { - PRINT_G(KERN_ERR, "Failed to remap registers"); - err = -ENXIO; - goto err; - } - ohci->init_state = OHCI_INIT_HAVE_IOMAPPING; - DBGMSG("Remapped memory spaces reg 0x%p", ohci->registers); - - /* csr_config rom allocation */ - ohci->csr_config_rom_cpu = - pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN, - &ohci->csr_config_rom_bus); - if (ohci->csr_config_rom_cpu == NULL) { - PRINT_G(KERN_ERR, "Failed to allocate %s", "buffer config rom"); - goto err; - } - ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER; - - /* self-id dma buffer allocation */ - ohci->selfid_buf_cpu = - pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE, - &ohci->selfid_buf_bus); - if (ohci->selfid_buf_cpu == NULL) { - PRINT_G(KERN_ERR, "Failed to allocate %s", "self-ID buffer"); - goto err; - } - ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER; - - if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff) - PRINT(KERN_INFO, "SelfID buffer %p is not aligned on " - "8Kb boundary... may cause problems on some CXD3222 chip", - ohci->selfid_buf_cpu); - - /* No self-id errors at startup */ - ohci->self_id_errors = 0; - - ohci->init_state = OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE; - /* AR DMA request context allocation */ - if (alloc_dma_rcv_ctx(ohci, &ohci->ar_req_context, - DMA_CTX_ASYNC_REQ, 0, AR_REQ_NUM_DESC, - AR_REQ_BUF_SIZE, AR_REQ_SPLIT_BUF_SIZE, - OHCI1394_AsReqRcvContextBase) < 0) { - PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Req context"); - goto err; - } - /* AR DMA response context allocation */ - if (alloc_dma_rcv_ctx(ohci, &ohci->ar_resp_context, - DMA_CTX_ASYNC_RESP, 0, AR_RESP_NUM_DESC, - AR_RESP_BUF_SIZE, AR_RESP_SPLIT_BUF_SIZE, - OHCI1394_AsRspRcvContextBase) < 0) { - PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Resp context"); - goto err; - } - /* AT DMA request context */ - if (alloc_dma_trm_ctx(ohci, &ohci->at_req_context, - DMA_CTX_ASYNC_REQ, 0, AT_REQ_NUM_DESC, - OHCI1394_AsReqTrContextBase) < 0) { - PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Req context"); - goto err; - } - /* AT DMA response context */ - if (alloc_dma_trm_ctx(ohci, &ohci->at_resp_context, - DMA_CTX_ASYNC_RESP, 1, AT_RESP_NUM_DESC, - OHCI1394_AsRspTrContextBase) < 0) { - PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Resp context"); - goto err; - } - /* Start off with a soft reset, to clear everything to a sane - * state. */ - ohci_soft_reset(ohci); - - /* Now enable LPS, which we need in order to start accessing - * most of the registers. In fact, on some cards (ALI M5251), - * accessing registers in the SClk domain without LPS enabled - * will lock up the machine. */ - reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); - - /* Disable and clear interrupts */ - reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); - reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); - - /* Flush MMIO writes and wait to make sure we have full link enabled. */ - reg_read(ohci, OHCI1394_Version); - msleep(50); - - /* Determine the number of available IR and IT contexts. */ - ohci->nb_iso_rcv_ctx = - get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet); - ohci->nb_iso_xmit_ctx = - get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet); - - /* Set the usage bits for non-existent contexts so they can't - * be allocated */ - ohci->ir_ctx_usage = ~0 << ohci->nb_iso_rcv_ctx; - ohci->it_ctx_usage = ~0 << ohci->nb_iso_xmit_ctx; - - INIT_LIST_HEAD(&ohci->iso_tasklet_list); - spin_lock_init(&ohci->iso_tasklet_list_lock); - ohci->ISO_channel_usage = 0; - spin_lock_init(&ohci->IR_channel_lock); - - spin_lock_init(&ohci->event_lock); - - /* - * interrupts are disabled, all right, but... due to IRQF_SHARED we - * might get called anyway. We'll see no event, of course, but - * we need to get to that "no event", so enough should be initialized - * by that point. - */ - err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED, - OHCI1394_DRIVER_NAME, ohci); - if (err) { - PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq); - goto err; - } - ohci->init_state = OHCI_INIT_HAVE_IRQ; - ohci_initialize(ohci); - - /* Set certain csr values */ - host->csr.guid_hi = reg_read(ohci, OHCI1394_GUIDHi); - host->csr.guid_lo = reg_read(ohci, OHCI1394_GUIDLo); - host->csr.cyc_clk_acc = 100; /* how do we determine clk accuracy? */ - host->csr.max_rec = (reg_read(ohci, OHCI1394_BusOptions) >> 12) & 0xf; - host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7; - - if (phys_dma) { - host->low_addr_space = - (u64) reg_read(ohci, OHCI1394_PhyUpperBound) << 16; - if (!host->low_addr_space) - host->low_addr_space = OHCI1394_PHYS_UPPER_BOUND_FIXED; - } - host->middle_addr_space = OHCI1394_MIDDLE_ADDRESS_SPACE; - - /* Tell the highlevel this host is ready */ - if (hpsb_add_host(host)) { - PRINT_G(KERN_ERR, "Failed to register host with highlevel"); - goto err; - } - ohci->init_state = OHCI_INIT_DONE; - - return 0; -err: - ohci1394_pci_remove(dev); - return err; -} - -static void ohci1394_pci_remove(struct pci_dev *dev) -{ - struct ti_ohci *ohci; - struct device *device; - - ohci = pci_get_drvdata(dev); - if (!ohci) - goto out; - - device = get_device(&ohci->host->device); - - switch (ohci->init_state) { - case OHCI_INIT_DONE: - hpsb_remove_host(ohci->host); - - /* Clear out BUS Options */ - reg_write(ohci, OHCI1394_ConfigROMhdr, 0); - reg_write(ohci, OHCI1394_BusOptions, - (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) | - 0x00ff0000); - memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN); - - case OHCI_INIT_HAVE_IRQ: - /* Clear interrupt registers */ - reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); - reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); - - /* Disable IRM Contender */ - set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4)); - - /* Clear link control register */ - reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); - - /* Let all other nodes know to ignore us */ - ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); - - /* Soft reset before we start - this disables - * interrupts and clears linkEnable and LPS. */ - ohci_soft_reset(ohci); - free_irq(dev->irq, ohci); - - case OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE: - /* The ohci_soft_reset() stops all DMA contexts, so we - * dont need to do this. */ - free_dma_rcv_ctx(&ohci->ar_req_context); - free_dma_rcv_ctx(&ohci->ar_resp_context); - free_dma_trm_ctx(&ohci->at_req_context); - free_dma_trm_ctx(&ohci->at_resp_context); - - case OHCI_INIT_HAVE_SELFID_BUFFER: - pci_free_consistent(dev, OHCI1394_SI_DMA_BUF_SIZE, - ohci->selfid_buf_cpu, - ohci->selfid_buf_bus); - - case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER: - pci_free_consistent(dev, OHCI_CONFIG_ROM_LEN, - ohci->csr_config_rom_cpu, - ohci->csr_config_rom_bus); - - case OHCI_INIT_HAVE_IOMAPPING: - iounmap(ohci->registers); - - case OHCI_INIT_HAVE_MEM_REGION: - release_mem_region(pci_resource_start(dev, 0), - OHCI1394_REGISTER_SIZE); - - case OHCI_INIT_ALLOC_HOST: - pci_set_drvdata(dev, NULL); - } - - if (device) - put_device(device); -out: - ohci1394_pmac_off(dev); -} - -#ifdef CONFIG_PM -static int ohci1394_pci_suspend(struct pci_dev *dev, pm_message_t state) -{ - int err; - struct ti_ohci *ohci = pci_get_drvdata(dev); - - if (!ohci) { - printk(KERN_ERR "%s: tried to suspend nonexisting host\n", - OHCI1394_DRIVER_NAME); - return -ENXIO; - } - DBGMSG("suspend called"); - - /* Clear the async DMA contexts and stop using the controller */ - hpsb_bus_reset(ohci->host); - - /* See ohci1394_pci_remove() for comments on this sequence */ - reg_write(ohci, OHCI1394_ConfigROMhdr, 0); - reg_write(ohci, OHCI1394_BusOptions, - (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) | - 0x00ff0000); - reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); - reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff); - reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff); - set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4)); - reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff); - ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); - ohci_soft_reset(ohci); - - free_irq(dev->irq, ohci); - err = pci_save_state(dev); - if (err) { - PRINT(KERN_ERR, "pci_save_state failed with %d", err); - return err; - } - err = pci_set_power_state(dev, pci_choose_state(dev, state)); - if (err) - DBGMSG("pci_set_power_state failed with %d", err); - ohci1394_pmac_off(dev); - - return 0; -} - -static int ohci1394_pci_resume(struct pci_dev *dev) -{ - int err; - struct ti_ohci *ohci = pci_get_drvdata(dev); - - if (!ohci) { - printk(KERN_ERR "%s: tried to resume nonexisting host\n", - OHCI1394_DRIVER_NAME); - return -ENXIO; - } - DBGMSG("resume called"); - - ohci1394_pmac_on(dev); - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - err = pci_enable_device(dev); - if (err) { - PRINT(KERN_ERR, "pci_enable_device failed with %d", err); - return err; - } - - /* See ohci1394_pci_probe() for comments on this sequence */ - ohci_soft_reset(ohci); - reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS); - reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff); - reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff); - reg_read(ohci, OHCI1394_Version); - msleep(50); - - err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED, - OHCI1394_DRIVER_NAME, ohci); - if (err) { - PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq); - return err; - } - - ohci_initialize(ohci); - - hpsb_resume_host(ohci->host); - return 0; -} -#endif /* CONFIG_PM */ - -static struct pci_device_id ohci1394_pci_tbl[] = { - { - .class = PCI_CLASS_SERIAL_FIREWIRE_OHCI, - .class_mask = PCI_ANY_ID, - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { 0, }, -}; - -MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl); - -static struct pci_driver ohci1394_pci_driver = { - .name = OHCI1394_DRIVER_NAME, - .id_table = ohci1394_pci_tbl, - .probe = ohci1394_pci_probe, - .remove = ohci1394_pci_remove, -#ifdef CONFIG_PM - .resume = ohci1394_pci_resume, - .suspend = ohci1394_pci_suspend, -#endif -}; - -/*********************************** - * OHCI1394 Video Interface * - ***********************************/ - -/* essentially the only purpose of this code is to allow another - module to hook into ohci's interrupt handler */ - -/* returns zero if successful, one if DMA context is locked up */ -int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg) -{ - int i=0; - - /* stop the channel program if it's still running */ - reg_write(ohci, reg, 0x8000); - - /* Wait until it effectively stops */ - while (reg_read(ohci, reg) & 0x400) { - i++; - if (i>5000) { - PRINT(KERN_ERR, - "Runaway loop while stopping context: %s...", msg ? msg : ""); - return 1; - } - - mb(); - udelay(10); - } - if (msg) PRINT(KERN_ERR, "%s: dma prg stopped", msg); - return 0; -} - -void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet, int type, - void (*func)(unsigned long), unsigned long data) -{ - tasklet_init(&tasklet->tasklet, func, data); - tasklet->type = type; - /* We init the tasklet->link field, so we can list_del() it - * without worrying whether it was added to the list or not. */ - INIT_LIST_HEAD(&tasklet->link); -} - -int ohci1394_register_iso_tasklet(struct ti_ohci *ohci, - struct ohci1394_iso_tasklet *tasklet) -{ - unsigned long flags, *usage; - int n, i, r = -EBUSY; - - if (tasklet->type == OHCI_ISO_TRANSMIT) { - n = ohci->nb_iso_xmit_ctx; - usage = &ohci->it_ctx_usage; - } - else { - n = ohci->nb_iso_rcv_ctx; - usage = &ohci->ir_ctx_usage; - - /* only one receive context can be multichannel (OHCI sec 10.4.1) */ - if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { - if (test_and_set_bit(0, &ohci->ir_multichannel_used)) { - return r; - } - } - } - - spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags); - - for (i = 0; i < n; i++) - if (!test_and_set_bit(i, usage)) { - tasklet->context = i; - list_add_tail(&tasklet->link, &ohci->iso_tasklet_list); - r = 0; - break; - } - - spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags); - - return r; -} - -void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci, - struct ohci1394_iso_tasklet *tasklet) -{ - unsigned long flags; - - tasklet_kill(&tasklet->tasklet); - - spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags); - - if (tasklet->type == OHCI_ISO_TRANSMIT) - clear_bit(tasklet->context, &ohci->it_ctx_usage); - else { - clear_bit(tasklet->context, &ohci->ir_ctx_usage); - - if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { - clear_bit(0, &ohci->ir_multichannel_used); - } - } - - list_del(&tasklet->link); - - spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags); -} - -EXPORT_SYMBOL(ohci1394_stop_context); -EXPORT_SYMBOL(ohci1394_init_iso_tasklet); -EXPORT_SYMBOL(ohci1394_register_iso_tasklet); -EXPORT_SYMBOL(ohci1394_unregister_iso_tasklet); - -/*********************************** - * General module initialization * - ***********************************/ - -MODULE_AUTHOR("Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>"); -MODULE_DESCRIPTION("Driver for PCI OHCI IEEE-1394 controllers"); -MODULE_LICENSE("GPL"); - -static void __exit ohci1394_cleanup (void) -{ - pci_unregister_driver(&ohci1394_pci_driver); -} - -static int __init ohci1394_init(void) -{ - return pci_register_driver(&ohci1394_pci_driver); -} - -module_init(ohci1394_init); -module_exit(ohci1394_cleanup); diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h deleted file mode 100644 index 7fb8ab9..0000000 --- a/drivers/ieee1394/ohci1394.h +++ /dev/null @@ -1,453 +0,0 @@ -/* - * ohci1394.h - driver for OHCI 1394 boards - * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au> - * Gord Peters <GordPeters@smarttech.com> - * - * 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 _OHCI1394_H -#define _OHCI1394_H - -#include "ieee1394_types.h" -#include <asm/io.h> - -#define OHCI1394_DRIVER_NAME "ohci1394" - -#define OHCI1394_MAX_AT_REQ_RETRIES 0xf -#define OHCI1394_MAX_AT_RESP_RETRIES 0x2 -#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8 -#define OHCI1394_MAX_SELF_ID_ERRORS 16 - -#define AR_REQ_NUM_DESC 4 /* number of AR req descriptors */ -#define AR_REQ_BUF_SIZE PAGE_SIZE /* size of AR req buffers */ -#define AR_REQ_SPLIT_BUF_SIZE PAGE_SIZE /* split packet buffer */ - -#define AR_RESP_NUM_DESC 4 /* number of AR resp descriptors */ -#define AR_RESP_BUF_SIZE PAGE_SIZE /* size of AR resp buffers */ -#define AR_RESP_SPLIT_BUF_SIZE PAGE_SIZE /* split packet buffer */ - -#define IR_NUM_DESC 16 /* number of IR descriptors */ -#define IR_BUF_SIZE PAGE_SIZE /* 4096 bytes/buffer */ -#define IR_SPLIT_BUF_SIZE PAGE_SIZE /* split packet buffer */ - -#define IT_NUM_DESC 16 /* number of IT descriptors */ - -#define AT_REQ_NUM_DESC 32 /* number of AT req descriptors */ -#define AT_RESP_NUM_DESC 32 /* number of AT resp descriptors */ - -#define OHCI_LOOP_COUNT 100 /* Number of loops for reg read waits */ - -#define OHCI_CONFIG_ROM_LEN 1024 /* Length of the mapped configrom space */ - -#define OHCI1394_SI_DMA_BUF_SIZE 8192 /* length of the selfid buffer */ - -/* PCI configuration space addresses */ -#define OHCI1394_PCI_HCI_Control 0x40 - -struct dma_cmd { - u32 control; - u32 address; - u32 branchAddress; - u32 status; -}; - -/* - * FIXME: - * It is important that a single at_dma_prg does not cross a page boundary - * The proper way to do it would be to do the check dynamically as the - * programs are inserted into the AT fifo. - */ -struct at_dma_prg { - struct dma_cmd begin; - quadlet_t data[4]; - struct dma_cmd end; - quadlet_t pad[4]; /* FIXME: quick hack for memory alignment */ -}; - -/* identify whether a DMA context is asynchronous or isochronous */ -enum context_type { DMA_CTX_ASYNC_REQ, DMA_CTX_ASYNC_RESP, DMA_CTX_ISO }; - -/* DMA receive context */ -struct dma_rcv_ctx { - struct ti_ohci *ohci; - enum context_type type; - int ctx; - unsigned int num_desc; - - unsigned int buf_size; - unsigned int split_buf_size; - - /* dma block descriptors */ - struct dma_cmd **prg_cpu; - dma_addr_t *prg_bus; - struct pci_pool *prg_pool; - - /* dma buffers */ - quadlet_t **buf_cpu; - dma_addr_t *buf_bus; - - unsigned int buf_ind; - unsigned int buf_offset; - quadlet_t *spb; - spinlock_t lock; - struct tasklet_struct task; - int ctrlClear; - int ctrlSet; - int cmdPtr; - int ctxtMatch; -}; - -/* DMA transmit context */ -struct dma_trm_ctx { - struct ti_ohci *ohci; - enum context_type type; - int ctx; - unsigned int num_desc; - - /* dma block descriptors */ - struct at_dma_prg **prg_cpu; - dma_addr_t *prg_bus; - struct pci_pool *prg_pool; - - unsigned int prg_ind; - unsigned int sent_ind; - int free_prgs; - quadlet_t *branchAddrPtr; - - /* list of packets inserted in the AT FIFO */ - struct list_head fifo_list; - - /* list of pending packets to be inserted in the AT FIFO */ - struct list_head pending_list; - - spinlock_t lock; - struct tasklet_struct task; - int ctrlClear; - int ctrlSet; - int cmdPtr; -}; - -struct ohci1394_iso_tasklet { - struct tasklet_struct tasklet; - struct list_head link; - int context; - enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE, - OHCI_ISO_MULTICHANNEL_RECEIVE } type; -}; - -struct ti_ohci { - struct pci_dev *dev; - - enum { - OHCI_INIT_ALLOC_HOST, - OHCI_INIT_HAVE_MEM_REGION, - OHCI_INIT_HAVE_IOMAPPING, - OHCI_INIT_HAVE_CONFIG_ROM_BUFFER, - OHCI_INIT_HAVE_SELFID_BUFFER, - OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE, - OHCI_INIT_HAVE_IRQ, - OHCI_INIT_DONE, - } init_state; - - /* remapped memory spaces */ - void __iomem *registers; - - /* dma buffer for self-id packets */ - quadlet_t *selfid_buf_cpu; - dma_addr_t selfid_buf_bus; - - /* buffer for csr config rom */ - quadlet_t *csr_config_rom_cpu; - dma_addr_t csr_config_rom_bus; - int csr_config_rom_length; - - unsigned int max_packet_size; - - /* async receive */ - struct dma_rcv_ctx ar_resp_context; - struct dma_rcv_ctx ar_req_context; - - /* async transmit */ - struct dma_trm_ctx at_resp_context; - struct dma_trm_ctx at_req_context; - - /* iso receive */ - int nb_iso_rcv_ctx; - unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */ - unsigned long ir_multichannel_used; /* ditto */ - spinlock_t IR_channel_lock; - - /* iso transmit */ - int nb_iso_xmit_ctx; - unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */ - - u64 ISO_channel_usage; - - /* IEEE-1394 part follows */ - struct hpsb_host *host; - - int phyid, isroot; - - spinlock_t phy_reg_lock; - spinlock_t event_lock; - - int self_id_errors; - - /* Tasklets for iso receive and transmit, used by video1394 - * and dv1394 */ - struct list_head iso_tasklet_list; - spinlock_t iso_tasklet_list_lock; - - /* Swap the selfid buffer? */ - unsigned int selfid_swap:1; - /* Some Apple chipset seem to swap incoming headers for us */ - unsigned int no_swap_incoming:1; - - /* Force extra paranoia checking on bus-reset handling */ - unsigned int check_busreset:1; -}; - -static inline int cross_bound(unsigned long addr, unsigned int size) -{ - if (size == 0) - return 0; - - if (size > PAGE_SIZE) - return 1; - - if (addr >> PAGE_SHIFT != (addr + size - 1) >> PAGE_SHIFT) - return 1; - - return 0; -} - -/* - * Register read and write helper functions. - */ -static inline void reg_write(const struct ti_ohci *ohci, int offset, u32 data) -{ - writel(data, ohci->registers + offset); -} - -static inline u32 reg_read(const struct ti_ohci *ohci, int offset) -{ - return readl(ohci->registers + offset); -} - - -/* 2 KiloBytes of register space */ -#define OHCI1394_REGISTER_SIZE 0x800 - -/* Offsets relative to context bases defined below */ - -#define OHCI1394_ContextControlSet 0x000 -#define OHCI1394_ContextControlClear 0x004 -#define OHCI1394_ContextCommandPtr 0x00C - -/* register map */ -#define OHCI1394_Version 0x000 -#define OHCI1394_GUID_ROM 0x004 -#define OHCI1394_ATRetries 0x008 -#define OHCI1394_CSRData 0x00C -#define OHCI1394_CSRCompareData 0x010 -#define OHCI1394_CSRControl 0x014 -#define OHCI1394_ConfigROMhdr 0x018 -#define OHCI1394_BusID 0x01C -#define OHCI1394_BusOptions 0x020 -#define OHCI1394_GUIDHi 0x024 -#define OHCI1394_GUIDLo 0x028 -#define OHCI1394_ConfigROMmap 0x034 -#define OHCI1394_PostedWriteAddressLo 0x038 -#define OHCI1394_PostedWriteAddressHi 0x03C -#define OHCI1394_VendorID 0x040 -#define OHCI1394_HCControlSet 0x050 -#define OHCI1394_HCControlClear 0x054 -#define OHCI1394_HCControl_noByteSwap 0x40000000 -#define OHCI1394_HCControl_programPhyEnable 0x00800000 -#define OHCI1394_HCControl_aPhyEnhanceEnable 0x00400000 -#define OHCI1394_HCControl_LPS 0x00080000 -#define OHCI1394_HCControl_postedWriteEnable 0x00040000 -#define OHCI1394_HCControl_linkEnable 0x00020000 -#define OHCI1394_HCControl_softReset 0x00010000 -#define OHCI1394_SelfIDBuffer 0x064 -#define OHCI1394_SelfIDCount 0x068 -#define OHCI1394_IRMultiChanMaskHiSet 0x070 -#define OHCI1394_IRMultiChanMaskHiClear 0x074 -#define OHCI1394_IRMultiChanMaskLoSet 0x078 -#define OHCI1394_IRMultiChanMaskLoClear 0x07C -#define OHCI1394_IntEventSet 0x080 -#define OHCI1394_IntEventClear 0x084 -#define OHCI1394_IntMaskSet 0x088 -#define OHCI1394_IntMaskClear 0x08C -#define OHCI1394_IsoXmitIntEventSet 0x090 -#define OHCI1394_IsoXmitIntEventClear 0x094 -#define OHCI1394_IsoXmitIntMaskSet 0x098 -#define OHCI1394_IsoXmitIntMaskClear 0x09C -#define OHCI1394_IsoRecvIntEventSet 0x0A0 -#define OHCI1394_IsoRecvIntEventClear 0x0A4 -#define OHCI1394_IsoRecvIntMaskSet 0x0A8 -#define OHCI1394_IsoRecvIntMaskClear 0x0AC -#define OHCI1394_InitialBandwidthAvailable 0x0B0 -#define OHCI1394_InitialChannelsAvailableHi 0x0B4 -#define OHCI1394_InitialChannelsAvailableLo 0x0B8 -#define OHCI1394_FairnessControl 0x0DC -#define OHCI1394_LinkControlSet 0x0E0 -#define OHCI1394_LinkControlClear 0x0E4 -#define OHCI1394_LinkControl_RcvSelfID 0x00000200 -#define OHCI1394_LinkControl_RcvPhyPkt 0x00000400 -#define OHCI1394_LinkControl_CycleTimerEnable 0x00100000 -#define OHCI1394_LinkControl_CycleMaster 0x00200000 -#define OHCI1394_LinkControl_CycleSource 0x00400000 -#define OHCI1394_NodeID 0x0E8 -#define OHCI1394_PhyControl 0x0EC -#define OHCI1394_IsochronousCycleTimer 0x0F0 -#define OHCI1394_AsReqFilterHiSet 0x100 -#define OHCI1394_AsReqFilterHiClear 0x104 -#define OHCI1394_AsReqFilterLoSet 0x108 -#define OHCI1394_AsReqFilterLoClear 0x10C -#define OHCI1394_PhyReqFilterHiSet 0x110 -#define OHCI1394_PhyReqFilterHiClear 0x114 -#define OHCI1394_PhyReqFilterLoSet 0x118 -#define OHCI1394_PhyReqFilterLoClear 0x11C -#define OHCI1394_PhyUpperBound 0x120 - -#define OHCI1394_AsReqTrContextBase 0x180 -#define OHCI1394_AsReqTrContextControlSet 0x180 -#define OHCI1394_AsReqTrContextControlClear 0x184 -#define OHCI1394_AsReqTrCommandPtr 0x18C - -#define OHCI1394_AsRspTrContextBase 0x1A0 -#define OHCI1394_AsRspTrContextControlSet 0x1A0 -#define OHCI1394_AsRspTrContextControlClear 0x1A4 -#define OHCI1394_AsRspTrCommandPtr 0x1AC - -#define OHCI1394_AsReqRcvContextBase 0x1C0 -#define OHCI1394_AsReqRcvContextControlSet 0x1C0 -#define OHCI1394_AsReqRcvContextControlClear 0x1C4 -#define OHCI1394_AsReqRcvCommandPtr 0x1CC - -#define OHCI1394_AsRspRcvContextBase 0x1E0 -#define OHCI1394_AsRspRcvContextControlSet 0x1E0 -#define OHCI1394_AsRspRcvContextControlClear 0x1E4 -#define OHCI1394_AsRspRcvCommandPtr 0x1EC - -/* Isochronous transmit registers */ -/* Add (16 * n) for context n */ -#define OHCI1394_IsoXmitContextBase 0x200 -#define OHCI1394_IsoXmitContextControlSet 0x200 -#define OHCI1394_IsoXmitContextControlClear 0x204 -#define OHCI1394_IsoXmitCommandPtr 0x20C - -/* Isochronous receive registers */ -/* Add (32 * n) for context n */ -#define OHCI1394_IsoRcvContextBase 0x400 -#define OHCI1394_IsoRcvContextControlSet 0x400 -#define OHCI1394_IsoRcvContextControlClear 0x404 -#define OHCI1394_IsoRcvCommandPtr 0x40C -#define OHCI1394_IsoRcvContextMatch 0x410 - -/* Interrupts Mask/Events */ - -#define OHCI1394_reqTxComplete 0x00000001 -#define OHCI1394_respTxComplete 0x00000002 -#define OHCI1394_ARRQ 0x00000004 -#define OHCI1394_ARRS 0x00000008 -#define OHCI1394_RQPkt 0x00000010 -#define OHCI1394_RSPkt 0x00000020 -#define OHCI1394_isochTx 0x00000040 -#define OHCI1394_isochRx 0x00000080 -#define OHCI1394_postedWriteErr 0x00000100 -#define OHCI1394_lockRespErr 0x00000200 -#define OHCI1394_selfIDComplete 0x00010000 -#define OHCI1394_busReset 0x00020000 -#define OHCI1394_phy 0x00080000 -#define OHCI1394_cycleSynch 0x00100000 -#define OHCI1394_cycle64Seconds 0x00200000 -#define OHCI1394_cycleLost 0x00400000 -#define OHCI1394_cycleInconsistent 0x00800000 -#define OHCI1394_unrecoverableError 0x01000000 -#define OHCI1394_cycleTooLong 0x02000000 -#define OHCI1394_phyRegRcvd 0x04000000 -#define OHCI1394_masterIntEnable 0x80000000 - -/* DMA Control flags */ -#define DMA_CTL_OUTPUT_MORE 0x00000000 -#define DMA_CTL_OUTPUT_LAST 0x10000000 -#define DMA_CTL_INPUT_MORE 0x20000000 -#define DMA_CTL_INPUT_LAST 0x30000000 -#define DMA_CTL_UPDATE 0x08000000 -#define DMA_CTL_IMMEDIATE 0x02000000 -#define DMA_CTL_IRQ 0x00300000 -#define DMA_CTL_BRANCH 0x000c0000 -#define DMA_CTL_WAIT 0x00030000 - -/* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */ -#define EVT_NO_STATUS 0x0 /* No event status */ -#define EVT_RESERVED_A 0x1 /* Reserved, not used !!! */ -#define EVT_LONG_PACKET 0x2 /* The revc data was longer than the buf */ -#define EVT_MISSING_ACK 0x3 /* A subaction gap was detected before an ack - arrived, or recv'd ack had a parity error */ -#define EVT_UNDERRUN 0x4 /* Underrun on corresponding FIFO, packet - truncated */ -#define EVT_OVERRUN 0x5 /* A recv FIFO overflowed on reception of ISO - packet */ -#define EVT_DESCRIPTOR_READ 0x6 /* An unrecoverable error occurred while host was - reading a descriptor block */ -#define EVT_DATA_READ 0x7 /* An error occurred while host controller was - attempting to read from host memory in the data - stage of descriptor processing */ -#define EVT_DATA_WRITE 0x8 /* An error occurred while host controller was - attempting to write either during the data stage - of descriptor processing, or when processing a single - 16-bit host memory write */ -#define EVT_BUS_RESET 0x9 /* Identifies a PHY packet in the recv buffer as - being a synthesized bus reset packet */ -#define EVT_TIMEOUT 0xa /* Indicates that the asynchronous transmit response - packet expired and was not transmitted, or that an - IT DMA context experienced a skip processing overflow */ -#define EVT_TCODE_ERR 0xb /* A bad tCode is associated with this packet. - The packet was flushed */ -#define EVT_RESERVED_B 0xc /* Reserved, not used !!! */ -#define EVT_RESERVED_C 0xd /* Reserved, not used !!! */ -#define EVT_UNKNOWN 0xe /* An error condition has occurred that cannot be - represented by any other event codes defined herein. */ -#define EVT_FLUSHED 0xf /* Send by the link side of output FIFO when asynchronous - packets are being flushed due to a bus reset. */ - -#define OHCI1394_TCODE_PHY 0xE - -/* Node offset map (phys DMA area, posted write area). - * The value of OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED may be modified but must - * be lower than OHCI1394_MIDDLE_ADDRESS_SPACE. - * OHCI1394_PHYS_UPPER_BOUND_FIXED and OHCI1394_MIDDLE_ADDRESS_SPACE are - * constants given by the OHCI spec. - */ -#define OHCI1394_PHYS_UPPER_BOUND_FIXED 0x000100000000ULL /* 4 GB */ -#define OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED 0x010000000000ULL /* 1 TB */ -#define OHCI1394_MIDDLE_ADDRESS_SPACE 0xffff00000000ULL - -void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet, - int type, - void (*func)(unsigned long), - unsigned long data); -int ohci1394_register_iso_tasklet(struct ti_ohci *ohci, - struct ohci1394_iso_tasklet *tasklet); -void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci, - struct ohci1394_iso_tasklet *tasklet); -int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg); -struct ti_ohci *ohci1394_get_struct(int card_num); - -#endif diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c deleted file mode 100644 index bf47fee..0000000 --- a/drivers/ieee1394/pcilynx.c +++ /dev/null @@ -1,1554 +0,0 @@ -/* - * pcilynx.c - Texas Instruments PCILynx driver - * Copyright (C) 1999,2000 Andreas Bombe <andreas.bombe@munich.netsurf.de>, - * Stephan Linz <linz@mazet.de> - * Manfred Weihs <weihs@ict.tuwien.ac.at> - * - * 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. - */ - -/* - * Contributions: - * - * Manfred Weihs <weihs@ict.tuwien.ac.at> - * reading bus info block (containing GUID) from serial - * eeprom via i2c and storing it in config ROM - * Reworked code for initiating bus resets - * (long, short, with or without hold-off) - * Enhancements in async and iso send code - */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/fs.h> -#include <linux/poll.h> -#include <linux/kdev_t.h> -#include <linux/dma-mapping.h> -#include <asm/byteorder.h> -#include <asm/atomic.h> -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/irq.h> - -#include "csr1212.h" -#include "ieee1394.h" -#include "ieee1394_types.h" -#include "hosts.h" -#include "ieee1394_core.h" -#include "highlevel.h" -#include "pcilynx.h" - -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> - -/* print general (card independent) information */ -#define PRINT_G(level, fmt, args...) printk(level "pcilynx: " fmt "\n" , ## args) -/* print card specific information */ -#define PRINT(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args) - -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG -#define PRINT_GD(level, fmt, args...) printk(level "pcilynx: " fmt "\n" , ## args) -#define PRINTD(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args) -#else -#define PRINT_GD(level, fmt, args...) do {} while (0) -#define PRINTD(level, card, fmt, args...) do {} while (0) -#endif - - -/* Module Parameters */ -static int skip_eeprom; -module_param(skip_eeprom, int, 0444); -MODULE_PARM_DESC(skip_eeprom, "Use generic bus info block instead of serial eeprom (default = 0)."); - - -static struct hpsb_host_driver lynx_driver; -static unsigned int card_id; - - - -/* - * I2C stuff - */ - -/* the i2c stuff was inspired by i2c-philips-par.c */ - -static void bit_setscl(void *data, int state) -{ - if (state) { - ((struct ti_lynx *) data)->i2c_driven_state |= 0x00000040; - } else { - ((struct ti_lynx *) data)->i2c_driven_state &= ~0x00000040; - } - reg_write((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL, ((struct ti_lynx *) data)->i2c_driven_state); -} - -static void bit_setsda(void *data, int state) -{ - if (state) { - ((struct ti_lynx *) data)->i2c_driven_state |= 0x00000010; - } else { - ((struct ti_lynx *) data)->i2c_driven_state &= ~0x00000010; - } - reg_write((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL, ((struct ti_lynx *) data)->i2c_driven_state); -} - -static int bit_getscl(void *data) -{ - return reg_read((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL) & 0x00000040; -} - -static int bit_getsda(void *data) -{ - return reg_read((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL) & 0x00000010; -} - -static struct i2c_algo_bit_data bit_data = { - .setsda = bit_setsda, - .setscl = bit_setscl, - .getsda = bit_getsda, - .getscl = bit_getscl, - .udelay = 5, - .timeout = 100, -}; - - -/* - * PCL handling functions. - */ - -static pcl_t alloc_pcl(struct ti_lynx *lynx) -{ - u8 m; - int i, j; - - spin_lock(&lynx->lock); - /* FIXME - use ffz() to make this readable */ - for (i = 0; i < (LOCALRAM_SIZE / 1024); i++) { - m = lynx->pcl_bmap[i]; - for (j = 0; j < 8; j++) { - if (m & 1<<j) { - continue; - } - m |= 1<<j; - lynx->pcl_bmap[i] = m; - spin_unlock(&lynx->lock); - return 8 * i + j; - } - } - spin_unlock(&lynx->lock); - - return -1; -} - - -#if 0 -static void free_pcl(struct ti_lynx *lynx, pcl_t pclid) -{ - int off, bit; - - off = pclid / 8; - bit = pclid % 8; - - if (pclid < 0) { - return; - } - - spin_lock(&lynx->lock); - if (lynx->pcl_bmap[off] & 1<<bit) { - lynx->pcl_bmap[off] &= ~(1<<bit); - } else { - PRINT(KERN_ERR, lynx->id, - "attempted to free unallocated PCL %d", pclid); - } - spin_unlock(&lynx->lock); -} - -/* functions useful for debugging */ -static void pretty_print_pcl(const struct ti_pcl *pcl) -{ - int i; - - printk("PCL next %08x, userdata %08x, status %08x, remtrans %08x, nextbuf %08x\n", - pcl->next, pcl->user_data, pcl->pcl_status, - pcl->remaining_transfer_count, pcl->next_data_buffer); - - printk("PCL"); - for (i=0; i<13; i++) { - printk(" c%x:%08x d%x:%08x", - i, pcl->buffer[i].control, i, pcl->buffer[i].pointer); - if (!(i & 0x3) && (i != 12)) printk("\nPCL"); - } - printk("\n"); -} - -static void print_pcl(const struct ti_lynx *lynx, pcl_t pclid) -{ - struct ti_pcl pcl; - - get_pcl(lynx, pclid, &pcl); - pretty_print_pcl(&pcl); -} -#endif - - - -/*********************************** - * IEEE-1394 functionality section * - ***********************************/ - - -static int get_phy_reg(struct ti_lynx *lynx, int addr) -{ - int retval; - int i = 0; - - unsigned long flags; - - if (addr > 15) { - PRINT(KERN_ERR, lynx->id, - "%s: PHY register address %d out of range", - __func__, addr); - return -1; - } - - spin_lock_irqsave(&lynx->phy_reg_lock, flags); - - reg_write(lynx, LINK_PHY, LINK_PHY_READ | LINK_PHY_ADDR(addr)); - do { - retval = reg_read(lynx, LINK_PHY); - - if (i > 10000) { - PRINT(KERN_ERR, lynx->id, "%s: runaway loop, aborting", - __func__); - retval = -1; - break; - } - i++; - } while ((retval & 0xf00) != LINK_PHY_RADDR(addr)); - - reg_write(lynx, LINK_INT_STATUS, LINK_INT_PHY_REG_RCVD); - spin_unlock_irqrestore(&lynx->phy_reg_lock, flags); - - if (retval != -1) { - return retval & 0xff; - } else { - return -1; - } -} - -static int set_phy_reg(struct ti_lynx *lynx, int addr, int val) -{ - unsigned long flags; - - if (addr > 15) { - PRINT(KERN_ERR, lynx->id, - "%s: PHY register address %d out of range", __func__, addr); - return -1; - } - - if (val > 0xff) { - PRINT(KERN_ERR, lynx->id, - "%s: PHY register value %d out of range", __func__, val); - return -1; - } - - spin_lock_irqsave(&lynx->phy_reg_lock, flags); - - reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | LINK_PHY_ADDR(addr) - | LINK_PHY_WDATA(val)); - - spin_unlock_irqrestore(&lynx->phy_reg_lock, flags); - - return 0; -} - -static int sel_phy_reg_page(struct ti_lynx *lynx, int page) -{ - int reg; - - if (page > 7) { - PRINT(KERN_ERR, lynx->id, - "%s: PHY page %d out of range", __func__, page); - return -1; - } - - reg = get_phy_reg(lynx, 7); - if (reg != -1) { - reg &= 0x1f; - reg |= (page << 5); - set_phy_reg(lynx, 7, reg); - return 0; - } else { - return -1; - } -} - -#if 0 /* not needed at this time */ -static int sel_phy_reg_port(struct ti_lynx *lynx, int port) -{ - int reg; - - if (port > 15) { - PRINT(KERN_ERR, lynx->id, - "%s: PHY port %d out of range", __func__, port); - return -1; - } - - reg = get_phy_reg(lynx, 7); - if (reg != -1) { - reg &= 0xf0; - reg |= port; - set_phy_reg(lynx, 7, reg); - return 0; - } else { - return -1; - } -} -#endif - -static u32 get_phy_vendorid(struct ti_lynx *lynx) -{ - u32 pvid = 0; - sel_phy_reg_page(lynx, 1); - pvid |= (get_phy_reg(lynx, 10) << 16); - pvid |= (get_phy_reg(lynx, 11) << 8); - pvid |= get_phy_reg(lynx, 12); - PRINT(KERN_INFO, lynx->id, "PHY vendor id 0x%06x", pvid); - return pvid; -} - -static u32 get_phy_productid(struct ti_lynx *lynx) -{ - u32 id = 0; - sel_phy_reg_page(lynx, 1); - id |= (get_phy_reg(lynx, 13) << 16); - id |= (get_phy_reg(lynx, 14) << 8); - id |= get_phy_reg(lynx, 15); - PRINT(KERN_INFO, lynx->id, "PHY product id 0x%06x", id); - return id; -} - -static quadlet_t generate_own_selfid(struct ti_lynx *lynx, - struct hpsb_host *host) -{ - quadlet_t lsid; - char phyreg[7]; - int i; - - phyreg[0] = lynx->phy_reg0; - for (i = 1; i < 7; i++) { - phyreg[i] = get_phy_reg(lynx, i); - } - - /* FIXME? We assume a TSB21LV03A phy here. This code doesn't support - more than 3 ports on the PHY anyway. */ - - lsid = 0x80400000 | ((phyreg[0] & 0xfc) << 22); - lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */ - lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */ - if (!hpsb_disable_irm) - lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */ - /* lsid |= 1 << 11; *//* set contender (hack) */ - lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */ - - for (i = 0; i < (phyreg[2] & 0xf); i++) { /* ports */ - if (phyreg[3 + i] & 0x4) { - lsid |= (((phyreg[3 + i] & 0x8) | 0x10) >> 3) - << (6 - i*2); - } else { - lsid |= 1 << (6 - i*2); - } - } - - cpu_to_be32s(&lsid); - PRINT(KERN_DEBUG, lynx->id, "generated own selfid 0x%x", lsid); - return lsid; -} - -static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host) -{ - quadlet_t *q = lynx->rcv_page; - int phyid, isroot, size; - quadlet_t lsid = 0; - int i; - - if (lynx->phy_reg0 == -1 || lynx->selfid_size == -1) return; - - size = lynx->selfid_size; - phyid = lynx->phy_reg0; - - i = (size > 16 ? 16 : size) / 4 - 1; - while (i >= 0) { - cpu_to_be32s(&q[i]); - i--; - } - - if (!lynx->phyic.reg_1394a) { - lsid = generate_own_selfid(lynx, host); - } - - isroot = (phyid & 2) != 0; - phyid >>= 2; - PRINT(KERN_INFO, lynx->id, "SelfID process finished (phyid %d, %s)", - phyid, (isroot ? "root" : "not root")); - reg_write(lynx, LINK_ID, (0xffc0 | phyid) << 16); - - if (!lynx->phyic.reg_1394a && !size) { - hpsb_selfid_received(host, lsid); - } - - while (size > 0) { - struct selfid *sid = (struct selfid *)q; - - if (!lynx->phyic.reg_1394a && !sid->extended - && (sid->phy_id == (phyid + 1))) { - hpsb_selfid_received(host, lsid); - } - - if (q[0] == ~q[1]) { - PRINT(KERN_DEBUG, lynx->id, "SelfID packet 0x%x rcvd", - q[0]); - hpsb_selfid_received(host, q[0]); - } else { - PRINT(KERN_INFO, lynx->id, - "inconsistent selfid 0x%x/0x%x", q[0], q[1]); - } - q += 2; - size -= 8; - } - - if (!lynx->phyic.reg_1394a && isroot && phyid != 0) { - hpsb_selfid_received(host, lsid); - } - - hpsb_selfid_complete(host, phyid, isroot); - - if (host->in_bus_reset) return; /* in bus reset again */ - - if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER); //FIXME: I do not think, we need this here - reg_set_bits(lynx, LINK_CONTROL, - LINK_CONTROL_RCV_CMP_VALID | LINK_CONTROL_TX_ASYNC_EN - | LINK_CONTROL_RX_ASYNC_EN | LINK_CONTROL_CYCTIMEREN); -} - - - -/* This must be called with the respective queue_lock held. */ -static void send_next(struct ti_lynx *lynx, int what) -{ - struct ti_pcl pcl; - struct lynx_send_data *d; - struct hpsb_packet *packet; - -#if 0 /* has been removed from ieee1394 core */ - d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async); -#else - d = &lynx->async; -#endif - if (!list_empty(&d->pcl_queue)) { - PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo"); - BUG(); - } - - packet = driver_packet(d->queue.next); - list_move_tail(&packet->driver_list, &d->pcl_queue); - - d->header_dma = pci_map_single(lynx->dev, packet->header, - packet->header_size, PCI_DMA_TODEVICE); - if (packet->data_size) { - d->data_dma = pci_map_single(lynx->dev, packet->data, - packet->data_size, - PCI_DMA_TODEVICE); - } else { - d->data_dma = 0; - } - - pcl.next = PCL_NEXT_INVALID; - pcl.async_error_next = PCL_NEXT_INVALID; - pcl.pcl_status = 0; - pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size; -#ifndef __BIG_ENDIAN - pcl.buffer[0].control |= PCL_BIGENDIAN; -#endif - pcl.buffer[0].pointer = d->header_dma; - pcl.buffer[1].control = PCL_LAST_BUFF | packet->data_size; - pcl.buffer[1].pointer = d->data_dma; - - switch (packet->type) { - case hpsb_async: - pcl.buffer[0].control |= PCL_CMD_XMT; - break; -#if 0 /* has been removed from ieee1394 core */ - case hpsb_iso: - pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE; - break; -#endif - case hpsb_raw: - pcl.buffer[0].control |= PCL_CMD_UNFXMT; - break; - } - - put_pcl(lynx, d->pcl, &pcl); - run_pcl(lynx, d->pcl_start, d->channel); -} - - -/* called from subsystem core */ -static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet) -{ - struct ti_lynx *lynx = host->hostdata; - struct lynx_send_data *d; - unsigned long flags; - - if (packet->data_size >= 4096) { - PRINT(KERN_ERR, lynx->id, "transmit packet data too big (%Zd)", - packet->data_size); - return -EOVERFLOW; - } - - switch (packet->type) { - case hpsb_async: - case hpsb_raw: - d = &lynx->async; - break; -#if 0 /* has been removed from ieee1394 core */ - case hpsb_iso: - d = &lynx->iso_send; - break; -#endif - default: - PRINT(KERN_ERR, lynx->id, "invalid packet type %d", - packet->type); - return -EINVAL; - } - - if (packet->tcode == TCODE_WRITEQ - || packet->tcode == TCODE_READQ_RESPONSE) { - cpu_to_be32s(&packet->header[3]); - } - - spin_lock_irqsave(&d->queue_lock, flags); - - list_add_tail(&packet->driver_list, &d->queue); - if (list_empty(&d->pcl_queue)) - send_next(lynx, packet->type); - - spin_unlock_irqrestore(&d->queue_lock, flags); - - return 0; -} - - -/* called from subsystem core */ -static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg) -{ - struct ti_lynx *lynx = host->hostdata; - int retval = 0; - struct hpsb_packet *packet; - LIST_HEAD(packet_list); - unsigned long flags; - int phy_reg; - - switch (cmd) { - case RESET_BUS: - if (reg_read(lynx, LINK_INT_STATUS) & LINK_INT_PHY_BUSRESET) { - retval = 0; - break; - } - - switch (arg) { - case SHORT_RESET: - if (lynx->phyic.reg_1394a) { - phy_reg = get_phy_reg(lynx, 5); - if (phy_reg == -1) { - PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); - retval = -1; - break; - } - phy_reg |= 0x40; - - PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset) on request"); - - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - set_phy_reg(lynx, 5, phy_reg); /* set ISBR */ - break; - } else { - PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy"); - /* fall through to long bus reset */ - } - case LONG_RESET: - phy_reg = get_phy_reg(lynx, 1); - if (phy_reg == -1) { - PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); - retval = -1; - break; - } - phy_reg |= 0x40; - - PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset) on request"); - - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */ - break; - case SHORT_RESET_NO_FORCE_ROOT: - if (lynx->phyic.reg_1394a) { - phy_reg = get_phy_reg(lynx, 1); - if (phy_reg == -1) { - PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); - retval = -1; - break; - } - if (phy_reg & 0x80) { - phy_reg &= ~0x80; - set_phy_reg(lynx, 1, phy_reg); /* clear RHB */ - } - - phy_reg = get_phy_reg(lynx, 5); - if (phy_reg == -1) { - PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); - retval = -1; - break; - } - phy_reg |= 0x40; - - PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, no force_root) on request"); - - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - set_phy_reg(lynx, 5, phy_reg); /* set ISBR */ - break; - } else { - PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy"); - /* fall through to long bus reset */ - } - case LONG_RESET_NO_FORCE_ROOT: - phy_reg = get_phy_reg(lynx, 1); - if (phy_reg == -1) { - PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); - retval = -1; - break; - } - phy_reg &= ~0x80; - phy_reg |= 0x40; - - PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, no force_root) on request"); - - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */ - break; - case SHORT_RESET_FORCE_ROOT: - if (lynx->phyic.reg_1394a) { - phy_reg = get_phy_reg(lynx, 1); - if (phy_reg == -1) { - PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); - retval = -1; - break; - } - if (!(phy_reg & 0x80)) { - phy_reg |= 0x80; - set_phy_reg(lynx, 1, phy_reg); /* set RHB */ - } - - phy_reg = get_phy_reg(lynx, 5); - if (phy_reg == -1) { - PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); - retval = -1; - break; - } - phy_reg |= 0x40; - - PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, force_root set) on request"); - - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - set_phy_reg(lynx, 5, phy_reg); /* set ISBR */ - break; - } else { - PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy"); - /* fall through to long bus reset */ - } - case LONG_RESET_FORCE_ROOT: - phy_reg = get_phy_reg(lynx, 1); - if (phy_reg == -1) { - PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); - retval = -1; - break; - } - phy_reg |= 0xc0; - - PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, force_root set) on request"); - - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - set_phy_reg(lynx, 1, phy_reg); /* set IBR and RHB */ - break; - default: - PRINT(KERN_ERR, lynx->id, "unknown argument for reset_bus command %d", arg); - retval = -1; - } - - break; - - case GET_CYCLE_COUNTER: - retval = reg_read(lynx, CYCLE_TIMER); - break; - - case SET_CYCLE_COUNTER: - reg_write(lynx, CYCLE_TIMER, arg); - break; - - case SET_BUS_ID: - reg_write(lynx, LINK_ID, - (arg << 22) | (reg_read(lynx, LINK_ID) & 0x003f0000)); - break; - - case ACT_CYCLE_MASTER: - if (arg) { - reg_set_bits(lynx, LINK_CONTROL, - LINK_CONTROL_CYCMASTER); - } else { - reg_clear_bits(lynx, LINK_CONTROL, - LINK_CONTROL_CYCMASTER); - } - break; - - case CANCEL_REQUESTS: - spin_lock_irqsave(&lynx->async.queue_lock, flags); - - reg_write(lynx, DMA_CHAN_CTRL(CHANNEL_ASYNC_SEND), 0); - list_splice_init(&lynx->async.queue, &packet_list); - - if (list_empty(&lynx->async.pcl_queue)) { - spin_unlock_irqrestore(&lynx->async.queue_lock, flags); - PRINTD(KERN_DEBUG, lynx->id, "no async packet in PCL to cancel"); - } else { - struct ti_pcl pcl; - u32 ack; - - PRINT(KERN_INFO, lynx->id, "cancelling async packet, that was already in PCL"); - - get_pcl(lynx, lynx->async.pcl, &pcl); - - packet = driver_packet(lynx->async.pcl_queue.next); - list_del_init(&packet->driver_list); - - pci_unmap_single(lynx->dev, lynx->async.header_dma, - packet->header_size, PCI_DMA_TODEVICE); - if (packet->data_size) { - pci_unmap_single(lynx->dev, lynx->async.data_dma, - packet->data_size, PCI_DMA_TODEVICE); - } - - spin_unlock_irqrestore(&lynx->async.queue_lock, flags); - - if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { - if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) { - ack = (pcl.pcl_status >> 15) & 0xf; - PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); - ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); - } else { - ack = (pcl.pcl_status >> 15) & 0xf; - } - } else { - PRINT(KERN_INFO, lynx->id, "async packet was not completed"); - ack = ACKX_ABORTED; - } - hpsb_packet_sent(host, packet, ack); - } - - while (!list_empty(&packet_list)) { - packet = driver_packet(packet_list.next); - list_del_init(&packet->driver_list); - hpsb_packet_sent(host, packet, ACKX_ABORTED); - } - - break; -#if 0 /* has been removed from ieee1394 core */ - case ISO_LISTEN_CHANNEL: - spin_lock_irqsave(&lynx->iso_rcv.lock, flags); - - if (lynx->iso_rcv.chan_count++ == 0) { - reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), - DMA_WORD1_CMP_ENABLE_MASTER); - } - - spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags); - break; - - case ISO_UNLISTEN_CHANNEL: - spin_lock_irqsave(&lynx->iso_rcv.lock, flags); - - if (--lynx->iso_rcv.chan_count == 0) { - reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), - 0); - } - - spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags); - break; -#endif - default: - PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd); - retval = -1; - } - - return retval; -} - - -/*************************************** - * IEEE-1394 functionality section END * - ***************************************/ - - -/******************************************************** - * Global stuff (interrupt handler, init/shutdown code) * - ********************************************************/ - - -static irqreturn_t lynx_irq_handler(int irq, void *dev_id) -{ - struct ti_lynx *lynx = (struct ti_lynx *)dev_id; - struct hpsb_host *host = lynx->host; - u32 intmask; - u32 linkint; - - linkint = reg_read(lynx, LINK_INT_STATUS); - intmask = reg_read(lynx, PCI_INT_STATUS); - - if (!(intmask & PCI_INT_INT_PEND)) - return IRQ_NONE; - - PRINTD(KERN_DEBUG, lynx->id, "interrupt: 0x%08x / 0x%08x", intmask, - linkint); - - reg_write(lynx, LINK_INT_STATUS, linkint); - reg_write(lynx, PCI_INT_STATUS, intmask); - - if (intmask & PCI_INT_1394) { - if (linkint & LINK_INT_PHY_TIMEOUT) { - PRINT(KERN_INFO, lynx->id, "PHY timeout occurred"); - } - if (linkint & LINK_INT_PHY_BUSRESET) { - PRINT(KERN_INFO, lynx->id, "bus reset interrupt"); - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - if (!host->in_bus_reset) - hpsb_bus_reset(host); - } - if (linkint & LINK_INT_PHY_REG_RCVD) { - u32 reg; - - spin_lock(&lynx->phy_reg_lock); - reg = reg_read(lynx, LINK_PHY); - spin_unlock(&lynx->phy_reg_lock); - - if (!host->in_bus_reset) { - PRINT(KERN_INFO, lynx->id, - "phy reg received without reset"); - } else if (reg & 0xf00) { - PRINT(KERN_INFO, lynx->id, - "unsolicited phy reg %d received", - (reg >> 8) & 0xf); - } else { - lynx->phy_reg0 = reg & 0xff; - handle_selfid(lynx, host); - } - } - if (linkint & LINK_INT_ISO_STUCK) { - PRINT(KERN_INFO, lynx->id, "isochronous transmitter stuck"); - } - if (linkint & LINK_INT_ASYNC_STUCK) { - PRINT(KERN_INFO, lynx->id, "asynchronous transmitter stuck"); - } - if (linkint & LINK_INT_SENT_REJECT) { - PRINT(KERN_INFO, lynx->id, "sent reject"); - } - if (linkint & LINK_INT_TX_INVALID_TC) { - PRINT(KERN_INFO, lynx->id, "invalid transaction code"); - } - if (linkint & LINK_INT_GRF_OVERFLOW) { - /* flush FIFO if overflow happens during reset */ - if (host->in_bus_reset) - reg_write(lynx, FIFO_CONTROL, - FIFO_CONTROL_GRF_FLUSH); - PRINT(KERN_INFO, lynx->id, "GRF overflow"); - } - if (linkint & LINK_INT_ITF_UNDERFLOW) { - PRINT(KERN_INFO, lynx->id, "ITF underflow"); - } - if (linkint & LINK_INT_ATF_UNDERFLOW) { - PRINT(KERN_INFO, lynx->id, "ATF underflow"); - } - } - - if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_RCV)) { - PRINTD(KERN_DEBUG, lynx->id, "iso receive"); - - spin_lock(&lynx->iso_rcv.lock); - - lynx->iso_rcv.stat[lynx->iso_rcv.next] = - reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ISO_RCV)); - - lynx->iso_rcv.used++; - lynx->iso_rcv.next = (lynx->iso_rcv.next + 1) % NUM_ISORCV_PCL; - - if ((lynx->iso_rcv.next == lynx->iso_rcv.last) - || !lynx->iso_rcv.chan_count) { - PRINTD(KERN_DEBUG, lynx->id, "stopped"); - reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0); - } - - run_sub_pcl(lynx, lynx->iso_rcv.pcl_start, lynx->iso_rcv.next, - CHANNEL_ISO_RCV); - - spin_unlock(&lynx->iso_rcv.lock); - - tasklet_schedule(&lynx->iso_rcv.tq); - } - - if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_SEND)) { - PRINTD(KERN_DEBUG, lynx->id, "async sent"); - spin_lock(&lynx->async.queue_lock); - - if (list_empty(&lynx->async.pcl_queue)) { - spin_unlock(&lynx->async.queue_lock); - PRINT(KERN_WARNING, lynx->id, "async dma halted, but no queued packet (maybe it was cancelled)"); - } else { - struct ti_pcl pcl; - u32 ack; - struct hpsb_packet *packet; - - get_pcl(lynx, lynx->async.pcl, &pcl); - - packet = driver_packet(lynx->async.pcl_queue.next); - list_del_init(&packet->driver_list); - - pci_unmap_single(lynx->dev, lynx->async.header_dma, - packet->header_size, PCI_DMA_TODEVICE); - if (packet->data_size) { - pci_unmap_single(lynx->dev, lynx->async.data_dma, - packet->data_size, PCI_DMA_TODEVICE); - } - - if (!list_empty(&lynx->async.queue)) { - send_next(lynx, hpsb_async); - } - - spin_unlock(&lynx->async.queue_lock); - - if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { - if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) { - ack = (pcl.pcl_status >> 15) & 0xf; - PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); - ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); - } else { - ack = (pcl.pcl_status >> 15) & 0xf; - } - } else { - PRINT(KERN_INFO, lynx->id, "async packet was not completed"); - ack = ACKX_SEND_ERROR; - } - hpsb_packet_sent(host, packet, ack); - } - } - - if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_SEND)) { - PRINTD(KERN_DEBUG, lynx->id, "iso sent"); - spin_lock(&lynx->iso_send.queue_lock); - - if (list_empty(&lynx->iso_send.pcl_queue)) { - spin_unlock(&lynx->iso_send.queue_lock); - PRINT(KERN_ERR, lynx->id, "iso send dma halted, but no queued packet"); - } else { - struct ti_pcl pcl; - u32 ack; - struct hpsb_packet *packet; - - get_pcl(lynx, lynx->iso_send.pcl, &pcl); - - packet = driver_packet(lynx->iso_send.pcl_queue.next); - list_del_init(&packet->driver_list); - - pci_unmap_single(lynx->dev, lynx->iso_send.header_dma, - packet->header_size, PCI_DMA_TODEVICE); - if (packet->data_size) { - pci_unmap_single(lynx->dev, lynx->iso_send.data_dma, - packet->data_size, PCI_DMA_TODEVICE); - } -#if 0 /* has been removed from ieee1394 core */ - if (!list_empty(&lynx->iso_send.queue)) { - send_next(lynx, hpsb_iso); - } -#endif - spin_unlock(&lynx->iso_send.queue_lock); - - if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) { - if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) { - ack = (pcl.pcl_status >> 15) & 0xf; - PRINTD(KERN_INFO, lynx->id, "special ack %d", ack); - ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR); - } else { - ack = (pcl.pcl_status >> 15) & 0xf; - } - } else { - PRINT(KERN_INFO, lynx->id, "iso send packet was not completed"); - ack = ACKX_SEND_ERROR; - } - - hpsb_packet_sent(host, packet, ack); //FIXME: maybe we should just use ACK_COMPLETE and ACKX_SEND_ERROR - } - } - - if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_RCV)) { - /* general receive DMA completed */ - int stat = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_RCV)); - - PRINTD(KERN_DEBUG, lynx->id, "received packet size %d", - stat & 0x1fff); - - if (stat & DMA_CHAN_STAT_SELFID) { - lynx->selfid_size = stat & 0x1fff; - handle_selfid(lynx, host); - } else { - quadlet_t *q_data = lynx->rcv_page; - if ((*q_data >> 4 & 0xf) == TCODE_READQ_RESPONSE - || (*q_data >> 4 & 0xf) == TCODE_WRITEQ) { - cpu_to_be32s(q_data + 3); - } - hpsb_packet_received(host, q_data, stat & 0x1fff, 0); - } - - run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV); - } - - return IRQ_HANDLED; -} - - -static void iso_rcv_bh(struct ti_lynx *lynx) -{ - unsigned int idx; - quadlet_t *data; - unsigned long flags; - - spin_lock_irqsave(&lynx->iso_rcv.lock, flags); - - while (lynx->iso_rcv.used) { - idx = lynx->iso_rcv.last; - spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags); - - data = lynx->iso_rcv.page[idx / ISORCV_PER_PAGE] - + (idx % ISORCV_PER_PAGE) * MAX_ISORCV_SIZE; - - if ((*data >> 16) + 4 != (lynx->iso_rcv.stat[idx] & 0x1fff)) { - PRINT(KERN_ERR, lynx->id, - "iso length mismatch 0x%08x/0x%08x", *data, - lynx->iso_rcv.stat[idx]); - } - - if (lynx->iso_rcv.stat[idx] - & (DMA_CHAN_STAT_PCIERR | DMA_CHAN_STAT_PKTERR)) { - PRINT(KERN_INFO, lynx->id, - "iso receive error on %d to 0x%p", idx, data); - } else { - hpsb_packet_received(lynx->host, data, - lynx->iso_rcv.stat[idx] & 0x1fff, - 0); - } - - spin_lock_irqsave(&lynx->iso_rcv.lock, flags); - lynx->iso_rcv.last = (idx + 1) % NUM_ISORCV_PCL; - lynx->iso_rcv.used--; - } - - if (lynx->iso_rcv.chan_count) { - reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), - DMA_WORD1_CMP_ENABLE_MASTER); - } - spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags); -} - - -static void remove_card(struct pci_dev *dev) -{ - struct ti_lynx *lynx; - struct device *lynx_dev; - int i; - - lynx = pci_get_drvdata(dev); - if (!lynx) return; - pci_set_drvdata(dev, NULL); - - lynx_dev = get_device(&lynx->host->device); - - switch (lynx->state) { - case is_host: - reg_write(lynx, PCI_INT_ENABLE, 0); - hpsb_remove_host(lynx->host); - case have_intr: - reg_write(lynx, PCI_INT_ENABLE, 0); - free_irq(lynx->dev->irq, lynx); - - /* Disable IRM Contender and LCtrl */ - if (lynx->phyic.reg_1394a) - set_phy_reg(lynx, 4, ~0xc0 & get_phy_reg(lynx, 4)); - - /* Let all other nodes know to ignore us */ - lynx_devctl(lynx->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT); - - case have_iomappings: - reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET); - /* Fix buggy cards with autoboot pin not tied low: */ - reg_write(lynx, DMA0_CHAN_CTRL, 0); - iounmap(lynx->registers); - iounmap(lynx->local_rom); - iounmap(lynx->local_ram); - iounmap(lynx->aux_port); - case have_1394_buffers: - for (i = 0; i < ISORCV_PAGES; i++) { - if (lynx->iso_rcv.page[i]) { - pci_free_consistent(lynx->dev, PAGE_SIZE, - lynx->iso_rcv.page[i], - lynx->iso_rcv.page_dma[i]); - } - } - pci_free_consistent(lynx->dev, PAGE_SIZE, lynx->rcv_page, - lynx->rcv_page_dma); - case have_aux_buf: - case have_pcl_mem: - pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem, - lynx->pcl_mem_dma); - case clear: - /* do nothing - already freed */ - ; - } - - tasklet_kill(&lynx->iso_rcv.tq); - - if (lynx_dev) - put_device(lynx_dev); -} - - -static int __devinit add_card(struct pci_dev *dev, - const struct pci_device_id *devid_is_unused) -{ -#define FAIL(fmt, args...) do { \ - PRINT_G(KERN_ERR, fmt , ## args); \ - remove_card(dev); \ - return error; \ - } while (0) - - char irq_buf[16]; - struct hpsb_host *host; - struct ti_lynx *lynx; /* shortcut to currently handled device */ - struct ti_pcl pcl; - u32 *pcli; - int i; - int error; - - error = -ENXIO; - - if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) - FAIL("DMA address limits not supported for PCILynx hardware"); - if (pci_enable_device(dev)) - FAIL("failed to enable PCILynx hardware"); - pci_set_master(dev); - - error = -ENOMEM; - - host = hpsb_alloc_host(&lynx_driver, sizeof(struct ti_lynx), &dev->dev); - if (!host) FAIL("failed to allocate control structure memory"); - - lynx = host->hostdata; - lynx->id = card_id++; - lynx->dev = dev; - lynx->state = clear; - lynx->host = host; - host->pdev = dev; - pci_set_drvdata(dev, lynx); - - spin_lock_init(&lynx->lock); - spin_lock_init(&lynx->phy_reg_lock); - - lynx->pcl_mem = pci_alloc_consistent(dev, LOCALRAM_SIZE, - &lynx->pcl_mem_dma); - - if (lynx->pcl_mem != NULL) { - lynx->state = have_pcl_mem; - PRINT(KERN_INFO, lynx->id, - "allocated PCL memory %d Bytes @ 0x%p", LOCALRAM_SIZE, - lynx->pcl_mem); - } else { - FAIL("failed to allocate PCL memory area"); - } - - lynx->rcv_page = pci_alloc_consistent(dev, PAGE_SIZE, - &lynx->rcv_page_dma); - if (lynx->rcv_page == NULL) { - FAIL("failed to allocate receive buffer"); - } - lynx->state = have_1394_buffers; - - for (i = 0; i < ISORCV_PAGES; i++) { - lynx->iso_rcv.page[i] = - pci_alloc_consistent(dev, PAGE_SIZE, - &lynx->iso_rcv.page_dma[i]); - if (lynx->iso_rcv.page[i] == NULL) { - FAIL("failed to allocate iso receive buffers"); - } - } - - lynx->registers = ioremap_nocache(pci_resource_start(dev,0), - PCILYNX_MAX_REGISTER); - lynx->local_ram = ioremap(pci_resource_start(dev,1), PCILYNX_MAX_MEMORY); - lynx->aux_port = ioremap(pci_resource_start(dev,2), PCILYNX_MAX_MEMORY); - lynx->local_rom = ioremap(pci_resource_start(dev,PCI_ROM_RESOURCE), - PCILYNX_MAX_MEMORY); - lynx->state = have_iomappings; - - if (lynx->registers == NULL) { - FAIL("failed to remap registers - card not accessible"); - } - - reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET); - /* Fix buggy cards with autoboot pin not tied low: */ - reg_write(lynx, DMA0_CHAN_CTRL, 0); - - sprintf (irq_buf, "%d", dev->irq); - - if (!request_irq(dev->irq, lynx_irq_handler, IRQF_SHARED, - PCILYNX_DRIVER_NAME, lynx)) { - PRINT(KERN_INFO, lynx->id, "allocated interrupt %s", irq_buf); - lynx->state = have_intr; - } else { - FAIL("failed to allocate shared interrupt %s", irq_buf); - } - - /* alloc_pcl return values are not checked, it is expected that the - * provided PCL space is sufficient for the initial allocations */ - lynx->rcv_pcl = alloc_pcl(lynx); - lynx->rcv_pcl_start = alloc_pcl(lynx); - lynx->async.pcl = alloc_pcl(lynx); - lynx->async.pcl_start = alloc_pcl(lynx); - lynx->iso_send.pcl = alloc_pcl(lynx); - lynx->iso_send.pcl_start = alloc_pcl(lynx); - - for (i = 0; i < NUM_ISORCV_PCL; i++) { - lynx->iso_rcv.pcl[i] = alloc_pcl(lynx); - } - lynx->iso_rcv.pcl_start = alloc_pcl(lynx); - - /* all allocations successful - simple init stuff follows */ - - reg_write(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL); - - tasklet_init(&lynx->iso_rcv.tq, (void (*)(unsigned long))iso_rcv_bh, - (unsigned long)lynx); - - spin_lock_init(&lynx->iso_rcv.lock); - - spin_lock_init(&lynx->async.queue_lock); - lynx->async.channel = CHANNEL_ASYNC_SEND; - spin_lock_init(&lynx->iso_send.queue_lock); - lynx->iso_send.channel = CHANNEL_ISO_SEND; - - PRINT(KERN_INFO, lynx->id, "remapped memory spaces reg 0x%p, rom 0x%p, " - "ram 0x%p, aux 0x%p", lynx->registers, lynx->local_rom, - lynx->local_ram, lynx->aux_port); - - /* now, looking for PHY register set */ - if ((get_phy_reg(lynx, 2) & 0xe0) == 0xe0) { - lynx->phyic.reg_1394a = 1; - PRINT(KERN_INFO, lynx->id, - "found 1394a conform PHY (using extended register set)"); - lynx->phyic.vendor = get_phy_vendorid(lynx); - lynx->phyic.product = get_phy_productid(lynx); - } else { - lynx->phyic.reg_1394a = 0; - PRINT(KERN_INFO, lynx->id, "found old 1394 PHY"); - } - - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - - INIT_LIST_HEAD(&lynx->async.queue); - INIT_LIST_HEAD(&lynx->async.pcl_queue); - INIT_LIST_HEAD(&lynx->iso_send.queue); - INIT_LIST_HEAD(&lynx->iso_send.pcl_queue); - - pcl.next = pcl_bus(lynx, lynx->rcv_pcl); - put_pcl(lynx, lynx->rcv_pcl_start, &pcl); - - pcl.next = PCL_NEXT_INVALID; - pcl.async_error_next = PCL_NEXT_INVALID; - - pcl.buffer[0].control = PCL_CMD_RCV | 16; -#ifndef __BIG_ENDIAN - pcl.buffer[0].control |= PCL_BIGENDIAN; -#endif - pcl.buffer[1].control = PCL_LAST_BUFF | 4080; - - pcl.buffer[0].pointer = lynx->rcv_page_dma; - pcl.buffer[1].pointer = lynx->rcv_page_dma + 16; - put_pcl(lynx, lynx->rcv_pcl, &pcl); - - pcl.next = pcl_bus(lynx, lynx->async.pcl); - pcl.async_error_next = pcl_bus(lynx, lynx->async.pcl); - put_pcl(lynx, lynx->async.pcl_start, &pcl); - - pcl.next = pcl_bus(lynx, lynx->iso_send.pcl); - pcl.async_error_next = PCL_NEXT_INVALID; - put_pcl(lynx, lynx->iso_send.pcl_start, &pcl); - - pcl.next = PCL_NEXT_INVALID; - pcl.async_error_next = PCL_NEXT_INVALID; - pcl.buffer[0].control = PCL_CMD_RCV | 4; -#ifndef __BIG_ENDIAN - pcl.buffer[0].control |= PCL_BIGENDIAN; -#endif - pcl.buffer[1].control = PCL_LAST_BUFF | 2044; - - for (i = 0; i < NUM_ISORCV_PCL; i++) { - int page = i / ISORCV_PER_PAGE; - int sec = i % ISORCV_PER_PAGE; - - pcl.buffer[0].pointer = lynx->iso_rcv.page_dma[page] - + sec * MAX_ISORCV_SIZE; - pcl.buffer[1].pointer = pcl.buffer[0].pointer + 4; - put_pcl(lynx, lynx->iso_rcv.pcl[i], &pcl); - } - - pcli = (u32 *)&pcl; - for (i = 0; i < NUM_ISORCV_PCL; i++) { - pcli[i] = pcl_bus(lynx, lynx->iso_rcv.pcl[i]); - } - put_pcl(lynx, lynx->iso_rcv.pcl_start, &pcl); - - /* FIFO sizes from left to right: ITF=48 ATF=48 GRF=160 */ - reg_write(lynx, FIFO_SIZES, 0x003030a0); - /* 20 byte threshold before triggering PCI transfer */ - reg_write(lynx, DMA_GLOBAL_REGISTER, 0x2<<24); - /* threshold on both send FIFOs before transmitting: - FIFO size - cache line size - 1 */ - i = reg_read(lynx, PCI_LATENCY_CACHELINE) & 0xff; - i = 0x30 - i - 1; - reg_write(lynx, FIFO_XMIT_THRESHOLD, (i << 8) | i); - - reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_1394); - - reg_write(lynx, LINK_INT_ENABLE, LINK_INT_PHY_TIMEOUT - | LINK_INT_PHY_REG_RCVD | LINK_INT_PHY_BUSRESET - | LINK_INT_ISO_STUCK | LINK_INT_ASYNC_STUCK - | LINK_INT_SENT_REJECT | LINK_INT_TX_INVALID_TC - | LINK_INT_GRF_OVERFLOW | LINK_INT_ITF_UNDERFLOW - | LINK_INT_ATF_UNDERFLOW); - - reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ASYNC_RCV), 0); - reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ASYNC_RCV), 0xa<<4); - reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ASYNC_RCV), 0); - reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ASYNC_RCV), - DMA_WORD1_CMP_MATCH_LOCAL_NODE | DMA_WORD1_CMP_MATCH_BROADCAST - | DMA_WORD1_CMP_MATCH_EXACT | DMA_WORD1_CMP_MATCH_BUS_BCAST - | DMA_WORD1_CMP_ENABLE_SELF_ID | DMA_WORD1_CMP_ENABLE_MASTER); - - run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV); - - reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ISO_RCV), 0); - reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ISO_RCV), 0x9<<4); - reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ISO_RCV), 0); - reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0); - - run_sub_pcl(lynx, lynx->iso_rcv.pcl_start, 0, CHANNEL_ISO_RCV); - - reg_write(lynx, LINK_CONTROL, LINK_CONTROL_RCV_CMP_VALID - | LINK_CONTROL_TX_ISO_EN | LINK_CONTROL_RX_ISO_EN - | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN - | LINK_CONTROL_RESET_TX | LINK_CONTROL_RESET_RX); - - if (!lynx->phyic.reg_1394a) { - if (!hpsb_disable_irm) { - /* attempt to enable contender bit -FIXME- would this - * work elsewhere? */ - reg_set_bits(lynx, GPIO_CTRL_A, 0x1); - reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1); - } - } else { - /* set the contender (if appropriate) and LCtrl bit in the - * extended PHY register set. (Should check that PHY_02_EXTENDED - * is set in register 2?) - */ - i = get_phy_reg(lynx, 4); - i |= PHY_04_LCTRL; - if (hpsb_disable_irm) - i &= ~PHY_04_CONTENDER; - else - i |= PHY_04_CONTENDER; - if (i != -1) set_phy_reg(lynx, 4, i); - } - - if (!skip_eeprom) - { - /* needed for i2c communication with serial eeprom */ - struct i2c_adapter *i2c_ad; - struct i2c_algo_bit_data i2c_adapter_data; - - error = -ENOMEM; - i2c_ad = kzalloc(sizeof(*i2c_ad), GFP_KERNEL); - if (!i2c_ad) FAIL("failed to allocate I2C adapter memory"); - - strlcpy(i2c_ad->name, "PCILynx I2C", sizeof(i2c_ad->name)); - i2c_adapter_data = bit_data; - i2c_ad->algo_data = &i2c_adapter_data; - i2c_adapter_data.data = lynx; - i2c_ad->dev.parent = &dev->dev; - - PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d", - reg_read(lynx, SERIAL_EEPROM_CONTROL)); - - /* reset hardware to sane state */ - lynx->i2c_driven_state = 0x00000070; - reg_write(lynx, SERIAL_EEPROM_CONTROL, lynx->i2c_driven_state); - - if (i2c_bit_add_bus(i2c_ad) < 0) - { - kfree(i2c_ad); - error = -ENXIO; - FAIL("unable to register i2c"); - } - else - { - /* do i2c stuff */ - unsigned char i2c_cmd = 0x10; - struct i2c_msg msg[2] = { { 0x50, 0, 1, &i2c_cmd }, - { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block } - }; - - /* we use i2c_transfer because we have no i2c_client - at hand */ - if (i2c_transfer(i2c_ad, msg, 2) < 0) { - PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c"); - } else { - PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom"); - /* FIXME: probably we should rewrite the max_rec, max_ROM(1394a), - * generation(1394a) and link_spd(1394a) field and recalculate - * the CRC */ - - for (i = 0; i < 5 ; i++) - PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x", - i, be32_to_cpu(lynx->bus_info_block[i])); - - /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */ - if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) && - (lynx->bus_info_block[1] == IEEE1394_BUSID_MAGIC)) - { - PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from"); - } else { - kfree(i2c_ad); - error = -ENXIO; - FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block"); - } - - } - - i2c_del_adapter(i2c_ad); - kfree(i2c_ad); - } - } - - host->csr.guid_hi = be32_to_cpu(lynx->bus_info_block[3]); - host->csr.guid_lo = be32_to_cpu(lynx->bus_info_block[4]); - host->csr.cyc_clk_acc = (be32_to_cpu(lynx->bus_info_block[2]) >> 16) & 0xff; - host->csr.max_rec = (be32_to_cpu(lynx->bus_info_block[2]) >> 12) & 0xf; - if (!lynx->phyic.reg_1394a) - host->csr.lnk_spd = (get_phy_reg(lynx, 2) & 0xc0) >> 6; - else - host->csr.lnk_spd = be32_to_cpu(lynx->bus_info_block[2]) & 0x7; - - if (hpsb_add_host(host)) { - error = -ENOMEM; - FAIL("Failed to register host with highlevel"); - } - - lynx->state = is_host; - - return 0; -#undef FAIL -} - - -static struct pci_device_id pci_table[] = { - { - .vendor = PCI_VENDOR_ID_TI, - .device = PCI_DEVICE_ID_TI_PCILYNX, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { } /* Terminating entry */ -}; - -static struct pci_driver lynx_pci_driver = { - .name = PCILYNX_DRIVER_NAME, - .id_table = pci_table, - .probe = add_card, - .remove = remove_card, -}; - -static struct hpsb_host_driver lynx_driver = { - .owner = THIS_MODULE, - .name = PCILYNX_DRIVER_NAME, - .set_hw_config_rom = NULL, - .transmit_packet = lynx_transmit, - .devctl = lynx_devctl, - .isoctl = NULL, -}; - -MODULE_AUTHOR("Andreas E. Bombe <andreas.bombe@munich.netsurf.de>"); -MODULE_DESCRIPTION("driver for Texas Instruments PCI Lynx IEEE-1394 controller"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("pcilynx"); -MODULE_DEVICE_TABLE(pci, pci_table); - -static int __init pcilynx_init(void) -{ - int ret; - - ret = pci_register_driver(&lynx_pci_driver); - if (ret < 0) { - PRINT_G(KERN_ERR, "PCI module init failed"); - return ret; - } - - return 0; -} - -static void __exit pcilynx_cleanup(void) -{ - pci_unregister_driver(&lynx_pci_driver); -} - - -module_init(pcilynx_init); -module_exit(pcilynx_cleanup); diff --git a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h deleted file mode 100644 index 693a169..0000000 --- a/drivers/ieee1394/pcilynx.h +++ /dev/null @@ -1,468 +0,0 @@ -#ifndef __PCILYNX_H__ -#define __PCILYNX_H__ - - -#define PCILYNX_DRIVER_NAME "pcilynx" -#define PCILYNX_MAJOR 177 - -#define PCILYNX_MINOR_AUX_START 0 -#define PCILYNX_MINOR_ROM_START 16 -#define PCILYNX_MINOR_RAM_START 32 - -#define PCILYNX_MAX_REGISTER 0xfff -#define PCILYNX_MAX_MEMORY 0xffff - -#define PCI_DEVICE_ID_TI_PCILYNX 0x8000 -#define MAX_PCILYNX_CARDS 4 -#define LOCALRAM_SIZE 4096 - -#define NUM_ISORCV_PCL 4 -#define MAX_ISORCV_SIZE 2048 -#define ISORCV_PER_PAGE (PAGE_SIZE / MAX_ISORCV_SIZE) -#define ISORCV_PAGES (NUM_ISORCV_PCL / ISORCV_PER_PAGE) - -#define CHANNEL_LOCALBUS 0 -#define CHANNEL_ASYNC_RCV 1 -#define CHANNEL_ISO_RCV 2 -#define CHANNEL_ASYNC_SEND 3 -#define CHANNEL_ISO_SEND 4 - -#define PCILYNX_CONFIG_ROM_LENGTH 1024 - -typedef int pcl_t; - -struct ti_lynx { - int id; /* sequential card number */ - - spinlock_t lock; - - struct pci_dev *dev; - - struct { - unsigned reg_1394a:1; - u32 vendor; - u32 product; - } phyic; - - enum { clear, have_intr, have_aux_buf, have_pcl_mem, - have_1394_buffers, have_iomappings, is_host } state; - - /* remapped memory spaces */ - void __iomem *registers; - void __iomem *local_rom; - void __iomem *local_ram; - void __iomem *aux_port; - __be32 bus_info_block[5]; - - /* - * use local RAM of LOCALRAM_SIZE bytes for PCLs, which allows for - * LOCALRAM_SIZE * 8 PCLs (each sized 128 bytes); - * the following is an allocation bitmap - */ - u8 pcl_bmap[LOCALRAM_SIZE / 1024]; - - /* point to PCLs memory area if needed */ - void *pcl_mem; - dma_addr_t pcl_mem_dma; - - /* PCLs for local mem / aux transfers */ - pcl_t dmem_pcl; - - /* IEEE-1394 part follows */ - struct hpsb_host *host; - - int phyid, isroot; - int selfid_size; - int phy_reg0; - - spinlock_t phy_reg_lock; - - pcl_t rcv_pcl_start, rcv_pcl; - void *rcv_page; - dma_addr_t rcv_page_dma; - int rcv_active; - - struct lynx_send_data { - pcl_t pcl_start, pcl; - struct list_head queue; - struct list_head pcl_queue; /* this queue contains at most one packet */ - spinlock_t queue_lock; - dma_addr_t header_dma, data_dma; - int channel; - } async, iso_send; - - struct { - pcl_t pcl[NUM_ISORCV_PCL]; - u32 stat[NUM_ISORCV_PCL]; - void *page[ISORCV_PAGES]; - dma_addr_t page_dma[ISORCV_PAGES]; - pcl_t pcl_start; - int chan_count; - int next, last, used, running; - struct tasklet_struct tq; - spinlock_t lock; - } iso_rcv; - - u32 i2c_driven_state; /* the state we currently drive the Serial EEPROM Control register */ -}; - -/* the per-file data structure for mem space access */ -struct memdata { - struct ti_lynx *lynx; - int cid; - atomic_t aux_intr_last_seen; - /* enum values are the same as LBUS_ADDR_SEL_* values below */ - enum { rom = 0x10000, aux = 0x20000, ram = 0 } type; -}; - - - -/* - * Register read and write helper functions. - */ -static inline void reg_write(const struct ti_lynx *lynx, int offset, u32 data) -{ - writel(data, lynx->registers + offset); -} - -static inline u32 reg_read(const struct ti_lynx *lynx, int offset) -{ - return readl(lynx->registers + offset); -} - -static inline void reg_set_bits(const struct ti_lynx *lynx, int offset, - u32 mask) -{ - reg_write(lynx, offset, (reg_read(lynx, offset) | mask)); -} - -static inline void reg_clear_bits(const struct ti_lynx *lynx, int offset, - u32 mask) -{ - reg_write(lynx, offset, (reg_read(lynx, offset) & ~mask)); -} - - - -/* chip register definitions follow */ - -#define PCI_LATENCY_CACHELINE 0x0c - -#define MISC_CONTROL 0x40 -#define MISC_CONTROL_SWRESET (1<<0) - -#define SERIAL_EEPROM_CONTROL 0x44 - -#define PCI_INT_STATUS 0x48 -#define PCI_INT_ENABLE 0x4c -/* status and enable have identical bit numbers */ -#define PCI_INT_INT_PEND (1<<31) -#define PCI_INT_FORCED_INT (1<<30) -#define PCI_INT_SLV_ADR_PERR (1<<28) -#define PCI_INT_SLV_DAT_PERR (1<<27) -#define PCI_INT_MST_DAT_PERR (1<<26) -#define PCI_INT_MST_DEV_TIMEOUT (1<<25) -#define PCI_INT_INTERNAL_SLV_TIMEOUT (1<<23) -#define PCI_INT_AUX_TIMEOUT (1<<18) -#define PCI_INT_AUX_INT (1<<17) -#define PCI_INT_1394 (1<<16) -#define PCI_INT_DMA4_PCL (1<<9) -#define PCI_INT_DMA4_HLT (1<<8) -#define PCI_INT_DMA3_PCL (1<<7) -#define PCI_INT_DMA3_HLT (1<<6) -#define PCI_INT_DMA2_PCL (1<<5) -#define PCI_INT_DMA2_HLT (1<<4) -#define PCI_INT_DMA1_PCL (1<<3) -#define PCI_INT_DMA1_HLT (1<<2) -#define PCI_INT_DMA0_PCL (1<<1) -#define PCI_INT_DMA0_HLT (1<<0) -/* all DMA interrupts combined: */ -#define PCI_INT_DMA_ALL 0x3ff - -#define PCI_INT_DMA_HLT(chan) (1 << (chan * 2)) -#define PCI_INT_DMA_PCL(chan) (1 << (chan * 2 + 1)) - -#define LBUS_ADDR 0xb4 -#define LBUS_ADDR_SEL_RAM (0x0<<16) -#define LBUS_ADDR_SEL_ROM (0x1<<16) -#define LBUS_ADDR_SEL_AUX (0x2<<16) -#define LBUS_ADDR_SEL_ZV (0x3<<16) - -#define GPIO_CTRL_A 0xb8 -#define GPIO_CTRL_B 0xbc -#define GPIO_DATA_BASE 0xc0 - -#define DMA_BREG(base, chan) (base + chan * 0x20) -#define DMA_SREG(base, chan) (base + chan * 0x10) - -#define DMA0_PREV_PCL 0x100 -#define DMA1_PREV_PCL 0x120 -#define DMA2_PREV_PCL 0x140 -#define DMA3_PREV_PCL 0x160 -#define DMA4_PREV_PCL 0x180 -#define DMA_PREV_PCL(chan) (DMA_BREG(DMA0_PREV_PCL, chan)) - -#define DMA0_CURRENT_PCL 0x104 -#define DMA1_CURRENT_PCL 0x124 -#define DMA2_CURRENT_PCL 0x144 -#define DMA3_CURRENT_PCL 0x164 -#define DMA4_CURRENT_PCL 0x184 -#define DMA_CURRENT_PCL(chan) (DMA_BREG(DMA0_CURRENT_PCL, chan)) - -#define DMA0_CHAN_STAT 0x10c -#define DMA1_CHAN_STAT 0x12c -#define DMA2_CHAN_STAT 0x14c -#define DMA3_CHAN_STAT 0x16c -#define DMA4_CHAN_STAT 0x18c -#define DMA_CHAN_STAT(chan) (DMA_BREG(DMA0_CHAN_STAT, chan)) -/* CHAN_STATUS registers share bits */ -#define DMA_CHAN_STAT_SELFID (1<<31) -#define DMA_CHAN_STAT_ISOPKT (1<<30) -#define DMA_CHAN_STAT_PCIERR (1<<29) -#define DMA_CHAN_STAT_PKTERR (1<<28) -#define DMA_CHAN_STAT_PKTCMPL (1<<27) -#define DMA_CHAN_STAT_SPECIALACK (1<<14) - - -#define DMA0_CHAN_CTRL 0x110 -#define DMA1_CHAN_CTRL 0x130 -#define DMA2_CHAN_CTRL 0x150 -#define DMA3_CHAN_CTRL 0x170 -#define DMA4_CHAN_CTRL 0x190 -#define DMA_CHAN_CTRL(chan) (DMA_BREG(DMA0_CHAN_CTRL, chan)) -/* CHAN_CTRL registers share bits */ -#define DMA_CHAN_CTRL_ENABLE (1<<31) -#define DMA_CHAN_CTRL_BUSY (1<<30) -#define DMA_CHAN_CTRL_LINK (1<<29) - -#define DMA0_READY 0x114 -#define DMA1_READY 0x134 -#define DMA2_READY 0x154 -#define DMA3_READY 0x174 -#define DMA4_READY 0x194 -#define DMA_READY(chan) (DMA_BREG(DMA0_READY, chan)) - -#define DMA_GLOBAL_REGISTER 0x908 - -#define FIFO_SIZES 0xa00 - -#define FIFO_CONTROL 0xa10 -#define FIFO_CONTROL_GRF_FLUSH (1<<4) -#define FIFO_CONTROL_ITF_FLUSH (1<<3) -#define FIFO_CONTROL_ATF_FLUSH (1<<2) - -#define FIFO_XMIT_THRESHOLD 0xa14 - -#define DMA0_WORD0_CMP_VALUE 0xb00 -#define DMA1_WORD0_CMP_VALUE 0xb10 -#define DMA2_WORD0_CMP_VALUE 0xb20 -#define DMA3_WORD0_CMP_VALUE 0xb30 -#define DMA4_WORD0_CMP_VALUE 0xb40 -#define DMA_WORD0_CMP_VALUE(chan) (DMA_SREG(DMA0_WORD0_CMP_VALUE, chan)) - -#define DMA0_WORD0_CMP_ENABLE 0xb04 -#define DMA1_WORD0_CMP_ENABLE 0xb14 -#define DMA2_WORD0_CMP_ENABLE 0xb24 -#define DMA3_WORD0_CMP_ENABLE 0xb34 -#define DMA4_WORD0_CMP_ENABLE 0xb44 -#define DMA_WORD0_CMP_ENABLE(chan) (DMA_SREG(DMA0_WORD0_CMP_ENABLE,chan)) - -#define DMA0_WORD1_CMP_VALUE 0xb08 -#define DMA1_WORD1_CMP_VALUE 0xb18 -#define DMA2_WORD1_CMP_VALUE 0xb28 -#define DMA3_WORD1_CMP_VALUE 0xb38 -#define DMA4_WORD1_CMP_VALUE 0xb48 -#define DMA_WORD1_CMP_VALUE(chan) (DMA_SREG(DMA0_WORD1_CMP_VALUE, chan)) - -#define DMA0_WORD1_CMP_ENABLE 0xb0c -#define DMA1_WORD1_CMP_ENABLE 0xb1c -#define DMA2_WORD1_CMP_ENABLE 0xb2c -#define DMA3_WORD1_CMP_ENABLE 0xb3c -#define DMA4_WORD1_CMP_ENABLE 0xb4c -#define DMA_WORD1_CMP_ENABLE(chan) (DMA_SREG(DMA0_WORD1_CMP_ENABLE,chan)) -/* word 1 compare enable flags */ -#define DMA_WORD1_CMP_MATCH_OTHERBUS (1<<15) -#define DMA_WORD1_CMP_MATCH_BROADCAST (1<<14) -#define DMA_WORD1_CMP_MATCH_BUS_BCAST (1<<13) -#define DMA_WORD1_CMP_MATCH_LOCAL_NODE (1<<12) -#define DMA_WORD1_CMP_MATCH_EXACT (1<<11) -#define DMA_WORD1_CMP_ENABLE_SELF_ID (1<<10) -#define DMA_WORD1_CMP_ENABLE_MASTER (1<<8) - -#define LINK_ID 0xf00 -#define LINK_ID_BUS(id) (id<<22) -#define LINK_ID_NODE(id) (id<<16) - -#define LINK_CONTROL 0xf04 -#define LINK_CONTROL_BUSY (1<<29) -#define LINK_CONTROL_TX_ISO_EN (1<<26) -#define LINK_CONTROL_RX_ISO_EN (1<<25) -#define LINK_CONTROL_TX_ASYNC_EN (1<<24) -#define LINK_CONTROL_RX_ASYNC_EN (1<<23) -#define LINK_CONTROL_RESET_TX (1<<21) -#define LINK_CONTROL_RESET_RX (1<<20) -#define LINK_CONTROL_CYCMASTER (1<<11) -#define LINK_CONTROL_CYCSOURCE (1<<10) -#define LINK_CONTROL_CYCTIMEREN (1<<9) -#define LINK_CONTROL_RCV_CMP_VALID (1<<7) -#define LINK_CONTROL_SNOOP_ENABLE (1<<6) - -#define CYCLE_TIMER 0xf08 - -#define LINK_PHY 0xf0c -#define LINK_PHY_READ (1<<31) -#define LINK_PHY_WRITE (1<<30) -#define LINK_PHY_ADDR(addr) (addr<<24) -#define LINK_PHY_WDATA(data) (data<<16) -#define LINK_PHY_RADDR(addr) (addr<<8) - - -#define LINK_INT_STATUS 0xf14 -#define LINK_INT_ENABLE 0xf18 -/* status and enable have identical bit numbers */ -#define LINK_INT_LINK_INT (1<<31) -#define LINK_INT_PHY_TIMEOUT (1<<30) -#define LINK_INT_PHY_REG_RCVD (1<<29) -#define LINK_INT_PHY_BUSRESET (1<<28) -#define LINK_INT_TX_RDY (1<<26) -#define LINK_INT_RX_DATA_RDY (1<<25) -#define LINK_INT_ISO_STUCK (1<<20) -#define LINK_INT_ASYNC_STUCK (1<<19) -#define LINK_INT_SENT_REJECT (1<<17) -#define LINK_INT_HDR_ERR (1<<16) -#define LINK_INT_TX_INVALID_TC (1<<15) -#define LINK_INT_CYC_SECOND (1<<11) -#define LINK_INT_CYC_START (1<<10) -#define LINK_INT_CYC_DONE (1<<9) -#define LINK_INT_CYC_PENDING (1<<8) -#define LINK_INT_CYC_LOST (1<<7) -#define LINK_INT_CYC_ARB_FAILED (1<<6) -#define LINK_INT_GRF_OVERFLOW (1<<5) -#define LINK_INT_ITF_UNDERFLOW (1<<4) -#define LINK_INT_ATF_UNDERFLOW (1<<3) -#define LINK_INT_ISOARB_FAILED (1<<0) - -/* PHY specifics */ -#define PHY_VENDORID_TI 0x800028 -#define PHY_PRODUCTID_TSB41LV03 0x000000 - - -/* this is the physical layout of a PCL, its size is 128 bytes */ -struct ti_pcl { - u32 next; - u32 async_error_next; - u32 user_data; - u32 pcl_status; - u32 remaining_transfer_count; - u32 next_data_buffer; - struct { - u32 control; - u32 pointer; - } buffer[13] __attribute__ ((packed)); -} __attribute__ ((packed)); - -#include <linux/stddef.h> -#define pcloffs(MEMBER) (offsetof(struct ti_pcl, MEMBER)) - - -static inline void put_pcl(const struct ti_lynx *lynx, pcl_t pclid, - const struct ti_pcl *pcl) -{ - memcpy_le32((u32 *)(lynx->pcl_mem + pclid * sizeof(struct ti_pcl)), - (u32 *)pcl, sizeof(struct ti_pcl)); -} - -static inline void get_pcl(const struct ti_lynx *lynx, pcl_t pclid, - struct ti_pcl *pcl) -{ - memcpy_le32((u32 *)pcl, - (u32 *)(lynx->pcl_mem + pclid * sizeof(struct ti_pcl)), - sizeof(struct ti_pcl)); -} - -static inline u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid) -{ - return lynx->pcl_mem_dma + pclid * sizeof(struct ti_pcl); -} - - -#if defined (__BIG_ENDIAN) -typedef struct ti_pcl pcltmp_t; - -static inline struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid, - pcltmp_t *tmp) -{ - get_pcl(lynx, pclid, tmp); - return tmp; -} - -static inline void commit_pcl(const struct ti_lynx *lynx, pcl_t pclid, - pcltmp_t *tmp) -{ - put_pcl(lynx, pclid, tmp); -} - -#else -typedef int pcltmp_t; /* just a dummy */ - -static inline struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid, - pcltmp_t *tmp) -{ - return lynx->pcl_mem + pclid * sizeof(struct ti_pcl); -} - -static inline void commit_pcl(const struct ti_lynx *lynx, pcl_t pclid, - pcltmp_t *tmp) -{ -} -#endif - - -static inline void run_sub_pcl(const struct ti_lynx *lynx, pcl_t pclid, int idx, - int dmachan) -{ - reg_write(lynx, DMA0_CURRENT_PCL + dmachan * 0x20, - pcl_bus(lynx, pclid) + idx * 4); - reg_write(lynx, DMA0_CHAN_CTRL + dmachan * 0x20, - DMA_CHAN_CTRL_ENABLE | DMA_CHAN_CTRL_LINK); -} - -static inline void run_pcl(const struct ti_lynx *lynx, pcl_t pclid, int dmachan) -{ - run_sub_pcl(lynx, pclid, 0, dmachan); -} - -#define PCL_NEXT_INVALID (1<<0) - -/* transfer commands */ -#define PCL_CMD_RCV (0x1<<24) -#define PCL_CMD_RCV_AND_UPDATE (0xa<<24) -#define PCL_CMD_XMT (0x2<<24) -#define PCL_CMD_UNFXMT (0xc<<24) -#define PCL_CMD_PCI_TO_LBUS (0x8<<24) -#define PCL_CMD_LBUS_TO_PCI (0x9<<24) - -/* aux commands */ -#define PCL_CMD_NOP (0x0<<24) -#define PCL_CMD_LOAD (0x3<<24) -#define PCL_CMD_STOREQ (0x4<<24) -#define PCL_CMD_STORED (0xb<<24) -#define PCL_CMD_STORE0 (0x5<<24) -#define PCL_CMD_STORE1 (0x6<<24) -#define PCL_CMD_COMPARE (0xe<<24) -#define PCL_CMD_SWAP_COMPARE (0xf<<24) -#define PCL_CMD_ADD (0xd<<24) -#define PCL_CMD_BRANCH (0x7<<24) - -/* BRANCH condition codes */ -#define PCL_COND_DMARDY_SET (0x1<<20) -#define PCL_COND_DMARDY_CLEAR (0x2<<20) - -#define PCL_GEN_INTR (1<<19) -#define PCL_LAST_BUFF (1<<18) -#define PCL_LAST_CMD (PCL_LAST_BUFF) -#define PCL_WAITSTAT (1<<17) -#define PCL_BIGENDIAN (1<<16) -#define PCL_ISOMODE (1<<12) - -#endif diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h deleted file mode 100644 index 7a225a4..0000000 --- a/drivers/ieee1394/raw1394-private.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef IEEE1394_RAW1394_PRIVATE_H -#define IEEE1394_RAW1394_PRIVATE_H - -/* header for definitions that are private to the raw1394 driver - and not visible to user-space */ - -#define RAW1394_DEVICE_MAJOR 171 -#define RAW1394_DEVICE_NAME "raw1394" - -#define RAW1394_MAX_USER_CSR_DIRS 16 - -struct iso_block_store { - atomic_t refcount; - size_t data_size; - quadlet_t data[0]; -}; - -enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0, - RAW1394_ISO_RECV = 1, - RAW1394_ISO_XMIT = 2 }; - -struct file_info { - struct list_head list; - - struct mutex state_mutex; - enum { opened, initialized, connected } state; - unsigned int protocol_version; - - struct hpsb_host *host; - - struct list_head req_pending; /* protected by reqlists_lock */ - struct list_head req_complete; /* protected by reqlists_lock */ - spinlock_t reqlists_lock; - wait_queue_head_t wait_complete; - - struct list_head addr_list; /* protected by host_info_lock */ - - u8 __user *fcp_buffer; - - u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */ - - /* new rawiso API */ - enum raw1394_iso_state iso_state; - struct hpsb_iso *iso_handle; - - /* User space's CSR1212 dynamic ConfigROM directories */ - struct csr1212_keyval *csr1212_dirs[RAW1394_MAX_USER_CSR_DIRS]; - - /* Legacy ConfigROM update flag */ - u8 cfgrom_upd; -}; - -struct arm_addr { - struct list_head addr_list; /* file_info list */ - u64 start, end; - u64 arm_tag; - u8 access_rights; - u8 notification_options; - u8 client_transactions; - u64 recvb; - u16 rec_length; - u8 *addr_space_buffer; /* accessed by read/write/lock requests */ -}; - -struct pending_request { - struct list_head list; - struct file_info *file_info; - struct hpsb_packet *packet; - struct iso_block_store *ibs; - quadlet_t *data; - int free_data; - struct raw1394_request req; -}; - -struct host_info { - struct list_head list; - struct hpsb_host *host; - struct list_head file_info_list; /* protected by host_info_lock */ -}; - -#endif /* IEEE1394_RAW1394_PRIVATE_H */ diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c deleted file mode 100644 index f340142..0000000 --- a/drivers/ieee1394/raw1394.c +++ /dev/null @@ -1,3096 +0,0 @@ -/* - * IEEE 1394 for Linux - * - * Raw interface to the bus - * - * Copyright (C) 1999, 2000 Andreas E. Bombe - * 2001, 2002 Manfred Weihs <weihs@ict.tuwien.ac.at> - * 2002 Christian Toegel <christian.toegel@gmx.at> - * - * This code is licensed under the GPL. See the file COPYING in the root - * directory of the kernel sources for details. - * - * - * Contributions: - * - * Manfred Weihs <weihs@ict.tuwien.ac.at> - * configuration ROM manipulation - * address range mapping - * adaptation for new (transparent) loopback mechanism - * sending of arbitrary async packets - * Christian Toegel <christian.toegel@gmx.at> - * address range mapping - * lock64 request - * transmit physical packet - * busreset notification control (switch on/off) - * busreset with selection of type (short/long) - * request_reply - */ - -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/fs.h> -#include <linux/poll.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/vmalloc.h> -#include <linux/cdev.h> -#include <asm/uaccess.h> -#include <asm/atomic.h> -#include <linux/compat.h> - -#include "csr1212.h" -#include "highlevel.h" -#include "hosts.h" -#include "ieee1394.h" -#include "ieee1394_core.h" -#include "ieee1394_hotplug.h" -#include "ieee1394_transactions.h" -#include "ieee1394_types.h" -#include "iso.h" -#include "nodemgr.h" -#include "raw1394.h" -#include "raw1394-private.h" - -#define int2ptr(x) ((void __user *)(unsigned long)x) -#define ptr2int(x) ((u64)(unsigned long)(void __user *)x) - -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG -#define RAW1394_DEBUG -#endif - -#ifdef RAW1394_DEBUG -#define DBGMSG(fmt, args...) \ -printk(KERN_INFO "raw1394:" fmt "\n" , ## args) -#else -#define DBGMSG(fmt, args...) do {} while (0) -#endif - -static LIST_HEAD(host_info_list); -static int host_count; -static DEFINE_SPINLOCK(host_info_lock); -static atomic_t internal_generation = ATOMIC_INIT(0); - -static atomic_t iso_buffer_size; -static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */ - -static struct hpsb_highlevel raw1394_highlevel; - -static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, - u64 addr, size_t length, u16 flags); -static int arm_write(struct hpsb_host *host, int nodeid, int destid, - quadlet_t * data, u64 addr, size_t length, u16 flags); -static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, - u16 flags); -static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode, - u16 flags); -static const struct hpsb_address_ops arm_ops = { - .read = arm_read, - .write = arm_write, - .lock = arm_lock, - .lock64 = arm_lock64, -}; - -static void queue_complete_cb(struct pending_request *req); - -static struct pending_request *__alloc_pending_request(gfp_t flags) -{ - struct pending_request *req; - - req = kzalloc(sizeof(*req), flags); - if (req) - INIT_LIST_HEAD(&req->list); - - return req; -} - -static inline struct pending_request *alloc_pending_request(void) -{ - return __alloc_pending_request(GFP_KERNEL); -} - -static void free_pending_request(struct pending_request *req) -{ - if (req->ibs) { - if (atomic_dec_and_test(&req->ibs->refcount)) { - atomic_sub(req->ibs->data_size, &iso_buffer_size); - kfree(req->ibs); - } - } else if (req->free_data) { - kfree(req->data); - } - hpsb_free_packet(req->packet); - kfree(req); -} - -/* fi->reqlists_lock must be taken */ -static void __queue_complete_req(struct pending_request *req) -{ - struct file_info *fi = req->file_info; - - list_move_tail(&req->list, &fi->req_complete); - wake_up(&fi->wait_complete); -} - -static void queue_complete_req(struct pending_request *req) -{ - unsigned long flags; - struct file_info *fi = req->file_info; - - spin_lock_irqsave(&fi->reqlists_lock, flags); - __queue_complete_req(req); - spin_unlock_irqrestore(&fi->reqlists_lock, flags); -} - -static void queue_complete_cb(struct pending_request *req) -{ - struct hpsb_packet *packet = req->packet; - int rcode = (packet->header[1] >> 12) & 0xf; - - switch (packet->ack_code) { - case ACKX_NONE: - case ACKX_SEND_ERROR: - req->req.error = RAW1394_ERROR_SEND_ERROR; - break; - case ACKX_ABORTED: - req->req.error = RAW1394_ERROR_ABORTED; - break; - case ACKX_TIMEOUT: - req->req.error = RAW1394_ERROR_TIMEOUT; - break; - default: - req->req.error = (packet->ack_code << 16) | rcode; - break; - } - - if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) { - req->req.length = 0; - } - - if ((req->req.type == RAW1394_REQ_ASYNC_READ) || - (req->req.type == RAW1394_REQ_ASYNC_WRITE) || - (req->req.type == RAW1394_REQ_ASYNC_STREAM) || - (req->req.type == RAW1394_REQ_LOCK) || - (req->req.type == RAW1394_REQ_LOCK64)) - hpsb_free_tlabel(packet); - - queue_complete_req(req); -} - -static void add_host(struct hpsb_host *host) -{ - struct host_info *hi; - unsigned long flags; - - hi = kmalloc(sizeof(*hi), GFP_KERNEL); - - if (hi) { - INIT_LIST_HEAD(&hi->list); - hi->host = host; - INIT_LIST_HEAD(&hi->file_info_list); - - spin_lock_irqsave(&host_info_lock, flags); - list_add_tail(&hi->list, &host_info_list); - host_count++; - spin_unlock_irqrestore(&host_info_lock, flags); - } - - atomic_inc(&internal_generation); -} - -static struct host_info *find_host_info(struct hpsb_host *host) -{ - struct host_info *hi; - - list_for_each_entry(hi, &host_info_list, list) - if (hi->host == host) - return hi; - - return NULL; -} - -static void remove_host(struct hpsb_host *host) -{ - struct host_info *hi; - unsigned long flags; - - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(host); - - if (hi != NULL) { - list_del(&hi->list); - host_count--; - /* - FIXME: address ranges should be removed - and fileinfo states should be initialized - (including setting generation to - internal-generation ...) - */ - } - spin_unlock_irqrestore(&host_info_lock, flags); - - if (hi == NULL) { - printk(KERN_ERR "raw1394: attempt to remove unknown host " - "0x%p\n", host); - return; - } - - kfree(hi); - - atomic_inc(&internal_generation); -} - -static void host_reset(struct hpsb_host *host) -{ - unsigned long flags; - struct host_info *hi; - struct file_info *fi; - struct pending_request *req; - - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(host); - - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - if (fi->notification == RAW1394_NOTIFY_ON) { - req = __alloc_pending_request(GFP_ATOMIC); - - if (req != NULL) { - req->file_info = fi; - req->req.type = RAW1394_REQ_BUS_RESET; - req->req.generation = - get_hpsb_generation(host); - req->req.misc = (host->node_id << 16) - | host->node_count; - if (fi->protocol_version > 3) { - req->req.misc |= - (NODEID_TO_NODE - (host->irm_id) - << 8); - } - - queue_complete_req(req); - } - } - } - } - spin_unlock_irqrestore(&host_info_lock, flags); -} - -static void fcp_request(struct hpsb_host *host, int nodeid, int direction, - int cts, u8 * data, size_t length) -{ - unsigned long flags; - struct host_info *hi; - struct file_info *fi; - struct pending_request *req, *req_next; - struct iso_block_store *ibs = NULL; - LIST_HEAD(reqs); - - if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) { - HPSB_INFO("dropped fcp request"); - return; - } - - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(host); - - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - if (!fi->fcp_buffer) - continue; - - req = __alloc_pending_request(GFP_ATOMIC); - if (!req) - break; - - if (!ibs) { - ibs = kmalloc(sizeof(*ibs) + length, - GFP_ATOMIC); - if (!ibs) { - kfree(req); - break; - } - - atomic_add(length, &iso_buffer_size); - atomic_set(&ibs->refcount, 0); - ibs->data_size = length; - memcpy(ibs->data, data, length); - } - - atomic_inc(&ibs->refcount); - - req->file_info = fi; - req->ibs = ibs; - req->data = ibs->data; - req->req.type = RAW1394_REQ_FCP_REQUEST; - req->req.generation = get_hpsb_generation(host); - req->req.misc = nodeid | (direction << 16); - req->req.recvb = ptr2int(fi->fcp_buffer); - req->req.length = length; - - list_add_tail(&req->list, &reqs); - } - } - spin_unlock_irqrestore(&host_info_lock, flags); - - list_for_each_entry_safe(req, req_next, &reqs, list) - queue_complete_req(req); -} - -#ifdef CONFIG_COMPAT -struct compat_raw1394_req { - __u32 type; - __s32 error; - __u32 misc; - - __u32 generation; - __u32 length; - - __u64 address; - - __u64 tag; - - __u64 sendb; - __u64 recvb; -} -#if defined(CONFIG_X86_64) || defined(CONFIG_IA64) -__attribute__((packed)) -#endif -; - -static const char __user *raw1394_compat_write(const char __user *buf) -{ - struct compat_raw1394_req __user *cr = (typeof(cr)) buf; - struct raw1394_request __user *r; - - r = compat_alloc_user_space(sizeof(struct raw1394_request)); - -#define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x)) - - if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) || - C(address) || - C(tag) || - C(sendb) || - C(recvb)) - return (__force const char __user *)ERR_PTR(-EFAULT); - - return (const char __user *)r; -} -#undef C - -#define P(x) __put_user(r->x, &cr->x) - -static int -raw1394_compat_read(const char __user *buf, struct raw1394_request *r) -{ - struct compat_raw1394_req __user *cr = (typeof(cr)) buf; - - if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) || - P(type) || - P(error) || - P(misc) || - P(generation) || - P(length) || - P(address) || - P(tag) || - P(sendb) || - P(recvb)) - return -EFAULT; - - return sizeof(struct compat_raw1394_req); -} -#undef P - -#endif - -/* get next completed request (caller must hold fi->reqlists_lock) */ -static inline struct pending_request *__next_complete_req(struct file_info *fi) -{ - struct list_head *lh; - struct pending_request *req = NULL; - - if (!list_empty(&fi->req_complete)) { - lh = fi->req_complete.next; - list_del(lh); - req = list_entry(lh, struct pending_request, list); - } - return req; -} - -/* atomically get next completed request */ -static struct pending_request *next_complete_req(struct file_info *fi) -{ - unsigned long flags; - struct pending_request *req; - - spin_lock_irqsave(&fi->reqlists_lock, flags); - req = __next_complete_req(fi); - spin_unlock_irqrestore(&fi->reqlists_lock, flags); - return req; -} - -static ssize_t raw1394_read(struct file *file, char __user * buffer, - size_t count, loff_t * offset_is_ignored) -{ - struct file_info *fi = file->private_data; - struct pending_request *req; - ssize_t ret; - -#ifdef CONFIG_COMPAT - if (count == sizeof(struct compat_raw1394_req)) { - /* ok */ - } else -#endif - if (count != sizeof(struct raw1394_request)) { - return -EINVAL; - } - - if (!access_ok(VERIFY_WRITE, buffer, count)) { - return -EFAULT; - } - - if (file->f_flags & O_NONBLOCK) { - if (!(req = next_complete_req(fi))) - return -EAGAIN; - } else { - /* - * NB: We call the macro wait_event_interruptible() with a - * condition argument with side effect. This is only possible - * because the side effect does not occur until the condition - * became true, and wait_event_interruptible() won't evaluate - * the condition again after that. - */ - if (wait_event_interruptible(fi->wait_complete, - (req = next_complete_req(fi)))) - return -ERESTARTSYS; - } - - if (req->req.length) { - if (copy_to_user(int2ptr(req->req.recvb), req->data, - req->req.length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - } - } - -#ifdef CONFIG_COMPAT - if (count == sizeof(struct compat_raw1394_req) && - sizeof(struct compat_raw1394_req) != - sizeof(struct raw1394_request)) { - ret = raw1394_compat_read(buffer, &req->req); - } else -#endif - { - if (copy_to_user(buffer, &req->req, sizeof(req->req))) { - ret = -EFAULT; - goto out; - } - ret = (ssize_t) sizeof(struct raw1394_request); - } - out: - free_pending_request(req); - return ret; -} - -static int state_opened(struct file_info *fi, struct pending_request *req) -{ - if (req->req.type == RAW1394_REQ_INITIALIZE) { - switch (req->req.misc) { - case RAW1394_KERNELAPI_VERSION: - case 3: - fi->state = initialized; - fi->protocol_version = req->req.misc; - req->req.error = RAW1394_ERROR_NONE; - req->req.generation = atomic_read(&internal_generation); - break; - - default: - req->req.error = RAW1394_ERROR_COMPAT; - req->req.misc = RAW1394_KERNELAPI_VERSION; - } - } else { - req->req.error = RAW1394_ERROR_STATE_ORDER; - } - - req->req.length = 0; - queue_complete_req(req); - return 0; -} - -static int state_initialized(struct file_info *fi, struct pending_request *req) -{ - unsigned long flags; - struct host_info *hi; - struct raw1394_khost_list *khl; - - if (req->req.generation != atomic_read(&internal_generation)) { - req->req.error = RAW1394_ERROR_GENERATION; - req->req.generation = atomic_read(&internal_generation); - req->req.length = 0; - queue_complete_req(req); - return 0; - } - - switch (req->req.type) { - case RAW1394_REQ_LIST_CARDS: - spin_lock_irqsave(&host_info_lock, flags); - khl = kmalloc(sizeof(*khl) * host_count, GFP_ATOMIC); - - if (khl) { - req->req.misc = host_count; - req->data = (quadlet_t *) khl; - - list_for_each_entry(hi, &host_info_list, list) { - khl->nodes = hi->host->node_count; - strcpy(khl->name, hi->host->driver->name); - khl++; - } - } - spin_unlock_irqrestore(&host_info_lock, flags); - - if (khl) { - req->req.error = RAW1394_ERROR_NONE; - req->req.length = min(req->req.length, - (u32) (sizeof - (struct raw1394_khost_list) - * req->req.misc)); - req->free_data = 1; - } else { - return -ENOMEM; - } - break; - - case RAW1394_REQ_SET_CARD: - spin_lock_irqsave(&host_info_lock, flags); - if (req->req.misc >= host_count) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - goto out_set_card; - } - list_for_each_entry(hi, &host_info_list, list) - if (!req->req.misc--) - break; - get_device(&hi->host->device); /* FIXME handle failure case */ - list_add_tail(&fi->list, &hi->file_info_list); - - /* prevent unloading of the host's low-level driver */ - if (!try_module_get(hi->host->driver->owner)) { - req->req.error = RAW1394_ERROR_ABORTED; - goto out_set_card; - } - WARN_ON(fi->host); - fi->host = hi->host; - fi->state = connected; - - req->req.error = RAW1394_ERROR_NONE; - req->req.generation = get_hpsb_generation(fi->host); - req->req.misc = (fi->host->node_id << 16) - | fi->host->node_count; - if (fi->protocol_version > 3) - req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8; -out_set_card: - spin_unlock_irqrestore(&host_info_lock, flags); - - req->req.length = 0; - break; - - default: - req->req.error = RAW1394_ERROR_STATE_ORDER; - req->req.length = 0; - break; - } - - queue_complete_req(req); - return 0; -} - -static void handle_fcp_listen(struct file_info *fi, struct pending_request *req) -{ - if (req->req.misc) { - if (fi->fcp_buffer) { - req->req.error = RAW1394_ERROR_ALREADY; - } else { - fi->fcp_buffer = int2ptr(req->req.recvb); - } - } else { - if (!fi->fcp_buffer) { - req->req.error = RAW1394_ERROR_ALREADY; - } else { - fi->fcp_buffer = NULL; - } - } - - req->req.length = 0; - queue_complete_req(req); -} - -static int handle_async_request(struct file_info *fi, - struct pending_request *req, int node) -{ - unsigned long flags; - struct hpsb_packet *packet = NULL; - u64 addr = req->req.address & 0xffffffffffffULL; - - switch (req->req.type) { - case RAW1394_REQ_ASYNC_READ: - DBGMSG("read_request called"); - packet = - hpsb_make_readpacket(fi->host, node, addr, req->req.length); - - if (!packet) - return -ENOMEM; - - if (req->req.length == 4) - req->data = &packet->header[3]; - else - req->data = packet->data; - - break; - - case RAW1394_REQ_ASYNC_WRITE: - DBGMSG("write_request called"); - - packet = hpsb_make_writepacket(fi->host, node, addr, NULL, - req->req.length); - if (!packet) - return -ENOMEM; - - if (req->req.length == 4) { - if (copy_from_user - (&packet->header[3], int2ptr(req->req.sendb), - req->req.length)) - req->req.error = RAW1394_ERROR_MEMFAULT; - } else { - if (copy_from_user - (packet->data, int2ptr(req->req.sendb), - req->req.length)) - req->req.error = RAW1394_ERROR_MEMFAULT; - } - - req->req.length = 0; - break; - - case RAW1394_REQ_ASYNC_STREAM: - DBGMSG("stream_request called"); - - packet = - hpsb_make_streampacket(fi->host, NULL, req->req.length, - node & 0x3f /*channel */ , - (req->req.misc >> 16) & 0x3, - req->req.misc & 0xf); - if (!packet) - return -ENOMEM; - - if (copy_from_user(packet->data, int2ptr(req->req.sendb), - req->req.length)) - req->req.error = RAW1394_ERROR_MEMFAULT; - - req->req.length = 0; - break; - - case RAW1394_REQ_LOCK: - DBGMSG("lock_request called"); - if ((req->req.misc == EXTCODE_FETCH_ADD) - || (req->req.misc == EXTCODE_LITTLE_ADD)) { - if (req->req.length != 4) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - break; - } - } else { - if (req->req.length != 8) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - break; - } - } - - packet = hpsb_make_lockpacket(fi->host, node, addr, - req->req.misc, NULL, 0); - if (!packet) - return -ENOMEM; - - if (copy_from_user(packet->data, int2ptr(req->req.sendb), - req->req.length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - break; - } - - req->data = packet->data; - req->req.length = 4; - break; - - case RAW1394_REQ_LOCK64: - DBGMSG("lock64_request called"); - if ((req->req.misc == EXTCODE_FETCH_ADD) - || (req->req.misc == EXTCODE_LITTLE_ADD)) { - if (req->req.length != 8) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - break; - } - } else { - if (req->req.length != 16) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - break; - } - } - packet = hpsb_make_lock64packet(fi->host, node, addr, - req->req.misc, NULL, 0); - if (!packet) - return -ENOMEM; - - if (copy_from_user(packet->data, int2ptr(req->req.sendb), - req->req.length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - break; - } - - req->data = packet->data; - req->req.length = 8; - break; - - default: - req->req.error = RAW1394_ERROR_STATE_ORDER; - } - - req->packet = packet; - - if (req->req.error) { - req->req.length = 0; - queue_complete_req(req); - return 0; - } - - hpsb_set_packet_complete_task(packet, - (void (*)(void *))queue_complete_cb, req); - - spin_lock_irqsave(&fi->reqlists_lock, flags); - list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irqrestore(&fi->reqlists_lock, flags); - - packet->generation = req->req.generation; - - if (hpsb_send_packet(packet) < 0) { - req->req.error = RAW1394_ERROR_SEND_ERROR; - req->req.length = 0; - hpsb_free_tlabel(packet); - queue_complete_req(req); - } - return 0; -} - -static int handle_async_send(struct file_info *fi, struct pending_request *req) -{ - unsigned long flags; - struct hpsb_packet *packet; - int header_length = req->req.misc & 0xffff; - int expect_response = req->req.misc >> 16; - size_t data_size; - - if (header_length > req->req.length || header_length < 12 || - header_length > FIELD_SIZEOF(struct hpsb_packet, header)) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - req->req.length = 0; - queue_complete_req(req); - return 0; - } - - data_size = req->req.length - header_length; - packet = hpsb_alloc_packet(data_size); - req->packet = packet; - if (!packet) - return -ENOMEM; - - if (copy_from_user(packet->header, int2ptr(req->req.sendb), - header_length)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - req->req.length = 0; - queue_complete_req(req); - return 0; - } - - if (copy_from_user - (packet->data, int2ptr(req->req.sendb) + header_length, - data_size)) { - req->req.error = RAW1394_ERROR_MEMFAULT; - req->req.length = 0; - queue_complete_req(req); - return 0; - } - - packet->type = hpsb_async; - packet->node_id = packet->header[0] >> 16; - packet->tcode = (packet->header[0] >> 4) & 0xf; - packet->tlabel = (packet->header[0] >> 10) & 0x3f; - packet->host = fi->host; - packet->expect_response = expect_response; - packet->header_size = header_length; - packet->data_size = data_size; - - req->req.length = 0; - hpsb_set_packet_complete_task(packet, - (void (*)(void *))queue_complete_cb, req); - - spin_lock_irqsave(&fi->reqlists_lock, flags); - list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irqrestore(&fi->reqlists_lock, flags); - - /* Update the generation of the packet just before sending. */ - packet->generation = req->req.generation; - - if (hpsb_send_packet(packet) < 0) { - req->req.error = RAW1394_ERROR_SEND_ERROR; - queue_complete_req(req); - } - - return 0; -} - -static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer, - u64 addr, size_t length, u16 flags) -{ - unsigned long irqflags; - struct pending_request *req; - struct host_info *hi; - struct file_info *fi = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - struct arm_request *arm_req = NULL; - struct arm_response *arm_resp = NULL; - int found = 0, size = 0, rcode = -1; - struct arm_request_response *arm_req_resp = NULL; - - DBGMSG("arm_read called by node: %X " - "addr: %4.4x %8.8x length: %Zu", nodeid, - (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), - length); - spin_lock_irqsave(&host_info_lock, irqflags); - hi = find_host_info(host); /* search address-entry */ - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = - list_entry(entry, struct arm_addr, - addr_list); - if (((arm_addr->start) <= (addr)) - && ((arm_addr->end) >= (addr + length))) { - found = 1; - break; - } - entry = entry->next; - } - if (found) { - break; - } - } - } - rcode = -1; - if (!found) { - printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found" - " -> rcode_address_error\n"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_ADDRESS_ERROR); - } else { - DBGMSG("arm_read addr_entry FOUND"); - } - if (arm_addr->rec_length < length) { - DBGMSG("arm_read blocklength too big -> rcode_data_error"); - rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */ - } - if (rcode == -1) { - if (arm_addr->access_rights & ARM_READ) { - if (!(arm_addr->client_transactions & ARM_READ)) { - memcpy(buffer, - (arm_addr->addr_space_buffer) + (addr - - (arm_addr-> - start)), - length); - DBGMSG("arm_read -> (rcode_complete)"); - rcode = RCODE_COMPLETE; - } - } else { - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - DBGMSG("arm_read -> rcode_type_error (access denied)"); - } - } - if (arm_addr->notification_options & ARM_READ) { - DBGMSG("arm_read -> entering notification-section"); - req = __alloc_pending_request(GFP_ATOMIC); - if (!req) { - DBGMSG("arm_read -> rcode_conflict_error"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - if (rcode == RCODE_COMPLETE) { - size = - sizeof(struct arm_request) + - sizeof(struct arm_response) + - length * sizeof(byte_t) + - sizeof(struct arm_request_response); - } else { - size = - sizeof(struct arm_request) + - sizeof(struct arm_response) + - sizeof(struct arm_request_response); - } - req->data = kmalloc(size, GFP_ATOMIC); - if (!(req->data)) { - free_pending_request(req); - DBGMSG("arm_read -> rcode_conflict_error"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - req->free_data = 1; - req->file_info = fi; - req->req.type = RAW1394_REQ_ARM; - req->req.generation = get_hpsb_generation(host); - req->req.misc = - (((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF)); - req->req.tag = arm_addr->arm_tag; - req->req.recvb = arm_addr->recvb; - req->req.length = size; - arm_req_resp = (struct arm_request_response *)(req->data); - arm_req = (struct arm_request *)((byte_t *) (req->data) + - (sizeof - (struct - arm_request_response))); - arm_resp = - (struct arm_response *)((byte_t *) (arm_req) + - (sizeof(struct arm_request))); - arm_req->buffer = NULL; - arm_resp->buffer = NULL; - if (rcode == RCODE_COMPLETE) { - byte_t *buf = - (byte_t *) arm_resp + sizeof(struct arm_response); - memcpy(buf, - (arm_addr->addr_space_buffer) + (addr - - (arm_addr-> - start)), - length); - arm_resp->buffer = - int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request) + - sizeof(struct arm_response)); - } - arm_resp->buffer_length = - (rcode == RCODE_COMPLETE) ? length : 0; - arm_resp->response_code = rcode; - arm_req->buffer_length = 0; - arm_req->generation = req->req.generation; - arm_req->extended_transaction_code = 0; - arm_req->destination_offset = addr; - arm_req->source_nodeid = nodeid; - arm_req->destination_nodeid = host->node_id; - arm_req->tlabel = (flags >> 10) & 0x3f; - arm_req->tcode = (flags >> 4) & 0x0f; - arm_req_resp->request = int2ptr((arm_addr->recvb) + - sizeof(struct - arm_request_response)); - arm_req_resp->response = - int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request)); - queue_complete_req(req); - } - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (rcode); -} - -static int arm_write(struct hpsb_host *host, int nodeid, int destid, - quadlet_t * data, u64 addr, size_t length, u16 flags) -{ - unsigned long irqflags; - struct pending_request *req; - struct host_info *hi; - struct file_info *fi = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - struct arm_request *arm_req = NULL; - struct arm_response *arm_resp = NULL; - int found = 0, size = 0, rcode = -1; - struct arm_request_response *arm_req_resp = NULL; - - DBGMSG("arm_write called by node: %X " - "addr: %4.4x %8.8x length: %Zu", nodeid, - (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF), - length); - spin_lock_irqsave(&host_info_lock, irqflags); - hi = find_host_info(host); /* search address-entry */ - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = - list_entry(entry, struct arm_addr, - addr_list); - if (((arm_addr->start) <= (addr)) - && ((arm_addr->end) >= (addr + length))) { - found = 1; - break; - } - entry = entry->next; - } - if (found) { - break; - } - } - } - rcode = -1; - if (!found) { - printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found" - " -> rcode_address_error\n"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_ADDRESS_ERROR); - } else { - DBGMSG("arm_write addr_entry FOUND"); - } - if (arm_addr->rec_length < length) { - DBGMSG("arm_write blocklength too big -> rcode_data_error"); - rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */ - } - if (rcode == -1) { - if (arm_addr->access_rights & ARM_WRITE) { - if (!(arm_addr->client_transactions & ARM_WRITE)) { - memcpy((arm_addr->addr_space_buffer) + - (addr - (arm_addr->start)), data, - length); - DBGMSG("arm_write -> (rcode_complete)"); - rcode = RCODE_COMPLETE; - } - } else { - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - DBGMSG("arm_write -> rcode_type_error (access denied)"); - } - } - if (arm_addr->notification_options & ARM_WRITE) { - DBGMSG("arm_write -> entering notification-section"); - req = __alloc_pending_request(GFP_ATOMIC); - if (!req) { - DBGMSG("arm_write -> rcode_conflict_error"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request my be retried */ - } - size = - sizeof(struct arm_request) + sizeof(struct arm_response) + - (length) * sizeof(byte_t) + - sizeof(struct arm_request_response); - req->data = kmalloc(size, GFP_ATOMIC); - if (!(req->data)) { - free_pending_request(req); - DBGMSG("arm_write -> rcode_conflict_error"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - req->free_data = 1; - req->file_info = fi; - req->req.type = RAW1394_REQ_ARM; - req->req.generation = get_hpsb_generation(host); - req->req.misc = - (((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF)); - req->req.tag = arm_addr->arm_tag; - req->req.recvb = arm_addr->recvb; - req->req.length = size; - arm_req_resp = (struct arm_request_response *)(req->data); - arm_req = (struct arm_request *)((byte_t *) (req->data) + - (sizeof - (struct - arm_request_response))); - arm_resp = - (struct arm_response *)((byte_t *) (arm_req) + - (sizeof(struct arm_request))); - arm_resp->buffer = NULL; - memcpy((byte_t *) arm_resp + sizeof(struct arm_response), - data, length); - arm_req->buffer = int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request) + - sizeof(struct arm_response)); - arm_req->buffer_length = length; - arm_req->generation = req->req.generation; - arm_req->extended_transaction_code = 0; - arm_req->destination_offset = addr; - arm_req->source_nodeid = nodeid; - arm_req->destination_nodeid = destid; - arm_req->tlabel = (flags >> 10) & 0x3f; - arm_req->tcode = (flags >> 4) & 0x0f; - arm_resp->buffer_length = 0; - arm_resp->response_code = rcode; - arm_req_resp->request = int2ptr((arm_addr->recvb) + - sizeof(struct - arm_request_response)); - arm_req_resp->response = - int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request)); - queue_complete_req(req); - } - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (rcode); -} - -static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store, - u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, - u16 flags) -{ - unsigned long irqflags; - struct pending_request *req; - struct host_info *hi; - struct file_info *fi = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - struct arm_request *arm_req = NULL; - struct arm_response *arm_resp = NULL; - int found = 0, size = 0, rcode = -1; - quadlet_t old, new; - struct arm_request_response *arm_req_resp = NULL; - - if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) || - ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) { - DBGMSG("arm_lock called by node: %X " - "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X", - nodeid, (u16) ((addr >> 32) & 0xFFFF), - (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF, - be32_to_cpu(data)); - } else { - DBGMSG("arm_lock called by node: %X " - "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X", - nodeid, (u16) ((addr >> 32) & 0xFFFF), - (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF, - be32_to_cpu(data), be32_to_cpu(arg)); - } - spin_lock_irqsave(&host_info_lock, irqflags); - hi = find_host_info(host); /* search address-entry */ - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = - list_entry(entry, struct arm_addr, - addr_list); - if (((arm_addr->start) <= (addr)) - && ((arm_addr->end) >= - (addr + sizeof(*store)))) { - found = 1; - break; - } - entry = entry->next; - } - if (found) { - break; - } - } - } - rcode = -1; - if (!found) { - printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found" - " -> rcode_address_error\n"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_ADDRESS_ERROR); - } else { - DBGMSG("arm_lock addr_entry FOUND"); - } - if (rcode == -1) { - if (arm_addr->access_rights & ARM_LOCK) { - if (!(arm_addr->client_transactions & ARM_LOCK)) { - memcpy(&old, - (arm_addr->addr_space_buffer) + (addr - - (arm_addr-> - start)), - sizeof(old)); - switch (ext_tcode) { - case (EXTCODE_MASK_SWAP): - new = data | (old & ~arg); - break; - case (EXTCODE_COMPARE_SWAP): - if (old == arg) { - new = data; - } else { - new = old; - } - break; - case (EXTCODE_FETCH_ADD): - new = - cpu_to_be32(be32_to_cpu(data) + - be32_to_cpu(old)); - break; - case (EXTCODE_LITTLE_ADD): - new = - cpu_to_le32(le32_to_cpu(data) + - le32_to_cpu(old)); - break; - case (EXTCODE_BOUNDED_ADD): - if (old != arg) { - new = - cpu_to_be32(be32_to_cpu - (data) + - be32_to_cpu - (old)); - } else { - new = old; - } - break; - case (EXTCODE_WRAP_ADD): - if (old != arg) { - new = - cpu_to_be32(be32_to_cpu - (data) + - be32_to_cpu - (old)); - } else { - new = data; - } - break; - default: - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - printk(KERN_ERR - "raw1394: arm_lock FAILED " - "ext_tcode not allowed -> rcode_type_error\n"); - break; - } /*switch */ - if (rcode == -1) { - DBGMSG("arm_lock -> (rcode_complete)"); - rcode = RCODE_COMPLETE; - memcpy(store, &old, sizeof(*store)); - memcpy((arm_addr->addr_space_buffer) + - (addr - (arm_addr->start)), - &new, sizeof(*store)); - } - } - } else { - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - DBGMSG("arm_lock -> rcode_type_error (access denied)"); - } - } - if (arm_addr->notification_options & ARM_LOCK) { - byte_t *buf1, *buf2; - DBGMSG("arm_lock -> entering notification-section"); - req = __alloc_pending_request(GFP_ATOMIC); - if (!req) { - DBGMSG("arm_lock -> rcode_conflict_error"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */ - req->data = kmalloc(size, GFP_ATOMIC); - if (!(req->data)) { - free_pending_request(req); - DBGMSG("arm_lock -> rcode_conflict_error"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - req->free_data = 1; - arm_req_resp = (struct arm_request_response *)(req->data); - arm_req = (struct arm_request *)((byte_t *) (req->data) + - (sizeof - (struct - arm_request_response))); - arm_resp = - (struct arm_response *)((byte_t *) (arm_req) + - (sizeof(struct arm_request))); - buf1 = (byte_t *) arm_resp + sizeof(struct arm_response); - buf2 = buf1 + 2 * sizeof(*store); - if ((ext_tcode == EXTCODE_FETCH_ADD) || - (ext_tcode == EXTCODE_LITTLE_ADD)) { - arm_req->buffer_length = sizeof(*store); - memcpy(buf1, &data, sizeof(*store)); - - } else { - arm_req->buffer_length = 2 * sizeof(*store); - memcpy(buf1, &arg, sizeof(*store)); - memcpy(buf1 + sizeof(*store), &data, sizeof(*store)); - } - if (rcode == RCODE_COMPLETE) { - arm_resp->buffer_length = sizeof(*store); - memcpy(buf2, &old, sizeof(*store)); - } else { - arm_resp->buffer_length = 0; - } - req->file_info = fi; - req->req.type = RAW1394_REQ_ARM; - req->req.generation = get_hpsb_generation(host); - req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) | - (ARM_LOCK & 0xFF)); - req->req.tag = arm_addr->arm_tag; - req->req.recvb = arm_addr->recvb; - req->req.length = size; - arm_req->generation = req->req.generation; - arm_req->extended_transaction_code = ext_tcode; - arm_req->destination_offset = addr; - arm_req->source_nodeid = nodeid; - arm_req->destination_nodeid = host->node_id; - arm_req->tlabel = (flags >> 10) & 0x3f; - arm_req->tcode = (flags >> 4) & 0x0f; - arm_resp->response_code = rcode; - arm_req_resp->request = int2ptr((arm_addr->recvb) + - sizeof(struct - arm_request_response)); - arm_req_resp->response = - int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request)); - arm_req->buffer = - int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request) + - sizeof(struct arm_response)); - arm_resp->buffer = - int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request) + - sizeof(struct arm_response) + 2 * sizeof(*store)); - queue_complete_req(req); - } - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (rcode); -} - -static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store, - u64 addr, octlet_t data, octlet_t arg, int ext_tcode, - u16 flags) -{ - unsigned long irqflags; - struct pending_request *req; - struct host_info *hi; - struct file_info *fi = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - struct arm_request *arm_req = NULL; - struct arm_response *arm_resp = NULL; - int found = 0, size = 0, rcode = -1; - octlet_t old, new; - struct arm_request_response *arm_req_resp = NULL; - - if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) || - ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) { - DBGMSG("arm_lock64 called by node: %X " - "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ", - nodeid, (u16) ((addr >> 32) & 0xFFFF), - (u32) (addr & 0xFFFFFFFF), - ext_tcode & 0xFF, - (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), - (u32) (be64_to_cpu(data) & 0xFFFFFFFF)); - } else { - DBGMSG("arm_lock64 called by node: %X " - "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: " - "%8.8X %8.8X ", - nodeid, (u16) ((addr >> 32) & 0xFFFF), - (u32) (addr & 0xFFFFFFFF), - ext_tcode & 0xFF, - (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF), - (u32) (be64_to_cpu(data) & 0xFFFFFFFF), - (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF), - (u32) (be64_to_cpu(arg) & 0xFFFFFFFF)); - } - spin_lock_irqsave(&host_info_lock, irqflags); - hi = find_host_info(host); /* search addressentry in file_info's for host */ - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = - list_entry(entry, struct arm_addr, - addr_list); - if (((arm_addr->start) <= (addr)) - && ((arm_addr->end) >= - (addr + sizeof(*store)))) { - found = 1; - break; - } - entry = entry->next; - } - if (found) { - break; - } - } - } - rcode = -1; - if (!found) { - printk(KERN_ERR - "raw1394: arm_lock64 FAILED addr_entry not found" - " -> rcode_address_error\n"); - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (RCODE_ADDRESS_ERROR); - } else { - DBGMSG("arm_lock64 addr_entry FOUND"); - } - if (rcode == -1) { - if (arm_addr->access_rights & ARM_LOCK) { - if (!(arm_addr->client_transactions & ARM_LOCK)) { - memcpy(&old, - (arm_addr->addr_space_buffer) + (addr - - (arm_addr-> - start)), - sizeof(old)); - switch (ext_tcode) { - case (EXTCODE_MASK_SWAP): - new = data | (old & ~arg); - break; - case (EXTCODE_COMPARE_SWAP): - if (old == arg) { - new = data; - } else { - new = old; - } - break; - case (EXTCODE_FETCH_ADD): - new = - cpu_to_be64(be64_to_cpu(data) + - be64_to_cpu(old)); - break; - case (EXTCODE_LITTLE_ADD): - new = - cpu_to_le64(le64_to_cpu(data) + - le64_to_cpu(old)); - break; - case (EXTCODE_BOUNDED_ADD): - if (old != arg) { - new = - cpu_to_be64(be64_to_cpu - (data) + - be64_to_cpu - (old)); - } else { - new = old; - } - break; - case (EXTCODE_WRAP_ADD): - if (old != arg) { - new = - cpu_to_be64(be64_to_cpu - (data) + - be64_to_cpu - (old)); - } else { - new = data; - } - break; - default: - printk(KERN_ERR - "raw1394: arm_lock64 FAILED " - "ext_tcode not allowed -> rcode_type_error\n"); - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - break; - } /*switch */ - if (rcode == -1) { - DBGMSG - ("arm_lock64 -> (rcode_complete)"); - rcode = RCODE_COMPLETE; - memcpy(store, &old, sizeof(*store)); - memcpy((arm_addr->addr_space_buffer) + - (addr - (arm_addr->start)), - &new, sizeof(*store)); - } - } - } else { - rcode = RCODE_TYPE_ERROR; /* function not allowed */ - DBGMSG - ("arm_lock64 -> rcode_type_error (access denied)"); - } - } - if (arm_addr->notification_options & ARM_LOCK) { - byte_t *buf1, *buf2; - DBGMSG("arm_lock64 -> entering notification-section"); - req = __alloc_pending_request(GFP_ATOMIC); - if (!req) { - spin_unlock_irqrestore(&host_info_lock, irqflags); - DBGMSG("arm_lock64 -> rcode_conflict_error"); - return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response); /* maximum */ - req->data = kmalloc(size, GFP_ATOMIC); - if (!(req->data)) { - free_pending_request(req); - spin_unlock_irqrestore(&host_info_lock, irqflags); - DBGMSG("arm_lock64 -> rcode_conflict_error"); - return (RCODE_CONFLICT_ERROR); /* A resource conflict was detected. - The request may be retried */ - } - req->free_data = 1; - arm_req_resp = (struct arm_request_response *)(req->data); - arm_req = (struct arm_request *)((byte_t *) (req->data) + - (sizeof - (struct - arm_request_response))); - arm_resp = - (struct arm_response *)((byte_t *) (arm_req) + - (sizeof(struct arm_request))); - buf1 = (byte_t *) arm_resp + sizeof(struct arm_response); - buf2 = buf1 + 2 * sizeof(*store); - if ((ext_tcode == EXTCODE_FETCH_ADD) || - (ext_tcode == EXTCODE_LITTLE_ADD)) { - arm_req->buffer_length = sizeof(*store); - memcpy(buf1, &data, sizeof(*store)); - - } else { - arm_req->buffer_length = 2 * sizeof(*store); - memcpy(buf1, &arg, sizeof(*store)); - memcpy(buf1 + sizeof(*store), &data, sizeof(*store)); - } - if (rcode == RCODE_COMPLETE) { - arm_resp->buffer_length = sizeof(*store); - memcpy(buf2, &old, sizeof(*store)); - } else { - arm_resp->buffer_length = 0; - } - req->file_info = fi; - req->req.type = RAW1394_REQ_ARM; - req->req.generation = get_hpsb_generation(host); - req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) | - (ARM_LOCK & 0xFF)); - req->req.tag = arm_addr->arm_tag; - req->req.recvb = arm_addr->recvb; - req->req.length = size; - arm_req->generation = req->req.generation; - arm_req->extended_transaction_code = ext_tcode; - arm_req->destination_offset = addr; - arm_req->source_nodeid = nodeid; - arm_req->destination_nodeid = host->node_id; - arm_req->tlabel = (flags >> 10) & 0x3f; - arm_req->tcode = (flags >> 4) & 0x0f; - arm_resp->response_code = rcode; - arm_req_resp->request = int2ptr((arm_addr->recvb) + - sizeof(struct - arm_request_response)); - arm_req_resp->response = - int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request)); - arm_req->buffer = - int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request) + - sizeof(struct arm_response)); - arm_resp->buffer = - int2ptr((arm_addr->recvb) + - sizeof(struct arm_request_response) + - sizeof(struct arm_request) + - sizeof(struct arm_response) + 2 * sizeof(*store)); - queue_complete_req(req); - } - spin_unlock_irqrestore(&host_info_lock, irqflags); - return (rcode); -} - -static int arm_register(struct file_info *fi, struct pending_request *req) -{ - int retval; - struct arm_addr *addr; - struct host_info *hi; - struct file_info *fi_hlp = NULL; - struct list_head *entry; - struct arm_addr *arm_addr = NULL; - int same_host, another_host; - unsigned long flags; - - DBGMSG("arm_register called " - "addr(Offset): %8.8x %8.8x length: %u " - "rights: %2.2X notify: %2.2X " - "max_blk_len: %4.4X", - (u32) ((req->req.address >> 32) & 0xFFFF), - (u32) (req->req.address & 0xFFFFFFFF), - req->req.length, ((req->req.misc >> 8) & 0xFF), - (req->req.misc & 0xFF), ((req->req.misc >> 16) & 0xFFFF)); - /* check addressrange */ - if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) || - (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) != - 0)) { - req->req.length = 0; - return (-EINVAL); - } - /* addr-list-entry for fileinfo */ - addr = kmalloc(sizeof(*addr), GFP_KERNEL); - if (!addr) { - req->req.length = 0; - return (-ENOMEM); - } - /* allocation of addr_space_buffer */ - addr->addr_space_buffer = vmalloc(req->req.length); - if (!(addr->addr_space_buffer)) { - kfree(addr); - req->req.length = 0; - return (-ENOMEM); - } - /* initialization of addr_space_buffer */ - if ((req->req.sendb) == (unsigned long)NULL) { - /* init: set 0 */ - memset(addr->addr_space_buffer, 0, req->req.length); - } else { - /* init: user -> kernel */ - if (copy_from_user - (addr->addr_space_buffer, int2ptr(req->req.sendb), - req->req.length)) { - vfree(addr->addr_space_buffer); - kfree(addr); - return (-EFAULT); - } - } - INIT_LIST_HEAD(&addr->addr_list); - addr->arm_tag = req->req.tag; - addr->start = req->req.address; - addr->end = req->req.address + req->req.length; - addr->access_rights = (u8) (req->req.misc & 0x0F); - addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F); - addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F); - addr->access_rights |= addr->client_transactions; - addr->notification_options |= addr->client_transactions; - addr->recvb = req->req.recvb; - addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF); - - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(fi->host); - same_host = 0; - another_host = 0; - /* same host with address-entry containing same addressrange ? */ - list_for_each_entry(fi_hlp, &hi->file_info_list, list) { - entry = fi_hlp->addr_list.next; - while (entry != &(fi_hlp->addr_list)) { - arm_addr = - list_entry(entry, struct arm_addr, addr_list); - if ((arm_addr->start == addr->start) - && (arm_addr->end == addr->end)) { - DBGMSG("same host ownes same " - "addressrange -> EALREADY"); - same_host = 1; - break; - } - entry = entry->next; - } - if (same_host) { - break; - } - } - if (same_host) { - /* addressrange occupied by same host */ - spin_unlock_irqrestore(&host_info_lock, flags); - vfree(addr->addr_space_buffer); - kfree(addr); - return (-EALREADY); - } - /* another host with valid address-entry containing same addressrange */ - list_for_each_entry(hi, &host_info_list, list) { - if (hi->host != fi->host) { - list_for_each_entry(fi_hlp, &hi->file_info_list, list) { - entry = fi_hlp->addr_list.next; - while (entry != &(fi_hlp->addr_list)) { - arm_addr = - list_entry(entry, struct arm_addr, - addr_list); - if ((arm_addr->start == addr->start) - && (arm_addr->end == addr->end)) { - DBGMSG - ("another host ownes same " - "addressrange"); - another_host = 1; - break; - } - entry = entry->next; - } - if (another_host) { - break; - } - } - } - } - spin_unlock_irqrestore(&host_info_lock, flags); - - if (another_host) { - DBGMSG("another hosts entry is valid -> SUCCESS"); - if (copy_to_user(int2ptr(req->req.recvb), - &addr->start, sizeof(u64))) { - printk(KERN_ERR "raw1394: arm_register failed " - " address-range-entry is invalid -> EFAULT !!!\n"); - vfree(addr->addr_space_buffer); - kfree(addr); - return (-EFAULT); - } - free_pending_request(req); /* immediate success or fail */ - /* INSERT ENTRY */ - spin_lock_irqsave(&host_info_lock, flags); - list_add_tail(&addr->addr_list, &fi->addr_list); - spin_unlock_irqrestore(&host_info_lock, flags); - return 0; - } - retval = - hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops, - req->req.address, - req->req.address + req->req.length); - if (retval) { - /* INSERT ENTRY */ - spin_lock_irqsave(&host_info_lock, flags); - list_add_tail(&addr->addr_list, &fi->addr_list); - spin_unlock_irqrestore(&host_info_lock, flags); - } else { - DBGMSG("arm_register failed errno: %d \n", retval); - vfree(addr->addr_space_buffer); - kfree(addr); - return (-EALREADY); - } - free_pending_request(req); /* immediate success or fail */ - return 0; -} - -static int arm_unregister(struct file_info *fi, struct pending_request *req) -{ - int found = 0; - int retval = 0; - struct list_head *entry; - struct arm_addr *addr = NULL; - struct host_info *hi; - struct file_info *fi_hlp = NULL; - struct arm_addr *arm_addr = NULL; - int another_host; - unsigned long flags; - - DBGMSG("arm_Unregister called addr(Offset): " - "%8.8x %8.8x", - (u32) ((req->req.address >> 32) & 0xFFFF), - (u32) (req->req.address & 0xFFFFFFFF)); - spin_lock_irqsave(&host_info_lock, flags); - /* get addr */ - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - addr = list_entry(entry, struct arm_addr, addr_list); - if (addr->start == req->req.address) { - found = 1; - break; - } - entry = entry->next; - } - if (!found) { - DBGMSG("arm_Unregister addr not found"); - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EINVAL); - } - DBGMSG("arm_Unregister addr found"); - another_host = 0; - /* another host with valid address-entry containing - same addressrange */ - list_for_each_entry(hi, &host_info_list, list) { - if (hi->host != fi->host) { - list_for_each_entry(fi_hlp, &hi->file_info_list, list) { - entry = fi_hlp->addr_list.next; - while (entry != &(fi_hlp->addr_list)) { - arm_addr = list_entry(entry, - struct arm_addr, - addr_list); - if (arm_addr->start == addr->start) { - DBGMSG("another host ownes " - "same addressrange"); - another_host = 1; - break; - } - entry = entry->next; - } - if (another_host) { - break; - } - } - } - } - if (another_host) { - DBGMSG("delete entry from list -> success"); - list_del(&addr->addr_list); - spin_unlock_irqrestore(&host_info_lock, flags); - vfree(addr->addr_space_buffer); - kfree(addr); - free_pending_request(req); /* immediate success or fail */ - return 0; - } - retval = - hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, - addr->start); - if (!retval) { - printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n"); - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EINVAL); - } - DBGMSG("delete entry from list -> success"); - list_del(&addr->addr_list); - spin_unlock_irqrestore(&host_info_lock, flags); - vfree(addr->addr_space_buffer); - kfree(addr); - free_pending_request(req); /* immediate success or fail */ - return 0; -} - -/* Copy data from ARM buffer(s) to user buffer. */ -static int arm_get_buf(struct file_info *fi, struct pending_request *req) -{ - struct arm_addr *arm_addr = NULL; - unsigned long flags; - unsigned long offset; - - struct list_head *entry; - - DBGMSG("arm_get_buf " - "addr(Offset): %04X %08X length: %u", - (u32) ((req->req.address >> 32) & 0xFFFF), - (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length); - - spin_lock_irqsave(&host_info_lock, flags); - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = list_entry(entry, struct arm_addr, addr_list); - if ((arm_addr->start <= req->req.address) && - (arm_addr->end > req->req.address)) { - if (req->req.address + req->req.length <= arm_addr->end) { - offset = req->req.address - arm_addr->start; - spin_unlock_irqrestore(&host_info_lock, flags); - - DBGMSG - ("arm_get_buf copy_to_user( %08X, %p, %u )", - (u32) req->req.recvb, - arm_addr->addr_space_buffer + offset, - (u32) req->req.length); - if (copy_to_user - (int2ptr(req->req.recvb), - arm_addr->addr_space_buffer + offset, - req->req.length)) - return (-EFAULT); - - /* We have to free the request, because we - * queue no response, and therefore nobody - * will free it. */ - free_pending_request(req); - return 0; - } else { - DBGMSG("arm_get_buf request exceeded mapping"); - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EINVAL); - } - } - entry = entry->next; - } - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EINVAL); -} - -/* Copy data from user buffer to ARM buffer(s). */ -static int arm_set_buf(struct file_info *fi, struct pending_request *req) -{ - struct arm_addr *arm_addr = NULL; - unsigned long flags; - unsigned long offset; - - struct list_head *entry; - - DBGMSG("arm_set_buf " - "addr(Offset): %04X %08X length: %u", - (u32) ((req->req.address >> 32) & 0xFFFF), - (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length); - - spin_lock_irqsave(&host_info_lock, flags); - entry = fi->addr_list.next; - while (entry != &(fi->addr_list)) { - arm_addr = list_entry(entry, struct arm_addr, addr_list); - if ((arm_addr->start <= req->req.address) && - (arm_addr->end > req->req.address)) { - if (req->req.address + req->req.length <= arm_addr->end) { - offset = req->req.address - arm_addr->start; - spin_unlock_irqrestore(&host_info_lock, flags); - - DBGMSG - ("arm_set_buf copy_from_user( %p, %08X, %u )", - arm_addr->addr_space_buffer + offset, - (u32) req->req.sendb, - (u32) req->req.length); - if (copy_from_user - (arm_addr->addr_space_buffer + offset, - int2ptr(req->req.sendb), - req->req.length)) - return (-EFAULT); - - /* We have to free the request, because we - * queue no response, and therefore nobody - * will free it. */ - free_pending_request(req); - return 0; - } else { - DBGMSG("arm_set_buf request exceeded mapping"); - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EINVAL); - } - } - entry = entry->next; - } - spin_unlock_irqrestore(&host_info_lock, flags); - return (-EINVAL); -} - -static int reset_notification(struct file_info *fi, struct pending_request *req) -{ - DBGMSG("reset_notification called - switch %s ", - (req->req.misc == RAW1394_NOTIFY_OFF) ? "OFF" : "ON"); - if ((req->req.misc == RAW1394_NOTIFY_OFF) || - (req->req.misc == RAW1394_NOTIFY_ON)) { - fi->notification = (u8) req->req.misc; - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - return 0; - } - /* error EINVAL (22) invalid argument */ - return (-EINVAL); -} - -static int write_phypacket(struct file_info *fi, struct pending_request *req) -{ - struct hpsb_packet *packet = NULL; - int retval = 0; - quadlet_t data; - unsigned long flags; - - data = be32_to_cpu((u32) req->req.sendb); - DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data); - packet = hpsb_make_phypacket(fi->host, data); - if (!packet) - return -ENOMEM; - req->req.length = 0; - req->packet = packet; - hpsb_set_packet_complete_task(packet, - (void (*)(void *))queue_complete_cb, req); - spin_lock_irqsave(&fi->reqlists_lock, flags); - list_add_tail(&req->list, &fi->req_pending); - spin_unlock_irqrestore(&fi->reqlists_lock, flags); - packet->generation = req->req.generation; - retval = hpsb_send_packet(packet); - DBGMSG("write_phypacket send_packet called => retval: %d ", retval); - if (retval < 0) { - req->req.error = RAW1394_ERROR_SEND_ERROR; - req->req.length = 0; - queue_complete_req(req); - } - return 0; -} - -static int get_config_rom(struct file_info *fi, struct pending_request *req) -{ - int ret = 0; - quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); - int status; - - if (!data) - return -ENOMEM; - - status = - csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET, - data, req->req.length); - if (copy_to_user(int2ptr(req->req.recvb), data, req->req.length)) - ret = -EFAULT; - if (copy_to_user - (int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len, - sizeof(fi->host->csr.rom->cache_head->len))) - ret = -EFAULT; - if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation, - sizeof(fi->host->csr.generation))) - ret = -EFAULT; - if (copy_to_user(int2ptr(req->req.sendb), &status, sizeof(status))) - ret = -EFAULT; - kfree(data); - if (ret >= 0) { - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - } - return ret; -} - -static int update_config_rom(struct file_info *fi, struct pending_request *req) -{ - int ret = 0; - quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL); - if (!data) - return -ENOMEM; - if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) { - ret = -EFAULT; - } else { - int status = hpsb_update_config_rom(fi->host, - data, req->req.length, - (unsigned char)req->req. - misc); - if (copy_to_user - (int2ptr(req->req.recvb), &status, sizeof(status))) - ret = -ENOMEM; - } - kfree(data); - if (ret >= 0) { - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - fi->cfgrom_upd = 1; - } - return ret; -} - -static int modify_config_rom(struct file_info *fi, struct pending_request *req) -{ - struct csr1212_keyval *kv; - struct csr1212_csr_rom_cache *cache; - struct csr1212_dentry *dentry; - u32 dr; - int ret = 0; - - if (req->req.misc == ~0) { - if (req->req.length == 0) - return -EINVAL; - - /* Find an unused slot */ - for (dr = 0; - dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr]; - dr++) ; - - if (dr == RAW1394_MAX_USER_CSR_DIRS) - return -ENOMEM; - - fi->csr1212_dirs[dr] = - csr1212_new_directory(CSR1212_KV_ID_VENDOR); - if (!fi->csr1212_dirs[dr]) - return -ENOMEM; - } else { - dr = req->req.misc; - if (!fi->csr1212_dirs[dr]) - return -EINVAL; - - /* Delete old stuff */ - for (dentry = - fi->csr1212_dirs[dr]->value.directory.dentries_head; - dentry; dentry = dentry->next) { - csr1212_detach_keyval_from_directory(fi->host->csr.rom-> - root_kv, - dentry->kv); - } - - if (req->req.length == 0) { - csr1212_release_keyval(fi->csr1212_dirs[dr]); - fi->csr1212_dirs[dr] = NULL; - - hpsb_update_config_rom_image(fi->host); - free_pending_request(req); - return 0; - } - } - - cache = csr1212_rom_cache_malloc(0, req->req.length); - if (!cache) { - csr1212_release_keyval(fi->csr1212_dirs[dr]); - fi->csr1212_dirs[dr] = NULL; - return -ENOMEM; - } - - cache->filled_head = kmalloc(sizeof(*cache->filled_head), GFP_KERNEL); - if (!cache->filled_head) { - csr1212_release_keyval(fi->csr1212_dirs[dr]); - fi->csr1212_dirs[dr] = NULL; - CSR1212_FREE(cache); - return -ENOMEM; - } - cache->filled_tail = cache->filled_head; - - if (copy_from_user(cache->data, int2ptr(req->req.sendb), - req->req.length)) { - csr1212_release_keyval(fi->csr1212_dirs[dr]); - fi->csr1212_dirs[dr] = NULL; - ret = -EFAULT; - } else { - cache->len = req->req.length; - cache->filled_head->offset_start = 0; - cache->filled_head->offset_end = cache->size - 1; - - cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr]; - - ret = CSR1212_SUCCESS; - /* parse all the items */ - for (kv = cache->layout_head; ret == CSR1212_SUCCESS && kv; - kv = kv->next) { - ret = csr1212_parse_keyval(kv, cache); - } - - /* attach top level items to the root directory */ - for (dentry = - fi->csr1212_dirs[dr]->value.directory.dentries_head; - ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) { - ret = - csr1212_attach_keyval_to_directory(fi->host->csr. - rom->root_kv, - dentry->kv); - } - - if (ret == CSR1212_SUCCESS) { - ret = hpsb_update_config_rom_image(fi->host); - - if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb), - &dr, sizeof(dr))) { - ret = -ENOMEM; - } - } - } - kfree(cache->filled_head); - CSR1212_FREE(cache); - - if (ret >= 0) { - /* we have to free the request, because we queue no response, - * and therefore nobody will free it */ - free_pending_request(req); - return 0; - } else { - for (dentry = - fi->csr1212_dirs[dr]->value.directory.dentries_head; - dentry; dentry = dentry->next) { - csr1212_detach_keyval_from_directory(fi->host->csr.rom-> - root_kv, - dentry->kv); - } - csr1212_release_keyval(fi->csr1212_dirs[dr]); - fi->csr1212_dirs[dr] = NULL; - return ret; - } -} - -static int state_connected(struct file_info *fi, struct pending_request *req) -{ - int node = req->req.address >> 48; - - req->req.error = RAW1394_ERROR_NONE; - - switch (req->req.type) { - - case RAW1394_REQ_ECHO: - queue_complete_req(req); - return 0; - - case RAW1394_REQ_ARM_REGISTER: - return arm_register(fi, req); - - case RAW1394_REQ_ARM_UNREGISTER: - return arm_unregister(fi, req); - - case RAW1394_REQ_ARM_SET_BUF: - return arm_set_buf(fi, req); - - case RAW1394_REQ_ARM_GET_BUF: - return arm_get_buf(fi, req); - - case RAW1394_REQ_RESET_NOTIFY: - return reset_notification(fi, req); - - case RAW1394_REQ_ISO_SEND: - case RAW1394_REQ_ISO_LISTEN: - printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n"); - req->req.error = RAW1394_ERROR_COMPAT; - req->req.misc = RAW1394_KERNELAPI_VERSION; - queue_complete_req(req); - return 0; - - case RAW1394_REQ_FCP_LISTEN: - handle_fcp_listen(fi, req); - return 0; - - case RAW1394_REQ_RESET_BUS: - if (req->req.misc == RAW1394_LONG_RESET) { - DBGMSG("busreset called (type: LONG)"); - hpsb_reset_bus(fi->host, LONG_RESET); - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - return 0; - } - if (req->req.misc == RAW1394_SHORT_RESET) { - DBGMSG("busreset called (type: SHORT)"); - hpsb_reset_bus(fi->host, SHORT_RESET); - free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */ - return 0; - } - /* error EINVAL (22) invalid argument */ - return (-EINVAL); - case RAW1394_REQ_GET_ROM: - return get_config_rom(fi, req); - - case RAW1394_REQ_UPDATE_ROM: - return update_config_rom(fi, req); - - case RAW1394_REQ_MODIFY_ROM: - return modify_config_rom(fi, req); - } - - if (req->req.generation != get_hpsb_generation(fi->host)) { - req->req.error = RAW1394_ERROR_GENERATION; - req->req.generation = get_hpsb_generation(fi->host); - req->req.length = 0; - queue_complete_req(req); - return 0; - } - - switch (req->req.type) { - case RAW1394_REQ_PHYPACKET: - return write_phypacket(fi, req); - case RAW1394_REQ_ASYNC_SEND: - return handle_async_send(fi, req); - } - - if (req->req.length == 0) { - req->req.error = RAW1394_ERROR_INVALID_ARG; - queue_complete_req(req); - return 0; - } - - return handle_async_request(fi, req, node); -} - -static ssize_t raw1394_write(struct file *file, const char __user * buffer, - size_t count, loff_t * offset_is_ignored) -{ - struct file_info *fi = file->private_data; - struct pending_request *req; - ssize_t retval = -EBADFD; - -#ifdef CONFIG_COMPAT - if (count == sizeof(struct compat_raw1394_req) && - sizeof(struct compat_raw1394_req) != - sizeof(struct raw1394_request)) { - buffer = raw1394_compat_write(buffer); - if (IS_ERR((__force void *)buffer)) - return PTR_ERR((__force void *)buffer); - } else -#endif - if (count != sizeof(struct raw1394_request)) { - return -EINVAL; - } - - req = alloc_pending_request(); - if (req == NULL) { - return -ENOMEM; - } - req->file_info = fi; - - if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) { - free_pending_request(req); - return -EFAULT; - } - - if (!mutex_trylock(&fi->state_mutex)) { - free_pending_request(req); - return -EAGAIN; - } - - switch (fi->state) { - case opened: - retval = state_opened(fi, req); - break; - - case initialized: - retval = state_initialized(fi, req); - break; - - case connected: - retval = state_connected(fi, req); - break; - } - - mutex_unlock(&fi->state_mutex); - - if (retval < 0) { - free_pending_request(req); - } else { - BUG_ON(retval); - retval = count; - } - - return retval; -} - -/* rawiso operations */ - -/* check if any RAW1394_REQ_RAWISO_ACTIVITY event is already in the - * completion queue (reqlists_lock must be taken) */ -static inline int __rawiso_event_in_queue(struct file_info *fi) -{ - struct pending_request *req; - - list_for_each_entry(req, &fi->req_complete, list) - if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) - return 1; - - return 0; -} - -/* put a RAWISO_ACTIVITY event in the queue, if one isn't there already */ -static void queue_rawiso_event(struct file_info *fi) -{ - unsigned long flags; - - spin_lock_irqsave(&fi->reqlists_lock, flags); - - /* only one ISO activity event may be in the queue */ - if (!__rawiso_event_in_queue(fi)) { - struct pending_request *req = - __alloc_pending_request(GFP_ATOMIC); - - if (req) { - req->file_info = fi; - req->req.type = RAW1394_REQ_RAWISO_ACTIVITY; - req->req.generation = get_hpsb_generation(fi->host); - __queue_complete_req(req); - } else { - /* on allocation failure, signal an overflow */ - if (fi->iso_handle) { - atomic_inc(&fi->iso_handle->overflows); - } - } - } - spin_unlock_irqrestore(&fi->reqlists_lock, flags); -} - -static void rawiso_activity_cb(struct hpsb_iso *iso) -{ - unsigned long flags; - struct host_info *hi; - struct file_info *fi; - - spin_lock_irqsave(&host_info_lock, flags); - hi = find_host_info(iso->host); - - if (hi != NULL) { - list_for_each_entry(fi, &hi->file_info_list, list) { - if (fi->iso_handle == iso) - queue_rawiso_event(fi); - } - } - - spin_unlock_irqrestore(&host_info_lock, flags); -} - -/* helper function - gather all the kernel iso status bits for returning to user-space */ -static void raw1394_iso_fill_status(struct hpsb_iso *iso, - struct raw1394_iso_status *stat) -{ - int overflows = atomic_read(&iso->overflows); - int skips = atomic_read(&iso->skips); - - stat->config.data_buf_size = iso->buf_size; - stat->config.buf_packets = iso->buf_packets; - stat->config.channel = iso->channel; - stat->config.speed = iso->speed; - stat->config.irq_interval = iso->irq_interval; - stat->n_packets = hpsb_iso_n_ready(iso); - stat->overflows = ((skips & 0xFFFF) << 16) | ((overflows & 0xFFFF)); - stat->xmit_cycle = iso->xmit_cycle; -} - -static int raw1394_iso_xmit_init(struct file_info *fi, void __user * uaddr) -{ - struct raw1394_iso_status stat; - - if (!fi->host) - return -EINVAL; - - if (copy_from_user(&stat, uaddr, sizeof(stat))) - return -EFAULT; - - fi->iso_handle = hpsb_iso_xmit_init(fi->host, - stat.config.data_buf_size, - stat.config.buf_packets, - stat.config.channel, - stat.config.speed, - stat.config.irq_interval, - rawiso_activity_cb); - if (!fi->iso_handle) - return -ENOMEM; - - fi->iso_state = RAW1394_ISO_XMIT; - - raw1394_iso_fill_status(fi->iso_handle, &stat); - if (copy_to_user(uaddr, &stat, sizeof(stat))) - return -EFAULT; - - /* queue an event to get things started */ - rawiso_activity_cb(fi->iso_handle); - - return 0; -} - -static int raw1394_iso_recv_init(struct file_info *fi, void __user * uaddr) -{ - struct raw1394_iso_status stat; - - if (!fi->host) - return -EINVAL; - - if (copy_from_user(&stat, uaddr, sizeof(stat))) - return -EFAULT; - - fi->iso_handle = hpsb_iso_recv_init(fi->host, - stat.config.data_buf_size, - stat.config.buf_packets, - stat.config.channel, - stat.config.dma_mode, - stat.config.irq_interval, - rawiso_activity_cb); - if (!fi->iso_handle) - return -ENOMEM; - - fi->iso_state = RAW1394_ISO_RECV; - - raw1394_iso_fill_status(fi->iso_handle, &stat); - if (copy_to_user(uaddr, &stat, sizeof(stat))) - return -EFAULT; - return 0; -} - -static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr) -{ - struct raw1394_iso_status stat; - struct hpsb_iso *iso = fi->iso_handle; - - raw1394_iso_fill_status(fi->iso_handle, &stat); - if (copy_to_user(uaddr, &stat, sizeof(stat))) - return -EFAULT; - - /* reset overflow counter */ - atomic_set(&iso->overflows, 0); - /* reset skip counter */ - atomic_set(&iso->skips, 0); - - return 0; -} - -/* copy N packet_infos out of the ringbuffer into user-supplied array */ -static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr) -{ - struct raw1394_iso_packets upackets; - unsigned int packet = fi->iso_handle->first_packet; - int i; - - if (copy_from_user(&upackets, uaddr, sizeof(upackets))) - return -EFAULT; - - if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle)) - return -EINVAL; - - /* ensure user-supplied buffer is accessible and big enough */ - if (!access_ok(VERIFY_WRITE, upackets.infos, - upackets.n_packets * - sizeof(struct raw1394_iso_packet_info))) - return -EFAULT; - - /* copy the packet_infos out */ - for (i = 0; i < upackets.n_packets; i++) { - if (__copy_to_user(&upackets.infos[i], - &fi->iso_handle->infos[packet], - sizeof(struct raw1394_iso_packet_info))) - return -EFAULT; - - packet = (packet + 1) % fi->iso_handle->buf_packets; - } - - return 0; -} - -/* copy N packet_infos from user to ringbuffer, and queue them for transmission */ -static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr) -{ - struct raw1394_iso_packets upackets; - int i, rv; - - if (copy_from_user(&upackets, uaddr, sizeof(upackets))) - return -EFAULT; - - if (upackets.n_packets >= fi->iso_handle->buf_packets) - return -EINVAL; - - if (upackets.n_packets >= hpsb_iso_n_ready(fi->iso_handle)) - return -EAGAIN; - - /* ensure user-supplied buffer is accessible and big enough */ - if (!access_ok(VERIFY_READ, upackets.infos, - upackets.n_packets * - sizeof(struct raw1394_iso_packet_info))) - return -EFAULT; - - /* copy the infos structs in and queue the packets */ - for (i = 0; i < upackets.n_packets; i++) { - struct raw1394_iso_packet_info info; - - if (__copy_from_user(&info, &upackets.infos[i], - sizeof(struct raw1394_iso_packet_info))) - return -EFAULT; - - rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset, - info.len, info.tag, info.sy); - if (rv) - return rv; - } - - return 0; -} - -static void raw1394_iso_shutdown(struct file_info *fi) -{ - if (fi->iso_handle) - hpsb_iso_shutdown(fi->iso_handle); - - fi->iso_handle = NULL; - fi->iso_state = RAW1394_ISO_INACTIVE; -} - -static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr) -{ - struct raw1394_cycle_timer ct; - int err; - - err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time); - if (!err) - if (copy_to_user(uaddr, &ct, sizeof(ct))) - err = -EFAULT; - return err; -} - -/* mmap the rawiso xmit/recv buffer */ -static int raw1394_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct file_info *fi = file->private_data; - int ret; - - if (!mutex_trylock(&fi->state_mutex)) - return -EAGAIN; - - if (fi->iso_state == RAW1394_ISO_INACTIVE) - ret = -EINVAL; - else - ret = dma_region_mmap(&fi->iso_handle->data_buf, file, vma); - - mutex_unlock(&fi->state_mutex); - - return ret; -} - -static long raw1394_ioctl_inactive(struct file_info *fi, unsigned int cmd, - void __user *argp) -{ - switch (cmd) { - case RAW1394_IOC_ISO_XMIT_INIT: - return raw1394_iso_xmit_init(fi, argp); - case RAW1394_IOC_ISO_RECV_INIT: - return raw1394_iso_recv_init(fi, argp); - default: - return -EINVAL; - } -} - -static long raw1394_ioctl_recv(struct file_info *fi, unsigned int cmd, - unsigned long arg) -{ - void __user *argp = (void __user *)arg; - - switch (cmd) { - case RAW1394_IOC_ISO_RECV_START:{ - int args[3]; - - if (copy_from_user(&args[0], argp, sizeof(args))) - return -EFAULT; - return hpsb_iso_recv_start(fi->iso_handle, - args[0], args[1], args[2]); - } - case RAW1394_IOC_ISO_XMIT_RECV_STOP: - hpsb_iso_stop(fi->iso_handle); - return 0; - case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL: - return hpsb_iso_recv_listen_channel(fi->iso_handle, arg); - case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL: - return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg); - case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{ - u64 mask; - - if (copy_from_user(&mask, argp, sizeof(mask))) - return -EFAULT; - return hpsb_iso_recv_set_channel_mask(fi->iso_handle, - mask); - } - case RAW1394_IOC_ISO_GET_STATUS: - return raw1394_iso_get_status(fi, argp); - case RAW1394_IOC_ISO_RECV_PACKETS: - return raw1394_iso_recv_packets(fi, argp); - case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: - return hpsb_iso_recv_release_packets(fi->iso_handle, arg); - case RAW1394_IOC_ISO_RECV_FLUSH: - return hpsb_iso_recv_flush(fi->iso_handle); - case RAW1394_IOC_ISO_SHUTDOWN: - raw1394_iso_shutdown(fi); - return 0; - case RAW1394_IOC_ISO_QUEUE_ACTIVITY: - queue_rawiso_event(fi); - return 0; - default: - return -EINVAL; - } -} - -static long raw1394_ioctl_xmit(struct file_info *fi, unsigned int cmd, - void __user *argp) -{ - switch (cmd) { - case RAW1394_IOC_ISO_XMIT_START:{ - int args[2]; - - if (copy_from_user(&args[0], argp, sizeof(args))) - return -EFAULT; - return hpsb_iso_xmit_start(fi->iso_handle, - args[0], args[1]); - } - case RAW1394_IOC_ISO_XMIT_SYNC: - return hpsb_iso_xmit_sync(fi->iso_handle); - case RAW1394_IOC_ISO_XMIT_RECV_STOP: - hpsb_iso_stop(fi->iso_handle); - return 0; - case RAW1394_IOC_ISO_GET_STATUS: - return raw1394_iso_get_status(fi, argp); - case RAW1394_IOC_ISO_XMIT_PACKETS: - return raw1394_iso_send_packets(fi, argp); - case RAW1394_IOC_ISO_SHUTDOWN: - raw1394_iso_shutdown(fi); - return 0; - case RAW1394_IOC_ISO_QUEUE_ACTIVITY: - queue_rawiso_event(fi); - return 0; - default: - return -EINVAL; - } -} - -/* ioctl is only used for rawiso operations */ -static long raw1394_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - struct file_info *fi = file->private_data; - void __user *argp = (void __user *)arg; - long ret; - - /* state-independent commands */ - switch(cmd) { - case RAW1394_IOC_GET_CYCLE_TIMER: - return raw1394_read_cycle_timer(fi, argp); - default: - break; - } - - if (!mutex_trylock(&fi->state_mutex)) - return -EAGAIN; - - switch (fi->iso_state) { - case RAW1394_ISO_INACTIVE: - ret = raw1394_ioctl_inactive(fi, cmd, argp); - break; - case RAW1394_ISO_RECV: - ret = raw1394_ioctl_recv(fi, cmd, arg); - break; - case RAW1394_ISO_XMIT: - ret = raw1394_ioctl_xmit(fi, cmd, argp); - break; - default: - ret = -EINVAL; - break; - } - - mutex_unlock(&fi->state_mutex); - - return ret; -} - -#ifdef CONFIG_COMPAT -struct raw1394_iso_packets32 { - __u32 n_packets; - compat_uptr_t infos; -} __attribute__((packed)); - -struct raw1394_cycle_timer32 { - __u32 cycle_timer; - __u64 local_time; -} -#if defined(CONFIG_X86_64) || defined(CONFIG_IA64) -__attribute__((packed)) -#endif -; - -#define RAW1394_IOC_ISO_RECV_PACKETS32 \ - _IOW ('#', 0x25, struct raw1394_iso_packets32) -#define RAW1394_IOC_ISO_XMIT_PACKETS32 \ - _IOW ('#', 0x27, struct raw1394_iso_packets32) -#define RAW1394_IOC_GET_CYCLE_TIMER32 \ - _IOR ('#', 0x30, struct raw1394_cycle_timer32) - -static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd, - struct raw1394_iso_packets32 __user *arg) -{ - compat_uptr_t infos32; - void __user *infos; - long err = -EFAULT; - struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets)); - - if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) && - !copy_from_user(&infos32, &arg->infos, sizeof infos32)) { - infos = compat_ptr(infos32); - if (!copy_to_user(&dst->infos, &infos, sizeof infos)) - err = raw1394_ioctl(file, cmd, (unsigned long)dst); - } - return err; -} - -static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr) -{ - struct raw1394_cycle_timer32 ct; - int err; - - err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time); - if (!err) - if (copy_to_user(uaddr, &ct, sizeof(ct))) - err = -EFAULT; - return err; -} - -static long raw1394_compat_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct file_info *fi = file->private_data; - void __user *argp = (void __user *)arg; - long err; - - switch (cmd) { - /* These requests have same format as long as 'int' has same size. */ - case RAW1394_IOC_ISO_RECV_INIT: - case RAW1394_IOC_ISO_RECV_START: - case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL: - case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL: - case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: - case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS: - case RAW1394_IOC_ISO_RECV_FLUSH: - case RAW1394_IOC_ISO_XMIT_RECV_STOP: - case RAW1394_IOC_ISO_XMIT_INIT: - case RAW1394_IOC_ISO_XMIT_START: - case RAW1394_IOC_ISO_XMIT_SYNC: - case RAW1394_IOC_ISO_GET_STATUS: - case RAW1394_IOC_ISO_SHUTDOWN: - case RAW1394_IOC_ISO_QUEUE_ACTIVITY: - err = raw1394_ioctl(file, cmd, arg); - break; - /* These request have different format. */ - case RAW1394_IOC_ISO_RECV_PACKETS32: - err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp); - break; - case RAW1394_IOC_ISO_XMIT_PACKETS32: - err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp); - break; - case RAW1394_IOC_GET_CYCLE_TIMER32: - err = raw1394_read_cycle_timer32(fi, argp); - break; - default: - err = -EINVAL; - break; - } - - return err; -} -#endif - -static unsigned int raw1394_poll(struct file *file, poll_table * pt) -{ - struct file_info *fi = file->private_data; - unsigned int mask = POLLOUT | POLLWRNORM; - unsigned long flags; - - poll_wait(file, &fi->wait_complete, pt); - - spin_lock_irqsave(&fi->reqlists_lock, flags); - if (!list_empty(&fi->req_complete)) { - mask |= POLLIN | POLLRDNORM; - } - spin_unlock_irqrestore(&fi->reqlists_lock, flags); - - return mask; -} - -static int raw1394_open(struct inode *inode, struct file *file) -{ - struct file_info *fi; - - fi = kzalloc(sizeof(*fi), GFP_KERNEL); - if (!fi) - return -ENOMEM; - - fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */ - - INIT_LIST_HEAD(&fi->list); - mutex_init(&fi->state_mutex); - fi->state = opened; - INIT_LIST_HEAD(&fi->req_pending); - INIT_LIST_HEAD(&fi->req_complete); - spin_lock_init(&fi->reqlists_lock); - init_waitqueue_head(&fi->wait_complete); - INIT_LIST_HEAD(&fi->addr_list); - - file->private_data = fi; - - return nonseekable_open(inode, file); -} - -static int raw1394_release(struct inode *inode, struct file *file) -{ - struct file_info *fi = file->private_data; - struct list_head *lh; - struct pending_request *req; - int i, fail; - int retval = 0; - struct list_head *entry; - struct arm_addr *addr = NULL; - struct host_info *hi; - struct file_info *fi_hlp = NULL; - struct arm_addr *arm_addr = NULL; - int another_host; - int csr_mod = 0; - unsigned long flags; - - if (fi->iso_state != RAW1394_ISO_INACTIVE) - raw1394_iso_shutdown(fi); - - spin_lock_irqsave(&host_info_lock, flags); - - fail = 0; - /* set address-entries invalid */ - - while (!list_empty(&fi->addr_list)) { - another_host = 0; - lh = fi->addr_list.next; - addr = list_entry(lh, struct arm_addr, addr_list); - /* another host with valid address-entry containing - same addressrange? */ - list_for_each_entry(hi, &host_info_list, list) { - if (hi->host != fi->host) { - list_for_each_entry(fi_hlp, &hi->file_info_list, - list) { - entry = fi_hlp->addr_list.next; - while (entry != &(fi_hlp->addr_list)) { - arm_addr = list_entry(entry, struct - arm_addr, - addr_list); - if (arm_addr->start == - addr->start) { - DBGMSG - ("raw1394_release: " - "another host ownes " - "same addressrange"); - another_host = 1; - break; - } - entry = entry->next; - } - if (another_host) { - break; - } - } - } - } - if (!another_host) { - DBGMSG("raw1394_release: call hpsb_arm_unregister"); - retval = - hpsb_unregister_addrspace(&raw1394_highlevel, - fi->host, addr->start); - if (!retval) { - ++fail; - printk(KERN_ERR - "raw1394_release arm_Unregister failed\n"); - } - } - DBGMSG("raw1394_release: delete addr_entry from list"); - list_del(&addr->addr_list); - vfree(addr->addr_space_buffer); - kfree(addr); - } /* while */ - spin_unlock_irqrestore(&host_info_lock, flags); - if (fail > 0) { - printk(KERN_ERR "raw1394: during addr_list-release " - "error(s) occurred \n"); - } - - for (;;) { - /* This locked section guarantees that neither - * complete nor pending requests exist once i!=0 */ - spin_lock_irqsave(&fi->reqlists_lock, flags); - while ((req = __next_complete_req(fi))) - free_pending_request(req); - - i = list_empty(&fi->req_pending); - spin_unlock_irqrestore(&fi->reqlists_lock, flags); - - if (i) - break; - /* - * Sleep until more requests can be freed. - * - * NB: We call the macro wait_event() with a condition argument - * with side effect. This is only possible because the side - * effect does not occur until the condition became true, and - * wait_event() won't evaluate the condition again after that. - */ - wait_event(fi->wait_complete, (req = next_complete_req(fi))); - free_pending_request(req); - } - - /* Remove any sub-trees left by user space programs */ - for (i = 0; i < RAW1394_MAX_USER_CSR_DIRS; i++) { - struct csr1212_dentry *dentry; - if (!fi->csr1212_dirs[i]) - continue; - for (dentry = - fi->csr1212_dirs[i]->value.directory.dentries_head; dentry; - dentry = dentry->next) { - csr1212_detach_keyval_from_directory(fi->host->csr.rom-> - root_kv, - dentry->kv); - } - csr1212_release_keyval(fi->csr1212_dirs[i]); - fi->csr1212_dirs[i] = NULL; - csr_mod = 1; - } - - if ((csr_mod || fi->cfgrom_upd) - && hpsb_update_config_rom_image(fi->host) < 0) - HPSB_ERR - ("Failed to generate Configuration ROM image for host %d", - fi->host->id); - - if (fi->state == connected) { - spin_lock_irqsave(&host_info_lock, flags); - list_del(&fi->list); - spin_unlock_irqrestore(&host_info_lock, flags); - - put_device(&fi->host->device); - } - - spin_lock_irqsave(&host_info_lock, flags); - if (fi->host) - module_put(fi->host->driver->owner); - spin_unlock_irqrestore(&host_info_lock, flags); - - kfree(fi); - - return 0; -} - -/*** HOTPLUG STUFF **********************************************************/ -/* - * Export information about protocols/devices supported by this driver. - */ -#ifdef MODULE -static const struct ieee1394_device_id raw1394_id_table[] = { - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = AVC_SW_VERSION_ENTRY & 0xffffff}, - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = CAMERA_SW_VERSION_ENTRY & 0xffffff}, - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff}, - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff}, - {} -}; - -MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table); -#endif /* MODULE */ - -static struct hpsb_protocol_driver raw1394_driver = { - .name = "raw1394", -}; - -/******************************************************************************/ - -static struct hpsb_highlevel raw1394_highlevel = { - .name = RAW1394_DEVICE_NAME, - .add_host = add_host, - .remove_host = remove_host, - .host_reset = host_reset, - .fcp_request = fcp_request, -}; - -static struct cdev raw1394_cdev; -static const struct file_operations raw1394_fops = { - .owner = THIS_MODULE, - .read = raw1394_read, - .write = raw1394_write, - .mmap = raw1394_mmap, - .unlocked_ioctl = raw1394_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = raw1394_compat_ioctl, -#endif - .poll = raw1394_poll, - .open = raw1394_open, - .release = raw1394_release, - .llseek = no_llseek, -}; - -static int __init init_raw1394(void) -{ - int ret = 0; - - hpsb_register_highlevel(&raw1394_highlevel); - - if (IS_ERR - (device_create(hpsb_protocol_class, NULL, - MKDEV(IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_RAW1394 * 16), - NULL, RAW1394_DEVICE_NAME))) { - ret = -EFAULT; - goto out_unreg; - } - - cdev_init(&raw1394_cdev, &raw1394_fops); - raw1394_cdev.owner = THIS_MODULE; - ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1); - if (ret) { - HPSB_ERR("raw1394 failed to register minor device block"); - goto out_dev; - } - - HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME); - - ret = hpsb_register_protocol(&raw1394_driver); - if (ret) { - HPSB_ERR("raw1394: failed to register protocol"); - cdev_del(&raw1394_cdev); - goto out_dev; - } - - goto out; - - out_dev: - device_destroy(hpsb_protocol_class, - MKDEV(IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_RAW1394 * 16)); - out_unreg: - hpsb_unregister_highlevel(&raw1394_highlevel); - out: - return ret; -} - -static void __exit cleanup_raw1394(void) -{ - device_destroy(hpsb_protocol_class, - MKDEV(IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_RAW1394 * 16)); - cdev_del(&raw1394_cdev); - hpsb_unregister_highlevel(&raw1394_highlevel); - hpsb_unregister_protocol(&raw1394_driver); -} - -module_init(init_raw1394); -module_exit(cleanup_raw1394); -MODULE_LICENSE("GPL"); diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h deleted file mode 100644 index 963ac20..0000000 --- a/drivers/ieee1394/raw1394.h +++ /dev/null @@ -1,191 +0,0 @@ -#ifndef IEEE1394_RAW1394_H -#define IEEE1394_RAW1394_H - -/* header for the raw1394 API that is exported to user-space */ - -#define RAW1394_KERNELAPI_VERSION 4 - -/* state: opened */ -#define RAW1394_REQ_INITIALIZE 1 - -/* state: initialized */ -#define RAW1394_REQ_LIST_CARDS 2 -#define RAW1394_REQ_SET_CARD 3 - -/* state: connected */ -#define RAW1394_REQ_ASYNC_READ 100 -#define RAW1394_REQ_ASYNC_WRITE 101 -#define RAW1394_REQ_LOCK 102 -#define RAW1394_REQ_LOCK64 103 -#define RAW1394_REQ_ISO_SEND 104 /* removed ABI, now a no-op */ -#define RAW1394_REQ_ASYNC_SEND 105 -#define RAW1394_REQ_ASYNC_STREAM 106 - -#define RAW1394_REQ_ISO_LISTEN 200 /* removed ABI, now a no-op */ -#define RAW1394_REQ_FCP_LISTEN 201 -#define RAW1394_REQ_RESET_BUS 202 -#define RAW1394_REQ_GET_ROM 203 -#define RAW1394_REQ_UPDATE_ROM 204 -#define RAW1394_REQ_ECHO 205 -#define RAW1394_REQ_MODIFY_ROM 206 - -#define RAW1394_REQ_ARM_REGISTER 300 -#define RAW1394_REQ_ARM_UNREGISTER 301 -#define RAW1394_REQ_ARM_SET_BUF 302 -#define RAW1394_REQ_ARM_GET_BUF 303 - -#define RAW1394_REQ_RESET_NOTIFY 400 - -#define RAW1394_REQ_PHYPACKET 500 - -/* kernel to user */ -#define RAW1394_REQ_BUS_RESET 10000 -#define RAW1394_REQ_ISO_RECEIVE 10001 -#define RAW1394_REQ_FCP_REQUEST 10002 -#define RAW1394_REQ_ARM 10003 -#define RAW1394_REQ_RAWISO_ACTIVITY 10004 - -/* error codes */ -#define RAW1394_ERROR_NONE 0 -#define RAW1394_ERROR_COMPAT (-1001) -#define RAW1394_ERROR_STATE_ORDER (-1002) -#define RAW1394_ERROR_GENERATION (-1003) -#define RAW1394_ERROR_INVALID_ARG (-1004) -#define RAW1394_ERROR_MEMFAULT (-1005) -#define RAW1394_ERROR_ALREADY (-1006) - -#define RAW1394_ERROR_EXCESSIVE (-1020) -#define RAW1394_ERROR_UNTIDY_LEN (-1021) - -#define RAW1394_ERROR_SEND_ERROR (-1100) -#define RAW1394_ERROR_ABORTED (-1101) -#define RAW1394_ERROR_TIMEOUT (-1102) - -/* arm_codes */ -#define ARM_READ 1 -#define ARM_WRITE 2 -#define ARM_LOCK 4 - -#define RAW1394_LONG_RESET 0 -#define RAW1394_SHORT_RESET 1 - -/* busresetnotify ... */ -#define RAW1394_NOTIFY_OFF 0 -#define RAW1394_NOTIFY_ON 1 - -#include <asm/types.h> - -struct raw1394_request { - __u32 type; - __s32 error; - __u32 misc; - - __u32 generation; - __u32 length; - - __u64 address; - - __u64 tag; - - __u64 sendb; - __u64 recvb; -}; - -struct raw1394_khost_list { - __u32 nodes; - __u8 name[32]; -}; - -typedef struct arm_request { - __u16 destination_nodeid; - __u16 source_nodeid; - __u64 destination_offset; - __u8 tlabel; - __u8 tcode; - __u8 extended_transaction_code; - __u32 generation; - __u16 buffer_length; - __u8 __user *buffer; -} *arm_request_t; - -typedef struct arm_response { - __s32 response_code; - __u16 buffer_length; - __u8 __user *buffer; -} *arm_response_t; - -typedef struct arm_request_response { - struct arm_request __user *request; - struct arm_response __user *response; -} *arm_request_response_t; - -/* rawiso API */ -#include "ieee1394-ioctl.h" - -/* per-packet metadata embedded in the ringbuffer */ -/* must be identical to hpsb_iso_packet_info in iso.h! */ -struct raw1394_iso_packet_info { - __u32 offset; - __u16 len; - __u16 cycle; /* recv only */ - __u8 channel; /* recv only */ - __u8 tag; - __u8 sy; -}; - -/* argument for RAW1394_ISO_RECV/XMIT_PACKETS ioctls */ -struct raw1394_iso_packets { - __u32 n_packets; - struct raw1394_iso_packet_info __user *infos; -}; - -struct raw1394_iso_config { - /* size of packet data buffer, in bytes (will be rounded up to PAGE_SIZE) */ - __u32 data_buf_size; - - /* # of packets to buffer */ - __u32 buf_packets; - - /* iso channel (set to -1 for multi-channel recv) */ - __s32 channel; - - /* xmit only - iso transmission speed */ - __u8 speed; - - /* The mode of the dma when receiving iso data. Must be supported by chip */ - __u8 dma_mode; - - /* max. latency of buffer, in packets (-1 if you don't care) */ - __s32 irq_interval; -}; - -/* argument to RAW1394_ISO_XMIT/RECV_INIT and RAW1394_ISO_GET_STATUS */ -struct raw1394_iso_status { - /* current settings */ - struct raw1394_iso_config config; - - /* number of packets waiting to be filled with data (ISO transmission) - or containing data received (ISO reception) */ - __u32 n_packets; - - /* approximate number of packets dropped due to overflow or - underflow of the packet buffer (a value of zero guarantees - that no packets have been dropped) */ - __u32 overflows; - - /* cycle number at which next packet will be transmitted; - -1 if not known */ - __s16 xmit_cycle; -}; - -/* argument to RAW1394_IOC_GET_CYCLE_TIMER ioctl */ -struct raw1394_cycle_timer { - /* contents of Isochronous Cycle Timer register, - as in OHCI 1.1 clause 5.13 (also with non-OHCI hosts) */ - __u32 cycle_timer; - - /* local time in microseconds since Epoch, - simultaneously read with cycle timer */ - __u64 local_time; -}; -#endif /* IEEE1394_RAW1394_H */ diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c deleted file mode 100644 index d6e251a..0000000 --- a/drivers/ieee1394/sbp2.c +++ /dev/null @@ -1,2138 +0,0 @@ -/* - * sbp2.c - SBP-2 protocol driver for IEEE-1394 - * - * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com) - * jamesg@filanet.com (JSG) - * - * Copyright (C) 2003 Ben Collins <bcollins@debian.org> - * - * 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. - */ - -/* - * Brief Description: - * - * This driver implements the Serial Bus Protocol 2 (SBP-2) over IEEE-1394 - * under Linux. The SBP-2 driver is implemented as an IEEE-1394 high-level - * driver. It also registers as a SCSI lower-level driver in order to accept - * SCSI commands for transport using SBP-2. - * - * You may access any attached SBP-2 (usually storage devices) as regular - * SCSI devices. E.g. mount /dev/sda1, fdisk, mkfs, etc.. - * - * See http://www.t10.org/drafts.htm#sbp2 for the final draft of the SBP-2 - * specification and for where to purchase the official standard. - * - * TODO: - * - look into possible improvements of the SCSI error handlers - * - handle Unit_Characteristics.mgt_ORB_timeout and .ORB_size - * - handle Logical_Unit_Number.ordered - * - handle src == 1 in status blocks - * - reimplement the DMA mapping in absence of physical DMA so that - * bus_to_virt is no longer required - * - debug the handling of absent physical DMA - * - replace CONFIG_IEEE1394_SBP2_PHYS_DMA by automatic detection - * (this is easy but depends on the previous two TODO items) - * - make the parameter serialize_io configurable per device - * - move all requests to fetch agent registers into non-atomic context, - * replace all usages of sbp2util_node_write_no_wait by true transactions - * Grep for inline FIXME comments below. - */ - -#include <linux/blkdev.h> -#include <linux/compiler.h> -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <linux/stat.h> -#include <linux/string.h> -#include <linux/stringify.h> -#include <linux/types.h> -#include <linux/wait.h> -#include <linux/workqueue.h> -#include <linux/scatterlist.h> - -#include <asm/byteorder.h> -#include <asm/errno.h> -#include <asm/param.h> -#include <asm/system.h> -#include <asm/types.h> - -#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA -#include <asm/io.h> /* for bus_to_virt */ -#endif - -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_dbg.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_host.h> - -#include "csr1212.h" -#include "highlevel.h" -#include "hosts.h" -#include "ieee1394.h" -#include "ieee1394_core.h" -#include "ieee1394_hotplug.h" -#include "ieee1394_transactions.h" -#include "ieee1394_types.h" -#include "nodemgr.h" -#include "sbp2.h" - -/* - * Module load parameter definitions - */ - -/* - * Change max_speed on module load if you have a bad IEEE-1394 - * controller that has trouble running 2KB packets at 400mb. - * - * NOTE: On certain OHCI parts I have seen short packets on async transmit - * (probably due to PCI latency/throughput issues with the part). You can - * bump down the speed if you are running into problems. - */ -static int sbp2_max_speed = IEEE1394_SPEED_MAX; -module_param_named(max_speed, sbp2_max_speed, int, 0644); -MODULE_PARM_DESC(max_speed, "Limit data transfer speed (5 <= 3200, " - "4 <= 1600, 3 <= 800, 2 <= 400, 1 <= 200, 0 = 100 Mb/s)"); - -/* - * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs. - * This is and always has been buggy in multiple subtle ways. See above TODOs. - */ -static int sbp2_serialize_io = 1; -module_param_named(serialize_io, sbp2_serialize_io, bool, 0444); -MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers " - "(default = Y, faster but buggy = N)"); - -/* - * Adjust max_sectors if you'd like to influence how many sectors each SCSI - * command can transfer at most. Please note that some older SBP-2 bridge - * chips are broken for transfers greater or equal to 128KB, therefore - * max_sectors used to be a safe 255 sectors for many years. We now have a - * default of 0 here which means that we let the SCSI stack choose a limit. - * - * The SBP2_WORKAROUND_128K_MAX_TRANS flag, if set either in the workarounds - * module parameter or in the sbp2_workarounds_table[], will override the - * value of max_sectors. We should use sbp2_workarounds_table[] to cover any - * bridge chip which becomes known to need the 255 sectors limit. - */ -static int sbp2_max_sectors; -module_param_named(max_sectors, sbp2_max_sectors, int, 0444); -MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported " - "(default = 0 = use SCSI stack's default)"); - -/* - * Exclusive login to sbp2 device? In most cases, the sbp2 driver should - * do an exclusive login, as it's generally unsafe to have two hosts - * talking to a single sbp2 device at the same time (filesystem coherency, - * etc.). If you're running an sbp2 device that supports multiple logins, - * and you're either running read-only filesystems or some sort of special - * filesystem supporting multiple hosts, e.g. OpenGFS, Oracle Cluster - * File System, or Lustre, then set exclusive_login to zero. - * - * So far only bridges from Oxford Semiconductor are known to support - * concurrent logins. Depending on firmware, four or two concurrent logins - * are possible on OXFW911 and newer Oxsemi bridges. - */ -static int sbp2_exclusive_login = 1; -module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644); -MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device " - "(default = Y, use N for concurrent initiators)"); - -/* - * If any of the following workarounds is required for your device to work, - * please submit the kernel messages logged by sbp2 to the linux1394-devel - * mailing list. - * - * - 128kB max transfer - * Limit transfer size. Necessary for some old bridges. - * - * - 36 byte inquiry - * When scsi_mod probes the device, let the inquiry command look like that - * from MS Windows. - * - * - skip mode page 8 - * Suppress sending of mode_sense for mode page 8 if the device pretends to - * support the SCSI Primary Block commands instead of Reduced Block Commands. - * - * - fix capacity - * Tell sd_mod to correct the last sector number reported by read_capacity. - * Avoids access beyond actual disk limits on devices with an off-by-one bug. - * Don't use this with devices which don't have this bug. - * - * - delay inquiry - * Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry. - * - * - power condition - * Set the power condition field in the START STOP UNIT commands sent by - * sd_mod on suspend, resume, and shutdown (if manage_start_stop is on). - * Some disks need this to spin down or to resume properly. - * - * - override internal blacklist - * Instead of adding to the built-in blacklist, use only the workarounds - * specified in the module load parameter. - * Useful if a blacklist entry interfered with a non-broken device. - */ -static int sbp2_default_workarounds; -module_param_named(workarounds, sbp2_default_workarounds, int, 0644); -MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" - ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS) - ", 36 byte inquiry = " __stringify(SBP2_WORKAROUND_INQUIRY_36) - ", skip mode page 8 = " __stringify(SBP2_WORKAROUND_MODE_SENSE_8) - ", fix capacity = " __stringify(SBP2_WORKAROUND_FIX_CAPACITY) - ", delay inquiry = " __stringify(SBP2_WORKAROUND_DELAY_INQUIRY) - ", set power condition in start stop unit = " - __stringify(SBP2_WORKAROUND_POWER_CONDITION) - ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) - ", or a combination)"); - -/* - * This influences the format of the sysfs attribute - * /sys/bus/scsi/devices/.../ieee1394_id. - * - * The default format is like in older kernels: %016Lx:%d:%d - * It contains the target's EUI-64, a number given to the logical unit by - * the ieee1394 driver's nodemgr (starting at 0), and the LUN. - * - * The long format is: %016Lx:%06x:%04x - * It contains the target's EUI-64, the unit directory's directory_ID as per - * IEEE 1212 clause 7.7.19, and the LUN. This format comes closest to the - * format of SBP(-3) target port and logical unit identifier as per SAM (SCSI - * Architecture Model) rev.2 to 4 annex A. Therefore and because it is - * independent of the implementation of the ieee1394 nodemgr, the longer format - * is recommended for future use. - */ -static int sbp2_long_sysfs_ieee1394_id; -module_param_named(long_ieee1394_id, sbp2_long_sysfs_ieee1394_id, bool, 0644); -MODULE_PARM_DESC(long_ieee1394_id, "8+3+2 bytes format of ieee1394_id in sysfs " - "(default = backwards-compatible = N, SAM-conforming = Y)"); - - -#define SBP2_INFO(fmt, args...) HPSB_INFO("sbp2: "fmt, ## args) -#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) - -/* - * Globals - */ -static void sbp2scsi_complete_all_commands(struct sbp2_lu *, u32); -static void sbp2scsi_complete_command(struct sbp2_lu *, u32, struct scsi_cmnd *, - void (*)(struct scsi_cmnd *)); -static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *); -static int sbp2_start_device(struct sbp2_lu *); -static void sbp2_remove_device(struct sbp2_lu *); -static int sbp2_login_device(struct sbp2_lu *); -static int sbp2_reconnect_device(struct sbp2_lu *); -static int sbp2_logout_device(struct sbp2_lu *); -static void sbp2_host_reset(struct hpsb_host *); -static int sbp2_handle_status_write(struct hpsb_host *, int, int, quadlet_t *, - u64, size_t, u16); -static int sbp2_agent_reset(struct sbp2_lu *, int); -static void sbp2_parse_unit_directory(struct sbp2_lu *, - struct unit_directory *); -static int sbp2_set_busy_timeout(struct sbp2_lu *); -static int sbp2_max_speed_and_size(struct sbp2_lu *); - - -static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xa, 0xa, 0xa }; - -static DEFINE_RWLOCK(sbp2_hi_logical_units_lock); - -static struct hpsb_highlevel sbp2_highlevel = { - .name = SBP2_DEVICE_NAME, - .host_reset = sbp2_host_reset, -}; - -static const struct hpsb_address_ops sbp2_ops = { - .write = sbp2_handle_status_write -}; - -#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA -static int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *, - u64, size_t, u16); -static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64, - size_t, u16); - -static const struct hpsb_address_ops sbp2_physdma_ops = { - .read = sbp2_handle_physdma_read, - .write = sbp2_handle_physdma_write, -}; -#endif - - -/* - * Interface to driver core and IEEE 1394 core - */ -static const struct ieee1394_device_id sbp2_id_table[] = { - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = SBP2_SW_VERSION_ENTRY & 0xffffff}, - {} -}; -MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); - -static int sbp2_probe(struct device *); -static int sbp2_remove(struct device *); -static int sbp2_update(struct unit_directory *); - -static struct hpsb_protocol_driver sbp2_driver = { - .name = SBP2_DEVICE_NAME, - .id_table = sbp2_id_table, - .update = sbp2_update, - .driver = { - .probe = sbp2_probe, - .remove = sbp2_remove, - }, -}; - - -/* - * Interface to SCSI core - */ -static int sbp2scsi_queuecommand(struct scsi_cmnd *, - void (*)(struct scsi_cmnd *)); -static int sbp2scsi_abort(struct scsi_cmnd *); -static int sbp2scsi_reset(struct scsi_cmnd *); -static int sbp2scsi_slave_alloc(struct scsi_device *); -static int sbp2scsi_slave_configure(struct scsi_device *); -static void sbp2scsi_slave_destroy(struct scsi_device *); -static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *, - struct device_attribute *, char *); - -static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); - -static struct device_attribute *sbp2_sysfs_sdev_attrs[] = { - &dev_attr_ieee1394_id, - NULL -}; - -static struct scsi_host_template sbp2_shost_template = { - .module = THIS_MODULE, - .name = "SBP-2 IEEE-1394", - .proc_name = SBP2_DEVICE_NAME, - .queuecommand = sbp2scsi_queuecommand, - .eh_abort_handler = sbp2scsi_abort, - .eh_device_reset_handler = sbp2scsi_reset, - .slave_alloc = sbp2scsi_slave_alloc, - .slave_configure = sbp2scsi_slave_configure, - .slave_destroy = sbp2scsi_slave_destroy, - .this_id = -1, - .sg_tablesize = SG_ALL, - .use_clustering = ENABLE_CLUSTERING, - .cmd_per_lun = SBP2_MAX_CMDS, - .can_queue = SBP2_MAX_CMDS, - .sdev_attrs = sbp2_sysfs_sdev_attrs, -}; - -#define SBP2_ROM_VALUE_WILDCARD ~0 /* match all */ -#define SBP2_ROM_VALUE_MISSING 0xff000000 /* not present in the unit dir. */ - -/* - * List of devices with known bugs. - * - * The firmware_revision field, masked with 0xffff00, is the best indicator - * for the type of bridge chip of a device. It yields a few false positives - * but this did not break correctly behaving devices so far. - */ -static const struct { - u32 firmware_revision; - u32 model; - unsigned workarounds; -} sbp2_workarounds_table[] = { - /* DViCO Momobay CX-1 with TSB42AA9 bridge */ { - .firmware_revision = 0x002800, - .model = 0x001010, - .workarounds = SBP2_WORKAROUND_INQUIRY_36 | - SBP2_WORKAROUND_MODE_SENSE_8 | - SBP2_WORKAROUND_POWER_CONDITION, - }, - /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { - .firmware_revision = 0x002800, - .model = 0x000000, - .workarounds = SBP2_WORKAROUND_POWER_CONDITION, - }, - /* Initio bridges, actually only needed for some older ones */ { - .firmware_revision = 0x000200, - .model = SBP2_ROM_VALUE_WILDCARD, - .workarounds = SBP2_WORKAROUND_INQUIRY_36, - }, - /* PL-3507 bridge with Prolific firmware */ { - .firmware_revision = 0x012800, - .model = SBP2_ROM_VALUE_WILDCARD, - .workarounds = SBP2_WORKAROUND_POWER_CONDITION, - }, - /* Symbios bridge */ { - .firmware_revision = 0xa0b800, - .model = SBP2_ROM_VALUE_WILDCARD, - .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, - }, - /* Datafab MD2-FW2 with Symbios/LSILogic SYM13FW500 bridge */ { - .firmware_revision = 0x002600, - .model = SBP2_ROM_VALUE_WILDCARD, - .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS, - }, - /* - * iPod 2nd generation: needs 128k max transfer size workaround - * iPod 3rd generation: needs fix capacity workaround - */ - { - .firmware_revision = 0x0a2700, - .model = 0x000000, - .workarounds = SBP2_WORKAROUND_128K_MAX_TRANS | - SBP2_WORKAROUND_FIX_CAPACITY, - }, - /* iPod 4th generation */ { - .firmware_revision = 0x0a2700, - .model = 0x000021, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - }, - /* iPod mini */ { - .firmware_revision = 0x0a2700, - .model = 0x000022, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - }, - /* iPod mini */ { - .firmware_revision = 0x0a2700, - .model = 0x000023, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - }, - /* iPod Photo */ { - .firmware_revision = 0x0a2700, - .model = 0x00007e, - .workarounds = SBP2_WORKAROUND_FIX_CAPACITY, - } -}; - -/************************************** - * General utility functions - **************************************/ - -#ifndef __BIG_ENDIAN -/* - * Converts a buffer from be32 to cpu byte ordering. Length is in bytes. - */ -static inline void sbp2util_be32_to_cpu_buffer(void *buffer, int length) -{ - u32 *temp = buffer; - - for (length = (length >> 2); length--; ) - temp[length] = be32_to_cpu(temp[length]); -} - -/* - * Converts a buffer from cpu to be32 byte ordering. Length is in bytes. - */ -static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length) -{ - u32 *temp = buffer; - - for (length = (length >> 2); length--; ) - temp[length] = cpu_to_be32(temp[length]); -} -#else /* BIG_ENDIAN */ -/* Why waste the cpu cycles? */ -#define sbp2util_be32_to_cpu_buffer(x,y) do {} while (0) -#define sbp2util_cpu_to_be32_buffer(x,y) do {} while (0) -#endif - -static DECLARE_WAIT_QUEUE_HEAD(sbp2_access_wq); - -/* - * Waits for completion of an SBP-2 access request. - * Returns nonzero if timed out or prematurely interrupted. - */ -static int sbp2util_access_timeout(struct sbp2_lu *lu, int timeout) -{ - long leftover; - - leftover = wait_event_interruptible_timeout( - sbp2_access_wq, lu->access_complete, timeout); - lu->access_complete = 0; - return leftover <= 0; -} - -static void sbp2_free_packet(void *packet) -{ - hpsb_free_tlabel(packet); - hpsb_free_packet(packet); -} - -/* - * This is much like hpsb_node_write(), except it ignores the response - * subaction and returns immediately. Can be used from atomic context. - */ -static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr, - quadlet_t *buf, size_t len) -{ - struct hpsb_packet *packet; - - packet = hpsb_make_writepacket(ne->host, ne->nodeid, addr, buf, len); - if (!packet) - return -ENOMEM; - - hpsb_set_packet_complete_task(packet, sbp2_free_packet, packet); - hpsb_node_fill_packet(ne, packet); - if (hpsb_send_packet(packet) < 0) { - sbp2_free_packet(packet); - return -EIO; - } - return 0; -} - -static void sbp2util_notify_fetch_agent(struct sbp2_lu *lu, u64 offset, - quadlet_t *data, size_t len) -{ - /* There is a small window after a bus reset within which the node - * entry's generation is current but the reconnect wasn't completed. */ - if (unlikely(atomic_read(&lu->state) == SBP2LU_STATE_IN_RESET)) - return; - - if (hpsb_node_write(lu->ne, lu->command_block_agent_addr + offset, - data, len)) - SBP2_ERR("sbp2util_notify_fetch_agent failed."); - - /* Now accept new SCSI commands, unless a bus reset happended during - * hpsb_node_write. */ - if (likely(atomic_read(&lu->state) != SBP2LU_STATE_IN_RESET)) - scsi_unblock_requests(lu->shost); -} - -static void sbp2util_write_orb_pointer(struct work_struct *work) -{ - struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work); - quadlet_t data[2]; - - data[0] = ORB_SET_NODE_ID(lu->hi->host->node_id); - data[1] = lu->last_orb_dma; - sbp2util_cpu_to_be32_buffer(data, 8); - sbp2util_notify_fetch_agent(lu, SBP2_ORB_POINTER_OFFSET, data, 8); -} - -static void sbp2util_write_doorbell(struct work_struct *work) -{ - struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work); - - sbp2util_notify_fetch_agent(lu, SBP2_DOORBELL_OFFSET, NULL, 4); -} - -static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu) -{ - struct sbp2_command_info *cmd; - struct device *dmadev = lu->hi->host->device.parent; - int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS; - - for (i = 0; i < orbs; i++) { - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) - goto failed_alloc; - - cmd->command_orb_dma = - dma_map_single(dmadev, &cmd->command_orb, - sizeof(struct sbp2_command_orb), - DMA_TO_DEVICE); - if (dma_mapping_error(dmadev, cmd->command_orb_dma)) - goto failed_orb; - - cmd->sge_dma = - dma_map_single(dmadev, &cmd->scatter_gather_element, - sizeof(cmd->scatter_gather_element), - DMA_TO_DEVICE); - if (dma_mapping_error(dmadev, cmd->sge_dma)) - goto failed_sge; - - INIT_LIST_HEAD(&cmd->list); - list_add_tail(&cmd->list, &lu->cmd_orb_completed); - } - return 0; - -failed_sge: - dma_unmap_single(dmadev, cmd->command_orb_dma, - sizeof(struct sbp2_command_orb), DMA_TO_DEVICE); -failed_orb: - kfree(cmd); -failed_alloc: - return -ENOMEM; -} - -static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu, - struct hpsb_host *host) -{ - struct list_head *lh, *next; - struct sbp2_command_info *cmd; - unsigned long flags; - - spin_lock_irqsave(&lu->cmd_orb_lock, flags); - if (!list_empty(&lu->cmd_orb_completed)) - list_for_each_safe(lh, next, &lu->cmd_orb_completed) { - cmd = list_entry(lh, struct sbp2_command_info, list); - dma_unmap_single(host->device.parent, - cmd->command_orb_dma, - sizeof(struct sbp2_command_orb), - DMA_TO_DEVICE); - dma_unmap_single(host->device.parent, cmd->sge_dma, - sizeof(cmd->scatter_gather_element), - DMA_TO_DEVICE); - kfree(cmd); - } - spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - return; -} - -/* - * Finds the sbp2_command for a given outstanding command ORB. - * Only looks at the in-use list. - */ -static struct sbp2_command_info *sbp2util_find_command_for_orb( - struct sbp2_lu *lu, dma_addr_t orb) -{ - struct sbp2_command_info *cmd; - unsigned long flags; - - spin_lock_irqsave(&lu->cmd_orb_lock, flags); - if (!list_empty(&lu->cmd_orb_inuse)) - list_for_each_entry(cmd, &lu->cmd_orb_inuse, list) - if (cmd->command_orb_dma == orb) { - spin_unlock_irqrestore( - &lu->cmd_orb_lock, flags); - return cmd; - } - spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - return NULL; -} - -/* - * Finds the sbp2_command for a given outstanding SCpnt. - * Only looks at the in-use list. - * Must be called with lu->cmd_orb_lock held. - */ -static struct sbp2_command_info *sbp2util_find_command_for_SCpnt( - struct sbp2_lu *lu, void *SCpnt) -{ - struct sbp2_command_info *cmd; - - if (!list_empty(&lu->cmd_orb_inuse)) - list_for_each_entry(cmd, &lu->cmd_orb_inuse, list) - if (cmd->Current_SCpnt == SCpnt) - return cmd; - return NULL; -} - -static struct sbp2_command_info *sbp2util_allocate_command_orb( - struct sbp2_lu *lu, - struct scsi_cmnd *Current_SCpnt, - void (*Current_done)(struct scsi_cmnd *)) -{ - struct list_head *lh; - struct sbp2_command_info *cmd = NULL; - unsigned long flags; - - spin_lock_irqsave(&lu->cmd_orb_lock, flags); - if (!list_empty(&lu->cmd_orb_completed)) { - lh = lu->cmd_orb_completed.next; - list_del(lh); - cmd = list_entry(lh, struct sbp2_command_info, list); - cmd->Current_done = Current_done; - cmd->Current_SCpnt = Current_SCpnt; - list_add_tail(&cmd->list, &lu->cmd_orb_inuse); - } else - SBP2_ERR("%s: no orbs available", __func__); - spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - return cmd; -} - -/* - * Unmaps the DMAs of a command and moves the command to the completed ORB list. - * Must be called with lu->cmd_orb_lock held. - */ -static void sbp2util_mark_command_completed(struct sbp2_lu *lu, - struct sbp2_command_info *cmd) -{ - if (scsi_sg_count(cmd->Current_SCpnt)) - dma_unmap_sg(lu->ud->ne->host->device.parent, - scsi_sglist(cmd->Current_SCpnt), - scsi_sg_count(cmd->Current_SCpnt), - cmd->Current_SCpnt->sc_data_direction); - list_move_tail(&cmd->list, &lu->cmd_orb_completed); -} - -/* - * Is lu valid? Is the 1394 node still present? - */ -static inline int sbp2util_node_is_available(struct sbp2_lu *lu) -{ - return lu && lu->ne && !lu->ne->in_limbo; -} - -/********************************************* - * IEEE-1394 core driver stack related section - *********************************************/ - -static int sbp2_probe(struct device *dev) -{ - struct unit_directory *ud; - struct sbp2_lu *lu; - - ud = container_of(dev, struct unit_directory, device); - - /* Don't probe UD's that have the LUN flag. We'll probe the LUN(s) - * instead. */ - if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY) - return -ENODEV; - - lu = sbp2_alloc_device(ud); - if (!lu) - return -ENOMEM; - - sbp2_parse_unit_directory(lu, ud); - return sbp2_start_device(lu); -} - -static int sbp2_remove(struct device *dev) -{ - struct unit_directory *ud; - struct sbp2_lu *lu; - struct scsi_device *sdev; - - ud = container_of(dev, struct unit_directory, device); - lu = dev_get_drvdata(&ud->device); - if (!lu) - return 0; - - if (lu->shost) { - /* Get rid of enqueued commands if there is no chance to - * send them. */ - if (!sbp2util_node_is_available(lu)) - sbp2scsi_complete_all_commands(lu, DID_NO_CONNECT); - /* scsi_remove_device() may trigger shutdown functions of SCSI - * highlevel drivers which would deadlock if blocked. */ - atomic_set(&lu->state, SBP2LU_STATE_IN_SHUTDOWN); - scsi_unblock_requests(lu->shost); - } - sdev = lu->sdev; - if (sdev) { - lu->sdev = NULL; - scsi_remove_device(sdev); - } - - sbp2_logout_device(lu); - sbp2_remove_device(lu); - - return 0; -} - -static int sbp2_update(struct unit_directory *ud) -{ - struct sbp2_lu *lu = dev_get_drvdata(&ud->device); - - if (sbp2_reconnect_device(lu) != 0) { - /* - * Reconnect failed. If another bus reset happened, - * let nodemgr proceed and call sbp2_update again later - * (or sbp2_remove if this node went away). - */ - if (!hpsb_node_entry_valid(lu->ne)) - return 0; - /* - * Or the target rejected the reconnect because we weren't - * fast enough. Try a regular login, but first log out - * just in case of any weirdness. - */ - sbp2_logout_device(lu); - - if (sbp2_login_device(lu) != 0) { - if (!hpsb_node_entry_valid(lu->ne)) - return 0; - - /* Maybe another initiator won the login. */ - SBP2_ERR("Failed to reconnect to sbp2 device!"); - return -EBUSY; - } - } - - sbp2_set_busy_timeout(lu); - sbp2_agent_reset(lu, 1); - sbp2_max_speed_and_size(lu); - - /* Complete any pending commands with busy (so they get retried) - * and remove them from our queue. */ - sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY); - - /* Accept new commands unless there was another bus reset in the - * meantime. */ - if (hpsb_node_entry_valid(lu->ne)) { - atomic_set(&lu->state, SBP2LU_STATE_RUNNING); - scsi_unblock_requests(lu->shost); - } - return 0; -} - -static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud) -{ - struct sbp2_fwhost_info *hi; - struct Scsi_Host *shost = NULL; - struct sbp2_lu *lu = NULL; - unsigned long flags; - - lu = kzalloc(sizeof(*lu), GFP_KERNEL); - if (!lu) { - SBP2_ERR("failed to create lu"); - goto failed_alloc; - } - - lu->ne = ud->ne; - lu->ud = ud; - lu->speed_code = IEEE1394_SPEED_100; - lu->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; - lu->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE; - INIT_LIST_HEAD(&lu->cmd_orb_inuse); - INIT_LIST_HEAD(&lu->cmd_orb_completed); - INIT_LIST_HEAD(&lu->lu_list); - spin_lock_init(&lu->cmd_orb_lock); - atomic_set(&lu->state, SBP2LU_STATE_RUNNING); - INIT_WORK(&lu->protocol_work, NULL); - - dev_set_drvdata(&ud->device, lu); - - hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host); - if (!hi) { - hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host, - sizeof(*hi)); - if (!hi) { - SBP2_ERR("failed to allocate hostinfo"); - goto failed_alloc; - } - hi->host = ud->ne->host; - INIT_LIST_HEAD(&hi->logical_units); - -#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA - /* Handle data movement if physical dma is not - * enabled or not supported on host controller */ - if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, - &sbp2_physdma_ops, - 0x0ULL, 0xfffffffcULL)) { - SBP2_ERR("failed to register lower 4GB address range"); - goto failed_alloc; - } -#endif - } - - if (dma_get_max_seg_size(hi->host->device.parent) > SBP2_MAX_SEG_SIZE) - BUG_ON(dma_set_max_seg_size(hi->host->device.parent, - SBP2_MAX_SEG_SIZE)); - - /* Prevent unloading of the 1394 host */ - if (!try_module_get(hi->host->driver->owner)) { - SBP2_ERR("failed to get a reference on 1394 host driver"); - goto failed_alloc; - } - - lu->hi = hi; - - write_lock_irqsave(&sbp2_hi_logical_units_lock, flags); - list_add_tail(&lu->lu_list, &hi->logical_units); - write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); - - /* Register the status FIFO address range. We could use the same FIFO - * for targets at different nodes. However we need different FIFOs per - * target in order to support multi-unit devices. - * The FIFO is located out of the local host controller's physical range - * but, if possible, within the posted write area. Status writes will - * then be performed as unified transactions. This slightly reduces - * bandwidth usage, and some Prolific based devices seem to require it. - */ - lu->status_fifo_addr = hpsb_allocate_and_register_addrspace( - &sbp2_highlevel, ud->ne->host, &sbp2_ops, - sizeof(struct sbp2_status_block), sizeof(quadlet_t), - ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END); - if (lu->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) { - SBP2_ERR("failed to allocate status FIFO address range"); - goto failed_alloc; - } - - shost = scsi_host_alloc(&sbp2_shost_template, sizeof(unsigned long)); - if (!shost) { - SBP2_ERR("failed to register scsi host"); - goto failed_alloc; - } - - shost->hostdata[0] = (unsigned long)lu; - shost->max_cmd_len = SBP2_MAX_CDB_SIZE; - - if (!scsi_add_host(shost, &ud->device)) { - lu->shost = shost; - return lu; - } - - SBP2_ERR("failed to add scsi host"); - scsi_host_put(shost); - -failed_alloc: - sbp2_remove_device(lu); - return NULL; -} - -static void sbp2_host_reset(struct hpsb_host *host) -{ - struct sbp2_fwhost_info *hi; - struct sbp2_lu *lu; - unsigned long flags; - - hi = hpsb_get_hostinfo(&sbp2_highlevel, host); - if (!hi) - return; - - read_lock_irqsave(&sbp2_hi_logical_units_lock, flags); - - list_for_each_entry(lu, &hi->logical_units, lu_list) - if (atomic_cmpxchg(&lu->state, - SBP2LU_STATE_RUNNING, SBP2LU_STATE_IN_RESET) - == SBP2LU_STATE_RUNNING) - scsi_block_requests(lu->shost); - - read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); -} - -static int sbp2_start_device(struct sbp2_lu *lu) -{ - struct sbp2_fwhost_info *hi = lu->hi; - int error; - - lu->login_response = dma_alloc_coherent(hi->host->device.parent, - sizeof(struct sbp2_login_response), - &lu->login_response_dma, GFP_KERNEL); - if (!lu->login_response) - goto alloc_fail; - - lu->query_logins_orb = dma_alloc_coherent(hi->host->device.parent, - sizeof(struct sbp2_query_logins_orb), - &lu->query_logins_orb_dma, GFP_KERNEL); - if (!lu->query_logins_orb) - goto alloc_fail; - - lu->query_logins_response = dma_alloc_coherent(hi->host->device.parent, - sizeof(struct sbp2_query_logins_response), - &lu->query_logins_response_dma, GFP_KERNEL); - if (!lu->query_logins_response) - goto alloc_fail; - - lu->reconnect_orb = dma_alloc_coherent(hi->host->device.parent, - sizeof(struct sbp2_reconnect_orb), - &lu->reconnect_orb_dma, GFP_KERNEL); - if (!lu->reconnect_orb) - goto alloc_fail; - - lu->logout_orb = dma_alloc_coherent(hi->host->device.parent, - sizeof(struct sbp2_logout_orb), - &lu->logout_orb_dma, GFP_KERNEL); - if (!lu->logout_orb) - goto alloc_fail; - - lu->login_orb = dma_alloc_coherent(hi->host->device.parent, - sizeof(struct sbp2_login_orb), - &lu->login_orb_dma, GFP_KERNEL); - if (!lu->login_orb) - goto alloc_fail; - - if (sbp2util_create_command_orb_pool(lu)) - goto alloc_fail; - - /* Wait a second before trying to log in. Previously logged in - * initiators need a chance to reconnect. */ - if (msleep_interruptible(1000)) { - sbp2_remove_device(lu); - return -EINTR; - } - - if (sbp2_login_device(lu)) { - sbp2_remove_device(lu); - return -EBUSY; - } - - sbp2_set_busy_timeout(lu); - sbp2_agent_reset(lu, 1); - sbp2_max_speed_and_size(lu); - - if (lu->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY) - ssleep(SBP2_INQUIRY_DELAY); - - error = scsi_add_device(lu->shost, 0, lu->ud->id, 0); - if (error) { - SBP2_ERR("scsi_add_device failed"); - sbp2_logout_device(lu); - sbp2_remove_device(lu); - return error; - } - - return 0; - -alloc_fail: - SBP2_ERR("Could not allocate memory for lu"); - sbp2_remove_device(lu); - return -ENOMEM; -} - -static void sbp2_remove_device(struct sbp2_lu *lu) -{ - struct sbp2_fwhost_info *hi; - unsigned long flags; - - if (!lu) - return; - hi = lu->hi; - if (!hi) - goto no_hi; - - if (lu->shost) { - scsi_remove_host(lu->shost); - scsi_host_put(lu->shost); - } - flush_scheduled_work(); - sbp2util_remove_command_orb_pool(lu, hi->host); - - write_lock_irqsave(&sbp2_hi_logical_units_lock, flags); - list_del(&lu->lu_list); - write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); - - if (lu->login_response) - dma_free_coherent(hi->host->device.parent, - sizeof(struct sbp2_login_response), - lu->login_response, - lu->login_response_dma); - if (lu->login_orb) - dma_free_coherent(hi->host->device.parent, - sizeof(struct sbp2_login_orb), - lu->login_orb, - lu->login_orb_dma); - if (lu->reconnect_orb) - dma_free_coherent(hi->host->device.parent, - sizeof(struct sbp2_reconnect_orb), - lu->reconnect_orb, - lu->reconnect_orb_dma); - if (lu->logout_orb) - dma_free_coherent(hi->host->device.parent, - sizeof(struct sbp2_logout_orb), - lu->logout_orb, - lu->logout_orb_dma); - if (lu->query_logins_orb) - dma_free_coherent(hi->host->device.parent, - sizeof(struct sbp2_query_logins_orb), - lu->query_logins_orb, - lu->query_logins_orb_dma); - if (lu->query_logins_response) - dma_free_coherent(hi->host->device.parent, - sizeof(struct sbp2_query_logins_response), - lu->query_logins_response, - lu->query_logins_response_dma); - - if (lu->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE) - hpsb_unregister_addrspace(&sbp2_highlevel, hi->host, - lu->status_fifo_addr); - - dev_set_drvdata(&lu->ud->device, NULL); - - module_put(hi->host->driver->owner); -no_hi: - kfree(lu); -} - -#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA -/* - * Deal with write requests on adapters which do not support physical DMA or - * have it switched off. - */ -static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, - int destid, quadlet_t *data, u64 addr, - size_t length, u16 flags) -{ - memcpy(bus_to_virt((u32) addr), data, length); - return RCODE_COMPLETE; -} - -/* - * Deal with read requests on adapters which do not support physical DMA or - * have it switched off. - */ -static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, - quadlet_t *data, u64 addr, size_t length, - u16 flags) -{ - memcpy(data, bus_to_virt((u32) addr), length); - return RCODE_COMPLETE; -} -#endif - -/************************************** - * SBP-2 protocol related section - **************************************/ - -static int sbp2_query_logins(struct sbp2_lu *lu) -{ - struct sbp2_fwhost_info *hi = lu->hi; - quadlet_t data[2]; - int max_logins; - int active_logins; - - lu->query_logins_orb->reserved1 = 0x0; - lu->query_logins_orb->reserved2 = 0x0; - - lu->query_logins_orb->query_response_lo = lu->query_logins_response_dma; - lu->query_logins_orb->query_response_hi = - ORB_SET_NODE_ID(hi->host->node_id); - lu->query_logins_orb->lun_misc = - ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST); - lu->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1); - lu->query_logins_orb->lun_misc |= ORB_SET_LUN(lu->lun); - - lu->query_logins_orb->reserved_resp_length = - ORB_SET_QUERY_LOGINS_RESP_LENGTH( - sizeof(struct sbp2_query_logins_response)); - - lu->query_logins_orb->status_fifo_hi = - ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id); - lu->query_logins_orb->status_fifo_lo = - ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr); - - sbp2util_cpu_to_be32_buffer(lu->query_logins_orb, - sizeof(struct sbp2_query_logins_orb)); - - memset(lu->query_logins_response, 0, - sizeof(struct sbp2_query_logins_response)); - - data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = lu->query_logins_orb_dma; - sbp2util_cpu_to_be32_buffer(data, 8); - - hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8); - - if (sbp2util_access_timeout(lu, 2*HZ)) { - SBP2_INFO("Error querying logins to SBP-2 device - timed out"); - return -EIO; - } - - if (lu->status_block.ORB_offset_lo != lu->query_logins_orb_dma) { - SBP2_INFO("Error querying logins to SBP-2 device - timed out"); - return -EIO; - } - - if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) { - SBP2_INFO("Error querying logins to SBP-2 device - failed"); - return -EIO; - } - - sbp2util_cpu_to_be32_buffer(lu->query_logins_response, - sizeof(struct sbp2_query_logins_response)); - - max_logins = RESPONSE_GET_MAX_LOGINS( - lu->query_logins_response->length_max_logins); - SBP2_INFO("Maximum concurrent logins supported: %d", max_logins); - - active_logins = RESPONSE_GET_ACTIVE_LOGINS( - lu->query_logins_response->length_max_logins); - SBP2_INFO("Number of active logins: %d", active_logins); - - if (active_logins >= max_logins) { - return -EIO; - } - - return 0; -} - -static int sbp2_login_device(struct sbp2_lu *lu) -{ - struct sbp2_fwhost_info *hi = lu->hi; - quadlet_t data[2]; - - if (!lu->login_orb) - return -EIO; - - if (!sbp2_exclusive_login && sbp2_query_logins(lu)) { - SBP2_INFO("Device does not support any more concurrent logins"); - return -EIO; - } - - /* assume no password */ - lu->login_orb->password_hi = 0; - lu->login_orb->password_lo = 0; - - lu->login_orb->login_response_lo = lu->login_response_dma; - lu->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id); - lu->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST); - - /* one second reconnect time */ - lu->login_orb->lun_misc |= ORB_SET_RECONNECT(0); - lu->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(sbp2_exclusive_login); - lu->login_orb->lun_misc |= ORB_SET_NOTIFY(1); - lu->login_orb->lun_misc |= ORB_SET_LUN(lu->lun); - - lu->login_orb->passwd_resp_lengths = - ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response)); - - lu->login_orb->status_fifo_hi = - ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id); - lu->login_orb->status_fifo_lo = - ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr); - - sbp2util_cpu_to_be32_buffer(lu->login_orb, - sizeof(struct sbp2_login_orb)); - - memset(lu->login_response, 0, sizeof(struct sbp2_login_response)); - - data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = lu->login_orb_dma; - sbp2util_cpu_to_be32_buffer(data, 8); - - hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8); - - /* wait up to 20 seconds for login status */ - if (sbp2util_access_timeout(lu, 20*HZ)) { - SBP2_ERR("Error logging into SBP-2 device - timed out"); - return -EIO; - } - - /* make sure that the returned status matches the login ORB */ - if (lu->status_block.ORB_offset_lo != lu->login_orb_dma) { - SBP2_ERR("Error logging into SBP-2 device - timed out"); - return -EIO; - } - - if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) { - SBP2_ERR("Error logging into SBP-2 device - failed"); - return -EIO; - } - - sbp2util_cpu_to_be32_buffer(lu->login_response, - sizeof(struct sbp2_login_response)); - lu->command_block_agent_addr = - ((u64)lu->login_response->command_block_agent_hi) << 32; - lu->command_block_agent_addr |= - ((u64)lu->login_response->command_block_agent_lo); - lu->command_block_agent_addr &= 0x0000ffffffffffffULL; - - SBP2_INFO("Logged into SBP-2 device"); - return 0; -} - -static int sbp2_logout_device(struct sbp2_lu *lu) -{ - struct sbp2_fwhost_info *hi = lu->hi; - quadlet_t data[2]; - int error; - - lu->logout_orb->reserved1 = 0x0; - lu->logout_orb->reserved2 = 0x0; - lu->logout_orb->reserved3 = 0x0; - lu->logout_orb->reserved4 = 0x0; - - lu->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST); - lu->logout_orb->login_ID_misc |= - ORB_SET_LOGIN_ID(lu->login_response->length_login_ID); - lu->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1); - - lu->logout_orb->reserved5 = 0x0; - lu->logout_orb->status_fifo_hi = - ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id); - lu->logout_orb->status_fifo_lo = - ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr); - - sbp2util_cpu_to_be32_buffer(lu->logout_orb, - sizeof(struct sbp2_logout_orb)); - - data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = lu->logout_orb_dma; - sbp2util_cpu_to_be32_buffer(data, 8); - - error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8); - if (error) - return error; - - /* wait up to 1 second for the device to complete logout */ - if (sbp2util_access_timeout(lu, HZ)) - return -EIO; - - SBP2_INFO("Logged out of SBP-2 device"); - return 0; -} - -static int sbp2_reconnect_device(struct sbp2_lu *lu) -{ - struct sbp2_fwhost_info *hi = lu->hi; - quadlet_t data[2]; - int error; - - lu->reconnect_orb->reserved1 = 0x0; - lu->reconnect_orb->reserved2 = 0x0; - lu->reconnect_orb->reserved3 = 0x0; - lu->reconnect_orb->reserved4 = 0x0; - - lu->reconnect_orb->login_ID_misc = - ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST); - lu->reconnect_orb->login_ID_misc |= - ORB_SET_LOGIN_ID(lu->login_response->length_login_ID); - lu->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1); - - lu->reconnect_orb->reserved5 = 0x0; - lu->reconnect_orb->status_fifo_hi = - ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id); - lu->reconnect_orb->status_fifo_lo = - ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr); - - sbp2util_cpu_to_be32_buffer(lu->reconnect_orb, - sizeof(struct sbp2_reconnect_orb)); - - data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = lu->reconnect_orb_dma; - sbp2util_cpu_to_be32_buffer(data, 8); - - error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8); - if (error) - return error; - - /* wait up to 1 second for reconnect status */ - if (sbp2util_access_timeout(lu, HZ)) { - SBP2_ERR("Error reconnecting to SBP-2 device - timed out"); - return -EIO; - } - - /* make sure that the returned status matches the reconnect ORB */ - if (lu->status_block.ORB_offset_lo != lu->reconnect_orb_dma) { - SBP2_ERR("Error reconnecting to SBP-2 device - timed out"); - return -EIO; - } - - if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) { - SBP2_ERR("Error reconnecting to SBP-2 device - failed"); - return -EIO; - } - - SBP2_INFO("Reconnected to SBP-2 device"); - return 0; -} - -/* - * Set the target node's Single Phase Retry limit. Affects the target's retry - * behaviour if our node is too busy to accept requests. - */ -static int sbp2_set_busy_timeout(struct sbp2_lu *lu) -{ - quadlet_t data; - - data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE); - if (hpsb_node_write(lu->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) - SBP2_ERR("%s error", __func__); - return 0; -} - -static void sbp2_parse_unit_directory(struct sbp2_lu *lu, - struct unit_directory *ud) -{ - struct csr1212_keyval *kv; - struct csr1212_dentry *dentry; - u64 management_agent_addr; - u32 firmware_revision, model; - unsigned workarounds; - int i; - - management_agent_addr = 0; - firmware_revision = SBP2_ROM_VALUE_MISSING; - model = ud->flags & UNIT_DIRECTORY_MODEL_ID ? - ud->model_id : SBP2_ROM_VALUE_MISSING; - - csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) { - switch (kv->key.id) { - case CSR1212_KV_ID_DEPENDENT_INFO: - if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) - management_agent_addr = - CSR1212_REGISTER_SPACE_BASE + - (kv->value.csr_offset << 2); - - else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) - lu->lun = ORB_SET_LUN(kv->value.immediate); - break; - - - case SBP2_FIRMWARE_REVISION_KEY: - firmware_revision = kv->value.immediate; - break; - - default: - /* FIXME: Check for SBP2_UNIT_CHARACTERISTICS_KEY - * mgt_ORB_timeout and ORB_size, SBP-2 clause 7.4.8. */ - - /* FIXME: Check for SBP2_DEVICE_TYPE_AND_LUN_KEY. - * Its "ordered" bit has consequences for command ORB - * list handling. See SBP-2 clauses 4.6, 7.4.11, 10.2 */ - break; - } - } - - workarounds = sbp2_default_workarounds; - - if (!(workarounds & SBP2_WORKAROUND_OVERRIDE)) - for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { - if (sbp2_workarounds_table[i].firmware_revision != - SBP2_ROM_VALUE_WILDCARD && - sbp2_workarounds_table[i].firmware_revision != - (firmware_revision & 0xffff00)) - continue; - if (sbp2_workarounds_table[i].model != - SBP2_ROM_VALUE_WILDCARD && - sbp2_workarounds_table[i].model != model) - continue; - workarounds |= sbp2_workarounds_table[i].workarounds; - break; - } - - if (workarounds) - SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x " - "(firmware_revision 0x%06x, vendor_id 0x%06x," - " model_id 0x%06x)", - NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), - workarounds, firmware_revision, ud->vendor_id, - model); - - /* We would need one SCSI host template for each target to adjust - * max_sectors on the fly, therefore warn only. */ - if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS && - (sbp2_max_sectors * 512) > (128 * 1024)) - SBP2_INFO("Node " NODE_BUS_FMT ": Bridge only supports 128KB " - "max transfer size. WARNING: Current max_sectors " - "setting is larger than 128KB (%d sectors)", - NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), - sbp2_max_sectors); - - /* If this is a logical unit directory entry, process the parent - * to get the values. */ - if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) { - struct unit_directory *parent_ud = container_of( - ud->device.parent, struct unit_directory, device); - sbp2_parse_unit_directory(lu, parent_ud); - } else { - lu->management_agent_addr = management_agent_addr; - lu->workarounds = workarounds; - if (ud->flags & UNIT_DIRECTORY_HAS_LUN) - lu->lun = ORB_SET_LUN(ud->lun); - } -} - -#define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2)) - -/* - * This function is called in order to determine the max speed and packet - * size we can use in our ORBs. Note, that we (the driver and host) only - * initiate the transaction. The SBP-2 device actually transfers the data - * (by reading from the DMA area we tell it). This means that the SBP-2 - * device decides the actual maximum data it can transfer. We just tell it - * the speed that it needs to use, and the max_rec the host supports, and - * it takes care of the rest. - */ -static int sbp2_max_speed_and_size(struct sbp2_lu *lu) -{ - struct sbp2_fwhost_info *hi = lu->hi; - u8 payload; - - lu->speed_code = hi->host->speed[NODEID_TO_NODE(lu->ne->nodeid)]; - - if (lu->speed_code > sbp2_max_speed) { - lu->speed_code = sbp2_max_speed; - SBP2_INFO("Reducing speed to %s", - hpsb_speedto_str[sbp2_max_speed]); - } - - /* Payload size is the lesser of what our speed supports and what - * our host supports. */ - payload = min(sbp2_speedto_max_payload[lu->speed_code], - (u8) (hi->host->csr.max_rec - 1)); - - /* If physical DMA is off, work around limitation in ohci1394: - * packet size must not exceed PAGE_SIZE */ - if (lu->ne->host->low_addr_space < (1ULL << 32)) - while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE && - payload) - payload--; - - SBP2_INFO("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]", - NODE_BUS_ARGS(hi->host, lu->ne->nodeid), - hpsb_speedto_str[lu->speed_code], - SBP2_PAYLOAD_TO_BYTES(payload)); - - lu->max_payload_size = payload; - return 0; -} - -static int sbp2_agent_reset(struct sbp2_lu *lu, int wait) -{ - quadlet_t data; - u64 addr; - int retval; - unsigned long flags; - - /* flush lu->protocol_work */ - if (wait) - flush_scheduled_work(); - - data = ntohl(SBP2_AGENT_RESET_DATA); - addr = lu->command_block_agent_addr + SBP2_AGENT_RESET_OFFSET; - - if (wait) - retval = hpsb_node_write(lu->ne, addr, &data, 4); - else - retval = sbp2util_node_write_no_wait(lu->ne, addr, &data, 4); - - if (retval < 0) { - SBP2_ERR("hpsb_node_write failed.\n"); - return -EIO; - } - - /* make sure that the ORB_POINTER is written on next command */ - spin_lock_irqsave(&lu->cmd_orb_lock, flags); - lu->last_orb = NULL; - spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - - return 0; -} - -static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, - struct sbp2_fwhost_info *hi, - struct sbp2_command_info *cmd, - unsigned int sg_count, - struct scatterlist *sg, - u32 orb_direction, - enum dma_data_direction dma_dir) -{ - struct device *dmadev = hi->host->device.parent; - struct sbp2_unrestricted_page_table *pt; - int i, n; - - n = dma_map_sg(dmadev, sg, sg_count, dma_dir); - if (n == 0) - return -ENOMEM; - - orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); - orb->misc |= ORB_SET_DIRECTION(orb_direction); - - /* special case if only one element (and less than 64KB in size) */ - if (n == 1) { - orb->misc |= ORB_SET_DATA_SIZE(sg_dma_len(sg)); - orb->data_descriptor_lo = sg_dma_address(sg); - } else { - pt = &cmd->scatter_gather_element[0]; - - dma_sync_single_for_cpu(dmadev, cmd->sge_dma, - sizeof(cmd->scatter_gather_element), - DMA_TO_DEVICE); - - for_each_sg(sg, sg, n, i) { - pt[i].high = cpu_to_be32(sg_dma_len(sg) << 16); - pt[i].low = cpu_to_be32(sg_dma_address(sg)); - } - - orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1) | - ORB_SET_DATA_SIZE(n); - orb->data_descriptor_lo = cmd->sge_dma; - - dma_sync_single_for_device(dmadev, cmd->sge_dma, - sizeof(cmd->scatter_gather_element), - DMA_TO_DEVICE); - } - return 0; -} - -static int sbp2_create_command_orb(struct sbp2_lu *lu, - struct sbp2_command_info *cmd, - struct scsi_cmnd *SCpnt) -{ - struct device *dmadev = lu->hi->host->device.parent; - struct sbp2_command_orb *orb = &cmd->command_orb; - unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt); - enum dma_data_direction dma_dir = SCpnt->sc_data_direction; - u32 orb_direction; - int ret; - - dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma, - sizeof(struct sbp2_command_orb), DMA_TO_DEVICE); - /* - * Set-up our command ORB. - * - * NOTE: We're doing unrestricted page tables (s/g), as this is - * best performance (at least with the devices I have). This means - * that data_size becomes the number of s/g elements, and - * page_size should be zero (for unrestricted). - */ - orb->next_ORB_hi = ORB_SET_NULL_PTR(1); - orb->next_ORB_lo = 0x0; - orb->misc = ORB_SET_MAX_PAYLOAD(lu->max_payload_size); - orb->misc |= ORB_SET_SPEED(lu->speed_code); - orb->misc |= ORB_SET_NOTIFY(1); - - if (dma_dir == DMA_NONE) - orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER; - else if (dma_dir == DMA_TO_DEVICE && scsi_request_bufflen) - orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA; - else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen) - orb_direction = ORB_DIRECTION_READ_FROM_MEDIA; - else { - SBP2_INFO("Falling back to DMA_NONE"); - orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER; - } - - /* set up our page table stuff */ - if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) { - orb->data_descriptor_hi = 0x0; - orb->data_descriptor_lo = 0x0; - orb->misc |= ORB_SET_DIRECTION(1); - ret = 0; - } else { - ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd, - scsi_sg_count(SCpnt), - scsi_sglist(SCpnt), - orb_direction, dma_dir); - } - sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb)); - - memset(orb->cdb, 0, sizeof(orb->cdb)); - memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len); - - dma_sync_single_for_device(dmadev, cmd->command_orb_dma, - sizeof(struct sbp2_command_orb), DMA_TO_DEVICE); - return ret; -} - -static void sbp2_link_orb_command(struct sbp2_lu *lu, - struct sbp2_command_info *cmd) -{ - struct sbp2_fwhost_info *hi = lu->hi; - struct sbp2_command_orb *last_orb; - dma_addr_t last_orb_dma; - u64 addr = lu->command_block_agent_addr; - quadlet_t data[2]; - size_t length; - unsigned long flags; - - /* check to see if there are any previous orbs to use */ - spin_lock_irqsave(&lu->cmd_orb_lock, flags); - last_orb = lu->last_orb; - last_orb_dma = lu->last_orb_dma; - if (!last_orb) { - /* - * last_orb == NULL means: We know that the target's fetch agent - * is not active right now. - */ - addr += SBP2_ORB_POINTER_OFFSET; - data[0] = ORB_SET_NODE_ID(hi->host->node_id); - data[1] = cmd->command_orb_dma; - sbp2util_cpu_to_be32_buffer(data, 8); - length = 8; - } else { - /* - * last_orb != NULL means: We know that the target's fetch agent - * is (very probably) not dead or in reset state right now. - * We have an ORB already sent that we can append a new one to. - * The target's fetch agent may or may not have read this - * previous ORB yet. - */ - dma_sync_single_for_cpu(hi->host->device.parent, last_orb_dma, - sizeof(struct sbp2_command_orb), - DMA_TO_DEVICE); - last_orb->next_ORB_lo = cpu_to_be32(cmd->command_orb_dma); - wmb(); - /* Tells hardware that this pointer is valid */ - last_orb->next_ORB_hi = 0; - dma_sync_single_for_device(hi->host->device.parent, - last_orb_dma, - sizeof(struct sbp2_command_orb), - DMA_TO_DEVICE); - addr += SBP2_DOORBELL_OFFSET; - data[0] = 0; - length = 4; - } - lu->last_orb = &cmd->command_orb; - lu->last_orb_dma = cmd->command_orb_dma; - spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - - if (sbp2util_node_write_no_wait(lu->ne, addr, data, length)) { - /* - * sbp2util_node_write_no_wait failed. We certainly ran out - * of transaction labels, perhaps just because there were no - * context switches which gave khpsbpkt a chance to collect - * free tlabels. Try again in non-atomic context. If necessary, - * the workqueue job will sleep to guaranteedly get a tlabel. - * We do not accept new commands until the job is over. - */ - scsi_block_requests(lu->shost); - PREPARE_WORK(&lu->protocol_work, - last_orb ? sbp2util_write_doorbell: - sbp2util_write_orb_pointer); - schedule_work(&lu->protocol_work); - } -} - -static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt, - void (*done)(struct scsi_cmnd *)) -{ - struct sbp2_command_info *cmd; - - cmd = sbp2util_allocate_command_orb(lu, SCpnt, done); - if (!cmd) - return -EIO; - - if (sbp2_create_command_orb(lu, cmd, SCpnt)) - return -ENOMEM; - - sbp2_link_orb_command(lu, cmd); - return 0; -} - -/* - * Translates SBP-2 status into SCSI sense data for check conditions - */ -static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, - unchar *sense_data) -{ - /* OK, it's pretty ugly... ;-) */ - sense_data[0] = 0x70; - sense_data[1] = 0x0; - sense_data[2] = sbp2_status[9]; - sense_data[3] = sbp2_status[12]; - sense_data[4] = sbp2_status[13]; - sense_data[5] = sbp2_status[14]; - sense_data[6] = sbp2_status[15]; - sense_data[7] = 10; - sense_data[8] = sbp2_status[16]; - sense_data[9] = sbp2_status[17]; - sense_data[10] = sbp2_status[18]; - sense_data[11] = sbp2_status[19]; - sense_data[12] = sbp2_status[10]; - sense_data[13] = sbp2_status[11]; - sense_data[14] = sbp2_status[20]; - sense_data[15] = sbp2_status[21]; - - return sbp2_status[8] & 0x3f; -} - -static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, - int destid, quadlet_t *data, u64 addr, - size_t length, u16 fl) -{ - struct sbp2_fwhost_info *hi; - struct sbp2_lu *lu = NULL, *lu_tmp; - struct scsi_cmnd *SCpnt = NULL; - struct sbp2_status_block *sb; - u32 scsi_status = SBP2_SCSI_STATUS_GOOD; - struct sbp2_command_info *cmd; - unsigned long flags; - - if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) { - SBP2_ERR("Wrong size of status block"); - return RCODE_ADDRESS_ERROR; - } - if (unlikely(!host)) { - SBP2_ERR("host is NULL - this is bad!"); - return RCODE_ADDRESS_ERROR; - } - hi = hpsb_get_hostinfo(&sbp2_highlevel, host); - if (unlikely(!hi)) { - SBP2_ERR("host info is NULL - this is bad!"); - return RCODE_ADDRESS_ERROR; - } - - /* Find the unit which wrote the status. */ - read_lock_irqsave(&sbp2_hi_logical_units_lock, flags); - list_for_each_entry(lu_tmp, &hi->logical_units, lu_list) { - if (lu_tmp->ne->nodeid == nodeid && - lu_tmp->status_fifo_addr == addr) { - lu = lu_tmp; - break; - } - } - read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags); - - if (unlikely(!lu)) { - SBP2_ERR("lu is NULL - device is gone?"); - return RCODE_ADDRESS_ERROR; - } - - /* Put response into lu status fifo buffer. The first two bytes - * come in big endian bit order. Often the target writes only a - * truncated status block, minimally the first two quadlets. The rest - * is implied to be zeros. */ - sb = &lu->status_block; - memset(sb->command_set_dependent, 0, sizeof(sb->command_set_dependent)); - memcpy(sb, data, length); - sbp2util_be32_to_cpu_buffer(sb, 8); - - /* Ignore unsolicited status. Handle command ORB status. */ - if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2)) - cmd = NULL; - else - cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo); - if (cmd) { - /* Grab SCSI command pointers and check status. */ - /* - * FIXME: If the src field in the status is 1, the ORB DMA must - * not be reused until status for a subsequent ORB is received. - */ - SCpnt = cmd->Current_SCpnt; - spin_lock_irqsave(&lu->cmd_orb_lock, flags); - sbp2util_mark_command_completed(lu, cmd); - spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - - if (SCpnt) { - u32 h = sb->ORB_offset_hi_misc; - u32 r = STATUS_GET_RESP(h); - - if (r != RESP_STATUS_REQUEST_COMPLETE) { - SBP2_INFO("resp 0x%x, sbp_status 0x%x", - r, STATUS_GET_SBP_STATUS(h)); - scsi_status = - r == RESP_STATUS_TRANSPORT_FAILURE ? - SBP2_SCSI_STATUS_BUSY : - SBP2_SCSI_STATUS_COMMAND_TERMINATED; - } - - if (STATUS_GET_LEN(h) > 1) - scsi_status = sbp2_status_to_sense_data( - (unchar *)sb, SCpnt->sense_buffer); - - if (STATUS_TEST_DEAD(h)) - sbp2_agent_reset(lu, 0); - } - - /* Check here to see if there are no commands in-use. If there - * are none, we know that the fetch agent left the active state - * _and_ that we did not reactivate it yet. Therefore clear - * last_orb so that next time we write directly to the - * ORB_POINTER register. That way the fetch agent does not need - * to refetch the next_ORB. */ - spin_lock_irqsave(&lu->cmd_orb_lock, flags); - if (list_empty(&lu->cmd_orb_inuse)) - lu->last_orb = NULL; - spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - - } else { - /* It's probably status after a management request. */ - if ((sb->ORB_offset_lo == lu->reconnect_orb_dma) || - (sb->ORB_offset_lo == lu->login_orb_dma) || - (sb->ORB_offset_lo == lu->query_logins_orb_dma) || - (sb->ORB_offset_lo == lu->logout_orb_dma)) { - lu->access_complete = 1; - wake_up_interruptible(&sbp2_access_wq); - } - } - - if (SCpnt) - sbp2scsi_complete_command(lu, scsi_status, SCpnt, - cmd->Current_done); - return RCODE_COMPLETE; -} - -/************************************** - * SCSI interface related section - **************************************/ - -static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, - void (*done)(struct scsi_cmnd *)) -{ - struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0]; - struct sbp2_fwhost_info *hi; - int result = DID_NO_CONNECT << 16; - - if (unlikely(!sbp2util_node_is_available(lu))) - goto done; - - hi = lu->hi; - - if (unlikely(!hi)) { - SBP2_ERR("sbp2_fwhost_info is NULL - this is bad!"); - goto done; - } - - /* Multiple units are currently represented to the SCSI core as separate - * targets, not as one target with multiple LUs. Therefore return - * selection time-out to any IO directed at non-zero LUNs. */ - if (unlikely(SCpnt->device->lun)) - goto done; - - if (unlikely(!hpsb_node_entry_valid(lu->ne))) { - SBP2_ERR("Bus reset in progress - rejecting command"); - result = DID_BUS_BUSY << 16; - goto done; - } - - /* Bidirectional commands are not yet implemented, - * and unknown transfer direction not handled. */ - if (unlikely(SCpnt->sc_data_direction == DMA_BIDIRECTIONAL)) { - SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command"); - result = DID_ERROR << 16; - goto done; - } - - if (sbp2_send_command(lu, SCpnt, done)) { - SBP2_ERR("Error sending SCSI command"); - sbp2scsi_complete_command(lu, - SBP2_SCSI_STATUS_SELECTION_TIMEOUT, - SCpnt, done); - } - return 0; - -done: - SCpnt->result = result; - done(SCpnt); - return 0; -} - -static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status) -{ - struct list_head *lh; - struct sbp2_command_info *cmd; - unsigned long flags; - - spin_lock_irqsave(&lu->cmd_orb_lock, flags); - while (!list_empty(&lu->cmd_orb_inuse)) { - lh = lu->cmd_orb_inuse.next; - cmd = list_entry(lh, struct sbp2_command_info, list); - sbp2util_mark_command_completed(lu, cmd); - if (cmd->Current_SCpnt) { - cmd->Current_SCpnt->result = status << 16; - cmd->Current_done(cmd->Current_SCpnt); - } - } - spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - - return; -} - -/* - * Complete a regular SCSI command. Can be called in atomic context. - */ -static void sbp2scsi_complete_command(struct sbp2_lu *lu, u32 scsi_status, - struct scsi_cmnd *SCpnt, - void (*done)(struct scsi_cmnd *)) -{ - if (!SCpnt) { - SBP2_ERR("SCpnt is NULL"); - return; - } - - switch (scsi_status) { - case SBP2_SCSI_STATUS_GOOD: - SCpnt->result = DID_OK << 16; - break; - - case SBP2_SCSI_STATUS_BUSY: - SBP2_ERR("SBP2_SCSI_STATUS_BUSY"); - SCpnt->result = DID_BUS_BUSY << 16; - break; - - case SBP2_SCSI_STATUS_CHECK_CONDITION: - SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16; - break; - - case SBP2_SCSI_STATUS_SELECTION_TIMEOUT: - SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT"); - SCpnt->result = DID_NO_CONNECT << 16; - scsi_print_command(SCpnt); - break; - - case SBP2_SCSI_STATUS_CONDITION_MET: - case SBP2_SCSI_STATUS_RESERVATION_CONFLICT: - case SBP2_SCSI_STATUS_COMMAND_TERMINATED: - SBP2_ERR("Bad SCSI status = %x", scsi_status); - SCpnt->result = DID_ERROR << 16; - scsi_print_command(SCpnt); - break; - - default: - SBP2_ERR("Unsupported SCSI status = %x", scsi_status); - SCpnt->result = DID_ERROR << 16; - } - - /* If a bus reset is in progress and there was an error, complete - * the command as busy so that it will get retried. */ - if (!hpsb_node_entry_valid(lu->ne) - && (scsi_status != SBP2_SCSI_STATUS_GOOD)) { - SBP2_ERR("Completing command with busy (bus reset)"); - SCpnt->result = DID_BUS_BUSY << 16; - } - - /* Tell the SCSI stack that we're done with this command. */ - done(SCpnt); -} - -static int sbp2scsi_slave_alloc(struct scsi_device *sdev) -{ - struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0]; - - if (sdev->lun != 0 || sdev->id != lu->ud->id || sdev->channel != 0) - return -ENODEV; - - lu->sdev = sdev; - sdev->allow_restart = 1; - - /* SBP-2 requires quadlet alignment of the data buffers. */ - blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1); - - if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36) - sdev->inquiry_len = 36; - return 0; -} - -static int sbp2scsi_slave_configure(struct scsi_device *sdev) -{ - struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0]; - - sdev->use_10_for_rw = 1; - - if (sbp2_exclusive_login) - sdev->manage_start_stop = 1; - if (sdev->type == TYPE_ROM) - sdev->use_10_for_ms = 1; - if (sdev->type == TYPE_DISK && - lu->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) - sdev->skip_ms_page_8 = 1; - if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) - sdev->fix_capacity = 1; - if (lu->workarounds & SBP2_WORKAROUND_POWER_CONDITION) - sdev->start_stop_pwr_cond = 1; - if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) - blk_queue_max_hw_sectors(sdev->request_queue, 128 * 1024 / 512); - - blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE); - return 0; -} - -static void sbp2scsi_slave_destroy(struct scsi_device *sdev) -{ - ((struct sbp2_lu *)sdev->host->hostdata[0])->sdev = NULL; - return; -} - -/* - * Called by scsi stack when something has really gone wrong. - * Usually called when a command has timed-out for some reason. - */ -static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) -{ - struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0]; - struct sbp2_command_info *cmd; - unsigned long flags; - - SBP2_INFO("aborting sbp2 command"); - scsi_print_command(SCpnt); - - if (sbp2util_node_is_available(lu)) { - sbp2_agent_reset(lu, 1); - - /* Return a matching command structure to the free pool. */ - spin_lock_irqsave(&lu->cmd_orb_lock, flags); - cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt); - if (cmd) { - sbp2util_mark_command_completed(lu, cmd); - if (cmd->Current_SCpnt) { - cmd->Current_SCpnt->result = DID_ABORT << 16; - cmd->Current_done(cmd->Current_SCpnt); - } - } - spin_unlock_irqrestore(&lu->cmd_orb_lock, flags); - - sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY); - } - - return SUCCESS; -} - -/* - * Called by scsi stack when something has really gone wrong. - */ -static int sbp2scsi_reset(struct scsi_cmnd *SCpnt) -{ - struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0]; - - SBP2_INFO("reset requested"); - - if (sbp2util_node_is_available(lu)) { - SBP2_INFO("generating sbp2 fetch agent reset"); - sbp2_agent_reset(lu, 1); - } - - return SUCCESS; -} - -static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct scsi_device *sdev; - struct sbp2_lu *lu; - - if (!(sdev = to_scsi_device(dev))) - return 0; - - if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0])) - return 0; - - if (sbp2_long_sysfs_ieee1394_id) - return sprintf(buf, "%016Lx:%06x:%04x\n", - (unsigned long long)lu->ne->guid, - lu->ud->directory_id, ORB_SET_LUN(lu->lun)); - else - return sprintf(buf, "%016Lx:%d:%d\n", - (unsigned long long)lu->ne->guid, - lu->ud->id, ORB_SET_LUN(lu->lun)); -} - -MODULE_AUTHOR("Ben Collins <bcollins@debian.org>"); -MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver"); -MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); -MODULE_LICENSE("GPL"); - -static int sbp2_module_init(void) -{ - int ret; - - if (sbp2_serialize_io) { - sbp2_shost_template.can_queue = 1; - sbp2_shost_template.cmd_per_lun = 1; - } - - sbp2_shost_template.max_sectors = sbp2_max_sectors; - - hpsb_register_highlevel(&sbp2_highlevel); - ret = hpsb_register_protocol(&sbp2_driver); - if (ret) { - SBP2_ERR("Failed to register protocol"); - hpsb_unregister_highlevel(&sbp2_highlevel); - return ret; - } - return 0; -} - -static void __exit sbp2_module_exit(void) -{ - hpsb_unregister_protocol(&sbp2_driver); - hpsb_unregister_highlevel(&sbp2_highlevel); -} - -module_init(sbp2_module_init); -module_exit(sbp2_module_exit); diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h deleted file mode 100644 index 64a3a66..0000000 --- a/drivers/ieee1394/sbp2.h +++ /dev/null @@ -1,346 +0,0 @@ -/* - * sbp2.h - Defines and prototypes for sbp2.c - * - * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com) - * jamesg@filanet.com - * - * 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 SBP2_H -#define SBP2_H - -#define SBP2_DEVICE_NAME "sbp2" - -/* - * There is no transport protocol limit to the CDB length, but we implement - * a fixed length only. 16 bytes is enough for disks larger than 2 TB. - */ -#define SBP2_MAX_CDB_SIZE 16 - -/* - * SBP-2 specific definitions - */ - -#define ORB_DIRECTION_WRITE_TO_MEDIA 0x0 -#define ORB_DIRECTION_READ_FROM_MEDIA 0x1 -#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2 - -#define ORB_SET_NULL_PTR(v) (((v) & 0x1) << 31) -#define ORB_SET_NOTIFY(v) (((v) & 0x1) << 31) -#define ORB_SET_RQ_FMT(v) (((v) & 0x3) << 29) -#define ORB_SET_NODE_ID(v) (((v) & 0xffff) << 16) -#define ORB_SET_STATUS_FIFO_HI(v, id) ((v) >> 32 | ORB_SET_NODE_ID(id)) -#define ORB_SET_STATUS_FIFO_LO(v) ((v) & 0xffffffff) -#define ORB_SET_DATA_SIZE(v) ((v) & 0xffff) -#define ORB_SET_PAGE_SIZE(v) (((v) & 0x7) << 16) -#define ORB_SET_PAGE_TABLE_PRESENT(v) (((v) & 0x1) << 19) -#define ORB_SET_MAX_PAYLOAD(v) (((v) & 0xf) << 20) -#define ORB_SET_SPEED(v) (((v) & 0x7) << 24) -#define ORB_SET_DIRECTION(v) (((v) & 0x1) << 27) - -struct sbp2_command_orb { - u32 next_ORB_hi; - u32 next_ORB_lo; - u32 data_descriptor_hi; - u32 data_descriptor_lo; - u32 misc; - u8 cdb[SBP2_MAX_CDB_SIZE]; -} __attribute__((packed)); - -#define SBP2_LOGIN_REQUEST 0x0 -#define SBP2_QUERY_LOGINS_REQUEST 0x1 -#define SBP2_RECONNECT_REQUEST 0x3 -#define SBP2_SET_PASSWORD_REQUEST 0x4 -#define SBP2_LOGOUT_REQUEST 0x7 -#define SBP2_ABORT_TASK_REQUEST 0xb -#define SBP2_ABORT_TASK_SET 0xc -#define SBP2_LOGICAL_UNIT_RESET 0xe -#define SBP2_TARGET_RESET_REQUEST 0xf - -#define ORB_SET_LUN(v) ((v) & 0xffff) -#define ORB_SET_FUNCTION(v) (((v) & 0xf) << 16) -#define ORB_SET_RECONNECT(v) (((v) & 0xf) << 20) -#define ORB_SET_EXCLUSIVE(v) ((v) ? 1 << 28 : 0) -#define ORB_SET_LOGIN_RESP_LENGTH(v) ((v) & 0xffff) -#define ORB_SET_PASSWD_LENGTH(v) (((v) & 0xffff) << 16) - -struct sbp2_login_orb { - u32 password_hi; - u32 password_lo; - u32 login_response_hi; - u32 login_response_lo; - u32 lun_misc; - u32 passwd_resp_lengths; - u32 status_fifo_hi; - u32 status_fifo_lo; -} __attribute__((packed)); - -#define RESPONSE_GET_LOGIN_ID(v) ((v) & 0xffff) -#define RESPONSE_GET_LENGTH(v) (((v) >> 16) & 0xffff) -#define RESPONSE_GET_RECONNECT_HOLD(v) ((v) & 0xffff) - -struct sbp2_login_response { - u32 length_login_ID; - u32 command_block_agent_hi; - u32 command_block_agent_lo; - u32 reconnect_hold; -} __attribute__((packed)); - -#define ORB_SET_LOGIN_ID(v) ((v) & 0xffff) -#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(v) ((v) & 0xffff) - -struct sbp2_query_logins_orb { - u32 reserved1; - u32 reserved2; - u32 query_response_hi; - u32 query_response_lo; - u32 lun_misc; - u32 reserved_resp_length; - u32 status_fifo_hi; - u32 status_fifo_lo; -} __attribute__((packed)); - -#define RESPONSE_GET_MAX_LOGINS(v) ((v) & 0xffff) -#define RESPONSE_GET_ACTIVE_LOGINS(v) ((RESPONSE_GET_LENGTH((v)) - 4) / 12) - -struct sbp2_query_logins_response { - u32 length_max_logins; - u32 misc_IDs; - u32 initiator_misc_hi; - u32 initiator_misc_lo; -} __attribute__((packed)); - -struct sbp2_reconnect_orb { - u32 reserved1; - u32 reserved2; - u32 reserved3; - u32 reserved4; - u32 login_ID_misc; - u32 reserved5; - u32 status_fifo_hi; - u32 status_fifo_lo; -} __attribute__((packed)); - -struct sbp2_logout_orb { - u32 reserved1; - u32 reserved2; - u32 reserved3; - u32 reserved4; - u32 login_ID_misc; - u32 reserved5; - u32 status_fifo_hi; - u32 status_fifo_lo; -} __attribute__((packed)); - -struct sbp2_unrestricted_page_table { - __be32 high; - __be32 low; -}; - -#define RESP_STATUS_REQUEST_COMPLETE 0x0 -#define RESP_STATUS_TRANSPORT_FAILURE 0x1 -#define RESP_STATUS_ILLEGAL_REQUEST 0x2 -#define RESP_STATUS_VENDOR_DEPENDENT 0x3 - -#define SBP2_STATUS_NO_ADDITIONAL_INFO 0x0 -#define SBP2_STATUS_REQ_TYPE_NOT_SUPPORTED 0x1 -#define SBP2_STATUS_SPEED_NOT_SUPPORTED 0x2 -#define SBP2_STATUS_PAGE_SIZE_NOT_SUPPORTED 0x3 -#define SBP2_STATUS_ACCESS_DENIED 0x4 -#define SBP2_STATUS_LU_NOT_SUPPORTED 0x5 -#define SBP2_STATUS_MAX_PAYLOAD_TOO_SMALL 0x6 -#define SBP2_STATUS_RESOURCES_UNAVAILABLE 0x8 -#define SBP2_STATUS_FUNCTION_REJECTED 0x9 -#define SBP2_STATUS_LOGIN_ID_NOT_RECOGNIZED 0xa -#define SBP2_STATUS_DUMMY_ORB_COMPLETED 0xb -#define SBP2_STATUS_REQUEST_ABORTED 0xc -#define SBP2_STATUS_UNSPECIFIED_ERROR 0xff - -#define SFMT_CURRENT_ERROR 0x0 -#define SFMT_DEFERRED_ERROR 0x1 -#define SFMT_VENDOR_DEPENDENT_STATUS 0x3 - -#define STATUS_GET_SRC(v) (((v) >> 30) & 0x3) -#define STATUS_GET_RESP(v) (((v) >> 28) & 0x3) -#define STATUS_GET_LEN(v) (((v) >> 24) & 0x7) -#define STATUS_GET_SBP_STATUS(v) (((v) >> 16) & 0xff) -#define STATUS_GET_ORB_OFFSET_HI(v) ((v) & 0x0000ffff) -#define STATUS_TEST_DEAD(v) ((v) & 0x08000000) -/* test 'resp' | 'dead' | 'sbp2_status' */ -#define STATUS_TEST_RDS(v) ((v) & 0x38ff0000) - -struct sbp2_status_block { - u32 ORB_offset_hi_misc; - u32 ORB_offset_lo; - u8 command_set_dependent[24]; -} __attribute__((packed)); - - -/* - * SBP2 related configuration ROM definitions - */ - -#define SBP2_UNIT_DIRECTORY_OFFSET_KEY 0xd1 -#define SBP2_CSR_OFFSET_KEY 0x54 -#define SBP2_UNIT_SPEC_ID_KEY 0x12 -#define SBP2_UNIT_SW_VERSION_KEY 0x13 -#define SBP2_COMMAND_SET_SPEC_ID_KEY 0x38 -#define SBP2_COMMAND_SET_KEY 0x39 -#define SBP2_UNIT_CHARACTERISTICS_KEY 0x3a -#define SBP2_DEVICE_TYPE_AND_LUN_KEY 0x14 -#define SBP2_FIRMWARE_REVISION_KEY 0x3c - -#define SBP2_AGENT_STATE_OFFSET 0x00ULL -#define SBP2_AGENT_RESET_OFFSET 0x04ULL -#define SBP2_ORB_POINTER_OFFSET 0x08ULL -#define SBP2_DOORBELL_OFFSET 0x10ULL -#define SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET 0x14ULL -#define SBP2_UNSOLICITED_STATUS_VALUE 0xf - -#define SBP2_BUSY_TIMEOUT_ADDRESS 0xfffff0000210ULL -/* biggest possible value for Single Phase Retry count is 0xf */ -#define SBP2_BUSY_TIMEOUT_VALUE 0xf - -#define SBP2_AGENT_RESET_DATA 0xf - -#define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e -#define SBP2_SW_VERSION_ENTRY 0x00010483 - -/* - * The default maximum s/g segment size of a FireWire controller is - * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to - * be quadlet-aligned, we set the length limit to 0xffff & ~3. - */ -#define SBP2_MAX_SEG_SIZE 0xfffc - -/* - * There is no real limitation of the queue depth (i.e. length of the linked - * list of command ORBs) at the target. The chosen depth is merely an - * implementation detail of the sbp2 driver. - */ -#define SBP2_MAX_CMDS 8 - -#define SBP2_SCSI_STATUS_GOOD 0x0 -#define SBP2_SCSI_STATUS_CHECK_CONDITION 0x2 -#define SBP2_SCSI_STATUS_CONDITION_MET 0x4 -#define SBP2_SCSI_STATUS_BUSY 0x8 -#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT 0x18 -#define SBP2_SCSI_STATUS_COMMAND_TERMINATED 0x22 -#define SBP2_SCSI_STATUS_SELECTION_TIMEOUT 0xff - - -/* - * Representations of commands and devices - */ - -/* Per SCSI command */ -struct sbp2_command_info { - struct list_head list; - struct sbp2_command_orb command_orb; - dma_addr_t command_orb_dma; - struct scsi_cmnd *Current_SCpnt; - void (*Current_done)(struct scsi_cmnd *); - - /* Also need s/g structure for each sbp2 command */ - struct sbp2_unrestricted_page_table - scatter_gather_element[SG_ALL] __attribute__((aligned(8))); - dma_addr_t sge_dma; -}; - -/* Per FireWire host */ -struct sbp2_fwhost_info { - struct hpsb_host *host; - struct list_head logical_units; -}; - -/* Per logical unit */ -struct sbp2_lu { - /* Operation request blocks */ - struct sbp2_command_orb *last_orb; - dma_addr_t last_orb_dma; - struct sbp2_login_orb *login_orb; - dma_addr_t login_orb_dma; - struct sbp2_login_response *login_response; - dma_addr_t login_response_dma; - struct sbp2_query_logins_orb *query_logins_orb; - dma_addr_t query_logins_orb_dma; - struct sbp2_query_logins_response *query_logins_response; - dma_addr_t query_logins_response_dma; - struct sbp2_reconnect_orb *reconnect_orb; - dma_addr_t reconnect_orb_dma; - struct sbp2_logout_orb *logout_orb; - dma_addr_t logout_orb_dma; - struct sbp2_status_block status_block; - - /* How to talk to the unit */ - u64 management_agent_addr; - u64 command_block_agent_addr; - u32 speed_code; - u32 max_payload_size; - u16 lun; - - /* Address for the unit to write status blocks to */ - u64 status_fifo_addr; - - /* Waitqueue flag for logins, reconnects, logouts, query logins */ - unsigned int access_complete:1; - - /* Pool of command ORBs for this logical unit */ - spinlock_t cmd_orb_lock; - struct list_head cmd_orb_inuse; - struct list_head cmd_orb_completed; - - /* Backlink to FireWire host; list of units attached to the host */ - struct sbp2_fwhost_info *hi; - struct list_head lu_list; - - /* IEEE 1394 core's device representations */ - struct node_entry *ne; - struct unit_directory *ud; - - /* SCSI core's device representations */ - struct scsi_device *sdev; - struct Scsi_Host *shost; - - /* Device specific workarounds/brokeness */ - unsigned workarounds; - - /* Connection state */ - atomic_t state; - - /* For deferred requests to the fetch agent */ - struct work_struct protocol_work; -}; - -/* For use in sbp2_lu.state */ -enum sbp2lu_state_types { - SBP2LU_STATE_RUNNING, /* all normal */ - SBP2LU_STATE_IN_RESET, /* between bus reset and reconnect */ - SBP2LU_STATE_IN_SHUTDOWN /* when sbp2_remove was called */ -}; - -/* For use in sbp2_lu.workarounds and in the corresponding - * module load parameter */ -#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 -#define SBP2_WORKAROUND_INQUIRY_36 0x2 -#define SBP2_WORKAROUND_MODE_SENSE_8 0x4 -#define SBP2_WORKAROUND_FIX_CAPACITY 0x8 -#define SBP2_WORKAROUND_DELAY_INQUIRY 0x10 -#define SBP2_INQUIRY_DELAY 12 -#define SBP2_WORKAROUND_POWER_CONDITION 0x20 -#define SBP2_WORKAROUND_OVERRIDE 0x100 - -#endif /* SBP2_H */ diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c deleted file mode 100644 index 5c74f79..0000000 --- a/drivers/ieee1394/video1394.c +++ /dev/null @@ -1,1528 +0,0 @@ -/* - * video1394.c - video 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. - * - * NOTES: - * - * ioctl return codes: - * EFAULT is only for invalid address for the argp - * EINVAL for out of range values - * EBUSY when trying to use an already used resource - * ESRCH when trying to free/stop a not used resource - * EAGAIN for resource allocation failure that could perhaps succeed later - * ENOTTY for unsupported ioctl request - * - */ -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/fs.h> -#include <linux/poll.h> -#include <linux/delay.h> -#include <linux/bitops.h> -#include <linux/types.h> -#include <linux/vmalloc.h> -#include <linux/timex.h> -#include <linux/mm.h> -#include <linux/compat.h> -#include <linux/cdev.h> - -#include "dma.h" -#include "highlevel.h" -#include "hosts.h" -#include "ieee1394.h" -#include "ieee1394_core.h" -#include "ieee1394_hotplug.h" -#include "ieee1394_types.h" -#include "nodemgr.h" -#include "ohci1394.h" -#include "video1394.h" - -#define ISO_CHANNELS 64 - -struct it_dma_prg { - struct dma_cmd begin; - quadlet_t data[4]; - struct dma_cmd end; - quadlet_t pad[4]; /* FIXME: quick hack for memory alignment */ -}; - -struct dma_iso_ctx { - struct ti_ohci *ohci; - int type; /* OHCI_ISO_TRANSMIT or OHCI_ISO_RECEIVE */ - struct ohci1394_iso_tasklet iso_tasklet; - int channel; - int ctx; - int last_buffer; - int * next_buffer; /* For ISO Transmit of video packets - to write the correct SYT field - into the next block */ - unsigned int num_desc; - unsigned int buf_size; - unsigned int frame_size; - unsigned int packet_size; - unsigned int left_size; - unsigned int nb_cmd; - - struct dma_region dma; - - struct dma_prog_region *prg_reg; - - struct dma_cmd **ir_prg; - struct it_dma_prg **it_prg; - - unsigned int *buffer_status; - unsigned int *buffer_prg_assignment; - struct timeval *buffer_time; /* time when the buffer was received */ - unsigned int *last_used_cmd; /* For ISO Transmit with - variable sized packets only ! */ - int ctrlClear; - int ctrlSet; - int cmdPtr; - int ctxMatch; - wait_queue_head_t waitq; - spinlock_t lock; - unsigned int syt_offset; - int flags; - - struct list_head link; -}; - - -struct file_ctx { - struct ti_ohci *ohci; - struct list_head context_list; - struct dma_iso_ctx *current_ctx; -}; - -#ifdef CONFIG_IEEE1394_VERBOSEDEBUG -#define VIDEO1394_DEBUG -#endif - -#ifdef DBGMSG -#undef DBGMSG -#endif - -#ifdef VIDEO1394_DEBUG -#define DBGMSG(card, fmt, args...) \ -printk(KERN_INFO "video1394_%d: " fmt "\n" , card , ## args) -#else -#define DBGMSG(card, fmt, args...) do {} while (0) -#endif - -/* print general (card independent) information */ -#define PRINT_G(level, fmt, args...) \ -printk(level "video1394: " fmt "\n" , ## args) - -/* print card specific information */ -#define PRINT(level, card, fmt, args...) \ -printk(level "video1394_%d: " fmt "\n" , card , ## args) - -static void wakeup_dma_ir_ctx(unsigned long l); -static void wakeup_dma_it_ctx(unsigned long l); - -static struct hpsb_highlevel video1394_highlevel; - -static int free_dma_iso_ctx(struct dma_iso_ctx *d) -{ - int i; - - DBGMSG(d->ohci->host->id, "Freeing dma_iso_ctx %d", d->ctx); - - ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); - if (d->iso_tasklet.link.next != NULL) - ohci1394_unregister_iso_tasklet(d->ohci, &d->iso_tasklet); - - dma_region_free(&d->dma); - - if (d->prg_reg) { - for (i = 0; i < d->num_desc; i++) - dma_prog_region_free(&d->prg_reg[i]); - kfree(d->prg_reg); - } - - kfree(d->ir_prg); - kfree(d->it_prg); - kfree(d->buffer_status); - kfree(d->buffer_prg_assignment); - kfree(d->buffer_time); - kfree(d->last_used_cmd); - kfree(d->next_buffer); - list_del(&d->link); - kfree(d); - - return 0; -} - -static struct dma_iso_ctx * -alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc, - int buf_size, int channel, unsigned int packet_size) -{ - struct dma_iso_ctx *d; - int i; - - d = kzalloc(sizeof(*d), GFP_KERNEL); - if (!d) { - PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma_iso_ctx"); - return NULL; - } - - d->ohci = ohci; - d->type = type; - d->channel = channel; - d->num_desc = num_desc; - d->frame_size = buf_size; - d->buf_size = PAGE_ALIGN(buf_size); - d->last_buffer = -1; - INIT_LIST_HEAD(&d->link); - init_waitqueue_head(&d->waitq); - - /* Init the regions for easy cleanup */ - dma_region_init(&d->dma); - - if (dma_region_alloc(&d->dma, (d->num_desc - 1) * d->buf_size, ohci->dev, - PCI_DMA_BIDIRECTIONAL)) { - PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma buffer"); - free_dma_iso_ctx(d); - return NULL; - } - - if (type == OHCI_ISO_RECEIVE) - ohci1394_init_iso_tasklet(&d->iso_tasklet, type, - wakeup_dma_ir_ctx, - (unsigned long) d); - else - ohci1394_init_iso_tasklet(&d->iso_tasklet, type, - wakeup_dma_it_ctx, - (unsigned long) d); - - if (ohci1394_register_iso_tasklet(ohci, &d->iso_tasklet) < 0) { - PRINT(KERN_ERR, ohci->host->id, "no free iso %s contexts", - type == OHCI_ISO_RECEIVE ? "receive" : "transmit"); - free_dma_iso_ctx(d); - return NULL; - } - d->ctx = d->iso_tasklet.context; - - d->prg_reg = kmalloc(d->num_desc * sizeof(*d->prg_reg), GFP_KERNEL); - if (!d->prg_reg) { - PRINT(KERN_ERR, ohci->host->id, "Failed to allocate ir prg regs"); - free_dma_iso_ctx(d); - return NULL; - } - /* Makes for easier cleanup */ - for (i = 0; i < d->num_desc; i++) - dma_prog_region_init(&d->prg_reg[i]); - - if (type == OHCI_ISO_RECEIVE) { - d->ctrlSet = OHCI1394_IsoRcvContextControlSet+32*d->ctx; - d->ctrlClear = OHCI1394_IsoRcvContextControlClear+32*d->ctx; - d->cmdPtr = OHCI1394_IsoRcvCommandPtr+32*d->ctx; - d->ctxMatch = OHCI1394_IsoRcvContextMatch+32*d->ctx; - - d->ir_prg = kzalloc(d->num_desc * sizeof(*d->ir_prg), - GFP_KERNEL); - - if (!d->ir_prg) { - PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg"); - free_dma_iso_ctx(d); - return NULL; - } - - d->nb_cmd = d->buf_size / PAGE_SIZE + 1; - d->left_size = (d->frame_size % PAGE_SIZE) ? - d->frame_size % PAGE_SIZE : PAGE_SIZE; - - for (i = 0;i < d->num_desc; i++) { - if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd * - sizeof(struct dma_cmd), ohci->dev)) { - PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg"); - free_dma_iso_ctx(d); - return NULL; - } - d->ir_prg[i] = (struct dma_cmd *)d->prg_reg[i].kvirt; - } - - } else { /* OHCI_ISO_TRANSMIT */ - d->ctrlSet = OHCI1394_IsoXmitContextControlSet+16*d->ctx; - d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx; - d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx; - - d->it_prg = kzalloc(d->num_desc * sizeof(*d->it_prg), - GFP_KERNEL); - - if (!d->it_prg) { - PRINT(KERN_ERR, ohci->host->id, - "Failed to allocate dma it prg"); - free_dma_iso_ctx(d); - return NULL; - } - - d->packet_size = packet_size; - - if (PAGE_SIZE % packet_size || packet_size>4096) { - PRINT(KERN_ERR, ohci->host->id, - "Packet size %d (page_size: %ld) " - "not yet supported\n", - packet_size, PAGE_SIZE); - free_dma_iso_ctx(d); - return NULL; - } - - d->nb_cmd = d->frame_size / d->packet_size; - if (d->frame_size % d->packet_size) { - d->nb_cmd++; - d->left_size = d->frame_size % d->packet_size; - } else - d->left_size = d->packet_size; - - for (i = 0; i < d->num_desc; i++) { - if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd * - sizeof(struct it_dma_prg), ohci->dev)) { - PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma it prg"); - free_dma_iso_ctx(d); - return NULL; - } - d->it_prg[i] = (struct it_dma_prg *)d->prg_reg[i].kvirt; - } - } - - d->buffer_status = - kzalloc(d->num_desc * sizeof(*d->buffer_status), GFP_KERNEL); - d->buffer_prg_assignment = - kzalloc(d->num_desc * sizeof(*d->buffer_prg_assignment), GFP_KERNEL); - d->buffer_time = - kzalloc(d->num_desc * sizeof(*d->buffer_time), GFP_KERNEL); - d->last_used_cmd = - kzalloc(d->num_desc * sizeof(*d->last_used_cmd), GFP_KERNEL); - d->next_buffer = - kzalloc(d->num_desc * sizeof(*d->next_buffer), GFP_KERNEL); - - if (!d->buffer_status || !d->buffer_prg_assignment || !d->buffer_time || - !d->last_used_cmd || !d->next_buffer) { - PRINT(KERN_ERR, ohci->host->id, - "Failed to allocate dma_iso_ctx member"); - free_dma_iso_ctx(d); - return NULL; - } - - spin_lock_init(&d->lock); - - DBGMSG(ohci->host->id, "Iso %s DMA: %d buffers " - "of size %d allocated for a frame size %d, each with %d prgs", - (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit", - d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd); - - return d; -} - -static void reset_ir_status(struct dma_iso_ctx *d, int n) -{ - int i; - d->ir_prg[n][0].status = cpu_to_le32(4); - d->ir_prg[n][1].status = cpu_to_le32(PAGE_SIZE-4); - for (i = 2; i < d->nb_cmd - 1; i++) - d->ir_prg[n][i].status = cpu_to_le32(PAGE_SIZE); - d->ir_prg[n][i].status = cpu_to_le32(d->left_size); -} - -static void reprogram_dma_ir_prg(struct dma_iso_ctx *d, int n, int buffer, int flags) -{ - struct dma_cmd *ir_prg = d->ir_prg[n]; - unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size; - int i; - - d->buffer_prg_assignment[n] = buffer; - - ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf - - (unsigned long)d->dma.kvirt)); - ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, - (buf + 4) - (unsigned long)d->dma.kvirt)); - - for (i=2;i<d->nb_cmd-1;i++) { - ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, - (buf+(i-1)*PAGE_SIZE) - - (unsigned long)d->dma.kvirt)); - } - - ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | - DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size); - ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, - (buf+(i-1)*PAGE_SIZE) - (unsigned long)d->dma.kvirt)); -} - -static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags) -{ - struct dma_cmd *ir_prg = d->ir_prg[n]; - struct dma_prog_region *ir_reg = &d->prg_reg[n]; - unsigned long buf = (unsigned long)d->dma.kvirt; - int i; - - /* the first descriptor will read only 4 bytes */ - ir_prg[0].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | - DMA_CTL_BRANCH | 4); - - /* set the sync flag */ - if (flags & VIDEO1394_SYNC_FRAMES) - ir_prg[0].control |= cpu_to_le32(DMA_CTL_WAIT); - - ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf - - (unsigned long)d->dma.kvirt)); - ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg, - 1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1); - - /* If there is *not* only one DMA page per frame (hence, d->nb_cmd==2) */ - if (d->nb_cmd > 2) { - /* The second descriptor will read PAGE_SIZE-4 bytes */ - ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | - DMA_CTL_BRANCH | (PAGE_SIZE-4)); - ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) - - (unsigned long)d->dma.kvirt)); - ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg, - 2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1); - - for (i = 2; i < d->nb_cmd - 1; i++) { - ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | - DMA_CTL_BRANCH | PAGE_SIZE); - ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, - (buf+(i-1)*PAGE_SIZE) - - (unsigned long)d->dma.kvirt)); - - ir_prg[i].branchAddress = - cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg, - (i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1); - } - - /* The last descriptor will generate an interrupt */ - ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | - DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size); - ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, - (buf+(i-1)*PAGE_SIZE) - - (unsigned long)d->dma.kvirt)); - } else { - /* Only one DMA page is used. Read d->left_size immediately and */ - /* generate an interrupt as this is also the last page. */ - ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | - DMA_CTL_IRQ | DMA_CTL_BRANCH | (d->left_size-4)); - ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, - (buf + 4) - (unsigned long)d->dma.kvirt)); - } -} - -static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags) -{ - struct ti_ohci *ohci = (struct ti_ohci *)d->ohci; - int i; - - d->flags = flags; - - ohci1394_stop_context(ohci, d->ctrlClear, NULL); - - for (i=0;i<d->num_desc;i++) { - initialize_dma_ir_prg(d, i, flags); - reset_ir_status(d, i); - } - - /* reset the ctrl register */ - reg_write(ohci, d->ctrlClear, 0xf0000000); - - /* Set bufferFill */ - reg_write(ohci, d->ctrlSet, 0x80000000); - - /* Set isoch header */ - if (flags & VIDEO1394_INCLUDE_ISO_HEADERS) - reg_write(ohci, d->ctrlSet, 0x40000000); - - /* Set the context match register to match on all tags, - sync for sync tag, and listen to d->channel */ - reg_write(ohci, d->ctxMatch, 0xf0000000|((tag&0xf)<<8)|d->channel); - - /* Set up isoRecvIntMask to generate interrupts */ - reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1<<d->ctx); -} - -/* find which context is listening to this channel */ -static struct dma_iso_ctx * -find_ctx(struct list_head *list, int type, int channel) -{ - struct dma_iso_ctx *ctx; - - list_for_each_entry(ctx, list, link) { - if (ctx->type == type && ctx->channel == channel) - return ctx; - } - - return NULL; -} - -static void wakeup_dma_ir_ctx(unsigned long l) -{ - struct dma_iso_ctx *d = (struct dma_iso_ctx *) l; - int i; - - spin_lock(&d->lock); - - for (i = 0; i < d->num_desc; i++) { - if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) { - reset_ir_status(d, i); - d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY; - do_gettimeofday(&d->buffer_time[d->buffer_prg_assignment[i]]); - dma_region_sync_for_cpu(&d->dma, - d->buffer_prg_assignment[i] * d->buf_size, - d->buf_size); - } - } - - spin_unlock(&d->lock); - - if (waitqueue_active(&d->waitq)) - wake_up_interruptible(&d->waitq); -} - -static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d, - int n) -{ - unsigned char* buf = d->dma.kvirt + n * d->buf_size; - u32 cycleTimer; - u32 timeStamp; - - if (n == -1) { - return; - } - - cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer); - - timeStamp = ((cycleTimer & 0x0fff) + d->syt_offset); /* 11059 = 450 us */ - timeStamp = (timeStamp % 3072 + ((timeStamp / 3072) << 12) - + (cycleTimer & 0xf000)) & 0xffff; - - buf[6] = timeStamp >> 8; - buf[7] = timeStamp & 0xff; - - /* if first packet is empty packet, then put timestamp into the next full one too */ - if ( (le32_to_cpu(d->it_prg[n][0].data[1]) >>16) == 0x008) { - buf += d->packet_size; - buf[6] = timeStamp >> 8; - buf[7] = timeStamp & 0xff; - } - - /* do the next buffer frame too in case of irq latency */ - n = d->next_buffer[n]; - if (n == -1) { - return; - } - buf = d->dma.kvirt + n * d->buf_size; - - timeStamp += (d->last_used_cmd[n] << 12) & 0xffff; - - buf[6] = timeStamp >> 8; - buf[7] = timeStamp & 0xff; - - /* if first packet is empty packet, then put timestamp into the next full one too */ - if ( (le32_to_cpu(d->it_prg[n][0].data[1]) >>16) == 0x008) { - buf += d->packet_size; - buf[6] = timeStamp >> 8; - buf[7] = timeStamp & 0xff; - } - -#if 0 - printk("curr: %d, next: %d, cycleTimer: %08x timeStamp: %08x\n", - curr, n, cycleTimer, timeStamp); -#endif -} - -static void wakeup_dma_it_ctx(unsigned long l) -{ - struct dma_iso_ctx *d = (struct dma_iso_ctx *) l; - struct ti_ohci *ohci = d->ohci; - int i; - - spin_lock(&d->lock); - - for (i = 0; i < d->num_desc; i++) { - if (d->it_prg[i][d->last_used_cmd[i]].end.status & - cpu_to_le32(0xFFFF0000)) { - int next = d->next_buffer[i]; - put_timestamp(ohci, d, next); - d->it_prg[i][d->last_used_cmd[i]].end.status = 0; - d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY; - } - } - - spin_unlock(&d->lock); - - if (waitqueue_active(&d->waitq)) - wake_up_interruptible(&d->waitq); -} - -static void reprogram_dma_it_prg(struct dma_iso_ctx *d, int n, int buffer) -{ - struct it_dma_prg *it_prg = d->it_prg[n]; - unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size; - int i; - - d->buffer_prg_assignment[n] = buffer; - for (i=0;i<d->nb_cmd;i++) { - it_prg[i].end.address = - cpu_to_le32(dma_region_offset_to_bus(&d->dma, - (buf+i*d->packet_size) - (unsigned long)d->dma.kvirt)); - } -} - -static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag) -{ - struct it_dma_prg *it_prg = d->it_prg[n]; - struct dma_prog_region *it_reg = &d->prg_reg[n]; - unsigned long buf = (unsigned long)d->dma.kvirt; - int i; - d->last_used_cmd[n] = d->nb_cmd - 1; - for (i=0;i<d->nb_cmd;i++) { - - it_prg[i].begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE | - DMA_CTL_IMMEDIATE | 8) ; - it_prg[i].begin.address = 0; - - it_prg[i].begin.status = 0; - - it_prg[i].data[0] = cpu_to_le32( - (IEEE1394_SPEED_100 << 16) - | (/* tag */ 1 << 14) - | (d->channel << 8) - | (TCODE_ISO_DATA << 4)); - if (i==0) it_prg[i].data[0] |= cpu_to_le32(sync_tag); - it_prg[i].data[1] = cpu_to_le32(d->packet_size << 16); - it_prg[i].data[2] = 0; - it_prg[i].data[3] = 0; - - it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | - DMA_CTL_BRANCH); - it_prg[i].end.address = - cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf+i*d->packet_size) - - (unsigned long)d->dma.kvirt)); - - if (i<d->nb_cmd-1) { - it_prg[i].end.control |= cpu_to_le32(d->packet_size); - it_prg[i].begin.branchAddress = - cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * - sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); - it_prg[i].end.branchAddress = - cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * - sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); - } else { - /* the last prg generates an interrupt */ - it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | - DMA_CTL_IRQ | d->left_size); - /* the last prg doesn't branch */ - it_prg[i].begin.branchAddress = 0; - it_prg[i].end.branchAddress = 0; - } - it_prg[i].end.status = 0; - } -} - -static void initialize_dma_it_prg_var_packet_queue( - struct dma_iso_ctx *d, int n, unsigned int * packet_sizes, - struct ti_ohci *ohci) -{ - struct it_dma_prg *it_prg = d->it_prg[n]; - struct dma_prog_region *it_reg = &d->prg_reg[n]; - int i; - -#if 0 - if (n != -1) { - put_timestamp(ohci, d, n); - } -#endif - d->last_used_cmd[n] = d->nb_cmd - 1; - - for (i = 0; i < d->nb_cmd; i++) { - unsigned int size; - if (packet_sizes[i] > d->packet_size) { - size = d->packet_size; - } else { - size = packet_sizes[i]; - } - it_prg[i].data[1] = cpu_to_le32(size << 16); - it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH); - - if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) { - it_prg[i].end.control |= cpu_to_le32(size); - it_prg[i].begin.branchAddress = - cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * - sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); - it_prg[i].end.branchAddress = - cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) * - sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3); - } else { - /* the last prg generates an interrupt */ - it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | - DMA_CTL_IRQ | size); - /* the last prg doesn't branch */ - it_prg[i].begin.branchAddress = 0; - it_prg[i].end.branchAddress = 0; - d->last_used_cmd[n] = i; - break; - } - } -} - -static void initialize_dma_it_ctx(struct dma_iso_ctx *d, int sync_tag, - unsigned int syt_offset, int flags) -{ - struct ti_ohci *ohci = (struct ti_ohci *)d->ohci; - int i; - - d->flags = flags; - d->syt_offset = (syt_offset == 0 ? 11000 : syt_offset); - - ohci1394_stop_context(ohci, d->ctrlClear, NULL); - - for (i=0;i<d->num_desc;i++) - initialize_dma_it_prg(d, i, sync_tag); - - /* Set up isoRecvIntMask to generate interrupts */ - reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx); -} - -static inline unsigned video1394_buffer_state(struct dma_iso_ctx *d, - unsigned int buffer) -{ - unsigned long flags; - unsigned int ret; - spin_lock_irqsave(&d->lock, flags); - ret = d->buffer_status[buffer]; - spin_unlock_irqrestore(&d->lock, flags); - return ret; -} - -static long video1394_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct file_ctx *ctx = file->private_data; - struct ti_ohci *ohci = ctx->ohci; - unsigned long flags; - void __user *argp = (void __user *)arg; - - switch(cmd) - { - case VIDEO1394_IOC_LISTEN_CHANNEL: - case VIDEO1394_IOC_TALK_CHANNEL: - { - struct video1394_mmap v; - u64 mask; - struct dma_iso_ctx *d; - int i; - - if (copy_from_user(&v, argp, sizeof(v))) - return -EFAULT; - - /* if channel < 0, find lowest available one */ - if (v.channel < 0) { - mask = (u64)0x1; - for (i=0; ; i++) { - if (i == ISO_CHANNELS) { - PRINT(KERN_ERR, ohci->host->id, - "No free channel found"); - return -EAGAIN; - } - if (!(ohci->ISO_channel_usage & mask)) { - v.channel = i; - PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i); - break; - } - mask = mask << 1; - } - } else if (v.channel >= ISO_CHANNELS) { - PRINT(KERN_ERR, ohci->host->id, - "Iso channel %d out of bounds", v.channel); - return -EINVAL; - } else { - mask = (u64)0x1<<v.channel; - } - DBGMSG(ohci->host->id, "mask: %08X%08X usage: %08X%08X\n", - (u32)(mask>>32),(u32)(mask&0xffffffff), - (u32)(ohci->ISO_channel_usage>>32), - (u32)(ohci->ISO_channel_usage&0xffffffff)); - if (ohci->ISO_channel_usage & mask) { - PRINT(KERN_ERR, ohci->host->id, - "Channel %d is already taken", v.channel); - return -EBUSY; - } - - if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) { - PRINT(KERN_ERR, ohci->host->id, - "Invalid %d length buffer requested",v.buf_size); - return -EINVAL; - } - - if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) { - PRINT(KERN_ERR, ohci->host->id, - "Invalid %d buffers requested",v.nb_buffers); - return -EINVAL; - } - - if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) { - PRINT(KERN_ERR, ohci->host->id, - "%d buffers of size %d bytes is too big", - v.nb_buffers, v.buf_size); - return -EINVAL; - } - - if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) { - d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE, - v.nb_buffers + 1, v.buf_size, - v.channel, 0); - - if (d == NULL) { - PRINT(KERN_ERR, ohci->host->id, - "Couldn't allocate ir context"); - return -EAGAIN; - } - initialize_dma_ir_ctx(d, v.sync_tag, v.flags); - - ctx->current_ctx = d; - - v.buf_size = d->buf_size; - list_add_tail(&d->link, &ctx->context_list); - - DBGMSG(ohci->host->id, - "iso context %d listen on channel %d", - d->ctx, v.channel); - } - else { - d = alloc_dma_iso_ctx(ohci, OHCI_ISO_TRANSMIT, - v.nb_buffers + 1, v.buf_size, - v.channel, v.packet_size); - - if (d == NULL) { - PRINT(KERN_ERR, ohci->host->id, - "Couldn't allocate it context"); - return -EAGAIN; - } - initialize_dma_it_ctx(d, v.sync_tag, - v.syt_offset, v.flags); - - ctx->current_ctx = d; - - v.buf_size = d->buf_size; - - list_add_tail(&d->link, &ctx->context_list); - - DBGMSG(ohci->host->id, - "Iso context %d talk on channel %d", d->ctx, - v.channel); - } - - if (copy_to_user(argp, &v, sizeof(v))) { - /* FIXME : free allocated dma resources */ - return -EFAULT; - } - - ohci->ISO_channel_usage |= mask; - - return 0; - } - case VIDEO1394_IOC_UNLISTEN_CHANNEL: - case VIDEO1394_IOC_UNTALK_CHANNEL: - { - int channel; - u64 mask; - struct dma_iso_ctx *d; - - if (copy_from_user(&channel, argp, sizeof(int))) - return -EFAULT; - - if (channel < 0 || channel >= ISO_CHANNELS) { - PRINT(KERN_ERR, ohci->host->id, - "Iso channel %d out of bound", channel); - return -EINVAL; - } - mask = (u64)0x1<<channel; - if (!(ohci->ISO_channel_usage & mask)) { - PRINT(KERN_ERR, ohci->host->id, - "Channel %d is not being used", channel); - return -ESRCH; - } - - /* Mark this channel as unused */ - ohci->ISO_channel_usage &= ~mask; - - if (cmd == VIDEO1394_IOC_UNLISTEN_CHANNEL) - d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, channel); - else - d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel); - - if (d == NULL) return -ESRCH; - DBGMSG(ohci->host->id, "Iso context %d " - "stop talking on channel %d", d->ctx, channel); - free_dma_iso_ctx(d); - - return 0; - } - case VIDEO1394_IOC_LISTEN_QUEUE_BUFFER: - { - struct video1394_wait v; - struct dma_iso_ctx *d; - int next_prg; - - if (unlikely(copy_from_user(&v, argp, sizeof(v)))) - return -EFAULT; - - d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); - if (unlikely(d == NULL)) - return -EFAULT; - - if (unlikely(v.buffer >= d->num_desc - 1)) { - PRINT(KERN_ERR, ohci->host->id, - "Buffer %d out of range",v.buffer); - return -EINVAL; - } - - spin_lock_irqsave(&d->lock,flags); - - if (unlikely(d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED)) { - PRINT(KERN_ERR, ohci->host->id, - "Buffer %d is already used",v.buffer); - spin_unlock_irqrestore(&d->lock,flags); - return -EBUSY; - } - - d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; - - next_prg = (d->last_buffer + 1) % d->num_desc; - if (d->last_buffer>=0) - d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = - cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0) - & 0xfffffff0) | 0x1); - - d->last_buffer = next_prg; - reprogram_dma_ir_prg(d, d->last_buffer, v.buffer, d->flags); - - d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0; - - spin_unlock_irqrestore(&d->lock,flags); - - if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) - { - DBGMSG(ohci->host->id, "Starting iso DMA ctx=%d",d->ctx); - - /* Tell the controller where the first program is */ - reg_write(ohci, d->cmdPtr, - dma_prog_region_offset_to_bus(&d->prg_reg[d->last_buffer], 0) | 0x1); - - /* Run IR context */ - reg_write(ohci, d->ctrlSet, 0x8000); - } - else { - /* Wake up dma context if necessary */ - if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - DBGMSG(ohci->host->id, - "Waking up iso dma ctx=%d", d->ctx); - reg_write(ohci, d->ctrlSet, 0x1000); - } - } - return 0; - - } - case VIDEO1394_IOC_LISTEN_WAIT_BUFFER: - case VIDEO1394_IOC_LISTEN_POLL_BUFFER: - { - struct video1394_wait v; - struct dma_iso_ctx *d; - int i = 0; - - if (unlikely(copy_from_user(&v, argp, sizeof(v)))) - return -EFAULT; - - d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); - if (unlikely(d == NULL)) - return -EFAULT; - - if (unlikely(v.buffer > d->num_desc - 1)) { - PRINT(KERN_ERR, ohci->host->id, - "Buffer %d out of range",v.buffer); - return -EINVAL; - } - - /* - * I change the way it works so that it returns - * the last received frame. - */ - spin_lock_irqsave(&d->lock, flags); - switch(d->buffer_status[v.buffer]) { - case VIDEO1394_BUFFER_READY: - d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; - break; - case VIDEO1394_BUFFER_QUEUED: - if (cmd == VIDEO1394_IOC_LISTEN_POLL_BUFFER) { - /* for polling, return error code EINTR */ - spin_unlock_irqrestore(&d->lock, flags); - return -EINTR; - } - - spin_unlock_irqrestore(&d->lock, flags); - wait_event_interruptible(d->waitq, - video1394_buffer_state(d, v.buffer) == - VIDEO1394_BUFFER_READY); - if (signal_pending(current)) - return -EINTR; - spin_lock_irqsave(&d->lock, flags); - d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; - break; - default: - PRINT(KERN_ERR, ohci->host->id, - "Buffer %d is not queued",v.buffer); - spin_unlock_irqrestore(&d->lock, flags); - return -ESRCH; - } - - /* set time of buffer */ - v.filltime = d->buffer_time[v.buffer]; - - /* - * Look ahead to see how many more buffers have been received - */ - i=0; - while (d->buffer_status[(v.buffer+1)%(d->num_desc - 1)]== - VIDEO1394_BUFFER_READY) { - v.buffer=(v.buffer+1)%(d->num_desc - 1); - i++; - } - spin_unlock_irqrestore(&d->lock, flags); - - v.buffer=i; - if (unlikely(copy_to_user(argp, &v, sizeof(v)))) - return -EFAULT; - - return 0; - } - case VIDEO1394_IOC_TALK_QUEUE_BUFFER: - { - struct video1394_wait v; - unsigned int *psizes = NULL; - struct dma_iso_ctx *d; - int next_prg; - - if (copy_from_user(&v, argp, sizeof(v))) - return -EFAULT; - - d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); - if (d == NULL) return -EFAULT; - - if (v.buffer >= d->num_desc - 1) { - PRINT(KERN_ERR, ohci->host->id, - "Buffer %d out of range",v.buffer); - return -EINVAL; - } - - if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) { - int buf_size = d->nb_cmd * sizeof(*psizes); - struct video1394_queue_variable __user *p = argp; - unsigned int __user *qv; - - if (get_user(qv, &p->packet_sizes)) - return -EFAULT; - - psizes = memdup_user(qv, buf_size); - if (IS_ERR(psizes)) - return PTR_ERR(psizes); - } - - spin_lock_irqsave(&d->lock,flags); - - /* last_buffer is last_prg */ - next_prg = (d->last_buffer + 1) % d->num_desc; - if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) { - PRINT(KERN_ERR, ohci->host->id, - "Buffer %d is already used",v.buffer); - spin_unlock_irqrestore(&d->lock,flags); - kfree(psizes); - return -EBUSY; - } - - if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) { - initialize_dma_it_prg_var_packet_queue( - d, next_prg, psizes, ohci); - } - - d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED; - - if (d->last_buffer >= 0) { - d->it_prg[d->last_buffer] - [ d->last_used_cmd[d->last_buffer] ].end.branchAddress = - cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], - 0) & 0xfffffff0) | 0x3); - - d->it_prg[d->last_buffer] - [ d->last_used_cmd[d->last_buffer] ].begin.branchAddress = - cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], - 0) & 0xfffffff0) | 0x3); - d->next_buffer[d->last_buffer] = (v.buffer + 1) % (d->num_desc - 1); - } - d->last_buffer = next_prg; - reprogram_dma_it_prg(d, d->last_buffer, v.buffer); - d->next_buffer[d->last_buffer] = -1; - - d->it_prg[d->last_buffer][d->last_used_cmd[d->last_buffer]].end.branchAddress = 0; - - spin_unlock_irqrestore(&d->lock,flags); - - if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) - { - DBGMSG(ohci->host->id, "Starting iso transmit DMA ctx=%d", - d->ctx); - put_timestamp(ohci, d, d->last_buffer); - dma_region_sync_for_device(&d->dma, - v.buffer * d->buf_size, d->buf_size); - - /* Tell the controller where the first program is */ - reg_write(ohci, d->cmdPtr, - dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0) | 0x3); - - /* Run IT context */ - reg_write(ohci, d->ctrlSet, 0x8000); - } - else { - /* Wake up dma context if necessary */ - if (!(reg_read(ohci, d->ctrlSet) & 0x400)) { - DBGMSG(ohci->host->id, - "Waking up iso transmit dma ctx=%d", - d->ctx); - put_timestamp(ohci, d, d->last_buffer); - dma_region_sync_for_device(&d->dma, - v.buffer * d->buf_size, d->buf_size); - - reg_write(ohci, d->ctrlSet, 0x1000); - } - } - - kfree(psizes); - return 0; - - } - case VIDEO1394_IOC_TALK_WAIT_BUFFER: - { - struct video1394_wait v; - struct dma_iso_ctx *d; - - if (copy_from_user(&v, argp, sizeof(v))) - return -EFAULT; - - d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); - if (d == NULL) return -EFAULT; - - if (v.buffer >= d->num_desc - 1) { - PRINT(KERN_ERR, ohci->host->id, - "Buffer %d out of range",v.buffer); - return -EINVAL; - } - - switch(d->buffer_status[v.buffer]) { - case VIDEO1394_BUFFER_READY: - d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; - return 0; - case VIDEO1394_BUFFER_QUEUED: - wait_event_interruptible(d->waitq, - (d->buffer_status[v.buffer] == VIDEO1394_BUFFER_READY)); - if (signal_pending(current)) - return -EINTR; - d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE; - return 0; - default: - PRINT(KERN_ERR, ohci->host->id, - "Buffer %d is not queued",v.buffer); - return -ESRCH; - } - } - default: - return -ENOTTY; - } -} - -/* - * This maps the vmalloced and reserved buffer to user space. - * - * FIXME: - * - PAGE_READONLY should suffice!? - * - remap_pfn_range is kind of inefficient for page by page remapping. - * But e.g. pte_alloc() does not work in modules ... :-( - */ - -static int video1394_mmap(struct file *file, struct vm_area_struct *vma) -{ - struct file_ctx *ctx = file->private_data; - - if (ctx->current_ctx == NULL) { - PRINT(KERN_ERR, ctx->ohci->host->id, - "Current iso context not set"); - return -EINVAL; - } - - return dma_region_mmap(&ctx->current_ctx->dma, file, vma); -} - -static unsigned int video1394_poll(struct file *file, poll_table *pt) -{ - struct file_ctx *ctx; - unsigned int mask = 0; - unsigned long flags; - struct dma_iso_ctx *d; - int i; - - ctx = file->private_data; - d = ctx->current_ctx; - if (d == NULL) { - PRINT(KERN_ERR, ctx->ohci->host->id, - "Current iso context not set"); - return POLLERR; - } - - poll_wait(file, &d->waitq, pt); - - spin_lock_irqsave(&d->lock, flags); - for (i = 0; i < d->num_desc; i++) { - if (d->buffer_status[i] == VIDEO1394_BUFFER_READY) { - mask |= POLLIN | POLLRDNORM; - break; - } - } - spin_unlock_irqrestore(&d->lock, flags); - - return mask; -} - -static int video1394_open(struct inode *inode, struct file *file) -{ - int i = ieee1394_file_to_instance(file); - struct ti_ohci *ohci; - struct file_ctx *ctx; - - ohci = hpsb_get_hostinfo_bykey(&video1394_highlevel, i); - if (ohci == NULL) - return -EIO; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - PRINT(KERN_ERR, ohci->host->id, "Cannot malloc file_ctx"); - return -ENOMEM; - } - - ctx->ohci = ohci; - INIT_LIST_HEAD(&ctx->context_list); - ctx->current_ctx = NULL; - file->private_data = ctx; - - return nonseekable_open(inode, file); -} - -static int video1394_release(struct inode *inode, struct file *file) -{ - struct file_ctx *ctx = file->private_data; - struct ti_ohci *ohci = ctx->ohci; - struct list_head *lh, *next; - u64 mask; - - list_for_each_safe(lh, next, &ctx->context_list) { - struct dma_iso_ctx *d; - d = list_entry(lh, struct dma_iso_ctx, link); - mask = (u64) 1 << d->channel; - - if (!(ohci->ISO_channel_usage & mask)) - PRINT(KERN_ERR, ohci->host->id, "On release: Channel %d " - "is not being used", d->channel); - else - ohci->ISO_channel_usage &= ~mask; - DBGMSG(ohci->host->id, "On release: Iso %s context " - "%d stop listening on channel %d", - d->type == OHCI_ISO_RECEIVE ? "receive" : "transmit", - d->ctx, d->channel); - free_dma_iso_ctx(d); - } - - kfree(ctx); - file->private_data = NULL; - - return 0; -} - -#ifdef CONFIG_COMPAT -static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg); -#endif - -static struct cdev video1394_cdev; -static const struct file_operations video1394_fops= -{ - .owner = THIS_MODULE, - .unlocked_ioctl = video1394_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = video1394_compat_ioctl, -#endif - .poll = video1394_poll, - .mmap = video1394_mmap, - .open = video1394_open, - .release = video1394_release, - .llseek = no_llseek, -}; - -/*** HOTPLUG STUFF **********************************************************/ -/* - * Export information about protocols/devices supported by this driver. - */ -#ifdef MODULE -static const struct ieee1394_device_id video1394_id_table[] = { - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = CAMERA_SW_VERSION_ENTRY & 0xffffff - }, - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff - }, - { - .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, - .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, - .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff - }, - { } -}; - -MODULE_DEVICE_TABLE(ieee1394, video1394_id_table); -#endif /* MODULE */ - -static struct hpsb_protocol_driver video1394_driver = { - .name = VIDEO1394_DRIVER_NAME, -}; - - -static void video1394_add_host (struct hpsb_host *host) -{ - struct ti_ohci *ohci; - int minor; - - /* We only work with the OHCI-1394 driver */ - if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME)) - return; - - ohci = (struct ti_ohci *)host->hostdata; - - if (!hpsb_create_hostinfo(&video1394_highlevel, host, 0)) { - PRINT(KERN_ERR, ohci->host->id, "Cannot allocate hostinfo"); - return; - } - - hpsb_set_hostinfo(&video1394_highlevel, host, ohci); - hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id); - - minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id; - device_create(hpsb_protocol_class, NULL, MKDEV(IEEE1394_MAJOR, minor), - NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id); -} - - -static void video1394_remove_host (struct hpsb_host *host) -{ - struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host); - - if (ohci) - device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id)); - return; -} - - -static struct hpsb_highlevel video1394_highlevel = { - .name = VIDEO1394_DRIVER_NAME, - .add_host = video1394_add_host, - .remove_host = video1394_remove_host, -}; - -MODULE_AUTHOR("Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>"); -MODULE_DESCRIPTION("driver for digital video on OHCI board"); -MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME); -MODULE_LICENSE("GPL"); - -#ifdef CONFIG_COMPAT - -#define VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER \ - _IOW ('#', 0x12, struct video1394_wait32) -#define VIDEO1394_IOC32_LISTEN_WAIT_BUFFER \ - _IOWR('#', 0x13, struct video1394_wait32) -#define VIDEO1394_IOC32_TALK_WAIT_BUFFER \ - _IOW ('#', 0x17, struct video1394_wait32) -#define VIDEO1394_IOC32_LISTEN_POLL_BUFFER \ - _IOWR('#', 0x18, struct video1394_wait32) - -struct video1394_wait32 { - u32 channel; - u32 buffer; - struct compat_timeval filltime; -}; - -static int video1394_wr_wait32(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct video1394_wait32 __user *argp = (void __user *)arg; - struct video1394_wait32 wait32; - struct video1394_wait wait; - mm_segment_t old_fs; - int ret; - - if (copy_from_user(&wait32, argp, sizeof(wait32))) - return -EFAULT; - - wait.channel = wait32.channel; - wait.buffer = wait32.buffer; - wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec; - wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - if (cmd == VIDEO1394_IOC32_LISTEN_WAIT_BUFFER) - ret = video1394_ioctl(file, - VIDEO1394_IOC_LISTEN_WAIT_BUFFER, - (unsigned long) &wait); - else - ret = video1394_ioctl(file, - VIDEO1394_IOC_LISTEN_POLL_BUFFER, - (unsigned long) &wait); - set_fs(old_fs); - - if (!ret) { - wait32.channel = wait.channel; - wait32.buffer = wait.buffer; - wait32.filltime.tv_sec = (int)wait.filltime.tv_sec; - wait32.filltime.tv_usec = (int)wait.filltime.tv_usec; - - if (copy_to_user(argp, &wait32, sizeof(wait32))) - ret = -EFAULT; - } - - return ret; -} - -static int video1394_w_wait32(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct video1394_wait32 wait32; - struct video1394_wait wait; - mm_segment_t old_fs; - int ret; - - if (copy_from_user(&wait32, (void __user *)arg, sizeof(wait32))) - return -EFAULT; - - wait.channel = wait32.channel; - wait.buffer = wait32.buffer; - wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec; - wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - if (cmd == VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER) - ret = video1394_ioctl(file, - VIDEO1394_IOC_LISTEN_QUEUE_BUFFER, - (unsigned long) &wait); - else - ret = video1394_ioctl(file, - VIDEO1394_IOC_TALK_WAIT_BUFFER, - (unsigned long) &wait); - set_fs(old_fs); - - return ret; -} - -static int video1394_queue_buf32(struct file *file, unsigned int cmd, unsigned long arg) -{ - return -EFAULT; /* ??? was there before. */ - - return video1394_ioctl(file, - VIDEO1394_IOC_TALK_QUEUE_BUFFER, arg); -} - -static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg) -{ - switch (cmd) { - case VIDEO1394_IOC_LISTEN_CHANNEL: - case VIDEO1394_IOC_UNLISTEN_CHANNEL: - case VIDEO1394_IOC_TALK_CHANNEL: - case VIDEO1394_IOC_UNTALK_CHANNEL: - return video1394_ioctl(f, cmd, arg); - - case VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER: - return video1394_w_wait32(f, cmd, arg); - case VIDEO1394_IOC32_LISTEN_WAIT_BUFFER: - return video1394_wr_wait32(f, cmd, arg); - case VIDEO1394_IOC_TALK_QUEUE_BUFFER: - return video1394_queue_buf32(f, cmd, arg); - case VIDEO1394_IOC32_TALK_WAIT_BUFFER: - return video1394_w_wait32(f, cmd, arg); - case VIDEO1394_IOC32_LISTEN_POLL_BUFFER: - return video1394_wr_wait32(f, cmd, arg); - default: - return -ENOIOCTLCMD; - } -} - -#endif /* CONFIG_COMPAT */ - -static void __exit video1394_exit_module (void) -{ - hpsb_unregister_protocol(&video1394_driver); - hpsb_unregister_highlevel(&video1394_highlevel); - cdev_del(&video1394_cdev); - PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module"); -} - -static int __init video1394_init_module (void) -{ - int ret; - - hpsb_init_highlevel(&video1394_highlevel); - - cdev_init(&video1394_cdev, &video1394_fops); - video1394_cdev.owner = THIS_MODULE; - ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16); - if (ret) { - PRINT_G(KERN_ERR, "video1394: unable to get minor device block"); - return ret; - } - - hpsb_register_highlevel(&video1394_highlevel); - - ret = hpsb_register_protocol(&video1394_driver); - if (ret) { - PRINT_G(KERN_ERR, "video1394: failed to register protocol"); - hpsb_unregister_highlevel(&video1394_highlevel); - cdev_del(&video1394_cdev); - return ret; - } - - PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module"); - return 0; -} - - -module_init(video1394_init_module); -module_exit(video1394_exit_module); diff --git a/drivers/ieee1394/video1394.h b/drivers/ieee1394/video1394.h deleted file mode 100644 index 9a89d9c..0000000 --- a/drivers/ieee1394/video1394.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 _VIDEO_1394_H -#define _VIDEO_1394_H - -#include "ieee1394-ioctl.h" - -#define VIDEO1394_DRIVER_NAME "video1394" - -#define VIDEO1394_MAX_SIZE 0x4000000 - -enum { - VIDEO1394_BUFFER_FREE = 0, - VIDEO1394_BUFFER_QUEUED, - VIDEO1394_BUFFER_READY -}; - -#define VIDEO1394_SYNC_FRAMES 0x00000001 -#define VIDEO1394_INCLUDE_ISO_HEADERS 0x00000002 -#define VIDEO1394_VARIABLE_PACKET_SIZE 0x00000004 - -struct video1394_mmap { - int channel; /* -1 to find an open channel in LISTEN/TALK */ - unsigned int sync_tag; - unsigned int nb_buffers; - unsigned int buf_size; - unsigned int packet_size; /* For VARIABLE_PACKET_SIZE: - Maximum packet size */ - unsigned int fps; - unsigned int syt_offset; - unsigned int flags; -}; - -/* For TALK_QUEUE_BUFFER with VIDEO1394_VARIABLE_PACKET_SIZE use */ -struct video1394_queue_variable { - unsigned int channel; - unsigned int buffer; - unsigned int __user * packet_sizes; /* Buffer of size: - buf_size / packet_size */ -}; - -struct video1394_wait { - unsigned int channel; - unsigned int buffer; - struct timeval filltime; /* time of buffer full */ -}; - - -#endif |