static uint32_t AllocUnitsVariantH(PPMdSubAllocatorVariantH *self,int num) { int index=self->Units2Index[num-1]; if(self->FreeList[index].next) return PointerToOffset(self,RemoveNode(self,index)); void *units=self->LowUnit; self->LowUnit+=I2B(self,index); if(self->LowUnit<=self->HighUnit) return PointerToOffset(self,units); self->LowUnit-=I2B(self,index); return _AllocUnits(self,index); }
static uint32_t AllocUnitsVariantI(PPMdSubAllocatorVariantI *self,int num) { int index=self->Units2Index[num-1]; if(AreBlocksAvailable(&self->BList[index])) return PointerToOffset(self,RemoveBlockAfter(&self->BList[index],self)); void *units=self->LowUnit; self->LowUnit+=I2B(self,index); if(self->LowUnit<=self->HighUnit) return PointerToOffset(self,units); self->LowUnit-=I2B(self,index); return _AllocUnits(self,index); }
static void SplitBlock(PPMdSubAllocatorBrimstone *self,void *pv,int oldindex,int newindex) { uint8_t *p=((uint8_t *)pv)+I2B(self,newindex); int diff=self->Index2Units[oldindex]-self->Index2Units[newindex]; int i=self->Units2Index[diff-1]; if(self->Index2Units[i]!=diff) { InsertNode(self,p,i-1); p+=I2B(self,i-1); diff-=self->Index2Units[i-1]; } InsertNode(self,p,self->Units2Index[diff-1]); }
static uint32_t _AllocUnits(PPMdSubAllocatorVariantI *self,int index) { if(self->GlueCount==0) { GlueFreeBlocks(self); if(AreBlocksAvailable(&self->BList[index])) return PointerToOffset(self,RemoveBlockAfter(&self->BList[index],self)); } for(int i=index+1;i<N_INDEXES;i++) { if(AreBlocksAvailable(&self->BList[i])) { void *units=RemoveBlockAfter(&self->BList[i],self); SplitBlock(self,units,i,index); return PointerToOffset(self,units); } } self->GlueCount--; int i=I2B(self,index); if(self->UnitsStart-self->pText>i) { self->UnitsStart-=i; return PointerToOffset(self,self->UnitsStart); } return 0; }
static uint32_t _AllocUnits(PPMdSubAllocatorVariantH *self,int index) { if(self->GlueCount==0) { self->GlueCount=255; GlueFreeBlocks(self); if(self->FreeList[index].next) return PointerToOffset(self,RemoveNode(self,index)); } for(int i=index+1;i<N_INDEXES;i++) { if(self->FreeList[i].next) { void *units=RemoveNode(self,i); SplitBlock(self,units,i,index); return PointerToOffset(self,units); } } self->GlueCount--; int i=I2B(self,index); if(self->UnitsStart-self->pText>i) { self->UnitsStart-=i; return PointerToOffset(self,self->UnitsStart); } return 0; }
static uint32_t AllocUnitsBrimstone(PPMdSubAllocatorBrimstone *self,int num) { int index=self->Units2Index[num-1]; if(self->FreeList[index].next) return PointerToOffset(self,RemoveNode(self,index)); void *units=self->LowUnit; self->LowUnit+=I2B(self,index); if(self->LowUnit<=self->HighUnit) return PointerToOffset(self,units); self->LowUnit-=I2B(self,index); for(int i=index+1;i<N_INDEXES;i++) { if(self->FreeList[i].next) { void *units=RemoveNode(self,i); SplitBlock(self,units,i,index); return PointerToOffset(self,units); } } return 0; }
static void SplitBlock(PPMdSubAllocatorVariantI *self,void *pv,int oldindex,int newindex) { uint8_t *p=((uint8_t *)pv)+I2B(self,newindex); int diff=self->Index2Units[oldindex]-self->Index2Units[newindex]; int i=self->Units2Index[diff-1]; if(self->Index2Units[i]!=diff) { int k=self->Index2Units[--i]; InsertBlockAfter(&self->BList[i],p,k,self); p+=k*UNIT_SIZE; diff-=k; } InsertBlockAfter(&self->BList[self->Units2Index[diff-1]],p,diff,self); }
static uint32_t ExpandUnitsBrimstone(PPMdSubAllocatorBrimstone *self,uint32_t oldoffs,int oldnum) { void *oldptr=OffsetToPointer(self,oldoffs); int oldindex=self->Units2Index[oldnum-1]; int newindex=self->Units2Index[oldnum]; if(oldindex==newindex) return oldoffs; uint32_t offs=AllocUnitsBrimstone(self,oldnum+1); if(offs) { // TODO: could copy less data memcpy(OffsetToPointer(self,offs),oldptr,I2B(self,oldindex)); InsertNode(self,oldptr,oldindex); } return offs; }
static uint32_t ShrinkUnitsBrimstone(PPMdSubAllocatorBrimstone *self,uint32_t oldoffs,int oldnum,int newnum) { void *oldptr=OffsetToPointer(self,oldoffs); int oldindex=self->Units2Index[oldnum-1]; int newindex=self->Units2Index[newnum-1]; if(oldindex==newindex) return oldoffs; if(self->FreeList[newindex].next) { void *ptr=RemoveNode(self,newindex); memcpy(ptr,oldptr,I2B(self,newindex)); InsertNode(self,oldptr,oldindex); return PointerToOffset(self,ptr); } else { SplitBlock(self,oldptr,oldindex,newindex); return oldoffs; } }
/* post receive buffers */ void dma_rxfill(dma_info_t *di) { void *p; uint rxin, rxout; uint ctrl; uint n; uint i; uint32 pa; uint rxbufsize; /* * Determine how many receive buffers we're lacking * from the full complement, allocate, initialize, * and post them, then update the chip rx lastdscr. */ rxin = di->rxin; rxout = di->rxout; rxbufsize = di->rxbufsize; n = di->nrxpost - NRXDACTIVE(rxin, rxout); DMA_TRACE(("%s: dma_rxfill: post %d\n", di->name, n)); for (i = 0; i < n; i++) { if ((p = PKTGET(di->drv, rxbufsize, FALSE)) == NULL) { DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n", di->name)); di->hnddma.rxnobuf++; break; } /* PR3263 & PR3387 & PR4642 war: rxh.len=0 means dma writes not complete */ *(uint32*)(OSL_UNCACHED(PKTDATA(di->drv, p))) = 0; pa = (uint32) DMA_MAP(di->dev, PKTDATA(di->drv, p), rxbufsize, DMA_RX, p); ASSERT(ISALIGNED(pa, 4)); /* save the free packet pointer */ #if 0 ASSERT(di->rxp[rxout] == NULL); #endif di->rxp[rxout] = p; /* paranoia */ ASSERT(R_SM(&di->rxd[rxout].addr) == 0); /* prep the descriptor control value */ ctrl = rxbufsize; if (rxout == (di->nrxd - 1)) ctrl |= CTRL_EOT; /* init the rx descriptor */ W_SM(&di->rxd[rxout].ctrl, BUS_SWAP32(ctrl)); W_SM(&di->rxd[rxout].addr, BUS_SWAP32(pa + di->dataoffset)); DMA_TRACE(("%s: dma_rxfill: ctrl %08x dataoffset: %08x\n", di->name, BUS_SWAP32(ctrl), BUS_SWAP32(pa + di->dataoffset))); rxout = NEXTRXD(rxout); } di->rxout = rxout; /* update the chip lastdscr pointer */ W_REG(&di->regs->rcvptr, I2B(rxout)); }
/* * Just like above except go through the extra effort of splitting * buffers that cross 4Kbyte boundaries into multiple tx descriptors. */ int dma_tx(dma_info_t *di, void *p0, uint32 coreflags) { void *p, *next; uchar *data; uint plen, len; uchar *page, *start, *end; uint txout; uint32 ctrl; uint32 pa; DMA_TRACE(("%s: dma_tx\n", di->name)); txout = di->txout; ctrl = 0; /* * Walk the chain of packet buffers * splitting those that cross 4 Kbyte boundaries * allocating and initializing transmit descriptor entries. */ for (p = p0; p; p = next) { data = PKTDATA(di->drv, p); plen = PKTLEN(di->drv, p); next = PKTNEXT(di->drv, p); /* PR988 - skip zero length buffers */ if (plen == 0) continue; for (page = (uchar*)PAGEBASE(data); page <= (uchar*)PAGEBASE(data + plen - 1); page += PAGESZ) { /* return nonzero if out of tx descriptors */ if (NEXTTXD(txout) == di->txin) goto outoftxd; start = (page == (uchar*)PAGEBASE(data))? data: page; end = (page == (uchar*)PAGEBASE(data + plen))? (data + plen): (page + PAGESZ); len = end - start; /* build the descriptor control value */ ctrl = len & CTRL_BC_MASK; /* PR3697: Descriptor flags are not ignored for descriptors where SOF is clear */ ctrl |= coreflags; if ((p == p0) && (start == data)) ctrl |= CTRL_SOF; if ((next == NULL) && (end == (data + plen))) ctrl |= (CTRL_IOC | CTRL_EOF); if (txout == (di->ntxd - 1)) ctrl |= CTRL_EOT; /* get physical address of buffer start */ pa = (uint32) DMA_MAP(di->dev, start, len, DMA_TX, p); /* init the tx descriptor */ W_SM(&di->txd[txout].ctrl, BUS_SWAP32(ctrl)); W_SM(&di->txd[txout].addr, BUS_SWAP32(pa + di->dataoffset)); ASSERT(di->txp[txout] == NULL); txout = NEXTTXD(txout); } } /* if last txd eof not set, fix it */ if (!(ctrl & CTRL_EOF)) W_SM(&di->txd[PREVTXD(txout)].ctrl, BUS_SWAP32(ctrl | CTRL_IOC | CTRL_EOF)); /* save the packet */ di->txp[di->txout] = p0; /* bump the tx descriptor index */ di->txout = txout; /* kick the chip */ W_REG(&di->regs->xmtptr, I2B(txout)); /* tx flow control */ di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1; return (0); outoftxd: DMA_ERROR(("%s: dma_tx: out of txds\n", di->name)); PKTFREE(di->drv, p0, TRUE); di->txavail = 0; di->hnddma.txnobuf++; return (-1); }