/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to dma/nwl.c

  • Committer: root
  • Date: 2011-06-17 21:40:33 UTC
  • Revision ID: root@iss-tomyspiel-l-20110617214033-np5x6881odzlfgmg
Enumerate DMA engines

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define _PCILIB_DMA_NWL_C
 
2
 
 
3
#include <stdio.h>
 
4
#include <stdlib.h>
 
5
#include <string.h>
 
6
 
 
7
#include "pci.h"
 
8
#include "pcilib.h"
 
9
#include "error.h"
 
10
#include "tools.h"
 
11
#include "nwl.h"
 
12
 
 
13
/* Common DMA registers */
 
14
#define REG_DMA_CTRL_STATUS     0x4000      /**< DMA Common Ctrl & Status */
 
15
 
 
16
/* These engine registers are applicable to both S2C and C2S channels. 
 
17
 * Register field mask and shift definitions are later in this file.
 
18
 */
 
19
 
 
20
#define REG_DMA_ENG_CAP         0x00000000  /**< DMA Engine Capabilities */
 
21
#define REG_DMA_ENG_CTRL_STATUS 0x00000004  /**< DMA Engine Control */
 
22
#define REG_DMA_ENG_NEXT_BD     0x00000008  /**< HW Next desc pointer */
 
23
#define REG_SW_NEXT_BD          0x0000000C  /**< SW Next desc pointer */
 
24
#define REG_DMA_ENG_LAST_BD     0x00000010  /**< HW Last completed pointer */
 
25
#define REG_DMA_ENG_ACTIVE_TIME 0x00000014  /**< DMA Engine Active Time */
 
26
#define REG_DMA_ENG_WAIT_TIME   0x00000018  /**< DMA Engine Wait Time */
 
27
#define REG_DMA_ENG_COMP_BYTES  0x0000001C  /**< DMA Engine Completed Bytes */
 
28
 
 
29
/* Register masks. The following constants define bit locations of various
 
30
 * control bits in the registers. For further information on the meaning of 
 
31
 * the various bit masks, refer to the hardware spec.
 
32
 *
 
33
 * Masks have been written assuming HW bits 0-31 correspond to SW bits 0-31 
 
34
 */
 
35
 
 
36
/** @name Bitmasks of REG_DMA_CTRL_STATUS register.
 
37
 * @{
 
38
 */
 
39
#define DMA_INT_ENABLE              0x00000001  /**< Enable global interrupts */
 
40
#define DMA_INT_DISABLE             0x00000000  /**< Disable interrupts */
 
41
#define DMA_INT_ACTIVE_MASK         0x00000002  /**< Interrupt active? */
 
42
#define DMA_INT_PENDING_MASK        0x00000004  /**< Engine interrupt pending */
 
43
#define DMA_INT_MSI_MODE            0x00000008  /**< MSI or Legacy mode? */
 
44
#define DMA_USER_INT_ENABLE         0x00000010  /**< Enable user interrupts */
 
45
#define DMA_USER_INT_ACTIVE_MASK    0x00000020  /**< Int - user interrupt */
 
46
#define DMA_USER_INT_ACK            0x00000020  /**< Acknowledge */
 
47
#define DMA_MPS_USED                0x00000700  /**< MPS Used */
 
48
#define DMA_MRRS_USED               0x00007000  /**< MRRS Used */
 
49
#define DMA_S2C_ENG_INT_VAL         0x00FF0000  /**< IRQ value of 1st 8 S2Cs */
 
50
#define DMA_C2S_ENG_INT_VAL         0xFF000000  /**< IRQ value of 1st 8 C2Ss */
 
51
 
 
52
/** @name Bitmasks of REG_DMA_ENG_CAP register.
 
53
 * @{
 
54
 */
 
55
/* DMA engine characteristics */
 
56
#define DMA_ENG_PRESENT_MASK    0x00000001  /**< DMA engine present? */
 
57
#define DMA_ENG_DIRECTION_MASK  0x00000002  /**< DMA engine direction */
 
58
#define DMA_ENG_C2S             0x00000002  /**< DMA engine - C2S */
 
59
#define DMA_ENG_S2C             0x00000000  /**< DMA engine - S2C */
 
60
#define DMA_ENG_TYPE_MASK       0x00000030  /**< DMA engine type */
 
61
#define DMA_ENG_BLOCK           0x00000000  /**< DMA engine - Block type */
 
62
#define DMA_ENG_PACKET          0x00000010  /**< DMA engine - Packet type */
 
63
#define DMA_ENG_NUMBER          0x0000FF00  /**< DMA engine number */
 
64
#define DMA_ENG_BD_MAX_BC       0x3F000000  /**< DMA engine max buffer size */
 
65
 
 
66
/* Shift constants for selected masks */
 
67
#define DMA_ENG_NUMBER_SHIFT        8
 
68
#define DMA_ENG_BD_MAX_BC_SHIFT     24
 
69
 
 
70
#define DMA_ENGINE_PER_SIZE     0x100   /**< Separation between engine regs */
 
71
#define DMA_OFFSET              0       /**< Starting register offset */
 
72
                                        /**< Size of DMA engine reg space */
 
73
#define DMA_SIZE                (MAX_DMA_ENGINES * DMA_ENGINE_PER_SIZE)
 
74
 
 
75
/*
 
76
pcilib_register_bank_description_t ipecamera_register_banks[] = {
 
77
    { PCILIB_REGISTER_DMABANK0, PCILIB_BAR0, 128, PCILIB_DEFAULT_PROTOCOL, DMA_NWL_OFFSET, DMA_NWL_OFFSET, PCILIB_LITTLE_ENDIAN, 32, PCILIB_LITTLE_ENDIAN, "%lx", "dma", "NorthWest Logick DMA Engine" },
 
78
    { 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
 
79
};
 
80
 
 
81
pcilib_register_description_t dma_nwl_registers[] = {
 
82
    {0,         0,      32,     0,      PCILIB_REGISTER_R , PCILIB_REGISTER_DMABANK, "dma_capabilities",  ""},
 
83
    {1,         0,      32,     0,      PCILIB_REGISTER_RW, PCILIB_REGISTER_DMABANK, "dma_control",  ""},
 
84
};
 
85
*/
 
86
 
 
87
typedef struct {
 
88
    pcilib_dma_engine_description_t desc;
 
89
    char *base_addr;
 
90
} pcilib_nwl_engine_description_t;
 
91
 
 
92
 
 
93
struct nwl_dma_s {
 
94
    pcilib_t *pcilib;
 
95
    
 
96
    pcilib_register_bank_description_t *dma_bank;
 
97
    char *base_addr;
 
98
    
 
99
    pcilib_nwl_engine_description_t engines[PCILIB_MAX_DMA_ENGINES + 1];
 
100
};
 
101
 
 
102
#define nwl_read_register(var, ctx, base, reg) pcilib_datacpy(&var, base + reg, 4, 1, ctx->dma_bank->raw_endianess)
 
103
#define nwl_write_register(var, ctx, base, reg) pcilib_datacpy(base + reg, &var, 4, 1, ctx->dma_bank->raw_endianess)
 
104
 
 
105
static int nwl_read_engine_config(nwl_dma_t *ctx, pcilib_nwl_engine_description_t *info, char *base) {
 
106
    uint32_t val;
 
107
    
 
108
    nwl_read_register(val, ctx, base, REG_DMA_ENG_CAP);
 
109
 
 
110
    if ((val & DMA_ENG_PRESENT_MASK) == 0) return PCILIB_ERROR_NOTAVAILABLE;
 
111
    
 
112
    info->desc.addr = (val & DMA_ENG_NUMBER) >> DMA_ENG_NUMBER_SHIFT;
 
113
    
 
114
    switch (val & DMA_ENG_DIRECTION_MASK) {
 
115
        case  DMA_ENG_C2S:
 
116
            info->desc.direction = PCILIB_DMA_FROM_DEVICE;
 
117
        break;
 
118
        default:
 
119
            info->desc.direction = PCILIB_DMA_TO_DEVICE;
 
120
    }
 
121
    
 
122
    switch (val & DMA_ENG_TYPE_MASK) {
 
123
        case DMA_ENG_BLOCK:
 
124
            info->desc.type = PCILIB_DMA_TYPE_BLOCK;
 
125
        break;
 
126
        case DMA_ENG_PACKET:
 
127
            info->desc.type = PCILIB_DMA_TYPE_PACKET;
 
128
        break;
 
129
        default:
 
130
            info->desc.type = PCILIB_DMA_TYPE_UNKNOWN;
 
131
    }
 
132
    
 
133
    info->desc.addr_bits = (val & DMA_ENG_BD_MAX_BC) >> DMA_ENG_BD_MAX_BC_SHIFT;
 
134
    
 
135
    return 0;
 
136
}
 
137
 
 
138
pcilib_dma_context_t *dma_nwl_init(pcilib_t *pcilib) {
 
139
    int i;
 
140
    int err;
 
141
    pcilib_dma_t n_engines;
 
142
 
 
143
    pcilib_model_description_t *model_info = pcilib_get_model_description(pcilib);
 
144
    
 
145
    nwl_dma_t *ctx = malloc(sizeof(nwl_dma_t));
 
146
    if (ctx) {
 
147
        memset(ctx, 0, sizeof(nwl_dma_t));
 
148
        ctx->pcilib = pcilib;
 
149
        pcilib_register_bank_t dma_bank = pcilib_find_bank_by_addr(pcilib, PCILIB_REGISTER_BANK_DMA);
 
150
 
 
151
        if (dma_bank == PCILIB_REGISTER_BANK_INVALID) {
 
152
            pcilib_error("DMA Register Bank could not be found");
 
153
            return NULL;
 
154
        }
 
155
        
 
156
        ctx->dma_bank = model_info->banks + dma_bank;
 
157
        ctx->base_addr = pcilib_resolve_register_address(pcilib, ctx->dma_bank->bar, ctx->dma_bank->read_addr);
 
158
 
 
159
        for (i = 0, n_engines = 0; i < 2 * PCILIB_MAX_DMA_ENGINES; i++) {
 
160
            char *addr = ctx->base_addr + DMA_OFFSET + i * DMA_ENGINE_PER_SIZE;
 
161
            err = nwl_read_engine_config(ctx, ctx->engines + n_engines, addr);
 
162
            if (!err) {
 
163
                ctx->engines[n_engines].base_addr = addr;
 
164
                pcilib_set_dma_engine_description(pcilib, n_engines, (pcilib_dma_engine_description_t*)(ctx->engines + n_engines));
 
165
                ++n_engines;
 
166
            }
 
167
        }
 
168
        pcilib_set_dma_engine_description(pcilib, n_engines, NULL);
 
169
    }
 
170
    return (pcilib_dma_context_t*)ctx;
 
171
}
 
172
 
 
173
void  dma_nwl_free(pcilib_dma_context_t *vctx) {
 
174
    nwl_dma_t *ctx = (nwl_dma_t*)vctx;
 
175
    if (ctx) {
 
176
        free(ctx);
 
177
    }
 
178
}