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

📄 pcidrv.c

📁 DM6437评估版BIOS下的PCI驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
    *vtpiocr  = 0xA01F ;

    /* wait for 33 VTP clock cycles */
    udelay (10000);
    *dftEnb   = 1 ;
    *vtpiocr  = 0xA000 | (*vtpr | 0x3FF) ;

    /* Wait for few more clock cycles */
    udelay (10000);
    *vtpiocr &= 0xFFFFDFFF ;
    *dftEnb   = 0 ;
}

/* ============================================================================
 *  @func   HAL_readDMA
 *
 *  @desc   DMAs contents from DSP memory to GPP Memory. Here read means DSP
 *          write.
 *
 *  @modif  None.
 *  ============================================================================
 */
Void
HAL_readDMA (Uint32       srcAddr,
             Uint32       dstAddr,
             Uint32       size)
{
    volatile DM64LCPCI_edmaRegs * edmaRegs = (DM64LCPCI_edmaRegs *) ((Uint32) regVirt + (DM64LCPCI_EDMAREG_BASE - 0x01C00000)) ;
    volatile DM64LCPCI_pciRegs *  pciRegs  = (DM64LCPCI_pciRegs *) ((Uint32) regVirt + (DM64LCPCI_PCIREG_BASE - 0x01C00000)) ;
    Uint32                        i        = 0 ;
    Uint32                        pageBase ;
    Uint32                        numUSec ;
    Uint32                        tmp ;

    if (size <= DM64LCPCI_PCIADLEN) {
        pageBase = dstAddr & DM64LCPCI_PCIADWRBITMASK ;
        pciRegs->PCIADDSUB [0] = pageBase ;
        printk ("<1>Page Base : %x %x\n", (int)pageBase, (int)dstAddr) ;
    }
    else {
        for (tmp = size, i = 0 ; tmp > 0 ; tmp -= DM64LCPCI_PCIADLEN, i++) {
            pageBase =   (dstAddr + (DM64LCPCI_PCIADLEN * i))
                       & DM64LCPCI_PCIADWRBITMASK ;
            pciRegs->PCIADDSUB [i] = pageBase ;
        }
    }

    do {
        /* Set the interrupt enable for 1st Channel. */
        edmaRegs->IESR |= 0x1 ;

        /* Clear any pending interrupt. */
        edmaRegs->ICR |= 0x1 ;

        /* Populate the Param entry. */
        edmaRegs->PARAMENTRY [0].OPTION       = 0x00100004 ;
        edmaRegs->PARAMENTRY [0].SRC          = srcAddr ;
        /* Calculate the DSP PCI address for the PC address */
        tmp = 0x30000000 + (dstAddr & ~DM64LCPCI_PCIADWRBITMASK) ;
        edmaRegs->PARAMENTRY [0].DST          = tmp ;

        /* Calculate the A & B count */
        if (size > 0x7000)  {
            tmp   = size / 0x7000 ;
            size -= (tmp * 0x7000) ;
            tmp <<= 16 ;
            tmp  |= 0x7000 ;
        }
        else {
            tmp = 0x10000 | size ;
            size = 0 ;
        }

        edmaRegs->PARAMENTRY [0].A_B_CNT      = tmp ;
        edmaRegs->PARAMENTRY [0].LINK_BCNTRLD = 0xFFFF ;
        edmaRegs->PARAMENTRY [0].SRC_DST_CIDX = 0 ;
        /* C Count is set to 1 since mostly size will not be more than 1GB */
        edmaRegs->PARAMENTRY [0].CCNT         = 0x1 ;
        /* no offset difference required */
        edmaRegs->PARAMENTRY [0].SRC_DST_BIDX = 0x70007000 ;

        /* Set the interrupt enable for 1st Channel. */
        edmaRegs->EESR |= 0x1 ;

        /* Clear any pending interrupt. */
        edmaRegs->ESR |= 0x1 ;

        /* wait for current DMA to finish. */
        numUSec = size / 132 ;
        do {
            udelay (numUSec) ;
            /* now check in steps of 10 usec. */
            numUSec = 10 ;
        } while ((edmaRegs->IPR & 0x1) == 0) ;
    } while (size != 0) ;

    /* Clear any pending interrupt. */
    edmaRegs->ICR |= 0x1 ;
}


/* ============================================================================
 *  @func   HAL_writeDMA
 *
 *  @desc   DMAs contents from GPP memory to DSP Memory. Here write means DSP
 *          read.
 *
 *  @modif  None.
 *  ============================================================================
 */
Void
HAL_writeDMA (Uint32       srcAddr,
              Uint32       dstAddr,
              Uint32       size)
{
    volatile DM64LCPCI_edmaRegs * edmaRegs = (DM64LCPCI_edmaRegs *) ((Uint32) regVirt + (DM64LCPCI_EDMAREG_BASE - 0x01C00000)) ;
    volatile DM64LCPCI_pciRegs *  pciRegs  = (DM64LCPCI_pciRegs *) ((Uint32) regVirt + (DM64LCPCI_PCIREG_BASE - 0x01C00000)) ;
    Uint32                        i        = 0 ;
    Uint32                        pageBase ;
    Uint32                        numUSec ;
    Uint32                        tmp ;

    if (size <= DM64LCPCI_PCIADLEN) {
        pageBase = srcAddr & DM64LCPCI_PCIADWRBITMASK ;
        pciRegs->PCIADDSUB [0] = pageBase ;
        printk ("<1>Page Base : %x %x\n", (int)pageBase, (int)srcAddr) ;
    }
    else {
        for (tmp = size, i = 0 ; tmp > 0 ; tmp -= DM64LCPCI_PCIADLEN, i++) {
            pageBase =   (srcAddr + (DM64LCPCI_PCIADLEN * i))
                       & DM64LCPCI_PCIADWRBITMASK ;
            pciRegs->PCIADDSUB [i] = pageBase ;
        }
    }

    do {
        /* Set the interrupt enable for 1st Channel. */
        edmaRegs->IESR  |= 0x1 ;

        /* Clear any pending interrupt. */
        edmaRegs->ICR |= 0x1 ;

        /* Populate the Param entry. */
        edmaRegs->PARAMENTRY [0].OPTION       = 0x00100004 ;

        /* Calculate the DSP PCI address for the PC address */
        tmp = 0x30000000 + (srcAddr & ~DM64LCPCI_PCIADWRBITMASK) ;
        edmaRegs->PARAMENTRY [0].SRC          = tmp ;
        edmaRegs->PARAMENTRY [0].DST          = dstAddr ;

        /* Calculate the A & B count */
        if (size > 0x7000)  {
            tmp   = size / 0x7000 ;
            size -= (tmp * 0x7000) ;
            tmp <<= 16 ;
            tmp  |= 0x7000 ;
        }
        else {
            tmp = 0x10000 | size ;
            size = 0 ;
        }

        edmaRegs->PARAMENTRY [0].A_B_CNT      = tmp ;
        edmaRegs->PARAMENTRY [0].LINK_BCNTRLD = 0xFFFF ;
        edmaRegs->PARAMENTRY [0].SRC_DST_CIDX = 0 ;
        /* no offset difference required */
        edmaRegs->PARAMENTRY [0].SRC_DST_BIDX = 0x70007000 ;
        /* C Count is set to 1 since mostly size will not be more than 1GB */
        edmaRegs->PARAMENTRY [0].CCNT         = 0x1 ;

        /* Set the interrupt enable for 1st Channel. */
        edmaRegs->EESR |= 0x1 ;

        /* Clear any pending interrupt. */
        edmaRegs->ESR |= 0x1 ;

        /* wait for current DMA to finish. */
        numUSec = size / 132 ;
        do {
            udelay (numUSec) ;
            /* now check in steps of 10 usec. */
            numUSec = 10 ;
        } while ((edmaRegs->IPR & 0x1) == 0) ;
    } while (size != 0) ;

    /* Clear any pending interrupt. */
    edmaRegs->ICR |= 0x1 ;
}


#define DM64LCPCI_LRESET_MASK   0x00000100
#define GEM_MDCTL               (0x01C41a00 + (4 * 39))
#define ADDR32(x)                 *((Uint32 *) ((Uint32)memVirt + x))
#define DM64LCPCI_DSPBOOTADDR   0x01C4000C

#define OP1                     0x02084068 /* MVKH.S1       0x10800000,A4 */
#define OP2                     0x0090B362 /* BNOP.S2X      A4,5          */
Uint32 dummy ;

int init_module(void)
{
    Uint8 * writeData ;
    Uint8 * readData ;
    Uint32  i     ;

    writeData = (Uint8 *) kmalloc (0x8000, GFP_DMA) ;
    readData = (Uint8 *) kmalloc (0x8000, GFP_DMA) ;

    printk("PCIDRV - Find PCI Devices\n");
    PCI_FindPciDevices () ;

    mdelay(1000);
    printk("PCIDRV - Reading Bar\n");
    PCI_readBAR () ;

    mdelay(1000);
    printk("PCIDRV - Enable Device\n");
    pci_enable_device (GEM) ;

    mdelay(1000);
    printk("PCIDRV - Set DRV Data\n");
    pci_set_drvdata (GEM, memVirt) ;

    mdelay(1000);
    printk("PCIDRV - Set Master\n");
    PCI_setMaster () ;
#if 0
    /* Enable the DDR2 PSC Module */
    HAL_changeState (13, 0x3) ;
    /* Programme the PLL1 (DDR2) to run at higher frequency. */
    HAL_cfgPLL1 (23, 11, 1) ;
    /* Programme the DDR PHY register corresponding to PLL1 frequency. */
    HAL_cfgDDR2 (162) ;
    /* Reset the DDR2 PSC Module */
    HAL_changeState (13, 0x1) ;
    /* Enable the DDR2 PSC Module */
    HAL_changeState (13, 0x3) ;
#endif

    PCI_dma () ;
    for (i = 0 ; i < 0x8000 ; i++) {
         writeData [i] = 0x42 ;
    }
    printk("Code ends here\n");
#if 0
    if (writeData && readData) {
        HAL_writeDMA ((Uint32) virt_to_bus (writeData), 0x80100000, 0x8000) ;
        HAL_readDMA  (0x80100000, (Uint32) virt_to_bus (readData), 0x8000) ;
        if (readData [0] == writeData [0]) {
            printk ("API DMA passed\n") ;
        }
        else {
            printk ("API DMA failed %x\n", readData [0]) ;
        }
    }
#endif
    mdelay(1000);
    printk("PCIDRV: Registering interrupt\n");
    HAL_PciDisableDspInterrupt () ;
    printk("Interrupt number is : %d\n", GEM->irq);
    request_irq (GEM->irq,   ISR_handler5,   SA_SHIRQ, "PCIDRV", &dummy) ;
    HAL_PciEnableDspInterrupt () ;
    mdelay(1000);
    printk("PCIDRV: Interrupts registered\n");

    if (regVirt) {
        /* put GEM in reset */
        *((Uint32 *) ((Uint32) regVirt + (GEM_MDCTL - 0x01C00000))) &= ~DM64LCPCI_LRESET_MASK ;

        /* Set the DSP boot address. */
        *((Uint32 *) ((Uint32) regVirt + (DM64LCPCI_DSPBOOTADDR - 0x01C00000))) = 0x10800000 ;
    }
    mdelay(1000);
    printk("PCIDRV: GEM is reset and Boot address is set\n");
    if (memVirt) {
        /* Write the self loop code at 0x10800000 */
        ADDR32 (0x0)  = OP1 ;
        ADDR32 (0x4)  = OP2 ;
        ADDR32 (0x8)  = 0x0 ;
        ADDR32 (0xC)  = 0x0 ;
        ADDR32 (0x10) = 0x0 ;
        ADDR32 (0x14) = 0x0 ;
        ADDR32 (0x18) = 0x0 ;
        ADDR32 (0x1C) = 0x0 ;
    }
    mdelay(1000);
    printk("PCIDRV: Opcode written\n");
    if (regVirt) {
        /* release the GEM from reset */
        *((Uint32 *) ((Uint32) regVirt + (GEM_MDCTL - 0x01C00000))) |= DM64LCPCI_LRESET_MASK ;
    }
    mdelay(1000);
    printk("PCIDRV: Release GEM reset\n");
    kfree(readData);
    kfree(writeData);
    return 0 ;
}

void cleanup_module(void)
{
    HAL_PciDisableDspInterrupt () ;

    iounmap(memVirt) ;
    if (pci_resource_flags (GEM, 0) & IORESOURCE_MEM) {
        /* Map the memory region. */
        release_mem_region (memBase,
                            memLen);
    }
    else {
        /* Map the memory region. */
        release_region (memBase,
                        memLen);
    }

    /* ---------------------------------------------------------------------
     * Unmap baseRegs region & release the reg region.
     * ---------------------------------------------------------------------
     */
    iounmap(ddrRegVirt) ;
    if (pci_resource_flags (GEM, 1) & IORESOURCE_MEM) {
        /* Map the memory region. */
        release_mem_region (ddrRegBase,
                            ddrRegLen);
    }
    else {
        /* Map the memory region. */
        release_region (ddrRegBase,
                        ddrRegLen);
    }

    /* ---------------------------------------------------------------------
     * Unmap baseRegs region & release the reg region.
     * ---------------------------------------------------------------------
     */
    iounmap(regVirt) ;
    if (pci_resource_flags (GEM, 2) & IORESOURCE_MEM) {
        /* Map the memory region. */
        release_mem_region (regBase,
                            regLen);
    }
    else {
        /* Map the memory region. */
        release_region (regBase,
                        regLen);
    }

    free_irq (GEM->irq, &dummy) ;
    /* Free the allocated memory for read-write */
    kfree((void*)rData);
    kfree((void*)wData);
}

//gcc -I/usr/src/linux-2.4/include/ -DMODULE -D__KERNEL__ -c gem.c

⌨️ 快捷键说明

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