⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dma.c

📁 linux 内核源代码
💻 C
字号:
/* *  linux/arch/arm/mach-pxa/dma.c * *  PXA DMA registration and IRQ dispatching * *  Author:	Nicolas Pitre *  Created:	Nov 15, 2001 *  Copyright:	MontaVista Software Inc. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 as *  published by the Free Software Foundation. */#include <linux/module.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/interrupt.h>#include <linux/errno.h>#include <asm/system.h>#include <asm/irq.h>#include <asm/hardware.h>#include <asm/dma.h>#include <asm/arch/pxa-regs.h>struct dma_channel {	char *name;	pxa_dma_prio prio;	void (*irq_handler)(int, void *);	void *data;};static struct dma_channel *dma_channels;static int num_dma_channels;int pxa_request_dma (char *name, pxa_dma_prio prio,			 void (*irq_handler)(int, void *),		 	 void *data){	unsigned long flags;	int i, found = 0;	/* basic sanity checks */	if (!name || !irq_handler)		return -EINVAL;	local_irq_save(flags);	do {		/* try grabbing a DMA channel with the requested priority */		for (i = 0; i < num_dma_channels; i++) {			if ((dma_channels[i].prio == prio) &&			    !dma_channels[i].name) {				found = 1;				break;			}		}		/* if requested prio group is full, try a hier priority */	} while (!found && prio--);	if (found) {		DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;		dma_channels[i].name = name;		dma_channels[i].irq_handler = irq_handler;		dma_channels[i].data = data;	} else {		printk (KERN_WARNING "No more available DMA channels for %s\n", name);		i = -ENODEV;	}	local_irq_restore(flags);	return i;}void pxa_free_dma (int dma_ch){	unsigned long flags;	if (!dma_channels[dma_ch].name) {		printk (KERN_CRIT			"%s: trying to free channel %d which is already freed\n",			__FUNCTION__, dma_ch);		return;	}	local_irq_save(flags);	DCSR(dma_ch) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;	dma_channels[dma_ch].name = NULL;	local_irq_restore(flags);}static irqreturn_t dma_irq_handler(int irq, void *dev_id){	int i, dint = DINT;	for (i = 0; i < num_dma_channels; i++) {		if (dint & (1 << i)) {			struct dma_channel *channel = &dma_channels[i];			if (channel->name && channel->irq_handler) {				channel->irq_handler(i, channel->data);			} else {				/*				 * IRQ for an unregistered DMA channel:				 * let's clear the interrupts and disable it.				 */				printk (KERN_WARNING "spurious IRQ for DMA channel %d\n", i);				DCSR(i) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;			}		}	}	return IRQ_HANDLED;}int __init pxa_init_dma(int num_ch){	int i, ret;	dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL);	if (dma_channels == NULL)		return -ENOMEM;	ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL);	if (ret) {		printk (KERN_CRIT "Wow!  Can't register IRQ for DMA\n");		kfree(dma_channels);		return ret;	}	/* dma channel priorities on pxa2xx processors:	 * ch 0 - 3,  16 - 19  <--> (0) DMA_PRIO_HIGH	 * ch 4 - 7,  20 - 23  <--> (1) DMA_PRIO_MEDIUM	 * ch 8 - 15, 24 - 31  <--> (2) DMA_PRIO_LOW	 */	for (i = 0; i < num_ch; i++)		dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW);	num_dma_channels = num_ch;	return 0;}EXPORT_SYMBOL(pxa_request_dma);EXPORT_SYMBOL(pxa_free_dma);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -