123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821 |
- /*
- * arch/v850/kernel/mb_a_pci.c -- PCI support for Midas lab RTE-MOTHER-A board
- *
- * Copyright (C) 2001,02,03,05 NEC Electronics Corporation
- * Copyright (C) 2001,02,03,05 Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
- *
- * Written by Miles Bader <miles@gnu.org>
- */
- #include <linux/config.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/slab.h>
- #include <linux/spinlock.h>
- #include <linux/pci.h>
- #include <asm/machdep.h>
- /* __nomods_init is like __devinit, but is a no-op when modules are enabled.
- This is used by some routines that can be called either during boot
- or by a module. */
- #ifdef CONFIG_MODULES
- #define __nomods_init /*nothing*/
- #else
- #define __nomods_init __devinit
- #endif
- /* PCI devices on the Mother-A board can only do DMA to/from the MB SRAM
- (the RTE-V850E/MA1-CB cpu board doesn't support PCI access to
- CPU-board memory), and since linux DMA buffers are allocated in
- normal kernel memory, we basically have to copy DMA blocks around
- (this is like a `bounce buffer'). When a DMA block is `mapped', we
- allocate an identically sized block in MB SRAM, and if we're doing
- output to the device, copy the CPU-memory block to the MB-SRAM block.
- When an active block is `unmapped', we will copy the block back to
- CPU memory if necessary, and then deallocate the MB SRAM block.
- Ack. */
- /* Where the motherboard SRAM is in the PCI-bus address space (the
- first 512K of it is also mapped at PCI address 0). */
- #define PCI_MB_SRAM_ADDR 0x800000
- /* Convert CPU-view MB SRAM address to/from PCI-view addresses of the
- same memory. */
- #define MB_SRAM_TO_PCI(mb_sram_addr) \
- ((dma_addr_t)mb_sram_addr - MB_A_SRAM_ADDR + PCI_MB_SRAM_ADDR)
- #define PCI_TO_MB_SRAM(pci_addr) \
- (void *)(pci_addr - PCI_MB_SRAM_ADDR + MB_A_SRAM_ADDR)
- static void pcibios_assign_resources (void);
- struct mb_pci_dev_irq {
- unsigned dev; /* PCI device number */
- unsigned irq_base; /* First IRQ */
- unsigned query_pin; /* True if we should read the device's
- Interrupt Pin info, and allocate
- interrupt IRQ_BASE + PIN. */
- };
- /* PCI interrupts are mapped statically to GBUS interrupts. */
- static struct mb_pci_dev_irq mb_pci_dev_irqs[] = {
- /* Motherboard SB82558 ethernet controller */
- { 10, IRQ_MB_A_LAN, 0 },
- /* PCI slot 1 */
- { 8, IRQ_MB_A_PCI1(0), 1 },
- /* PCI slot 2 */
- { 9, IRQ_MB_A_PCI2(0), 1 }
- };
- #define NUM_MB_PCI_DEV_IRQS \
- (sizeof mb_pci_dev_irqs / sizeof mb_pci_dev_irqs[0])
- /* PCI configuration primitives. */
- #define CONFIG_DMCFGA(bus, devfn, offs) \
- (0x80000000 \
- | ((offs) & ~0x3) \
- | ((devfn) << 8) \
- | ((bus)->number << 16))
- static int
- mb_pci_read (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 *rval)
- {
- u32 addr;
- int flags;
- local_irq_save (flags);
- MB_A_PCI_PCICR = 0x7;
- MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
- addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
- switch (size) {
- case 1: *rval = *(volatile u8 *)addr; break;
- case 2: *rval = *(volatile u16 *)addr; break;
- case 4: *rval = *(volatile u32 *)addr; break;
- }
- if (MB_A_PCI_PCISR & 0x2000) {
- MB_A_PCI_PCISR = 0x2000;
- *rval = ~0;
- }
- MB_A_PCI_DMCFGA = 0;
- local_irq_restore (flags);
- return PCIBIOS_SUCCESSFUL;
- }
- static int
- mb_pci_write (struct pci_bus *bus, unsigned devfn, int offs, int size, u32 val)
- {
- u32 addr;
- int flags;
- local_irq_save (flags);
- MB_A_PCI_PCICR = 0x7;
- MB_A_PCI_DMCFGA = CONFIG_DMCFGA (bus, devfn, offs);
- addr = MB_A_PCI_IO_ADDR + (offs & 0x3);
- switch (size) {
- case 1: *(volatile u8 *)addr = val; break;
- case 2: *(volatile u16 *)addr = val; break;
- case 4: *(volatile u32 *)addr = val; break;
- }
- if (MB_A_PCI_PCISR & 0x2000)
- MB_A_PCI_PCISR = 0x2000;
- MB_A_PCI_DMCFGA = 0;
- local_irq_restore (flags);
- return PCIBIOS_SUCCESSFUL;
- }
- static struct pci_ops mb_pci_config_ops = {
- .read = mb_pci_read,
- .write = mb_pci_write,
- };
- /* PCI Initialization. */
- static struct pci_bus *mb_pci_bus = 0;
- /* Do initial PCI setup. */
- static int __devinit pcibios_init (void)
- {
- u32 id = MB_A_PCI_PCIHIDR;
- u16 vendor = id & 0xFFFF;
- u16 device = (id >> 16) & 0xFFFF;
- if (vendor == PCI_VENDOR_ID_PLX && device == PCI_DEVICE_ID_PLX_9080) {
- printk (KERN_INFO
- "PCI: PLX Technology PCI9080 HOST/PCI bridge\n");
- MB_A_PCI_PCICR = 0x147;
- MB_A_PCI_PCIBAR0 = 0x007FFF00;
- MB_A_PCI_PCIBAR1 = 0x0000FF00;
- MB_A_PCI_PCIBAR2 = 0x00800000;
- MB_A_PCI_PCILTR = 0x20;
- MB_A_PCI_PCIPBAM |= 0x3;
- MB_A_PCI_PCISR = ~0; /* Clear errors. */
- /* Reprogram the motherboard's IO/config address space,
- as we don't support the GCS7 address space that the
- default uses. */
- /* Significant address bits used for decoding PCI GCS5 space
- accessess. */
- MB_A_PCI_DMRR = ~(MB_A_PCI_MEM_SIZE - 1);
- /* I don't understand this, but the SolutionGear example code
- uses such an offset, and it doesn't work without it. XXX */
- #if GCS5_SIZE == 0x00800000
- #define GCS5_CFG_OFFS 0x00800000
- #else
- #define GCS5_CFG_OFFS 0
- #endif
- /* Address bit values for matching. Note that we have to give
- the address from the motherboard's point of view, which is
- different than the CPU's. */
- /* PCI memory space. */
- MB_A_PCI_DMLBAM = GCS5_CFG_OFFS + 0x0;
- /* PCI I/O space. */
- MB_A_PCI_DMLBAI =
- GCS5_CFG_OFFS + (MB_A_PCI_IO_ADDR - GCS5_ADDR);
- mb_pci_bus = pci_scan_bus (0, &mb_pci_config_ops, 0);
- pcibios_assign_resources ();
- } else
- printk (KERN_ERR "PCI: HOST/PCI bridge not found\n");
- return 0;
- }
- subsys_initcall (pcibios_init);
- char __devinit *pcibios_setup (char *option)
- {
- /* Don't handle any options. */
- return option;
- }
- int __nomods_init pcibios_enable_device (struct pci_dev *dev, int mask)
- {
- u16 cmd, old_cmd;
- int idx;
- struct resource *r;
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- old_cmd = cmd;
- for (idx = 0; idx < 6; idx++) {
- r = &dev->resource[idx];
- if (!r->start && r->end) {
- printk(KERN_ERR "PCI: Device %s not available because "
- "of resource collisions\n", pci_name(dev));
- return -EINVAL;
- }
- if (r->flags & IORESOURCE_IO)
- cmd |= PCI_COMMAND_IO;
- if (r->flags & IORESOURCE_MEM)
- cmd |= PCI_COMMAND_MEMORY;
- }
- if (cmd != old_cmd) {
- printk("PCI: Enabling device %s (%04x -> %04x)\n",
- pci_name(dev), old_cmd, cmd);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
- return 0;
- }
- /* Resource allocation. */
- static void __devinit pcibios_assign_resources (void)
- {
- struct pci_dev *dev = NULL;
- struct resource *r;
- for_each_pci_dev(dev) {
- unsigned di_num;
- unsigned class = dev->class >> 8;
- if (class && class != PCI_CLASS_BRIDGE_HOST) {
- unsigned r_num;
- for(r_num = 0; r_num < 6; r_num++) {
- r = &dev->resource[r_num];
- if (!r->start && r->end)
- pci_assign_resource (dev, r_num);
- }
- }
- /* Assign interrupts. */
- for (di_num = 0; di_num < NUM_MB_PCI_DEV_IRQS; di_num++) {
- struct mb_pci_dev_irq *di = &mb_pci_dev_irqs[di_num];
- if (di->dev == PCI_SLOT (dev->devfn)) {
- unsigned irq = di->irq_base;
- if (di->query_pin) {
- /* Find out which interrupt pin
- this device uses (each PCI
- slot has 4). */
- u8 irq_pin;
- pci_read_config_byte (dev,
- PCI_INTERRUPT_PIN,
- &irq_pin);
- if (irq_pin == 0)
- /* Doesn't use interrupts. */
- continue;
- else
- irq += irq_pin - 1;
- }
- pcibios_update_irq (dev, irq);
- }
- }
- }
- }
- void __devinit pcibios_update_irq (struct pci_dev *dev, int irq)
- {
- dev->irq = irq;
- pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq);
- }
- void __devinit
- pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
- struct resource *res)
- {
- unsigned long offset = 0;
- if (res->flags & IORESOURCE_IO) {
- offset = MB_A_PCI_IO_ADDR;
- } else if (res->flags & IORESOURCE_MEM) {
- offset = MB_A_PCI_MEM_ADDR;
- }
- region->start = res->start - offset;
- region->end = res->end - offset;
- }
- /* Stubs for things we don't use. */
- /* Called after each bus is probed, but before its children are examined. */
- void pcibios_fixup_bus(struct pci_bus *b)
- {
- }
- void
- pcibios_align_resource (void *data, struct resource *res,
- unsigned long size, unsigned long align)
- {
- }
- void pcibios_set_master (struct pci_dev *dev)
- {
- }
- /* Mother-A SRAM memory allocation. This is a simple first-fit allocator. */
- /* A memory free-list node. */
- struct mb_sram_free_area {
- void *mem;
- unsigned long size;
- struct mb_sram_free_area *next;
- };
- /* The tail of the free-list, which starts out containing all the SRAM. */
- static struct mb_sram_free_area mb_sram_free_tail = {
- (void *)MB_A_SRAM_ADDR, MB_A_SRAM_SIZE, 0
- };
- /* The free-list. */
- static struct mb_sram_free_area *mb_sram_free_areas = &mb_sram_free_tail;
- /* The free-list of free free-list nodes. (:-) */
- static struct mb_sram_free_area *mb_sram_free_free_areas = 0;
- /* Spinlock protecting the above globals. */
- static DEFINE_SPINLOCK(mb_sram_lock);
- /* Allocate a memory block at least SIZE bytes long in the Mother-A SRAM
- space. */
- static void *alloc_mb_sram (size_t size)
- {
- struct mb_sram_free_area *prev, *fa;
- int flags;
- void *mem = 0;
- spin_lock_irqsave (mb_sram_lock, flags);
- /* Look for a free area that can contain SIZE bytes. */
- for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
- if (fa->size >= size) {
- /* Found one! */
- mem = fa->mem;
- if (fa->size == size) {
- /* In fact, it fits exactly, so remove
- this node from the free-list. */
- if (prev)
- prev->next = fa->next;
- else
- mb_sram_free_areas = fa->next;
- /* Put it on the free-list-entry-free-list. */
- fa->next = mb_sram_free_free_areas;
- mb_sram_free_free_areas = fa;
- } else {
- /* FA is bigger than SIZE, so just
- reduce its size to account for this
- allocation. */
- fa->mem += size;
- fa->size -= size;
- }
- break;
- }
- spin_unlock_irqrestore (mb_sram_lock, flags);
- return mem;
- }
- /* Return the memory area MEM of size SIZE to the MB SRAM free pool. */
- static void free_mb_sram (void *mem, size_t size)
- {
- struct mb_sram_free_area *prev, *fa, *new_fa;
- int flags;
- void *end = mem + size;
- spin_lock_irqsave (mb_sram_lock, flags);
- retry:
- /* Find an adjacent free-list entry. */
- for (prev = 0, fa = mb_sram_free_areas; fa; prev = fa, fa = fa->next)
- if (fa->mem == end) {
- /* FA is just after MEM, grow down to encompass it. */
- fa->mem = mem;
- fa->size += size;
- goto done;
- } else if (fa->mem + fa->size == mem) {
- struct mb_sram_free_area *next_fa = fa->next;
- /* FA is just before MEM, expand to encompass it. */
- fa->size += size;
- /* See if FA can now be merged with its successor. */
- if (next_fa && fa->mem + fa->size == next_fa->mem) {
- /* Yup; merge NEXT_FA's info into FA. */
- fa->size += next_fa->size;
- fa->next = next_fa->next;
- /* Free NEXT_FA. */
- next_fa->next = mb_sram_free_free_areas;
- mb_sram_free_free_areas = next_fa;
- }
- goto done;
- } else if (fa->mem > mem)
- /* We've reached the right spot in the free-list
- without finding an adjacent free-area, so add
- a new free area to hold mem. */
- break;
- /* Make a new free-list entry. */
- /* First, get a free-list entry. */
- if (! mb_sram_free_free_areas) {
- /* There are none, so make some. */
- void *block;
- size_t block_size = sizeof (struct mb_sram_free_area) * 8;
- /* Don't hold the lock while calling kmalloc (I'm not
- sure whether it would be a problem, since we use
- GFP_ATOMIC, but it makes me nervous). */
- spin_unlock_irqrestore (mb_sram_lock, flags);
- block = kmalloc (block_size, GFP_ATOMIC);
- if (! block)
- panic ("free_mb_sram: can't allocate free-list entry");
- /* Now get the lock back. */
- spin_lock_irqsave (mb_sram_lock, flags);
- /* Add the new free free-list entries. */
- while (block_size > 0) {
- struct mb_sram_free_area *nfa = block;
- nfa->next = mb_sram_free_free_areas;
- mb_sram_free_free_areas = nfa;
- block += sizeof *nfa;
- block_size -= sizeof *nfa;
- }
- /* Since we dropped the lock to call kmalloc, the
- free-list could have changed, so retry from the
- beginning. */
- goto retry;
- }
- /* Remove NEW_FA from the free-list of free-list entries. */
- new_fa = mb_sram_free_free_areas;
- mb_sram_free_free_areas = new_fa->next;
- /* NEW_FA initially holds only MEM. */
- new_fa->mem = mem;
- new_fa->size = size;
- /* Insert NEW_FA in the free-list between PREV and FA. */
- new_fa->next = fa;
- if (prev)
- prev->next = new_fa;
- else
- mb_sram_free_areas = new_fa;
- done:
- spin_unlock_irqrestore (mb_sram_lock, flags);
- }
- /* Maintainence of CPU -> Mother-A DMA mappings. */
- struct dma_mapping {
- void *cpu_addr;
- void *mb_sram_addr;
- size_t size;
- struct dma_mapping *next;
- };
- /* A list of mappings from CPU addresses to MB SRAM addresses for active
- DMA blocks (that have been `granted' to the PCI device). */
- static struct dma_mapping *active_dma_mappings = 0;
- /* A list of free mapping objects. */
- static struct dma_mapping *free_dma_mappings = 0;
- /* Spinlock protecting the above globals. */
- static DEFINE_SPINLOCK(dma_mappings_lock);
- static struct dma_mapping *new_dma_mapping (size_t size)
- {
- int flags;
- struct dma_mapping *mapping;
- void *mb_sram_block = alloc_mb_sram (size);
- if (! mb_sram_block)
- return 0;
- spin_lock_irqsave (dma_mappings_lock, flags);
- if (! free_dma_mappings) {
- /* We're out of mapping structures, make more. */
- void *mblock;
- size_t mblock_size = sizeof (struct dma_mapping) * 8;
- /* Don't hold the lock while calling kmalloc (I'm not
- sure whether it would be a problem, since we use
- GFP_ATOMIC, but it makes me nervous). */
- spin_unlock_irqrestore (dma_mappings_lock, flags);
- mblock = kmalloc (mblock_size, GFP_ATOMIC);
- if (! mblock) {
- free_mb_sram (mb_sram_block, size);
- return 0;
- }
- /* Get the lock back. */
- spin_lock_irqsave (dma_mappings_lock, flags);
- /* Add the new mapping structures to the free-list. */
- while (mblock_size > 0) {
- struct dma_mapping *fm = mblock;
- fm->next = free_dma_mappings;
- free_dma_mappings = fm;
- mblock += sizeof *fm;
- mblock_size -= sizeof *fm;
- }
- }
- /* Get a mapping struct from the freelist. */
- mapping = free_dma_mappings;
- free_dma_mappings = mapping->next;
- /* Initialize the mapping. Other fields should be filled in by
- caller. */
- mapping->mb_sram_addr = mb_sram_block;
- mapping->size = size;
- /* Add it to the list of active mappings. */
- mapping->next = active_dma_mappings;
- active_dma_mappings = mapping;
- spin_unlock_irqrestore (dma_mappings_lock, flags);
- return mapping;
- }
- static struct dma_mapping *find_dma_mapping (void *mb_sram_addr)
- {
- int flags;
- struct dma_mapping *mapping;
- spin_lock_irqsave (dma_mappings_lock, flags);
- for (mapping = active_dma_mappings; mapping; mapping = mapping->next)
- if (mapping->mb_sram_addr == mb_sram_addr) {
- spin_unlock_irqrestore (dma_mappings_lock, flags);
- return mapping;
- }
- panic ("find_dma_mapping: unmapped PCI DMA addr 0x%x",
- MB_SRAM_TO_PCI (mb_sram_addr));
- }
- static struct dma_mapping *deactivate_dma_mapping (void *mb_sram_addr)
- {
- int flags;
- struct dma_mapping *mapping, *prev;
- spin_lock_irqsave (dma_mappings_lock, flags);
- for (prev = 0, mapping = active_dma_mappings;
- mapping;
- prev = mapping, mapping = mapping->next)
- {
- if (mapping->mb_sram_addr == mb_sram_addr) {
- /* This is the MAPPING; deactivate it. */
- if (prev)
- prev->next = mapping->next;
- else
- active_dma_mappings = mapping->next;
- spin_unlock_irqrestore (dma_mappings_lock, flags);
- return mapping;
- }
- }
- panic ("deactivate_dma_mapping: unmapped PCI DMA addr 0x%x",
- MB_SRAM_TO_PCI (mb_sram_addr));
- }
- /* Return MAPPING to the freelist. */
- static inline void
- free_dma_mapping (struct dma_mapping *mapping)
- {
- int flags;
- free_mb_sram (mapping->mb_sram_addr, mapping->size);
- spin_lock_irqsave (dma_mappings_lock, flags);
- mapping->next = free_dma_mappings;
- free_dma_mappings = mapping;
- spin_unlock_irqrestore (dma_mappings_lock, flags);
- }
- /* Single PCI DMA mappings. */
- /* `Grant' to PDEV the memory block at CPU_ADDR, for doing DMA. The
- 32-bit PCI bus mastering address to use is returned. the device owns
- this memory until either pci_unmap_single or pci_dma_sync_single is
- performed. */
- dma_addr_t
- pci_map_single (struct pci_dev *pdev, void *cpu_addr, size_t size, int dir)
- {
- struct dma_mapping *mapping = new_dma_mapping (size);
- if (! mapping)
- return 0;
- mapping->cpu_addr = cpu_addr;
- if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_TODEVICE)
- memcpy (mapping->mb_sram_addr, cpu_addr, size);
- return MB_SRAM_TO_PCI (mapping->mb_sram_addr);
- }
- /* Return to the CPU the PCI DMA memory block previously `granted' to
- PDEV, at DMA_ADDR. */
- void pci_unmap_single (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
- int dir)
- {
- void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
- struct dma_mapping *mapping = deactivate_dma_mapping (mb_sram_addr);
- if (size != mapping->size)
- panic ("pci_unmap_single: size (%d) doesn't match"
- " size of mapping at PCI DMA addr 0x%x (%d)\n",
- size, dma_addr, mapping->size);
- /* Copy back the DMA'd contents if necessary. */
- if (dir == PCI_DMA_BIDIRECTIONAL || dir == PCI_DMA_FROMDEVICE)
- memcpy (mapping->cpu_addr, mb_sram_addr, size);
- /* Return mapping to the freelist. */
- free_dma_mapping (mapping);
- }
- /* Make physical memory consistent for a single streaming mode DMA
- translation after a transfer.
- If you perform a pci_map_single() but wish to interrogate the
- buffer using the cpu, yet do not wish to teardown the PCI dma
- mapping, you must call this function before doing so. At the next
- point you give the PCI dma address back to the card, you must first
- perform a pci_dma_sync_for_device, and then the device again owns
- the buffer. */
- void
- pci_dma_sync_single_for_cpu (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
- int dir)
- {
- void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
- struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr);
- /* Synchronize the DMA buffer with the CPU buffer if necessary. */
- if (dir == PCI_DMA_FROMDEVICE)
- memcpy (mapping->cpu_addr, mb_sram_addr, size);
- else if (dir == PCI_DMA_TODEVICE)
- ; /* nothing to do */
- else
- panic("pci_dma_sync_single: unsupported sync dir: %d", dir);
- }
- void
- pci_dma_sync_single_for_device (struct pci_dev *pdev, dma_addr_t dma_addr, size_t size,
- int dir)
- {
- void *mb_sram_addr = PCI_TO_MB_SRAM (dma_addr);
- struct dma_mapping *mapping = find_dma_mapping (mb_sram_addr);
- /* Synchronize the DMA buffer with the CPU buffer if necessary. */
- if (dir == PCI_DMA_FROMDEVICE)
- ; /* nothing to do */
- else if (dir == PCI_DMA_TODEVICE)
- memcpy (mb_sram_addr, mapping->cpu_addr, size);
- else
- panic("pci_dma_sync_single: unsupported sync dir: %d", dir);
- }
- /* Scatter-gather PCI DMA mappings. */
- /* Do multiple DMA mappings at once. */
- int
- pci_map_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len, int dir)
- {
- BUG ();
- return 0;
- }
- /* Unmap multiple DMA mappings at once. */
- void
- pci_unmap_sg (struct pci_dev *pdev, struct scatterlist *sg, int sg_len,int dir)
- {
- BUG ();
- }
- /* Make physical memory consistent for a set of streaming mode DMA
- translations after a transfer. The same as pci_dma_sync_single_* but
- for a scatter-gather list, same rules and usage. */
- void
- pci_dma_sync_sg_for_cpu (struct pci_dev *dev,
- struct scatterlist *sg, int sg_len,
- int dir)
- {
- BUG ();
- }
- void
- pci_dma_sync_sg_for_device (struct pci_dev *dev,
- struct scatterlist *sg, int sg_len,
- int dir)
- {
- BUG ();
- }
- /* PCI mem mapping. */
- /* Allocate and map kernel buffer using consistent mode DMA for PCI
- device. Returns non-NULL cpu-view pointer to the buffer if
- successful and sets *DMA_ADDR to the pci side dma address as well,
- else DMA_ADDR is undefined. */
- void *
- pci_alloc_consistent (struct pci_dev *pdev, size_t size, dma_addr_t *dma_addr)
- {
- void *mb_sram_mem = alloc_mb_sram (size);
- if (mb_sram_mem)
- *dma_addr = MB_SRAM_TO_PCI (mb_sram_mem);
- return mb_sram_mem;
- }
- /* Free and unmap a consistent DMA buffer. CPU_ADDR and DMA_ADDR must
- be values that were returned from pci_alloc_consistent. SIZE must be
- the same as what as passed into pci_alloc_consistent. References to
- the memory and mappings assosciated with CPU_ADDR or DMA_ADDR past
- this call are illegal. */
- void
- pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr,
- dma_addr_t dma_addr)
- {
- void *mb_sram_mem = PCI_TO_MB_SRAM (dma_addr);
- free_mb_sram (mb_sram_mem, size);
- }
- /* iomap/iomap */
- void __iomem *pci_iomap (struct pci_dev *dev, int bar, unsigned long max)
- {
- unsigned long start = pci_resource_start (dev, bar);
- unsigned long len = pci_resource_len (dev, bar);
- if (!start || len == 0)
- return 0;
- /* None of the ioremap functions actually do anything, other than
- re-casting their argument, so don't bother differentiating them. */
- return ioremap (start, len);
- }
- void pci_iounmap (struct pci_dev *dev, void __iomem *addr)
- {
- /* nothing */
- }
- /* symbol exports (for modules) */
- EXPORT_SYMBOL (pci_map_single);
- EXPORT_SYMBOL (pci_unmap_single);
- EXPORT_SYMBOL (pci_alloc_consistent);
- EXPORT_SYMBOL (pci_free_consistent);
- EXPORT_SYMBOL (pci_dma_sync_single_for_cpu);
- EXPORT_SYMBOL (pci_dma_sync_single_for_device);
- EXPORT_SYMBOL (pci_iomap);
- EXPORT_SYMBOL (pci_iounmap);
|