summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2013-05-21 09:46:36 +0200
committerDaniel Hellstrom <daniel@gaisler.com>2013-05-21 09:48:37 +0200
commit242a9113f0d63cd143ddfc3c9fbcd872ac6c6222 (patch)
treed408b904f936455c68b3f8bac88c133547f40804
parentf4f0d08579159c4672bc9e466638ae14bce4b1c2 (diff)
DRVMGR: reworked the address translation functions
Cleaned up the address translation implementation and updated all users to the new interface. The old implementation had a bug and the users used it incorrect. This patch aims to fix both problems. One can not translate a address upstreams and then take that address and expect it to be translateable downstreams..
-rw-r--r--c/src/lib/libbsp/sparc/shared/1553/b1553brm.c66
-rw-r--r--c/src/lib/libbsp/sparc/shared/1553/b1553rt.c57
-rw-r--r--c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c93
-rw-r--r--c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c62
-rw-r--r--c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c175
-rw-r--r--c/src/lib/libbsp/sparc/shared/can/grcan.c111
-rw-r--r--c/src/lib/libbsp/sparc/shared/graes/graes.c7
-rw-r--r--c/src/lib/libbsp/sparc/shared/grpwrx/grpwrx.c9
-rw-r--r--c/src/lib/libbsp/sparc/shared/net/greth.c63
-rw-r--r--c/src/lib/libbsp/sparc/shared/spw/grspw.c171
-rw-r--r--c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c18
-rw-r--r--c/src/lib/libbsp/sparc/shared/tmtc/grtc.c45
-rw-r--r--c/src/lib/libbsp/sparc/shared/tmtc/grtm.c6
-rw-r--r--cpukit/libdrvmgr/Makefile.am1
-rw-r--r--cpukit/libdrvmgr/drvmgr.h111
-rw-r--r--cpukit/libdrvmgr/drvmgr_translate.c109
-rw-r--r--cpukit/libdrvmgr/drvmgr_translate_check.c35
-rw-r--r--cpukit/libmisc/shell/main_drvmgr.c18
18 files changed, 726 insertions, 431 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c b/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c
index ca81a929a6..65af6bfd49 100644
--- a/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c
+++ b/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c
@@ -424,7 +424,8 @@ int b1553brm_device_init(brm_priv *pDev)
struct amba_dev_info *ambadev;
struct ambapp_core *pnpinfo;
union drvmgr_key_value *value;
- char *mem;
+ unsigned int mem;
+ int size;
/* Get device information from AMBA PnP information */
ambadev = (struct amba_dev_info *)pDev->dev->businfo;
@@ -449,44 +450,57 @@ int b1553brm_device_init(brm_priv *pDev)
memset(pDev->log,0,sizeof(pDev->log));
#endif
+#ifdef DMA_MEM_128K
+ size = 128 * 1024;
+#else
+ size = 16 * 1024;
+#endif
+
/* Get memory configuration from bus resources */
value = drvmgr_dev_key_get(pDev->dev, "dmaBaseAdr", KEY_TYPE_POINTER);
- if ( value ) {
- mem = value->ptr;
- if ( (unsigned int)mem & 1 ) {
- /* Remote address, address as BRM looks at it. */
-
- /* Translate the base address into an address that the the CPU can understand */
- mem = (char *)((unsigned int)mem & ~1);
- drvmgr_translate(pDev->dev, 1, 1, (void *)mem, (void **)&mem);
- }
+ if (value)
+ mem = (unsigned int)value->ptr;
+
+ if (value && (mem & 1)) {
+ /* Remote address, address as BRM looks at it. */
+
+ /* Translate the base address into an address that the the CPU can understand */
+ pDev->memarea_base_remote = mem & ~1;
+ drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU,
+ (void *)pDev->memarea_base_remote,
+ (void **)&pDev->memarea_base,
+ size);
} else {
- /* Use dynamically allocated memory */
- mem = (char *)malloc(128 * 1024 * 2); /* 128k DMA memory + 128k for alignment */
- if ( !mem ){
- printk("BRM: Failed to allocate HW memory\n\r");
- return -1;
+ if (!value) {
+ /* Use dynamically allocated memory + 128k for
+ * alignment
+ */
+ mem = (unsigned int)malloc(size + 128 * 1024);
+ if (!mem){
+ printk("BRM: Failed to allocate HW memory\n\r");
+ return -1;
+ }
+ /* align memory to 128k boundary */
+ pDev->memarea_base = (mem + 0x1ffff) & ~0x1ffff;
+ } else {
+ pDev->memarea_base = mem;
}
+
+ /* Translate the base address into an address that the BRM core can understand */
+ drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA,
+ (void *)pDev->memarea_base,
+ (void **)&pDev->memarea_base_remote,
+ size);
}
- /* align memory to 128k boundary */
- mem = (char *)(((unsigned int)mem+0x1ffff) & ~0x1ffff);
/* clear the used memory */
-#ifdef DMA_MEM_128K
- memset(mem, 0, (128 * 1024));
-#else
- memset(mem, 0, (16 * 1024));
-#endif
+ memset((char *)pDev->memarea_base, 0, size);
/* Set base address of all descriptors */
- pDev->memarea_base = (unsigned int)mem;
pDev->desc = (struct desc_table *) pDev->memarea_base;
pDev->mem = (volatile unsigned short *) pDev->memarea_base;
pDev->irq_log = (struct irq_log_list *)(pDev->memarea_base + (0xFFE0<<1)); /* last 64byte */
- /* Translate the base address into an address that the BRM core can understand */
- drvmgr_translate(pDev->dev, 0, 0, (void *)mem, (void **)&pDev->memarea_base_remote);
-
pDev->bm_event = NULL;
pDev->rt_event = NULL;
diff --git a/c/src/lib/libbsp/sparc/shared/1553/b1553rt.c b/c/src/lib/libbsp/sparc/shared/1553/b1553rt.c
index acb9379650..f663a2dc95 100644
--- a/c/src/lib/libbsp/sparc/shared/1553/b1553rt.c
+++ b/c/src/lib/libbsp/sparc/shared/1553/b1553rt.c
@@ -282,7 +282,7 @@ int b1553rt_device_init(rt_priv *pDev)
struct amba_dev_info *ambadev;
struct ambapp_core *pnpinfo;
union drvmgr_key_value *value;
- char *mem;
+ unsigned int mem;
unsigned int sys_freq_hz;
/* Get device information from AMBA PnP information */
@@ -304,36 +304,47 @@ int b1553rt_device_init(rt_priv *pDev)
/* Get memory configuration from bus resources */
value = drvmgr_dev_key_get(pDev->dev, "dmaBaseAdr", KEY_TYPE_POINTER);
- if ( value ) {
- mem = value->ptr;
- if ( (unsigned int)mem & 1 ) {
- /* Remote address, address as RT looks at it. */
-
- /* Translate the base address into an address that the the CPU can understand */
- mem = (char *)((unsigned int)mem & ~1);
- drvmgr_translate(pDev->dev, 1, 1, (void *)mem, (void **)&mem);
- }
+ if (value)
+ mem = (unsigned int)value->ptr;
+
+ if (value && (mem & 1)) {
+ /* Remote address, address as RT looks at it. */
+
+ /* Translate the base address into an address that the the CPU can understand */
+ pDev->memarea_base = mem & ~1;
+ drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU,
+ (void *)pDev->memarea_base_remote,
+ (void **)&pDev->memarea_base,
+ 4 * 1024);
} else {
- /* Use dynamically allocated memory */
- mem = (char *)malloc(4 * 1024 * 2); /* 4k DMA memory + 4k for alignment */
- if ( !mem ){
- printk("RT: Failed to allocate HW memory\n\r");
- return -1;
+ if (!value) {
+ /* Use dynamically allocated memory,
+ * 4k DMA memory + 4k for alignment
+ */
+ mem = (char *)malloc(4 * 1024 * 2);
+ if ( !mem ){
+ printk("RT: Failed to allocate HW memory\n\r");
+ return -1;
+ }
+ /* align memory to 4k boundary */
+ pDev->memarea_base = (mem + 0xfff) & ~0xfff;
+ } else {
+ pDev->memarea_base = mem;
}
- }
- /* align memory to 4k boundary */
- mem = (char *)(((unsigned int)mem+0xfff) & ~0xfff);
+ /* Translate the base address into an address that the RT core can understand */
+ drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA,
+ (void *)pDev->memarea_base,
+ (void **)&pDev->memarea_base_remote,
+ 4 * 1024);
+ }
/* clear the used memory */
- memset(mem, 0, (4 * 1024));
+ memset((char *)pDev->memarea_base, 0, 4 * 1024);
/* Set base address of all descriptors */
pDev->memarea_base = (unsigned int)mem;
- pDev->mem = (volatile unsigned short *) pDev->memarea_base;
-
- /* Translate the base address into an address that the RT core can understand */
- drvmgr_translate(pDev->dev, 0, 0, (void *)mem, (void **)&pDev->memarea_base_remote);
+ pDev->mem = (volatile unsigned short *)pDev->memarea_base;
pDev->rt_event = NULL;
diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c
index d409761994..e224f25174 100644
--- a/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c
+++ b/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c
@@ -309,47 +309,51 @@ int gr1553bc_list_table_alloc
/* Remember user's settings for uninitialization */
list->_table_custom = bdtab_custom;
- if ( bdtab_custom == NULL ) {
- /* Get Size required for descriptors */
- size = gr1553bc_list_table_size(list);
+ /* Get Size required for descriptors */
+ size = gr1553bc_list_table_size(list);
- /* Allocate descriptors */
- list->_table = malloc(size + (GR1553BC_BD_ALIGN-1));
- if ( list->_table == NULL )
- return -1;
- } else if ( (unsigned int)bdtab_custom & 0x1 ) {
+ if ((unsigned int)bdtab_custom & 0x1) {
/* Address given in Hardware accessible address, we
* convert it into CPU-accessible address.
*/
- drvmgr_translate(
- *bcpriv->pdev,
- 1,
- 1,
- (void *)((unsigned int)bdtab_custom & ~0x1),
- (void **)&list->_table
- );
- } else {
- /* Custom address, given in CPU-accessible address */
+ list->table_hw = (unsigned int)bdtab_custom & ~0x1;
list->_table = bdtab_custom;
- }
-
- /* 128-bit Alignment required by HW */
- table = (unsigned int)list->_table;
- table = (table + (GR1553BC_BD_ALIGN-1)) & ~(GR1553BC_BD_ALIGN-1);
- list->table_cpu = table;
- list->table_hw = table;
-
- /* We got CPU accessible descriptor table address, now we translate
- * that into an address which the Hardware can understand
- */
- if ( bcpriv ) {
- drvmgr_translate(
+ drvmgr_translate_check(
*bcpriv->pdev,
- 0,
- 0,
- (void *)list->table_cpu,
- (void **)&list->table_hw
- );
+ DMAMEM_TO_CPU,
+ (void *)list->table_hw,
+ (void **)&list->table_cpu,
+ size);
+ } else {
+ if (bdtab_custom == NULL) {
+ /* Allocate descriptors */
+ list->_table = malloc(size + (GR1553BC_BD_ALIGN-1));
+ if ( list->_table == NULL )
+ return -1;
+ } else {
+ /* Custom address, given in CPU-accessible address */
+ list->_table = bdtab_custom;
+ }
+ /* 128-bit Alignment required by HW */
+ list->table_cpu =
+ (((unsigned int)list->_table + (GR1553BC_BD_ALIGN-1)) &
+ ~(GR1553BC_BD_ALIGN-1));
+
+ /* We got CPU accessible descriptor table address, now we
+ * translate that into an address that the Hardware can
+ * understand
+ */
+ if (bcpriv) {
+ drvmgr_translate_check(
+ *bcpriv->pdev,
+ CPUMEM_TO_DMA,
+ (void *)list->table_cpu,
+ (void **)&list->table_hw,
+ size
+ );
+ } else {
+ list->table_hw = list->table_cpu;
+ }
}
/* Write End-Of-List all over the descriptor table here,
@@ -359,6 +363,7 @@ int gr1553bc_list_table_alloc
/* Assign descriptors to all minor frames. The addresses is
* CPU-accessible addresses.
*/
+ table = list->table_cpu;
for (i=0; i<list->major_cnt; i++) {
major = list->majors[i];
minor_cnt = major->cfg->minor_cnt;
@@ -1039,11 +1044,9 @@ int gr1553bc_slot_transfer(
drvmgr_translate(
*bcpriv->pdev,
- 0,
- 0,
+ CPUMEM_TO_DMA,
(void *)((unsigned int)dptr & ~0x1),
- (void **)&dptr
- );
+ (void **)&dptr);
}
/* It is assumed that the descriptor has already been initialized
@@ -1113,8 +1116,7 @@ int gr1553bc_slot_update
if ( dataptr & 0x1 ) {
drvmgr_translate(
*bcpriv->pdev,
- 0,
- 0,
+ CPUMEM_TO_DMA,
(void *)(dataptr & ~0x1),
(void **)&dptr
);
@@ -1478,13 +1480,12 @@ void gr1553bc_device_init(struct gr1553bc_priv *priv)
(((uint32_t)priv->irq_log_p + (GR1553BC_IRQLOG_SIZE-1)) &
~(GR1553BC_IRQLOG_SIZE-1));
/* Translate into a hardware accessible address */
- drvmgr_translate(
+ drvmgr_translate_check(
*priv->pdev,
- 0,
- 0,
+ CPUMEM_TO_DMA,
(void *)priv->irq_log_base,
- (void **)&priv->irq_log_base_hw
- );
+ (void **)&priv->irq_log_base_hw,
+ GR1553BC_IRQLOG_SIZE);
priv->irq_log_curr = priv->irq_log_base;
priv->irq_log_end = &priv->irq_log_base[GR1553BC_IRQLOG_CNT-1];
priv->irq_func = gr1553bc_isr_std;
diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c
index 2ceb2a9046..d2fc979b0c 100644
--- a/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c
+++ b/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c
@@ -209,46 +209,46 @@ int gr1553bm_config(void *bm, struct gr1553bm_config *cfg)
priv->buffer = NULL;
}
priv->buffer_size = cfg->buffer_size & ~0x7; /* on 8 byte bounadry */
- if ( cfg->buffer_custom == NULL ) {
- /* Allocate new buffer dynamically */
- priv->buffer = malloc(priv->buffer_size + 8);
- if ( priv->buffer == NULL )
- return -1;
+ if ((unsigned int)cfg->buffer_custom & 1) {
+ /* Custom Address Given in Remote address. We need
+ * to convert it intoTranslate into Hardware a
+ * hardware accessible address
+ */
+ priv->buffer_base_hw = (unsigned int)cfg->buffer_custom & ~1;
+ priv->buffer = cfg->buffer_custom;
+ drvmgr_translate_check(
+ *priv->pdev,
+ DMAMEM_TO_CPU,
+ (void *)priv->buffer_base_hw,
+ (void **)&priv->buffer_base,
+ priv->buffer_size);
} else {
- if ( (unsigned int)cfg->buffer_custom & 1 ) {
- /* Custom Address Given in Remote address. We need
- * to convert it intoTranslate into Hardware a
- * hardware accessible address
- */
- drvmgr_translate(
- *priv->pdev,
- 1,
- 1,
- (void *)((unsigned int)cfg->buffer_custom & ~1),
- (void **)&priv->buffer
- );
+ if (cfg->buffer_custom == NULL) {
+ /* Allocate new buffer dynamically */
+ priv->buffer = malloc(priv->buffer_size + 8);
+ if (priv->buffer == NULL)
+ return -1;
} else {
/* Address given in CPU accessible address, no
* translation required.
*/
priv->buffer = cfg->buffer_custom;
}
+ /* Align to 16 bytes */
+ priv->buffer_base = ((unsigned int)priv->buffer + (8-1)) &
+ ~(8-1);
+ /* Translate address of buffer base into address that Hardware must
+ * use to access the buffer.
+ */
+ drvmgr_translate_check(
+ *priv->pdev,
+ CPUMEM_TO_DMA,
+ (void *)priv->buffer_base,
+ (void **)&priv->buffer_base_hw,
+ priv->buffer_size);
+
}
- /* Align to 16 bytes */
- priv->buffer_base = ((unsigned int)priv->buffer + (8-1)) & ~(8-1);
-
- /* Translate address of buffer base into address that Hardware must
- * use to access the buffer.
- */
- drvmgr_translate(
- *priv->pdev,
- 0,
- 0,
- (void *)priv->buffer_base,
- (void **)&priv->buffer_base_hw
- );
-
/* Copy valid config */
priv->cfg = *cfg;
diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c
index 7ada4d1ac7..a984b52754 100644
--- a/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c
+++ b/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c
@@ -207,7 +207,7 @@ int gr1553rt_bd_alloc(void *rt, struct gr1553rt_sw_bd **bd, int cnt)
struct gr1553rt_sw_bd *curr;
int i;
- if ( priv->swbd_free_cnt < cnt ) {
+ if ((priv->swbd_free_cnt < cnt) || (cnt <= 0)) {
*bd = NULL;
return -1;
}
@@ -352,8 +352,7 @@ int gr1553rt_bd_init(
dataptr &= ~1;
drvmgr_translate(
*priv->pdev,
- 0,
- 0,
+ CPUMEM_TO_DMA,
(void *)dataptr,
(void **)&dataptr
);
@@ -399,8 +398,7 @@ int gr1553rt_bd_update(
dataptr &= ~1;
drvmgr_translate(
*priv->pdev,
- 0,
- 0,
+ CPUMEM_TO_DMA,
(void *)dataptr,
(void **)&dataptr
);
@@ -832,38 +830,78 @@ int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
int size;
/* Allocate Event log */
- if ( priv->cfg.evlog_buffer == NULL ) {
- priv->evlog_buffer = malloc(priv->cfg.evlog_size * 2);
- } else if ( (unsigned int)priv->cfg.evlog_buffer & 1 ) {
+ if ((unsigned int)priv->cfg.evlog_buffer & 1) {
/* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */
- drvmgr_translate(
+ priv->evlog_hw_base = (unsigned int *)
+ ((unsigned int)priv->cfg.evlog_buffer & ~0x1);
+ priv->evlog_buffer = priv->cfg.evlog_buffer;
+ drvmgr_translate_check(
*priv->pdev,
- 1,
- 1,
- (void *)((unsigned int)priv->cfg.evlog_buffer & ~0x1),
- (void **)&priv->evlog_buffer
+ DMAMEM_TO_CPU,
+ (void *)priv->evlog_hw_base,
+ (void **)&priv->evlog_cpu_base,
+ priv->cfg.evlog_size
);
} else {
- /* Addess already CPU-LOCAL */
- priv->evlog_buffer = priv->cfg.evlog_buffer;
+ if (priv->cfg.evlog_buffer == NULL) {
+ priv->evlog_buffer = malloc(priv->cfg.evlog_size * 2);
+ if (priv->evlog_buffer == NULL)
+ return -1;
+ } else {
+ /* Addess already CPU-LOCAL */
+ priv->evlog_buffer = priv->cfg.evlog_buffer;
+ }
+ /* Align to SIZE bytes boundary */
+ priv->evlog_cpu_base = (unsigned int *)
+ (((unsigned int)priv->evlog_buffer +
+ (priv->cfg.evlog_size-1)) & ~(priv->cfg.evlog_size-1));
+
+ drvmgr_translate_check(
+ *priv->pdev,
+ CPUMEM_TO_DMA,
+ (void *)priv->evlog_cpu_base,
+ (void **)&priv->evlog_hw_base,
+ priv->cfg.evlog_size
+ );
}
+ priv->evlog_cpu_end = priv->evlog_cpu_base +
+ priv->cfg.evlog_size/sizeof(unsigned int *);
/* Allocate Transfer Descriptors */
- if ( priv->cfg.bd_buffer == NULL ) {
- size = priv->cfg.bd_count * sizeof(struct gr1553rt_bd) + 0xf;
- priv->bd_buffer = malloc(size);
- } else if ( (unsigned int)priv->cfg.bd_buffer & 1 ) {
+ priv->bds_cnt = priv->cfg.bd_count;
+ size = priv->bds_cnt * sizeof(struct gr1553rt_bd);
+ if ((unsigned int)priv->cfg.bd_buffer & 1) {
/* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */
- drvmgr_translate(
+ priv->bds_hw = (unsigned int)priv->cfg.bd_buffer & ~0x1;
+ priv->bd_buffer = priv->cfg.bd_buffer;
+ drvmgr_translate_check(
*priv->pdev,
- 1,
- 1,
- (void *)((unsigned int)priv->cfg.bd_buffer & ~0x1),
- (void **)&priv->bd_buffer
+ DMAMEM_TO_CPU,
+ (void *)priv->bds_hw,
+ (void **)&priv->bds_cpu,
+ size
);
} else {
- /* Addess already CPU-LOCAL */
- priv->bd_buffer = priv->cfg.bd_buffer;
+ if ( priv->cfg.bd_buffer == NULL ) {
+ priv->bd_buffer = malloc(size + 0xf);
+ if (priv->bd_buffer == NULL)
+ return -1;
+ } else {
+ /* Addess already CPU-LOCAL */
+ priv->bd_buffer = priv->cfg.bd_buffer;
+ }
+ /* Align to 16 bytes boundary */
+ priv->bds_cpu = (struct gr1553rt_bd *)
+ (((unsigned int)priv->bd_buffer + 0xf) & ~0xf);
+
+ /* Translate from CPU address to hardware address */
+ drvmgr_translate_check(
+ *priv->pdev,
+ CPUMEM_TO_DMA,
+ (void *)priv->bds_cpu,
+ (void **)&priv->bds_hw,
+ size
+ );
}
#if (RTBD_MAX == 0)
@@ -875,76 +913,53 @@ int gr1553rt_sw_alloc(struct gr1553rt_priv *priv)
#endif
/* Allocate Sub address table */
- if ( priv->cfg.satab_buffer == NULL ) {
- priv->satab_buffer = malloc((16 * 32) * 2);
- } else if ( (unsigned int)priv->cfg.satab_buffer & 1 ) {
+ if ((unsigned int)priv->cfg.satab_buffer & 1) {
/* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */
- drvmgr_translate(
+ priv->sas_hw = (unsigned int)priv->cfg.satab_buffer & ~0x1;
+ priv->satab_buffer = priv->cfg.satab_buffer;
+ drvmgr_translate_check(
*priv->pdev,
- 1,
- 1,
- (void *)((unsigned int)priv->cfg.satab_buffer & ~0x1),
- (void **)&priv->satab_buffer
- );
+ DMAMEM_TO_CPU,
+ (void *)priv->sas_hw,
+ (void **)&priv->sas_cpu,
+ 16 * 32);
} else {
- /* Addess already CPU-LOCAL */
- priv->satab_buffer = priv->cfg.satab_buffer;
- }
+ if (priv->cfg.satab_buffer == NULL) {
+ priv->satab_buffer = malloc((16 * 32) * 2);
+ if (priv->satab_buffer == NULL)
+ return -1;
+ } else {
+ /* Addess already CPU-LOCAL */
+ priv->satab_buffer = priv->cfg.satab_buffer;
+ }
+ /* Align to 512 bytes boundary */
+ priv->sas_cpu = (struct gr1553rt_sa *)
+ (((unsigned int)priv->satab_buffer + 0x1ff) &
+ ~0x1ff);
- if ( !priv->evlog_buffer || !priv->bd_buffer || !priv->satab_buffer )
- return -1;
+ /* Translate Address from CPU-LOCAL to HARDWARE (REMOTE) */
+ drvmgr_translate_check(
+ *priv->pdev,
+ CPUMEM_TO_DMA,
+ (void *)priv->sas_cpu,
+ (void **)&priv->sas_hw,
+ 16 * 32);
+ }
return 0;
}
void gr1553rt_sw_init(struct gr1553rt_priv *priv)
{
- unsigned int buf;
int i;
- /* Align to 512 bytes boundary */
- buf = (unsigned int)priv->satab_buffer;
- buf = (buf + 0x1ff) & ~0x1ff;
- priv->sas_cpu = (struct gr1553rt_sa *)buf;
- /* Translate Address from CPU-LOCAL to HARDWARE (REMOTE) */
- drvmgr_translate(
- *priv->pdev,
- 0,
- 0,
- (void *)buf,
- (void **)&priv->sas_hw
- );
+ /* Clear Sub Address table */
memset(priv->sas_cpu, 0, 512);
- /* Align to 16 bytes boundary */
- buf = (unsigned int)priv->bd_buffer;
- buf = (buf + 0xf) & ~0xf;
- priv->bds_cpu = (struct gr1553rt_bd *)buf;
- /* Translate from CPU address to hardware address */
- drvmgr_translate(
- *priv->pdev,
- 0,
- 0,
- (void *)buf,
- (void **)&priv->bds_hw
- );
- priv->bds_cnt = priv->cfg.bd_count;
+ /* Clear Transfer descriptors */
memset(priv->bds_cpu, 0, priv->bds_cnt * 16);
- /* Align to SIZE bytes boundary */
- buf = (unsigned int)priv->evlog_buffer;
- buf = (buf + (priv->cfg.evlog_size-1)) & ~(priv->cfg.evlog_size-1);
- priv->evlog_cpu_base = (unsigned int *)buf;
- /* Translate from CPU address to hardware address */
- drvmgr_translate(
- *priv->pdev,
- 0,
- 0,
- (void *)buf,
- (void **)&priv->evlog_hw_base
- );
- priv->evlog_cpu_end = priv->evlog_cpu_base +
- priv->cfg.evlog_size/sizeof(unsigned int *);
+ /* Clear the Event log */
memset(priv->evlog_cpu_base, 0, priv->cfg.evlog_size);
/* Init descriptor allocation algorithm */
diff --git a/c/src/lib/libbsp/sparc/shared/can/grcan.c b/c/src/lib/libbsp/sparc/shared/can/grcan.c
index 251519ac86..1f27d3f390 100644
--- a/c/src/lib/libbsp/sparc/shared/can/grcan.c
+++ b/c/src/lib/libbsp/sparc/shared/can/grcan.c
@@ -123,8 +123,8 @@ struct grcan_priv {
unsigned int corefreq_hz;
/* Circular DMA buffers */
- void *_rx;
- void *_tx;
+ void *_rx, *_rx_hw;
+ void *_tx, *_tx_hw;
void *txbuf_adr;
void *rxbuf_adr;
struct grcan_msg *rx;
@@ -456,13 +456,11 @@ static rtems_device_driver grcan_start(struct grcan_priv *pDev)
}
/* Setup receiver */
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->rx, (void **)&pDev->regs->rx0addr);
- /*pDev->regs->rx0addr = MEMAREA_TO_HW((unsigned int)pDev->rx);*/
+ pDev->regs->rx0addr = (unsigned int)pDev->_rx_hw;
pDev->regs->rx0size = pDev->rxbuf_size;
/* Setup Transmitter */
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->tx, (void **)&pDev->regs->tx0addr);
- /*pDev->regs->tx0addr = MEMAREA_TO_HW((unsigned int)pDev->tx);*/
+ pDev->regs->tx0addr = (unsigned int)pDev->_tx_hw;
pDev->regs->tx0size = pDev->txbuf_size;
/* Setup acceptance filters */
@@ -1106,38 +1104,95 @@ static int grcan_tx_flush(struct grcan_priv *pDev)
static int grcan_alloc_buffers(struct grcan_priv *pDev, int rx, int tx)
{
+ unsigned int adr;
FUNCDBG();
if ( tx ) {
- if ( pDev->txbuf_adr ) {
- /* User defined address */
- pDev->_tx = pDev->txbuf_adr;
+ adr = (unsigned int)pDev->txbuf_adr;
+ if (adr & 0x1) {
+ /* User defined "remote" address. Translate it into
+ * a CPU accessible address
+ */
+ pDev->_tx_hw = (void *)(adr & ~0x1);
+ drvmgr_translate_check(
+ pDev->dev,
+ DMAMEM_TO_CPU,
+ (void *)pDev->_tx_hw,
+ (void **)&pDev->_tx,
+ pDev->txbuf_size);
+ pDev->tx = (struct grcan_msg *)pDev->_tx;
} else {
- pDev->_tx = malloc(pDev->txbuf_size + BUFFER_ALIGNMENT_NEEDS);
- if ( !pDev->_tx )
- return -1;
+ if (adr == 0) {
+ pDev->_tx = malloc(pDev->txbuf_size +
+ BUFFER_ALIGNMENT_NEEDS);
+ if (!pDev->_tx)
+ return -1;
+ } else {
+ /* User defined "cou-local" address. Translate
+ * it into a CPU accessible address
+ */
+ pDev->_tx = (void *)adr;
+ }
+ /* Align TX buffer */
+ pDev->tx = (struct grcan_msg *)
+ (((unsigned int)pDev->_tx +
+ (BUFFER_ALIGNMENT_NEEDS-1)) &
+ ~(BUFFER_ALIGNMENT_NEEDS-1));
+
+ /* Translate address into an hardware accessible
+ * address
+ */
+ drvmgr_translate_check(
+ pDev->dev,
+ CPUMEM_TO_DMA,
+ (void *)pDev->tx,
+ (void **)&pDev->_tx_hw,
+ pDev->txbuf_size);
}
-
- /* Align TX buffer */
- pDev->tx = (struct grcan_msg *)
- (((unsigned int)pDev->_tx + (BUFFER_ALIGNMENT_NEEDS-1)) &
- ~(BUFFER_ALIGNMENT_NEEDS-1));
}
if ( rx ) {
- if ( pDev->rxbuf_adr ) {
- /* User defined address */
- pDev->_rx = pDev->rxbuf_adr;
+ adr = (unsigned int)pDev->rxbuf_adr;
+ if (adr & 0x1) {
+ /* User defined "remote" address. Translate it into
+ * a CPU accessible address
+ */
+ pDev->_rx_hw = (void *)(adr & ~0x1);
+ drvmgr_translate_check(
+ pDev->dev,
+ DMAMEM_TO_CPU,
+ (void *)pDev->_rx_hw,
+ (void **)&pDev->_rx,
+ pDev->rxbuf_size);
+ pDev->rx = (struct grcan_msg *)pDev->_rx;
} else {
- pDev->_rx = malloc(pDev->rxbuf_size + BUFFER_ALIGNMENT_NEEDS);
- if ( !pDev->_rx )
- return -1;
+ if (adr == 0) {
+ pDev->_rx = malloc(pDev->rxbuf_size +
+ BUFFER_ALIGNMENT_NEEDS);
+ if (!pDev->_rx)
+ return -1;
+ } else {
+ /* User defined "cou-local" address. Translate
+ * it into a CPU accessible address
+ */
+ pDev->_rx = (void *)adr;
+ }
+ /* Align RX buffer */
+ pDev->rx = (struct grcan_msg *)
+ (((unsigned int)pDev->_rx +
+ (BUFFER_ALIGNMENT_NEEDS-1)) &
+ ~(BUFFER_ALIGNMENT_NEEDS-1));
+
+ /* Translate address into an hardware accessible
+ * address
+ */
+ drvmgr_translate_check(
+ pDev->dev,
+ CPUMEM_TO_DMA,
+ (void *)pDev->rx,
+ (void **)&pDev->_rx_hw,
+ pDev->rxbuf_size);
}
-
- /* Align RX buffer */
- pDev->rx = (struct grcan_msg *)
- (((unsigned int)pDev->_rx + (BUFFER_ALIGNMENT_NEEDS-1)) &
- ~(BUFFER_ALIGNMENT_NEEDS-1));
}
return 0;
}
diff --git a/c/src/lib/libbsp/sparc/shared/graes/graes.c b/c/src/lib/libbsp/sparc/shared/graes/graes.c
index 1e729837b7..e1778a4dce 100644
--- a/c/src/lib/libbsp/sparc/shared/graes/graes.c
+++ b/c/src/lib/libbsp/sparc/shared/graes/graes.c
@@ -466,7 +466,8 @@ static int graes_start(struct graes_priv *pDev)
/* Set Descriptor Pointer Base register to point to first descriptor */
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->bds, (void **)&transaddr);
+ drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, (void *)pDev->bds,
+ (void **)&transaddr, GRAES_BDAR_SIZE);
regs->dma_bd = transaddr;
DBG("GRAES: set bd to 0x%08x\n",transaddr);
@@ -699,7 +700,7 @@ static unsigned int graes_trans(struct graes_priv *pDev, struct graes_block *cur
*/
if ( curr_frm->flags & (GRAES_FLAGS_TRANSLATE|GRAES_FLAGS_TRANSLATE_AND_REMEMBER) ) {
/* Do translation */
- drvmgr_translate(pDev->dev, 0, 0, (void *)addr_in, (void **)&addr);
+ drvmgr_translate(pDev->dev, CPUMEM_TO_DMA, (void *)addr_in, (void **)&addr);
if ( curr_frm->flags & GRAES_FLAGS_TRANSLATE_AND_REMEMBER ) {
if ( addr_in != addr ) {
/* Translation needed */
@@ -770,7 +771,7 @@ static int graes_schedule_ready(struct graes_priv *pDev, int ints_off)
curr_bd->bd->u.d[i++] = addr;
}
- drvmgr_translate(pDev->dev, 0, 0, (void *)curr_bd->next->bd, (void **)&naddr);
+ drvmgr_translate(pDev->dev, CPUMEM_TO_DMA, (void *)curr_bd->next->bd, (void **)&naddr);
curr_bd->bd->u.d[i++] = naddr;
if ( curr_bd->next == pDev->_ring ){
diff --git a/c/src/lib/libbsp/sparc/shared/grpwrx/grpwrx.c b/c/src/lib/libbsp/sparc/shared/grpwrx/grpwrx.c
index 2f29c148a4..bfc6462b48 100644
--- a/c/src/lib/libbsp/sparc/shared/grpwrx/grpwrx.c
+++ b/c/src/lib/libbsp/sparc/shared/grpwrx/grpwrx.c
@@ -530,7 +530,12 @@ static int grpwrx_start(struct grpwrx_priv *pDev)
regs->dma_status = GRPWRX_DMA_STS_ALL;
/* Set Descriptor Pointer Base register to point to first descriptor */
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->bds, (void **)&transaddr);
+ drvmgr_translate_check(
+ pDev->dev,
+ CPUMEM_TO_DMA,
+ (void *)pDev->bds,
+ (void **)&transaddr,
+ GRPWRX_BDAR_SIZE);
regs->dma_bd = transaddr;
DBG("GRPWRX: set bd to 0x%08x\n",transaddr);
@@ -789,7 +794,7 @@ static int grpwrx_schedule_ready(struct grpwrx_priv *pDev, int ints_off)
*/
if ( curr_frm->flags & (GRPWRX_FLAGS_TRANSLATE|GRPWRX_FLAGS_TRANSLATE_AND_REMEMBER) ) {
/* Do translation */
- drvmgr_translate(pDev->dev, 0, 0, (void *)curr_frm->payload, (void **)&transaddr);
+ drvmgr_translate(pDev->dev, CPUMEM_TO_DMA, (void *)curr_frm->payload, (void **)&transaddr);
curr_bd->bd->address = transaddr;
if ( curr_frm->flags & GRPWRX_FLAGS_TRANSLATE_AND_REMEMBER ) {
if ( curr_frm->payload != curr_bd->bd->address ) {
diff --git a/c/src/lib/libbsp/sparc/shared/net/greth.c b/c/src/lib/libbsp/sparc/shared/net/greth.c
index fea8890c72..d72158627a 100644
--- a/c/src/lib/libbsp/sparc/shared/net/greth.c
+++ b/c/src/lib/libbsp/sparc/shared/net/greth.c
@@ -203,11 +203,11 @@ struct greth_softc
int greth_process_tx_gbit(struct greth_softc *sc);
int greth_process_tx(struct greth_softc *sc);
-static char *almalloc(int sz)
+static char *almalloc(int sz, int alignment)
{
char *tmp;
- tmp = calloc(1,2*sz);
- tmp = (char *) (((int)tmp+sz) & ~(sz -1));
+ tmp = calloc(1, sz + (alignment-1));
+ tmp = (char *) (((int)tmp+alignment) & ~(alignment -1));
return(tmp);
}
@@ -490,17 +490,26 @@ auto_neg_done:
;
regs->ctrl = GRETH_CTRL_DD;
- /* Initialize rx/tx descriptor pointers */
- sc->txdesc = (greth_rxtxdesc *) almalloc(1024);
- sc->rxdesc = (greth_rxtxdesc *) almalloc(1024);
+ /* Initialize rx/tx descriptor table pointers. Due to alignment we
+ * always allocate maximum table size.
+ */
+ sc->txdesc = (greth_rxtxdesc *) almalloc(0x800, 0x400);
+ sc->rxdesc = (greth_rxtxdesc *) &sc->txdesc[128];
sc->tx_ptr = 0;
sc->tx_dptr = 0;
sc->tx_cnt = 0;
sc->rx_ptr = 0;
- /* Translate the base address into an address that the GRETH core can understand */
- drvmgr_translate(sc->dev, 0, 0, (void *)sc->txdesc, (void **)&sc->txdesc_remote);
- drvmgr_translate(sc->dev, 0, 0, (void *)sc->rxdesc, (void **)&sc->rxdesc_remote);
+ /* Translate the Descriptor DMA table base address into an address that
+ * the GRETH core can understand
+ */
+ drvmgr_translate_check(
+ sc->dev,
+ CPUMEM_TO_DMA,
+ (void *)sc->txdesc,
+ (void **)&sc->txdesc_remote,
+ 0x800);
+ sc->rxdesc_remote = sc->txdesc_remote + 0x400;
regs->txdesc = (int) sc->txdesc_remote;
regs->rxdesc = (int) sc->rxdesc_remote;
@@ -509,10 +518,15 @@ auto_neg_done:
for (i = 0; i < sc->txbufs; i++)
{
- sc->txdesc[i].ctrl = 0;
- if (!(sc->gbit_mac)) {
- drvmgr_translate(sc->dev, 0, 0, (void *)malloc(GRETH_MAXBUF_LEN), (void **)&sc->txdesc[i].addr);
- }
+ sc->txdesc[i].ctrl = 0;
+ if (!(sc->gbit_mac)) {
+ drvmgr_translate_check(
+ sc->dev,
+ CPUMEM_TO_DMA,
+ (void *)malloc(GRETH_MAXBUF_LEN),
+ (void **)&sc->txdesc[i].addr,
+ GRETH_MAXBUF_LEN);
+ }
#ifdef GRETH_DEBUG
/* printf("TXBUF: %08x\n", (int) sc->txdesc[i].addr); */
#endif
@@ -525,7 +539,12 @@ auto_neg_done:
m->m_data += 2;
m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
sc->rxmbuf[i] = m;
- drvmgr_translate(sc->dev, 0, 0, (void *)mtod(m, uint32_t *), (void **)&sc->rxdesc[i].addr);
+ drvmgr_translate_check(
+ sc->dev,
+ CPUMEM_TO_DMA,
+ (void *)mtod(m, uint32_t *),
+ (void **)&sc->rxdesc[i].addr,
+ GRETH_MAXBUF_LEN);
sc->rxdesc[i].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ;
#ifdef GRETH_DEBUG
/* printf("RXBUF: %08x\n", (int) sc->rxdesc[i].addr); */
@@ -718,7 +737,12 @@ again:
m->m_data += 2;
dp->rxmbuf[dp->rx_ptr] = m;
m->m_pkthdr.rcvif = ifp;
- drvmgr_translate(dp->dev, 0, 0, (void *)mtod (m, uint32_t *), (void **)&dp->rxdesc[dp->rx_ptr].addr);
+ drvmgr_translate_check(
+ dp->dev,
+ CPUMEM_TO_DMA,
+ (void *)mtod (m, uint32_t *),
+ (void **)&dp->rxdesc[dp->rx_ptr].addr,
+ GRETH_MAXBUF_LEN);
dp->rxPackets++;
}
if (dp->rx_ptr == dp->rxbufs - 1) {
@@ -773,7 +797,7 @@ sendpacket (struct ifnet *ifp, struct mbuf *m)
len = 0;
temp = (unsigned char *) GRETH_MEM_LOAD(&dp->txdesc[dp->tx_ptr].addr);
- drvmgr_translate(dp->dev, 1, 1, (void *)temp, (void **)&temp);
+ drvmgr_translate(dp->dev, CPUMEM_FROM_DMA, (void *)temp, (void **)&temp);
#ifdef GRETH_DEBUG
printf("TXD: 0x%08x : BUF: 0x%08x\n", (int) m->m_data, (int) temp);
#endif
@@ -887,7 +911,12 @@ sendpacket_gbit (struct ifnet *ifp, struct mbuf *m)
printf("\n");
#endif
len += m->m_len;
- drvmgr_translate(dp->dev, 0, 0, (void *)(uint32_t *)m->m_data, (void **)&dp->txdesc[dp->tx_ptr].addr);
+ drvmgr_translate_check(
+ dp->dev,
+ CPUMEM_TO_DMA,
+ (void *)(uint32_t *)m->m_data,
+ (void **)&dp->txdesc[dp->tx_ptr].addr,
+ m->m_len);
/* Wrap around? */
if (dp->tx_ptr < dp->txbufs-1) {
diff --git a/c/src/lib/libbsp/sparc/shared/spw/grspw.c b/c/src/lib/libbsp/sparc/shared/spw/grspw.c
index 42dbeae887..2e3ae5c37c 100644
--- a/c/src/lib/libbsp/sparc/shared/spw/grspw.c
+++ b/c/src/lib/libbsp/sparc/shared/spw/grspw.c
@@ -159,11 +159,12 @@ typedef struct {
char *ptr_rxbuf0;
char *ptr_txdbuf0;
char *ptr_txhbuf0;
- char *ptr_bd0;
+ char *_ptr_bd0, *ptr_bd0;
char *ptr_rxbuf0_remote;
char *ptr_txdbuf0_remote;
char *ptr_txhbuf0_remote;
+ char *ptr_bd0_remote;
unsigned int irq;
int minor;
@@ -655,73 +656,122 @@ static unsigned int grspw_calc_disconnect(int freq_khz){
static int grspw_buffer_alloc(GRSPW_DEV *pDev)
{
- if ( pDev->rx_dma_area ) {
-#warning Check size?
- if ( pDev->rx_dma_area & 1 ) {
- /* Address given in remote address */
- drvmgr_translate(pDev->dev, 1, 1, (void *)(pDev->rx_dma_area & ~1), (void **)&pDev->ptr_rxbuf0);
- } else {
- pDev->ptr_rxbuf0 = pDev->rx_dma_area;
- }
+ /* RX DMA AREA */
+ if (pDev->rx_dma_area & 1) {
+ /* Address given in remote address */
+ pDev->ptr_rxbuf0_remote = (char *)(pDev->rx_dma_area & ~1);
+ drvmgr_translate_check(
+ pDev->dev,
+ DMAMEM_TO_CPU,
+ (void *)pDev->ptr_rxbuf0_remote,
+ (void **)&pDev->ptr_rxbuf0,
+ pDev->rxbufsize * pDev->rxbufcnt);
+
} else {
- if (pDev->_ptr_rxbuf0) {
- free(pDev->_ptr_rxbuf0);
- }
- pDev->_ptr_rxbuf0 = (unsigned int) malloc(pDev->rxbufsize * pDev->rxbufcnt+4);
- pDev->ptr_rxbuf0 = (char *)((pDev->_ptr_rxbuf0+7)&~7);
- if ( !pDev->ptr_rxbuf0 )
- return 1;
- }
- if ( pDev->tx_data_dma_area ) {
- if ( pDev->tx_data_dma_area & 1 ) {
- /* Address given in remote address */
- drvmgr_translate(pDev->dev, 1, 1, (void *)(pDev->tx_data_dma_area & ~1), (void **)&pDev->ptr_txdbuf0);
+ if (pDev->rx_dma_area == 0) {
+ if (pDev->_ptr_rxbuf0)
+ free((void *)pDev->_ptr_rxbuf0);
+ pDev->_ptr_rxbuf0 = (unsigned int) malloc(pDev->rxbufsize * pDev->rxbufcnt+4);
+ pDev->ptr_rxbuf0 = (char *)((pDev->_ptr_rxbuf0+7)&~7);
+ if ( !pDev->ptr_rxbuf0 )
+ return 1;
} else {
- pDev->ptr_txdbuf0 = pDev->tx_data_dma_area;
+ pDev->ptr_rxbuf0 = (char *)pDev->rx_dma_area;
}
- } else {
- if (pDev->ptr_txdbuf0) {
- free(pDev->ptr_txdbuf0);
- }
- pDev->ptr_txdbuf0 = (char *) malloc(pDev->txdbufsize * pDev->txbufcnt);
- if ( !pDev->ptr_txdbuf0 )
- return 1;
+ drvmgr_translate_check(
+ pDev->dev,
+ CPUMEM_TO_DMA,
+ (void *)pDev->ptr_rxbuf0,
+ (void **)&pDev->ptr_rxbuf0_remote,
+ pDev->rxbufsize * pDev->rxbufcnt);
}
- if ( pDev->tx_hdr_dma_area ) {
- if ( pDev->tx_hdr_dma_area & 1 ) {
- /* Address given in remote address */
- drvmgr_translate(pDev->dev, 1, 1, (void *)(pDev->tx_hdr_dma_area & ~1), (void **)&pDev->ptr_txhbuf0);
- } else {
- pDev->ptr_txhbuf0 = pDev->tx_hdr_dma_area;
- }
+
+ /* TX-DATA DMA AREA */
+ if (pDev->tx_data_dma_area & 1) {
+ /* Address given in remote address */
+ pDev->ptr_txdbuf0_remote = (char*)(pDev->tx_data_dma_area & ~1);
+ drvmgr_translate_check(
+ pDev->dev,
+ DMAMEM_TO_CPU,
+ (void *)pDev->ptr_txdbuf0_remote,
+ (void **)&pDev->ptr_txdbuf0,
+ pDev->txdbufsize * pDev->txbufcnt);
} else {
- if (pDev->ptr_txhbuf0) {
- free(pDev->ptr_txhbuf0);
+ if (pDev->tx_data_dma_area == 0) {
+ if (pDev->ptr_txdbuf0)
+ free(pDev->ptr_txdbuf0);
+ pDev->ptr_txdbuf0 = (char *) malloc(pDev->txdbufsize * pDev->txbufcnt);
+ if (!pDev->ptr_txdbuf0)
+ return 1;
+ } else {
+ pDev->ptr_txdbuf0 = (char *)pDev->tx_data_dma_area;
}
- pDev->ptr_txhbuf0 = (char *) malloc(pDev->txhbufsize * pDev->txbufcnt);
- if ( !pDev->ptr_txhbuf0 )
- return 1;
+ drvmgr_translate_check(
+ pDev->dev,
+ CPUMEM_TO_DMA,
+ (void *)pDev->ptr_txdbuf0,
+ (void **)&pDev->ptr_txdbuf0_remote,
+ pDev->txdbufsize * pDev->txbufcnt);
}
- if ( pDev->bd_dma_area ) {
- if ( pDev->bd_dma_area & 1 ) {
- /* Address given in remote address */
- drvmgr_translate(pDev->dev, 1, 1, (void *)(pDev->bd_dma_area & ~1), (void **)&pDev->ptr_bd0);
+
+ /* TX-HEADER DMA AREA */
+ if (pDev->tx_hdr_dma_area & 1) {
+ /* Address given in remote address */
+ pDev->ptr_txhbuf0_remote = (char *)(pDev->tx_hdr_dma_area & ~1);
+ drvmgr_translate_check(
+ pDev->dev,
+ DMAMEM_TO_CPU,
+ (void *)pDev->ptr_txhbuf0_remote,
+ (void **)&pDev->ptr_txhbuf0,
+ pDev->txhbufsize * pDev->txbufcnt);
+ } else {
+ if (pDev->tx_hdr_dma_area == 0) {
+ if (pDev->ptr_txhbuf0)
+ free(pDev->ptr_txhbuf0);
+ pDev->ptr_txhbuf0 = (char *) malloc(pDev->txhbufsize * pDev->txbufcnt);
+ if (!pDev->ptr_txhbuf0)
+ return 1;
} else {
- pDev->ptr_bd0 = pDev->bd_dma_area;
+ pDev->ptr_txhbuf0 = (char *)pDev->tx_hdr_dma_area;
}
+ drvmgr_translate_check(
+ pDev->dev,
+ CPUMEM_TO_DMA,
+ (void *)pDev->ptr_txhbuf0,
+ (void **)&pDev->ptr_txhbuf0_remote,
+ pDev->txhbufsize * pDev->txbufcnt);
+ }
+
+ /* DMA DESCRIPTOR TABLES */
+ if (pDev->bd_dma_area & 1) {
+ /* Address given in remote address */
+ pDev->ptr_bd0_remote = (char *)(pDev->bd_dma_area & ~1);
+ drvmgr_translate_check(
+ pDev->dev,
+ DMAMEM_TO_CPU,
+ (void *)pDev->ptr_bd0_remote,
+ (void **)&pDev->ptr_bd0,
+ 2 * SPACEWIRE_BDTABLE_SIZE);
} else {
- if (pDev->ptr_bd0) {
- free(pDev->ptr_bd0);
+ if (pDev->bd_dma_area == 0) {
+ if (pDev->_ptr_bd0)
+ free(pDev->_ptr_bd0);
+ pDev->_ptr_bd0 = malloc(3 * SPACEWIRE_BDTABLE_SIZE);
+ if (!pDev->_ptr_bd0)
+ return 1;
+ pDev->ptr_bd0 = (char *)SPW_ALIGN(pDev->_ptr_bd0,
+ SPACEWIRE_BDTABLE_SIZE);
+ } else {
+ pDev->ptr_bd0 = (char *)pDev->bd_dma_area;
}
- pDev->ptr_bd0 = (char *) malloc(3*SPACEWIRE_BDTABLE_SIZE);
- if ( !pDev->ptr_bd0 )
- return 1;
+ drvmgr_translate_check(
+ pDev->dev,
+ CPUMEM_TO_DMA,
+ (void *)pDev->ptr_bd0,
+ (void **)&pDev->ptr_bd0_remote,
+ 2 * SPACEWIRE_BDTABLE_SIZE);
}
- /* Translate into remote address */
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->ptr_rxbuf0, (void **)&pDev->ptr_rxbuf0_remote);
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->ptr_txdbuf0,(void **)&pDev->ptr_txdbuf0_remote);
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->ptr_txhbuf0, (void **)&pDev->ptr_txhbuf0_remote);
return 0;
}
@@ -1592,12 +1642,12 @@ static int grspw_hw_init(GRSPW_DEV *pDev) {
ctrl = SPW_CTRL_READ(pDev);
- pDev->rx = (SPACEWIRE_RXBD *) SPW_ALIGN(pDev->ptr_bd0, SPACEWIRE_BDTABLE_SIZE);
- pDev->tx = (SPACEWIRE_TXBD *) &pDev->rx[SPACEWIRE_RXBUFS_NR];
+ pDev->rx = (SPACEWIRE_RXBD *) pDev->ptr_bd0;
+ pDev->tx = (SPACEWIRE_TXBD *) (pDev->ptr_bd0 + SPACEWIRE_BDTABLE_SIZE);
- /* Translate into remote address */
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->rx, (void **)&pDev->rx_remote);
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->tx, (void **)&pDev->tx_remote);
+ /* Set up remote addresses */
+ pDev->rx_remote = (unsigned int)pDev->ptr_bd0_remote;
+ pDev->tx_remote = pDev->rx_remote + SPACEWIRE_BDTABLE_SIZE;
SPACEWIRE_DBG("hw_init [minor %i]\n", pDev->minor);
@@ -1779,7 +1829,6 @@ int grspw_hw_send(GRSPW_DEV *pDev, unsigned int hlen, char *hdr, unsigned int dl
char *txd = pDev->ptr_txdbuf0 + (cur * pDev->txdbufsize);
char *txh_remote = pDev->ptr_txhbuf0_remote + (cur * pDev->txhbufsize);
char *txd_remote = pDev->ptr_txdbuf0_remote + (cur * pDev->txdbufsize);
- unsigned int tmp, tmp2;
ctrl = SPW_READ((volatile void *)&pDev->tx[cur].ctrl);
diff --git a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
index 10a869748d..3573812718 100644
--- a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
+++ b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c
@@ -483,6 +483,7 @@ void *grspw_open(int dev_no)
* - 128 RX descriptors per DMA Channel
* - 64 TX descriptors per DMA Channel
*/
+ bdtabsize = 2 * BDTAB_SIZE * priv->hwsup.ndma_chans;
value = drvmgr_dev_key_get(priv->dev, "bdDmaArea", KEY_TYPE_INT);
if (value) {
priv->bd_mem = value->i;
@@ -494,7 +495,6 @@ void *grspw_open(int dev_no)
goto out;
}
} else {
- bdtabsize = 2 * BDTAB_SIZE * priv->hwsup.ndma_chans;
priv->bd_mem_alloced = (unsigned int)malloc(bdtabsize + BDTAB_ALIGN - 1);
if (priv->bd_mem_alloced == 0) {
priv = NULL;
@@ -508,7 +508,12 @@ void *grspw_open(int dev_no)
/* Translate into DMA address that HW can use to access DMA
* descriptors
*/
- drvmgr_translate(priv->dev, 0, 0, (void *)priv->bd_mem, (void **)&hwa);
+ drvmgr_translate_check(
+ priv->dev,
+ CPUMEM_TO_DMA,
+ (void *)priv->bd_mem,
+ (void **)&hwa,
+ bdtabsize);
GRSPW_DBG("GRSPW%d DMA descriptor table setup: (alloced:%p, bd_mem:%p, size: %d)\n",
priv->index, priv->bd_mem_alloced, priv->bd_mem, bdtabsize + BDTAB_ALIGN - 1);
@@ -968,7 +973,8 @@ STATIC int grspw_rx_schedule_ready(struct grspw_dma_priv *dma)
/* Prepare descriptor address. */
hwaddr = curr_pkt->data;
if (curr_pkt->flags & PKT_FLAG_TR_DATA) {
- drvmgr_translate(dma->core->dev, 0, 0, hwaddr, &hwaddr);
+ drvmgr_translate(dma->core->dev, CPUMEM_TO_DMA,
+ hwaddr, &hwaddr);
if (curr_pkt->data == hwaddr) /* translation needed? */
curr_pkt->flags &= ~PKT_FLAG_TR_DATA;
}
@@ -1182,7 +1188,8 @@ STATIC int grspw_tx_schedule_send(struct grspw_dma_priv *dma)
if (curr_pkt->hdr && curr_pkt->hlen) {
hwaddr = curr_pkt->hdr;
if (curr_pkt->flags & PKT_FLAG_TR_HDR) {
- drvmgr_translate(dma->core->dev, 0, 0, hwaddr, &hwaddr);
+ drvmgr_translate(dma->core->dev, CPUMEM_TO_DMA,
+ hwaddr, &hwaddr);
/* translation needed? */
if (curr_pkt->hdr == hwaddr)
curr_pkt->flags &= ~PKT_FLAG_TR_HDR;
@@ -1221,7 +1228,8 @@ STATIC int grspw_tx_schedule_send(struct grspw_dma_priv *dma)
if (curr_pkt->data && curr_pkt->dlen) {
hwaddr = curr_pkt->data;
if (curr_pkt->flags & PKT_FLAG_TR_DATA) {
- drvmgr_translate(dma->core->dev, 0, 0, hwaddr, &hwaddr);
+ drvmgr_translate(dma->core->dev, CPUMEM_TO_DMA,
+ hwaddr, &hwaddr);
/* translation needed? */
if (curr_pkt->data == hwaddr)
curr_pkt->flags &= ~PKT_FLAG_TR_DATA;
diff --git a/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c b/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
index 470c5c7eb4..3c8a90ef07 100644
--- a/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
+++ b/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
@@ -1629,22 +1629,26 @@ static rtems_device_driver grtc_ioctl(rtems_device_major_number major, rtems_dev
pDev->buf = NULL;
pDev->len = buf_arg->length*1024;
- if ( pDev->len > 0 ){
- if ( buf_arg->custom_buffer ){
- if ( (unsigned int)buf_arg->custom_buffer & 1 ) {
- /* Remote address given, the address is as the GRTC core looks at it */
-
- /* Translate the base address into an address that the the CPU can understand */
- mem = ((unsigned int)buf_arg->custom_buffer & ~1);
- drvmgr_translate(pDev->dev, 1, 1, (void *)mem, (void **)&pDev->buf);
- } else {
- pDev->buf = buf_arg->custom_buffer;
- }
- pDev->buf_custom = 1;
- }else{
+ if (pDev->len <= 0)
+ break;
+ mem = (unsigned int)buf_arg->custom_buffer;
+ pDev->buf_custom = mem;
+
+ if (mem & 1) {
+ /* Remote address given, the address is as the GRTC
+ * core looks at it. Translate the base address into
+ * an address that the CPU can understand.
+ */
+ pDev->buf_remote = (void *)(mem & ~0x1);
+ drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU,
+ (void *)pDev->buf_remote,
+ (void **)&pDev->buf,
+ pDev->len);
+ } else {
+ if (mem == 0) {
pDev->buf = grtc_memalign((~GRTC_ASR_BUFST)+1,pDev->len,&pDev->_buf);
DBG("grtc_ioctl: SETBUF: new buf: 0x%x(0x%x), Len: %d\n",pDev->buf,pDev->_buf,pDev->len);
- if ( !pDev->buf ){
+ if (!pDev->buf){
pDev->len = 0;
pDev->buf_custom = 0;
pDev->_buf = NULL;
@@ -1652,10 +1656,19 @@ static rtems_device_driver grtc_ioctl(rtems_device_major_number major, rtems_dev
DBG("GRTC: Failed to allocate memory\n");
return RTEMS_NO_MEMORY;
}
+ } else{
+ pDev->buf = buf_arg->custom_buffer;
}
+
+ /* Translate into a remote address so that GRTC core
+ * on a remote AMBA bus (for example over the PCI bus)
+ * gets a valid address
+ */
+ drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA,
+ (void *)pDev->buf,
+ (void **)&pDev->buf_remote,
+ pDev->len);
}
- /* Translate into a remote address so that GRTC core on a remote AMBA bus (for example over the PCI bus) gets a valid address */
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->buf, (void **)&pDev->buf_remote);
break;
case GRTC_IOC_GET_BUF_PARAM:
diff --git a/c/src/lib/libbsp/sparc/shared/tmtc/grtm.c b/c/src/lib/libbsp/sparc/shared/tmtc/grtm.c
index 8c5bc95b93..fcea522bd4 100644
--- a/c/src/lib/libbsp/sparc/shared/tmtc/grtm.c
+++ b/c/src/lib/libbsp/sparc/shared/tmtc/grtm.c
@@ -810,8 +810,8 @@ static int grtm_start(struct grtm_priv *pDev)
regs->dma_status = GRTM_DMA_STS_ALL;
/* Set Descriptor Pointer Base register to point to first descriptor */
- drvmgr_translate(pDev->dev, 0, 0, (void *)pDev->bds, (void **)&regs->dma_bd);
- /*regs->dma_bd = (unsigned int)pDev->bds;*/
+ drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, (void *)pDev->bds,
+ (void **)&regs->dma_bd, 0x400);
/* Set hardware options as defined by config */
if ( grtm_hw_set_config(pDev, cfg, &pDev->hw_avail) ) {
@@ -1103,7 +1103,7 @@ static int grtm_schedule_ready(struct grtm_priv *pDev, int ints_off)
*/
if ( curr_frm->flags & (GRTM_FLAGS_TRANSLATE|GRTM_FLAGS_TRANSLATE_AND_REMEMBER) ) {
/* Do translation */
- drvmgr_translate(pDev->dev, 0, 0, (void *)curr_frm->payload, (void **)&curr_bd->bd->address);
+ drvmgr_translate(pDev->dev, CPUMEM_TO_DMA, (void *)curr_frm->payload, (void **)&curr_bd->bd->address);
if ( curr_frm->flags & GRTM_FLAGS_TRANSLATE_AND_REMEMBER ) {
if ( curr_frm->payload != curr_bd->bd->address ) {
/* Translation needed */
diff --git a/cpukit/libdrvmgr/Makefile.am b/cpukit/libdrvmgr/Makefile.am
index 898db65999..d93854a6c4 100644
--- a/cpukit/libdrvmgr/Makefile.am
+++ b/cpukit/libdrvmgr/Makefile.am
@@ -27,6 +27,7 @@ libdrvmgr_a_SOURCES += drvmgr_print.c
libdrvmgr_a_SOURCES += drvmgr_res.c
libdrvmgr_a_SOURCES += drvmgr_rw.c
libdrvmgr_a_SOURCES += drvmgr_translate.c
+libdrvmgr_a_SOURCES += drvmgr_translate_check.c
libdrvmgr_a_SOURCES += drvmgr_unregister.c
include $(top_srcdir)/automake/local.am
diff --git a/cpukit/libdrvmgr/drvmgr.h b/cpukit/libdrvmgr/drvmgr.h
index 05c6956bcb..09d46ea4b2 100644
--- a/cpukit/libdrvmgr/drvmgr.h
+++ b/cpukit/libdrvmgr/drvmgr.h
@@ -613,44 +613,86 @@ extern int drvmgr_interrupt_mask(
struct drvmgr_dev *dev,
int index);
+/*! drvmgr_translate() translation options */
+enum drvmgr_tr_opts {
+ /* Translate CPU RAM Address (input) to DMA unit accessible address
+ * (output), this is an upstreams translation in reverse order.
+ *
+ * Typical Usage:
+ * It is common to translate a CPU accessible RAM address to an
+ * address that DMA units can access over bridges.
+ */
+ CPUMEM_TO_DMA = 0x0,
+
+ /* Translate DMA Unit Accessible address mapped to CPU RAM (input) to
+ * CPU accessible address (output). This is an upstreams translation.
+ *
+ * Typical Usage (not often used):
+ * The DMA unit descriptors contain pointers to DMA buffers located at
+ * CPU RAM addresses that the DMA unit can access, the CPU processes
+ * the descriptors and want to access the data but a translation back
+ * to CPU address is required.
+ */
+ CPUMEM_FROM_DMA = 0x1,
+
+ /* Translate DMA Memory Address (input) to CPU accessible address
+ * (output), this is a downstreams translation in reverse order.
+ *
+ * Typical Usage:
+ * A PCI network card puts packets into its memory not doing DMA over
+ * PCI, in order for the CPU to access them the PCI address must be
+ * translated.
+ */
+ DMAMEM_TO_CPU = 0x2,
+
+ /* Translate CPU accessible address (input) mapped to DMA Memory Address
+ * to DMA Unit accessible address (output). This is a downstreams
+ * translation.
+ */
+ DMAMEM_FROM_CPU = 0x3,
+};
+#define DRVMGR_TR_REVERSE 0x1 /* do reverse translation direction order */
+#define DRVMGR_TR_PATH 0x2 /* 0x0=down-stream 0x2=up-stream address path */
+
/*! Translate an address on one bus to an address on another bus.
*
* The device determines source or destination bus, the root bus is always
* the other bus. It is assumed that the CPU is located on the root bus or
- * that it can access it without address translation (mapped 1:1).
- *
- * cpu_addresses determines if the address is targeted for the CPU (1) or
- * hardware (0) doing DMA.
- *
- * The address conversion can be done up-streams (towards the CPU) or down-
- * streams (towards DMA hardware) the bus architecture. The CPU is assumed
- * to be located on level 0 top most in the bus hierarchy.
+ * that it can access it without address translation (mapped 1:1). The CPU
+ * is thus assumed to be located on level 0 top most in the bus hierarchy.
*
- * Source address is translated and the result is put into *dst_address, if
- * the address is not accessible on the other bus -1 is returned.
+ * If no map is present in the bus driver src_address is translated 1:1
+ * (just copied).
*
+ * Addresses are typically converted up-streams from the DMA unit towards the
+ * CPU (DMAMEM_TO_CPU) or down-streams towards DMA hardware from the CPU
+ * (CPUMEM_TO_DMA) over one or multiple bridges depending on bus architecture.
+ * See 'enum drvmgr_tr_opts' for other translation direction options.
+ * For example:
* Two common operations is to translate a CPU accessible RAM address to an
- * address that DMA units can access (dev=DMA-unit, cpu_address=0, upstream=0,
+ * address that DMA units can access (dev=DMA-unit, CPUMEM_TO_DMA,
* src_address=CPU-RAM-ADR) and to translate an address of a PCI resource for
* example RAM mapped into a PCI BAR to an CPU accessible address
- * (dev=PCI-device, cpu_address=1, upstream=1, src_address=PCI-BAR-ADR).
+ * (dev=PCI-device, DMAMEM_TO_CPU, src_address=PCI-BAR-ADR).
+ *
+ * Source address is translated and the result is put into *dst_address, if
+ * the address is not accessible on the other bus -1 is returned.
*
* \param dev Device to translate addresses for
- * \param cpu_addresses Addresses are inteded for CPU(1) or DMA-Hardware(0)
- * \param upsteam Select translation direction (0=towards hardware,
- * 1=towards CPU) and thereby which bus src_address is
- * valid for
+ * \param options Tanslation direction options, see enum drvmgr_tr_opts
* \param src_address Address to translate
* \param dst_address Location where translated address is stored
*
- * Returns -1 if unable to translate. If no map is present src_address is
- * translated 1:1 (just copied). If dev is on root-bus no translation is
- * performed 0 is returned and src_address is stored in *dst_address.
+ * Returns 0 if unable to translate. The remaining length from the given
+ * address of the map is returned on success, for example if a map starts
+ * at 0x40000000 of size 0x100000 the result will be 0x40000 if the address
+ * was translated into 0x400C0000.
+ * If dev is on root-bus no translation is performed 0xffffffff is returned
+ * and src_address is stored in *dst_address.
*/
-extern int drvmgr_translate(
+extern unsigned int drvmgr_translate(
struct drvmgr_dev *dev,
- int cpu_addresses,
- int upstream,
+ unsigned int options,
void *src_address,
void **dst_address);
@@ -666,16 +708,35 @@ extern int drvmgr_translate(
* \param src_address Address to be translated
* \param dst_address Translated address is stored here on success (return=0)
*
- * Returns -1 if failed to translate address between buses. 0 successfully
- * translated, reuslt is in *dst_address
+ * Returns 0 if unable to translate. The remaining length from the given
+ * address of the map is returned on success and the result is stored into
+ * *dst_address. For example if a map starts at 0x40000000 of size 0x100000
+ * the result will be 0x40000 if the address was translated into 0x400C0000.
+ * If dev is on root-bus no translation is performed 0xffffffff is returned.
+ * and src_address is stored in *dst_address.
*/
-extern int drvmgr_translate_bus(
+extern unsigned int drvmgr_translate_bus(
struct drvmgr_bus *from,
struct drvmgr_bus *to,
int reverse,
void *src_address,
void **dst_address);
+/* Calls drvmgr_translate() to translate an address range and checks the result,
+ * a printout is generated if the check fails. All parameters are passed on to
+ * drvmgr_translate() except for size, see paramters of drvmgr_translate().
+ *
+ * If size=0 only the starting address is not checked.
+ *
+ * If mapping failes a non-zero result is returned.
+ */
+extern int drvmgr_translate_check(
+ struct drvmgr_dev *dev,
+ unsigned int options,
+ void *src_address,
+ void **dst_address,
+ unsigned int size);
+
/*! Get function pointer from Device Driver or Bus Driver.
*
* Returns 0 if function is available
diff --git a/cpukit/libdrvmgr/drvmgr_translate.c b/cpukit/libdrvmgr/drvmgr_translate.c
index 630ba6f007..7f12aa5588 100644
--- a/cpukit/libdrvmgr/drvmgr_translate.c
+++ b/cpukit/libdrvmgr/drvmgr_translate.c
@@ -28,7 +28,7 @@
#include <drvmgr/drvmgr.h>
#include "drvmgr_internal.h"
-int drvmgr_translate_bus(
+unsigned int drvmgr_translate_bus(
struct drvmgr_bus *from,
struct drvmgr_bus *to,
int reverse,
@@ -36,61 +36,61 @@ int drvmgr_translate_bus(
void **dst_address)
{
struct drvmgr_bus *path[16];
- int upstream, ret, depth, i;
+ int dir, levels, i;
void *dst, *from_adr, *to_adr;
struct drvmgr_map_entry *map;
struct drvmgr_bus *bus;
+ unsigned int sz;
+ struct drvmgr_bus *bus_bot, *bus_top;
dst = src_address;
- ret = 0;
+ sz = 0xffffffff;
- if (from == to) /* no need traslating addresses when on same bus */
+ if (from == to) /* no need translating addresses when on same bus */
goto out;
+ /* Always find translation path from remote bus towards root bus. All
+ * buses have root bus has parent at some level
+ */
if (from->depth > to->depth) {
- /* up-streams */
- upstream = 1;
- depth = from->depth - to->depth;
- if (depth >= 16)
- return -1; /* Does not support such a big depth */
-
- /* Intensionally we skip the last bus since its bridge is
- * not used in this translation
- */
- path[0] = from;
- for (i=1; i < depth; i++)
- path[i] = path[i-1]->dev->parent;
+ bus_bot = from;
+ bus_top = to;
+ dir = 0;
} else {
- /* down-streams */
- upstream = 0;
- depth = to->depth - from->depth;
- if (depth >= 16)
- return -1; /* Does not support such a big depth */
-
- /* Intensionally we skip the last bus since its bridge is
- * not used in this translation
- */
- path[depth-1] = to;
- for (i=depth-1; i > 0; i--)
- path[i-1] = path[i]->dev->parent;
+ bus_bot = to;
+ bus_top = from;
+ dir = 1;
}
+ levels = bus_bot->depth - bus_top->depth;
+ if (levels >= 16)
+ return 0; /* Does not support such a big depth */
+ i = 0;
+ while ((bus_bot != NULL) && bus_bot != bus_top) {
+ if (dir)
+ path[(levels - 1) - i] = bus_bot;
+ else
+ path[i] = bus_bot;
+ i++;
+ bus_bot = bus_bot->dev->parent;
+ }
+ if (bus_bot == NULL)
+ return 0; /* from -> to is not linearly connected */
- /* Translate address */
- for (i=0; i < depth && ret == 0; i++) {
+ for (i = 0; i < levels; i++) {
bus = path[i];
- if ((upstream && reverse) || (!upstream && !reverse))
- map = bus->maps_down;
- else
+ if ((dir && reverse) || (!dir && !reverse))
map = bus->maps_up;
+ else
+ map = bus->maps_down;
if (map == NULL)
continue; /* No translation needed - 1:1 mapping */
- ret = -1;
-
- if (map == DRVMGR_TRANSLATE_NO_BRIDGE)
+ if (map == DRVMGR_TRANSLATE_NO_BRIDGE) {
+ sz = 0;
break; /* No bridge interface in this direction */
+ }
while (map->size != 0) {
if (reverse) {
@@ -104,49 +104,44 @@ int drvmgr_translate_bus(
if ((dst >= from_adr) &&
(dst <= (from_adr + (map->size - 1)))) {
+ if (((from_adr + (map->size - 1)) - dst) < sz)
+ sz = (from_adr + (map->size - 1)) - dst;
dst = (dst - from_adr) + to_adr;
- ret = 0;
break;
}
map++;
}
+ /* quit if no matching translation information */
+ if (map->size == 0) {
+ sz = 0;
+ break;
+ }
}
out:
if (dst_address)
*dst_address = dst;
- return ret;
+ return sz;
}
-/* Translate Address, used by drivers when an address need to be
- * converted in order to access a remote address or for a remote
- * hardware to access (DMA) to access CPU local RAM.
- * - from remote address to CPU local
- * - from CPU local to remote
- */
-int drvmgr_translate(
+unsigned int drvmgr_translate(
struct drvmgr_dev *dev,
- int cpu_addresses,
- int upstream,
+ unsigned int options,
void *src_address,
void **dst_address)
{
struct drvmgr_bus *to, *from;
- int rev;
+ int rev = 0;
- if (upstream) {
- from = dev->parent;
- to = drv_mgr.root_dev.bus;
- } else {
+ rev = (~options) & 1;
+ if ((options == CPUMEM_TO_DMA) || (options == DMAMEM_FROM_CPU)) {
from = drv_mgr.root_dev.bus;
to = dev->parent;
+ } else { /* CPUMEM_FROM_DMA || DMAMEM_TO_CPU */
+ from = dev->parent;
+ to = drv_mgr.root_dev.bus;
}
- if (cpu_addresses)
- rev = upstream;
- else
- rev = !upstream;
-
return drvmgr_translate_bus(from, to, rev, src_address, dst_address);
}
diff --git a/cpukit/libdrvmgr/drvmgr_translate_check.c b/cpukit/libdrvmgr/drvmgr_translate_check.c
new file mode 100644
index 0000000000..bd9c07177c
--- /dev/null
+++ b/cpukit/libdrvmgr/drvmgr_translate_check.c
@@ -0,0 +1,35 @@
+/* Driver Manager Driver Translate Interface Implementation
+ *
+ * COPYRIGHT (c) 2010.
+ * Aeroflex Gaisler AB
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <drvmgr/drvmgr.h>
+
+/* Calls drvmgr_translate() to translate an address range and check the result,
+ * a printout is generated if the check fails. See paramters of
+ * drvmgr_translate().
+ * If size=0 only the starting address is not checked.
+ */
+int drvmgr_translate_check(
+ struct drvmgr_dev *dev,
+ unsigned int options,
+ void *src_address,
+ void **dst_address,
+ unsigned int size)
+{
+ unsigned int max;
+
+ max = drvmgr_translate(dev, options, src_address, dst_address);
+ if (max == 0 || (max < size && (size != 0))) {
+ printk(" ### dev %p (%s) failed mapping %p\n",
+ dev, dev->name ? dev->name : "unnamed", src_address);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/cpukit/libmisc/shell/main_drvmgr.c b/cpukit/libmisc/shell/main_drvmgr.c
index 1a2563af7f..cfea12de4a 100644
--- a/cpukit/libmisc/shell/main_drvmgr.c
+++ b/cpukit/libmisc/shell/main_drvmgr.c
@@ -279,7 +279,7 @@ int shell_drvmgr_mem(int argc, char *argv[])
int shell_drvmgr_translate(int argc, char *argv[])
{
- int rc, cpu, up, obj_type;
+ int rc, rev, up, obj_type;
void *obj, *dst;
unsigned long src, tmp;
@@ -301,8 +301,8 @@ int shell_drvmgr_translate(int argc, char *argv[])
puts(" Not a valid option OPT, only [0..3] is valid");
return 0;
}
- cpu = tmp & 1;
- up = (tmp >> 1) & 1;
+ rev = tmp & DRVMGR_TR_REVERSE;
+ up = tmp & DRVMGR_TR_PATH;
src = strtoul(argv[4], NULL, 0);
if (src == ULONG_MAX && errno == ERANGE) {
@@ -310,11 +310,13 @@ int shell_drvmgr_translate(int argc, char *argv[])
return 0;
}
- rc = drvmgr_translate((struct drvmgr_dev *)obj, cpu, up, (void *)src, &dst);
- if (rc != 0)
+ rc = drvmgr_translate((struct drvmgr_dev *)obj, up | rev, (void *)src, &dst);
+ if (rc == 0)
printf(" Address %p could not be translated\n", (void *)src);
+ else if (rc == 0xffffffff)
+ printf(" %p => %p (no translation required)\n", (void *)src, dst);
else
- printf(" %p => %p\n", (void *)src, dst);
+ printf(" %p => %p (map size 0x%x)\n", (void *)src, dst, rc);
return 0;
}
@@ -334,8 +336,8 @@ const char drvmgr_usage_str[] =
" drvmgr short [ID] Short info about all devices/buses or one\n"
" device/bus\n"
" drvmgr topo Show bus topology with all devices\n"
- " drvmgr tr ID OPT ADR Translate hw(0)/cpu(1) (OPT bit0) address ADR\n"
- " down(0)/up(1) streams (OPT bit1) for device\n"
+ " drvmgr tr ID OPT ADR Translate ADR down(0)/up(1) -streams (OPT bit 1) in\n"
+ " std(0)/reverse(1) (OPT bit 0) direction for device\n"
" drvmgr --help\n";
static void usage(void)