diff -uNr linux.orig/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- linux.orig/arch/ppc/kernel/Makefile	Mon Jan 31 16:40:34 2000
+++ linux/arch/ppc/kernel/Makefile	Fri Feb  4 00:33:11 2000
@@ -38,7 +38,7 @@
 endif
 
 ifdef CONFIG_PCI
-O_OBJS += pci.o
+O_OBJS += pci.o pci-dma.o
 endif
 
 ifdef CONFIG_KGDB
diff -uNr linux.orig/arch/ppc/kernel/pci-dma.c linux/arch/ppc/kernel/pci-dma.c
--- linux.orig/arch/ppc/kernel/pci-dma.c	Wed Dec 31 19:00:00 1969
+++ linux/arch/ppc/kernel/pci-dma.c	Fri Feb  4 00:32:10 2000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2000   Ani Joshi <ajoshi@unixbox.com>
+ *
+ *
+ * Dynamic DMA mapping support.
+ *
+ * swiped from i386
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.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;
+}
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+			   dma_addr_t *dma_handle)
+{
+	void *ret;
+	int gfp = GFP_ATOMIC;
+
+	if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
+		gfp |= GFP_DMA;
+	ret = (void *)__get_free_pages(gfp, __get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_bus(ret);
+	}
+	return ret;
+}
+
+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));
+}
diff -uNr linux.orig/arch/ppc/kernel/semaphore.c linux/arch/ppc/kernel/semaphore.c
--- linux.orig/arch/ppc/kernel/semaphore.c	Wed Oct 20 01:50:29 1999
+++ linux/arch/ppc/kernel/semaphore.c	Fri Feb  4 00:21:10 2000
@@ -137,3 +137,44 @@
 {
 	return waking_non_zero_trylock(sem);
 }
+
+
+/*
+ * rw semaphores    Ani Joshi <ajoshi@unixbox.com>
+ * based on alpha port by Andrea Arcangeli <andrea@suse.de>
+ */
+
+void down_read_failed(struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	do {
+		__set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+		spin_unlock_irq(&sem->lock);
+		schedule();
+		spin_lock_irq(&sem->lock);
+	} while(sem->wr);
+
+	remove_wait_queue(&sem->wait, &wait);
+}
+
+void down_write_failed(struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	do {
+		__set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
+		spin_unlock_irq(&sem->lock);
+		schedule();
+		spin_lock_irq(&sem->lock);
+	} while(sem->rd || sem->wr);
+
+	remove_wait_queue(&sem->wait, &wait);
+}
+
diff -uNr linux.orig/include/asm-ppc/pci.h linux/include/asm-ppc/pci.h
--- linux.orig/include/asm-ppc/pci.h	Mon Jan 31 16:40:58 2000
+++ linux/include/asm-ppc/pci.h	Fri Feb  4 00:37:24 2000
@@ -10,4 +10,56 @@
 #define PCIBIOS_MIN_IO		0x1000
 #define PCIBIOS_MIN_MEM		0x10000000
 
+/* Dynamic DMA Mapping stuff
+ * 	++ajoshi
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <asm/scatterlist.h>
+#include <asm/io.h>
+
+struct pci_dev;
+
+extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+				  dma_addr_t *dma_handle);
+extern void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+				void *vaddr, dma_addr_t dma_handle);
+extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
+					size_t size)
+{
+	return virt_to_bus(ptr);
+}
+extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+				    size_t size)
+{
+	/* nothing to do */
+}
+extern inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+			     int nents)
+{
+	return nents;
+}
+extern inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+				int nents)
+{
+	/* nothing to do */
+}
+extern inline void pci_dma_sync_single(struct pci_dev *hwdev,
+				       dma_addr_t dma_handle,
+				       size_t size)
+{
+	/* nothing to do */
+}
+extern inline void pci_dma_syng_sg(struct pci_dev *hwdev,
+				   struct scatterlist *sg,
+				   int nelems)
+{
+	/* nothing to do */
+}
+
+#define sg_dma_address(sg)	(virt_to_bus((sg)->address))
+#define sg_dma_len(sg)		((sg)->length)
+
 #endif /* __PPC_PCI_H */
diff -uNr linux.orig/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h
--- linux.orig/include/asm-ppc/semaphore.h	Wed Oct 20 01:52:08 1999
+++ linux/include/asm-ppc/semaphore.h	Thu Feb  3 23:59:53 2000
@@ -4,6 +4,9 @@
 /*
  * Swiped from asm-sparc/semaphore.h and modified
  * -- Cort (cort@cs.nmt.edu)
+ *
+ * Stole some rw spinlock-based semaphore stuff from asm-alpha/semaphore.h
+ * -- Ani Joshi (ajoshi@unixbox.com)
  */
 
 #ifdef __KERNEL__
@@ -101,6 +104,99 @@
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }	
+
+
+/* RW spinlock-based semaphores */
+
+struct rw_semaphore
+{
+	spinlock_t lock;
+	int rd, wr;
+	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
+};
+
+#define __RWSEM_INITIALIZER(name, rd, wr)		\
+{							\
+	SPIN_LOCK_UNLOCKED,				\
+	(rd), (wr),					\
+	__WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
+	__SEM_DEBUG_INIT(name)				\
+}
+
+#define __DECLARE_RWSEM_GENERIC(name, rd, wr)		\
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name, rd, wr)
+
+#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name, 0, 0)
+#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name, 1, 0)
+#define DECLAER_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name, 0, 1)
+
+extern inline void init_rwsem(struct rw_semaphore *sem)
+{
+	spin_lock_init(&sem->lock);
+	sem->rd = sem->wr = 0;
+	init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (long)&sem->__magic;
+#endif
+}
+
+#ifndef CHECK_MAGIC
+#define CHECK_MAGIC(x)
+#endif
+
+extern void down_read_failed(struct rw_semaphore *);
+extern void down_write_failed(struct rw_semaphore *);
+
+extern inline void down_read(struct rw_semaphore *sem)
+{
+	CHECK_MAGIC(sem->__magic);
+
+	spin_lock_irq(&sem->lock);
+	if (sem->wr)
+		down_read_failed(sem);
+	sem->rd++;
+	spin_unlock_irq(&sem->lock);
+}
+
+extern inline void down_write(struct rw_semaphore *sem)
+{
+	CHECK_MAGIC(sem->__magic);
+
+	spin_lock(&sem->lock);
+	if(sem->rd || sem->wr)
+		down_write_failed(sem);
+	sem->wr = 1;
+	spin_unlock(&sem->lock);
+}
+
+#define up_read(sem)							\
+	do {								\
+		unsigned long flags;					\
+									\
+		CHECK_MAGIC((sem)->__magic);				\
+									\
+		spin_lock_irqsave(&(sem)->lock, flags);			\
+		if (!--(sem)->rd && waitqueue_active(&(sem)->wait))	\
+			wake_up(&(sem)->wait);				\
+		spin_unlock_irqrestore(&(sem)->lock, flags);		\
+	} while (0)
+
+#define up_write(sem)							\
+	do {								\
+		unsigned long flags;					\
+									\
+		CHECK_MAGIC((sem)->__magic);				\
+									\
+		spin_lock_irqsave(&(sem)->lock, flags);			\
+		(sem)->wr = 0;						\
+		if (waitqueue_active(&(sem)->wait))			\
+			wake_up(&(sem)->wait);				\
+		spin_unlock_irqrestore(&(sem)->lock, flags);		\
+	} while (0)
+
 
 #endif /* __KERNEL__ */
 
diff -uNr linux.orig/include/asm-ppc/types.h linux/include/asm-ppc/types.h
--- linux.orig/include/asm-ppc/types.h	Thu Mar 11 00:30:32 1999
+++ linux/include/asm-ppc/types.h	Thu Feb  3 23:46:20 2000
@@ -41,6 +41,10 @@
 
 #define BITS_PER_LONG 32
 
+/* DMA addresses are 32-bits wide */
+
+typedef u32 dma_addr_t;
+
 #endif /* __KERNEL__ */
 
 #endif
