From 242a9113f0d63cd143ddfc3c9fbcd872ac6c6222 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Tue, 21 May 2013 09:46:36 +0200 Subject: 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.. --- c/src/lib/libbsp/sparc/shared/1553/b1553brm.c | 66 ++++++---- c/src/lib/libbsp/sparc/shared/1553/b1553rt.c | 57 +++++---- c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c | 93 +++++++------- c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c | 62 ++++----- c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c | 175 ++++++++++++++------------ c/src/lib/libbsp/sparc/shared/can/grcan.c | 111 +++++++++++----- c/src/lib/libbsp/sparc/shared/graes/graes.c | 7 +- c/src/lib/libbsp/sparc/shared/grpwrx/grpwrx.c | 9 +- c/src/lib/libbsp/sparc/shared/net/greth.c | 63 +++++++--- c/src/lib/libbsp/sparc/shared/spw/grspw.c | 171 ++++++++++++++++--------- c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c | 18 ++- c/src/lib/libbsp/sparc/shared/tmtc/grtc.c | 45 ++++--- c/src/lib/libbsp/sparc/shared/tmtc/grtm.c | 6 +- cpukit/libdrvmgr/Makefile.am | 1 + cpukit/libdrvmgr/drvmgr.h | 111 ++++++++++++---- cpukit/libdrvmgr/drvmgr_translate.c | 109 ++++++++-------- cpukit/libdrvmgr/drvmgr_translate_check.c | 35 ++++++ cpukit/libmisc/shell/main_drvmgr.c | 18 +-- 18 files changed, 726 insertions(+), 431 deletions(-) create mode 100644 cpukit/libdrvmgr/drvmgr_translate_check.c 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; imajor_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 **)®s->dma_bd); - /*regs->dma_bd = (unsigned int)pDev->bds;*/ + drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, (void *)pDev->bds, + (void **)®s->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 #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 + +/* 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) -- cgit v1.2.3