/* $NetBSD: rbus.c,v 1.29 2012/01/27 18:53:07 para Exp $ */
/*
* Copyright (c) 1999 and 2000
* HAYAKAWA Koichi. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
if (mask == 0) {
/* FULL Decode */
decodesize = 0;
}
if (rbt->rb_flags == RBUS_SPACE_ASK_PARENT) {
return rbus_space_alloc(rbt->rb_parent, addr, size, mask,
align, flags, addrp, bshp);
} else if (rbt->rb_flags == RBUS_SPACE_SHARE ||
rbt->rb_flags == RBUS_SPACE_DEDICATE) {
/* rbt has its own sh_extent */
/*
* sanity check: the subregion [substart, subend] should be
* smaller than the region included in sh_extent.
*/
if (substart < rbt->rb_ext->ex_start
|| subend > rbt->rb_ext->ex_end) {
DPRINTF(("rbus: out of range\n"));
return 1;
}
if (decodesize == align) {
if(extent_alloc_subregion(rbt->rb_ext, substart,
subend, size, align, 0, exflags, &result)) {
return 1;
}
} else if (decodesize == 0) {
/* maybe, the register is overflowed. */
/* sanity check */
if (parent != NULL) {
if (start < parent->rb_start || end > parent->rb_end) {
/*
* out of range: [start, size] should be
* contained in parent space
*/
return 0;
/* Should I invoke panic? */
}
}
if (NULL == (rb = (rbus_tag_t)malloc(sizeof(struct rbustag), M_DEVBUF,
M_NOWAIT))) {
panic("no memory for rbus instance");
}
/*
* int rbus_delete (rbus_tag_t rb)
*
* This function deletes the rbus structure pointed in the argument.
*/
int
rbus_delete(rbus_tag_t rb)
{
DPRINTF(("rbus_delete called [%s]\n",
rb->rb_ext != NULL ? rb->rb_ext->ex_name : "noname"));
if (rb->rb_flags == RBUS_SPACE_DEDICATE) {
extent_destroy(rb->rb_ext);
}