/** * @brief Finds space for a map of the given size in the atlas. * @details This methods searches for a space to store a region of the given * size in the atlas. tile_width and tile_height should be already in tile * space. They can be converted using ShadowAtlas::get_required_tiles. * * If no region is found, or an invalid size is passed, an integer vector with * all components set to -1 is returned. * * If a region is found, an integer vector with the given layout is returned: * x: x- Start of the region * y: y- Start of the region * z: width of the region * w: height of the region * * The layout is in tile space, and can get converted to uv space using * ShadowAtlas::region_to_uv. * * @param tile_width Width of the region in tile space * @param tile_height Height of the region in tile space * * @return Region, see description, or -1 when no region is found. */ LVecBase4i ShadowAtlas::find_and_reserve_region(size_t tile_width, size_t tile_height) { // Check for empty region if (tile_width < 1 || tile_height < 1) { shadowatlas_cat.error() << "Called find_and_reserve_region with null-region!" << endl; return LVecBase4i(-1); } // Check for region bigger than the shadow atlas if (tile_width > _num_tiles || tile_height > _num_tiles) { shadowatlas_cat.error() << "Requested region exceeds shadow atlas size!" << endl; return LVecBase4i(-1); } // Iterate over every possible region and check if its still free for (size_t x = 0; x <= _num_tiles - tile_width; ++x) { for (size_t y = 0; y <= _num_tiles - tile_height; ++y) { if (region_is_free(x, y, tile_width, tile_height)) { // Found free region, now reserve it reserve_region(x, y, tile_width, tile_height); return LVecBase4i(x, y, tile_width, tile_height); } } } // When we reached this part, we couldn't find a free region, so the atlas // seems to be full. shadowatlas_cat.error() << "Failed to find a free region of size " << tile_width << " x " << tile_height << "!" << endl; return LVecBase4i(-1); }
/* * This function is called from mem_init() to reserve the pages needed for * ST-RAM management. */ void __init atari_stram_reserve_pages(unsigned long start_mem) { #ifdef CONFIG_STRAM_SWAP /* if max_swap_size is negative (i.e. no stram_swap= option given), * determine at run time whether to use ST-RAM swapping */ if (max_swap_size < 0) /* Use swapping if ST-RAM doesn't make up more than MAX_STRAM_FRACTION * of total memory. In that case, the max. size is set to 16 MB, * because ST-RAM can never be bigger than that. * Also, never use swapping on a Hades, there's no separate ST-RAM in * that machine. */ max_swap_size = (!MACH_IS_HADES && (N_PAGES(stram_end-stram_start)*MAX_STRAM_FRACTION_DENOM <= max_mapnr*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0; DPRINTK( "atari_stram_reserve_pages: max_swap_size = %d\n", max_swap_size ); #endif /* always reserve first page of ST-RAM, the first 2 kB are * supervisor-only! */ set_bit( PG_reserved, &mem_map[MAP_NR(stram_start)].flags ); #ifdef CONFIG_STRAM_SWAP if (!max_swap_size) { fallback: #endif DPRINTK( "atari_stram_reserve_pages: swapping disabled\n" ); if (!kernel_in_stram) { /* Reserve all pages that have been marked by pre-mem_init * stram_alloc() (e.g. for the screen memory). */ reserve_region( rsvd_stram_beg, rsvd_stram_end ); DPRINTK( "atari_stram_reserve_pages: reseverved %08lx-%08lx\n", rsvd_stram_beg, rsvd_stram_end ); } /* else (kernel in ST-RAM): nothing to do, ST-RAM buffers are * kernel data */ #ifdef CONFIG_STRAM_SWAP } else { unsigned long swap_data; BLOCK *p; /* determine first page to use as swap: * if the kernel is in TT-RAM, this is the first page of (usable) * ST-RAM; else if there were already some allocations (probable...), * use the lowest address of these (the list is sorted by address!); * otherwise just use the end of kernel data (= start_mem) */ swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : alloc_list ? alloc_list->start : start_mem; /* decrement by one page, rest of kernel assumes that first swap page * is always reserved and maybe doesn't handle SWP_ENTRY == 0 * correctly */ swap_start -= PAGE_SIZE; swap_end = stram_end; if (swap_end-swap_start > max_swap_size) swap_end = swap_start + max_swap_size; DPRINTK( "atari_stram_reserve_pages: swapping enabled; " "swap=%08lx-%08lx\n", swap_start, swap_end ); /* reserve some amount of memory for maintainance of * swapping itself: 1 page for the lockmap, and one page * for each 2048 (PAGE_SIZE/2) swap pages. (2 bytes for * each page) */ swap_data = start_mem; start_mem += (((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1) >> (PAGE_SHIFT-1)) + 1) << PAGE_SHIFT; /* correct swap_start if necessary */ if (swap_start == swap_data) swap_start = start_mem; if (!swap_init( start_mem, swap_data )) { printk( KERN_ERR "ST-RAM swap space initialization failed\n" ); max_swap_size = 0; goto fallback; } /* reserve region for swapping meta-data */ reserve_region( swap_data, start_mem ); /* reserve swapping area itself */ reserve_region( swap_start+PAGE_SIZE, swap_end ); /* Formerly static areas have been included in the swap area. */ for( p = alloc_list; p; p = p->next ) { if (p->flags & BLOCK_STATIC) p->flags = (p->flags & ~BLOCK_STATIC) | BLOCK_INSWAP; } /* * If the whole ST-RAM is used for swapping, there are no allocatable * dma pages left. But unfortunately, some shared parts of the kernel * (particularily the SCSI mid-level) call __get_dma_pages() * unconditionally :-( These calls then fail, and scsi.c even doesn't * check for NULL return values and just crashes. The quick fix for * this (instead of doing much clean up work in the SCSI code) is to * pretend all pages are DMA-able by setting mach_max_dma_address to * ULONG_MAX. This doesn't change any functionality so far, since * get_dma_pages() shouldn't be used on Atari anyway anymore (better * use atari_stram_alloc()), and the Atari SCSI drivers don't need DMA * memory. But unfortunately there's now no kind of warning (even not * a NULL return value) if you use get_dma_pages() nevertheless :-( * You just will get non-DMA-able memory... */ mach_max_dma_address = 0xffffffff; /* * Ok, num_physpages needs not be really exact, but it's better to * subtract the pages set aside for swapping. */ num_physpages -= SWAP_NR(swap_end)-1; } #endif mem_init_done = 1; }