Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/sh/drivers/dma/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  dma-api.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * arch/sh/drivers/dma/dma-api.c
 *
 * SuperH-specific DMA management API
 *
 * Copyright (C) 2003, 2004, 2005  Paul Mundt
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/list.h>
#include <linux/platform_device.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <asm/dma.h>

DEFINE_SPINLOCK(dma_spin_lock);
static LIST_HEAD(registered_dmac_list);

struct dma_info *get_dma_info(unsigned int chan)
{
 struct dma_info *info;

 /*
 * Look for each DMAC's range to determine who the owner of
 * the channel is.
 */

 list_for_each_entry(info, ®istered_dmac_list, list) {
  if ((chan <  info->first_vchannel_nr) ||
      (chan >= info->first_vchannel_nr + info->nr_channels))
   continue;

  return info;
 }

 return NULL;
}
EXPORT_SYMBOL(get_dma_info);

static unsigned int get_nr_channels(void)
{
 struct dma_info *info;
 unsigned int nr = 0;

 if (unlikely(list_empty(®istered_dmac_list)))
  return nr;

 list_for_each_entry(info, ®istered_dmac_list, list)
  nr += info->nr_channels;

 return nr;
}

struct dma_channel *get_dma_channel(unsigned int chan)
{
 struct dma_info *info = get_dma_info(chan);
 struct dma_channel *channel;
 int i;

 if (unlikely(!info))
  return ERR_PTR(-EINVAL);

 for (i = 0; i < info->nr_channels; i++) {
  channel = &info->channels[i];
  if (channel->vchan == chan)
   return channel;
 }

 return NULL;
}
EXPORT_SYMBOL(get_dma_channel);

int get_dma_residue(unsigned int chan)
{
 struct dma_info *info = get_dma_info(chan);
 struct dma_channel *channel = get_dma_channel(chan);

 if (info->ops->get_residue)
  return info->ops->get_residue(channel);

 return 0;
}
EXPORT_SYMBOL(get_dma_residue);

int request_dma(unsigned int chan, const char *dev_id)
{
 struct dma_channel *channel = { 0 };
 struct dma_info *info = get_dma_info(chan);
 int result;

 channel = get_dma_channel(chan);
 if (atomic_xchg(&channel->busy, 1))
  return -EBUSY;

 strscpy(channel->dev_id, dev_id, sizeof(channel->dev_id));

 if (info->ops->request) {
  result = info->ops->request(channel);
  if (result)
   atomic_set(&channel->busy, 0);

  return result;
 }

 return 0;
}
EXPORT_SYMBOL(request_dma);

void free_dma(unsigned int chan)
{
 struct dma_info *info = get_dma_info(chan);
 struct dma_channel *channel = get_dma_channel(chan);

 if (info->ops->free)
  info->ops->free(channel);

 atomic_set(&channel->busy, 0);
}
EXPORT_SYMBOL(free_dma);

void dma_wait_for_completion(unsigned int chan)
{
 struct dma_info *info = get_dma_info(chan);
 struct dma_channel *channel = get_dma_channel(chan);

 if (channel->flags & DMA_TEI_CAPABLE) {
  wait_event(channel->wait_queue,
      (info->ops->get_residue(channel) == 0));
  return;
 }

 while (info->ops->get_residue(channel))
  cpu_relax();
}
EXPORT_SYMBOL(dma_wait_for_completion);

void dma_configure_channel(unsigned int chan, unsigned long flags)
{
 struct dma_info *info = get_dma_info(chan);
 struct dma_channel *channel = get_dma_channel(chan);

 if (info->ops->configure)
  info->ops->configure(channel, flags);
}
EXPORT_SYMBOL(dma_configure_channel);

int dma_xfer(unsigned int chan, unsigned long from,
      unsigned long to, size_t size, unsigned int mode)
{
 struct dma_info *info = get_dma_info(chan);
 struct dma_channel *channel = get_dma_channel(chan);

 channel->sar = from;
 channel->dar = to;
 channel->count = size;
 channel->mode = mode;

 return info->ops->xfer(channel);
}
EXPORT_SYMBOL(dma_xfer);

static int dma_proc_show(struct seq_file *m, void *v)
{
 struct dma_info *info = v;

 if (list_empty(®istered_dmac_list))
  return 0;

 /*
 * Iterate over each registered DMAC
 */

 list_for_each_entry(info, ®istered_dmac_list, list) {
  int i;

  /*
 * Iterate over each channel
 */

  for (i = 0; i < info->nr_channels; i++) {
   struct dma_channel *channel = info->channels + i;

   if (!(channel->flags & DMA_CONFIGURED))
    continue;

   seq_printf(m, "%2d: %14s %s\n", i,
       info->name, channel->dev_id);
  }
 }

 return 0;
}

int register_dmac(struct dma_info *info)
{
 unsigned int total_channels, i;

 INIT_LIST_HEAD(&info->list);

 printk(KERN_INFO "DMA: Registering %s handler (%d channel%s).\n",
        info->name, info->nr_channels, info->nr_channels > 1 ? "s" : "");

 BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels);

 info->pdev = platform_device_register_simple(info->name, -1,
           NULL, 0);
 if (IS_ERR(info->pdev))
  return PTR_ERR(info->pdev);

 /*
 * Don't touch pre-configured channels
 */

 if (!(info->flags & DMAC_CHANNELS_CONFIGURED)) {
  unsigned int size;

  size = sizeof(struct dma_channel) * info->nr_channels;

  info->channels = kzalloc(size, GFP_KERNEL);
  if (!info->channels)
   return -ENOMEM;
 }

 total_channels = get_nr_channels();
 info->first_vchannel_nr = total_channels;
 for (i = 0; i < info->nr_channels; i++) {
  struct dma_channel *chan = &info->channels[i];

  atomic_set(&chan->busy, 0);

  chan->chan  = info->first_channel_nr + i;
  chan->vchan = info->first_channel_nr + i + total_channels;

  memcpy(chan->dev_id, "Unused", 7);

  if (info->flags & DMAC_CHANNELS_TEI_CAPABLE)
   chan->flags |= DMA_TEI_CAPABLE;

  init_waitqueue_head(&chan->wait_queue);
  dma_create_sysfs_files(chan, info);
 }

 list_add(&info->list, ®istered_dmac_list);

 return 0;
}
EXPORT_SYMBOL(register_dmac);

void unregister_dmac(struct dma_info *info)
{
 unsigned int i;

 for (i = 0; i < info->nr_channels; i++)
  dma_remove_sysfs_files(info->channels + i, info);

 if (!(info->flags & DMAC_CHANNELS_CONFIGURED))
  kfree(info->channels);

 list_del(&info->list);
 platform_device_unregister(info->pdev);
}
EXPORT_SYMBOL(unregister_dmac);

static int __init dma_api_init(void)
{
 printk(KERN_NOTICE "DMA: Registering DMA API.\n");
 return proc_create_single("dma", 0, NULL, dma_proc_show) ? 0 : -ENOMEM;
}
subsys_initcall(dma_api_init);

MODULE_AUTHOR("Paul Mundt ");
MODULE_DESCRIPTION("DMA API for SuperH");
MODULE_LICENSE("GPL v2");

Messung V0.5
C=98 H=93 G=95

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.