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 */


  • 相关阅读:
    Leetcode Reverse Words in a String
    topcoder SRM 619 DIV2 GoodCompanyDivTwo
    topcoder SRM 618 DIV2 MovingRooksDiv2
    topcoder SRM 618 DIV2 WritingWords
    topcoder SRM 618 DIV2 LongWordsDiv2
    Zepto Code Rush 2014 A. Feed with Candy
    Zepto Code Rush 2014 B
    Codeforces Round #245 (Div. 2) B
    Codeforces Round #245 (Div. 2) A
    Codeforces Round #247 (Div. 2) B
  • 原文地址:https://www.cnblogs.com/xiaofengwei/p/3774007.html
Copyright © 2011-2022 走看看