void shared_lb_put( IN shared_info_t *shared, IN struct lbfree *l, IN struct lbuf *lb ) { NdisAcquireSpinLock(&l->queue_lock); ASSERT(l->count <= l->total); ASSERT(lb->p == NULL); ASSERT(lb->link == NULL); ASSERT(lb->next == NULL); ASSERT(lb->l == l); lb->data = lb->tail = (uchar*)(uintptr)0xdeadbeef; lb->len = 0; lb->link = l->free; l->free = lb; l->count++; if ((uint)shared_lb_freecount(&shared->rxfree) > shared->rxflowHi) { if (shared->rxflowMode == RX_FLOW_CONTROL_WATERMARK && shared->rxflow == TRUE) { shared->rxflow = FALSE; ND_TRACE(("%s: rx flow OFF, free count = %d\n", __FUNCTION__, shared_lb_freecount(&shared->rxfree))); dhd_rx_flow(shared->dhd, FALSE); } } NdisReleaseSpinLock(&l->queue_lock); }
struct lbuf * shared_lb_get( IN shared_info_t *shared, IN struct lbfree *l ) { struct lbuf *lb; NdisAcquireSpinLock(&l->queue_lock); ASSERT(l->count <= l->total); if (lb = l->free) { l->free = lb->link; lb->link = lb->next = NULL; lb->data = lb->tail = lb->head; lb->priority = 0; lb->len = 0; l->count--; bzero(lb->pkttag, OSL_PKTTAG_SZ); } if ((uint)shared_lb_freecount(&shared->rxfree) < shared->rxflowLow) { if (shared->rxflowMode == RX_FLOW_CONTROL_WATERMARK && shared->rxflow == FALSE) { shared->rxflow = TRUE; ND_TRACE(("%s: rx flow ON, free count = %d\n", __FUNCTION__, shared_lb_freecount(&shared->rxfree))); dhd_rx_flow(shared->dhd, TRUE); } } NdisReleaseSpinLock(&l->queue_lock); return (lb); }
void shared_lb_free( IN shared_info_t *shared, IN struct lbfree *l, IN BOOLEAN shared_mem, IN BOOLEAN cached ) { uint i; int maxpages; ND_TRACE(("%s%d: shared_lb_free\n", shared->id, shared->unit)); ASSERT(l->count <= l->total); /* uncached not supported */ ASSERT(cached); /* free all buffer memory pages */ for (i = 0; i < l->npages; i++) { if (!shared_mem) MFREE(shared->osh, l->pages[i].va, PAGE_SIZE); else { NdisMFreeSharedMemory(shared->adapterhandle, PAGE_SIZE, cached, (PVOID)l->pages[i].va, l->pages[i].pa); } } /* free the page list */ if (l->pages) { maxpages = (l->total * l->size) / PAGE_SIZE; MFREE(shared->osh, (uchar *) l->pages, maxpages * sizeof(page_t)); } l->free = NULL; l->total = 0; l->count = 0; l->pages = NULL; l->npages = 0; NdisFreeSpinLock(&l->queue_lock); }
void target_init(void) { #if defined(NAND_BOOT_INCLUDE) ASSERT(NAND_MTD_PARTITION_NUM == num_parts); unsigned offset; unsigned total_num_of_blocks; unsigned blocks_per_megabytes; unsigned next_ptr_start_adr = 0; int ret, i; struct flash_info *flash_info; bool start_addr_changed = false; unsigned long long nMTDReserved_Num=0; // total number of MTD Reserved Area TNFTL_MTDBadBlkInfo MTDBadBlkInfo[num_parts]; ///////////////////////////////////////////////////////////////////////////////////////////// unsigned long long nROAreaSize, nPartitionSize = 0; unsigned long int nBlockSize, nBlockSize_MB; unsigned int nDevPBpV, nDevBBpZ, nDevBBpV, nRervRate; unsigned int j, nUserDataArea = 0; struct ptable sPartition_List; memset( MTDBadBlkInfo, 0, sizeof(TNFTL_MTDBadBlkInfo) * num_parts ); edi_init(); #endif dprintf(ALWAYS, "target_init()\n"); keys_init(); keypad_init(); #if defined(BOOTSD_INCLUDE) if (target_is_emmc_boot()) { emmc_boot_main(); return ; } #endif #if defined(NAND_BOOT_INCLUDE) #if defined(TNFTL_V8_INCLUDE) if (check_fwdn_mode()) { fwdn_start(); return; } flash_boot_main(); #else if ( ( flash_get_ptable() == NULL ) ) { ptable_init(&flash_ptable); flash_set_partnum( num_parts ); flash_init(); flash_info = flash_get_info(); ASSERT(flash_info); if ( (flash_info->num_blocks) && (!flash_check_table()) ) { memcpy( sPartition_List.parts, board_part_list, sizeof( struct ptentry ) * num_parts ); flash_get_DevPBpV( &nDevPBpV, &nDevBBpZ, &nMTDReserved_Num ); nROAreaSize = (unsigned long long)( nMTDReserved_Num << 20 ); nBlockSize = flash_info->page_size << flash_info->ShiftPpB; // Set Block Size ( Byte Size ) //nROAreaSize = flash_info->num_blocks * nBlockSize; // Set Total ROArea Size ( Byte Size ) nBlockSize_MB = nBlockSize / ( 1 << 20 ); if( nBlockSize_MB > 1 ) // If Block is over the 1MB. Block must aligned. { // ex) Block Size 2MB, If Partition Size is 3MB. Partition Block Number must be 2. not 1. if( nBlockSize_MB == 2 ) // If Block Size 2MB. { for( i = 0; i < num_parts; i++ ) { if( sPartition_List.parts[i].length & 0x01 ) sPartition_List.parts[i].length++; } } else if ( nBlockSize_MB == 4 ) // If Block Size 4MB { unsigned int nDiff_Val; for( i = 0; i < num_parts; i++ ) { nDiff_Val = sPartition_List.parts[i].length & 0x03; if( nDiff_Val ) sPartition_List.parts[i].length += ( 4 - nDiff_Val ); } } } nMTDReserved_Num = ( nMTDReserved_Num << 20 ) / nBlockSize; nDevBBpV = ( nDevPBpV / 1024 ) * nDevBBpZ; nRervRate = ( nMTDReserved_Num * 100 ) / nDevPBpV; nDevBBpV = ( nDevBBpV * nRervRate ) / 100; if( nRervRate != 0 ) nRervRate = ( 100 / nRervRate ); nMTDReserved_Num = nRervRate + nDevBBpV; // Setup ROArea Reserved Block if(nMTDReserved_Num == 0) nMTDReserved_Num = 2; else if ( nMTDReserved_Num & 0x01 ) nMTDReserved_Num++; if( flash_info->ExtInterrupt == TRUE ) nMTDReserved_Num = nMTDReserved_Num << 1; for( i = 0; i < num_parts; i++ ) { if( sPartition_List.parts[i].length != VARIABLE_LENGTH ) { sPartition_List.parts[i].length = (unsigned long long)(sPartition_List.parts[i].length << 20); // Convert Length Unit. MByte -> Byte nPartitionSize += sPartition_List.parts[i].length; //ND_TRACE("sPartition_List.parts[%d].length:%lld [nPartitionSize:%d]\n", i, sPartition_List.parts[i].length, nPartitionSize); } else { nUserDataArea = i; } } if( nUserDataArea != 0 ) { sPartition_List.parts[nUserDataArea].length = nROAreaSize - nPartitionSize; // Calculate UserDataArea Size ( include Rerv Block ) //ND_TRACE("sPartition_List.parts[5].length:%lld [nPartitionSize:%d]\n", i, sPartition_List.parts[5].length, nPartitionSize); //sPartition_List.parts[nUserDataArea].length -= (nMTDReserved_Num * nBlockSize ); // UserDataArea Size. Reverved Block Removed } i = 1; sPartition_List.parts[0].length /= nBlockSize; // Partition 0 Length ( Block Unit ) MTDBadBlkInfo[0].PartBlkNum = sPartition_List.parts[0].length; // Set Block Number Each Partition do { sPartition_List.parts[i].length /= nBlockSize; // Partition i Length ( Block Unit ) sPartition_List.parts[i].start = sPartition_List.parts[i-1].start + sPartition_List.parts[i-1].length; MTDBadBlkInfo[i].PartBlkNum = sPartition_List.parts[i].length; // Set Block Number Each Partition ++i; } while( i < num_parts ); flash_set_rervnum( nMTDReserved_Num ); // Set Reserved Block Number flash_set_badblkinfo( MTDBadBlkInfo ); // Set Bad Block Table Info. About Block Number Each Partition for( i = 0; i < num_parts; i++ ) { ptable_add(&flash_ptable, sPartition_List.parts[i].name, flash_info->offset + sPartition_List.parts[i].start, sPartition_List.parts[i].length, sPartition_List.parts[i].flags); } ND_TRACE("\n-------------- [ Partition Table ] --------------\n"); for( i = 0; i < num_parts; i++ ) { ND_TRACE(" [Part %2d.%9s] [Start:%4d] [Length:%4d]\n", i, sPartition_List.parts[i].name ,sPartition_List.parts[i].start + flash_info->offset, sPartition_List.parts[i].length ); } ND_TRACE("-------------------------------------------------\n"); dprintf(INFO, "[NAND ] [Maker:0x%02x ][Device:0x%02x][Page_size:%d]\n", flash_info->vendor, flash_info->device, flash_info->page_size); dprintf(INFO, " [Spare_Size:%d][Block_Size:%d][MTD_TotalBlock:%d]\n", flash_info->spare_size, flash_info->block_size, flash_info->num_blocks); //dprintf(INFO, " [Spare_Size:%d][Block_Size:%d][MTD_Block:%d][Rerv_Block:%d]\n", // flash_info->spare_size, flash_info->block_size, flash_info->num_blocks - (U32)nMTDReserved_Num, (U32)nMTDReserved_Num); //ptable_dump(&flash_ptable); flash_set_ptable(&flash_ptable); ret = flash_set_badblktable(); if( ret != SUCCESS ) { dprintf(INFO, " !!! Fail Create Bad Block Table. [func:%s] [line:%d] !!! \n", __func__, __LINE__ ); ASSERT(-1); } flash_set_tablestatus(TRUE); } } #endif #endif }
void target_init(void) { ASSERT(NAND_MTD_PARTITION_NUM == num_parts); unsigned offset; unsigned total_num_of_blocks; unsigned blocks_per_megabytes; unsigned next_ptr_start_adr = 0; int ret, i; struct flash_info *flash_info; bool start_addr_changed = false; unsigned int nMTDReserved_Num=0; // total number of MTD Reserved Area TNFTL_MTDBadBlkInfo MTDBadBlkInfo[num_parts]; ///////////////////////////////////////////////////////////////////////////////////////////// unsigned int nROAreaSize, nPartitionSize = 0; unsigned int nBlockSize, nBlockSize_MB; unsigned int nDevPBpV, nDevBBpZ, nDevBBpV, nRervRate; unsigned int j, nUserDataArea = 0; struct ptable sPartition_List; memset( MTDBadBlkInfo, 0, sizeof(TNFTL_MTDBadBlkInfo) * num_parts ); dprintf(ALWAYS, "target_init()\n"); #if _EMMC_BOOT_TCC PARTITION PartitionArr[50]; unsigned int nPartitionCnt = 0; #endif #ifdef TRIFLASH_INCLUDE ioctl_diskinfo_t disk_info; #endif #if (!ENABLE_NANDWRITE) #ifdef BOARD_TCC930X_STB_DEMO #else keys_init(); keypad_init(); #endif #endif if (target_is_emmc_boot()) { #if _EMMC_BOOT_TCC dprintf(INFO, "target_init() emmc_boot\n"); ptable_init(&flash_ptable); //SDMMC init //MCC DISK_Ioctl(DISK_DEVICE_TRIFLASH, DEV_INITIALIZE, NULL ); //get flash info? //MCC DISK_Ioctl(DISK_DEVICE_TRIFLASH, DEV_GET_DISKINFO, (void *)&disk_info); dprintf(INFO, "disk info: head: %d cylinder: %d sector : %d sector size: %d Total_sectors: %d \n",disk_info.head,disk_info.cylinder,disk_info.sector,disk_info.sector_size,disk_info.Total_sectors); //ptabel init //MCC // offset = flash_info->offset; offset = 0; //fixme // total_num_of_blocks = flash_info->num_blocks; total_num_of_blocks=10000000; // fixme memset(&PartitionArr, 0, sizeof(PARTITION) * 50); nPartitionCnt = GetLocalPartition(0, PartitionArr); for(i=0; i<nPartitionCnt; i++) PrintPartitionInfo(&PartitionArr[i], i); /* convert partition size to block unit */ //512byte ? blocks_per_megabytes = 1024*1024 / (disk_info.sector_size); ASSERT(blocks_per_megabytes); for (i = 0; i < num_parts; i++) { struct ptentry *ptn = &board_part_list[i]; if (ptn->length != VARIABLE_LENGTH) ptn->length *= blocks_per_megabytes; } for (i = 0; i < num_parts; i++) { struct ptentry *ptn = &board_part_list[i]; unsigned len = ptn->length; if (ptn->start != DIFF_START_ADDR) { if(i==2) { ptn->start = PartitionArr[1].start; } else { ptn->start *= blocks_per_megabytes; } } if (len == VARIABLE_LENGTH) { start_addr_changed = true; unsigned length_for_prt = ptn->start; unsigned j; for (j = i+1; j < num_parts; j++) { struct ptentry *temp_ptn = &board_part_list[j]; ASSERT(temp_ptn->length != VARIABLE_LENGTH); length_for_prt += temp_ptn->length; } len = total_num_of_blocks - length_for_prt; ASSERT(len >= 0); next_ptr_start_adr = ptn->start + len; } if((ptn->start == DIFF_START_ADDR) && (start_addr_changed)) { ASSERT(next_ptr_start_adr); ptn->start = next_ptr_start_adr; next_ptr_start_adr = ptn->start + ptn->length; } ptable_add(&flash_ptable, ptn->name, offset + ptn->start, len, ptn->flags); } ptable_dump(&flash_ptable); flash_set_ptable(&flash_ptable); #endif return; } if (flash_get_ptable() == NULL) { ptable_init(&flash_ptable); flash_set_partnum( num_parts ); flash_init(); flash_info = flash_get_info(); ASSERT(flash_info); if ( (flash_info->num_blocks) && (!flash_check_table()) ) { memcpy( sPartition_List.parts, board_part_list, sizeof( struct ptentry ) * num_parts ); nBlockSize = flash_info->page_size << flash_info->ShiftPpB; // Set Block Size ( Byte Size ) nROAreaSize = flash_info->num_blocks * nBlockSize; // Set Total ROArea Size ( Byte Size ) nBlockSize_MB = nBlockSize / ( 1 << 20 ); if( nBlockSize_MB > 1 ) // If Block is over the 1MB. Block must aligned. { // ex) Block Size 2MB, If Partition Size is 3MB. Partition Block Number must be 2. not 1. if( nBlockSize_MB == 2 ) // If Block Size 2MB. { for( i = 0; i < num_parts; i++ ) { if( sPartition_List.parts[i].length & 0x01 ) sPartition_List.parts[i].length++; } } else if ( nBlockSize_MB == 4 ) // If Block Size 4MB { unsigned int nDiff_Val; for( i = 0; i < num_parts; i++ ) { nDiff_Val = sPartition_List.parts[i].length & 0x03; if( nDiff_Val ) sPartition_List.parts[i].length += ( 4 - nDiff_Val ); } } } flash_get_DevPBpV( &nDevPBpV, &nDevBBpZ, &nMTDReserved_Num ); nMTDReserved_Num = ( nMTDReserved_Num << 20 ) / nBlockSize; nDevBBpV = ( nDevPBpV / 1024 ) * nDevBBpZ; nRervRate = ( nMTDReserved_Num * 100 ) / nDevPBpV; nDevBBpV = ( nDevBBpV * nRervRate ) / 100; nRervRate = ( 100 / nRervRate ); nMTDReserved_Num = nRervRate + nDevBBpV; // Setup ROArea Reserved Block if( nMTDReserved_Num & 0x01 ) nMTDReserved_Num++; if( flash_info->ExtInterrupt == TRUE ) nMTDReserved_Num = nMTDReserved_Num << 1; for( i = 0; i < num_parts; i++ ) { if( sPartition_List.parts[i].length != VARIABLE_LENGTH ) { sPartition_List.parts[i].length = sPartition_List.parts[i].length << 20; // Convert Length Unit. MByte -> Byte nPartitionSize += sPartition_List.parts[i].length; } else { nUserDataArea = i; } } sPartition_List.parts[nUserDataArea].length = nROAreaSize - nPartitionSize; // Calculate UserDataArea Size ( include Rerv Block ) sPartition_List.parts[nUserDataArea].length -= (nMTDReserved_Num * nBlockSize ); // UserDataArea Size. Reverved Block Removed i = 1; sPartition_List.parts[0].length /= nBlockSize; // Partition 0 Length ( Block Unit ) MTDBadBlkInfo[0].PartBlkNum = sPartition_List.parts[0].length; // Set Block Number Each Partition do { sPartition_List.parts[i].length /= nBlockSize; // Partition i Length ( Block Unit ) sPartition_List.parts[i].start = sPartition_List.parts[i-1].start + sPartition_List.parts[i-1].length; MTDBadBlkInfo[i].PartBlkNum = sPartition_List.parts[i].length; // Set Block Number Each Partition ++i; } while( i < num_parts ); flash_set_rervnum( nMTDReserved_Num ); // Set Reserved Block Number flash_set_badblkinfo( MTDBadBlkInfo ); // Set Bad Block Table Info. About Block Number Each Partition for( i = 0; i < num_parts; i++ ) { ptable_add(&flash_ptable, sPartition_List.parts[i].name, flash_info->offset + sPartition_List.parts[i].start, sPartition_List.parts[i].length, sPartition_List.parts[i].flags); } ND_TRACE("\n-------------- [ Partition Table ] --------------\n"); for( i = 0; i < num_parts; i++ ) { ND_TRACE(" [Part %2d.%9s] [Start:%4d] [Length:%4d]\n", i, sPartition_List.parts[i].name ,sPartition_List.parts[i].start + flash_info->offset, sPartition_List.parts[i].length ); } ND_TRACE("-------------------------------------------------\n"); dprintf(INFO, "[NAND ] [Maker:0x%02x ][Device:0x%02x][Page_size:%d]\n", flash_info->vendor, flash_info->device, flash_info->page_size); dprintf(INFO, " [Spare_Size:%d][Block_Size:%d][MTD_Block:%d][Rerv_Block:%d]\n", flash_info->spare_size, flash_info->block_size, flash_info->num_blocks - (U32)nMTDReserved_Num, (U32)nMTDReserved_Num); //ptable_dump(&flash_ptable); flash_set_ptable(&flash_ptable); ret = flash_set_badblktable(); if( ret != SUCCESS ) { dprintf(INFO, " !!! Fail Create Bad Block Table. [func:%s] [line:%d] !!! \n", __func__, __LINE__ ); ASSERT(-1); } flash_set_tablestatus(TRUE); } } }
NDIS_STATUS shared_lb_alloc( IN shared_info_t *shared, IN struct lbfree *l, IN uint total, IN BOOLEAN shared_mem, IN BOOLEAN cached, IN BOOLEAN piomode, IN BOOLEAN data_buf ) { NDIS_STATUS status; page_t page; int maxpages; int i; uint ipp, lbdatasz; /* uncached not supported */ ASSERT(cached); if (data_buf) total = ROUNDUP(total, BPP); else /* add one if LBPP is not page aligned */ total = ROUNDUP(total, (LBPP + ((PAGE_SIZE % sizeof(struct lbuf)) ? 1 : 0))); ND_TRACE(("%s%d: shared_lb_alloc: total %d\n", shared->id, shared->unit, total)); l->free = NULL; l->total = total; l->count = 0; l->size = data_buf ? LBUFSZ : sizeof(struct lbuf); l->pages = NULL; l->npages = 0; l->headroom = 0; NdisAllocateSpinLock(&l->queue_lock); maxpages = (l->total * l->size) / PAGE_SIZE; /* allocate page list memory */ if ((l->pages = (page_t*) MALLOC(shared->osh, maxpages * sizeof(page_t))) == NULL) goto enomem; bzero(l->pages, maxpages * sizeof(page_t)); /* set item per page number and data size */ if (data_buf) { ipp = BPP; lbdatasz = LBDATASZ; } else { ipp = LBPP; lbdatasz = 0; } /* fill the freelist */ for (i = 0; i < maxpages; i++) { status = shared_allocpage(shared, shared_mem, cached, &page); if (NDIS_ERROR(status)) goto enomem; status = shared_lb_addpage(shared, l, piomode, &page, ipp, lbdatasz); if (NDIS_ERROR(status)) goto enomem; } return (NDIS_STATUS_SUCCESS); enomem: ND_ERROR(("%s%d: shared_lb_alloc: out of memory, malloced %d bytes\n", shared->id, shared->unit, MALLOCED(shared->osh))); shared_lb_free(shared, l, shared_mem, TRUE); return (NDIS_STATUS_RESOURCES); }