patch-2.4.21 linux-2.4.21/drivers/ieee1394/video1394.c

Next file: linux-2.4.21/drivers/ieee1394/video1394.h
Previous file: linux-2.4.21/drivers/ieee1394/sbp2.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/drivers/ieee1394/video1394.c linux-2.4.21/drivers/ieee1394/video1394.c
@@ -35,11 +35,9 @@
 #include <linux/poll.h>
 #include <linux/smp_lock.h>
 #include <linux/proc_fs.h>
-#include <linux/tqueue.h>
 #include <linux/delay.h>
 #include <linux/devfs_fs_kernel.h>
-
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/wrapper.h>
 #include <linux/vmalloc.h>
@@ -48,10 +46,12 @@
 
 #include "ieee1394.h"
 #include "ieee1394_types.h"
+#include "ieee1394_hotplug.h"
 #include "hosts.h"
 #include "ieee1394_core.h"
 #include "highlevel.h"
 #include "video1394.h"
+#include "dma.h"
 
 #include "ohci1394.h"
 
@@ -65,14 +65,6 @@
 #define vmalloc_32(x) vmalloc(x)
 #endif
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,3))
-#define remap_page_range_1394(vma, start, addr, size, prot) \
-	remap_page_range(start, addr, size, prot)
-#else
-#define remap_page_range_1394(vma, start, addr, size, prot) \
-	remap_page_range(vma, start, addr, size, prot)
-#endif
-
 struct it_dma_prg {
 	struct dma_cmd begin;
 	quadlet_t data[4];
@@ -96,9 +88,14 @@
 	unsigned int packet_size;
 	unsigned int left_size;
 	unsigned int nb_cmd;
-	unsigned char *buf;
+
+	struct dma_region dma;
+
+	struct dma_prog_region *prg_reg;
+
         struct dma_cmd **ir_prg;
 	struct it_dma_prg **it_prg;
+
 	unsigned int *buffer_status;
         struct timeval *buffer_time; /* time when the buffer was received */
 	unsigned int *last_used_cmd; /* For ISO Transmit with 
@@ -117,8 +114,6 @@
 
 struct video_card {
 	struct ti_ohci *ohci;
-	struct list_head list;
-	int id;
 	devfs_handle_t devfs;
 };
 
@@ -155,80 +150,9 @@
 void wakeup_dma_ir_ctx(unsigned long l);
 void wakeup_dma_it_ctx(unsigned long l);
 
-static LIST_HEAD(video1394_cards);
-static spinlock_t video1394_cards_lock = SPIN_LOCK_UNLOCKED;
-
 static devfs_handle_t devfs_handle;
-static struct hpsb_highlevel *hl_handle = NULL;
 
-/* Code taken from bttv.c */
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-static inline unsigned long kvirt_to_bus(unsigned long adr) 
-{
-	unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = virt_to_bus((void *)kva);
-	return ret;
-}
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr) 
-{
-        unsigned long kva, ret;
-
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-        return ret;
-}
-
-static void * rvmalloc(unsigned long size)
-{
-	void * mem;
-	unsigned long adr;
-
-	size=PAGE_ALIGN(size);
-	mem=vmalloc_32(size);
-	if (mem) 
-	{
-		memset(mem, 0, size); /* Clear the ram out, 
-					 no junk to the user */
-	        adr=(unsigned long) mem;
-		while (size > 0) 
-                {
-			mem_map_reserve(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-	}
-	return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
-        unsigned long adr;
-
-	if (mem) 
-	{
-	        adr=(unsigned long) mem;
-		while ((long) size > 0) 
-                {
-			mem_map_unreserve(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-		vfree(mem);
-	}
-}
-/* End of code taken from bttv.c */
+static struct hpsb_highlevel video1394_highlevel;
 
 static int free_dma_iso_ctx(struct dma_iso_ctx *d)
 {
@@ -240,20 +164,19 @@
 	if (d->iso_tasklet.link.next != NULL)
 		ohci1394_unregister_iso_tasklet(d->ohci, &d->iso_tasklet);
 
-	if (d->buf)
-		rvfree((void *)d->buf, d->num_desc * d->buf_size);
+	dma_region_free(&d->dma);
 
-	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->prg_reg) {
+		for (i = 0; i < d->num_desc; i++)
+			dma_prog_region_free(&d->prg_reg[i]);
+		kfree(d->prg_reg);
 	}
 
-	if (d->it_prg) {
-		for (i=0;i<d->num_desc;i++) 
-			if (d->it_prg[i]) kfree(d->it_prg[i]);
+	if (d->ir_prg)
+		kfree(d->ir_prg);
+
+	if (d->it_prg)
 		kfree(d->it_prg);
-	}
 
 	if (d->buffer_status)
 		kfree(d->buffer_status);
@@ -293,18 +216,17 @@
 	d->frame_size = buf_size;
 	d->buf_size = PAGE_ALIGN(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);
+	/* Init the regions for easy cleanup */
+	dma_region_init(&d->dma);
 
-	if (d->buf == NULL) {
+	if (dma_region_alloc(&d->dma, d->num_desc * d->buf_size, ohci->dev,
+			     PCI_DMA_BIDIRECTIONAL)) {
 		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 == OHCI_ISO_RECEIVE)
 		ohci1394_init_iso_tasklet(&d->iso_tasklet, type,
@@ -323,6 +245,17 @@
 	}
 	d->ctx = d->iso_tasklet.context;
 
+	d->prg_reg = kmalloc(d->num_desc * sizeof(struct dma_prog_region),
+			GFP_KERNEL);
+	if (d->prg_reg == NULL) {
+		PRINT(KERN_ERR, ohci->id, "Failed to allocate ir prg regs");
+		free_dma_iso_ctx(d);
+		return NULL;
+	}
+	/* Makes for easier cleanup */
+	for (i = 0; i < d->num_desc; i++)
+		dma_prog_region_init(&d->prg_reg[i]);
+
 	if (type == OHCI_ISO_RECEIVE) {
 		d->ctrlSet = OHCI1394_IsoRcvContextControlSet+32*d->ctx;
 		d->ctrlClear = OHCI1394_IsoRcvContextControlClear+32*d->ctx;
@@ -333,31 +266,27 @@
 				    GFP_KERNEL);
 
 		if (d->ir_prg == NULL) {
-			PRINT(KERN_ERR, ohci->id, 
-			      "Failed to allocate dma ir prg");
+			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");
+		for (i = 0;i < d->num_desc; i++) {
+			if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
+						  sizeof(struct dma_cmd), ohci->dev)) {
+				PRINT(KERN_ERR, ohci->id, "Failed to allocate dma ir prg");
 				free_dma_iso_ctx(d);
 				return NULL;
 			}
+			d->ir_prg[i] = (struct dma_cmd *)d->prg_reg[i].kvirt;
 		}
 
-	}
-	else {  /* OHCI_ISO_TRANSMIT */
+	} else {  /* OHCI_ISO_TRANSMIT */
 		d->ctrlSet = OHCI1394_IsoXmitContextControlSet+16*d->ctx;
 		d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx;
 		d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx;
@@ -388,20 +317,17 @@
 		if (d->frame_size % d->packet_size) {
 			d->nb_cmd++;
 			d->left_size = d->frame_size % d->packet_size;
-		}
-		else
+		} 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");
+		for (i = 0; i < d->num_desc; i++) {
+			if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
+						sizeof(struct it_dma_prg), ohci->dev)) {
+				PRINT(KERN_ERR, ohci->id, "Failed to allocate dma it prg");
 				free_dma_iso_ctx(d);
 				return NULL;
 			}
+			d->it_prg[i] = (struct it_dma_prg *)d->prg_reg[i].kvirt;
 		}
 	}
 
@@ -454,7 +380,7 @@
 	int i;
 	d->ir_prg[n][0].status = cpu_to_le32(4);
 	d->ir_prg[n][1].status = cpu_to_le32(PAGE_SIZE-4);
-	for (i=2;i<d->nb_cmd-1;i++)
+	for (i = 2; i < d->nb_cmd - 1; i++)
 		d->ir_prg[n][i].status = cpu_to_le32(PAGE_SIZE);
 	d->ir_prg[n][i].status = cpu_to_le32(d->left_size);
 }
@@ -462,7 +388,8 @@
 static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
 {
 	struct dma_cmd *ir_prg = d->ir_prg[n];
-	unsigned long buf = (unsigned long)d->buf+n*d->buf_size;
+	struct dma_prog_region *ir_reg = &d->prg_reg[n];
+	unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
 	int i;
 
 	/* the first descriptor will read only 4 bytes */
@@ -473,31 +400,37 @@
 	if (flags & VIDEO1394_SYNC_FRAMES)
 		ir_prg[0].control |= cpu_to_le32(DMA_CTL_WAIT);
 
-	ir_prg[0].address = cpu_to_le32(kvirt_to_bus(buf));
-	ir_prg[0].branchAddress =  cpu_to_le32((virt_to_bus(&(ir_prg[1].control)) 
-				    & 0xfffffff0) | 0x1);
+	ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
+				(unsigned long)d->dma.kvirt));
+	ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+					1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
 
 	/* the second descriptor will read PAGE_SIZE-4 bytes */
 	ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
 		DMA_CTL_BRANCH | (PAGE_SIZE-4));
-	ir_prg[1].address = cpu_to_le32(kvirt_to_bus(buf+4));
-	ir_prg[1].branchAddress =  cpu_to_le32((virt_to_bus(&(ir_prg[2].control)) 
-				    & 0xfffffff0) | 0x1);
+	ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
+					(unsigned long)d->dma.kvirt));
+	ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+					2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
 	
 	for (i=2;i<d->nb_cmd-1;i++) {
 		ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
 			DMA_CTL_BRANCH | PAGE_SIZE);
-		ir_prg[i].address = cpu_to_le32(kvirt_to_bus(buf+(i-1)*PAGE_SIZE));
-
-		ir_prg[i].branchAddress =  
-			cpu_to_le32((virt_to_bus(&(ir_prg[i+1].control)) 
-			 & 0xfffffff0) | 0x1);
+		ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+					        (buf+(i-1)*PAGE_SIZE) -
+						(unsigned long)d->dma.kvirt));
+
+		ir_prg[i].branchAddress =
+			cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
+				(i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
 	}
 
 	/* the last descriptor will generate an interrupt */
 	ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | 
 		DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
-	ir_prg[i].address = cpu_to_le32(kvirt_to_bus(buf+(i-1)*PAGE_SIZE));
+	ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+					(buf+(i-1)*PAGE_SIZE) -
+					(unsigned long)d->dma.kvirt));
 }
 	
 static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags)
@@ -559,11 +492,7 @@
 		if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) {
 			reset_ir_status(d, i);
 			d->buffer_status[i] = VIDEO1394_BUFFER_READY;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,18)
-			get_fast_time(&d->buffer_time[i]);
-#else
 			do_gettimeofday(&d->buffer_time[i]);
-#endif
 		}
 	}
 
@@ -576,7 +505,7 @@
 static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d,
 				 int n)
 {
-	unsigned char* buf = d->buf + n * d->buf_size;
+	unsigned char* buf = d->dma.kvirt + n * d->buf_size;
 	u32 cycleTimer;
 	u32 timeStamp;
 
@@ -605,7 +534,7 @@
 	if (n == -1) {
 	  return;
 	}
-	buf = d->buf + n * d->buf_size;
+	buf = d->dma.kvirt + n * d->buf_size;
 
 	timeStamp += (d->last_used_cmd[n] << 12) & 0xffff;
 
@@ -652,7 +581,8 @@
 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;
+	struct dma_prog_region *it_reg = &d->prg_reg[n];
+	unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
 	int i;
 	d->last_used_cmd[n] = d->nb_cmd - 1;
 	for (i=0;i<d->nb_cmd;i++) {
@@ -676,18 +606,18 @@
 		it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST |
 			    	    	     DMA_CTL_BRANCH);
 		it_prg[i].end.address =
-			cpu_to_le32(kvirt_to_bus(buf+i*d->packet_size));
+			cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf+i*d->packet_size) -
+						(unsigned long)d->dma.kvirt));
 
 		if (i<d->nb_cmd-1) {
 			it_prg[i].end.control |= cpu_to_le32(d->packet_size);
 			it_prg[i].begin.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) 
-				 & 0xfffffff0) | 0x3);
+				cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
+					sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
 			it_prg[i].end.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) 
-				 & 0xfffffff0) | 0x3);
-		}
-		else {
+				cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
+					sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
+		} else {
 			/* the last prg generates an interrupt */
 			it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | 
 				DMA_CTL_IRQ | d->left_size);
@@ -696,15 +626,6 @@
 			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
 	}
 }
 
@@ -713,6 +634,7 @@
 	struct ti_ohci *ohci)
 {
 	struct it_dma_prg *it_prg = d->it_prg[n];
+	struct dma_prog_region *it_reg = &d->prg_reg[n];
 	int i;
 
 #if 0
@@ -734,12 +656,12 @@
 
 		if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) {
 			it_prg[i].end.control |= cpu_to_le32(size);
-			it_prg[i].begin.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) 
-				 & 0xfffffff0) | 0x3);
-			it_prg[i].end.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(it_prg[i+1].begin.control)) 
-				 & 0xfffffff0) | 0x3);
+			it_prg[i].begin.branchAddress =
+				cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
+					sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
+			it_prg[i].end.branchAddress =
+				cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
+					sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
 		} else {
 			/* the last prg generates an interrupt */
 			it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE | 
@@ -771,37 +693,6 @@
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx);
 }
 
-static int do_iso_mmap(struct ti_ohci *ohci, struct dma_iso_ctx *d,
-		       struct vm_area_struct *vma)
-{
-        unsigned long start = vma->vm_start;
-	unsigned long size = vma->vm_end - vma->vm_start;
-        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_1394(vma, 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)
 {
@@ -814,6 +705,8 @@
 	{
 	case VIDEO1394_LISTEN_CHANNEL:
 	case VIDEO1394_TALK_CHANNEL:
+	case VIDEO1394_IOC_LISTEN_CHANNEL:
+	case VIDEO1394_IOC_TALK_CHANNEL:
 	{
 		struct video1394_mmap v;
 		u64 mask;
@@ -872,7 +765,7 @@
 			return -EFAULT;
 		}
 
-		if (cmd == VIDEO1394_LISTEN_CHANNEL) {
+		if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL || cmd == VIDEO1394_LISTEN_CHANNEL) {
 			d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE,
 					      v.nb_buffers, v.buf_size, 
 					      v.channel, 0);
@@ -922,8 +815,10 @@
 
 		return 0;
 	}
-	case VIDEO1394_UNLISTEN_CHANNEL: 
+	case VIDEO1394_UNLISTEN_CHANNEL:
 	case VIDEO1394_UNTALK_CHANNEL:
+	case VIDEO1394_IOC_UNLISTEN_CHANNEL: 
+	case VIDEO1394_IOC_UNTALK_CHANNEL:
 	{
 		int channel;
 		u64 mask;
@@ -947,7 +842,7 @@
 		/* Mark this channel as unused */
 		ohci->ISO_channel_usage &= ~mask;
 
-		if (cmd == VIDEO1394_UNLISTEN_CHANNEL)
+		if (cmd == VIDEO1394_IOC_UNLISTEN_CHANNEL || cmd == VIDEO1394_UNLISTEN_CHANNEL)
 			d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, channel);
 		else
 			d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);
@@ -960,6 +855,7 @@
 		return 0;
 	}
 	case VIDEO1394_LISTEN_QUEUE_BUFFER:
+	case VIDEO1394_IOC_LISTEN_QUEUE_BUFFER:
 	{
 		struct video1394_wait v;
 		struct dma_iso_ctx *d;
@@ -986,10 +882,10 @@
 		
 		d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
 
-		if (d->last_buffer>=0) 
-			d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 
-				cpu_to_le32((virt_to_bus(&(d->ir_prg[v.buffer][0].control)) 
-				 & 0xfffffff0) | 0x1);
+		if (d->last_buffer>=0)
+			d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =
+				cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0)
+					& 0xfffffff0) | 0x1);
 
 		d->last_buffer = v.buffer;
 
@@ -1002,9 +898,9 @@
 			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);
-			
+			reg_write(ohci, d->cmdPtr,
+				dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x1);
+
 			/* Run IR context */
 			reg_write(ohci, d->ctrlSet, 0x8000);
 		}
@@ -1021,6 +917,8 @@
 	}
 	case VIDEO1394_LISTEN_WAIT_BUFFER:
 	case VIDEO1394_LISTEN_POLL_BUFFER:
+	case VIDEO1394_IOC_LISTEN_WAIT_BUFFER:
+	case VIDEO1394_IOC_LISTEN_POLL_BUFFER:
 	{
 		struct video1394_wait v;
 		struct dma_iso_ctx *d;
@@ -1047,7 +945,8 @@
 			d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
 			break;
 		case VIDEO1394_BUFFER_QUEUED:
-			if (cmd == VIDEO1394_LISTEN_POLL_BUFFER) {
+			if (cmd == VIDEO1394_IOC_LISTEN_POLL_BUFFER ||
+			    cmd == VIDEO1394_LISTEN_POLL_BUFFER) {
 			    /* for polling, return error code EINTR */
 			    spin_unlock_irqrestore(&d->lock, flags);
 			    return -EINTR;
@@ -1102,6 +1001,7 @@
 		return 0;
 	}
 	case VIDEO1394_TALK_QUEUE_BUFFER:
+	case VIDEO1394_IOC_TALK_QUEUE_BUFFER:
 	{
 		struct video1394_wait v;
 		struct video1394_queue_variable qv;
@@ -1144,18 +1044,16 @@
 
 		d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
 
-		if (d->last_buffer>=0) {
+		if (d->last_buffer >= 0) {
 			d->it_prg[d->last_buffer]
-				[ d->last_used_cmd[d->last_buffer]
-					].end.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) 
-				 & 0xfffffff0) | 0x3);
+				[ d->last_used_cmd[d->last_buffer] ].end.branchAddress = 
+					cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
+						0) & 0xfffffff0) | 0x3);
 
 			d->it_prg[d->last_buffer]
-				[d->last_used_cmd[d->last_buffer]
-					].begin.branchAddress = 
-				cpu_to_le32((virt_to_bus(&(d->it_prg[v.buffer][0].begin.control)) 
-				 & 0xfffffff0) | 0x3);
+				[ d->last_used_cmd[d->last_buffer] ].begin.branchAddress =
+					cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
+						0) & 0xfffffff0) | 0x3);
 			d->next_buffer[d->last_buffer] = v.buffer;
 		}
 		d->last_buffer = v.buffer;
@@ -1172,9 +1070,9 @@
 			put_timestamp(ohci, d, d->last_buffer);
 
 			/* Tell the controller where the first program is */
-			reg_write(ohci, d->cmdPtr, 
-				  virt_to_bus(&(d->it_prg[v.buffer][0]))|0x3);
-			
+			reg_write(ohci, d->cmdPtr,
+				dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x3);
+
 			/* Run IT context */
 			reg_write(ohci, d->ctrlSet, 0x8000);
 		}
@@ -1192,6 +1090,7 @@
 		
 	}
 	case VIDEO1394_TALK_WAIT_BUFFER:
+	case VIDEO1394_IOC_TALK_WAIT_BUFFER:
 	{
 		struct video1394_wait v;
 		struct dma_iso_ctx *d;
@@ -1260,7 +1159,7 @@
 	if (ctx->current_ctx == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Current iso context not set");
 	} else
-		res = do_iso_mmap(ohci, ctx->current_ctx, vma);
+		res = dma_region_mmap(&ctx->current_ctx->dma, file, vma);
 	unlock_kernel();
 	return res;
 }
@@ -1268,21 +1167,10 @@
 static int video1394_open(struct inode *inode, struct file *file)
 {
 	int i = ieee1394_file_to_instance(file);
-	unsigned long flags;
-	struct video_card *video = NULL;
-	struct list_head *lh;
+	struct video_card *video;
 	struct file_ctx *ctx;
 
-	spin_lock_irqsave(&video1394_cards_lock, flags);
-	list_for_each(lh, &video1394_cards) {
-		struct video_card *p = list_entry(lh, struct video_card, list);
-		if (p->id == i) {
-			video = p;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&video1394_cards_lock, flags);
-
+	video = hpsb_get_hostinfo_bykey(&video1394_highlevel, i);
         if (video == NULL)
                 return -EIO;
 
@@ -1343,91 +1231,74 @@
 	.release =	video1394_release
 };
 
-static int video1394_init(struct ti_ohci *ohci)
+/*** HOTPLUG STUFF **********************************************************/
+/*
+ * Export information about protocols/devices supported by this driver.
+ */
+static struct ieee1394_device_id video1394_id_table[] = {
+	{
+		.match_flags	= IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+		.specifier_id	= CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+		.version	= CAMERA_SW_VERSION_ENTRY & 0xffffff
+	},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
+
+static struct hpsb_protocol_driver video1394_driver = {
+	.name		= "1394 Digital Camera Driver",
+	.id_table	= video1394_id_table,
+};
+
+
+static void video1394_add_host (struct hpsb_host *host)
 {
+	struct ti_ohci *ohci;
 	struct video_card *video;
-	unsigned long flags;
 	char name[16];
 	int minor;
 
-	video = kmalloc(sizeof(struct video_card), GFP_KERNEL);
+	/* We only work with the OHCI-1394 driver */
+	if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
+		return;
+
+	ohci = (struct ti_ohci *)host->hostdata;
+
+	video = hpsb_create_hostinfo(&video1394_highlevel, host, sizeof(*video));
 	if (video == NULL) {
 		PRINT(KERN_ERR, ohci->id, "Cannot allocate video_card");
-		return -1;
+		return;
 	}
 
-	memset(video, 0, sizeof(struct video_card));
-
-	spin_lock_irqsave(&video1394_cards_lock, flags);
-	INIT_LIST_HEAD(&video->list);
-	list_add_tail(&video->list, &video1394_cards);
-	spin_unlock_irqrestore(&video1394_cards_lock, flags);
-
-	video->id = ohci->id;
+	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->id);
 	video->ohci = ohci;
 
-	sprintf(name, "%d", video->id);
-	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + video->id;
+	sprintf(name, "%d", ohci->id);
+	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id;
 	video->devfs = devfs_register(devfs_handle, name,
 				      DEVFS_FL_AUTO_OWNER,
 				      IEEE1394_MAJOR, minor,
 				      S_IFCHR | S_IRUSR | S_IWUSR,
 				      &video1394_fops, NULL);
 
-	return 0;
+	return;
 }
 
-/* Must be called under spinlock */
-static void remove_card(struct video_card *video)
-{
-	devfs_unregister(video->devfs);
-	list_del(&video->list);
-
-	kfree(video);
-}
 
 static void video1394_remove_host (struct hpsb_host *host)
 {
-	struct ti_ohci *ohci;
-	unsigned long flags;
-	struct list_head *lh, *next;
-	struct video_card *p;
+	struct video_card *video = hpsb_get_hostinfo(&video1394_highlevel, host);
 
-	/* We only work with the OHCI-1394 driver */
-	if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
-		return;
-
-	ohci = (struct ti_ohci *)host->hostdata;
-
-        spin_lock_irqsave(&video1394_cards_lock, flags);
-	list_for_each_safe(lh, next, &video1394_cards) {
-		p = list_entry(lh, struct video_card, list);
-		if (p->ohci == ohci) {
-			remove_card(p);
-			break;
-		}
-	}
-	spin_unlock_irqrestore(&video1394_cards_lock, flags);
+	if (video)
+		devfs_unregister(video->devfs);
 
 	return;
 }
 
-static void video1394_add_host (struct hpsb_host *host)
-{
-	struct ti_ohci *ohci;
 
-	/* We only work with the OHCI-1394 driver */
-	if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
-		return;
-
-	ohci = (struct ti_ohci *)host->hostdata;
-
-	video1394_init(ohci);
-	
-	return;
-}
-
-static struct hpsb_highlevel_ops hl_ops = {
+static struct hpsb_highlevel video1394_highlevel = {
+	.name =		VIDEO1394_DRIVER_NAME,
 	.add_host =	video1394_add_host,
 	.remove_host =	video1394_remove_host,
 };
@@ -1439,7 +1310,9 @@
 
 static void __exit video1394_exit_module (void)
 {
-	hpsb_unregister_highlevel (hl_handle);
+	hpsb_unregister_protocol(&video1394_driver);
+
+	hpsb_unregister_highlevel(&video1394_highlevel);
 
 	devfs_unregister(devfs_handle);
 	ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394);
@@ -1455,20 +1328,11 @@
  		return -EIO;
  	}
 	
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-	devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME,
-			strlen(VIDEO1394_DRIVER_NAME), NULL);
-#else
 	devfs_handle = devfs_mk_dir(NULL, VIDEO1394_DRIVER_NAME, NULL);
-#endif
 
-	hl_handle = hpsb_register_highlevel (VIDEO1394_DRIVER_NAME, &hl_ops);
-	if (hl_handle == NULL) {
-		PRINT_G(KERN_ERR, "No more memory for driver\n");
-		devfs_unregister(devfs_handle);
-		ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_VIDEO1394);
-		return -ENOMEM;
-	}
+	hpsb_register_highlevel(&video1394_highlevel);
+
+	hpsb_register_protocol(&video1394_driver);
 
 	PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
 	return 0;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)