zoukankan      html  css  js  c++  java
  • kernel/dma.c

    /* $Id: dma.c,v 1.5 1992/11/18 02:49:05 root Exp root $
     * linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c.
     * Written by Hennus Bergman, 1992.
     */

    #include <linux/kernel.h>
    #include <linux/errno.h>
    #include <asm/dma.h>


    /* A note on resource allocation:
     *
     * All drivers needing DMA channels, should allocate and release them
     * through the public routines `request_dma()' and `free_dma()'.
     *
     * In order to avoid problems, all processes should allocate resources in
     * the same sequence and release them in the reverse order.
     *
     * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA.
     * When releasing them, first release the DMA, then release the IRQ.
     * If you don't, you may cause allocation requests to fail unnecessarily.
     * This doesn't really matter now, but it will once we get real semaphores
     * in the kernel.
     */



    /* Channel n is busy iff dma_chan_busy[n] != 0.
     * DMA0 is reserved for DRAM refresh, I think.
     * DMA4 is reserved for cascading (?).
     */
     /* dma_chan_busy[n] != 0 表示该通道不可用
     * DMA0 用作DRAM的刷新.
     * DMA4 用作级连.
     */
    static volatile unsigned int dma_chan_busy[MAX_DMA_CHANNELS] = {
        1, 0, 0, 0, 1, 0, 0, 0
    };



    /* Atomically swap memory location [32 bits] with `newval'.
     * This avoid the cli()/sti() junk and related problems.
     * [And it's faster too :-)]
     * Maybe this should be in include/asm/mutex.h and be used for
     * implementing kernel-semaphores as well.
     */
     // 将*p指向的数据替换为newval.由关键字xchgl看,这个值是32位的值。
     // xchgl是原子操作,可以省去cli和sti.
    static __inline__ unsigned int mutex_atomic_swap(volatile unsigned int * p, unsigned int newval)
    {
        unsigned int semval = newval;

        /* If one of the operands for the XCHG instructions is a memory ref,
         * it makes the swap an uninterruptible RMW cycle.
         *
         * One operand must be in memory, the other in a register, otherwise
         * the swap may not be atomic.
         */

        asm __volatile__ ("xchgl %2, %0 "
                : /* outputs: semval   */ "=r" (semval)
                : /* inputs: newval, p */ "0" (semval), "m" (*p)
                );    /* p is a var, containing an address */
        return semval;
    } /* mutex_atomic_swap */


    //请求DMA,核心由上个函数mutex_atomic_swap完成
    int request_dma(unsigned int dmanr)
    {
        if (dmanr >= MAX_DMA_CHANNELS)
            return -EINVAL;

        if (mutex_atomic_swap(&dma_chan_busy[dmanr], 1) != 0)
            return -EBUSY;
        else
            /* old flag was 0, now contains 1 to indicate busy */
            return 0;
    } /* request_dma */

    //释放DMA,核心由函数mutex_atomic_swap完成
    void free_dma(unsigned int dmanr)
    {
        if (dmanr >= MAX_DMA_CHANNELS) {
            printk("Trying to free DMA%d ", dmanr);
            return;
        }

        if (mutex_atomic_swap(&dma_chan_busy[dmanr], 0) == 0)
            printk("Trying to free free DMA%d ", dmanr);
    } /* free_dma */


  • 相关阅读:
    装饰者模式(包装模式)
    内网穿透
    SpringMVC框架工作流程图及工作原理
    Java 使用 Socket 判断某服务能否连通
    最简单的一个socket客户端,保持连接服务端
    java读取txt文件
    SQL汇总
    最简单的一个socket服务端
    初级软件工程师怎么走向BATJ?——献给迷茫中的测试人
    软件测试工程师——100问面试题,你敢来接招吗?
  • 原文地址:https://www.cnblogs.com/xiaofengwei/p/3774007.html
Copyright © 2011-2022 走看看