1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-27 16:39:08 +00:00

- Split the routine to initialize a bus_space_handle into the separate

function.
- Only access a bus_space_handle if the resource type is SYS_RES_MEMORY or
  SYS_RES_IOPORT.
- Add the bus_space_subregion supports.
This commit is contained in:
Yoshihiro Takahashi 2002-02-17 09:16:45 +00:00
parent a6e1e07f4d
commit 9d139b79d4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=90762
9 changed files with 339 additions and 142 deletions

View File

@ -76,9 +76,6 @@
#include <i386/isa/intr_machdep.h>
#include <sys/rtprio.h>
#ifdef PC98
static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
#endif
static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
struct nexus_device {
struct resource_list nx_resources;
@ -438,40 +435,32 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0)
return 0;
#ifdef PC98
/* Allocate bushandle. */
rv->r_bushandle = malloc(sizeof *rv->r_bushandle, M_BUSSPACEHANDLE,
M_NOWAIT | M_ZERO);
if (rv->r_bushandle == 0) {
rman_release_resource(rv);
return 0;
}
#endif
if (type == SYS_RES_MEMORY) {
rman_set_bustag(rv, I386_BUS_SPACE_MEM);
} else if (type == SYS_RES_IOPORT) {
rman_set_bustag(rv, I386_BUS_SPACE_IO);
#ifdef PC98
/* PC-98: the type of bus_space_handle_t is the structure. */
rv->r_bushandle->bsh_base = rv->r_start;
rv->r_bushandle->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
rv->r_bushandle->bsh_iatsz = 0;
rv->r_bushandle->bsh_res = NULL;
rv->r_bushandle->bsh_ressz = 0;
/* default: direct access */
rv->r_bushandle->bsh_bam = rv->r_bustag->bs_da;
#else
/* IBM-PC: the type of bus_space_handle_t is u_int */
#ifndef PC98
rman_set_bushandle(rv, rv->r_start);
#endif
}
#ifdef PC98
if ((type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) &&
i386_bus_space_handle_alloc(rv->r_bustag, rv->r_start, count,
&rv->r_bushandle) != 0) {
rman_release_resource(rv);
return 0;
}
#endif
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
#ifdef PC98
free(rv->r_bushandle, M_BUSSPACEHANDLE);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
i386_bus_space_handle_free(rv->r_bustag,
rv->r_bushandle, rv->r_bushandle->bsh_sz);
}
#endif
rman_release_resource(rv);
return 0;
@ -511,13 +500,6 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
#ifdef PC98
/* PC-98: the type of bus_space_handle_t is the structure. */
r->r_bushandle->bsh_base = (bus_addr_t) vaddr;
r->r_bushandle->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
r->r_bushandle->bsh_iatsz = 0;
r->r_bushandle->bsh_res = NULL;
r->r_bushandle->bsh_ressz = 0;
/* default: direct access */
r->r_bushandle->bsh_bam = r->r_bustag->bs_da;
#else
/* IBM-PC: the type of bus_space_handle_t is u_int */
rman_set_bushandle(r, (bus_space_handle_t) vaddr);
@ -554,7 +536,10 @@ nexus_release_resource(device_t bus, device_t child, int type, int rid,
return error;
}
#ifdef PC98
free(r->r_bushandle, M_BUSSPACEHANDLE);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
i386_bus_space_handle_free(r->r_bustag, r->r_bushandle,
r->r_bushandle->bsh_sz);
}
#endif
return (rman_release_resource(r));
}

View File

@ -76,9 +76,6 @@
#include <i386/isa/intr_machdep.h>
#include <sys/rtprio.h>
#ifdef PC98
static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
#endif
static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
struct nexus_device {
struct resource_list nx_resources;
@ -438,40 +435,32 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0)
return 0;
#ifdef PC98
/* Allocate bushandle. */
rv->r_bushandle = malloc(sizeof *rv->r_bushandle, M_BUSSPACEHANDLE,
M_NOWAIT | M_ZERO);
if (rv->r_bushandle == 0) {
rman_release_resource(rv);
return 0;
}
#endif
if (type == SYS_RES_MEMORY) {
rman_set_bustag(rv, I386_BUS_SPACE_MEM);
} else if (type == SYS_RES_IOPORT) {
rman_set_bustag(rv, I386_BUS_SPACE_IO);
#ifdef PC98
/* PC-98: the type of bus_space_handle_t is the structure. */
rv->r_bushandle->bsh_base = rv->r_start;
rv->r_bushandle->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
rv->r_bushandle->bsh_iatsz = 0;
rv->r_bushandle->bsh_res = NULL;
rv->r_bushandle->bsh_ressz = 0;
/* default: direct access */
rv->r_bushandle->bsh_bam = rv->r_bustag->bs_da;
#else
/* IBM-PC: the type of bus_space_handle_t is u_int */
#ifndef PC98
rman_set_bushandle(rv, rv->r_start);
#endif
}
#ifdef PC98
if ((type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) &&
i386_bus_space_handle_alloc(rv->r_bustag, rv->r_start, count,
&rv->r_bushandle) != 0) {
rman_release_resource(rv);
return 0;
}
#endif
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
#ifdef PC98
free(rv->r_bushandle, M_BUSSPACEHANDLE);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
i386_bus_space_handle_free(rv->r_bustag,
rv->r_bushandle, rv->r_bushandle->bsh_sz);
}
#endif
rman_release_resource(rv);
return 0;
@ -511,13 +500,6 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
#ifdef PC98
/* PC-98: the type of bus_space_handle_t is the structure. */
r->r_bushandle->bsh_base = (bus_addr_t) vaddr;
r->r_bushandle->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
r->r_bushandle->bsh_iatsz = 0;
r->r_bushandle->bsh_res = NULL;
r->r_bushandle->bsh_ressz = 0;
/* default: direct access */
r->r_bushandle->bsh_bam = r->r_bustag->bs_da;
#else
/* IBM-PC: the type of bus_space_handle_t is u_int */
rman_set_bushandle(r, (bus_space_handle_t) vaddr);
@ -554,7 +536,10 @@ nexus_release_resource(device_t bus, device_t child, int type, int rid,
return error;
}
#ifdef PC98
free(r->r_bushandle, M_BUSSPACEHANDLE);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
i386_bus_space_handle_free(r->r_bustag, r->r_bushandle,
r->r_bushandle->bsh_sz);
}
#endif
return (rman_release_resource(r));
}

View File

@ -236,11 +236,13 @@ isa_release_resource(device_t bus, device_t child, int type, int rid,
*/
int i;
for (i = 1; i < r->r_bushandle->bsh_ressz; i++)
resource_list_release(rl, bus, child, type, rid + i,
r->r_bushandle->bsh_res[i]);
if (r->r_bushandle->bsh_res != NULL)
free(r->r_bushandle->bsh_res, M_DEVBUF);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
for (i = 1; i < r->r_bushandle->bsh_ressz; i++)
resource_list_release(rl, bus, child, type, rid + i,
r->r_bushandle->bsh_res[i]);
if (r->r_bushandle->bsh_res != NULL)
free(r->r_bushandle->bsh_res, M_DEVBUF);
}
#endif
return resource_list_release(rl, bus, child, type, rid, r);
}

View File

@ -76,9 +76,6 @@
#include <i386/isa/intr_machdep.h>
#include <sys/rtprio.h>
#ifdef PC98
static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
#endif
static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
struct nexus_device {
struct resource_list nx_resources;
@ -438,40 +435,32 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0)
return 0;
#ifdef PC98
/* Allocate bushandle. */
rv->r_bushandle = malloc(sizeof *rv->r_bushandle, M_BUSSPACEHANDLE,
M_NOWAIT | M_ZERO);
if (rv->r_bushandle == 0) {
rman_release_resource(rv);
return 0;
}
#endif
if (type == SYS_RES_MEMORY) {
rman_set_bustag(rv, I386_BUS_SPACE_MEM);
} else if (type == SYS_RES_IOPORT) {
rman_set_bustag(rv, I386_BUS_SPACE_IO);
#ifdef PC98
/* PC-98: the type of bus_space_handle_t is the structure. */
rv->r_bushandle->bsh_base = rv->r_start;
rv->r_bushandle->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
rv->r_bushandle->bsh_iatsz = 0;
rv->r_bushandle->bsh_res = NULL;
rv->r_bushandle->bsh_ressz = 0;
/* default: direct access */
rv->r_bushandle->bsh_bam = rv->r_bustag->bs_da;
#else
/* IBM-PC: the type of bus_space_handle_t is u_int */
#ifndef PC98
rman_set_bushandle(rv, rv->r_start);
#endif
}
#ifdef PC98
if ((type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) &&
i386_bus_space_handle_alloc(rv->r_bustag, rv->r_start, count,
&rv->r_bushandle) != 0) {
rman_release_resource(rv);
return 0;
}
#endif
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
#ifdef PC98
free(rv->r_bushandle, M_BUSSPACEHANDLE);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
i386_bus_space_handle_free(rv->r_bustag,
rv->r_bushandle, rv->r_bushandle->bsh_sz);
}
#endif
rman_release_resource(rv);
return 0;
@ -511,13 +500,6 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
#ifdef PC98
/* PC-98: the type of bus_space_handle_t is the structure. */
r->r_bushandle->bsh_base = (bus_addr_t) vaddr;
r->r_bushandle->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
r->r_bushandle->bsh_iatsz = 0;
r->r_bushandle->bsh_res = NULL;
r->r_bushandle->bsh_ressz = 0;
/* default: direct access */
r->r_bushandle->bsh_bam = r->r_bustag->bs_da;
#else
/* IBM-PC: the type of bus_space_handle_t is u_int */
rman_set_bushandle(r, (bus_space_handle_t) vaddr);
@ -554,7 +536,10 @@ nexus_release_resource(device_t bus, device_t child, int type, int rid,
return error;
}
#ifdef PC98
free(r->r_bushandle, M_BUSSPACEHANDLE);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
i386_bus_space_handle_free(r->r_bustag, r->r_bushandle,
r->r_bushandle->bsh_sz);
}
#endif
return (rman_release_resource(r));
}

View File

@ -76,9 +76,6 @@
#include <i386/isa/intr_machdep.h>
#include <sys/rtprio.h>
#ifdef PC98
static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
#endif
static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
struct nexus_device {
struct resource_list nx_resources;
@ -438,40 +435,32 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv == 0)
return 0;
#ifdef PC98
/* Allocate bushandle. */
rv->r_bushandle = malloc(sizeof *rv->r_bushandle, M_BUSSPACEHANDLE,
M_NOWAIT | M_ZERO);
if (rv->r_bushandle == 0) {
rman_release_resource(rv);
return 0;
}
#endif
if (type == SYS_RES_MEMORY) {
rman_set_bustag(rv, I386_BUS_SPACE_MEM);
} else if (type == SYS_RES_IOPORT) {
rman_set_bustag(rv, I386_BUS_SPACE_IO);
#ifdef PC98
/* PC-98: the type of bus_space_handle_t is the structure. */
rv->r_bushandle->bsh_base = rv->r_start;
rv->r_bushandle->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
rv->r_bushandle->bsh_iatsz = 0;
rv->r_bushandle->bsh_res = NULL;
rv->r_bushandle->bsh_ressz = 0;
/* default: direct access */
rv->r_bushandle->bsh_bam = rv->r_bustag->bs_da;
#else
/* IBM-PC: the type of bus_space_handle_t is u_int */
#ifndef PC98
rman_set_bushandle(rv, rv->r_start);
#endif
}
#ifdef PC98
if ((type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) &&
i386_bus_space_handle_alloc(rv->r_bustag, rv->r_start, count,
&rv->r_bushandle) != 0) {
rman_release_resource(rv);
return 0;
}
#endif
if (needactivate) {
if (bus_activate_resource(child, type, *rid, rv)) {
#ifdef PC98
free(rv->r_bushandle, M_BUSSPACEHANDLE);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
i386_bus_space_handle_free(rv->r_bustag,
rv->r_bushandle, rv->r_bushandle->bsh_sz);
}
#endif
rman_release_resource(rv);
return 0;
@ -511,13 +500,6 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
#ifdef PC98
/* PC-98: the type of bus_space_handle_t is the structure. */
r->r_bushandle->bsh_base = (bus_addr_t) vaddr;
r->r_bushandle->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
r->r_bushandle->bsh_iatsz = 0;
r->r_bushandle->bsh_res = NULL;
r->r_bushandle->bsh_ressz = 0;
/* default: direct access */
r->r_bushandle->bsh_bam = r->r_bustag->bs_da;
#else
/* IBM-PC: the type of bus_space_handle_t is u_int */
rman_set_bushandle(r, (bus_space_handle_t) vaddr);
@ -554,7 +536,10 @@ nexus_release_resource(device_t bus, device_t child, int type, int rid,
return error;
}
#ifdef PC98
free(r->r_bushandle, M_BUSSPACEHANDLE);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
i386_bus_space_handle_free(r->r_bustag, r->r_bushandle,
r->r_bushandle->bsh_sz);
}
#endif
return (rman_release_resource(r));
}

View File

@ -148,6 +148,8 @@ extern struct bus_space_tag SBUS_mem_space_tag;
*/
struct bus_space_handle {
bus_addr_t bsh_base;
size_t bsh_sz;
bus_addr_t bsh_iat[BUS_SPACE_IAT_MAXSIZE];
size_t bsh_maxiatsz;
size_t bsh_iatsz;
@ -159,6 +161,29 @@ struct bus_space_handle {
};
typedef struct bus_space_handle *bus_space_handle_t;
/*
* Allocate/Free bus_space_handle
*/
int i386_bus_space_handle_alloc(bus_space_tag_t t, bus_addr_t bpa,
bus_size_t size, bus_space_handle_t *bshp);
void i386_bus_space_handle_free(bus_space_tag_t t, bus_space_handle_t bsh,
size_t size);
/*
* int bus_space_subregion (bus_space_tag_t t,
* bus_space_handle_t bsh, bus_size_t offset, bus_size_t size,
* bus_space_handle_t *nbshp);
*
* Get a new handle for a subregion of an already-mapped area of bus space.
*/
int i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
bus_size_t offset, bus_size_t size,
bus_space_handle_t *nbshp);
#define bus_space_subregion(t, h, o, s, nhp) \
i386_memio_subregion((t), (h), (o), (s), (nhp))
/*
* Access methods for bus resources and address space.
*/

View File

@ -236,11 +236,13 @@ isa_release_resource(device_t bus, device_t child, int type, int rid,
*/
int i;
for (i = 1; i < r->r_bushandle->bsh_ressz; i++)
resource_list_release(rl, bus, child, type, rid + i,
r->r_bushandle->bsh_res[i]);
if (r->r_bushandle->bsh_res != NULL)
free(r->r_bushandle->bsh_res, M_DEVBUF);
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
for (i = 1; i < r->r_bushandle->bsh_ressz; i++)
resource_list_release(rl, bus, child, type, rid + i,
r->r_bushandle->bsh_res[i]);
if (r->r_bushandle->bsh_res != NULL)
free(r->r_bushandle->bsh_res, M_DEVBUF);
}
#endif
return resource_list_release(rl, bus, child, type, rid, r);
}

View File

@ -43,8 +43,11 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <machine/bus.h>
static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int8_t,1)
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int16_t,2)
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int32_t,4)
@ -142,3 +145,114 @@ struct bus_space_tag NEPC_mem_space_tag = {
};
#endif /* DEV_MECIA */
/*************************************************************************
* map init
*************************************************************************/
static __inline void
bus_space_iat_init(bus_space_handle_t bsh)
{
int i;
for (i = 0; i < bsh->bsh_maxiatsz; i++)
bsh->bsh_iat[i] = bsh->bsh_base + i;
}
/*************************************************************************
* handle allocation
*************************************************************************/
int
i386_bus_space_handle_alloc(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
bus_space_handle_t *bshp)
{
bus_space_handle_t bsh;
bsh = (bus_space_handle_t) malloc(sizeof (*bsh), M_BUSSPACEHANDLE,
M_NOWAIT | M_ZERO);
if (bsh == NULL)
return ENOMEM;
bsh->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
bsh->bsh_iatsz = 0;
bsh->bsh_base = bpa;
bsh->bsh_sz = size;
bsh->bsh_res = NULL;
bsh->bsh_ressz = 0;
bus_space_iat_init(bsh);
bsh->bsh_bam = t->bs_da; /* default: direct access */
*bshp = bsh;
return 0;
}
void
i386_bus_space_handle_free(bus_space_tag_t t, bus_space_handle_t bsh,
size_t size)
{
free(bsh, M_BUSSPACEHANDLE);
}
/*************************************************************************
* map
*************************************************************************/
int
i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh,
bus_size_t offset, bus_size_t size,
bus_space_handle_t *tbshp)
{
int i, error = 0;
bus_space_handle_t bsh;
bus_addr_t pbase;
pbase = pbsh->bsh_base + offset;
switch (t->bs_tag) {
case BUS_SPACE_IO:
if (pbsh->bsh_iatsz > 0) {
if (offset >= pbsh->bsh_iatsz ||
offset + size > pbsh->bsh_iatsz)
return EINVAL;
pbase = pbsh->bsh_base;
}
break;
case BUS_SPACE_MEM:
if (pbsh->bsh_iatsz > 0)
return EINVAL;
if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz)
return EINVAL;
break;
default:
panic("i386_memio_subregion: bad bus space tag");
break;
}
error = i386_bus_space_handle_alloc(t, pbase, size, &bsh);
if (error != 0)
return error;
switch (t->bs_tag) {
case BUS_SPACE_IO:
if (pbsh->bsh_iatsz > 0) {
for (i = 0; i < size; i ++)
bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset];
bsh->bsh_iatsz = size;
} else if (pbsh->bsh_base > bsh->bsh_base ||
pbsh->bsh_base + pbsh->bsh_sz <
bsh->bsh_base + bsh->bsh_sz) {
i386_bus_space_handle_free(t, bsh, size);
return EINVAL;
}
break;
case BUS_SPACE_MEM:
break;
}
if (pbsh->bsh_iatsz > 0)
bsh->bsh_bam = t->bs_ra; /* relocate access */
*tbshp = bsh;
return error;
}

View File

@ -43,8 +43,11 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <machine/bus.h>
static MALLOC_DEFINE(M_BUSSPACEHANDLE, "busspacehandle", "Bus space handle");
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int8_t,1)
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int16_t,2)
_BUS_SPACE_CALL_FUNCS_PROTO(SBUS_DA_io,u_int32_t,4)
@ -142,3 +145,114 @@ struct bus_space_tag NEPC_mem_space_tag = {
};
#endif /* DEV_MECIA */
/*************************************************************************
* map init
*************************************************************************/
static __inline void
bus_space_iat_init(bus_space_handle_t bsh)
{
int i;
for (i = 0; i < bsh->bsh_maxiatsz; i++)
bsh->bsh_iat[i] = bsh->bsh_base + i;
}
/*************************************************************************
* handle allocation
*************************************************************************/
int
i386_bus_space_handle_alloc(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
bus_space_handle_t *bshp)
{
bus_space_handle_t bsh;
bsh = (bus_space_handle_t) malloc(sizeof (*bsh), M_BUSSPACEHANDLE,
M_NOWAIT | M_ZERO);
if (bsh == NULL)
return ENOMEM;
bsh->bsh_maxiatsz = BUS_SPACE_IAT_MAXSIZE;
bsh->bsh_iatsz = 0;
bsh->bsh_base = bpa;
bsh->bsh_sz = size;
bsh->bsh_res = NULL;
bsh->bsh_ressz = 0;
bus_space_iat_init(bsh);
bsh->bsh_bam = t->bs_da; /* default: direct access */
*bshp = bsh;
return 0;
}
void
i386_bus_space_handle_free(bus_space_tag_t t, bus_space_handle_t bsh,
size_t size)
{
free(bsh, M_BUSSPACEHANDLE);
}
/*************************************************************************
* map
*************************************************************************/
int
i386_memio_subregion(bus_space_tag_t t, bus_space_handle_t pbsh,
bus_size_t offset, bus_size_t size,
bus_space_handle_t *tbshp)
{
int i, error = 0;
bus_space_handle_t bsh;
bus_addr_t pbase;
pbase = pbsh->bsh_base + offset;
switch (t->bs_tag) {
case BUS_SPACE_IO:
if (pbsh->bsh_iatsz > 0) {
if (offset >= pbsh->bsh_iatsz ||
offset + size > pbsh->bsh_iatsz)
return EINVAL;
pbase = pbsh->bsh_base;
}
break;
case BUS_SPACE_MEM:
if (pbsh->bsh_iatsz > 0)
return EINVAL;
if (offset > pbsh->bsh_sz || offset + size > pbsh->bsh_sz)
return EINVAL;
break;
default:
panic("i386_memio_subregion: bad bus space tag");
break;
}
error = i386_bus_space_handle_alloc(t, pbase, size, &bsh);
if (error != 0)
return error;
switch (t->bs_tag) {
case BUS_SPACE_IO:
if (pbsh->bsh_iatsz > 0) {
for (i = 0; i < size; i ++)
bsh->bsh_iat[i] = pbsh->bsh_iat[i + offset];
bsh->bsh_iatsz = size;
} else if (pbsh->bsh_base > bsh->bsh_base ||
pbsh->bsh_base + pbsh->bsh_sz <
bsh->bsh_base + bsh->bsh_sz) {
i386_bus_space_handle_free(t, bsh, size);
return EINVAL;
}
break;
case BUS_SPACE_MEM:
break;
}
if (pbsh->bsh_iatsz > 0)
bsh->bsh_bam = t->bs_ra; /* relocate access */
*tbshp = bsh;
return error;
}