--- ../../alsa-kernel/usb/usx2y/usx2yhwdeppcm.c	2009-12-10 14:29:27.000000000 +0100
+++ usx2yhwdeppcm.c	2010-01-20 11:12:58.000000000 +0100
@@ -1,3 +1,5 @@
+#include "usx2yhwdeppcm.inc"
+
 /*
  *   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
@@ -150,7 +152,11 @@ static inline void usX2Y_usbpcm_urb_capt
 {
 	int pack;
 	for (pack = 0; pack < nr_of_packs(); ++pack) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 20)
 		struct usb_iso_packet_descriptor *desc = urb->iso_frame_desc + pack;
+#else
+		iso_packet_descriptor_t *desc = urb->iso_frame_desc + pack;
+#endif
 		if (NULL != subs) {
 			struct snd_usX2Y_hwdep_pcm_shm *shm = subs->usX2Y->hwdep_pcm_shm;
 			int head = shm->captured_iso_head + 1;
@@ -226,7 +232,11 @@ static inline int usX2Y_usbpcm_usbframe_
 }
 
 
+#if !defined(OLD_USB) && !defined(CONFIG_SND_NEW_IRQ_HANDLER)
+static void i_usX2Y_usbpcm_urb_complete(struct urb *urb, struct pt_regs *regs)
+#else
 static void i_usX2Y_usbpcm_urb_complete(struct urb *urb)
+#endif
 {
 	struct snd_usX2Y_substream *subs = urb->context;
 	struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -256,9 +266,15 @@ static void i_usX2Y_usbpcm_urb_complete(
 	if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED &&
 	    (NULL == capsubs2 || capsubs2->completed_urb) &&
 	    (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) {
-		if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame))
-			usX2Y->wait_iso_frame += nr_of_packs();
-		else {
+		if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) {
+#if !USB_2_6_18
+			if (nr_of_packs() <= urb->start_frame &&
+			    urb->start_frame <= (2 * nr_of_packs() - 1))	// uhci and ohci
+				usX2Y->wait_iso_frame = urb->start_frame - nr_of_packs();
+			else
+#endif
+				usX2Y->wait_iso_frame +=  nr_of_packs();
+		} else {
 			snd_printdd("\n");
 			usX2Y_clients_stop(usX2Y);
 		}
@@ -290,7 +306,11 @@ static void usX2Y_usbpcm_subs_startup_fi
 	usX2Y->prepare_subs = NULL;
 }
 
+#if !defined(OLD_USB) && !defined(CONFIG_SND_NEW_IRQ_HANDLER)
+static void i_usX2Y_usbpcm_subs_startup(struct urb *urb, struct pt_regs *regs)
+#else
 static void i_usX2Y_usbpcm_subs_startup(struct urb *urb)
+#endif
 {
 	struct snd_usX2Y_substream *subs = urb->context;
 	struct usX2Ydev *usX2Y = subs->usX2Y;
@@ -307,7 +327,11 @@ static void i_usX2Y_usbpcm_subs_startup(
 		wake_up(&usX2Y->prepare_wait_queue);
 	}
 
+#if !defined(OLD_USB) && !defined(CONFIG_SND_NEW_IRQ_HANDLER)
+	i_usX2Y_usbpcm_urb_complete(urb, regs);
+#else
 	i_usX2Y_usbpcm_urb_complete(urb);
+#endif
 }
 
 /*
@@ -429,6 +453,9 @@ static int usX2Y_usbpcm_urbs_start(struc
 		if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED)
 			goto start;
 	}
+#if !USB_2_6_18
+	usX2Y->wait_iso_frame = -1;
+#endif
 
  start:
 	usX2Y_usbpcm_subs_startup(subs);
@@ -454,7 +481,11 @@ static int usX2Y_usbpcm_urbs_start(struc
 						goto cleanup;
 					}  else {
 						snd_printdd("%i\n", urb->start_frame);
+#if USB_2_6_18
 						if (u == 0)
+#else
+						if (0 > usX2Y->wait_iso_frame)
+#endif
 							usX2Y->wait_iso_frame = urb->start_frame;
 					}
 					urb->transfer_flags = 0;
@@ -683,6 +714,7 @@ static void snd_usX2Y_hwdep_pcm_vm_close
 }
 
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 static int snd_usX2Y_hwdep_pcm_vm_fault(struct vm_area_struct *area,
 					struct vm_fault *vmf)
 {
@@ -695,12 +727,60 @@ static int snd_usX2Y_hwdep_pcm_vm_fault(
 	get_page(vmf->page);
 	return 0;
 }
+#else /* 2.6.24 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+static struct page * snd_usX2Y_hwdep_pcm_vm_nopage(struct vm_area_struct *area,
+					unsigned long address, int *type)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
+static struct page * snd_usX2Y_hwdep_pcm_vm_nopage(struct vm_area_struct *area,
+					unsigned long address, int no_share)
+#else
+static unsigned long snd_usX2Y_hwdep_pcm_vm_nopage(struct vm_area_struct *area,
+					unsigned long address, int no_share)
+#endif
+{
+	unsigned long offset;
+	struct page *page;
+	void *vaddr;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
+	offset = area->vm_pgoff << PAGE_SHIFT;
+#else
+	offset = area->vm_offset;
+#endif
+	offset += address - area->vm_start;
+	if (snd_BUG_ON(offset % PAGE_SIZE))
+		return NOPAGE_OOM;
+	vaddr = (char*)((struct usX2Ydev *)
+			area->vm_private_data)->hwdep_pcm_shm + offset;
+	page = virt_to_page(vaddr);
+#ifndef CONFIG_SND_REMOVE_PAGE_RESERVE
+	if (!PageReserved(page))
+#endif
+ 	get_page(page);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+	if (type)
+		*type = VM_FAULT_MINOR;
+#endif
+
+#ifndef LINUX_2_2
+	return page;
+#else
+#undef page_address
+	return page_address(page);
+#endif
+}
+#endif /* >= 2.6.24 */
 
 static const struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = {
 	.open = snd_usX2Y_hwdep_pcm_vm_open,
 	.close = snd_usX2Y_hwdep_pcm_vm_close,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 	.fault = snd_usX2Y_hwdep_pcm_vm_fault,
+#else
+	.nopage = snd_usX2Y_hwdep_pcm_vm_nopage,
+#endif
 };
 
 
@@ -722,8 +802,14 @@ static int snd_usX2Y_hwdep_pcm_mmap(stru
 		return -ENODEV;
 	}
 	area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops;
+#ifdef VM_RESERVED
 	area->vm_flags |= VM_RESERVED | VM_DONTEXPAND;
+#endif
+#ifndef LINUX_2_2
 	area->vm_private_data = hw->private_data;
+#else
+	area->vm_private_data = (long)hw->private_data;
+#endif
 	return 0;
 }
 
