コード例 #1
0
ファイル: hal_flash.c プロジェクト: tecbea/larva
int
flash_erase_sector(uint32_t sector_address)
{
    int next_sector_id;
    int sector_id;
    int area_id;

    flash_native_ensure_file_open();

    area_id = find_area(sector_address);
    if (area_id == -1) {
        return -1;
    }

    sector_id = flash_area_descs[area_id].fad_sector_id;
    while (1) {
        flash_native_erase(sector_address,
                           flash_area_descs[area_id].fad_length);

        area_id++;
        if (area_id >= FLASH_NUM_AREAS) {
            break;
        }

        next_sector_id = flash_area_descs[area_id].fad_sector_id;
        if (next_sector_id != sector_id) {
            break;
        }

        sector_id = next_sector_id;
    }

    return 0;
}
コード例 #2
0
ファイル: TimeSource.cpp プロジェクト: mylegacy/haiku
/* explicit */
BTimeSource::BTimeSource(media_node_id id) :
	BMediaNode("This one is never called"),
	fStarted(false),
	fArea(-1),
	fBuf(NULL),
	fSlaveNodes(NULL),
	fIsRealtime(false)
{
	CALLED();
	AddNodeKind(B_TIME_SOURCE);
	ASSERT(id > 0);
//	printf("###### explicit BTimeSource::BTimeSource() id %ld, name %s\n", id, Name());

	// This constructor is only called by the derived BPrivate::media::TimeSourceObject objects
	// We create a clone of the communication area
	char name[32];
	area_id area;
	sprintf(name, "__timesource_buf_%" B_PRId32, id);
	area = find_area(name);
	if (area <= 0) {
		ERROR("BTimeSource::BTimeSource couldn't find area, node %" B_PRId32
			"\n", id);
		return;
	}
	sprintf(name, "__cloned_timesource_buf_%" B_PRId32, id);
	fArea = clone_area(name, reinterpret_cast<void **>(const_cast<BPrivate::media::TimeSourceTransmit **>(&fBuf)), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area);
	if (fArea <= 0) {
		ERROR("BTimeSource::BTimeSource couldn't clone area, node %" B_PRId32
			"\n", id);
		return;
	}
}
コード例 #3
0
void *gw_check_realloc(void *p, size_t size, const char *filename,
                       long lineno, const char *function)
{
    struct area *area;

    if (p == NULL)
        return gw_check_malloc(size, filename, lineno, function);

    gw_assert(initialized);
    gw_assert(size > 0);

    lock();
    area = find_area(p);
    if (!area) {
        unlock();
        panic(0, "Realloc called on non-allocated area");
    }

    if (size == area->area_size) {
        /* No changes */
    } else if (size <= area->max_size) {
        change_total_size(size - area->area_size);
        area->area_size = size;
        endmark(p, size);
    } else if (size > area->max_size) {
        /* The current block is not large enough for the reallocation.
         * We will allocate a new block, copy the data over, and free
         * the old block.  We round the size up to a power of two,
         * to prevent frequent reallocations. */
        struct area *new_area;
        size_t new_size;
        unsigned char *new_p;

        new_size = round_pow2(size + 2 * MARKER_SIZE);
        new_p = malloc(new_size);
        new_size -= 2 * MARKER_SIZE;
        new_p += MARKER_SIZE;
        memcpy(new_p, p, area->area_size);
        fill(new_p + area->area_size, size - area->area_size,
             NEW_AREA_PATTERN);
        new_area = record_allocation(new_p, size,
                                     area->allocator.filename,
                                     area->allocator.lineno,
                                     area->allocator.function);
        new_area->max_size = new_size;
        free_area(area);

        p = new_p;
        area = new_area;
    }

    area->reallocator.filename = filename;
    area->reallocator.lineno = lineno;
    area->reallocator.function = function;
    unlock();
    return p;
}
コード例 #4
0
int gw_check_is_allocated(void *p)
{
    struct area *area;

    lock();
    area = find_area(p);
    unlock();
    return area != NULL;
}
コード例 #5
0
ファイル: bspgetworkarea.c プロジェクト: RTEMS/rtems
static size_t remove_reserved_memory(
  const void *fdt,
  Heap_Area *areas,
  size_t area_count
)
{
  int node;

  node = fdt_path_offset_namelen(
    fdt,
    reserved_memory_path,
    (int) sizeof(reserved_memory_path) - 1
  );

  if (node >= 0) {
    node = fdt_first_subnode(fdt, node);

    while (node >= 0) {
      int len;
      const void *val;
      uintptr_t area_begin;
      uintptr_t area_end;
      uintptr_t hole_begin;
      uintptr_t hole_end;
      Heap_Area *area;

      val = fdt_getprop(fdt, node, "reg", &len);
      if (len == 8) {
        hole_begin = fdt32_to_cpu(((fdt32_t *) val)[0]);
        hole_end = hole_begin + fdt32_to_cpu(((fdt32_t *) val)[1]);
      } else {
        rtems_panic("unexpected reserved memory area");
      }

      area = find_area(areas, area_count, hole_begin);
      area_begin = (uintptr_t) area->begin;
      area_end = area_begin + (uintptr_t) area->size;
      area->size = hole_begin - area_begin;

      if (hole_end <= area_end) {
        if (area_count >= AREA_COUNT_MAX) {
          rtems_panic("too many reserved memory areas");
        }

        area = &areas[area_count];
        ++area_count;
        area->begin = (void *) hole_end;
        area->size = area_end - hole_end;
      }

      node = fdt_next_subnode(fdt, node);
    }
  }

  return area_count;
}
コード例 #6
0
word_t
get_word_at (struct pdp10_memory *memory, int address)
{
  struct pdp10_area *area;

  area = find_area (memory, address);
  if (area == NULL)
    return -1;

  return getword (area, address);
}
コード例 #7
0
ファイル: shm.c プロジェクト: Kiddinglife/geco-game-engine
APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
                                         apr_pool_t *pool)
{
    area_id deleteme = find_area(filename);
    
    if (deleteme == B_NAME_NOT_FOUND)
        return APR_EINVAL;

    delete_area(deleteme);
    return APR_SUCCESS;
}
コード例 #8
0
static int
native_flash_erase_sector(uint32_t sector_address)
{
    int area_id;
    uint32_t len;

    flash_native_ensure_file_open();

    area_id = find_area(sector_address);
    if (area_id == -1) {
        return -1;
    }
    len = flash_sector_len(area_id);
    flash_native_erase(sector_address, len);
    return 0;
}
コード例 #9
0
long gw_check_area_size(void *p)
{
    struct area *area;
    size_t size;

    lock();
    area = find_area(p);
    if (!area) {
        unlock();
        warning(0, "Area_size called on non-allocated area %p", p);
        return -1;
    }
    size = area->area_size;
    unlock();
    return size;
}
コード例 #10
0
void gw_check_free(void *p, const char *filename, long lineno,
                   const char *function)
{
    struct area *area;
    gw_assert(initialized);

    if (p == NULL)
        return;

    lock();
    area = find_area(p);
    if (!area) {
        unlock();
        panic(0, "Free called on non-allocated area");
    }

    free_area(area);
    unlock();
}
コード例 #11
0
ファイル: shm.c プロジェクト: Kiddinglife/geco-game-engine
APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m,
                                         const char *filename,
                                         apr_pool_t *pool)
{
    area_info ai;
    thread_info ti;
    apr_shm_t *new_m;
    area_id deleteme = find_area(filename);

    if (deleteme == B_NAME_NOT_FOUND)
        return APR_EINVAL;

    new_m = (apr_shm_t*)apr_palloc(pool, sizeof(apr_shm_t*));
    if (new_m == NULL)
        return APR_ENOMEM;
    new_m->pool = pool;

    get_area_info(deleteme, &ai);
    get_thread_info(find_thread(NULL), &ti);

    if (ti.team != ai.team) {
        area_id narea;
        
        narea = clone_area(ai.name, &(ai.address), B_CLONE_ADDRESS,
                           B_READ_AREA|B_WRITE_AREA, ai.area);

        if (narea < B_OK)
            return narea;
            
        get_area_info(narea, &ai);
        new_m->aid = narea;
        new_m->memblock = ai.address;
        new_m->ptr = (void*)ai.address;
        new_m->avail = ai.size;
        new_m->reqsize = ai.size;
    }

    (*m) = new_m;
    
    return APR_SUCCESS;
}
コード例 #12
0
int
set_address (struct pdp10_memory *memory, int address)
{
  struct pdp10_area *area;

  if (address == -1)
    {
      memory->current_address = -1;
      memory->current_area = NULL;
      return 0;
    }

  area = find_area (memory, address);
  if (area == NULL)
    return -1;

  memory->current_address = address;
  memory->current_area = area;

  return 0;
}
コード例 #13
0
ファイル: support.c プロジェクト: BALDELab/incubator-hawq
void
beos_backend_startup(void)
{
	char		nom[50];
	char		nvnom[50];
	area_info	inf;
	int32		cook = 0;

	/* Perform the remapping process */

	/* Loop in all our team areas */
	while (get_next_area_info(0, &cook, &inf) == B_OK)
	{
		strcpy(nom, inf.name);
		strcpy(nvnom, inf.name);
		nom[9] = 0;
		nvnom[5] = 'i';
		/* Is it a SYS V area ? */
		if (!strcmp(nom, "SYSV_IPC_"))
		{
			void	   *area_address;
			area_id		area_postmaster;

			/* Get the area address */
			area_address = inf.address;
			/* Destroy the bad area */
			delete_area(inf.area);
			/* Find the postmaster area */
			area_postmaster = find_area(inf.name);
			/* Compute new area name */
			sprintf(nvnom, "SYSV_IPC %d", area_postmaster);
			/* Clone it at the exact same address */
			clone_area(nvnom, &area_address, B_CLONE_ADDRESS, B_READ_AREA | B_WRITE_AREA, area_postmaster);
		}
	}

	/* remapping done release semaphore to allow other backend to startup */

	release_sem(beos_shm_sem);
}
コード例 #14
0
ファイル: NetPeek.cpp プロジェクト: AlexandreCo/macemu
int main(void)
{
	area_id handler_buffer;
	if ((handler_buffer = find_area("packet buffer")) < B_NO_ERROR) {
		printf("Can't find packet buffer\n");
		return 10;
	}
	if ((buffer_area = clone_area("local packet buffer", &net_buffer_ptr, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, handler_buffer)) < B_NO_ERROR) {
		printf("Can't clone packet buffer\n");
		return 10;
	}

	uint8 *p = net_buffer_ptr->ether_addr;
	printf("Ethernet address  : %02x %02x %02x %02x %02x %02x\n", p[0], p[1], p[2], p[3], p[4], p[5]);
	printf("read_sem          : %d\n", net_buffer_ptr->read_sem);
	printf("read_ofs          : %d\n", net_buffer_ptr->read_ofs);
	printf("read_packet_size  : %d\n", net_buffer_ptr->read_packet_size);
	printf("read_packet_count : %d\n", net_buffer_ptr->read_packet_count);
	printf("write_sem         : %d\n", net_buffer_ptr->write_sem);
	printf("write_ofs         : %d\n", net_buffer_ptr->write_ofs);
	printf("write_packet_size : %d\n", net_buffer_ptr->write_packet_size);
	printf("write_packet_count: %d\n", net_buffer_ptr->write_packet_count);

	printf("\nRead packets:\n");
	for (int i=0; i<READ_PACKET_COUNT; i++) {
		net_packet *p = &net_buffer_ptr->read[i];
		printf("cmd   : %08lx\n", p->cmd);
		printf("length: %d\n", p->length);
	}
	printf("\nWrite packets:\n");
	for (int i=0; i<WRITE_PACKET_COUNT; i++) {
		net_packet *p = &net_buffer_ptr->write[i];
		printf("cmd   : %08lx\n", p->cmd);
		printf("length: %d\n", p->length);
	}
	return 0;
}
コード例 #15
0
ファイル: shm.c プロジェクト: Kiddinglife/geco-game-engine
APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, 
                                         apr_size_t reqsize, 
                                         const char *filename, 
                                         apr_pool_t *p)
{
    apr_size_t pagesize;
    area_id newid;
    char *addr;
    char shname[B_OS_NAME_LENGTH];
    
    (*m) = (apr_shm_t *)apr_pcalloc(p, sizeof(apr_shm_t));
    /* we MUST allocate in pages, so calculate how big an area we need... */
    pagesize = ((reqsize + B_PAGE_SIZE - 1) / B_PAGE_SIZE) * B_PAGE_SIZE;
     
    if (!filename) {
        int num = 0;
        snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld", find_thread(NULL));
        while (find_area(shname) >= 0)
            snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld_%d",
                     find_thread(NULL), num++);
    }
    newid = create_area(filename ? filename : shname, 
                        (void*)&addr, B_ANY_ADDRESS,
                        pagesize, B_LAZY_LOCK, B_READ_AREA|B_WRITE_AREA);

    if (newid < 0)
        return errno;

    (*m)->pool = p;
    (*m)->aid = newid;
    (*m)->memblock = addr;
    (*m)->ptr = (void*)addr;
    (*m)->avail = pagesize; /* record how big an area we actually created... */
    (*m)->reqsize = reqsize;

    return APR_SUCCESS;
}
コード例 #16
0
void *gw_check_claim_area(void *p, const char *filename, long lineno,
                          const char *function)
{
    struct area *area;

    /* Allow this for the convenience of wrapper macros. */
    if (p == NULL)
        return NULL;

    lock();
    area = find_area(p);
    if (!area) {
        unlock();
        panic(0, "Claim_area called on non-allocated area");
    }

    area->claimer.filename = filename;
    area->claimer.lineno = lineno;
    area->claimer.function = function;
    unlock();

    /* For convenience of calling macros */
    return p;
}
コード例 #17
0
int
add_memory (struct pdp10_memory *memory, int address, int length, void *data)
{
  struct pdp10_area *area;

  if (find_area (memory, address) != NULL)
    return -2;

  memory->areas++;
  area = realloc (memory->area, memory->areas * sizeof (struct pdp10_area));
  if (area == NULL)
    {
      memory->areas--;
      return -1;
    }
  memory->area = area;

  area = &memory->area[memory->areas - 1];
  area->start = address;
  area->end = address + length;
  area->data = data;

  return 0;
}
コード例 #18
0
ファイル: renumber.c プロジェクト: InfiniteAxis/SmaugFUSS
void do_renumber( CHAR_DATA* ch, const char* argument)
{
   RENUMBER_AREA *r_area;
   AREA_DATA *area;
   bool is_proto;
   char arg1[MAX_INPUT_LENGTH];
   int new_base;
   bool fill_gaps, verbose;

   /*
    * parse the first two parameters 
    */
   /*
    * first, area 
    */
   argument = one_argument( argument, arg1 );

   if( arg1[0] == '\0' )
   {
      ch_printf( ch, "What area do you want to renumber?\r\n" );
      return;
   }

   area = find_area( arg1, &is_proto );

   if( area == NULL )
   {
      ch_printf( ch, "No such area '%s'.\r\n", arg1 );
      return;
   }

   /*
    * and new vnum base 
    */
   argument = one_argument( argument, arg1 );
   if( arg1[0] == '\0' )
   {
      ch_printf( ch, "What will be the new vnum base for this area?\r\n" );
      return;
   }

   if( !is_number( arg1 ) )
   {
      ch_printf( ch, "Sorry, '%s' is not a valid vnum base number!\r\n", arg1 );
      return;
   }

   new_base = atoi( arg1 );

   /*
    * parse the flags 
    */
   fill_gaps = FALSE;
   verbose = FALSE;

   for( ;; )
   {
      argument = one_argument( argument, arg1 );

      if( arg1[0] == '\0' )
         break;
      else if( !str_prefix( arg1, "fillgaps" ) )
         fill_gaps = TRUE;
      else if( !str_prefix( arg1, "verbose" ) )
         verbose = TRUE;
      else
      {
         ch_printf( ch, "Invalid flag '%s'.\r\n", arg1 );
         return;
      }
   }

   /*
    * sanity check 
    */
   if( new_base == area->low_r_vnum && new_base == area->low_o_vnum && new_base == area->low_m_vnum && !fill_gaps )
   {
      ch_printf( ch,
                 "You don't want to change the base vnum and you don't want to fill gaps...\r\nSo what DO you wanna do?\r\n" );
      return;
   }

   /*
    * some restrictions 
    */
   if( IS_NPC( ch ) )
   {
      ch_printf( ch, "Yeah, right.\r\n" );
      return;
   }

   if( ch->level < LEVEL_SAVIOR )
   {
      ch_printf( ch, "You don't have enough privileges.\r\n" );
      return;
   }

   if( ch->level == LEVEL_SAVIOR )
   {
      if( area->low_r_vnum < ch->pcdata->r_range_lo || area->hi_r_vnum > ch->pcdata->r_range_hi ||
          area->low_m_vnum < ch->pcdata->m_range_lo || area->hi_m_vnum > ch->pcdata->m_range_hi ||
          area->low_o_vnum < ch->pcdata->o_range_lo || area->hi_o_vnum > ch->pcdata->o_range_hi )
      {
         ch_printf( ch, "You can't renumber that area ('%s').\r\n", area->filename );
         return;
      }
   }

   /*
    * get the renumber data 
    */
   r_area = gather_renumber_data( area, new_base, fill_gaps );

   /*
    * one more restriction 
    */
   if( ch->level == LEVEL_SAVIOR )
   {
      if( r_area->low_room < ch->pcdata->r_range_lo || r_area->hi_room > ch->pcdata->r_range_hi ||
          r_area->low_obj < ch->pcdata->o_range_lo || r_area->hi_obj > ch->pcdata->o_range_hi ||
          r_area->low_mob < ch->pcdata->m_range_lo || r_area->hi_mob > ch->pcdata->m_range_hi )
      {
         DISPOSE( r_area );
         ch_printf( ch, "The renumbered area would be outside your assigned vnum range.\r\n" );
         return;
      }
   }
   else if( is_proto )
   {
      if( r_area->low_room < area->low_r_vnum || r_area->hi_room > area->hi_r_vnum ||
          r_area->low_obj < area->low_o_vnum || r_area->hi_obj > area->hi_o_vnum ||
          r_area->low_mob < area->low_m_vnum || r_area->hi_mob > area->hi_m_vnum )
      {
         DISPOSE( r_area );
         ch_printf( ch, "Moving a proto area out of its range would create problems.\r\nWait till the area is finished to move it.\r\n" );
         return;
      }
   }

   /*
    * no overwriting of dest vnums
    *
    * Bugfix - Memory leak if r_area was valid.
    */
   if( check_vnums( ch, area, r_area ) )
   {
      if( r_area )
         DISPOSE( r_area );
      return;
   }

   /*
    * another sanity check :) 
    */
   if( r_area == NULL || ( r_area->r_obj == NULL && r_area->r_mob == NULL && r_area->r_room == NULL ) )
   {
      ch_printf( ch, "No changes to make.\r\n" );
      if( r_area != NULL )
         DISPOSE( r_area );
      return;
   }

   /*
    * ok, do it! 
    */
   pager_printf( ch, "Renumbering area '%s' to new base %d, filling gaps: %s\r\n",
                 area->filename, new_base, fill_gaps ? "yes" : "no" );
   renumber_area( ch, area, r_area, is_proto, verbose );
   pager_printf( ch, "Done.\r\n" );

   /*
    * clean up and goodbye 
    */
   if( r_area->r_room != NULL )
      free_renumber_data( r_area->r_room );
   if( r_area->r_obj != NULL )
      free_renumber_data( r_area->r_obj );
   if( r_area->r_mob != NULL )
      free_renumber_data( r_area->r_mob );
   DISPOSE( r_area );
}
コード例 #19
0
ファイル: usb.cpp プロジェクト: MaddTheSane/haiku
static int32
bus_std_ops(int32 op, ...)
{
	switch (op) {
		case B_MODULE_INIT: {
			TRACE_MODULE("init\n");
			if (gUSBStack)
				return B_OK;

#ifdef HAIKU_TARGET_PLATFORM_BEOS
			// This code is to handle plain R5 (non-BONE) where the same module
			// gets loaded multiple times (once for each exported module
			// interface, the USB v2 and v3 API in our case). We don't want to
			// ever create multiple stacks however, so we "share" the same stack
			// for both modules by storing it's address in a shared area.
			void *address = NULL;
			area_id shared = find_area("shared usb stack");
			if (shared >= B_OK && clone_area("usb stack clone", &address,
				B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, shared) >= B_OK) {
				gUSBStack = *((Stack **)address);
				TRACE_MODULE("found shared stack at %p\n", gUSBStack);
				return B_OK;
			}
#endif

#ifdef TRACE_USB
			set_dprintf_enabled(true);
#ifndef HAIKU_TARGET_PLATFORM_HAIKU
			load_driver_symbols("usb");
#endif
#endif
			Stack *stack = new(std::nothrow) Stack();
			TRACE_MODULE("usb_module: stack created %p\n", stack);
			if (!stack)
				return B_NO_MEMORY;

			if (stack->InitCheck() != B_OK) {
				delete stack;
				return ENODEV;
			}

			gUSBStack = stack;

#ifdef HAIKU_TARGET_PLATFORM_HAIKU
			add_debugger_command("get_usb_pipe_for_id",
				&debug_get_pipe_for_id,
				"Gets the config for a USB pipe");
#elif HAIKU_TARGET_PLATFORM_BEOS
			// Plain R5 workaround, see comment above.
			shared = create_area("shared usb stack", &address,
				B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_NO_LOCK,
				B_KERNEL_WRITE_AREA);
			if (shared >= B_OK)
				*((Stack **)address) = gUSBStack;
#endif
			break;
		}

		case B_MODULE_UNINIT:
			TRACE_MODULE("uninit\n");
			delete gUSBStack;
			gUSBStack = NULL;

#ifdef HAIKU_TARGET_PLATFORM_HAIKU
			remove_debugger_command("get_usb_pipe_for_id",
				&debug_get_pipe_for_id);
#endif
			break;

		default:
			return EINVAL;
	}

	return B_OK;
}
コード例 #20
0
ファイル: iwdma.c プロジェクト: HaikuArchives/InterWave
status_t iw_find_low_memory(interwave_dev * iw)
{
	size_t low_size = (MIN_MEMORY_SIZE+(B_PAGE_SIZE-1))&~(B_PAGE_SIZE-1);
	size_t allocate_size;
	physical_entry where;
	uint32 boundary;
	size_t trysize;
	area_id curarea;
	void * addr;
	char name[DEVNAME];

	if (low_size < MIN_MEMORY_SIZE) {
		low_size = MIN_MEMORY_SIZE;
	}
	if (low_size > 65536) {
		iwprintf("too much low memory requested !");
		low_size = 65536;
	}
	
	allocate_size = 2*low_size;

	sprintf(name, "%s_low", iw->name);
	
	curarea = find_area(name);
	if (curarea >= 0) {	/* area there from previous run */
		area_info ainfo;
		iwprintf("testing likely candidate...");
		if (get_area_info(curarea, &ainfo)) {
			iwprintf("no info");
			goto allocate;
		}
		/* test area we found */
		trysize = ainfo.size;
		addr = ainfo.address;
		if (trysize < allocate_size) {
			iwprintf("too small (%x)", trysize);
			goto allocate;
		}
		if (get_memory_map(addr, trysize, &where, 1) < B_OK) {
			iwprintf("no memory map");
			goto allocate;
		}
		if ((uint32)where.address & 0xff000000) {
			iwprintf("bad physical address");
			goto allocate;
		}
		if (ainfo.lock < B_FULL_LOCK || where.size < allocate_size) {
			iwprintf("lock not contiguous");
			goto allocate;
		}
		goto a_o_k;
	}

allocate:
	if (curarea >= 0) {
		delete_area(curarea); /* area didn't work */
		curarea = -1;
	}

	iwprintf("allocating new low area");

	trysize = allocate_size;
	curarea = create_area(name, &addr, B_ANY_KERNEL_ADDRESS, 
		trysize, B_LOMEM, B_READ_AREA | B_WRITE_AREA);
	iwprintf("create_area(%d) returned area %x at logical 0x%08x", trysize, curarea, addr);
	if (curarea < 0) {
		goto oops;
	}
	if (get_memory_map(addr, allocate_size, &where, 1) < 0) {
		delete_area(curarea);
		curarea = B_ERROR;
		goto oops;
	}
	if ((uint32)where.address & 0xff000000) {                 // does not start in low memory
		delete_area(curarea);
		curarea = B_ERROR;
		goto oops;
	}
	if (((uint32)where.address+allocate_size) & 0xff000000) { // does not end in low memory
		delete_area(curarea);
		curarea = B_ERROR;
		goto oops;
	}

oops:
	if (curarea < 0) {
		dprintf("interwave: failed to create low_mem area\n");
		return curarea;
	}
	
a_o_k:
	iwprintf("successfully found or created low area!");
	iwprintf("physical 0x%08x-0x%08x logical 0x%08x size %d", where.address, 
		where.address+trysize-1, addr, trysize);
	
	iw->low_size = low_size;
	iw->low_area = curarea;

	// The resulting double-sized area probably crosses a 64K boundary.
	// Let's change the start address so that the final, normal-sized one does not.

	// The first boundary possibly crossed
	boundary = ((uint32)where.address & 0xffff0000) + 0x00010000;
	
	// The good chunk (low_size bytes not crossing a 64K boundary) may be
	// either below or above the first boundary.
	if((boundary-(uint32)where.address) >= low_size) { // it's below, nothing to change
		iw->low_mem = (uchar *)addr;
		iw->low_phys = (vuchar *)where.address;
		
		iwprintf("current size is %d bytes",trysize);
		iwprintf("keeping %d bytes",low_size);
		if(trysize>low_size)
			resize_area(curarea,low_size);
	} else {                                           // it's above - bump up start address
		uint32 delta = boundary - (uint32)where.address;
	
		iw->low_mem = (uchar *)addr + delta;
		iw->low_phys = (vuchar *)boundary;
		
		// Unfortunately, what's below the boundary (delta bytes) is wasted.
		// We can't truncate an area's bottom.
		iwprintf("current size is %d bytes",trysize);
		iwprintf("keeping %d bytes, waste=%d",low_size+delta,delta);
		if(trysize>low_size+delta)
			resize_area(curarea,low_size+delta);
	}
	
	iwprintf("using physical 0x%08x-0x%08x logical 0x%08x size %d", iw->low_phys,
		iw->low_phys+iw->low_size-1, iw->low_mem, iw->low_size);

	return B_OK;
}