static unsigned int graes_trans(struct graes_priv *pDev, struct graes_block *curr_frm, unsigned int addr_in ) { unsigned int addr = addr_in; /* Prepare descriptor address. Three cases: * - GRAES core on same bus as CPU ==> no translation (Address used by CPU = address used by GRAES) * - GRAES core on remote bus, and payload address given as used by CPU ==> Translation needed * - GRAES core on remote bus, and payload address given as used by GRAES ==> no translation [ USER does custom translation] */ if ( curr_frm->flags & (GRAES_FLAGS_TRANSLATE|GRAES_FLAGS_TRANSLATE_AND_REMEMBER) ) { /* Do translation */ 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 */ curr_frm->flags &= ~GRAES_FLAGS_TRANSLATE_AND_REMEMBER; curr_frm->flags |= GRAES_FLAGS_TRANSLATE; } else { /* No Trnaslation needed */ curr_frm->flags &= ~(GRAES_FLAGS_TRANSLATE|GRAES_FLAGS_TRANSLATE_AND_REMEMBER); } } } else { /* Custom translation or no translation needed */ addr = (unsigned int)addr_in; } return addr; }
/* 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; }
/* Moves as many frames in the ready queue (as there are free descriptors for) * to the scheduled queue. The free descriptors are then assigned one frame * each and enabled for transmission. * * Return Value * Returns number of frames moved from ready to scheduled queue */ static int graes_schedule_ready(struct graes_priv *pDev, int ints_off) { int cnt; unsigned int ctrl, dmactrl, oldLevel, addr; struct graes_ring *curr_bd; struct graes_block *curr_frm, *last_frm; if ( !pDev->ready.head ){ return 0; } cnt=0; curr_frm = pDev->ready.head; curr_bd = pDev->ring; while( !curr_bd->frm ){ int i = 0, j; unsigned int kaddr = -1, iaddr = -1, oaddr = -1, daddr, naddr; /* Assign frame to descriptor */ curr_bd->frm = curr_frm; /* Prepare descriptor address. Three cases: * - GRAES core on same bus as CPU ==> no translation (Address used by CPU = address used by GRAES) * - GRAES core on remote bus, and payload address given as used by CPU ==> Translation needed * - GRAES core on remote bus, and payload address given as used by GRAES ==> no translation [ USER does custom translation] */ ctrl = GRAES_BD_EN; daddr = addr = graes_trans(pDev, curr_frm, curr_frm->payload); curr_bd->bd->u.d[i++] = addr; if (curr_frm->out) { ctrl |= GRAES_BD_OUT; oaddr = addr = graes_trans(pDev, curr_frm, curr_frm->out); curr_bd->bd->u.d[i++] = addr; } if (curr_frm->iv) { ctrl |= GRAES_BD_IV; iaddr = addr = graes_trans(pDev, curr_frm, curr_frm->iv); curr_bd->bd->u.d[i++] = addr; } if (curr_frm->key) { ctrl |= GRAES_BD_KEY; kaddr = addr = graes_trans(pDev, curr_frm, curr_frm->key); curr_bd->bd->u.d[i++] = addr; } 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 ){ /* Wrap around */ } ctrl |= ((curr_frm->length & 0x7ff) << 21); /* Apply user options/flags */ ctrl |= (curr_frm->flags & GRAES_FLAGS_MASK); /* Is this Frame going to be an interrupt Frame? */ if ( (--pDev->enable_cnt_curr) <= 0 ){ if ( pDev->config.enable_cnt == 0 ){ pDev->enable_cnt_curr = 0x3fffffff; }else{ pDev->enable_cnt_curr = pDev->config.enable_cnt; ctrl |= GRAES_BD_IE; } } /* Enable descriptor */ curr_bd->bd->ctrl = ctrl; #ifdef DEBUG printk(" add bd: 0x%08x @ 0x%08x [0x%08x",ctrl,curr_bd->bd, daddr); if(oaddr != -1) printk(",o:0x%08x",oaddr); if(iaddr != -1) printk(",i:0x%08x",iaddr); if(kaddr != -1) printk(",k:0x%08x",kaddr); printk("] ["); for (j = 0; j < 6; j++) { printk(" 0x%08x",((unsigned int *)curr_bd->bd)[j]); } printk("]\n"); #endif last_frm = curr_frm; curr_bd = curr_bd->next; cnt++; /* Get Next Frame from Ready Queue */ if ( curr_frm == pDev->ready.tail ){ /* Handled all in ready queue. */ curr_frm = NULL; break; } curr_frm = curr_frm->next; } /* Has frames have been scheduled? */ if ( cnt > 0 ){ /* Make last frame mark end of chain, probably pointless... */ last_frm->next = NULL; /* Insert scheduled packets into scheduled queue */ if ( !pDev->scheduled.head ){ /* empty scheduled queue */ pDev->scheduled.head = pDev->ready.head; pDev->scheduled.tail = last_frm; }else{ pDev->scheduled.tail->next = pDev->ready.head; pDev->scheduled.tail = last_frm; } /* Remove scheduled packets from ready queue */ pDev->ready.head = curr_frm; if ( !curr_frm ){ pDev->ready.tail = NULL; } /* Update TX ring posistion */ pDev->ring = curr_bd; if ( !ints_off ) { IRQ_GLOBAL_DISABLE(oldLevel); } /* Make hardware aware of the newly enabled descriptors */ dmactrl = READ_REG(&pDev->regs->dma_ctrl); dmactrl |= GRAES_DMA_CTRL_EN; pDev->regs->dma_ctrl = dmactrl; if ( !ints_off ) { IRQ_GLOBAL_ENABLE(oldLevel); } } return cnt; }
/* Moves as many frames in the ready queue (as there are free descriptors for) * to the scheduled queue. The free descriptors are then assigned one frame * each and enabled for transmission. * * Return Value * Returns number of frames moved from ready to scheduled queue */ static int grtm_schedule_ready(struct grtm_priv *pDev) { int cnt; unsigned int ctrl, dmactrl; struct grtm_ring *curr_bd; struct grtm_frame *curr_frm, *last_frm; if ( !pDev->ready.head ){ return 0; } cnt=0; curr_frm = pDev->ready.head; curr_bd = pDev->ring; while( !curr_bd->frm ){ /* Assign frame to descriptor */ curr_bd->frm = curr_frm; /* Prepare descriptor address. Three cases: * - GRTM core on same bus as CPU ==> no translation (Address used by CPU = address used by GRTM) * - GRTM core on remote bus, and payload address given as used by CPU ==> Translation needed * - GRTM core on remote bus, and payload address given as used by GRTM ==> no translation [ USER does custom translation] */ if ( curr_frm->flags & (GRTM_FLAGS_TRANSLATE|GRTM_FLAGS_TRANSLATE_AND_REMEMBER) ) { /* Do translation */ 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 != (unsigned int *)curr_bd->bd->address ) { /* Translation needed */ curr_frm->flags &= ~GRTM_FLAGS_TRANSLATE_AND_REMEMBER; curr_frm->flags |= GRTM_FLAGS_TRANSLATE; } else { /* No Trnaslation needed */ curr_frm->flags &= ~(GRTM_FLAGS_TRANSLATE|GRTM_FLAGS_TRANSLATE_AND_REMEMBER); } } } else { /* Custom translation or no translation needed */ curr_bd->bd->address = (unsigned int)curr_frm->payload; } ctrl = GRTM_BD_EN; if ( curr_bd->next == pDev->_ring ){ ctrl |= GRTM_BD_WR; /* Wrap around */ } /* Apply user options/flags */ ctrl |= (curr_frm->flags & GRTM_FLAGS_MASK); /* Is this Frame going to be an interrupt Frame? */ if ( (--pDev->enable_cnt_curr) <= 0 ){ if ( pDev->config.enable_cnt == 0 ){ pDev->enable_cnt_curr = 0x3fffffff; }else{ pDev->enable_cnt_curr = pDev->config.enable_cnt; ctrl |= GRTM_BD_IE; } } /* Enable descriptor */ curr_bd->bd->ctrl = ctrl; last_frm = curr_frm; curr_bd = curr_bd->next; cnt++; /* Get Next Frame from Ready Queue */ if ( curr_frm == pDev->ready.tail ){ /* Handled all in ready queue. */ curr_frm = NULL; break; } curr_frm = curr_frm->next; } /* Has frames have been scheduled? */ if ( cnt > 0 ){ /* Make last frame mark end of chain, probably pointless... */ last_frm->next = NULL; /* Insert scheduled packets into scheduled queue */ if ( !pDev->scheduled.head ){ /* empty scheduled queue */ pDev->scheduled.head = pDev->ready.head; pDev->scheduled.tail = last_frm; }else{ pDev->scheduled.tail->next = pDev->ready.head; pDev->scheduled.tail = last_frm; } /* Remove scheduled packets from ready queue */ pDev->ready.head = curr_frm; if ( !curr_frm ){ pDev->ready.tail = NULL; } /* Update TX ring posistion */ pDev->ring = curr_bd; /* Make hardware aware of the newly enabled descriptors */ dmactrl = READ_REG(&pDev->regs->dma_ctrl); dmactrl &= ~(GRTM_DMA_CTRL_TXRST | GRTM_DMA_CTRL_RST); dmactrl |= GRTM_DMA_CTRL_EN; pDev->regs->dma_ctrl = dmactrl; } return cnt; }