summaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r--drivers/ieee1394/Config.in4
-rw-r--r--drivers/ieee1394/Makefile11
-rw-r--r--drivers/ieee1394/aic5800.c2
-rw-r--r--drivers/ieee1394/csr.c3
-rw-r--r--drivers/ieee1394/guid.c3
-rw-r--r--drivers/ieee1394/highlevel.c3
-rw-r--r--drivers/ieee1394/hosts.c3
-rw-r--r--drivers/ieee1394/ieee1394_core.c16
-rw-r--r--drivers/ieee1394/ieee1394_core.h10
-rw-r--r--drivers/ieee1394/ieee1394_syms.c3
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c79
-rw-r--r--drivers/ieee1394/ieee1394_types.h156
-rw-r--r--drivers/ieee1394/ohci1394.c1552
-rw-r--r--drivers/ieee1394/ohci1394.h133
-rw-r--r--drivers/ieee1394/pcilynx.c185
-rw-r--r--drivers/ieee1394/pcilynx.h31
-rw-r--r--drivers/ieee1394/raw1394.c57
-rw-r--r--drivers/ieee1394/raw1394.h28
-rw-r--r--drivers/ieee1394/video1394.c1266
-rw-r--r--drivers/ieee1394/video1394.h15
20 files changed, 2364 insertions, 1196 deletions
diff --git a/drivers/ieee1394/Config.in b/drivers/ieee1394/Config.in
index df0e3cfd2..bdb3002d2 100644
--- a/drivers/ieee1394/Config.in
+++ b/drivers/ieee1394/Config.in
@@ -4,18 +4,20 @@ if [ "$CONFIG_PCI" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
mainmenu_option next_comment
comment 'IEEE 1394 (FireWire) support'
- tristate 'IEEE 1394 (FireWire) support (EXPERIMENTAL)' CONFIG_IEEE1394 $CONFIG_PCI
+ dep_tristate 'IEEE 1394 (FireWire) support (EXPERIMENTAL)' CONFIG_IEEE1394 $CONFIG_PCI
if [ "$CONFIG_IEEE1394" != "n" ]; then
dep_tristate 'Texas Instruments PCILynx support' CONFIG_IEEE1394_PCILYNX $CONFIG_IEEE1394
if [ "$CONFIG_IEEE1394_PCILYNX" != "n" ]; then
bool ' Use PCILynx local RAM' CONFIG_IEEE1394_PCILYNX_LOCALRAM
+ bool ' Support for non-IEEE1394 local ports' CONFIG_IEEE1394_PCILYNX_PORTS
fi
dep_tristate 'Adaptec AIC-5800 (AHA-89xx) support' CONFIG_IEEE1394_AIC5800 $CONFIG_IEEE1394
dep_tristate 'OHCI (Open Host Controller Interface) support' CONFIG_IEEE1394_OHCI1394 $CONFIG_IEEE1394
+ dep_tristate 'Video1394 support' CONFIG_IEEE1394_VIDEO1394 $CONFIG_IEEE1394_OHCI1394
dep_tristate 'Raw IEEE1394 I/O support' CONFIG_IEEE1394_RAWIO $CONFIG_IEEE1394
diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
index c89374f45..cc6b40ee4 100644
--- a/drivers/ieee1394/Makefile
+++ b/drivers/ieee1394/Makefile
@@ -53,13 +53,20 @@ else
endif
ifeq ($(CONFIG_IEEE1394_OHCI1394),y)
-L_OBJS += ohci1394.o
+LX_OBJS += ohci1394.o
else
ifeq ($(CONFIG_IEEE1394_OHCI1394),m)
- M_OBJS += ohci1394.o
+ MX_OBJS += ohci1394.o
endif
endif
+ifeq ($(CONFIG_IEEE1394_VIDEO1394),y)
+L_OBJS += video1394.o
+else
+ ifeq ($(CONFIG_IEEE1394_VIDEO1394),m)
+ M_OBJS += video1394.o
+ endif
+endif
ifeq ($(CONFIG_IEEE1394_RAWIO),y)
L_OBJS += raw1394.o
diff --git a/drivers/ieee1394/aic5800.c b/drivers/ieee1394/aic5800.c
index 6cf3779d5..2748c21b6 100644
--- a/drivers/ieee1394/aic5800.c
+++ b/drivers/ieee1394/aic5800.c
@@ -646,7 +646,7 @@ static void aic_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
phyid = phyid & 0x3F;
handle_selfid(aic, host, phyid, isroot, rcv_bytes);
} else {
- hpsb_packet_received(host, aic->rcv_page, rcv_bytes);
+ hpsb_packet_received(host, aic->rcv_page, rcv_bytes, 0);
};
} else {
PRINT(KERN_ERR, aic->id,
diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c
index a884f2a1c..486ad1ad4 100644
--- a/drivers/ieee1394/csr.c
+++ b/drivers/ieee1394/csr.c
@@ -4,6 +4,9 @@
* CSR implementation, iso/bus manager implementation.
*
* 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/string.h>
diff --git a/drivers/ieee1394/guid.c b/drivers/ieee1394/guid.c
index 36ac332c5..1aa453292 100644
--- a/drivers/ieee1394/guid.c
+++ b/drivers/ieee1394/guid.c
@@ -4,6 +4,9 @@
* GUID collection and management
*
* Copyright (C) 2000 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/kernel.h>
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 3e20824aa..130a40527 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -2,6 +2,9 @@
* 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.
*/
#include <linux/config.h>
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index 9a9951204..8e0e80da1 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -5,6 +5,9 @@
*
* 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/config.h>
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index ffcfc7f52..e0641271b 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -5,6 +5,9 @@
* highlevel or lowlevel code
*
* Copyright (C) 1999, 2000 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/config.h>
@@ -534,7 +537,7 @@ struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
if (packet == NULL) break
void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data,
- size_t size)
+ size_t size, int write_acked)
{
struct hpsb_packet *packet;
int length, rcode, extcode;
@@ -548,7 +551,8 @@ void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data,
addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
rcode = highlevel_write(host, source, data+3, addr, 4);
- if (((data[0] >> 16) & NODE_MASK) != NODE_MASK) {
+ if (!write_acked
+ && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) {
/* not a broadcast write, reply */
PREP_REPLY_PACKET(0);
fill_async_write_resp(packet, rcode);
@@ -561,7 +565,8 @@ void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data,
rcode = highlevel_write(host, source, data+4, addr,
data[3]>>16);
- if (((data[0] >> 16) & NODE_MASK) != NODE_MASK) {
+ if (!write_acked
+ && ((data[0] >> 16) & NODE_MASK) != NODE_MASK) {
/* not a broadcast write, reply */
PREP_REPLY_PACKET(0);
fill_async_write_resp(packet, rcode);
@@ -644,7 +649,8 @@ void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data,
#undef PREP_REPLY_PACKET
-void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size)
+void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
+ int write_acked)
{
int tcode;
@@ -672,7 +678,7 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size)
case TCODE_READQ:
case TCODE_READB:
case TCODE_LOCK_REQUEST:
- handle_incoming_packet(host, tcode, data, size);
+ handle_incoming_packet(host, tcode, data, size, write_acked);
break;
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index 636aef40e..faeeca45d 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -52,8 +52,7 @@ struct hpsb_packet {
* overwritten to allow in-place byte swapping. Neither of these is
* CRCed (the sizes also don't include CRC), but contain space for at
* least one additional quadlet to allow in-place CRCing. The memory is
- * also guaranteed to have physical mapping (virt_to_bus() is meaningful
- * on these pointers).
+ * also guaranteed to be DMA mappable.
*/
quadlet_t *header;
quadlet_t *data;
@@ -145,7 +144,12 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
* 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 arg is ignored for any other
+ * packet type.
*/
-void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size);
+void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
+ int write_acked);
#endif /* _IEEE1394_CORE_H */
diff --git a/drivers/ieee1394/ieee1394_syms.c b/drivers/ieee1394/ieee1394_syms.c
index c1ebadd10..39a61a01b 100644
--- a/drivers/ieee1394/ieee1394_syms.c
+++ b/drivers/ieee1394/ieee1394_syms.c
@@ -4,6 +4,9 @@
* Exported symbols for module usage.
*
* 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/types.h>
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index c5c5cc4ad..179834ac7 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -4,6 +4,9 @@
* 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/sched.h>
@@ -152,38 +155,58 @@ void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
* Return value: The allocated transaction label or -1 if there was no free
* tlabel and @wait is false.
*/
+static int __get_tlabel(struct hpsb_host *host, nodeid_t nodeid)
+{
+ int tlabel;
+
+ if (host->tlabel_count) {
+ host->tlabel_count--;
+
+ if (host->tlabel_pool[0] != ~0) {
+ tlabel = ffz(host->tlabel_pool[0]);
+ host->tlabel_pool[0] |= 1 << tlabel;
+ } else {
+ tlabel = ffz(host->tlabel_pool[1]);
+ host->tlabel_pool[1] |= 1 << tlabel;
+ tlabel += 32;
+ }
+ return tlabel;
+ }
+ return -1;
+}
+
int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait)
{
unsigned long flags;
int tlabel;
-
- while (1) {
- spin_lock_irqsave(&host->tlabel_lock, flags);
-
- if (host->tlabel_count) {
- host->tlabel_count--;
-
- if (host->tlabel_pool[0] != ~0) {
- tlabel = ffz(host->tlabel_pool[0]);
- host->tlabel_pool[0] |= 1 << tlabel;
- } else {
- tlabel = ffz(host->tlabel_pool[1]);
- host->tlabel_pool[1] |= 1 << tlabel;
- tlabel += 32;
- }
-
- spin_unlock_irqrestore(&host->tlabel_lock, flags);
- return tlabel;
- }
-
- spin_unlock_irqrestore(&host->tlabel_lock, flags);
-
- if (wait) {
- sleep_on(&host->tlabel_wait);
- } else {
- return -1;
- }
- }
+ wait_queue_t wq;
+
+ spin_lock_irqsave(&host->tlabel_lock, flags);
+
+ tlabel = __get_tlabel(host, nodeid);
+ if (tlabel != -1 || !wait) {
+ spin_unlock_irqrestore(&host->tlabel_lock, flags);
+ return tlabel;
+ }
+
+ init_waitqueue_entry(&wq, current);
+ add_wait_queue(&host->tlabel_wait, &wq);
+
+ for (;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ tlabel = __get_tlabel(host, nodeid);
+ if (tlabel != -1) break;
+
+ spin_unlock_irqrestore(&host->tlabel_lock, flags);
+ schedule();
+ spin_lock_irqsave(&host->tlabel_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&host->tlabel_lock, flags);
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&host->tlabel_wait, &wq);
+
+ return tlabel;
}
/**
diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h
index 411b79b36..84be6aa05 100644
--- a/drivers/ieee1394/ieee1394_types.h
+++ b/drivers/ieee1394/ieee1394_types.h
@@ -11,15 +11,23 @@
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+#include <linux/wait.h>
#define DECLARE_WAITQUEUE(name, task) struct wait_queue name = { task, NULL }
typedef struct wait_queue *wait_queue_head_t;
+typedef struct wait_queue wait_queue_t;
inline static void init_waitqueue_head(wait_queue_head_t *wh)
{
*wh = NULL;
}
+inline static void init_waitqueue_entry(wait_queue_t *wq, struct task_struct *p)
+{
+ wq->task = p;
+ wq->next = NULL;
+}
+
static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
{
__list_add(new, head->prev, head);
@@ -30,6 +38,22 @@ static __inline__ void list_add_tail(struct list_head *new, struct list_head *he
#define set_current_state(state_value) \
do { current->state = (state_value); } while (0)
+
+#include <asm/page.h>
+/* Pure 2^n version of get_order */
+extern __inline__ int get_order(unsigned long size)
+{
+ int order;
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+}
+
+
#include <linux/pci.h>
inline static int pci_enable_device(struct pci_dev *dev)
{
@@ -39,8 +63,134 @@ inline static int pci_enable_device(struct pci_dev *dev)
return 0;
}
+#define PCI_DMA_BIDIRECTIONAL 0
+#define PCI_DMA_TODEVICE 1
+#define PCI_DMA_FROMDEVICE 2
+#define PCI_DMA_NONE 3
+#define PCI_ROM_RESOURCE 6
+#define pci_resource_start(dev, bar) ((bar) == PCI_ROM_RESOURCE \
+ ? (dev)->rom_address \
+ : (dev)->base_address[(bar)])
+#define BUG() *(int *)0 = 0
+
+#include <asm/io.h>
+typedef u32 dma_addr_t;
+
+extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask)
+{
+ return 1;
+}
+
+extern inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+ dma_addr_t *dma_handle)
+{
+ void *ret;
+ ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
+ if (ret) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_bus(ret);
+ }
+ return ret;
+}
+
+extern inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long)vaddr, get_order(size));
+}
+
+extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
+ size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE)
+ BUG();
+ return virt_to_bus(ptr);
+}
+
+extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+ size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE)
+ BUG();
+}
+
+struct scatterlist {};
+extern inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+ int nents, int direction)
+{
+ if (direction == PCI_DMA_NONE)
+ BUG();
+ return nents;
+}
+
+extern inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+ int nents, int direction)
+{
+ if (direction == PCI_DMA_NONE)
+ BUG();
+}
+
+extern inline void pci_dma_sync_single(struct pci_dev *hwdev,
+ dma_addr_t dma_handle,
+ size_t size, int direction)
+{
+ if (direction == PCI_DMA_NONE)
+ BUG();
+}
+
+extern inline void pci_dma_sync_sg(struct pci_dev *hwdev,
+ struct scatterlist *sg,
+ int nelems, int direction)
+{
+ if (direction == PCI_DMA_NONE)
+ BUG();
+}
+
+
+#ifndef _LINUX_DEVFS_FS_KERNEL_H
+typedef struct devfs_entry * devfs_handle_t;
+#define DEVFS_FL_NONE 0
+
+static inline devfs_handle_t devfs_register (devfs_handle_t dir,
+ const char *name,
+ unsigned int flags,
+ unsigned int major,
+ unsigned int minor,
+ umode_t mode,
+ void *ops, void *info)
+{
+ return NULL;
+}
+static inline void devfs_unregister (devfs_handle_t de)
+{
+ return;
+}
+static inline int devfs_register_chrdev (unsigned int major, const char *name,
+ struct file_operations *fops)
+{
+ return register_chrdev (major, name, fops);
+}
+static inline int devfs_unregister_chrdev (unsigned int major,const char *name)
+{
+ return unregister_chrdev (major, name);
+}
+#endif /* _LINUX_DEVFS_FS_KERNEL_H */
+
+
+#define V22_COMPAT_MOD_INC_USE_COUNT MOD_INC_USE_COUNT
+#define V22_COMPAT_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT
+#define OWNER_THIS_MODULE
+
+#else /* Linux version < 2.3 */
+
+#define V22_COMPAT_MOD_INC_USE_COUNT do {} while (0)
+#define V22_COMPAT_MOD_DEC_USE_COUNT do {} while (0)
+#define OWNER_THIS_MODULE owner: THIS_MODULE,
+
#endif /* Linux version < 2.3 */
+
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
#include <asm/spinlock.h>
#else
@@ -55,9 +205,9 @@ inline static int pci_enable_device(struct pci_dev *dev)
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
-typedef __u32 quadlet_t;
-typedef __u64 octlet_t;
-typedef __u16 nodeid_t;
+typedef u32 quadlet_t;
+typedef u64 octlet_t;
+typedef u16 nodeid_t;
#define BUS_MASK 0xffc0
#define NODE_MASK 0x003f
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index a0933c3e4..05e1063d7 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -25,10 +25,10 @@
* . Async Request Receive
* . Async Response Transmit
* . Iso Receive
+ * . DMA mmap for iso receive
*
* Things not implemented:
* . Iso Transmit
- * . DMA to user's space in iso receive mode
* . DMA error recovery
*
* Things to be fixed:
@@ -38,7 +38,6 @@
* . Self-id are sometimes not received properly
* if card is initialized with no other nodes
* on the bus
- * . SONY CXD3222 chip is not working properly
* . Apple PowerBook detected but not working yet
*/
@@ -56,7 +55,7 @@
* Albrecht Dress <ad@mpifr-bonn.mpg.de>
* . Apple PowerBook detection
* Daniel Kobras <daniel.kobras@student.uni-tuebingen.de>
- * . Reset the board properly before leaving
+ * . Reset the board properly before leaving + misc cleanups
*/
#include <linux/config.h>
@@ -130,6 +129,8 @@ int supported_chips[][2] = {
{ PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72870 },
{ PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_UPD72871 },
{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_FW },
+ { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_ALI_OHCI1394_M5251 },
+ { PCI_VENDOR_ID_LUCENT, PCI_DEVICE_ID_LUCENT_FW323 },
{ -1, -1 }
};
@@ -142,617 +143,6 @@ static int init_driver(void);
static void dma_trm_bh(void *data);
static void dma_rcv_bh(void *data);
static void dma_trm_reset(struct dma_trm_ctx *d);
-static void stop_context(struct ti_ohci *ohci, int reg, char *msg);
-
-#ifdef _VIDEO_1394_H
-
-/* Taken from bttv.c */
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-#define MDEBUG(x) do { } while(0) /* Debug memory management */
-
-/* [DaveM] I've recoded most of this so that:
- * 1) It's easier to tell what is happening
- * 2) It's more portable, especially for translating things
- * out of vmalloc mapped areas in the kernel.
- * 3) Less unnecessary translations happen.
- *
- * The code used to assume that the kernel vmalloc mappings
- * existed in the page tables of every process, this is simply
- * not guarenteed. We now use pgd_offset_k which is the
- * defined way to get at the kernel page tables.
- */
-
-/* Given PGD from the address space's page table, return the kernel
- * virtual mapping of the physical memory mapped at ADR.
- */
-static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
-{
- unsigned long ret = 0UL;
- pmd_t *pmd;
- pte_t *ptep, pte;
-
- if (!pgd_none(*pgd)) {
- pmd = pmd_offset(pgd, adr);
- if (!pmd_none(*pmd)) {
- ptep = pte_offset(pmd, adr);
- pte = *ptep;
- if(pte_present(pte))
- ret = (pte_page(pte)|(adr&(PAGE_SIZE-1)));
- }
- }
- MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
- return ret;
-}
-
-static inline unsigned long uvirt_to_bus(unsigned long adr)
-{
- unsigned long kva, ret;
-
- kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
- ret = virt_to_bus((void *)kva);
- MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
- return ret;
-}
-
-static inline unsigned long kvirt_to_bus(unsigned long adr)
-{
- unsigned long va, kva, ret;
-
- va = VMALLOC_VMADDR(adr);
- kva = uvirt_to_kva(pgd_offset_k(va), va);
- ret = virt_to_bus((void *)kva);
- MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
- return ret;
-}
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr)
-{
- unsigned long va, kva, ret;
-
- va = VMALLOC_VMADDR(adr);
- kva = uvirt_to_kva(pgd_offset_k(va), va);
- ret = __pa(kva);
- MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
- return ret;
-}
-
-static void * rvmalloc(unsigned long size)
-{
- void * mem;
- unsigned long adr, page;
-
- mem=vmalloc(size);
- if (mem)
- {
- memset(mem, 0, size); /* Clear the ram out, no junk to the user */
- adr=(unsigned long) mem;
- while (size > 0)
- {
- page = kvirt_to_pa(adr);
- mem_map_reserve(MAP_NR(__va(page)));
- adr+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
- }
- return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
- unsigned long adr, page;
-
- if (mem)
- {
- adr=(unsigned long) mem;
- while (size > 0)
- {
- page = kvirt_to_pa(adr);
- mem_map_unreserve(MAP_NR(__va(page)));
- adr+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
- vfree(mem);
- }
-}
-
-static int free_dma_fbuf_ctx(struct dma_fbuf_ctx **d)
-{
- int i;
- struct ti_ohci *ohci;
-
- if ((*d)==NULL) return -1;
-
- ohci = (struct ti_ohci *)(*d)->ohci;
-
- DBGMSG(ohci->id, "Freeing dma_fbuf_ctx %d", (*d)->ctx);
-
- stop_context(ohci, (*d)->ctrlClear, NULL);
-
- if ((*d)->buf) rvfree((void *)(*d)->buf,
- (*d)->num_desc * (*d)->buf_size);
-
- if ((*d)->prg) {
- for (i=0;i<(*d)->num_desc;i++)
- if ((*d)->prg[i]) kfree((*d)->prg[i]);
- kfree((*d)->prg);
- }
-
- if ((*d)->buffer_status)
- kfree((*d)->buffer_status);
-
- kfree(*d);
- *d = NULL;
-
- return 0;
-}
-
-static struct dma_fbuf_ctx *
-alloc_dma_fbuf_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
- int buf_size, int channel)
-{
- struct dma_fbuf_ctx *d=NULL;
- int i;
-
- d = (struct dma_fbuf_ctx *)kmalloc(sizeof(struct dma_fbuf_ctx),
- GFP_KERNEL);
-
- if (d==NULL) {
- PRINT(KERN_ERR, ohci->id, "failed to allocate dma_fbuf_ctx");
- return NULL;
- }
-
- d->ohci = (void *)ohci;
- d->ctx = ctx;
- d->channel = channel;
- d->num_desc = num_desc;
- d->frame_size = buf_size;
- if (buf_size%PAGE_SIZE)
- d->buf_size = buf_size + PAGE_SIZE - (buf_size%PAGE_SIZE);
- else
- d->buf_size = buf_size;
- d->ctrlSet = OHCI1394_IrRcvContextControlSet+32*d->ctx;
- d->ctrlClear = OHCI1394_IrRcvContextControlClear+32*d->ctx;
- d->cmdPtr = OHCI1394_IrRcvCommandPtr+32*d->ctx;
- d->ctxMatch = OHCI1394_IrRcvContextMatch+32*d->ctx;
- d->nb_cmd = d->buf_size / PAGE_SIZE + 1;
- d->last_buffer = 0;
- d->buf = NULL;
- d->prg = NULL;
- init_waitqueue_head(&d->waitq);
-
- d->buf = rvmalloc(d->num_desc * d->buf_size);
-
- if (d->buf == NULL) {
- PRINT(KERN_ERR, ohci->id, "failed to allocate dma fbuffer");
- free_dma_fbuf_ctx(&d);
- return NULL;
- }
- memset(d->buf, 0, d->num_desc * d->buf_size);
-
- d->prg = kmalloc(d->num_desc * sizeof(struct dma_cmd *),
- GFP_KERNEL);
-
- if (d->prg == NULL) {
- PRINT(KERN_ERR, ohci->id, "failed to allocate dma fbuf prg");
- free_dma_fbuf_ctx(&d);
- return NULL;
- }
- memset(d->prg, 0, d->num_desc * sizeof(struct dma_cmd *));
-
- for (i=0;i<d->num_desc;i++) {
- d->prg[i] = kmalloc(d->nb_cmd * sizeof(struct dma_cmd),
- GFP_KERNEL);
- if (d->prg[i] == NULL) {
- PRINT(KERN_ERR, ohci->id,
- "failed to allocate dma fbuf prg");
- free_dma_fbuf_ctx(&d);
- return NULL;
- }
- }
-
- d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int),
- GFP_KERNEL);
-
- if (d->buffer_status == NULL) {
- PRINT(KERN_ERR, ohci->id, "failed to allocate dma fbuf prg");
- free_dma_fbuf_ctx(&d);
- return NULL;
- }
- memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
-
- PRINT(KERN_INFO, ohci->id, "Iso DMA to User's Space: %d buffers "
- "of size %d allocated for a frame size %d, each with %d prgs",
- d->num_desc, d->buf_size, d->frame_size, d->nb_cmd);
-
- return d;
-}
-
-static void initialize_dma_fbuf_prg(struct dma_cmd *prg, int n,
- int frame_size, unsigned long buf)
-{
- int i;
- int leftsize = (frame_size%PAGE_SIZE) ?
- frame_size%PAGE_SIZE : PAGE_SIZE;
-
- /* the first descriptor will sync and read only 4 bytes */
- prg[0].control = (0x280F << 16) | 4;
- prg[0].address = kvirt_to_bus(buf);
- prg[0].branchAddress = (virt_to_bus(&(prg[1].control))
- & 0xfffffff0) | 0x1;
- prg[0].status = 0;
-
- /* the second descriptor will read PAGE_SIZE-4 bytes */
- prg[1].control = (0x280C << 16) | (PAGE_SIZE-4);
- prg[1].address = kvirt_to_bus(buf+4);
- prg[1].branchAddress = (virt_to_bus(&(prg[2].control))
- & 0xfffffff0) | 0x1;
- prg[1].status = 0;
-
- for (i=2;i<n-1;i++) {
- prg[i].control = (0x280C << 16) | PAGE_SIZE;
- prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
-
- prg[i].branchAddress =
- (virt_to_bus(&(prg[i+1].control))
- & 0xfffffff0) | 0x1;
-
- prg[i].status = 0;
- }
-
- /* the last descriptor will generate an interrupt */
- prg[i].control = (0x283C << 16) | leftsize;
- prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
- prg[i].status = 0;
-}
-
-static void initialize_dma_fbuf_ctx(struct dma_fbuf_ctx *d, int tag)
-{
- struct ti_ohci *ohci = (struct ti_ohci *)d->ohci;
- int i;
-
- stop_context(ohci, d->ctrlClear, NULL);
-
- for (i=0;i<d->num_desc;i++) {
- initialize_dma_fbuf_prg(d->prg[i], d->nb_cmd, d->frame_size,
- (unsigned long)d->buf+i*d->buf_size);
- }
-
- /* Set bufferFill, no header */
- reg_write(ohci, d->ctrlSet, 0x80000000);
-
- /* 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 */
-int fbuf_ctx_listening(struct ti_ohci *ohci, int channel)
-{
- int i;
- for (i=0;i<ohci->nb_iso_ctx-1;i++)
- if (ohci->fbuf_context[i]) {
- if (ohci->fbuf_context[i]->channel==channel)
- return i;
- }
-
- PRINT(KERN_ERR, ohci->id,
- "no iso context is listening to channel %d",
- channel);
- return -1;
-}
-
-static int ohci_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct ti_ohci *ohci=&cards[MINOR(inode->i_rdev)];
-
- switch(cmd)
- {
- case VIDEO1394_LISTEN_CHANNEL:
- {
- struct video1394_mmap v;
- int i;
-
- if(copy_from_user(&v, (void *)arg, sizeof(v)))
- return -EFAULT;
- if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) {
- PRINT(KERN_ERR, ohci->id,
- "iso channel %d out of bound", v.channel);
- return -EFAULT;
- }
- if (test_and_set_bit(v.channel, &ohci->IR_channel_usage)) {
- PRINT(KERN_ERR, ohci->id,
- "channel %d is already taken", v.channel);
- return -EFAULT;
- }
-
- /* find a free iso context */
- for (i=0;i<ohci->nb_iso_ctx-1;i++)
- if (ohci->fbuf_context[i]==NULL) break;
-
- if (i==(ohci->nb_iso_ctx-1)) {
- PRINT(KERN_ERR, ohci->id, "no iso context available");
- return -EFAULT;
- }
-
- if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) {
- PRINT(KERN_ERR, ohci->id,
- "%d buffers of size %d bytes is too big",
- v.nb_buffers, v.buf_size);
- return -EFAULT;
- }
-
- ohci->fbuf_context[i] =
- alloc_dma_fbuf_ctx(ohci, i+1, v.nb_buffers,
- v.buf_size, v.channel);
-
- if (ohci->fbuf_context[i] == NULL) {
- PRINT(KERN_ERR, ohci->id,
- "Couldn't allocate fbuf context");
- return -EFAULT;
- }
- initialize_dma_fbuf_ctx(ohci->fbuf_context[i], v.sync_tag);
-
- ohci->current_fbuf_ctx = ohci->fbuf_context[i];
-
- v.buf_size = ohci->fbuf_context[i]->buf_size;
-
- PRINT(KERN_INFO, ohci->id,
- "iso context %d listen on channel %d", i+1,
- v.channel);
-
- if(copy_to_user((void *)arg, &v, sizeof(v)))
- return -EFAULT;
-
- return 0;
- }
- case VIDEO1394_UNLISTEN_CHANNEL:
- {
- int channel;
- int i;
-
- if(copy_from_user(&channel, (void *)arg, sizeof(int)))
- return -EFAULT;
-
- if (!test_and_clear_bit(channel, &ohci->IR_channel_usage)) {
- PRINT(KERN_ERR, ohci->id,
- "channel %d is not being used", channel);
- return -EFAULT;
- }
-
- i = fbuf_ctx_listening(ohci, channel);
- if (i<0) return -EFAULT;
-
- free_dma_fbuf_ctx(&ohci->fbuf_context[i]);
-
- PRINT(KERN_INFO, ohci->id,
- "iso context %d stop listening on channel %d",
- i+1, channel);
-
- return 0;
- }
- case VIDEO1394_QUEUE_BUFFER:
- {
- struct video1394_wait v;
- struct dma_fbuf_ctx *d;
- int i;
-
- if(copy_from_user(&v, (void *)arg, sizeof(v)))
- return -EFAULT;
-
- i = fbuf_ctx_listening(ohci, v.channel);
- if (i<0) return -EFAULT;
- d = ohci->fbuf_context[i];
-
- if ((v.buffer<0) || (v.buffer>d->num_desc)) {
- PRINT(KERN_ERR, ohci->id,
- "buffer %d out of range",v.buffer);
- return -EFAULT;
- }
-
- if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
- PRINT(KERN_ERR, ohci->id,
- "buffer %d is already used",v.buffer);
- return -EFAULT;
- }
-
- d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
-
- d->prg[d->last_buffer][d->nb_cmd-1].branchAddress =
- (virt_to_bus(&(d->prg[v.buffer][0].control))
- & 0xfffffff0) | 0x1;
-
- d->last_buffer = v.buffer;
-
- if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
- {
- DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx);
-
- /* Tell the controller where the first program is */
- reg_write(ohci, d->cmdPtr,
- virt_to_bus(&(d->prg[v.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)) {
- PRINT(KERN_INFO, ohci->id,
- "Waking up iso dma ctx=%d", d->ctx);
- reg_write(ohci, d->ctrlSet, 0x1000);
- }
- }
- return 0;
-
- }
- case VIDEO1394_WAIT_BUFFER:
- {
- struct video1394_wait v;
- struct dma_fbuf_ctx *d;
- int i;
-
- if(copy_from_user(&v, (void *)arg, sizeof(v)))
- return -EFAULT;
-
- i = fbuf_ctx_listening(ohci, v.channel);
- if (i<0) return -EFAULT;
- d = ohci->fbuf_context[i];
-
- if ((v.buffer<0) || (v.buffer>d->num_desc)) {
- PRINT(KERN_ERR, ohci->id,
- "buffer %d out of range",v.buffer);
- return -EFAULT;
- }
-
- switch(d->buffer_status[v.buffer]) {
- case VIDEO1394_BUFFER_READY:
- d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
- return 0;
- case VIDEO1394_BUFFER_QUEUED:
- while(d->buffer_status[v.buffer]!=
- VIDEO1394_BUFFER_READY) {
- interruptible_sleep_on(&d->waitq);
- if(signal_pending(current)) return -EINTR;
- }
- d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
- return 0;
- default:
- PRINT(KERN_ERR, ohci->id,
- "buffer %d is not queued",v.buffer);
- return -EFAULT;
- }
- }
- default:
- return -EINVAL;
- }
-}
-
-/*
- * This maps the vmalloced and reserved fbuffer to user space.
- *
- * FIXME:
- * - PAGE_READONLY should suffice!?
- * - remap_page_range is kind of inefficient for page by page remapping.
- * But e.g. pte_alloc() does not work in modules ... :-(
- */
-
-static int do_fbuf_mmap(struct ti_ohci *ohci, struct dma_fbuf_ctx *d,
- const char *adr, unsigned long size)
-{
- unsigned long start=(unsigned long) adr;
- unsigned long page,pos;
-
- if (size>d->num_desc * d->buf_size) {
- PRINT(KERN_ERR, ohci->id,
- "fbuf context %d buf size is different from mmap size",
- d->ctx);
- return -EINVAL;
- }
- if (!d->buf) {
- PRINT(KERN_ERR, ohci->id,
- "fbuf context %d is not allocated", d->ctx);
- return -EINVAL;
- }
-
- pos=(unsigned long) d->buf;
- while (size > 0) {
- page = kvirt_to_pa(pos);
- if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
- return -EAGAIN;
- start+=PAGE_SIZE;
- pos+=PAGE_SIZE;
- size-=PAGE_SIZE;
- }
- return 0;
-}
-
-int ohci_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct ti_ohci *ohci=&cards[MINOR(file->f_dentry->d_inode->i_rdev)];
- PRINT(KERN_INFO, ohci->id, "mmap");
- if (ohci->current_fbuf_ctx == NULL) {
- PRINT(KERN_ERR, ohci->id, "current fbuf context not set");
- return -EINVAL;
- }
-
- return do_fbuf_mmap(ohci, ohci->current_fbuf_ctx,
- (char *)vma->vm_start,
- (unsigned long)(vma->vm_end-vma->vm_start));
- return 0;
-}
-
-static int ohci_open(struct inode *inode, struct file *file)
-{
- struct ti_ohci *ohci=&cards[MINOR(inode->i_rdev)];
- PRINT(KERN_INFO, ohci->id, "open");
- return 0;
-}
-
-static int ohci_release(struct inode *inode, struct file *file)
-{
- struct ti_ohci *ohci=&cards[MINOR(inode->i_rdev)];
- int i;
-
- PRINT(KERN_INFO, ohci->id, "release");
- for (i=0;i<ohci->nb_iso_ctx-1;i++)
- if (ohci->fbuf_context[i]) {
- if (!test_and_clear_bit(ohci->fbuf_context[i]->channel,
- &ohci->IR_channel_usage)) {
- PRINT(KERN_ERR, ohci->id,
- "channel %d is not being used",
- ohci->fbuf_context[i]->channel);
- }
- PRINT(KERN_INFO, ohci->id,
- "iso context %d stop listening on channel %d",
- i+1, ohci->fbuf_context[i]->channel);
- free_dma_fbuf_ctx(&ohci->fbuf_context[i]);
- }
- return 0;
-}
-
-static struct file_operations ohci_fops=
-{
- owner: THIS_MODULE,
- ioctl: ohci_ioctl,
- mmap: ohci_mmap,
- open: ohci_open,
- release: ohci_release
-};
-
-int wakeup_dma_fbuf_ctx(struct ti_ohci *ohci, struct dma_fbuf_ctx *d)
-{
- int i;
-
- if (d==NULL) {
- PRINT(KERN_ERR, ohci->id, "Iso receive event received but "
- "context not allocated");
- return -EFAULT;
- }
-
- for (i=0;i<d->num_desc;i++) {
- if (d->prg[i][d->nb_cmd-1].status) {
- d->prg[i][d->nb_cmd-1].status=0;
- d->buffer_status[i] = VIDEO1394_BUFFER_READY;
- }
- }
- if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq);
- return 0;
-}
-
-#endif
-
-
/***********************************
* IEEE-1394 functionality section *
@@ -827,14 +217,14 @@ static int set_phy_reg(struct ti_ohci *ohci, int addr, unsigned char data) {
inline static int handle_selfid(struct ti_ohci *ohci, struct hpsb_host *host,
int phyid, int isroot)
{
- quadlet_t *q = ohci->self_id_buffer;
+ quadlet_t *q = ohci->selfid_buf_cpu;
quadlet_t self_id_count=reg_read(ohci, OHCI1394_SelfIDCount);
size_t size;
quadlet_t lsid;
/* Self-id handling seems much easier than for the aic5800 chip.
All the self-id packets, including this device own self-id,
- should be correctly arranged in the self_id_buffer at this
+ should be correctly arranged in the selfid buffer at this
stage */
/* Check status of self-id reception */
@@ -952,55 +342,36 @@ static int run_context(struct ti_ohci *ohci, int reg, char *msg)
return 0;
}
-static void 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, ohci->id,
- "runaway loop while stopping context...");
- break;
- }
- }
- if (msg) PRINT(KERN_ERR, ohci->id, "%s\n dma prg stopped\n", msg);
-}
-
/* Generate the dma receive prgs and start the context */
static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d)
{
struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
int i;
- stop_context(ohci, d->ctrlClear, NULL);
+ ohci1394_stop_context(ohci, d->ctrlClear, NULL);
for (i=0; i<d->num_desc; i++) {
/* end of descriptor list? */
if ((i+1) < d->num_desc) {
- d->prg[i]->control = (0x283C << 16) | d->buf_size;
- d->prg[i]->branchAddress =
- (virt_to_bus(d->prg[i+1]) & 0xfffffff0) | 0x1;
+ d->prg_cpu[i]->control = (0x283C << 16) | d->buf_size;
+ d->prg_cpu[i]->branchAddress =
+ (d->prg_bus[i+1] & 0xfffffff0) | 0x1;
} else {
- d->prg[i]->control = (0x283C << 16) | d->buf_size;
- d->prg[i]->branchAddress =
- (virt_to_bus(d->prg[0]) & 0xfffffff0);
+ d->prg_cpu[i]->control = (0x283C << 16) | d->buf_size;
+ d->prg_cpu[i]->branchAddress =
+ d->prg_bus[0] & 0xfffffff0;
}
- d->prg[i]->address = virt_to_bus(d->buf[i]);
- d->prg[i]->status = d->buf_size;
+ d->prg_cpu[i]->address = d->buf_bus[i];
+ d->prg_cpu[i]->status = d->buf_size;
}
d->buf_ind = 0;
d->buf_offset = 0;
/* Tell the controller where the first AR program is */
- reg_write(ohci, d->cmdPtr, virt_to_bus(d->prg[0]) | 0x1);
+ reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1);
/* Run AR context */
reg_write(ohci, d->ctrlSet, 0x00008000);
@@ -1014,26 +385,30 @@ static void initialize_dma_trm_ctx(struct dma_trm_ctx *d)
struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
/* Stop the context */
- stop_context(ohci, d->ctrlClear, NULL);
+ ohci1394_stop_context(ohci, d->ctrlClear, NULL);
d->prg_ind = 0;
d->sent_ind = 0;
d->free_prgs = d->num_desc;
d->branchAddrPtr = NULL;
- d->first = NULL;
- d->last = NULL;
+ d->fifo_first = NULL;
+ d->fifo_last = NULL;
+ d->pending_first = NULL;
+ d->pending_last = NULL;
PRINT(KERN_INFO, ohci->id, "AT dma ctx=%d initialized", d->ctx);
}
/* Count the number of available iso contexts */
-static int get_nb_iso_ctx(struct ti_ohci *ohci)
+static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg)
{
int i,ctx=0;
u32 tmp;
- reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0xffffffff);
- tmp = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
+ reg_write(ohci, reg, 0xffffffff);
+ tmp = reg_read(ohci, reg);
+
+ DBGMSG(ohci->id,"Iso contexts reg: %08x implemented: %08x", reg, tmp);
/* Count the number of contexts */
for(i=0; i<32; i++) {
@@ -1062,7 +437,7 @@ static int ohci_initialize(struct hpsb_host *host)
if ((retval=ohci_soft_reset(ohci))<0) return retval;
/*
- *Delay aftger soft reset to make sure everything has settled
+ * Delay after soft reset to make sure everything has settled
* down (sanity)
*/
mdelay(100);
@@ -1089,31 +464,33 @@ static int ohci_initialize(struct hpsb_host *host)
reg_write(ohci, OHCI1394_LinkControlSet, 0x00300000);
/* Clear interrupt registers */
- reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
/* Set up self-id dma buffer */
- reg_write(ohci, OHCI1394_SelfIDBuffer,
- virt_to_bus(ohci->self_id_buffer));
+ reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);
/* enable self-id dma */
reg_write(ohci, OHCI1394_LinkControlSet, 0x00000200);
/* Set the configuration ROM mapping register */
- reg_write(ohci, OHCI1394_ConfigROMmap,
- virt_to_bus(ohci->csr_config_rom));
-
- /* Write the config ROM header */
- reg_write(ohci, OHCI1394_ConfigROMhdr,
- cpu_to_be32(ohci->csr_config_rom[0]));
+ reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus);
/* Set bus options */
reg_write(ohci, OHCI1394_BusOptions,
- cpu_to_be32(ohci->csr_config_rom[2]));
-
+ cpu_to_be32(ohci->csr_config_rom_cpu[2]));
+
+#if 0
/* Write the GUID into the csr config rom */
- ohci->csr_config_rom[3] = be32_to_cpu(reg_read(ohci, OHCI1394_GUIDHi));
- ohci->csr_config_rom[4] = be32_to_cpu(reg_read(ohci, OHCI1394_GUIDLo));
+ ohci->csr_config_rom_cpu[3] =
+ be32_to_cpu(reg_read(ohci, OHCI1394_GUIDHi));
+ ohci->csr_config_rom_cpu[4] =
+ be32_to_cpu(reg_read(ohci, OHCI1394_GUIDLo));
+#endif
+
+ /* Write the config ROM header */
+ reg_write(ohci, OHCI1394_ConfigROMhdr,
+ cpu_to_be32(ohci->csr_config_rom_cpu[0]));
ohci->max_packet_size =
1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
@@ -1124,39 +501,56 @@ static int ohci_initialize(struct hpsb_host *host)
reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
/* Initialize IR dma */
- ohci->nb_iso_ctx = get_nb_iso_ctx(ohci);
- PRINT(KERN_INFO, ohci->id, "%d iso contexts available",
- ohci->nb_iso_ctx);
- for (i=0;i<ohci->nb_iso_ctx;i++) {
- reg_write(ohci, OHCI1394_IrRcvContextControlClear+32*i,
+ ohci->nb_iso_rcv_ctx =
+ get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet);
+ PRINT(KERN_INFO, ohci->id, "%d iso receive contexts available",
+ ohci->nb_iso_rcv_ctx);
+ for (i=0;i<ohci->nb_iso_rcv_ctx;i++) {
+ reg_write(ohci, OHCI1394_IsoRcvContextControlClear+32*i,
0xffffffff);
- reg_write(ohci, OHCI1394_IrRcvContextMatch+32*i, 0);
- reg_write(ohci, OHCI1394_IrRcvCommandPtr+32*i, 0);
- }
-#ifdef _VIDEO_1394_H
- ohci->fbuf_context = (struct dma_fbuf_ctx **)
- kmalloc((ohci->nb_iso_ctx-1)*sizeof(struct dma_fbuf_ctx *),
- GFP_KERNEL);
- if (ohci->fbuf_context)
- memset(ohci->fbuf_context, 0,
- (ohci->nb_iso_ctx-1)*sizeof(struct dma_fbuf_ctx *));
- else {
- PRINT(KERN_ERR, ohci->id, "Cannot allocate fbuf_context");
- return -1;
+ reg_write(ohci, OHCI1394_IsoRcvContextMatch+32*i, 0);
+ reg_write(ohci, OHCI1394_IsoRcvCommandPtr+32*i, 0);
}
-#endif
+
/* Set bufferFill, isochHeader, multichannel for IR context */
- reg_write(ohci, OHCI1394_IrRcvContextControlSet, 0xd0000000);
+ reg_write(ohci, OHCI1394_IsoRcvContextControlSet, 0xd0000000);
/* Set the context match register to match on all tags */
- reg_write(ohci, OHCI1394_IrRcvContextMatch, 0xf0000000);
+ reg_write(ohci, OHCI1394_IsoRcvContextMatch, 0xf0000000);
+
+ /* Clear the interrupt mask */
+ reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
+
+ /* Initialize IT dma */
+ ohci->nb_iso_xmit_ctx =
+ get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet);
+ PRINT(KERN_INFO, ohci->id, "%d iso transmit contexts available",
+ ohci->nb_iso_xmit_ctx);
+ for (i=0;i<ohci->nb_iso_xmit_ctx;i++) {
+ reg_write(ohci, OHCI1394_IsoXmitContextControlClear+32*i,
+ 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoXmitCommandPtr+32*i, 0);
+ }
+
+ /* Clear the interrupt mask */
+ reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
+ reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
/* Clear the multi channel mask high and low registers */
reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff);
reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
- /* Clear the interrupt mask */
- reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
+ /* Initialize AR dma */
+ initialize_dma_rcv_ctx(ohci->ar_req_context);
+ initialize_dma_rcv_ctx(ohci->ar_resp_context);
+
+ /* Initialize AT dma */
+ initialize_dma_trm_ctx(ohci->at_req_context);
+ initialize_dma_trm_ctx(ohci->at_resp_context);
+
+ /* Initialize IR dma */
+ initialize_dma_rcv_ctx(ohci->ir_context);
/* Set up isoRecvIntMask to generate interrupts for context 0
(thanks to Michael Greger for seeing that I forgot this) */
@@ -1193,23 +587,13 @@ static int ohci_initialize(struct hpsb_host *host)
OHCI1394_ARRQ |
OHCI1394_respTxComplete |
OHCI1394_reqTxComplete |
- OHCI1394_isochRx
+ OHCI1394_isochRx |
+ OHCI1394_isochTx
);
/* Enable link */
reg_write(ohci, OHCI1394_HCControlSet, 0x00020000);
- /* Initialize AR dma */
- initialize_dma_rcv_ctx(ohci->ar_req_context);
- initialize_dma_rcv_ctx(ohci->ar_resp_context);
-
- /* Initialize AT dma */
- initialize_dma_trm_ctx(ohci->at_req_context);
- initialize_dma_trm_ctx(ohci->at_resp_context);
-
- /* Initialize IR dma */
- initialize_dma_rcv_ctx(ohci->ir_context);
-
return 1;
}
@@ -1223,74 +607,132 @@ static void ohci_remove(struct hpsb_host *host)
}
}
-/* Insert a packet in the AT DMA fifo and generate the DMA prg */
+/*
+ * Insert a packet in the AT 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;
- d->prg[idx].begin.address = 0;
- d->prg[idx].begin.branchAddress = 0;
+ d->prg_cpu[idx]->begin.address = 0;
+ d->prg_cpu[idx]->begin.branchAddress = 0;
if (d->ctx==1) {
/*
* 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[idx].begin.status =
+ d->prg_cpu[idx]->begin.status =
(((((cycleTimer>>25)&0x7)+1)&0x7)<<13) |
((cycleTimer&0x01fff000)>>12);
DBGMSG(ohci->id, "cycleTimer: %08x timeStamp: %08x",
- cycleTimer, d->prg[idx].begin.status);
+ cycleTimer, d->prg_cpu[idx]->begin.status);
}
else
- d->prg[idx].begin.status = 0;
+ d->prg_cpu[idx]->begin.status = 0;
- d->prg[idx].data[0] = packet->speed_code<<16 |
+ d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
(packet->header[0] & 0xFFFF);
- d->prg[idx].data[1] = (packet->header[1] & 0xFFFF) |
+ d->prg_cpu[idx]->data[1] = (packet->header[1] & 0xFFFF) |
(packet->header[0] & 0xFFFF0000);
- d->prg[idx].data[2] = packet->header[2];
- d->prg[idx].data[3] = packet->header[3];
+ d->prg_cpu[idx]->data[2] = packet->header[2];
+ d->prg_cpu[idx]->data[3] = packet->header[3];
if (packet->data_size) { /* block transmit */
- d->prg[idx].begin.control = OUTPUT_MORE_IMMEDIATE | 0x10;
- d->prg[idx].end.control = OUTPUT_LAST | packet->data_size;
- d->prg[idx].end.address = virt_to_bus(packet->data);
- d->prg[idx].end.branchAddress = 0;
- d->prg[idx].end.status = 0x4000;
+ d->prg_cpu[idx]->begin.control = OUTPUT_MORE_IMMEDIATE | 0x10;
+ d->prg_cpu[idx]->end.control = OUTPUT_LAST | packet->data_size;
+ /*
+ * FIXME: check that the packet data buffer
+ * do not cross a page boundary
+ */
+ d->prg_cpu[idx]->end.address =
+ 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) = virt_to_bus(d->prg+idx) | 0x3;
- d->branchAddrPtr = &(d->prg[idx].end.branchAddress);
+ *(d->branchAddrPtr) = d->prg_bus[idx] | 0x3;
+ d->branchAddrPtr = &(d->prg_cpu[idx]->end.branchAddress);
}
else { /* quadlet transmit */
- d->prg[idx].begin.control =
+ d->prg_cpu[idx]->begin.control =
OUTPUT_LAST_IMMEDIATE | packet->header_size;
if (d->branchAddrPtr)
- *(d->branchAddrPtr) = virt_to_bus(d->prg+idx) | 0x2;
- d->branchAddrPtr = &(d->prg[idx].begin.branchAddress);
+ *(d->branchAddrPtr) = d->prg_bus[idx] | 0x2;
+ d->branchAddrPtr = &(d->prg_cpu[idx]->begin.branchAddress);
}
d->free_prgs--;
/* queue the packet in the appropriate context queue */
- if (d->last) {
- d->last->xnext = packet;
- d->last = packet;
+ if (d->fifo_last) {
+ d->fifo_last->xnext = packet;
+ d->fifo_last = packet;
+ }
+ else {
+ d->fifo_first = packet;
+ d->fifo_last = packet;
+ }
+ d->prg_ind = (d->prg_ind+1)%d->num_desc;
+}
+
+/*
+ * This function fills the AT FIFO with the (eventual) pending packets
+ * and runs or wake up the AT DMA prg if necessary.
+ * The function MUST be called with the d->lock held.
+ */
+static int dma_trm_flush(struct ti_ohci *ohci, struct dma_trm_ctx *d)
+{
+ int idx,z;
+
+ if (d->pending_first == NULL || d->free_prgs == 0)
+ return 0;
+
+ idx = d->prg_ind;
+ z = (d->pending_first->data_size) ? 3 : 2;
+
+ /* insert the packets into the at dma fifo */
+ while (d->free_prgs>0 && d->pending_first) {
+ insert_packet(ohci, d, d->pending_first);
+ d->pending_first = d->pending_first->xnext;
+ }
+ if (d->pending_first == NULL)
+ d->pending_last = NULL;
+ else
+ PRINT(KERN_INFO, ohci->id,
+ "AT DMA FIFO ctx=%d full... waiting",d->ctx);
+
+ /* 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)) {
+ DBGMSG(ohci->id,"Starting AT DMA ctx=%d",d->ctx);
+ reg_write(ohci, d->cmdPtr, d->prg_bus[idx]|z);
+ run_context(ohci, d->ctrlSet, NULL);
}
else {
- d->first = packet;
- d->last = packet;
+ DBGMSG(ohci->id,"Waking AT DMA ctx=%d",d->ctx);
+ /* wake up the dma context if necessary */
+ if (!(reg_read(ohci, d->ctrlSet) & 0x400))
+ reg_write(ohci, d->ctrlSet, 0x1000);
}
+ return 1;
}
+/*
+ * Transmission of an async 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 char tcode;
- int timeout=50;
+ unsigned long flags;
if (packet->data_size >= ohci->max_packet_size) {
PRINT(KERN_ERR, ohci->id,
@@ -1305,48 +747,21 @@ static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
if (tcode & 0x02) d = ohci->at_resp_context;
else d = ohci->at_req_context;
- spin_lock(&d->lock);
+ spin_lock_irqsave(&d->lock,flags);
- if (d->free_prgs<1) {
- PRINT(KERN_INFO, ohci->id,
- "AT DMA ctx=%d Running out of prgs... waiting",d->ctx);
- }
- while (d->free_prgs<1) {
- spin_unlock(&d->lock);
- interruptible_sleep_on(&d->waitq);
- if(signal_pending(current)) return -EINTR;
- if (timeout--<0) {
- stop_context(ohci, d->ctrlClear,
- "AT DMA runaway loop... bailing out");
- return 0;
- }
- spin_lock(&d->lock);
- }
-
- insert_packet(ohci, d, packet);
-
- /* 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)) {
- DBGMSG(ohci->id,"Starting AT DMA ctx=%d",d->ctx);
- if (packet->data_size)
- reg_write(ohci, d->cmdPtr,
- virt_to_bus(&(d->prg[d->prg_ind])) | 0x3);
- else
- reg_write(ohci, d->cmdPtr,
- virt_to_bus(&(d->prg[d->prg_ind])) | 0x2);
-
- run_context(ohci, d->ctrlSet, NULL);
+ /* queue the packet for later insertion into to dma fifo */
+ if (d->pending_last) {
+ d->pending_last->xnext = packet;
+ d->pending_last = packet;
}
else {
- DBGMSG(ohci->id,"Waking AT DMA ctx=%d",d->ctx);
- /* wake up the dma context if necessary */
- if (!(reg_read(ohci, d->ctrlSet) & 0x400))
- reg_write(ohci, d->ctrlSet, 0x1000);
+ d->pending_first = packet;
+ d->pending_last = packet;
}
+
+ dma_trm_flush(ohci, d);
- d->prg_ind = (d->prg_ind+1)%d->num_desc;
- spin_unlock(&d->lock);
+ spin_unlock_irqrestore(&d->lock,flags);
return 1;
}
@@ -1359,7 +774,10 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
switch (cmd) {
case RESET_BUS:
- host->attempt_root=1;
+ /*
+ * FIXME: this flag might be necessary in some case
+ */
+ /* host->attempt_root = 1; */
PRINT(KERN_INFO, ohci->id, "resetting bus on request%s",
(host->attempt_root ? " and attempting to become root"
: ""));
@@ -1415,14 +833,9 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
-#if 0
- PRINT(KERN_INFO, ohci->id, "!!! try listen on channel %d !!!",
- arg);
-#endif
-
if (!test_and_set_bit(arg, &ohci->IR_channel_usage)) {
- PRINT(KERN_INFO, ohci->id,
- "listening enabled on channel %d", arg);
+ DBGMSG(ohci->id,
+ "listening enabled on channel %d", arg);
if (arg > 31) {
u32 setMask= 0x00000001;
@@ -1447,8 +860,8 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
if (test_and_clear_bit(arg, &ohci->IR_channel_usage)) {
- PRINT(KERN_INFO, ohci->id,
- "listening disabled on iso channel %d", arg);
+ DBGMSG(ohci->id,
+ "listening disabled on iso channel %d", arg);
if (arg > 31) {
u32 clearMask= 0x00000001;
@@ -1490,29 +903,42 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
static void dma_trm_reset(struct dma_trm_ctx *d)
{
struct ti_ohci *ohci;
+ unsigned long flags;
if (d==NULL) {
PRINT_G(KERN_ERR, "dma_trm_reset called with NULL arg");
return;
}
ohci = (struct ti_ohci *)(d->ohci);
- stop_context(ohci, d->ctrlClear, NULL);
+ ohci1394_stop_context(ohci, d->ctrlClear, NULL);
- spin_lock(&d->lock);
+ spin_lock_irqsave(&d->lock,flags);
+
+ /* is there still any packet pending in the fifo ? */
+ while(d->fifo_first) {
+ PRINT(KERN_INFO, ohci->id,
+ "AT dma reset ctx=%d, aborting transmission",
+ d->ctx);
+ hpsb_packet_sent(ohci->host, d->fifo_first, ACKX_ABORTED);
+ d->fifo_first = d->fifo_first->xnext;
+ }
+ d->fifo_first = d->fifo_last = NULL;
/* is there still any packet pending ? */
- while(d->first) {
+ while(d->pending_first) {
PRINT(KERN_INFO, ohci->id,
"AT dma reset ctx=%d, aborting transmission",
d->ctx);
- hpsb_packet_sent(ohci->host, d->first, ACKX_ABORTED);
- d->first = d->first->xnext;
+ hpsb_packet_sent(ohci->host, d->pending_first,
+ ACKX_ABORTED);
+ d->pending_first = d->pending_first->xnext;
}
- d->first = d->last = NULL;
+ d->pending_first = d->pending_last = NULL;
+
d->branchAddrPtr=NULL;
d->sent_ind = d->prg_ind;
d->free_prgs = d->num_desc;
- spin_unlock(&d->lock);
+ spin_unlock_irqrestore(&d->lock,flags);
}
static void ohci_irq_handler(int irq, void *dev_id,
@@ -1528,10 +954,10 @@ static void ohci_irq_handler(int irq, void *dev_id,
/* read the interrupt event register */
event=reg_read(ohci, OHCI1394_IntEventClear);
- DBGMSG(ohci->id, "IntEvent: %08x",event);
-
if (!event) return;
+ DBGMSG(ohci->id, "IntEvent: %08x",event);
+
/* clear the interrupt event register */
reg_write(ohci, OHCI1394_IntEventClear, event);
@@ -1560,7 +986,7 @@ static void ohci_irq_handler(int irq, void *dev_id,
DBGMSG(ohci->id, "Got reqTxComplete interrupt "
"status=0x%08X", reg_read(ohci, d->ctrlSet));
if (reg_read(ohci, d->ctrlSet) & 0x800)
- stop_context(ohci, d->ctrlClear,
+ ohci1394_stop_context(ohci, d->ctrlClear,
"reqTxComplete");
else
dma_trm_bh((void *)d);
@@ -1570,7 +996,7 @@ static void ohci_irq_handler(int irq, void *dev_id,
DBGMSG(ohci->id, "Got respTxComplete interrupt "
"status=0x%08X", reg_read(ohci, d->ctrlSet));
if (reg_read(ohci, d->ctrlSet) & 0x800)
- stop_context(ohci, d->ctrlClear,
+ ohci1394_stop_context(ohci, d->ctrlClear,
"respTxComplete");
else
dma_trm_bh((void *)d);
@@ -1580,9 +1006,9 @@ static void ohci_irq_handler(int irq, void *dev_id,
DBGMSG(ohci->id, "Got RQPkt interrupt status=0x%08X",
reg_read(ohci, d->ctrlSet));
if (reg_read(ohci, d->ctrlSet) & 0x800)
- stop_context(ohci, d->ctrlClear, "RQPkt");
+ ohci1394_stop_context(ohci, d->ctrlClear, "RQPkt");
else {
-#if 1
+#if IEEE1394_USE_BOTTOM_HALVES
queue_task(&d->task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
#else
@@ -1595,9 +1021,9 @@ static void ohci_irq_handler(int irq, void *dev_id,
DBGMSG(ohci->id, "Got RSPkt interrupt status=0x%08X",
reg_read(ohci, d->ctrlSet));
if (reg_read(ohci, d->ctrlSet) & 0x800)
- stop_context(ohci, d->ctrlClear, "RSPkt");
+ ohci1394_stop_context(ohci, d->ctrlClear, "RSPkt");
else {
-#if 1
+#if IEEE1394_USE_BOTTOM_HALVES
queue_task(&d->task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
#else
@@ -1608,9 +1034,6 @@ static void ohci_irq_handler(int irq, void *dev_id,
if (event & OHCI1394_isochRx) {
quadlet_t isoRecvIntEvent;
struct dma_rcv_ctx *d = ohci->ir_context;
-#ifdef _VIDEO_1394_H
- int i;
-#endif
isoRecvIntEvent =
reg_read(ohci, OHCI1394_IsoRecvIntEventSet);
reg_write(ohci, OHCI1394_IsoRecvIntEventClear,
@@ -1620,10 +1043,10 @@ static void ohci_irq_handler(int irq, void *dev_id,
reg_read(ohci, d->ctrlSet), isoRecvIntEvent);
if (isoRecvIntEvent & 0x1) {
if (reg_read(ohci, d->ctrlSet) & 0x800)
- stop_context(ohci, d->ctrlClear,
+ ohci1394_stop_context(ohci, d->ctrlClear,
"isochRx");
else {
-#if 1
+#if IEEE1394_USE_BOTTOM_HALVES
queue_task(&d->task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
#else
@@ -1631,12 +1054,21 @@ static void ohci_irq_handler(int irq, void *dev_id,
#endif
}
}
-#ifdef _VIDEO_1394_H
- for (i=0;i<ohci->nb_iso_ctx-1;i++)
- if (isoRecvIntEvent & (1<<(i+1)))
- wakeup_dma_fbuf_ctx(
- ohci,ohci->fbuf_context[i]);
-#endif
+ if (ohci->video_tmpl)
+ ohci->video_tmpl->irq_handler(ohci->id,
+ isoRecvIntEvent,
+ 0);
+ }
+ if (event & OHCI1394_isochTx) {
+ quadlet_t isoXmitIntEvent;
+ isoXmitIntEvent =
+ reg_read(ohci, OHCI1394_IsoXmitIntEventSet);
+ reg_write(ohci, OHCI1394_IsoXmitIntEventClear,
+ isoXmitIntEvent);
+ DBGMSG(ohci->id, "Got isochTx interrupt");
+ if (ohci->video_tmpl)
+ ohci->video_tmpl->irq_handler(ohci->id, 0,
+ isoXmitIntEvent);
}
if (event & OHCI1394_selfIDComplete) {
if (host->in_bus_reset) {
@@ -1703,10 +1135,10 @@ static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx)
struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
DBGMSG(ohci->id, "Inserting dma buf ctx=%d idx=%d", d->ctx, idx);
- d->prg[idx]->status = d->buf_size;
- d->prg[idx]->branchAddress &= 0xfffffff0;
+ d->prg_cpu[idx]->status = d->buf_size;
+ d->prg_cpu[idx]->branchAddress &= 0xfffffff0;
idx = (idx + d->num_desc - 1 ) % d->num_desc;
- d->prg[idx]->branchAddress |= 0x1;
+ d->prg_cpu[idx]->branchAddress |= 0x1;
/* wake up the dma context if necessary */
if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
@@ -1724,7 +1156,7 @@ static int block_length(struct dma_rcv_ctx *d, int idx,
/* Where is the data length ? */
if (offset+12>=d->buf_size)
- length = (d->buf[(idx+1)%d->num_desc]
+ length = (d->buf_cpu[(idx+1)%d->num_desc]
[3-(d->buf_size-offset)/4]>>16);
else
length = (buf_ptr[3]>>16);
@@ -1769,7 +1201,7 @@ static void dma_rcv_bh(void *data)
struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
unsigned int split_left, idx, offset, rescount;
unsigned char tcode;
- int length, bytes_left;
+ int length, bytes_left, ack;
quadlet_t *buf_ptr;
char *split_ptr;
char msg[256];
@@ -1778,9 +1210,9 @@ static void dma_rcv_bh(void *data)
idx = d->buf_ind;
offset = d->buf_offset;
- buf_ptr = d->buf[idx] + offset/4;
+ buf_ptr = d->buf_cpu[idx] + offset/4;
- rescount = d->prg[idx]->status&0xffff;
+ rescount = d->prg_cpu[idx]->status&0xffff;
bytes_left = d->buf_size - rescount - offset;
while (bytes_left>0) {
@@ -1790,21 +1222,22 @@ static void dma_rcv_bh(void *data)
if (length<4) { /* something is wrong */
sprintf(msg,"unexpected tcode 0x%X in AR ctx=%d",
tcode, d->ctx);
- stop_context(ohci, d->ctrlClear, msg);
+ ohci1394_stop_context(ohci, d->ctrlClear, msg);
spin_unlock(&d->lock);
return;
}
if ((offset+length)>d->buf_size) { /* Split packet */
if (length>d->split_buf_size) {
- stop_context(ohci, d->ctrlClear,
+ ohci1394_stop_context(ohci, d->ctrlClear,
"split packet size exceeded");
d->buf_ind = idx;
d->buf_offset = offset;
spin_unlock(&d->lock);
return;
}
- if (d->prg[(idx+1)%d->num_desc]->status==d->buf_size) {
+ if (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 */
@@ -1822,7 +1255,7 @@ static void dma_rcv_bh(void *data)
split_ptr += d->buf_size-offset;
insert_dma_buffer(d, idx);
idx = (idx+1) % d->num_desc;
- buf_ptr = d->buf[idx];
+ buf_ptr = d->buf_cpu[idx];
offset=0;
while (split_left >= d->buf_size) {
memcpy(split_ptr,buf_ptr,d->buf_size);
@@ -1830,7 +1263,7 @@ static void dma_rcv_bh(void *data)
split_left -= d->buf_size;
insert_dma_buffer(d, idx);
idx = (idx+1) % d->num_desc;
- buf_ptr = d->buf[idx];
+ buf_ptr = d->buf_cpu[idx];
}
if (split_left>0) {
memcpy(split_ptr, buf_ptr, split_left);
@@ -1838,17 +1271,6 @@ static void dma_rcv_bh(void *data)
buf_ptr += offset/4;
}
- /*
- * Tip by James Goodwin <jamesg@Filanet.com>
- * We need to handle write requests that are received
- * to our middle address space (posted writes).
- * In this case, the hardware generates an
- * ack_complete... but, if we pass the packet up to
- * the subsystem, it will try and send a response
- * (which it shouldn't), because it assumes we
- * returned ack_pending.
- */
-
/*
* We get one phy packet for each bus reset.
* we know that from now on the bus topology may
@@ -1862,22 +1284,12 @@ static void dma_rcv_bh(void *data)
(d->spb[length/4-1]>>16)&0x1f,
(d->spb[length/4-1]>>21)&0x3,
tcode, length, d->spb[3], d->ctx);
+
+ ack = (((d->spb[length/4-1]>>16)&0x1f)
+ == 0x11) ? 1 : 0;
- /*
- * Tip by James Goodwin <jamesg@Filanet.com>
- * Handle case of posted writes. If we receive
- * an ack_complete, we should not send a
- * response. Fake out upper layers by turning
- * the packet into a broadcast packet... we
- * should really modify the core stack to
- * accept an ack received argument and figure
- * out whether to reply.
- */
- if (((d->spb[length/4-1]>>16)&0x1f) == 0x11) {
- d->spb[0] |= (ALL_NODES<<16);
- }
hpsb_packet_received(ohci->host, d->spb,
- length);
+ length, ack);
}
else
PRINT(KERN_INFO, ohci->id,
@@ -1899,21 +1311,11 @@ static void dma_rcv_bh(void *data)
(buf_ptr[length/4-1]>>21)&0x3,
tcode, length, buf_ptr[3], d->ctx);
- /*
- * Tip by James Goodwin <jamesg@Filanet.com>
- * Handle case of posted writes. If we receive
- * an ack_complete, we should not send a
- * response. Fake out upper layers by turning
- * the packet into a broadcast packet... we
- * should really modify the core stack to
- * accept an ack received argument and figure
- * out whether to reply.
- */
- if (((d->spb[length/4-1]>>16)&0x1f) == 0x11) {
- buf_ptr[0] |= (ALL_NODES<<16);
- }
+ ack = (((buf_ptr[length/4-1]>>16)&0x1f)
+ == 0x11) ? 1 : 0;
+
hpsb_packet_received(ohci->host, buf_ptr,
- length);
+ length, ack);
}
else
PRINT(KERN_INFO, ohci->id,
@@ -1924,11 +1326,11 @@ static void dma_rcv_bh(void *data)
if (offset==d->buf_size) {
insert_dma_buffer(d, idx);
idx = (idx+1) % d->num_desc;
- buf_ptr = d->buf[idx];
+ buf_ptr = d->buf_cpu[idx];
offset=0;
}
}
- rescount = d->prg[idx]->status & 0xffff;
+ rescount = d->prg_cpu[idx]->status & 0xffff;
bytes_left = d->buf_size - rescount - offset;
}
@@ -1945,32 +1347,51 @@ static void dma_trm_bh(void *data)
struct dma_trm_ctx *d = (struct dma_trm_ctx*)data;
struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
struct hpsb_packet *packet;
+ unsigned long flags;
u32 ack;
- spin_lock(&d->lock);
+ spin_lock_irqsave(&d->lock, flags);
- if (d->first==NULL) {
- stop_context(ohci, d->ctrlClear,
+ if (d->fifo_first==NULL) {
+#if 0
+ ohci1394_stop_context(ohci, d->ctrlClear,
"Packet sent ack received but queue is empty");
- spin_unlock(&d->lock);
+#endif
+ spin_unlock_irqrestore(&d->lock, flags);
return;
}
- packet = d->first;
- d->first = d->first->xnext;
- if (d->first==NULL) d->last=NULL;
- if (packet->data_size)
- ack = d->prg[d->sent_ind].end.status>>16;
- else
- ack = d->prg[d->sent_ind].begin.status>>16;
- d->sent_ind = (d->sent_ind+1)%d->num_desc;
- d->free_prgs++;
- spin_unlock(&d->lock);
- if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq);
+ while (d->fifo_first) {
+ packet = d->fifo_first;
+ if (packet->data_size)
+ ack = d->prg_cpu[d->sent_ind]->end.status>>16;
+ else
+ ack = d->prg_cpu[d->sent_ind]->begin.status>>16;
+
+ if (ack==0)
+ /* this packet hasn't been sent yet*/
+ break;
+
+ DBGMSG(ohci->id,
+ "Packet sent to node %d ack=0x%X spd=%d ctx=%d",
+ (packet->header[0]>>16)&0x3f, ack&0x1f, (ack>>5)&0x3,
+ d->ctx);
+ hpsb_packet_sent(ohci->host, packet, ack&0xf);
+
+ if (packet->data_size)
+ pci_unmap_single(ohci->dev,
+ d->prg_cpu[d->sent_ind]->end.address,
+ packet->data_size, PCI_DMA_TODEVICE);
+
+ d->sent_ind = (d->sent_ind+1)%d->num_desc;
+ d->free_prgs++;
+ d->fifo_first = d->fifo_first->xnext;
+ }
+ if (d->fifo_first==NULL) d->fifo_last=NULL;
+
+ dma_trm_flush(ohci, d);
- DBGMSG(ohci->id, "Packet sent to node %d ack=0x%X spd=%d ctx=%d",
- (packet->header[0]>>16)&0x3f, ack&0x1f, (ack>>5)&0x3, d->ctx);
- hpsb_packet_sent(ohci->host, packet, ack&0xf);
+ spin_unlock_irqrestore(&d->lock, flags);
}
static int free_dma_rcv_ctx(struct dma_rcv_ctx **d)
@@ -1984,17 +1405,25 @@ static int free_dma_rcv_ctx(struct dma_rcv_ctx **d)
DBGMSG(ohci->id, "Freeing dma_rcv_ctx %d",(*d)->ctx);
- stop_context(ohci, (*d)->ctrlClear, NULL);
+ ohci1394_stop_context(ohci, (*d)->ctrlClear, NULL);
- if ((*d)->buf) {
- for (i=0; i<(*d)->num_desc; i++)
- if ((*d)->buf[i]) kfree((*d)->buf[i]);
- kfree((*d)->buf);
- }
- if ((*d)->prg) {
+ if ((*d)->buf_cpu) {
for (i=0; i<(*d)->num_desc; i++)
- if ((*d)->prg[i]) kfree((*d)->prg[i]);
- kfree((*d)->prg);
+ 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_free_consistent(
+ ohci->dev, sizeof(struct dma_cmd),
+ (*d)->prg_cpu[i], (*d)->prg_bus[i]);
+ kfree((*d)->prg_cpu);
+ kfree((*d)->prg_bus);
}
if ((*d)->spb) kfree((*d)->spb);
@@ -2030,27 +1459,34 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
d->ctrlClear = ctrlClear;
d->cmdPtr = cmdPtr;
- d->buf = NULL;
- d->prg = NULL;
+ d->buf_cpu = NULL;
+ d->buf_bus = NULL;
+ d->prg_cpu = NULL;
+ d->prg_bus = NULL;
d->spb = NULL;
- d->buf = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL);
+ d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL);
+ d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
- if (d->buf == NULL) {
+ if (d->buf_cpu == NULL || d->buf_bus == NULL) {
PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer");
free_dma_rcv_ctx(&d);
return NULL;
}
- memset(d->buf, 0, d->num_desc * sizeof(quadlet_t*));
+ memset(d->buf_cpu, 0, d->num_desc * sizeof(quadlet_t*));
+ memset(d->buf_bus, 0, d->num_desc * sizeof(dma_addr_t));
- d->prg = kmalloc(d->num_desc * sizeof(struct dma_cmd*), GFP_KERNEL);
+ d->prg_cpu = kmalloc(d->num_desc * sizeof(struct dma_cmd*),
+ GFP_KERNEL);
+ d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
- if (d->prg == NULL) {
+ if (d->prg_cpu == NULL || d->prg_bus == NULL) {
PRINT(KERN_ERR, ohci->id, "failed to allocate dma prg");
free_dma_rcv_ctx(&d);
return NULL;
}
- memset(d->prg, 0, d->num_desc * sizeof(struct dma_cmd*));
+ memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*));
+ memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
d->spb = kmalloc(d->split_buf_size, GFP_KERNEL);
@@ -2061,10 +1497,12 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
}
for (i=0; i<d->num_desc; i++) {
- d->buf[i] = kmalloc(d->buf_size, GFP_KERNEL);
+ d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
+ d->buf_size,
+ d->buf_bus+i);
- if (d->buf[i] != NULL) {
- memset(d->buf[i], 0, d->buf_size);
+ if (d->buf_cpu[i] != NULL) {
+ memset(d->buf_cpu[i], 0, d->buf_size);
} else {
PRINT(KERN_ERR, ohci->id,
"failed to allocate dma buffer");
@@ -2072,10 +1510,13 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
return NULL;
}
- d->prg[i]= kmalloc(sizeof(struct dma_cmd), GFP_KERNEL);
+
+ d->prg_cpu[i] = pci_alloc_consistent(ohci->dev,
+ sizeof(struct dma_cmd),
+ d->prg_bus+i);
- if (d->prg[i] != NULL) {
- memset(d->prg[i], 0, sizeof(struct dma_cmd));
+ if (d->prg_cpu[i] != NULL) {
+ memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
} else {
PRINT(KERN_ERR, ohci->id,
"failed to allocate dma prg");
@@ -2098,6 +1539,7 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
static int free_dma_trm_ctx(struct dma_trm_ctx **d)
{
struct ti_ohci *ohci;
+ int i;
if (*d==NULL) return -1;
@@ -2105,9 +1547,18 @@ static int free_dma_trm_ctx(struct dma_trm_ctx **d)
DBGMSG(ohci->id, "Freeing dma_trm_ctx %d",(*d)->ctx);
- stop_context(ohci, (*d)->ctrlClear, NULL);
+ ohci1394_stop_context(ohci, (*d)->ctrlClear, NULL);
+
+ if ((*d)->prg_cpu) {
+ for (i=0; i<(*d)->num_desc; i++)
+ if ((*d)->prg_cpu[i] && (*d)->prg_bus[i])
+ pci_free_consistent(
+ ohci->dev, sizeof(struct at_dma_prg),
+ (*d)->prg_cpu[i], (*d)->prg_bus[i]);
+ kfree((*d)->prg_cpu);
+ kfree((*d)->prg_bus);
+ }
- if ((*d)->prg) kfree((*d)->prg);
kfree(*d);
*d = NULL;
return 0;
@@ -2118,6 +1569,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
int ctrlSet, int ctrlClear, int cmdPtr)
{
struct dma_trm_ctx *d=NULL;
+ int i;
d = (struct dma_trm_ctx *)kmalloc(sizeof(struct dma_trm_ctx),
GFP_KERNEL);
@@ -2133,16 +1585,35 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
d->ctrlSet = ctrlSet;
d->ctrlClear = ctrlClear;
d->cmdPtr = cmdPtr;
- d->prg = NULL;
+ d->prg_cpu = NULL;
+ d->prg_bus = NULL;
- d->prg = kmalloc(d->num_desc * sizeof(struct at_dma_prg), GFP_KERNEL);
+ d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*),
+ GFP_KERNEL);
+ d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
- if (d->prg == NULL) {
+ if (d->prg_cpu == NULL || d->prg_bus == NULL) {
PRINT(KERN_ERR, ohci->id, "failed to allocate at dma prg");
free_dma_trm_ctx(&d);
return NULL;
}
- memset(d->prg, 0, d->num_desc * sizeof(struct at_dma_prg));
+ memset(d->prg_cpu, 0, d->num_desc * sizeof(struct at_dma_prg*));
+ memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
+
+ for (i=0; i<d->num_desc; i++) {
+ d->prg_cpu[i] = pci_alloc_consistent(ohci->dev,
+ sizeof(struct at_dma_prg),
+ 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, ohci->id,
+ "failed to allocate at dma prg");
+ free_dma_trm_ctx(&d);
+ return NULL;
+ }
+ }
spin_lock_init(&d->lock);
@@ -2150,15 +1621,42 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, int ctx, int num_desc,
d->task.routine = dma_trm_bh;
d->task.data = (void*)d;
- init_waitqueue_head(&d->waitq);
-
return d;
}
+static u32 ohci_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) ^ (*data >> shift)) & 0xf;
+ next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
+ }
+ check = next & 0xffff;
+ data++;
+ }
+
+ return check;
+}
+
+static void ohci_init_config_rom(struct ti_ohci *ohci)
+{
+ int i;
+
+ ohci_csr_rom[3] = reg_read(ohci, OHCI1394_GUIDHi);
+ ohci_csr_rom[4] = reg_read(ohci, OHCI1394_GUIDLo);
+
+ ohci_csr_rom[0] = 0x04040000 | ohci_crc16(ohci_csr_rom+1, 4);
+
+ for (i=0;i<sizeof(ohci_csr_rom)/4;i++)
+ ohci->csr_config_rom_cpu[i] = cpu_to_be32(ohci_csr_rom[i]);
+}
+
static int add_card(struct pci_dev *dev)
{
struct ti_ohci *ohci; /* shortcut to currently handled device */
- int i;
if (num_of_cards == MAX_OHCI1394_CARDS) {
PRINT_G(KERN_WARNING, "cannot handle more than %d cards. "
@@ -2182,21 +1680,29 @@ static int add_card(struct pci_dev *dev)
ohci->state = 0;
/* csr_config rom allocation */
- ohci->csr_config_rom = kmalloc(1024, GFP_KERNEL);
- if (ohci->csr_config_rom == NULL) {
+ ohci->csr_config_rom_cpu =
+ pci_alloc_consistent(ohci->dev, sizeof(ohci_csr_rom),
+ &ohci->csr_config_rom_bus);
+ if (ohci->csr_config_rom_cpu == NULL) {
FAIL("failed to allocate buffer config rom");
}
- for (i=0;i<sizeof(ohci_csr_rom)/4;i++)
- ohci->csr_config_rom[i] = cpu_to_be32(ohci_csr_rom[i]);
DBGMSG(ohci->id, "The 1st byte at offset 0x404 is: 0x%02x",
- *((char *)ohci->csr_config_rom+4));
+ *((char *)ohci->csr_config_rom_cpu+4));
- /* self-id dma buffer allocation */
- ohci->self_id_buffer = kmalloc(2048, GFP_KERNEL);
- if (ohci->self_id_buffer == NULL) {
+ /*
+ * self-id dma buffer allocation
+ * FIXME: some early chips may need 8KB alignment for the
+ * selfid buffer
+ */
+ ohci->selfid_buf_cpu =
+ pci_alloc_consistent(ohci->dev, 2048, &ohci->selfid_buf_bus);
+ if (ohci->selfid_buf_cpu == NULL) {
FAIL("failed to allocate DMA buffer for self-id packets");
}
+ if ((unsigned long)ohci->selfid_buf_cpu & 0xfff)
+ PRINT(KERN_INFO, ohci->id, "Selfid buffer %p not aligned on "
+ "8Kb boundary", ohci->selfid_buf_cpu);
ohci->ar_req_context =
alloc_dma_rcv_ctx(ohci, 0, AR_REQ_NUM_DESC,
@@ -2241,9 +1747,9 @@ static int add_card(struct pci_dev *dev)
ohci->ir_context =
alloc_dma_rcv_ctx(ohci, 2, IR_NUM_DESC,
IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
- OHCI1394_IrRcvContextControlSet,
- OHCI1394_IrRcvContextControlClear,
- OHCI1394_IrRcvCommandPtr);
+ OHCI1394_IsoRcvContextControlSet,
+ OHCI1394_IsoRcvContextControlClear,
+ OHCI1394_IsoRcvCommandPtr);
if (ohci->ir_context == NULL) {
FAIL("failed to allocate IR context");
@@ -2274,6 +1780,8 @@ static int add_card(struct pci_dev *dev)
FAIL("failed to allocate shared interrupt %d", dev->irq);
}
+ ohci_init_config_rom(ohci);
+
return 0;
#undef FAIL
}
@@ -2297,12 +1805,9 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
//unsigned char phyreg;
//int i, nports;
int i;
+
struct dma_rcv_ctx *d=NULL;
struct dma_trm_ctx *dt=NULL;
-#ifdef _VIDEO_1394_H
- int j;
- struct dma_fbuf_ctx *f=ohci->fbuf_context[0];
-#endif
p += sprintf(p,"IEEE-1394 OHCI Driver status report:\n");
p += sprintf(p," bus number: 0x%x Node ID: 0x%x\n",
@@ -2332,26 +1837,6 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
p += sprintf(p,"\n---Iso Receive DMA---\n");
-#ifdef _VIDEO_1394_H
-
-#if 0
- if (f!=NULL) {
- for (i=0; i<f->num_desc; i++) {
- for (j=0;j<f->nb_cmd;j++) {
- p += sprintf(p,
- "prg[%d][%d]: %p %08x %08x %08x %08x\n",
- i,j,virt_to_bus(&(f->prg[i][j])),
- f->prg[i][j].control,
- f->prg[i][j].address,
- f->prg[i][j].branchAddress,
- f->prg[i][j].status);
- }
- }
- }
-#endif
-
-#else
-
d = ohci->ir_context;
#if 0
for (i=0; i<d->num_desc; i++) {
@@ -2389,7 +1874,7 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
dt->prg_ind, dt->sent_ind, dt->free_prgs,
dt->branchAddrPtr);
p += sprintf(p, "AT req queue: first: %p last: %p\n",
- dt->first, dt->last);
+ dt->fifo_first, dt->fifo_last);
dt = ohci->at_resp_context;
#if 0
for (i=0; i<dt->num_desc; i++) {
@@ -2437,15 +1922,14 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
dt->prg_ind, dt->sent_ind, dt->free_prgs,
dt->branchAddrPtr);
p += sprintf(p, "AT resp queue: first: %p last: %p\n",
- dt->first, dt->last);
-#endif
+ dt->fifo_first, dt->fifo_last);
/* ----- Register Dump ----- */
p += sprintf(p,"\n### HC Register dump ###\n");
SR("Version : %08x GUID_ROM : %08x ATRetries : %08x\n",
OHCI1394_Version, OHCI1394_GUID_ROM, OHCI1394_ATRetries);
- SR("CSRReadData : %08x CSRCompData : %08x CSRControl : %08x\n",
- OHCI1394_CSRReadData, OHCI1394_CSRCompareData, OHCI1394_CSRControl);
+ SR("CSRData : %08x CSRCompData : %08x CSRControl : %08x\n",
+ OHCI1394_CSRData, OHCI1394_CSRCompareData, OHCI1394_CSRControl);
SR("ConfigROMhdr: %08x BusID : %08x BusOptions : %08x\n",
OHCI1394_ConfigROMhdr, OHCI1394_BusID, OHCI1394_BusOptions);
SR("GUIDHi : %08x GUIDLo : %08x ConfigROMmap: %08x\n",
@@ -2481,14 +1965,21 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
SR("AsRsRvCtxCtl: %08x AsRsRvCmdPtr: %08x IntEvent : %08x\n",
OHCI1394_AsRspRcvContextControlSet, OHCI1394_AsRspRcvCommandPtr,
OHCI1394_IntEventSet);
- for (i=0;i<4;i++) {
+ for (i=0;i<ohci->nb_iso_rcv_ctx;i++) {
p += sprintf(p,"IsoRCtxCtl%02d: %08x IsoRCmdPtr%02d: %08x"
" IsoRCxtMch%02d: %08x\n", i,
reg_read(ohci,
- OHCI1394_IrRcvContextControlSet+32*i),
- i,reg_read(ohci, OHCI1394_IrRcvCommandPtr+32*i),
+ OHCI1394_IsoRcvContextControlSet+32*i),
+ i,reg_read(ohci, OHCI1394_IsoRcvCommandPtr+32*i),
i,reg_read(ohci,
- OHCI1394_IrRcvContextMatch+32*i));
+ OHCI1394_IsoRcvContextMatch+32*i));
+ }
+ for (i=0;i<ohci->nb_iso_xmit_ctx;i++) {
+ p += sprintf(p,"IsoTCtxCtl%02d: %08x IsoTCmdPtr%02d: %08x\n",
+ i,
+ reg_read(ohci,
+ OHCI1394_IsoXmitContextControlSet+32*i),
+ i,reg_read(ohci,OHCI1394_IsoXmitCommandPtr+32*i));
}
#if 0
@@ -2554,9 +2045,11 @@ struct proc_dir_entry ohci_proc_entry =
static void remove_card(struct ti_ohci *ohci)
{
-#ifdef _VIDEO_1394_H
- int i;
-#endif
+ /*
+ * Reset the board properly before leaving
+ * Daniel Kobras <daniel.kobras@student.uni-tuebingen.de>
+ */
+ ohci_soft_reset(ohci);
/* Free AR dma */
free_dma_rcv_ctx(&ohci->ar_req_context);
@@ -2569,28 +2062,18 @@ static void remove_card(struct ti_ohci *ohci)
/* Free IR dma */
free_dma_rcv_ctx(&ohci->ir_context);
-#ifdef _VIDEO_1394_H
- /* Free the frame buffer context */
- if (ohci->fbuf_context)
- for (i=0;i<ohci->nb_iso_ctx-1;i++) {
- free_dma_fbuf_ctx(&ohci->fbuf_context[i]);
- }
-#endif
-
- /*
- * Reset the board properly before leaving
- * Daniel Kobras <daniel.kobras@student.uni-tuebingen.de>
- */
- ohci_soft_reset(ohci);
-
/* Free self-id buffer */
- if (ohci->self_id_buffer)
- kfree(ohci->self_id_buffer);
+ if (ohci->selfid_buf_cpu)
+ pci_free_consistent(ohci->dev, 2048,
+ ohci->selfid_buf_cpu,
+ ohci->selfid_buf_bus);
/* Free config rom */
- if (ohci->csr_config_rom)
- kfree(ohci->csr_config_rom);
-
+ if (ohci->csr_config_rom_cpu)
+ pci_free_consistent(ohci->dev, sizeof(ohci_csr_rom),
+ ohci->csr_config_rom_cpu,
+ ohci->csr_config_rom_bus);
+
/* Free the IRQ */
free_irq(ohci->dev->irq, ohci);
@@ -2646,9 +2129,9 @@ static size_t get_ohci_rom(struct hpsb_host *host, const quadlet_t **ptr)
struct ti_ohci *ohci=host->hostdata;
DBGMSG(ohci->id, "request csr_rom address: %08X",
- (u32)ohci->csr_config_rom);
+ (u32)ohci->csr_config_rom_cpu);
- *ptr = ohci->csr_config_rom;
+ *ptr = ohci->csr_config_rom_cpu;
return sizeof(ohci_csr_rom);
}
@@ -2675,6 +2158,118 @@ struct hpsb_host_template *get_ohci_template(void)
return &tmpl;
}
+void 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, ohci->id,
+ "runaway loop while stopping context...");
+ break;
+ }
+ }
+ if (msg) PRINT(KERN_ERR, ohci->id, "%s\n dma prg stopped\n", msg);
+}
+
+struct ti_ohci *ohci1394_get_struct(int card_num)
+{
+ if (card_num>=0 && card_num<num_of_cards)
+ return &cards[card_num];
+ return NULL;
+}
+
+int ohci1394_register_video(struct ti_ohci *ohci,
+ struct video_template *tmpl)
+{
+ if (ohci->video_tmpl)
+ return -ENFILE;
+ ohci->video_tmpl = tmpl;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+void ohci1394_unregister_video(struct ti_ohci *ohci,
+ struct video_template *tmpl)
+{
+ if (ohci->video_tmpl != tmpl) {
+ PRINT(KERN_ERR, ohci->id,
+ "Trying to unregister wrong video device");
+ }
+ else {
+ ohci->video_tmpl = NULL;
+ MOD_DEC_USE_COUNT;
+ }
+}
+
+#if 0
+int ohci_compare_swap(struct ti_ohci *ohci, quadlet_t *data,
+ quadlet_t compare, int sel)
+{
+ int timeout = 255;
+ reg_write(ohci, OHCI1394_CSRData, *data);
+ reg_write(ohci, OHCI1394_CSRCompareData, compare);
+ reg_write(ohci, OHCI1394_CSRControl, sel);
+ while(!(reg_read(ohci, OHCI1394_CSRControl)&0x80000000)) {
+ if (timeout--) {
+ PRINT(KERN_INFO, ohci->id, "request_channel timeout");
+ return -1;
+ }
+ }
+ *data = reg_read(ohci, OHCI1394_CSRData);
+ return 0;
+}
+
+int ohci1394_request_channel(struct ti_ohci *ohci, int channel)
+{
+ int csrSel;
+ quadlet_t chan, data1=0, data2=0;
+ int timeout = 32;
+
+ if (channel<32) {
+ chan = 1<<channel;
+ csrSel = 2;
+ }
+ else {
+ chan = 1<<(channel-32);
+ csrSel = 3;
+ }
+ if (ohci_compare_swap(ohci, &data1, 0, csrSel)<0) {
+ PRINT(KERN_INFO, ohci->id, "request_channel timeout");
+ return -1;
+ }
+ while (timeout--) {
+ if (data1 & chan) {
+ PRINT(KERN_INFO, ohci->id,
+ "request channel %d failed", channel);
+ return -1;
+ }
+ data2 = data1;
+ data1 |= chan;
+ if (ohci_compare_swap(ohci, &data1, data2, csrSel)<0) {
+ PRINT(KERN_INFO, ohci->id, "request_channel timeout");
+ return -1;
+ }
+ if (data1==data2) {
+ PRINT(KERN_INFO, ohci->id,
+ "request channel %d succeded", channel);
+ return 0;
+ }
+ }
+ PRINT(KERN_INFO, ohci->id, "request channel %d failed", channel);
+ return -1;
+}
+#endif
+
+EXPORT_SYMBOL(ohci1394_stop_context);
+EXPORT_SYMBOL(ohci1394_get_struct);
+EXPORT_SYMBOL(ohci1394_register_video);
+EXPORT_SYMBOL(ohci1394_unregister_video);
#ifdef MODULE
@@ -2695,10 +2290,6 @@ void cleanup_module(void)
#endif
#endif
-#ifdef _VIDEO_1394_H
- unregister_chrdev(OHCI1394_MAJOR, "ohci1394");
-#endif
-
PRINT_G(KERN_INFO, "removed " OHCI1394_DRIVER_NAME " module\n");
}
@@ -2709,17 +2300,8 @@ int init_module(void)
if (hpsb_register_lowlevel(get_ohci_template())) {
PRINT_G(KERN_ERR, "registering failed\n");
return -ENXIO;
- } else {
-#ifdef _VIDEO_1394_H
- if (register_chrdev(OHCI1394_MAJOR, "ohci1394", &ohci_fops))
- {
- printk("ohci1394: unable to get major %d\n",
- OHCI1394_MAJOR);
- return -EIO;
- }
-#endif
- return 0;
- }
+ }
+ return 0;
}
#endif /* MODULE */
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index d778cbe7d..af1aeb2a6 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -22,8 +22,8 @@
#define _OHCI1394_H
#include "ieee1394_types.h"
-/* include this for the video frame grabber */
-/* #include "video1394.h" */
+
+#define IEEE1394_USE_BOTTOM_HALVES 0
#define OHCI1394_DRIVER_NAME "ohci1394"
@@ -71,6 +71,18 @@
#define PCI_DEVICE_ID_APPLE_UNI_N_FW 0x0018
#endif
+#ifndef PCI_DEVICE_ID_ALI_OHCI1394_M5251
+#define PCI_DEVICE_ID_ALI_OHCI1394_M5251 0x5251
+#endif
+
+#ifndef PCI_VENDOR_ID_LUCENT
+#define PCI_VENDOR_ID_LUCENT 0x11c1
+#endif
+
+#ifndef PCI_DEVICE_ID_LUCENT_FW323
+#define PCI_DEVICE_ID_LUCENT_FW323 0x5811
+#endif
+
#define MAX_OHCI1394_CARDS 4
#define OHCI1394_MAX_AT_REQ_RETRIES 0x2
@@ -87,8 +99,8 @@
#define AR_RESP_SPLIT_BUF_SIZE 4096 /* split packet buffer */
#define IR_NUM_DESC 16 /* number of IR descriptors */
-#define IR_BUF_SIZE 6480 /* 6480 bytes/buffer */
-#define IR_SPLIT_BUF_SIZE 8192 /* split packet buffer */
+#define IR_BUF_SIZE 4096 /* 6480 bytes/buffer */
+#define IR_SPLIT_BUF_SIZE 4096 /* split packet buffer */
#define AT_REQ_NUM_DESC 32 /* number of AT req descriptors */
#define AT_RESP_NUM_DESC 32 /* number of AT resp descriptors */
@@ -113,8 +125,15 @@ struct dma_rcv_ctx {
unsigned int num_desc;
unsigned int buf_size;
unsigned int split_buf_size;
- struct dma_cmd **prg;
- quadlet_t **buf;
+
+ /* dma block descriptors */
+ struct dma_cmd **prg_cpu;
+ dma_addr_t *prg_bus;
+
+ /* dma buffers */
+ quadlet_t **buf_cpu;
+ dma_addr_t *buf_bus;
+
unsigned int buf_ind;
unsigned int buf_offset;
quadlet_t *spb;
@@ -130,45 +149,37 @@ struct dma_trm_ctx {
void *ohci;
int ctx;
unsigned int num_desc;
- struct at_dma_prg *prg;
+
+ /* dma block descriptors */
+ struct at_dma_prg **prg_cpu;
+ dma_addr_t *prg_bus;
+
unsigned int prg_ind;
unsigned int sent_ind;
int free_prgs;
quadlet_t *branchAddrPtr;
- struct hpsb_packet *first;
- struct hpsb_packet *last;
+
+ /* list of packets inserted in the AT FIFO */
+ struct hpsb_packet *fifo_first;
+ struct hpsb_packet *fifo_last;
+
+ /* list of pending packets to be inserted in the AT FIFO */
+ struct hpsb_packet *pending_first;
+ struct hpsb_packet *pending_last;
+
spinlock_t lock;
struct tq_struct task;
int ctrlClear;
int ctrlSet;
int cmdPtr;
- wait_queue_head_t waitq;
};
-#ifdef _VIDEO_1394_H
-
-#define OHCI1394_MAJOR 172
-#define ISO_CHANNELS 64
-
-struct dma_fbuf_ctx {
- void *ohci;
- int ctx;
- int channel;
- int last_buffer;
- unsigned int num_desc;
- unsigned int buf_size;
- unsigned int frame_size;
- unsigned int nb_cmd;
- unsigned char *buf;
- struct dma_cmd **prg;
- unsigned int *buffer_status;
- int ctrlClear;
- int ctrlSet;
- int cmdPtr;
- int ctxMatch;
- wait_queue_head_t waitq;
+/* video device template */
+struct video_template {
+ void (*irq_handler) (int card, quadlet_t isoRecvEvent,
+ quadlet_t isoXmitEvent);
};
-#endif
+
struct ti_ohci {
int id; /* sequential card number */
@@ -180,8 +191,13 @@ struct ti_ohci {
/* remapped memory spaces */
void *registers;
- quadlet_t *self_id_buffer; /* dma buffer for self-id packets */
- quadlet_t *csr_config_rom; /* buffer for csr config rom */
+ /* 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;
unsigned int max_packet_size;
@@ -197,13 +213,10 @@ struct ti_ohci {
struct dma_rcv_ctx *ir_context;
u64 IR_channel_usage;
spinlock_t IR_channel_lock;
- int nb_iso_ctx;
+ int nb_iso_rcv_ctx;
-#ifdef _VIDEO_1394_H
- /* frame buffer context */
- struct dma_fbuf_ctx **fbuf_context;
- struct dma_fbuf_ctx *current_fbuf_ctx;
-#endif
+ /* iso transmit */
+ int nb_iso_xmit_ctx;
/* IEEE-1394 part follows */
struct hpsb_host *host;
@@ -214,8 +227,23 @@ struct ti_ohci {
int self_id_errors;
int NumBusResets;
+
+ /* video device */
+ struct video_template *video_tmpl;
};
+inline static int cross_bound(unsigned long addr, unsigned int size)
+{
+ int cross=0;
+ if (size>PAGE_SIZE) {
+ cross = size/PAGE_SIZE;
+ size -= cross*PAGE_SIZE;
+ }
+ if ((PAGE_SIZE-addr%PAGE_SIZE)<size)
+ cross++;
+ return cross;
+}
+
/*
* Register read and write helper functions.
*/
@@ -310,7 +338,7 @@ quadlet_t ohci_csr_rom[] = {
#define OHCI1394_Version 0x000
#define OHCI1394_GUID_ROM 0x004
#define OHCI1394_ATRetries 0x008
-#define OHCI1394_CSRReadData 0x00C
+#define OHCI1394_CSRData 0x00C
#define OHCI1394_CSRCompareData 0x010
#define OHCI1394_CSRControl 0x014
#define OHCI1394_ConfigROMhdr 0x018
@@ -370,12 +398,18 @@ quadlet_t ohci_csr_rom[] = {
#define OHCI1394_AsRspRcvContextControlClear 0x1E4
#define OHCI1394_AsRspRcvCommandPtr 0x1EC
+/* Isochronous transmit registers */
+/* Add (32 * n) for context n */
+#define OHCI1394_IsoXmitContextControlSet 0x200
+#define OHCI1394_IsoXmitContextControlClear 0x204
+#define OHCI1394_IsoXmitCommandPtr 0x20C
+
/* Isochronous receive registers */
/* Add (32 * n) for context n */
-#define OHCI1394_IrRcvContextControlSet 0x400
-#define OHCI1394_IrRcvContextControlClear 0x404
-#define OHCI1394_IrRcvCommandPtr 0x40C
-#define OHCI1394_IrRcvContextMatch 0x410
+#define OHCI1394_IsoRcvContextControlSet 0x400
+#define OHCI1394_IsoRcvContextControlClear 0x404
+#define OHCI1394_IsoRcvCommandPtr 0x40C
+#define OHCI1394_IsoRcvContextMatch 0x410
/* Interrupts Mask/Events */
@@ -410,5 +444,12 @@ quadlet_t ohci_csr_rom[] = {
#define DMA_SPEED_200 0x1
#define DMA_SPEED_400 0x2
+void ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg);
+struct ti_ohci *ohci1394_get_struct(int card_num);
+int ohci1394_register_video(struct ti_ohci *ohci,
+ struct video_template *tmpl);
+void ohci1394_unregister_video(struct ti_ohci *ohci,
+ struct video_template *tmpl);
+
#endif
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index 368c5137b..16aeaa92d 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -82,7 +82,7 @@ static pcl_t alloc_pcl(struct ti_lynx *lynx)
spin_lock(&lynx->lock);
/* FIXME - use ffz() to make this readable */
- for (i = 0; i < LOCALRAM_SIZE; i++) {
+ for (i = 0; i < (LOCALRAM_SIZE / 1024); i++) {
m = lynx->pcl_bmap[i];
for (j = 0; j < 8; j++) {
if (m & 1<<j) {
@@ -385,11 +385,22 @@ static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host, size_t s
-/* This must be called with the async_queue_lock held. */
+/* This must be called with the async.queue_lock held. */
static void send_next_async(struct ti_lynx *lynx)
{
struct ti_pcl pcl;
- struct hpsb_packet *packet = lynx->async_queue;
+ struct hpsb_packet *packet = lynx->async.queue;
+
+ lynx->async.header_dma = pci_map_single(lynx->dev, packet->header,
+ packet->header_size,
+ PCI_DMA_TODEVICE);
+ if (packet->data_size) {
+ lynx->async.data_dma = pci_map_single(lynx->dev, packet->data,
+ packet->data_size,
+ PCI_DMA_TODEVICE);
+ } else {
+ lynx->async.data_dma = 0;
+ }
pcl.next = PCL_NEXT_INVALID;
pcl.async_error_next = PCL_NEXT_INVALID;
@@ -400,16 +411,16 @@ static void send_next_async(struct ti_lynx *lynx)
pcl.buffer[0].control = PCL_CMD_XMT | packet->speed_code << 14
| packet->header_size | PCL_BIGENDIAN;
#endif
- pcl.buffer[0].pointer = virt_to_bus(packet->header);
+ pcl.buffer[0].pointer = lynx->async.header_dma;
pcl.buffer[1].control = PCL_LAST_BUFF | packet->data_size;
- pcl.buffer[1].pointer = virt_to_bus(packet->data);
+ pcl.buffer[1].pointer = lynx->async.data_dma;
if (!packet->data_be) {
pcl.buffer[1].control |= PCL_BIGENDIAN;
}
- put_pcl(lynx, lynx->async_pcl, &pcl);
- run_pcl(lynx, lynx->async_pcl_start, 3);
+ put_pcl(lynx, lynx->async.pcl, &pcl);
+ run_pcl(lynx, lynx->async.pcl_start, 3);
}
@@ -440,8 +451,8 @@ static int lynx_initialize(struct hpsb_host *host)
int i;
u32 *pcli;
- lynx->async_queue = NULL;
- spin_lock_init(&lynx->async_queue_lock);
+ lynx->async.queue = NULL;
+ spin_lock_init(&lynx->async.queue_lock);
spin_lock_init(&lynx->phy_reg_lock);
pcl.next = pcl_bus(lynx, lynx->rcv_pcl);
@@ -456,13 +467,13 @@ static int lynx_initialize(struct hpsb_host *host)
pcl.buffer[0].control = PCL_CMD_RCV | PCL_BIGENDIAN | 16;
pcl.buffer[1].control = PCL_LAST_BUFF | 4080;
#endif
- pcl.buffer[0].pointer = virt_to_bus(lynx->rcv_page);
- pcl.buffer[1].pointer = virt_to_bus(lynx->rcv_page) + 16;
+ 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->async.pcl);
+ pcl.async_error_next = pcl_bus(lynx, lynx->async.pcl);
+ put_pcl(lynx, lynx->async.pcl_start, &pcl);
pcl.next = PCL_NEXT_INVALID;
pcl.async_error_next = PCL_NEXT_INVALID;
@@ -476,7 +487,7 @@ static int lynx_initialize(struct hpsb_host *host)
int page = i / ISORCV_PER_PAGE;
int sec = i % ISORCV_PER_PAGE;
- pcl.buffer[0].pointer = virt_to_bus(lynx->iso_rcv.page[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);
@@ -542,7 +553,9 @@ static void lynx_release(struct hpsb_host *host)
lynx = host->hostdata;
remove_card(lynx);
} else {
+#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME);
+#endif
}
}
@@ -568,13 +581,13 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
cpu_to_be32s(&packet->header[3]);
}
- spin_lock_irqsave(&lynx->async_queue_lock, flags);
+ spin_lock_irqsave(&lynx->async.queue_lock, flags);
- if (lynx->async_queue == NULL) {
- lynx->async_queue = packet;
+ if (lynx->async.queue == NULL) {
+ lynx->async.queue = packet;
send_next_async(lynx);
} else {
- p = lynx->async_queue;
+ p = lynx->async.queue;
while (p->xnext != NULL) {
p = p->xnext;
}
@@ -582,7 +595,7 @@ static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
p->xnext = packet;
}
- spin_unlock_irqrestore(&lynx->async_queue_lock, flags);
+ spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
return 1;
}
@@ -637,13 +650,13 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
break;
case CANCEL_REQUESTS:
- spin_lock_irqsave(&lynx->async_queue_lock, flags);
+ spin_lock_irqsave(&lynx->async.queue_lock, flags);
reg_write(lynx, DMA3_CHAN_CTRL, 0);
- packet = lynx->async_queue;
- lynx->async_queue = NULL;
+ packet = lynx->async.queue;
+ lynx->async.queue = NULL;
- spin_unlock_irqrestore(&lynx->async_queue_lock, flags);
+ spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
while (packet != NULL) {
lastpacket = packet;
@@ -696,7 +709,7 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
* IEEE-1394 functionality section END *
***************************************/
-
+#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
/* VFS functions for local bus / aux device access. Access to those
* is implemented as a character device instead of block devices
* because buffers are not wanted for this. Therefore llseek (from
@@ -710,7 +723,7 @@ static ssize_t mem_write(struct file*, const char*, size_t, loff_t*);
static struct file_operations aux_ops = {
- owner: THIS_MODULE,
+ OWNER_THIS_MODULE
/* FIXME: should have custom llseek with bounds checking */
read: mem_read,
write: mem_write,
@@ -735,18 +748,23 @@ static int mem_open(struct inode *inode, struct file *file)
enum { rom, aux, ram } type;
struct memdata *md;
+ V22_COMPAT_MOD_INC_USE_COUNT;
+
if (cid < PCILYNX_MINOR_AUX_START) {
/* just for completeness */
+ V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENXIO;
} else if (cid < PCILYNX_MINOR_ROM_START) {
cid -= PCILYNX_MINOR_AUX_START;
if (cid >= num_of_cards || !cards[cid].aux_port) {
+ V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENXIO;
}
type = aux;
} else if (cid < PCILYNX_MINOR_RAM_START) {
cid -= PCILYNX_MINOR_ROM_START;
if (cid >= num_of_cards || !cards[cid].local_rom) {
+ V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENXIO;
}
type = rom;
@@ -755,6 +773,7 @@ static int mem_open(struct inode *inode, struct file *file)
* It is currently used inside the driver! */
cid -= PCILYNX_MINOR_RAM_START;
if (cid >= num_of_cards || !cards[cid].local_ram) {
+ V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENXIO;
}
type = ram;
@@ -762,6 +781,7 @@ static int mem_open(struct inode *inode, struct file *file)
md = (struct memdata *)vmalloc(sizeof(struct memdata));
if (md == NULL) {
+ V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENOMEM;
}
@@ -793,6 +813,7 @@ static int mem_release(struct inode *inode, struct file *file)
vfree(md);
+ V22_COMPAT_MOD_DEC_USE_COUNT;
return 0;
}
@@ -801,16 +822,15 @@ static unsigned int aux_poll(struct file *file, poll_table *pt)
struct memdata *md = (struct memdata *)file->private_data;
int cid = md->cid;
unsigned int mask;
- int intr_seen;
/* reading and writing is always allowed */
mask = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
if (md->type == aux) {
poll_wait(file, &cards[cid].aux_intr_wait, pt);
- intr_seen = atomic_read(&cards[cid].aux_intr_seen);
- if (atomic_read(&md->aux_intr_last_seen) != intr_seen) {
+ if (atomic_read(&md->aux_intr_last_seen)
+ != atomic_read(&cards[cid].aux_intr_seen)) {
mask |= POLLPRI;
atomic_inc(&md->aux_intr_last_seen);
}
@@ -956,7 +976,7 @@ static ssize_t mem_read(struct file *file, char *buffer, size_t count,
}
while (bcount >= 4) {
- retval = mem_dmaread(md, virt_to_phys(md->lynx->mem_dma_buffer)
+ retval = mem_dmaread(md, md->lynx->mem_dma_buffer_dma
+ count - bcount, bcount, off);
if (retval < 0) return retval;
@@ -1008,7 +1028,7 @@ static ssize_t mem_write(struct file *file, const char *buffer, size_t count,
file->f_pos += count;
return count;
}
-
+#endif /* CONFIG_IEEE1394_PCILYNX_PORTS */
/********************************************************
@@ -1028,6 +1048,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
reg_write(lynx, LINK_INT_STATUS, linkint);
//printk("-%d- one interrupt: 0x%08x / 0x%08x\n", lynx->id, intmask, linkint);
+#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
if (intmask & PCI_INT_AUX_INT) {
atomic_inc(&lynx->aux_intr_seen);
wake_up_interruptible(&lynx->aux_intr_wait);
@@ -1036,6 +1057,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
if (intmask & PCI_INT_DMA0_HLT) {
wake_up_interruptible(&lynx->mem_dma_intr_wait);
}
+#endif
if (intmask & PCI_INT_1394) {
@@ -1108,17 +1130,24 @@ static void lynx_irq_handler(int irq, void *dev_id,
u32 ack;
struct hpsb_packet *packet;
- spin_lock(&lynx->async_queue_lock);
+ spin_lock(&lynx->async.queue_lock);
ack = reg_read(lynx, DMA3_CHAN_STAT);
- packet = lynx->async_queue;
- lynx->async_queue = packet->xnext;
+ packet = lynx->async.queue;
+ lynx->async.queue = packet->xnext;
+
+ 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 (lynx->async_queue != NULL) {
+ if (lynx->async.queue != NULL) {
send_next_async(lynx);
}
- spin_unlock(&lynx->async_queue_lock);
+ spin_unlock(&lynx->async.queue_lock);
if (ack & DMA_CHAN_STAT_SPECIALACK) {
ack = (ack >> 15) & 0xf;
@@ -1150,7 +1179,7 @@ static void lynx_irq_handler(int irq, void *dev_id,
|| (*q_data >> 4 & 0xf) == TCODE_WRITEQ) {
cpu_to_be32s(q_data + 3);
}
- hpsb_packet_received(host, q_data, stat & 0x1fff);
+ hpsb_packet_received(host, q_data, stat & 0x1fff, 0);
}
run_pcl(lynx, lynx->rcv_pcl_start, 1);
@@ -1184,7 +1213,8 @@ static void iso_rcv_bh(struct ti_lynx *lynx)
"iso receive error on %d to 0x%p", idx, data);
} else {
hpsb_packet_received(lynx->host, data,
- lynx->iso_rcv.stat[idx] & 0x1fff);
+ lynx->iso_rcv.stat[idx] & 0x1fff,
+ 0);
}
spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
@@ -1210,12 +1240,11 @@ static int add_card(struct pci_dev *dev)
} while (0)
struct ti_lynx *lynx; /* shortcut to currently handled device */
- unsigned long page;
unsigned int i;
if (num_of_cards == MAX_PCILYNX_CARDS) {
PRINT_G(KERN_WARNING, "cannot handle more than %d cards. "
- "Adjust MAX_PCILYNX_CARDS in ti_pcilynx.h.",
+ "Adjust MAX_PCILYNX_CARDS in pcilynx.h.",
MAX_PCILYNX_CARDS);
return 1;
}
@@ -1225,6 +1254,10 @@ static int add_card(struct pci_dev *dev)
lynx->id = num_of_cards-1;
lynx->dev = dev;
+ if (!pci_dma_supported(dev, 0xffffffff)) {
+ FAIL("DMA address limits not supported for PCILynx hardware %d",
+ lynx->id);
+ }
if (pci_enable_device(dev)) {
FAIL("failed to enable PCILynx hardware %d", lynx->id);
}
@@ -1239,61 +1272,50 @@ static int add_card(struct pci_dev *dev)
}
#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
- lynx->pcl_mem = kmalloc(8 * sizeof(lynx->pcl_bmap)
- * sizeof(struct ti_pcl), GFP_KERNEL);
+ 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",
- 8 * sizeof(lynx->pcl_bmap) * sizeof(struct ti_pcl),
+ "allocated PCL memory %d Bytes @ 0x%p", LOCALRAM_SIZE,
lynx->pcl_mem);
} else {
FAIL("failed to allocate PCL memory area");
}
#endif
- lynx->mem_dma_buffer = kmalloc(65536, GFP_KERNEL);
- if (lynx->mem_dma_buffer != NULL) {
- lynx->state = have_aux_buf;
- } else {
+#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
+ lynx->mem_dma_buffer = pci_alloc_consistent(dev, 65536,
+ &lynx->mem_dma_buffer_dma);
+ if (lynx->mem_dma_buffer == NULL) {
FAIL("failed to allocate DMA buffer for aux");
}
+ lynx->state = have_aux_buf;
+#endif
- page = get_free_page(GFP_KERNEL);
- if (page != 0) {
- lynx->rcv_page = (void *)page;
- lynx->state = have_1394_buffers;
- } else {
+ 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++) {
- page = get_free_page(GFP_KERNEL);
- if (page != 0) {
- lynx->iso_rcv.page[i] = (void *)page;
- } else {
+ 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");
}
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
- lynx->registers = ioremap_nocache(dev->base_address[0],
- PCILYNX_MAX_REGISTER);
- lynx->local_ram = ioremap(dev->base_address[1], PCILYNX_MAX_MEMORY);
- lynx->aux_port = ioremap(dev->base_address[2], PCILYNX_MAX_MEMORY);
-#else
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);
-#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,15)
- lynx->local_rom = ioremap(dev->rom_address, PCILYNX_MAX_MEMORY);
-#else
+ 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);
-#endif
lynx->state = have_iomappings;
if (lynx->registers == NULL) {
@@ -1309,15 +1331,17 @@ static int add_card(struct pci_dev *dev)
/* alloc_pcl return values are not checked, it is expected that the
* provided PCL space is sufficient for the initial allocations */
+#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
if (lynx->aux_port != NULL) {
lynx->dmem_pcl = alloc_pcl(lynx);
aux_setup_pcls(lynx);
sema_init(&lynx->mem_dma_mutex, 1);
}
+#endif
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->async.pcl = alloc_pcl(lynx);
+ lynx->async.pcl_start = alloc_pcl(lynx);
for (i = 0; i < NUM_ISORCV_PCL; i++) {
lynx->iso_rcv.pcl[i] = alloc_pcl(lynx);
@@ -1330,8 +1354,10 @@ static int add_card(struct pci_dev *dev)
reg_write(lynx, PCI_INT_ENABLE, PCI_INT_AUX_INT | PCI_INT_DMA_ALL);
+#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
init_waitqueue_head(&lynx->mem_dma_intr_wait);
init_waitqueue_head(&lynx->aux_intr_wait);
+#endif
lynx->iso_rcv.tq.routine = (void (*)(void*))iso_rcv_bh;
lynx->iso_rcv.tq.data = lynx;
@@ -1372,15 +1398,22 @@ static void remove_card(struct ti_lynx *lynx)
case have_1394_buffers:
for (i = 0; i < ISORCV_PAGES; i++) {
if (lynx->iso_rcv.page[i]) {
- free_page((unsigned long)lynx->iso_rcv.page[i]);
+ pci_free_consistent(lynx->dev, PAGE_SIZE,
+ lynx->iso_rcv.page[i],
+ lynx->iso_rcv.page_dma[i]);
}
}
- free_page((unsigned long)lynx->rcv_page);
+ pci_free_consistent(lynx->dev, PAGE_SIZE, lynx->rcv_page,
+ lynx->rcv_page_dma);
case have_aux_buf:
- kfree(lynx->mem_dma_buffer);
+#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
+ pci_free_consistent(lynx->dev, 65536, lynx->mem_dma_buffer,
+ lynx->mem_dma_buffer_dma);
+#endif
case have_pcl_mem:
#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
- kfree(lynx->pcl_mem);
+ pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem,
+ lynx->pcl_mem_dma);
#endif
case have_intr:
free_irq(lynx->dev->irq, lynx);
@@ -1416,11 +1449,13 @@ static int init_driver()
return -ENXIO;
}
+#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
if (register_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME, &aux_ops)) {
PRINT_G(KERN_ERR, "allocation of char major number %d failed",
PCILYNX_MAJOR);
return -EBUSY;
}
+#endif
return 0;
}
diff --git a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h
index cf45d8d0a..ccb5a9f0b 100644
--- a/drivers/ieee1394/pcilynx.h
+++ b/drivers/ieee1394/pcilynx.h
@@ -12,7 +12,7 @@
#define PCI_DEVICE_ID_TI_PCILYNX 0x8000
#define MAX_PCILYNX_CARDS 4
-#define LOCALRAM_SIZE 64
+#define LOCALRAM_SIZE 4096
#define NUM_ISORCV_PCL 4
#define MAX_ISORCV_SIZE 2048
@@ -50,23 +50,27 @@ struct ti_lynx {
void *aux_port;
+#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
atomic_t aux_intr_seen;
wait_queue_head_t aux_intr_wait;
void *mem_dma_buffer;
+ dma_addr_t mem_dma_buffer_dma;
struct semaphore mem_dma_mutex;
wait_queue_head_t mem_dma_intr_wait;
+#endif
/*
- * use local RAM of LOCALRAM_SIZE (in kB) for PCLs, which allows for
+ * 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];
+ u8 pcl_bmap[LOCALRAM_SIZE / 1024];
-#ifndef CONFIG_IEEE1394_LYNXRAM
+#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
/* point to PCLs memory area if needed */
void *pcl_mem;
+ dma_addr_t pcl_mem_dma;
#endif
/* PCLs for local mem / aux transfers */
@@ -81,16 +85,21 @@ struct ti_lynx {
pcl_t rcv_pcl_start, rcv_pcl;
void *rcv_page;
+ dma_addr_t rcv_page_dma;
int rcv_active;
- pcl_t async_pcl_start, async_pcl;
- struct hpsb_packet *async_queue;
- spinlock_t async_queue_lock;
+ struct {
+ pcl_t pcl_start, pcl;
+ struct hpsb_packet *queue;
+ spinlock_t queue_lock;
+ dma_addr_t header_dma, data_dma;
+ } async;
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;
@@ -381,11 +390,7 @@ inline static void get_pcl(const struct ti_lynx *lynx, pcl_t pclid,
inline static u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
- return lynx->dev->base_address[1] + pclid * sizeof(struct ti_pcl);
-#else
- return lynx->dev->resource[1].start + pclid * sizeof(struct ti_pcl);
-#endif
+ return pci_resource_start(lynx->dev, 1) + pclid * sizeof(struct ti_pcl);
}
#else /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */
@@ -407,7 +412,7 @@ inline static void get_pcl(const struct ti_lynx *lynx, pcl_t pclid,
inline static u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
{
- return virt_to_bus(lynx->pcl_mem) + pclid * sizeof(struct ti_pcl);
+ return lynx->pcl_mem_dma + pclid * sizeof(struct ti_pcl);
}
#endif /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 523f5d393..83c1169fe 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -4,6 +4,9 @@
* Raw interface to the bus
*
* Copyright (C) 1999, 2000 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/kernel.h>
@@ -13,8 +16,13 @@
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/module.h>
+#include <linux/version.h>
#include <asm/uaccess.h>
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
+#include <linux/devfs_fs_kernel.h>
+#endif
+
#include "ieee1394.h"
#include "ieee1394_types.h"
#include "ieee1394_core.h"
@@ -24,6 +32,8 @@
#include "raw1394.h"
+static devfs_handle_t devfs_handle = NULL;
+
LIST_HEAD(host_info_list);
static int host_count = 0;
spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
@@ -257,7 +267,7 @@ static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
req->req.type = RAW1394_REQ_ISO_RECEIVE;
req->req.generation = get_hpsb_generation();
req->req.misc = 0;
- req->req.recvb = fi->iso_buffer;
+ req->req.recvb = (u64)fi->iso_buffer;
req->req.length = MIN(length, fi->iso_buffer_length);
list_add_tail(&req->list, &reqs);
@@ -326,7 +336,7 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
req->req.type = RAW1394_REQ_FCP_REQUEST;
req->req.generation = get_hpsb_generation();
req->req.misc = nodeid | (direction << 16);
- req->req.recvb = (quadlet_t *)fi->fcp_buffer;
+ req->req.recvb = (u64)fi->fcp_buffer;
req->req.length = length;
list_add_tail(&req->list, &reqs);
@@ -343,7 +353,7 @@ static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
}
-static int dev_read(struct file *file, char *buffer, size_t count,
+static ssize_t dev_read(struct file *file, char *buffer, size_t count,
loff_t *offset_is_ignored)
{
struct file_info *fi = (struct file_info *)file->private_data;
@@ -376,7 +386,8 @@ static int dev_read(struct file *file, char *buffer, size_t count,
req = list_entry(lh, struct pending_request, list);
if (req->req.length) {
- if (copy_to_user(req->req.recvb, req->data, req->req.length)) {
+ if (copy_to_user((void *)req->req.recvb, req->data,
+ req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
}
}
@@ -507,7 +518,7 @@ static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
} else {
fi->listen_channels |= 1ULL << channel;
hpsb_listen_channel(hl_handle, fi->host, channel);
- fi->iso_buffer = req->req.recvb;
+ fi->iso_buffer = (void *)req->req.recvb;
fi->iso_buffer_length = req->req.length;
}
} else {
@@ -563,7 +574,7 @@ static int handle_local_request(struct file_info *fi,
break;
case RAW1394_REQ_ASYNC_WRITE:
- if (copy_from_user(req->data, req->req.sendb,
+ if (copy_from_user(req->data, (void *)req->req.sendb,
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
break;
@@ -588,7 +599,7 @@ static int handle_local_request(struct file_info *fi,
}
}
- if (copy_from_user(req->data, req->req.sendb,
+ if (copy_from_user(req->data, (void *)req->req.sendb,
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
break;
@@ -646,7 +657,7 @@ static int handle_remote_request(struct file_info *fi,
if (req->req.length == 4) {
quadlet_t x;
- if (copy_from_user(&x, req->req.sendb, 4)) {
+ if (copy_from_user(&x, (void *)req->req.sendb, 4)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
}
@@ -658,7 +669,7 @@ static int handle_remote_request(struct file_info *fi,
req->req.length);
if (!packet) return -ENOMEM;
- if (copy_from_user(packet->data, req->req.sendb,
+ if (copy_from_user(packet->data, (void *)req->req.sendb,
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
}
@@ -684,7 +695,7 @@ static int handle_remote_request(struct file_info *fi,
req->req.misc);
if (!packet) return -ENOMEM;
- if (copy_from_user(packet->data, req->req.sendb,
+ if (copy_from_user(packet->data, (void *)req->req.sendb,
req->req.length)) {
req->req.error = RAW1394_ERROR_MEMFAULT;
break;
@@ -761,12 +772,12 @@ static int state_connected(struct file_info *fi, struct pending_request *req)
}
-static int dev_write(struct file *file, const char *buffer, size_t count,
+static ssize_t dev_write(struct file *file, const char *buffer, size_t count,
loff_t *offset_is_ignored)
{
struct file_info *fi = (struct file_info *)file->private_data;
struct pending_request *req;
- int retval = 0;
+ ssize_t retval = 0;
if (count != sizeof(struct raw1394_request)) {
return -EINVAL;
@@ -828,8 +839,11 @@ static int dev_open(struct inode *inode, struct file *file)
return -ENXIO;
}
+ V22_COMPAT_MOD_INC_USE_COUNT;
+
fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
if (fi == NULL) {
+ V22_COMPAT_MOD_DEC_USE_COUNT;
return -ENOMEM;
}
@@ -898,6 +912,7 @@ static int dev_release(struct inode *inode, struct file *file)
kfree(fi);
+ V22_COMPAT_MOD_DEC_USE_COUNT;
return 0;
}
@@ -910,7 +925,7 @@ static struct hpsb_highlevel_ops hl_ops = {
};
static struct file_operations file_ops = {
- owner: THIS_MODULE,
+ OWNER_THIS_MODULE
read: dev_read,
write: dev_write,
poll: dev_poll,
@@ -926,18 +941,24 @@ int init_raw1394(void)
return -ENOMEM;
}
- if (register_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME,
- &file_ops)) {
- HPSB_ERR("raw1394 failed to allocate device major");
+ devfs_handle = devfs_register(NULL, RAW1394_DEVICE_NAME, DEVFS_FL_NONE,
+ RAW1394_DEVICE_MAJOR, 0,
+ S_IFCHR | S_IRUSR | S_IWUSR, &file_ops,
+ NULL);
+
+ if (devfs_register_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME,
+ &file_ops)) {
+ HPSB_ERR("raw1394 failed to register /dev/raw1394 device");
return -EBUSY;
}
-
+ printk(KERN_INFO "raw1394: /dev/%s device initialized\n", RAW1394_DEVICE_NAME);
return 0;
}
void cleanup_raw1394(void)
{
- unregister_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME);
+ devfs_unregister_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME);
+ devfs_unregister(devfs_handle);
hpsb_unregister_highlevel(hl_handle);
}
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
index f23bfc051..b0d819429 100644
--- a/drivers/ieee1394/raw1394.h
+++ b/drivers/ieee1394/raw1394.h
@@ -1,11 +1,10 @@
-
#ifndef IEEE1394_RAW1394_H
#define IEEE1394_RAW1394_H
#define RAW1394_DEVICE_MAJOR 171
#define RAW1394_DEVICE_NAME "raw1394"
-#define RAW1394_KERNELAPI_VERSION 2
+#define RAW1394_KERNELAPI_VERSION 3
/* state: opened */
#define RAW1394_REQ_INITIALIZE 1
@@ -45,24 +44,27 @@
#define RAW1394_ERROR_TIMEOUT (-1102)
+#include <asm/types.h>
+
struct raw1394_request {
- int type;
- int error;
- int misc;
+ __u32 type;
+ __s32 error;
+ __u32 misc;
+
+ __u32 generation;
+ __u32 length;
- unsigned int generation;
- octlet_t address;
+ __u64 address;
- unsigned long tag;
+ __u64 tag;
- size_t length;
- quadlet_t *sendb;
- quadlet_t *recvb;
+ __u64 sendb;
+ __u64 recvb;
};
struct raw1394_khost_list {
- int nodes;
- char name[32];
+ __u32 nodes;
+ __u8 name[32];
};
#ifdef __KERNEL__
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
new file mode 100644
index 000000000..9f00fd3f0
--- /dev/null
+++ b/drivers/ieee1394/video1394.c
@@ -0,0 +1,1266 @@
+/*
+ * 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.
+ */
+
+#include <linux/config.h>
+#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/pci.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <asm/byteorder.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/tqueue.h>
+#include <linux/delay.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/sched.h>
+#include <asm/segment.h>
+#include <linux/types.h>
+#include <linux/wrapper.h>
+#include <linux/vmalloc.h>
+
+#include "ieee1394.h"
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "video1394.h"
+
+#include "ohci1394.h"
+
+#define VIDEO1394_MAJOR 172
+#define ISO_CHANNELS 64
+#define ISO_RECEIVE 0
+#define ISO_TRANSMIT 1
+
+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 ctx;
+ int channel;
+ int last_buffer;
+ unsigned int num_desc;
+ unsigned int buf_size;
+ unsigned int frame_size;
+ unsigned int packet_size;
+ unsigned int left_size;
+ unsigned int nb_cmd;
+ unsigned char *buf;
+ struct dma_cmd **ir_prg;
+ struct it_dma_prg **it_prg;
+ unsigned int *buffer_status;
+ int ctrlClear;
+ int ctrlSet;
+ int cmdPtr;
+ int ctxMatch;
+ wait_queue_head_t waitq;
+};
+
+struct video_card {
+ struct ti_ohci *ohci;
+
+ struct dma_iso_ctx **ir_context;
+ struct dma_iso_ctx **it_context;
+ 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...)
+#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)
+
+void irq_handler(int card, quadlet_t isoRecvIntEvent,
+ quadlet_t isoXmitIntEvent);
+
+static struct video_card video_cards[MAX_OHCI1394_CARDS];
+static int num_of_video_cards = 0;
+static struct video_template video_tmpl = { irq_handler };
+
+/* Taken from bttv.c */
+/*******************************/
+/* Memory management functions */
+/*******************************/
+
+#define MDEBUG(x) do { } while(0) /* Debug memory management */
+
+/* [DaveM] I've recoded most of this so that:
+ * 1) It's easier to tell what is happening
+ * 2) It's more portable, especially for translating things
+ * out of vmalloc mapped areas in the kernel.
+ * 3) Less unnecessary translations happen.
+ *
+ * The code used to assume that the kernel vmalloc mappings
+ * existed in the page tables of every process, this is simply
+ * not guarenteed. We now use pgd_offset_k which is the
+ * defined way to get at the kernel page tables.
+ */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+#define page_address(x) (x)
+#endif
+
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
+{
+ unsigned long ret = 0UL;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ if (!pgd_none(*pgd)) {
+ pmd = pmd_offset(pgd, adr);
+ if (!pmd_none(*pmd)) {
+ ptep = pte_offset(pmd, adr);
+ pte = *ptep;
+ if(pte_present(pte))
+ ret = (page_address(pte_page(pte))|
+ (adr&(PAGE_SIZE-1)));
+ }
+ }
+ MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+static inline unsigned long uvirt_to_bus(unsigned long adr)
+{
+ unsigned long kva, ret;
+
+ kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
+ ret = virt_to_bus((void *)kva);
+ MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+static inline unsigned long kvirt_to_bus(unsigned long adr)
+{
+ unsigned long va, kva, ret;
+
+ va = VMALLOC_VMADDR(adr);
+ kva = uvirt_to_kva(pgd_offset_k(va), va);
+ ret = virt_to_bus((void *)kva);
+ MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+ unsigned long va, kva, ret;
+
+ va = VMALLOC_VMADDR(adr);
+ kva = uvirt_to_kva(pgd_offset_k(va), va);
+ ret = __pa(kva);
+ MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
+ return ret;
+}
+
+static void * rvmalloc(unsigned long size)
+{
+ void * mem;
+ unsigned long adr, page;
+
+ mem=vmalloc(size);
+ if (mem)
+ {
+ memset(mem, 0, size); /* Clear the ram out,
+ no junk to the user */
+ adr=(unsigned long) mem;
+ while (size > 0)
+ {
+ page = kvirt_to_pa(adr);
+ mem_map_reserve(MAP_NR(__va(page)));
+ adr+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ }
+ return mem;
+}
+
+static void rvfree(void * mem, unsigned long size)
+{
+ unsigned long adr, page;
+
+ if (mem)
+ {
+ adr=(unsigned long) mem;
+ while (size > 0)
+ {
+ page = kvirt_to_pa(adr);
+ mem_map_unreserve(MAP_NR(__va(page)));
+ adr+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ vfree(mem);
+ }
+}
+
+static int free_dma_iso_ctx(struct dma_iso_ctx **d)
+{
+ int i;
+ struct ti_ohci *ohci;
+
+ if ((*d)==NULL) return -1;
+
+ ohci = (struct ti_ohci *)(*d)->ohci;
+
+ DBGMSG(ohci->id, "Freeing dma_iso_ctx %d", (*d)->ctx);
+
+ ohci1394_stop_context(ohci, (*d)->ctrlClear, NULL);
+
+ if ((*d)->buf) rvfree((void *)(*d)->buf,
+ (*d)->num_desc * (*d)->buf_size);
+
+ if ((*d)->ir_prg) {
+ for (i=0;i<(*d)->num_desc;i++)
+ if ((*d)->ir_prg[i]) kfree((*d)->ir_prg[i]);
+ kfree((*d)->ir_prg);
+ }
+
+ if ((*d)->it_prg) {
+ for (i=0;i<(*d)->num_desc;i++)
+ if ((*d)->it_prg[i]) kfree((*d)->it_prg[i]);
+ kfree((*d)->it_prg);
+ }
+
+ if ((*d)->buffer_status)
+ kfree((*d)->buffer_status);
+
+ kfree(*d);
+ *d = NULL;
+
+ return 0;
+}
+
+static struct dma_iso_ctx *
+alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int ctx, int num_desc,
+ int buf_size, int channel, unsigned int packet_size)
+{
+ struct dma_iso_ctx *d=NULL;
+ int i;
+
+ d = (struct dma_iso_ctx *)kmalloc(sizeof(struct dma_iso_ctx),
+ GFP_KERNEL);
+ memset(d, 0, sizeof(struct dma_iso_ctx));
+
+ if (d==NULL) {
+ PRINT(KERN_ERR, ohci->id, "failed to allocate dma_iso_ctx");
+ return NULL;
+ }
+
+ d->ohci = (void *)ohci;
+ d->ctx = ctx;
+ d->channel = channel;
+ d->num_desc = num_desc;
+ d->frame_size = buf_size;
+ if (buf_size%PAGE_SIZE)
+ d->buf_size = buf_size + PAGE_SIZE - (buf_size%PAGE_SIZE);
+ else
+ d->buf_size = buf_size;
+ d->last_buffer = -1;
+ d->buf = NULL;
+ d->ir_prg = NULL;
+ init_waitqueue_head(&d->waitq);
+
+ d->buf = rvmalloc(d->num_desc * d->buf_size);
+
+ if (d->buf == NULL) {
+ PRINT(KERN_ERR, ohci->id, "failed to allocate dma buffer");
+ free_dma_iso_ctx(&d);
+ return NULL;
+ }
+ memset(d->buf, 0, d->num_desc * d->buf_size);
+
+ if (type == 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 = kmalloc(d->num_desc * sizeof(struct dma_cmd *),
+ GFP_KERNEL);
+
+ if (d->ir_prg == NULL) {
+ PRINT(KERN_ERR, ohci->id,
+ "failed to allocate dma ir prg");
+ free_dma_iso_ctx(&d);
+ return NULL;
+ }
+ memset(d->ir_prg, 0, d->num_desc * sizeof(struct dma_cmd *));
+
+ 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++) {
+ d->ir_prg[i] = kmalloc(d->nb_cmd *
+ sizeof(struct dma_cmd),
+ GFP_KERNEL);
+ if (d->ir_prg[i] == NULL) {
+ PRINT(KERN_ERR, ohci->id,
+ "failed to allocate dma ir prg");
+ free_dma_iso_ctx(&d);
+ return NULL;
+ }
+ }
+ }
+ else { /* 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 = kmalloc(d->num_desc * sizeof(struct it_dma_prg *),
+ GFP_KERNEL);
+
+ if (d->it_prg == NULL) {
+ PRINT(KERN_ERR, ohci->id,
+ "failed to allocate dma it prg");
+ free_dma_iso_ctx(&d);
+ return NULL;
+ }
+ memset(d->it_prg, 0, d->num_desc*sizeof(struct it_dma_prg *));
+
+ d->packet_size = packet_size;
+
+ if (PAGE_SIZE % packet_size || packet_size>2048) {
+ PRINT(KERN_ERR, ohci->id,
+ "Packet size %d not yet supported\n",
+ packet_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++) {
+ d->it_prg[i] = kmalloc(d->nb_cmd *
+ sizeof(struct it_dma_prg),
+ GFP_KERNEL);
+ if (d->it_prg[i] == NULL) {
+ PRINT(KERN_ERR, ohci->id,
+ "failed to allocate dma it prg");
+ free_dma_iso_ctx(&d);
+ return NULL;
+ }
+ }
+ }
+
+ d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int),
+ GFP_KERNEL);
+
+ if (d->buffer_status == NULL) {
+ PRINT(KERN_ERR, ohci->id, "failed to allocate dma ir prg");
+ free_dma_iso_ctx(&d);
+ return NULL;
+ }
+ memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
+
+ PRINT(KERN_INFO, ohci->id, "Iso %s DMA: %d buffers "
+ "of size %d allocated for a frame size %d, each with %d prgs",
+ (type==ISO_RECEIVE) ? "receive" : "transmit",
+ d->num_desc, 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 = 4;
+ d->ir_prg[n][1].status = PAGE_SIZE-4;
+ for (i=2;i<d->nb_cmd-1;i++)
+ d->ir_prg[n][i].status = PAGE_SIZE;
+ d->ir_prg[n][i].status = d->left_size;
+}
+
+static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n)
+{
+ struct dma_cmd *ir_prg = d->ir_prg[n];
+ unsigned long buf = (unsigned long)d->buf+n*d->buf_size;
+ int i;
+
+ /* the first descriptor will sync and read only 4 bytes */
+ ir_prg[0].control = (0x280F << 16) | 4;
+ ir_prg[0].address = kvirt_to_bus(buf);
+ ir_prg[0].branchAddress = (virt_to_bus(&(ir_prg[1].control))
+ & 0xfffffff0) | 0x1;
+
+ /* the second descriptor will read PAGE_SIZE-4 bytes */
+ ir_prg[1].control = (0x280C << 16) | (PAGE_SIZE-4);
+ ir_prg[1].address = kvirt_to_bus(buf+4);
+ ir_prg[1].branchAddress = (virt_to_bus(&(ir_prg[2].control))
+ & 0xfffffff0) | 0x1;
+
+ for (i=2;i<d->nb_cmd-1;i++) {
+ ir_prg[i].control = (0x280C << 16) | PAGE_SIZE;
+ ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
+
+ ir_prg[i].branchAddress =
+ (virt_to_bus(&(ir_prg[i+1].control))
+ & 0xfffffff0) | 0x1;
+ }
+
+ /* the last descriptor will generate an interrupt */
+ ir_prg[i].control = (0x283C << 16) | d->left_size;
+ ir_prg[i].address = kvirt_to_bus(buf+(i-1)*PAGE_SIZE);
+}
+
+static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag)
+{
+ 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++) {
+ initialize_dma_ir_prg(d, i);
+ reset_ir_status(d, i);
+ }
+
+ /* Set bufferFill, no header */
+ reg_write(ohci, d->ctrlSet, 0x80000000);
+
+ /* 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 */
+int ir_ctx_listening(struct video_card *video, int channel)
+{
+ int i;
+ struct ti_ohci *ohci = video->ohci;
+
+ for (i=0;i<ohci->nb_iso_rcv_ctx-1;i++)
+ if (video->ir_context[i]) {
+ if (video->ir_context[i]->channel==channel)
+ return i;
+ }
+
+ PRINT(KERN_ERR, ohci->id,
+ "no iso context is listening to channel %d",
+ channel);
+ return -1;
+}
+
+int it_ctx_talking(struct video_card *video, int channel)
+{
+ int i;
+ struct ti_ohci *ohci = video->ohci;
+
+ for (i=0;i<ohci->nb_iso_xmit_ctx;i++)
+ if (video->it_context[i]) {
+ if (video->it_context[i]->channel==channel)
+ return i;
+ }
+
+ PRINT(KERN_ERR, ohci->id,
+ "no iso context is talking to channel %d",
+ channel);
+ return -1;
+}
+
+int wakeup_dma_ir_ctx(struct ti_ohci *ohci, struct dma_iso_ctx *d)
+{
+ int i;
+
+ if (d==NULL) {
+ PRINT(KERN_ERR, ohci->id, "Iso receive event received but "
+ "context not allocated");
+ return -EFAULT;
+ }
+
+ for (i=0;i<d->num_desc;i++) {
+ if (d->ir_prg[i][d->nb_cmd-1].status & 0xFFFF0000) {
+ reset_ir_status(d, i);
+ d->buffer_status[i] = VIDEO1394_BUFFER_READY;
+ }
+ }
+ if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq);
+ return 0;
+}
+
+int wakeup_dma_it_ctx(struct ti_ohci *ohci, struct dma_iso_ctx *d)
+{
+ int i;
+
+ if (d==NULL) {
+ PRINT(KERN_ERR, ohci->id, "Iso transmit event received but "
+ "context not allocated");
+ return -EFAULT;
+ }
+
+ for (i=0;i<d->num_desc;i++) {
+ if (d->it_prg[i][d->nb_cmd-1].end.status & 0xFFFF0000) {
+ d->it_prg[i][d->nb_cmd-1].end.status = 0;
+ d->buffer_status[i] = VIDEO1394_BUFFER_READY;
+ }
+ }
+ if (waitqueue_active(&d->waitq)) wake_up_interruptible(&d->waitq);
+ return 0;
+}
+
+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];
+ unsigned long buf = (unsigned long)d->buf+n*d->buf_size;
+ int i;
+
+ for (i=0;i<d->nb_cmd;i++) {
+
+ it_prg[i].begin.control = OUTPUT_MORE_IMMEDIATE | 8 ;
+ it_prg[i].begin.address = 0;
+
+ it_prg[i].begin.status = 0;
+
+ /* FIXME: what is the tag value + speed selection */
+ it_prg[i].data[0] =
+ (DMA_SPEED_400<<16) | (d->channel<<8) | 0xa0;
+ if (i==0) it_prg[i].data[0] |= sync_tag;
+ it_prg[i].data[1] = d->packet_size << 16;
+ it_prg[i].data[2] = 0;
+ it_prg[i].data[3] = 0;
+
+ it_prg[i].end.control = 0x100c0000;
+ it_prg[i].end.address =
+ kvirt_to_bus(buf+i*d->packet_size);
+
+ if (i<d->nb_cmd-1) {
+ it_prg[i].end.control |= d->packet_size;
+ it_prg[i].begin.branchAddress =
+ (virt_to_bus(&(it_prg[i+1].begin.control))
+ & 0xfffffff0) | 0x3;
+ it_prg[i].end.branchAddress =
+ (virt_to_bus(&(it_prg[i+1].begin.control))
+ & 0xfffffff0) | 0x3;
+ }
+ else {
+ /* the last prg generates an interrupt */
+ it_prg[i].end.control |= 0x08300000 | 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;
+
+#if 0
+ printk("%d:%d: %08x-%08x ctrl %08x brch %08x d0 %08x d1 %08x\n",n,i,
+ virt_to_bus(&(it_prg[i].begin.control)),
+ virt_to_bus(&(it_prg[i].end.control)),
+ it_prg[i].end.control,
+ it_prg[i].end.branchAddress,
+ it_prg[i].data[0], it_prg[i].data[1]);
+#endif
+ }
+}
+
+static void initialize_dma_it_ctx(struct dma_iso_ctx *d, int sync_tag)
+{
+ 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++)
+ initialize_dma_it_prg(d, i, sync_tag);
+
+ /* Set up isoRecvIntMask to generate interrupts */
+ reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx);
+}
+
+static int do_iso_mmap(struct ti_ohci *ohci, struct dma_iso_ctx *d,
+ const char *adr, unsigned long size)
+{
+ unsigned long start=(unsigned long) adr;
+ unsigned long page,pos;
+
+ if (size>d->num_desc * d->buf_size) {
+ PRINT(KERN_ERR, ohci->id,
+ "iso context %d buf size is different from mmap size",
+ d->ctx);
+ return -EINVAL;
+ }
+ if (!d->buf) {
+ PRINT(KERN_ERR, ohci->id,
+ "iso context %d is not allocated", d->ctx);
+ return -EINVAL;
+ }
+
+ pos=(unsigned long) d->buf;
+ while (size > 0) {
+ page = kvirt_to_pa(pos);
+ if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+ return -EAGAIN;
+ start+=PAGE_SIZE;
+ pos+=PAGE_SIZE;
+ size-=PAGE_SIZE;
+ }
+ return 0;
+}
+
+static int video1394_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct video_card *video = &video_cards[MINOR(inode->i_rdev)];
+ struct ti_ohci *ohci= video->ohci;
+
+ switch(cmd)
+ {
+ case VIDEO1394_LISTEN_CHANNEL:
+ case VIDEO1394_TALK_CHANNEL:
+ {
+ struct video1394_mmap v;
+ int i;
+
+ if(copy_from_user(&v, (void *)arg, sizeof(v)))
+ return -EFAULT;
+ if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) {
+ PRINT(KERN_ERR, ohci->id,
+ "iso channel %d out of bound", v.channel);
+ return -EFAULT;
+ }
+ if (test_and_set_bit(v.channel, &ohci->IR_channel_usage)) {
+ PRINT(KERN_ERR, ohci->id,
+ "channel %d is already taken", v.channel);
+ return -EFAULT;
+ }
+
+ if (v.buf_size<=0) {
+ PRINT(KERN_ERR, ohci->id,
+ "Invalid %d length buffer requested",v.buf_size);
+ return -EFAULT;
+ }
+
+ if (v.nb_buffers<=0) {
+ PRINT(KERN_ERR, ohci->id,
+ "Invalid %d buffers requested",v.nb_buffers);
+ return -EFAULT;
+ }
+
+ if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) {
+ PRINT(KERN_ERR, ohci->id,
+ "%d buffers of size %d bytes is too big",
+ v.nb_buffers, v.buf_size);
+ return -EFAULT;
+ }
+
+ if (cmd == VIDEO1394_LISTEN_CHANNEL) {
+ /* find a free iso receive context */
+ for (i=0;i<ohci->nb_iso_rcv_ctx-1;i++)
+ if (video->ir_context[i]==NULL) break;
+
+ if (i==(ohci->nb_iso_rcv_ctx-1)) {
+ PRINT(KERN_ERR, ohci->id,
+ "no iso context available");
+ return -EFAULT;
+ }
+
+ video->ir_context[i] =
+ alloc_dma_iso_ctx(ohci, ISO_RECEIVE, i+1,
+ v.nb_buffers, v.buf_size,
+ v.channel, 0);
+
+ if (video->ir_context[i] == NULL) {
+ PRINT(KERN_ERR, ohci->id,
+ "Couldn't allocate ir context");
+ return -EFAULT;
+ }
+ initialize_dma_ir_ctx(video->ir_context[i],
+ v.sync_tag);
+
+ video->current_ctx = video->ir_context[i];
+
+ v.buf_size = video->ir_context[i]->buf_size;
+
+ PRINT(KERN_INFO, ohci->id,
+ "iso context %d listen on channel %d", i+1,
+ v.channel);
+ }
+ else {
+ /* find a free iso transmit context */
+ for (i=0;i<ohci->nb_iso_xmit_ctx;i++)
+ if (video->it_context[i]==NULL) break;
+
+ if (i==ohci->nb_iso_xmit_ctx) {
+ PRINT(KERN_ERR, ohci->id,
+ "no iso context available");
+ return -EFAULT;
+ }
+
+ video->it_context[i] =
+ alloc_dma_iso_ctx(ohci, ISO_TRANSMIT, i,
+ v.nb_buffers, v.buf_size,
+ v.channel, v.packet_size);
+
+ if (video->it_context[i] == NULL) {
+ PRINT(KERN_ERR, ohci->id,
+ "Couldn't allocate it context");
+ return -EFAULT;
+ }
+ initialize_dma_it_ctx(video->it_context[i],
+ v.sync_tag);
+
+ video->current_ctx = video->it_context[i];
+
+ v.buf_size = video->it_context[i]->buf_size;
+
+ PRINT(KERN_INFO, ohci->id,
+ "iso context %d talk on channel %d", i,
+ v.channel);
+ }
+
+ if(copy_to_user((void *)arg, &v, sizeof(v)))
+ return -EFAULT;
+
+ return 0;
+ }
+ case VIDEO1394_UNLISTEN_CHANNEL:
+ case VIDEO1394_UNTALK_CHANNEL:
+ {
+ int channel;
+ int i;
+
+ if(copy_from_user(&channel, (void *)arg, sizeof(int)))
+ return -EFAULT;
+
+ if (!test_and_clear_bit(channel, &ohci->IR_channel_usage)) {
+ PRINT(KERN_ERR, ohci->id,
+ "channel %d is not being used", channel);
+ return -EFAULT;
+ }
+
+ if (cmd == VIDEO1394_UNLISTEN_CHANNEL) {
+ i = ir_ctx_listening(video, channel);
+ if (i<0) return -EFAULT;
+
+ free_dma_iso_ctx(&video->ir_context[i]);
+
+ PRINT(KERN_INFO, ohci->id,
+ "iso context %d stop listening on channel %d",
+ i+1, channel);
+ }
+ else {
+ i = it_ctx_talking(video, channel);
+ if (i<0) return -EFAULT;
+
+ free_dma_iso_ctx(&video->it_context[i]);
+
+ PRINT(KERN_INFO, ohci->id,
+ "iso context %d stop talking on channel %d",
+ i, channel);
+ }
+
+ return 0;
+ }
+ case VIDEO1394_LISTEN_QUEUE_BUFFER:
+ {
+ struct video1394_wait v;
+ struct dma_iso_ctx *d;
+ int i;
+
+ if(copy_from_user(&v, (void *)arg, sizeof(v)))
+ return -EFAULT;
+
+ i = ir_ctx_listening(video, v.channel);
+ if (i<0) return -EFAULT;
+ d = video->ir_context[i];
+
+ if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+ PRINT(KERN_ERR, ohci->id,
+ "buffer %d out of range",v.buffer);
+ return -EFAULT;
+ }
+
+ if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
+ PRINT(KERN_ERR, ohci->id,
+ "buffer %d is already used",v.buffer);
+ return -EFAULT;
+ }
+
+ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
+
+ if (d->last_buffer>=0)
+ d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =
+ (virt_to_bus(&(d->ir_prg[v.buffer][0].control))
+ & 0xfffffff0) | 0x1;
+
+ d->last_buffer = v.buffer;
+
+ d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;
+
+ if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
+ {
+ DBGMSG(ohci->id, "Starting iso DMA ctx=%d",d->ctx);
+
+ /* Tell the controller where the first program is */
+ reg_write(ohci, d->cmdPtr,
+ virt_to_bus(&(d->ir_prg[v.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)) {
+ PRINT(KERN_INFO, ohci->id,
+ "Waking up iso dma ctx=%d", d->ctx);
+ reg_write(ohci, d->ctrlSet, 0x1000);
+ }
+ }
+ return 0;
+
+ }
+ case VIDEO1394_LISTEN_WAIT_BUFFER:
+ {
+ struct video1394_wait v;
+ struct dma_iso_ctx *d;
+ int i;
+
+ if(copy_from_user(&v, (void *)arg, sizeof(v)))
+ return -EFAULT;
+
+ i = ir_ctx_listening(video, v.channel);
+ if (i<0) return -EFAULT;
+ d = video->ir_context[i];
+
+ if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+ PRINT(KERN_ERR, ohci->id,
+ "buffer %d out of range",v.buffer);
+ return -EFAULT;
+ }
+
+ switch(d->buffer_status[v.buffer]) {
+ case VIDEO1394_BUFFER_READY:
+ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
+ return 0;
+ case VIDEO1394_BUFFER_QUEUED:
+#if 1
+ while(d->buffer_status[v.buffer]!=
+ VIDEO1394_BUFFER_READY) {
+ interruptible_sleep_on(&d->waitq);
+ if(signal_pending(current)) return -EINTR;
+ }
+#else
+ if (wait_event_interruptible(d->waitq,
+ d->buffer_status[v.buffer]
+ == VIDEO1394_BUFFER_READY)
+ == -ERESTARTSYS)
+ return -EINTR;
+#endif
+ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
+ return 0;
+ default:
+ PRINT(KERN_ERR, ohci->id,
+ "buffer %d is not queued",v.buffer);
+ return -EFAULT;
+ }
+ }
+ case VIDEO1394_TALK_QUEUE_BUFFER:
+ {
+ struct video1394_wait v;
+ struct dma_iso_ctx *d;
+ int i;
+
+ if(copy_from_user(&v, (void *)arg, sizeof(v)))
+ return -EFAULT;
+
+ i = it_ctx_talking(video, v.channel);
+ if (i<0) return -EFAULT;
+ d = video->it_context[i];
+
+ if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+ PRINT(KERN_ERR, ohci->id,
+ "buffer %d out of range",v.buffer);
+ return -EFAULT;
+ }
+
+ if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
+ PRINT(KERN_ERR, ohci->id,
+ "buffer %d is already used",v.buffer);
+ return -EFAULT;
+ }
+
+ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
+
+ if (d->last_buffer>=0) {
+ d->it_prg[d->last_buffer]
+ [d->nb_cmd-1].end.branchAddress =
+ (virt_to_bus(&(d->it_prg[v.buffer][0].begin.control))
+ & 0xfffffff0) | 0x3;
+
+ d->it_prg[d->last_buffer]
+ [d->nb_cmd-1].begin.branchAddress =
+ (virt_to_bus(&(d->it_prg[v.buffer][0].begin.control))
+ & 0xfffffff0) | 0x3;
+ }
+ d->last_buffer = v.buffer;
+
+ d->it_prg[d->last_buffer][d->nb_cmd-1].end.branchAddress = 0;
+
+ if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
+ {
+ DBGMSG(ohci->id, "Starting iso transmit DMA ctx=%d",
+ d->ctx);
+
+ /* Tell the controller where the first program is */
+ reg_write(ohci, d->cmdPtr,
+ virt_to_bus(&(d->it_prg[v.buffer][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)) {
+ PRINT(KERN_INFO, ohci->id,
+ "Waking up iso transmit dma ctx=%d",
+ d->ctx);
+ reg_write(ohci, d->ctrlSet, 0x1000);
+ }
+ }
+ return 0;
+
+ }
+ case VIDEO1394_TALK_WAIT_BUFFER:
+ {
+ struct video1394_wait v;
+ struct dma_iso_ctx *d;
+ int i;
+
+ if(copy_from_user(&v, (void *)arg, sizeof(v)))
+ return -EFAULT;
+
+ i = it_ctx_talking(video, v.channel);
+ if (i<0) return -EFAULT;
+ d = video->it_context[i];
+
+ if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+ PRINT(KERN_ERR, ohci->id,
+ "buffer %d out of range",v.buffer);
+ return -EFAULT;
+ }
+
+ switch(d->buffer_status[v.buffer]) {
+ case VIDEO1394_BUFFER_READY:
+ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
+ return 0;
+ case VIDEO1394_BUFFER_QUEUED:
+#if 1
+ while(d->buffer_status[v.buffer]!=
+ VIDEO1394_BUFFER_READY) {
+ interruptible_sleep_on(&d->waitq);
+ if(signal_pending(current)) return -EINTR;
+ }
+#else
+ if (wait_event_interruptible(d->waitq,
+ d->buffer_status[v.buffer]
+ == VIDEO1394_BUFFER_READY)
+ == -ERESTARTSYS)
+ return -EINTR;
+#endif
+ d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
+ return 0;
+ default:
+ PRINT(KERN_ERR, ohci->id,
+ "buffer %d is not queued",v.buffer);
+ return -EFAULT;
+ }
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+/*
+ * This maps the vmalloced and reserved buffer to user space.
+ *
+ * FIXME:
+ * - PAGE_READONLY should suffice!?
+ * - remap_page_range is kind of inefficient for page by page remapping.
+ * But e.g. pte_alloc() does not work in modules ... :-(
+ */
+
+int video1394_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct video_card *video =
+ &video_cards[MINOR(file->f_dentry->d_inode->i_rdev)];
+ struct ti_ohci *ohci= video->ohci;
+
+ PRINT(KERN_INFO, ohci->id, "mmap");
+ if (video->current_ctx == NULL) {
+ PRINT(KERN_ERR, ohci->id, "current iso context not set");
+ return -EINVAL;
+ }
+
+ return do_iso_mmap(ohci, video->current_ctx,
+ (char *)vma->vm_start,
+ (unsigned long)(vma->vm_end-vma->vm_start));
+ return 0;
+}
+
+static int video1394_open(struct inode *inode, struct file *file)
+{
+ int i = MINOR(inode->i_rdev);
+
+ if (i<0 || i>=num_of_video_cards) {
+ PRINT(KERN_ERR, i, "ohci card %d not found", i);
+ return -EIO;
+ }
+
+ V22_COMPAT_MOD_INC_USE_COUNT;
+
+ PRINT(KERN_INFO, i, "open");
+
+ return 0;
+}
+
+static int video1394_release(struct inode *inode, struct file *file)
+{
+ struct video_card *video = &video_cards[MINOR(inode->i_rdev)];
+ struct ti_ohci *ohci= video->ohci;
+ int i;
+
+ for (i=0;i<ohci->nb_iso_rcv_ctx-1;i++)
+ if (video->ir_context[i]) {
+ if (!test_and_clear_bit(
+ video->ir_context[i]->channel,
+ &ohci->IR_channel_usage)) {
+ PRINT(KERN_ERR, ohci->id,
+ "channel %d is not being used",
+ video->ir_context[i]->channel);
+ }
+ PRINT(KERN_INFO, ohci->id,
+ "iso receive context %d stop listening "
+ "on channel %d", i+1,
+ video->ir_context[i]->channel);
+ free_dma_iso_ctx(&video->ir_context[i]);
+ }
+
+ for (i=0;i<ohci->nb_iso_xmit_ctx;i++)
+ if (video->it_context[i]) {
+ if (!test_and_clear_bit(
+ video->it_context[i]->channel,
+ &ohci->IR_channel_usage)) {
+ PRINT(KERN_ERR, ohci->id,
+ "channel %d is not being used",
+ video->it_context[i]->channel);
+ }
+ PRINT(KERN_INFO, ohci->id,
+ "iso transmit context %d stop talking "
+ "on channel %d", i+1,
+ video->it_context[i]->channel);
+ free_dma_iso_ctx(&video->it_context[i]);
+ }
+
+
+ V22_COMPAT_MOD_DEC_USE_COUNT;
+
+ PRINT(KERN_INFO, ohci->id, "release");
+ return 0;
+}
+
+void irq_handler(int card, quadlet_t isoRecvIntEvent,
+ quadlet_t isoXmitIntEvent)
+{
+ int i;
+ struct video_card *video = &video_cards[card];
+
+ DBGMSG(card, "Iso event Recv: %08x Xmit: %08x",
+ isoRecvIntEvent, isoXmitIntEvent);
+
+ for (i=0;i<video->ohci->nb_iso_rcv_ctx-1;i++)
+ if (isoRecvIntEvent & (1<<(i+1)))
+ wakeup_dma_ir_ctx(video->ohci,
+ video->ir_context[i]);
+
+ for (i=0;i<video->ohci->nb_iso_xmit_ctx;i++)
+ if (isoXmitIntEvent & (1<<i))
+ wakeup_dma_it_ctx(video->ohci,
+ video->it_context[i]);
+}
+
+static struct file_operations video1394_fops=
+{
+ OWNER_THIS_MODULE
+ ioctl: video1394_ioctl,
+ mmap: video1394_mmap,
+ open: video1394_open,
+ release: video1394_release
+};
+
+static int video1394_init(int i, struct ti_ohci *ohci)
+{
+ struct video_card *video = &video_cards[i];
+
+ if (ohci1394_register_video(ohci, &video_tmpl)<0) {
+ PRINT(KERN_ERR, i, "register_video failed");
+ return -1;
+ }
+
+ video->ohci = ohci;
+
+ /* Iso receive dma contexts */
+ video->ir_context = (struct dma_iso_ctx **)
+ kmalloc((ohci->nb_iso_rcv_ctx-1)*
+ sizeof(struct dma_iso_ctx *), GFP_KERNEL);
+ if (video->ir_context)
+ memset(video->ir_context, 0,
+ (ohci->nb_iso_rcv_ctx-1)*sizeof(struct dma_iso_ctx *));
+ else {
+ PRINT(KERN_ERR, ohci->id, "Cannot allocate ir_context");
+ return -1;
+ }
+
+ /* Iso transmit dma contexts */
+ video->it_context = (struct dma_iso_ctx **)
+ kmalloc(ohci->nb_iso_xmit_ctx *
+ sizeof(struct dma_iso_ctx *), GFP_KERNEL);
+ if (video->it_context)
+ memset(video->it_context, 0,
+ ohci->nb_iso_xmit_ctx * sizeof(struct dma_iso_ctx *));
+ else {
+ PRINT(KERN_ERR, ohci->id, "Cannot allocate it_context");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void remove_card(struct video_card *video)
+{
+ int i;
+
+ ohci1394_unregister_video(video->ohci, &video_tmpl);
+
+ /* Free the iso receive contexts */
+ if (video->ir_context) {
+ for (i=0;i<video->ohci->nb_iso_rcv_ctx-1;i++) {
+ free_dma_iso_ctx(&video->ir_context[i]);
+ }
+ kfree(video->ir_context);
+ }
+
+ /* Free the iso transmit contexts */
+ if (video->it_context) {
+ for (i=0;i<video->ohci->nb_iso_xmit_ctx;i++) {
+ free_dma_iso_ctx(&video->it_context[i]);
+ }
+ kfree(video->it_context);
+ }
+}
+
+#ifdef MODULE
+
+/* EXPORT_NO_SYMBOLS; */
+
+MODULE_AUTHOR("Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>");
+MODULE_DESCRIPTION("driver for digital video on OHCI board");
+MODULE_SUPPORTED_DEVICE("video1394");
+
+void cleanup_module(void)
+{
+ int i;
+ unregister_chrdev(VIDEO1394_MAJOR, VIDEO1394_DRIVER_NAME);
+
+ for (i=0; i<num_of_video_cards; i++)
+ remove_card(&video_cards[i]);
+
+ printk(KERN_INFO "removed " VIDEO1394_DRIVER_NAME " module\n");
+}
+
+int init_module(void)
+{
+ struct ti_ohci *ohci;
+ int i;
+
+ memset(video_cards, 0, MAX_OHCI1394_CARDS * sizeof(struct video_card));
+ num_of_video_cards = 0;
+
+ for (i=0; i<MAX_OHCI1394_CARDS; i++) {
+ ohci=ohci1394_get_struct(i);
+ if (ohci) {
+ num_of_video_cards++;
+ video1394_init(i, ohci);
+ }
+ }
+
+ if (!num_of_video_cards) {
+ PRINT_G(KERN_INFO, "no ohci card found... init failed");
+ return -EIO;
+ }
+
+ if (register_chrdev(VIDEO1394_MAJOR, VIDEO1394_DRIVER_NAME,
+ &video1394_fops)) {
+ printk("video1394: unable to get major %d\n",
+ VIDEO1394_MAJOR);
+ return -EIO;
+ }
+
+ PRINT_G(KERN_INFO, "initialized with %d ohci cards",
+ num_of_video_cards);
+
+ return 0;
+}
+
+#endif /* MODULE */
+
+
diff --git a/drivers/ieee1394/video1394.h b/drivers/ieee1394/video1394.h
index 47b8e64a2..dc6e5c981 100644
--- a/drivers/ieee1394/video1394.h
+++ b/drivers/ieee1394/video1394.h
@@ -20,6 +20,8 @@
#ifndef _VIDEO_1394_H
#define _VIDEO_1394_H
+#define VIDEO1394_DRIVER_NAME "video1394"
+
#define VIDEO1394_MAX_SIZE 0x400000
enum {
@@ -31,8 +33,12 @@ enum {
enum {
VIDEO1394_LISTEN_CHANNEL = 0,
VIDEO1394_UNLISTEN_CHANNEL,
- VIDEO1394_QUEUE_BUFFER,
- VIDEO1394_WAIT_BUFFER
+ VIDEO1394_LISTEN_QUEUE_BUFFER,
+ VIDEO1394_LISTEN_WAIT_BUFFER,
+ VIDEO1394_TALK_CHANNEL,
+ VIDEO1394_UNTALK_CHANNEL,
+ VIDEO1394_TALK_QUEUE_BUFFER,
+ VIDEO1394_TALK_WAIT_BUFFER
};
struct video1394_mmap {
@@ -40,6 +46,8 @@ struct video1394_mmap {
int sync_tag;
int nb_buffers;
int buf_size;
+ int packet_size;
+ int fps;
};
struct video1394_wait {
@@ -47,4 +55,5 @@ struct video1394_wait {
int buffer;
};
-#endif
+
+#endif