-/*
+/*
* arch/sh/boards/dreamcast/setup.c
*
* Hardware support for the Sega Dreamcast.
*
* Copyright (c) 2001, 2002 M. R. Brown <mrbrown@linuxdc.org>
- * Copyright (c) 2002, 2003 Paul Mundt <lethal@linux-sh.org>
+ * Copyright (c) 2002, 2003, 2004 Paul Mundt <lethal@linux-sh.org>
*
* This file is part of the LinuxDC project (www.linuxdc.org)
*
* Released under the terms of the GNU GPL v2.0.
- *
+ *
* This file originally bore the message (with enclosed-$):
* Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp
* SEGA Dreamcast support
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/device.h>
#include <asm/io.h>
#include <asm/irq.h>
extern void aica_time_init(void);
extern int gapspci_init(void);
extern int systemasic_irq_demux(int);
+
+void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
+int dreamcast_consistent_free(struct device *, size_t, void *, dma_addr_t);
+
const char *get_system_type(void)
{
return "Sega Dreamcast";
.mv_nr_irqs = NR_IRQS,
.mv_irq_demux = systemasic_irq_demux,
+
+#ifdef CONFIG_PCI
+ .mv_consistent_alloc = dreamcast_consistent_alloc,
+ .mv_consistent_free = dreamcast_consistent_free,
+#endif
};
ALIAS_MV(dreamcast)
extern int rts7751r2d_irq_demux(int irq);
extern void *voyagergx_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
-extern void voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
+extern int voyagergx_consistent_free(struct device *, size_t, void *, dma_addr_t);
/*
* The Machine Vector
#endif
.mv_irq_demux = rts7751r2d_irq_demux,
+#ifdef CONFIG_USB_OHCI_HCD
.mv_consistent_alloc = voyagergx_consistent_alloc,
.mv_consistent_free = voyagergx_consistent_free,
+#endif
};
ALIAS_MV(rts7751r2d)
if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
(dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
shdev->dev_id != SH_DEV_ID_USB_OHCI))
- return consistent_alloc(flag, size, handle);
+ return NULL;
start = OHCI_SRAM_START + OHCI_HCCA_SIZE;
entry = kmalloc(sizeof(struct voya_alloc_entry), GFP_ATOMIC);
if (!entry)
- return NULL;
+ return ERR_PTR(-ENOMEM);
entry->len = (size + 15) & ~15;
kfree(entry);
spin_unlock_irqrestore(&voya_list_lock, flags);
- return NULL;
+ return ERR_PTR(-EINVAL);
}
-void voyagergx_consistent_free(struct device *dev, size_t size,
- void *vaddr, dma_addr_t handle)
+int voyagergx_consistent_free(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t handle)
{
struct voya_alloc_entry *entry;
struct sh_dev *shdev = to_sh_dev(dev);
if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
(dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
- shdev->dev_id != SH_DEV_ID_USB_OHCI)) {
- consistent_free(vaddr, size);
- return;
- }
+ shdev->dev_id != SH_DEV_ID_USB_OHCI))
+ return -EINVAL;
spin_lock_irqsave(&voya_list_lock, flags);
list_for_each_entry(entry, &voya_alloc_list, list) {
break;
}
spin_unlock_irqrestore(&voya_list_lock, flags);
+
+ return 0;
}
EXPORT_SYMBOL(voyagergx_consistent_alloc);
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
#include <asm/io.h>
#include <asm/irq.h>
static int gapspci_dma_used = 0;
-void *__pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
- dma_addr_t * dma_handle)
+void *dreamcast_consistent_alloc(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, int flag)
{
unsigned long buf;
- if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE)
+ if (dev && dev->bus != &pci_bus_type)
return NULL;
- buf = GAPSPCI_DMA_BASE+gapspci_dma_used;
+ if (gapspci_dma_used + size > GAPSPCI_DMA_SIZE)
+ return ERR_PTR(-EINVAL);
+
+ buf = GAPSPCI_DMA_BASE + gapspci_dma_used;
gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size);
-
+
*dma_handle = (dma_addr_t)buf;
buf = P2SEGADDR(buf);
return (void *)buf;
}
-void __pci_free_consistent(struct pci_dev *hwdev, size_t size,
+int dreamcast_consistent_free(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
+ if (dev && dev->bus != &pci_bus_type)
+ return -EINVAL;
+
/* XXX */
gapspci_dma_used = 0;
+
+ return 0;
}
BUG();
}
}
+
+EXPORT_SYMBOL(consistent_alloc);
+EXPORT_SYMBOL(consistent_free);
EXPORT_SYMBOL(consistent_sync);
+
#include <linux/config.h>
#include <linux/mm.h>
+#include <linux/device.h>
#include <asm/scatterlist.h>
#include <asm/io.h>
+extern struct bus_type pci_bus_type;
+
/* arch/sh/mm/consistent.c */
extern void *consistent_alloc(int gfp, size_t size, dma_addr_t *handle);
extern void consistent_free(void *vaddr, size_t size);
extern void consistent_sync(void *vaddr, size_t size, int direction);
-#ifdef CONFIG_SH_DREAMCAST
-struct pci_dev;
-extern struct bus_type pci_bus_type;
-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);
-#endif
-
#define dma_supported(dev, mask) (1)
static inline int dma_set_mask(struct device *dev, u64 mask)
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, int flag)
{
- /*
- * Some platforms have special pci_alloc_consistent() implementations,
- * in these instances we can't use the generic consistent_alloc().
- */
-#ifdef CONFIG_SH_DREAMCAST
- if (dev && dev->bus == &pci_bus_type)
- return __pci_alloc_consistent(NULL, size, dma_handle);
-#endif
- if (sh_mv.mv_consistent_alloc)
- return sh_mv.mv_consistent_alloc(dev, size, dma_handle, flag);
+ if (sh_mv.mv_consistent_alloc) {
+ void *ret;
+
+ ret = sh_mv.mv_consistent_alloc(dev, size, dma_handle, flag);
+ if (ret != NULL)
+ return ret;
+ }
return consistent_alloc(flag, size, dma_handle);
}
static inline void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
- /*
- * Same note as above applies to pci_free_consistent()..
- */
-#ifdef CONFIG_SH_DREAMCAST
- if (dev && dev->bus == &pci_bus_type) {
- __pci_free_consistent(NULL, size, vaddr, dma_handle);
- return;
- }
-#endif
-
if (sh_mv.mv_consistent_free) {
- sh_mv.mv_consistent_free(dev, size, vaddr, dma_handle);
- return;
+ int ret;
+
+ ret = sh_mv.mv_consistent_free(dev, size, vaddr, dma_handle);
+ if (ret == 0)
+ return;
}
consistent_free(vaddr, size);
void (*mv_heartbeat)(void);
void *(*mv_consistent_alloc)(struct device *, size_t, dma_addr_t *, int);
- void (*mv_consistent_free)(struct device *, size_t, void *, dma_addr_t);
+ int (*mv_consistent_free)(struct device *, size_t, void *, dma_addr_t);
};
extern struct sh_machine_vector sh_mv;