Please note as of Wednesday, August 15th, 2018 this wiki has been set to read only. If you are a TI Employee and require Edit ability please contact x0211426 from the company directory.

Test PCI Driver

From Texas Instruments Wiki
Jump to: navigation, search

Introduction

This document describes the PCI test driver, which can be used to test the PCI hardware before running DSPLink.

Overview

This PCI driver tests all hardware related aspect needed by DSPLink for providing support on the desired platform. DSPLink requires memory to be shared between HOST and device, power management, interrupts between HOST and device and EDMA features of DSP device. This test driver tests each of these components.

Details

This test driver is written from the DSP and HAL logic of DSPLink source. APIs provided by this test driver are somewhat similar to APIs provided by DSPLink DSP and HAL code.
It gives out error message incase of failure otherwise it prints successful message.

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>

/** ============================================================================
 *  @macro  Data types
 *
 *  @desc   Basic data types
 *  ============================================================================
 */
typedef signed char         Int8 ;      /*  8 bit value */
typedef signed short int    Int16 ;     /* 16 bit value */
typedef signed long  int    Int32 ;     /* 32 bit value */

typedef unsigned char       Uint8 ;     /*  8 bit value */
typedef unsigned short int  Uint16 ;    /* 16 bit value */
typedef unsigned long  int  Uint32 ;    /* 32 bit value */

typedef float               Real32 ;    /* 32 bit value */
typedef double              Real64 ;    /* 64 bit value */

typedef short int           Bool ;      /* 16 bit value */

typedef char                Char8 ;     /*  8 bit value */
typedef short               Char16 ;    /* 16 bit value */

typedef unsigned char       Uchar8 ;    /*  8 bit value */
typedef unsigned short      Uchar16 ;   /* 16 bit value */

#define Void                void
typedef void *              Pvoid ;

typedef Char8 *             Pstr ;
typedef Uchar8 *            Pustr ;

/** ============================================================================
 *  @const  PCI_TI_VENDOR
 *
 *  @desc   TI Vendor ID.
 *  ============================================================================
 */
#define PCI_TI_VENDOR   0x104c

/** ============================================================================
 *  @const  PCI_TI_DEVICE
 *
 *  @desc   PCI Device ID.
 *  ============================================================================
 */
#define PCI_TI_DEVICE   0xB001

/** ============================================================================
 *  @const   DM64LCPCI_DEVREG_BASE
 *
 *  @desc    Base address of Device config registers.
 *  ============================================================================
 */
#define DM64LCPCI_DEVREG_BASE      0x01C40000

/** ============================================================================
 *  @const   DM64LCPCI_PLLREG_BASE
 *
 *  @desc    Base address of PLL0 registers.
 *  ============================================================================
 */
#define DM64LCPCI_PLL0REG_BASE      0x01C40800

/** ============================================================================
 *  @const   DM64LCPCI_PLLREG_BASE
 *
 *  @desc    Base address of PLL1 registers.
 *  ============================================================================
 */
#define DM64LCPCI_PLL1REG_BASE      0x01C40C00

/** ============================================================================
 *  @const   DM64LCPCI_EDMAREG_BASE
 *
 *  @desc    Base address of EDMA registers.
 *  ============================================================================
 */
#define DM64LCPCI_EDMAREG_BASE      0x01C00000

/** ============================================================================
 *  @const   DM64LCPCI_DDRREG_BASE
 *
 *  @desc    Base address of DDR PHY registers.
 *  ============================================================================
 */
#define DM64LCPCI_DDRREG_BASE       0x20000000

/** ============================================================================
 *  @const   DM64LCPCI_PSCREG_BASE
 *
 *  @desc    Base address of PSC registers.
 *  ============================================================================
 */
#define DM64LCPCI_PSCREG_BASE       0x01C41000

/** ============================================================================
 *  @const   DM64LCPCI_PCIREG_BASE
 *
 *  @desc    Base address of PCI backend registers.
 *  ============================================================================
 */
#define DM64LCPCI_PCIREG_BASE       0x01C1A000

/** ============================================================================
 *  @const   DM64LCPCI_SOFTINT0_MASK
 *
 *  @desc    Mask for generating soft int0 (DSP->GPP)
 *  ============================================================================
 */
#define DM64LCPCI_SOFTINT0_MASK       0x01000000

/** ============================================================================
 *  @const   DM64LCPCI_SOFTINT1_MASK
 *
 *  @desc    Mask for generating soft int1 (GPP->DSP)
 *  ============================================================================
 */
#define DM64LCPCI_SOFTINT1_MASK       0x02000000

/** ============================================================================
 *  @const   DM64LCPCI_LRESET_MASK
 *
 *  @desc    Mask for reseting/releasing GEM.
 *  ============================================================================
 */
#define DM64LCPCI_LRESET_MASK         0x00000100

/** ============================================================================
 *  @const   DM64LCPCI_INTSTATUS_MASK
 *
 *  @desc    Bitmask for Interrupt status (DSP->GPP)
 *  ============================================================================
 */
#define DM64LCPCI_INTSTATUS_MASK      0x00080000

/** ============================================================================
 *  @const   DM64LCPCI_PCIADLEN
 *
 *  @desc    Length each segment of addressable PCI Space..
 *  ============================================================================
 */
#define DM64LCPCI_PCIADLEN            0x00800000

/** ============================================================================
 *  @const   DM64LCPCI_PCIADWRBITMASK
 *
 *  @desc    Mask indicating writeable bits in PCI Address Window registers.
 *  ============================================================================
 */
#define DM64LCPCI_PCIADWRBITMASK      0xFF800000

/** ============================================================================
 *  @const   DM64LCPCI_PAGEWRBITMASK
 *
 *  @desc    Mask indicating writeable bits in PCI Base Address Mask Register5.
 *  ============================================================================
 */
#define DM64LCPCI_PAGEWRBITMASK       0xFF800000

/** ============================================================================
 *  @name   DM64LCPCI_pllRegs
 *
 *  @desc   Register Overlay Structure for Device config registers.
 *  ============================================================================
 */
typedef struct DM64LCPCI_devRegs_tag {
    volatile Uint32 PINMUX0       ;
    volatile Uint32 PINMUX1       ;
    volatile Uint32 DSPBOOTADDR   ;
    volatile Uint32 BOOTCMPLT     ;
    volatile Uint32 RSVD0         ;
    volatile Uint32 BOOTCFG       ;
    volatile Uint32 VDD1P0V_ADJ   ;
    volatile Uint32 VDD1P2V_ADJ   ;
    volatile Uint32 DDR_SLEW      ;
    volatile Uint32 PERIPHEN      ;
    volatile Uint32 DEVICE_ID     ;
    volatile Uint32 DAC_DEMEN     ;
    volatile Uint32 UHPICTL       ;
    volatile Uint32 RSVD1 [2]     ;
    volatile Uint32 MSTPRI0       ;
    volatile Uint32 MSTPRI1       ;
    volatile Uint32 VPSS_CLK_CTRL ;
    volatile Uint32 VDD3P3V_PWRDN ;
    volatile Uint32 DFT_ENABLE    ;
    volatile Uint32 SEC_SCAN_REG  ;
    volatile Uint32 SEC_TEST_REG  ;
    volatile Uint32 SEC_TAP_CTL   ;
    volatile Uint32 PUBLIC_KEY0   ;
    volatile Uint32 PUBLIC_KEY1   ;
    volatile Uint32 PUBLIC_KEY2   ;
    volatile Uint32 PUBLIC_KEY3   ;
    volatile Uint32 VLYNQ_DELAY   ;
    volatile Uint32 SEC_PSEUDO0   ;
    volatile Uint32 SEC_PSEUDO1   ;
    volatile Uint32 RSVD2 [3]     ;
    volatile Uint32 TIMERCTL      ;
    volatile Uint32 TPTCCCFG      ;
    volatile Uint32 RSVD3         ;
} DM64LCPCI_devRegs ;

/** ============================================================================
 *  @name   DM64LCPCI_pllRegs
 *
 *  @desc   Register Overlay Structure for PLL.
 *  ============================================================================
 */
typedef struct DM64LCPCI_pllRegs_tag {
    volatile Uint32 PID         ;
    volatile Uint8  RSVD0 [220] ;
    volatile Uint32 FUSERR      ;
    volatile Uint32 RSTYPE      ;
    volatile Uint32 RSTDEF      ;
    volatile Uint8  RSVD1 [20]  ;
    volatile Uint32 PLLCTL      ;
    volatile Uint32 OCSEL       ;
    volatile Uint32 SECCTL      ;
    volatile Uint8  RSVD2 [4]   ;
    volatile Uint32 PLLM        ;
    volatile Uint32 PREDIV      ;
    volatile Uint32 PLLDIV1     ;
    volatile Uint32 PLLDIV2     ;
    volatile Uint32 PLLDIV3     ;
    volatile Uint32 OSCDIV1     ;
    volatile Uint32 POSTDIV     ;
    volatile Uint32 BPDIV       ;
    volatile Uint32 WAKEUP      ;
    volatile Uint8  RSVD3 [4]   ;
    volatile Uint32 PLLCMD      ;
    volatile Uint32 PLLSTAT     ;
    volatile Uint32 ALNCTL      ;
    volatile Uint32 DCHANGE     ;
    volatile Uint32 CKEN        ;
    volatile Uint32 CKSTAT      ;
    volatile Uint32 SYSTAT      ;
    volatile Uint8  RSVD4 [12]  ;
    volatile Uint32 PLLDIV4     ;
    volatile Uint32 PLLDIV5     ;
    volatile Uint32 PLLDIV6     ;
    volatile Uint32 PLLDIV7     ;
    volatile Uint32 PLLDIV8     ;
} DM64LCPCI_pllRegs ;

/** ============================================================================
 *  @name   DM64LCPCI_ddrRegs
 *
 *  @desc   Register Overlay Structure for DDR.
 *  ============================================================================
 */
typedef struct  {
    volatile Uint32 ERCSR       ;
    volatile Uint32 SDRSTAT     ;
    volatile Uint32 SDBCR       ;
    volatile Uint32 SDRCR       ;
    volatile Uint32 SDTIMR      ;
    volatile Uint32 SDTIMR2     ;
    volatile Uint8  RSVD0 [8]   ;
    volatile Uint32 VBPR        ;
    volatile Uint8  RSVD1 [4]   ;
    volatile Uint32 VBCFG1      ;
    volatile Uint32 VBCFG2      ;
    volatile Uint8  RSVD2 [16]  ;
    volatile Uint32 PERFC1R     ;
    volatile Uint32 PERFC2R     ;
    volatile Uint32 PCCR        ;
    volatile Uint32 PCMRSR      ;
    volatile Uint8  RSVD3 [48]  ;
    volatile Uint32 ASYNCCS2CR  ;
    volatile Uint32 ASYNCCS3CR  ;
    volatile Uint32 ASYNCCS4CR  ;
    volatile Uint32 ASYNCCS5CR  ;
    volatile Uint8  RSVD4 [16]  ;
    volatile Uint32 AWCCR       ;
    volatile Uint8  RSVD5 [28]  ;
    volatile Uint32 IRR         ;
    volatile Uint32 IMR         ;
    volatile Uint32 IMSR        ;
    volatile Uint32 IMCR        ;
    volatile Uint8  RSVD6 [16]  ;
    volatile Uint32 DDRPHYREV   ;
    volatile Uint32 DDRPHYCR    ;
    volatile Uint32 DDRPHYSR    ;
    volatile Uint8  RSVD7 [4]   ;
    volatile Uint32 VTPCTRL     ;
    volatile Uint32 VTPSTAT     ;
} DM64LCPCI_ddrRegs ;

/** ============================================================================
 *  @name   DM64LCPCI_pscRegs
 *
 *  @desc   Register Overlay Structure for PSC.
 *  ============================================================================
 */
typedef struct DM64LCPCI_pscRegs_tag {
    volatile Uint32 PID          ;
    volatile Uint8  RSVD0 [12]   ;
    volatile Uint32 GBLCTL       ;
    volatile Uint8  RSVD1 [4]    ;
    volatile Uint32 INTEVAL      ;
    volatile Uint8  RSVD2 [36]   ;
    volatile Uint32 ERRPR0       ;
    volatile Uint32 ERRPR1       ;
    volatile Uint8  RSVD3 [8]    ;
    volatile Uint32 ERRCR0       ;
    volatile Uint32 ERRCR1       ;
    volatile Uint8  RSVD4 [8]    ;
    volatile Uint32 PERRPR       ;
    volatile Uint8  RSVD5 [4]    ;
    volatile Uint32 PERRCR       ;
    volatile Uint8  RSVD6 [4]    ;
    volatile Uint32 EPCPR        ;
    volatile Uint8  RSVD7 [4]    ;
    volatile Uint32 EPCR         ;
    volatile Uint8  RSVD8 [132]  ;
    volatile Uint32 RAILSTAT     ;
    volatile Uint32 RAILCTL      ;
    volatile Uint32 RAILSEL      ;
    volatile Uint8  RSVD9 [20]   ;
    volatile Uint32 PTCMD        ;
    volatile Uint8  RSVD10 [4]   ;
    volatile Uint32 PTSTAT       ;
    volatile Uint8  RSVD11 [212] ;
    volatile Uint32 PDSTAT [41]  ;
    volatile Uint8  RSVD12 [92]  ;
    volatile Uint32 PDCTL [41]   ;
    volatile Uint8  RSVD13 [348] ;
    volatile Uint32 MRSTOUT [2]  ;
    volatile Uint8  RSVD14 [8]   ;
    volatile Uint32 MCKOUT [2]   ;
    volatile Uint8  RSVD15 [232] ;
    volatile Uint32 MDCFG [41]   ;
    volatile Uint8  RSVD16 [348] ;
    volatile Uint32 MDSTAT [41]  ;
    volatile Uint8  RSVD17 [348] ;
    volatile Uint32 MDCTL [41]   ;
} DM64LCPCI_pscRegs ;

/** ============================================================================
 *  @name   DM64LCPCI_paramEntry
 *
 *  @desc   Register Overlay Structure for PARAMENTRY.
 *  ============================================================================
 */
typedef struct DM64LCPCI_paramEntry_tags {
    volatile Uint32 OPTION           ;
    volatile Uint32 SRC           ;
    volatile Uint32 A_B_CNT       ;
    volatile Uint32 DST           ;
    volatile Uint32 SRC_DST_BIDX  ;
    volatile Uint32 LINK_BCNTRLD  ;
    volatile Uint32 SRC_DST_CIDX  ;
    volatile Uint32 CCNT          ;
} DM64LCPCI_paramEntry ;

/** ============================================================================
 *  @name   DM64LCPCI_edmaRegs
 *
 *  @desc   Register Overlay Structure for EDMA.
 *  ============================================================================
 */
typedef struct DM64LCPCI_edmaRegs_tag {
    volatile Uint32      REV                ;
    volatile Uint32      CCCFG              ;
    volatile Uint8       RSVD0 [248]        ;
    volatile Uint32      DCHMAP [64]        ;
    volatile Uint32      QCHMAP [8]         ;
    volatile Uint8       RSVD1 [32]         ;
    volatile Uint32      DMAQNUM [8]        ;
    volatile Uint32      QDMAQNUM           ;
    volatile Uint8       RSVD2 [28]         ;
    volatile Uint32      QUETCMAP           ;
    volatile Uint32      QUEPRI             ;
    volatile Uint8       RSVD3 [120]        ;
    volatile Uint32      EMR                ;
    volatile Uint32      EMRH               ;
    volatile Uint32      EMCR               ;
    volatile Uint32      EMCRH              ;
    volatile Uint32      QEMR               ;
    volatile Uint32      QEMCR              ;
    volatile Uint32      CCERR              ;
    volatile Uint32      CCERRCLR           ;
    volatile Uint32      EEVAL              ;
    volatile Uint8       RSVD4  [28]        ;
    volatile Uint8       RSVD5 [64]         ;
    volatile Uint32      QRAE [8]           ;
    volatile Uint8       RSVD6[96]          ;
    volatile Uint8       RSVD7 [512]        ;
    volatile Uint32      QSTAT [8]          ;
    volatile Uint32      QWMTHRA            ;
    volatile Uint32      QWMTHRB            ;
    volatile Uint8       RSVD8 [24]         ;
    volatile Uint32      CCSTAT             ;
    volatile Uint8       RSVD9 [188]        ;
    volatile Uint32      AETCTL             ;
    volatile Uint32      AETSTAT            ;
    volatile Uint32      AETCMD             ;
    volatile Uint8       RSVD10 [244]       ;
    volatile Uint32      MPFAR              ;
    volatile Uint32      MPFSR              ;
    volatile Uint32      MPFCR              ;
    volatile Uint32      MPPAG              ;
    volatile Uint32      MPPA [8]           ;
    volatile Uint8       RSVD11 [2000]      ;
    volatile Uint32      ER                 ;
    volatile Uint32      ERH                ;
    volatile Uint32      ECR                ;
    volatile Uint32      ECRH               ;
    volatile Uint32      ESR                ;
    volatile Uint32      ESRH               ;
    volatile Uint32      CER                ;
    volatile Uint32      CERH               ;
    volatile Uint32      EER                ;
    volatile Uint32      EERH               ;
    volatile Uint32      EECR               ;
    volatile Uint32      EECRH              ;
    volatile Uint32      EESR               ;
    volatile Uint32      EESRH              ;
    volatile Uint32      SER                ;
    volatile Uint32      SERH               ;
    volatile Uint32      SECR               ;
    volatile Uint32      SECRH              ;
    volatile Uint8       RSVD12 [8]         ;
    volatile Uint32      IER                ;
    volatile Uint32      IERH               ;
    volatile Uint32      IECR               ;
    volatile Uint32      IECRH              ;
    volatile Uint32      IESR               ;
    volatile Uint32      IESRH              ;
    volatile Uint32      IPR                ;
    volatile Uint32      IPRH               ;
    volatile Uint32      ICR                ;
    volatile Uint32      ICRH               ;
    volatile Uint32      IEVAL              ;
    volatile Uint8       RSVD13 [4]         ;
    volatile Uint32      QER                ;
    volatile Uint32      QEER               ;
    volatile Uint32      QEECR              ;
    volatile Uint32      QEESR              ;
    volatile Uint32      QSER               ;
    volatile Uint32      QSECR              ;
    volatile Uint8       RSVD14 [3944]      ;
    volatile Uint8       RSVD15 [4096]      ;
    volatile Uint8       RSVD16 [4096]      ;
    DM64LCPCI_paramEntry PARAMENTRY[512]    ;
} DM64LCPCI_edmaRegs ;

/** ============================================================================
 *  @name   DM64LCPCI_pciRegs
 *
 *  @desc   PCI Back end register overlay structure.
 *  ============================================================================
 */
typedef struct DM64LCPCI_pciRegs_tag {
    volatile Uint32 PCIREVID       ;
    volatile Uint8  RSVD0 [12]     ;
    volatile Uint32 PCISTATSET     ;
    volatile Uint32 PCISTATCLR     ;
    volatile Uint8  RSVD1 [8]      ;
    volatile Uint32 PCIHINTSET     ;
    volatile Uint32 PCIHINTCLR     ;
    volatile Uint8  RSVD2 [8]      ;
    volatile Uint32 PCIBINTSET     ;
    volatile Uint32 PCIBINTCLR     ;
    volatile Uint32 PCIBCLKMGT     ;
    volatile Uint8  RSVD3 [196]    ;
    volatile Uint32 PCIVENDEVMIR   ;
    volatile Uint32 PCICSRMIR      ;
    volatile Uint32 PCICLREVMIR    ;
    volatile Uint32 PCICLINEMIR    ;
    volatile Uint32 PCIBAR0MSK     ;
    volatile Uint32 PCIBAR1MSK     ;
    volatile Uint32 PCIBAR2MSK     ;
    volatile Uint32 PCIBAR3MSK     ;
    volatile Uint32 PCIBAR4MSK     ;
    volatile Uint32 PCIBAR5MSK     ;
    volatile Uint8  RSVD4[4]       ;
    volatile Uint32 PCISUBIDMIR    ;
    volatile Uint8  RSVD5 [4]      ;
    volatile Uint32 PCICPBPTRMIR   ;
    volatile Uint8  RSVD6 [4]      ;
    volatile Uint32 PCILGINTMIR    ;
    volatile Uint8  RSVD7 [64]     ;
    volatile Uint32 PCISLVCNTL     ;
    volatile Uint8  RSVD8 [60]     ;
    volatile Uint32 PCIBAR0TRL     ;
    volatile Uint32 PCIBAR1TRL     ;
    volatile Uint32 PCIBAR2TRL     ;
    volatile Uint32 PCIBAR3TRL     ;
    volatile Uint32 PCIBAR4TRL     ;
    volatile Uint32 PCIBAR5TRL     ;
    volatile Uint8  RSVD9 [8]      ;
    volatile Uint32 PCIBARMIR [6]  ;
    volatile Uint8  RSVD10 [264]   ;
    volatile Uint32 PCIMCFGDAT     ;
    volatile Uint32 PCIMCFGADR     ;
    volatile Uint32 PCIMCFGCMD     ;
    volatile Uint8  RSVD11 [4]     ;
    volatile Uint32 PCIMSTCFG      ;
    volatile Uint32 PCIADDSUB [32] ;
    volatile Uint32 PCIVENDEVPRG   ;
    volatile Uint32 PCICMDSTATPRG  ;
    volatile Uint32 PCICLREVPRG    ;
    volatile Uint32 PCISUBIDPRG    ;
    volatile Uint32 PCIMAXLGPRG    ;
    volatile Uint32 PCILRSTREG     ;
    volatile Uint32 PCICFGDONE     ;
    volatile Uint32 PCIBAR0MPRG    ;
    volatile Uint32 PCIBAR1MPRG    ;
    volatile Uint32 PCIBAR2MPRG    ;
    volatile Uint32 PCIBAR3MPRG    ;
    volatile Uint32 PCIBAR4MPRG    ;
    volatile Uint32 PCIBAR5MPRG    ;
    volatile Uint32 PCIBAR0PRG     ;
    volatile Uint32 PCIBAR1PRG     ;
    volatile Uint32 PCIBAR2PRG     ;
    volatile Uint32 PCIBAR3PRG     ;
    volatile Uint32 PCIBAR4PRG     ;
    volatile Uint32 PCIBAR5PRG     ;
    volatile Uint32 PCIBAR0TRLPRG  ;
    volatile Uint32 PCIBAR1TRLPRG  ;
    volatile Uint32 PCIBAR2TRLPRG  ;
    volatile Uint32 PCIBAR3TRLPRG  ;
    volatile Uint32 PCIBAR4TRLPRG  ;
    volatile Uint32 PCIBAR5TRLPRG  ;
    volatile Uint32 PCIBASENPRG    ;
} DM64LCPCI_pciRegs ;


struct pci_dev * GEM = NULL ;

Uint32   regBase = 0 ;
Uint32   memBase = 0 ;
Uint32   ddrRegBase = 0 ;

Uint32 * regVirt = NULL ;
Uint32 * memVirt = NULL ;
Uint32 * ddrRegVirt = NULL ;

Uint32   memLen  = 0 ;
Uint32   regLen  = 0 ;
Uint32   ddrRegLen  = 0 ;

Int32    irqNo ;


/* ============================================================================
 *  @func   PCI_FindPciDevices
 *
 *  @desc   This function locates DM642 PCI cards on system.
 *
 *  @modif  None.
 *  ============================================================================
 */
Void
PCI_FindPciDevices (Void)
{
    struct pci_dev * dev = NULL ;

    while ((dev = pci_find_device (PCI_TI_VENDOR, PCI_TI_DEVICE, dev)) != NULL)
    {
        irqNo = dev->irq ;
        GEM = dev ;
        break ;
    }
}

/* ============================================================================
 *  @func   PCI_readBAR
 *
 *  @desc   This function reads config.
 *
 *  @modif  None.
 *  ============================================================================
 */
Void PCI_readBAR (Void)
{
    Uint32  barStart [3]  ;
    Uint32  barLen   [3]  ;
    Uint32  barFlags [3]  ;

    barStart [0] = pci_resource_start (GEM, 0);
    barLen   [0] = pci_resource_len   (GEM, 0);
    barFlags [0] = pci_resource_flags (GEM, 0);
    barStart [1] = pci_resource_start (GEM, 1);
    barLen   [1] = pci_resource_len   (GEM, 1);
    barFlags [1] = pci_resource_flags (GEM, 1);
    barStart [2] = pci_resource_start (GEM, 2);
    barLen   [2] = pci_resource_len   (GEM, 2);
    barFlags [2] = pci_resource_flags (GEM, 2);

    /* ---------------------------------------------------------------------
     * Map the L2RAM memory region
     * ---------------------------------------------------------------------
     */
    if (barFlags [0] & IORESOURCE_MEM) {
        memBase = barStart [0] ;
        /* Map the memory region. */
        request_mem_region (memBase,
                            barLen [0],
                            "DSPLINK");
    }
    else {
        /* Map the memory region. */
        request_region (memBase,
                        barLen [0],
                        "DSPLINK");
    }

    if (memBase > 0) {
        memVirt = ioremap (barStart [0],
                           barLen [0]) ;
    }

    /* ---------------------------------------------------------------------
     * Map the DDR REG memory region
     * ---------------------------------------------------------------------
     */
    if (barFlags [1] & IORESOURCE_MEM) {
        ddrRegBase = barStart [1] ;
        /* Map the memory region. */
        request_mem_region (ddrRegBase,
                            barLen [1],
                            "DSPLINK");
    }
    else {
        /* Map the memory region. */
        request_region (ddrRegBase,
                        barLen [1],
                        "DSPLINK");
    }

    if (ddrRegBase > 0) {
        ddrRegVirt = ioremap (barStart [1],
                              barLen [1]) ;
    }

    /* ---------------------------------------------------------------------
     * Map the REG memory region
     * ---------------------------------------------------------------------
     */
    if (barFlags [2] & IORESOURCE_MEM) {
        regBase = barStart [2] ;
        /* Map the memory region. */
        request_mem_region (regBase,
                            barLen [2],
                            "DSPLINK");
    }
    else {
        /* Map the memory region. */
        request_region (regBase,
                        barLen [2],
                        "DSPLINK");
    }

    if (regBase > 0) {
        regVirt = ioremap (barStart [2],
                           barLen [2]) ;
    }

    memLen    = barLen [0] ;
    ddrRegLen = barLen [1] ;
    regLen    = barLen [2] ;
}

/* =============================================================================
 *  @func   PCI_setMaster
 *
 *  @desc   This function makes the given device to be master.
 *
 *  @modif  None.
 *  ============================================================================
 */
Void
PCI_setMaster (void)
{
    Int32   retVal ;
    Uint16  cmdVal ;
    struct pci_dev * dev ;

    dev = GEM ;

    /* set the DMA mask */
    if (pci_set_dma_mask (dev, 0xfffffff0ULL)) {
    }

    /*
     * set the desired PCI dev to be master, this internally sets the latency
     * timer.
     */
    pci_set_master (dev) ;
    pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);

    /* Add support memory write invalidate */
    retVal = pci_set_mwi (dev) ;

    pci_read_config_word (dev, PCI_COMMAND, (u16 *) &cmdVal) ;
    /* and set the master bit in command register. */
    cmdVal |=   PCI_COMMAND_MEMORY
              | PCI_COMMAND_MASTER
              | PCI_COMMAND_SERR  ;
    /* and clear the interrupt disable bit in command register. */
    cmdVal &=   ~PCI_COMMAND_INTX_DISABLE;
    pci_write_config_word (dev, PCI_COMMAND, cmdVal) ;
}



/* =============================================================================
 *  @func   HAL_CheckPciInterrupt
 *
 *  @desc   This function check whether interrupt is generated by DM642 or not.
 *
 *  @modif  None.
 *  ============================================================================
 */
Bool
HAL_CheckPciInterrupt (void)
{
    volatile DM64LCPCI_pciRegs * pciRegs = (DM64LCPCI_pciRegs *) ((Uint32) regVirt + (DM64LCPCI_PCIREG_BASE - 0x01C00000)) ;
    Bool                 status = 0 ;

    if (   (pciRegs->PCICSRMIR & DM64LCPCI_INTSTATUS_MASK)
        == (DM64LCPCI_INTSTATUS_MASK)) {
        status = 1 ;
    }

    return status ;
}


/** ============================================================================
 *  @func   HAL_PciClearDspInterrupt
 *
 *  @desc   Clear pending interrupt from DSP to Host.
 *
 *  @modif  None.
 *  ============================================================================
 */
Void
HAL_PciClearDspInterrupt (Void)
{
    volatile DM64LCPCI_pciRegs * pciRegs = (DM64LCPCI_pciRegs *) ((Uint32) regVirt + (DM64LCPCI_PCIREG_BASE - 0x01C00000)) ;

    pciRegs->PCISTATCLR |= DM64LCPCI_SOFTINT0_MASK ;
}


/** ============================================================================
 *  @func   HAL_PciEnableDspInterrupt
 *
 *  @desc   Allow the DSP to generate interrupts to the Host.
 *
 *  @modif  None.
 *  ============================================================================
 */
Void
HAL_PciEnableDspInterrupt (Void)
{
    volatile DM64LCPCI_pciRegs * pciRegs = (DM64LCPCI_pciRegs *) ((Uint32) regVirt + (DM64LCPCI_PCIREG_BASE - 0x01C00000)) ;

    pciRegs->PCIHINTSET |= DM64LCPCI_SOFTINT0_MASK ;
}


/** ============================================================================
 *  @func   HAL_PciDisableDspInterrupt
 *
 *  @desc   Disallow the DSP to generate interrupts to the Host.
 *
 *  @modif  None.
 *  ============================================================================
 */
Void
HAL_PciDisableDspInterrupt (Void)
{
    volatile DM64LCPCI_pciRegs * pciRegs = (DM64LCPCI_pciRegs *) ((Uint32) regVirt + (DM64LCPCI_PCIREG_BASE - 0x01C00000)) ;

    pciRegs->PCIHINTCLR |= DM64LCPCI_SOFTINT0_MASK ;
}


/*  ----------------------------------------------------------------------------
 *  @func   HAL_changeState
 *
 *  @desc   Change power module state to ( ENABLE, DISABLE, SYNCRESET, RESET ).
 *
 *  @modif  None
 *  ----------------------------------------------------------------------------
 */
Void
HAL_changeState (Uint32 lpscNum, Uint16 state)
{
    volatile DM64LCPCI_pscRegs * pscRegs = (DM64LCPCI_pscRegs *) ((Uint32) regVirt + (DM64LCPCI_PSCREG_BASE - 0x01C00000)) ;

    if ((pscRegs->MDSTAT [lpscNum] & 0x001F) == state) {
        return ;
    }
    /*  ------------------------------------------------------------------------
     *  Step 1 - Wait for PTSTAT.GOSTAT to clear
     *  ------------------------------------------------------------------------
     */
    while (pscRegs->PTSTAT & 0x1) ;

    /*  ------------------------------------------------------------------------
     *  Step 2 - Set MDCTLx.NEXT to new state
     *  ------------------------------------------------------------------------
     */
    pscRegs->MDCTL [lpscNum] &= 0xFFE0 ;
    pscRegs->MDCTL [lpscNum] |= state  ;

    /*  ------------------------------------------------------------------------
     *  Step 3 - Start power transition ( set PTCMD.GO to 1 )
     *  ------------------------------------------------------------------------
     */
    pscRegs->PTCMD = 0x0001 ;

    /*  ------------------------------------------------------------------------
     *  Step 4 - Wait for PTSTAT.GOSTAT to clear
     *  ------------------------------------------------------------------------
     */
    while (pscRegs->PTSTAT & 0x1) ;

    /*  ------------------------------------------------------------------------
     *  Step 5 - Verify state changed
     *  ------------------------------------------------------------------------
     */
    while ((pscRegs->MDSTAT [lpscNum] & 0x001F) != state) ;
}


/*  ----------------------------------------------------------------------------
 *  @func   HAL_cfgPLL1
 *
 *  @desc   Configures the PLL1.
 *
 *  @modif  None
 *  ----------------------------------------------------------------------------
 */
Void
HAL_cfgPLL1 (Uint32       pllm,
             Uint32       div1,
             Uint32       div2)
{
    volatile DM64LCPCI_pllRegs * pllRegs = (DM64LCPCI_pllRegs *) ((Uint32) regVirt + (DM64LCPCI_PLL1REG_BASE - 0x01C00000)) ;

    /*  ------------------------------------------------------------------------
     *  Step 1 - Set PLL to BYPASS mode and select clock source.
     *  ------------------------------------------------------------------------
     */
    pllRegs->PLLCTL &= 0xFFFFFEFF ;
    pllRegs->PLLCTL |= 0x0 ;
    pllRegs->PLLCTL &= 0xFFFFFFDF ;
    pllRegs->PLLCTL &= 0xFFFFFFFE ;

    udelay (10000) ;

    pllRegs->PLLCTL &= 0xFFFFFFF7 ;
    pllRegs->PLLCTL |= 0x00000010 ;
    pllRegs->PLLCTL &= 0xFFFFFFFD ;
    pllRegs->PLLCTL &= 0xFFFFFFEF ;
    pllRegs->PLLCTL &= 0xFFFFFEFF ;
    pllRegs->PLLCTL |= 0x0 ;

    /*  ------------------------------------------------------------------------
     *  Step 2 - Load PLL multiplier.
     *  ------------------------------------------------------------------------
     */
    pllRegs->PLLM = pllm ;

    /*  ------------------------------------------------------------------------
     *  Step 3 - Load PLL2 divider - DDR2 and VPBE are programmable.
     *  ------------------------------------------------------------------------
     */
    pllRegs->PLLDIV1  =  div2 ;
    pllRegs->PLLDIV2  =  div1 ;
    pllRegs->PLLDIV1 &= 0xFFFF7FFF ;
    pllRegs->PLLDIV2 &= 0xFFFF7FFF ;
    pllRegs->PLLDIV1 |= 0x00008000 ;
    pllRegs->PLLDIV2 |= 0x00008000 ;

    /*  ------------------------------------------------------------------------
     *  Step 4 - Set phase alignment and Wait for operation to finish.
     *  ------------------------------------------------------------------------
     */
    pllRegs->PLLCMD |= 0x00000001 ;
    while ((pllRegs->PLLSTAT & 0x1) == 0x1) ;

    /*  ------------------------------------------------------------------------
     *  Step 5 - Wait for PLL to re-lock ( 2000 cycles ).
     *  ------------------------------------------------------------------------
     */
    udelay (10000) ;
    pllRegs->PLLCTL |= 0x00000008 ;

    /*  ------------------------------------------------------------------------
     *  Step 6 - Switch out of BYPASS mode.
     *  ------------------------------------------------------------------------
     */
    udelay (10000) ;
    pllRegs->PLLCTL |= 0x00000001 ;
}


/*  ----------------------------------------------------------------------------
 *  @func   HAL_cfgDDR2
 *
 *  @desc   Configures the DDR2 module.
 *
 *  @modif  None
 *  ----------------------------------------------------------------------------
 */
Void
HAL_cfgDDR2 (Uint32  freq)
{
    volatile DM64LCPCI_ddrRegs * ddrRegs = (DM64LCPCI_ddrRegs *) ((Uint32) ddrRegVirt) ;
    Uint32 *             vtpiocr = NULL ;
    Uint32 *             vtpr    = NULL ;
    Uint32 *             dftEnb  = NULL ;

    vtpiocr  = (Uint32 *) ((Uint32) ddrRegVirt  + 0xF0) ;
    vtpr     = (Uint32 *) ((Uint32) regVirt + 0x42038) ;
    dftEnb   = (Uint32 *) ((Uint32) regVirt + 0x4004C) ;

    /* Enable the DDR2 PSC Module */
    HAL_changeState (13, 0x3) ;

    /*  ------------------------------------------------------------------------
     *  Step 1. Enable DDR2 PHY.
     *  ------------------------------------------------------------------------
     */
    ddrRegs->DDRPHYCR =  0x50006405 ;
    ddrRegs->SDBCR    =  0x00138822 ;
    ddrRegs->SDTIMR   =  0x16492148 ;
    ddrRegs->SDTIMR2  =  0x000CC702 ;
    ddrRegs->SDBCR    =  0x00130822 ;

    /*  ------------------------------------------------------------------------
     *  Step 3. Refresh Control [ 7.8 usec * freq in MHz ].
     *  ------------------------------------------------------------------------
     */
    ddrRegs->SDRCR = 0x4EF ;

    /* Reset the DDR2 PSC Module */
    HAL_changeState (13, 0x1) ;
    HAL_changeState (13, 0x3) ;

    /*  ------------------------------------------------------------------------
     *  Step 4. Enable VTP calibration
     *  ------------------------------------------------------------------------
     */
    *vtpiocr  = 0x201F ;
    *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                        tSize   ;
    Uint32                        tmp ;

    if (size <= DM64LCPCI_PCIADLEN) {
        pageBase = dstAddr & DM64LCPCI_PCIADWRBITMASK ;
        pciRegs->PCIADDSUB [0] = pageBase ;
    }
    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 ;
            tSize = tmp * 0x7000 ;
            size -= (tmp * 0x7000) ;
            tmp <<= 16 ;
            tmp  |= 0x7000 ;
        }
        else {
            tmp = 0x10000 | size ;
            tSize = 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 = tSize / 132 ;
        do {
            udelay (numUSec) ;
            /* now check in steps of 10 usec. */
            numUSec = 10 ;
        } while ((edmaRegs->IPR & 0x1) == 0) ;

        if (size != 0) {
            srcAddr += tSize ;
            dstAddr += tSize ;
        }
    } 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 ;
    Uint32                        tSize ;

    if (size <= DM64LCPCI_PCIADLEN) {
        pageBase = srcAddr & DM64LCPCI_PCIADWRBITMASK ;
        pciRegs->PCIADDSUB [0] = pageBase ;
    }
    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 ;
            tSize = tmp * 0x7000 ;
            size -= (tmp * 0x7000) ;
            tmp <<= 16 ;
            tmp  |= 0x7000 ;
        }
        else {
            tmp = 0x10000 | size ;
            tSize = 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 = tSize / 132 ;
        do {
            udelay (numUSec) ;
            /* now check in steps of 10 usec. */
            numUSec = 10 ;
        } while ((edmaRegs->IPR & 0x1) == 0) ;

        if (size != 0) {
            srcAddr += tSize ;
            dstAddr += tSize ;
        }
    } while (size != 0) ;

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


#define ADDR32(x)                 *((Uint32 *) ((Uint32)memVirt + x))
/** ============================================================================
 *  @const   LPSC_EDMA_TPCC
 *
 *  @desc    Module number for EDMA TPCC.
 *  ============================================================================
 */
#define LPSC_EDMA_TPCC              2

/** ============================================================================
 *  @const   LPSC_EDMA_TPTC0
 *
 *  @desc    Module number for EDMA TPTC0.
 *  ============================================================================
 */
#define LPSC_EDMA_TPTC0             3

/** ============================================================================
 *  @const   LPSC_EDMA_TPTC1
 *
 *  @desc    Module number for EDMA TPTC1.
 *  ============================================================================
 */
#define LPSC_EDMA_TPTC1             4

static irqreturn_t ISR_handler (int irq, void * arg, struct pt_regs * flags)
{
    Uint32 status = HAL_CheckPciInterrupt ()  ;
    if (status == 1) {
        HAL_PciClearDspInterrupt () ;
        printk ("Interrupt %d received from DSP\n", irq) ;
        return IRQ_HANDLED;
    }
        return IRQ_NONE;
}

Uint32 dummy ;

int init_module(void)
{
    Uint32 i;
    Uint32 j;
    Uint8 * wData ;
    Uint8 * rData ;

    wData = (Uint8 *) kmalloc (0x8000, GFP_DMA) ;
    rData = (Uint8 *) kmalloc (0x8000, GFP_DMA) ;

    printk ("<1>Finding the device....\n") ;
    PCI_FindPciDevices () ;

    if (GEM != NULL) {
        printk ("<1>Reading the BAR areas....\n") ;
        PCI_readBAR () ;

        printk ("<1>Enabling the device....\n") ;
        pci_enable_device (GEM) ;

        pci_set_drvdata (GEM, memVirt) ;

        PCI_setMaster () ;

        printk ("<1>Registering the irq\n") ;
        request_irq (irqNo, ISR_handler, SA_SHIRQ, "PCIDRV", &dummy) ;
        HAL_PciEnableDspInterrupt () ;

        printk ("<1>Powering EDMA engine....\n") ;
        HAL_changeState (LPSC_EDMA_TPCC, 0x3) ;
        HAL_changeState (LPSC_EDMA_TPTC0, 0x3) ;
        HAL_changeState (LPSC_EDMA_TPTC1, 0x3) ;

        printk ("<1>PConfiguring the PLL1....\n") ;
        HAL_cfgPLL1 (23, 11, 1) ;

        printk ("<1>Configuring the DDR2....\n") ;
        HAL_cfgDDR2 (162) ;

        printk ("<1>Running memory test....\n") ;
        {
            volatile Uint32 * ptr = (Uint32 *) memVirt ;
            int               i ;

            for (j = 0 ; j < 1000 ; j++) {
                printk ("<1>Initializing memory....%d\n", j) ;
                /* Initialize the buffer */
                for (i = 0 ; i < 0x8000; i++) {
                    ptr [i] = i ;
                }

                printk ("<1>Reading back memory....%d\n", j) ;
                /* read the buffer back */
                for (i = 0 ; i < 0x8000; i++) {
                    if (ptr [i] != i) {
                        printk ("<1> Memory test failed at 0x%08x\n", 0x10800000+(i*4)) ;
                    }
                }
            }
        }
        
        /* If you see failure prints before this, means test failed */ 
        printk ("<1>Memory test passed....\n") ;

        printk ("<1>Running DMA test....\n") ;
        if (wData && rData) {
            printk ("<1>Initializing memory....\n") ;
            for (i = 0 ; i < 0x8000; i++) {
                wData [i] = 0xAB ;
                rData [i] = 0x00 ;
            }

            printk ("<1>Write DMA to DSP....\n") ;
            HAL_writeDMA ((Uint32) virt_to_bus (wData), 0x80100000, 0x8000) ;
            printk ("<1>Read DMA to DSP....\n") ;
            HAL_readDMA  (0x80100000, (Uint32) virt_to_bus (rData), 0x8000) ;
            if ((rData [0] == wData [0]) && (wData [0x4000] == rData [0x4000])) {
                printk ("API DMA passed\n") ;
            }
            else {
                printk ("API DMA failed %x\n", rData [0]) ;
            }
        }
        printk ("<1>Generating the irq\n") ;
        {
            volatile DM64LCPCI_pciRegs * pciRegs =
                (DM64LCPCI_pciRegs *) (   (Uint32) regVirt
                                        + (DM64LCPCI_PCIREG_BASE - 0x01C00000)) ;
            pciRegs->PCISTATSET |= DM64LCPCI_SOFTINT0_MASK ;
        }
    }
    else {
        printk ("<1>No PCI device found!!!\n") ;
    }

    kfree (rData) ;
    kfree (wData) ;

    return 0 ;
}

void cleanup_module(void)
{
    if (GEM != NULL) {
        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 (irqNo, &dummy) ;
    }
}
KDIR=/usr/src/kernels/linux-2.6.21.7
PWD=$(shell pwd)

obj-m = pcidrv.o

all:
	$(MAKE) -C $(KDIR) M=$(PWD) 
clean:
	rm -fr *.o *.mod.c *.ko

Usage

  • Copy the c code into a file called pcidrv.c
  • Copy it to the Linux workstation
  • Copy the gmake syntax to a file called Makefile
  • Copy it also to the same directory where c code was copied.
  • Then issue the following command.
    • $make
  • Output of this command is pcidrv.ko file
    • Run it as follows: $insmod pcidrv.ko
    • Type the following command to see the output: $dmesg