[BACK]Return to bus_space.c CVS log [TXT][DIR] Up to [local] / sys / arch / mvmeppc / mvmeppc

File: [local] / sys / arch / mvmeppc / mvmeppc / bus_space.c (download)

Revision 1.1, Tue Mar 4 16:07:46 2008 UTC (16 years, 2 months ago) by nbrk
Branch point for: MAIN

Initial revision

/*      $OpenBSD: bus_space.c,v 1.6 2004/01/29 12:00:32 miod Exp $     */
/*      $NetBSD: bus_space.c,v 1.4 2001/06/15 15:50:05 nonaka Exp $     */

/*-
 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
 * Simulation Facility, NASA Ames Research Center.
 *
 * 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.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the NetBSD
 *      Foundation, Inc. and its contributors.
 * 4. Neither the name of The NetBSD Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``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 FOUNDATION OR CONTRIBUTORS
 * 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.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/extent.h>
#include <sys/mbuf.h>

#include <uvm/uvm_extern.h>

#include <machine/bus.h>

static int prep_memio_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
        bus_space_handle_t *);
static void prep_memio_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t);
static int prep_memio_alloc(bus_space_tag_t, bus_addr_t, bus_addr_t,
        bus_size_t, bus_size_t, bus_size_t, int, bus_addr_t *,
        bus_space_handle_t *);
static void prep_memio_free(bus_space_tag_t, bus_space_handle_t, bus_size_t);

const struct ppc_bus_space prep_io_space_tag = {
        PREP_BUS_SPACE_IO,  0x80000000, 0x80000000, 0x3f800000,
        prep_memio_map, prep_memio_unmap, prep_memio_alloc, prep_memio_free
};
const struct ppc_bus_space prep_isa_io_space_tag = {
        PREP_BUS_SPACE_IO,  0x80000000, 0x80000000, 0x00010000,
        prep_memio_map, prep_memio_unmap, prep_memio_alloc, prep_memio_free
};
const struct ppc_bus_space prep_mem_space_tag = {
        PREP_BUS_SPACE_MEM, 0xC0000000, 0xC0000000, 0x3f000000,
        prep_memio_map, prep_memio_unmap, prep_memio_alloc, prep_memio_free
};
const struct ppc_bus_space prep_isa_mem_space_tag = {
        PREP_BUS_SPACE_MEM, 0xC0000000, 0xC0000000, 0x01000000,
        prep_memio_map, prep_memio_unmap, prep_memio_alloc, prep_memio_free
};
static long ioport_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];

struct extent *ioport_ex;
struct extent *iomem_ex;

static int ioport_malloc_safe;

void
prep_bus_space_init()
{
        int error;

        ioport_ex = extent_create("ioport", 0, 0x3f7fffff, M_DEVBUF,
            (caddr_t)ioport_ex_storage, sizeof(ioport_ex_storage),
            EX_NOCOALESCE|EX_NOWAIT);
        error = extent_alloc_region(ioport_ex, 0x10000, 0x7F0000, EX_NOWAIT);
        if (error)
                panic("prep_bus_space_init: can't block out reserved I/O space 0x10000-0x7fffff: error=%d", error);
        iomem_ex = extent_create("iomem", 0, 0x3effffff, M_DEVBUF,
            (caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
            EX_NOCOALESCE|EX_NOWAIT);
}

void
prep_bus_space_mallocok()
{

        ioport_malloc_safe = 1;
}

static int
prep_memio_map(t, bpa, size, flags, bshp)
        bus_space_tag_t t;
        bus_addr_t bpa;
        bus_size_t size;
        int flags;
        bus_space_handle_t *bshp;
{
        int error;
        struct extent *ex;

        if (bpa + size > t->pbs_limit)
                return (EINVAL);
        /*
         * Pick the appropriate extent map.
         */
        if (t->pbs_type == PREP_BUS_SPACE_IO) {
                if (flags & BUS_SPACE_MAP_LINEAR)
                        return (EOPNOTSUPP);
                ex = ioport_ex;
        } else if (t->pbs_type == PREP_BUS_SPACE_MEM) {
                ex = iomem_ex;
        } else
                panic("prep_memio_map: bad bus space tag");

        /*
         * Before we go any further, let's make sure that this
         * region is available.
         */
        if ((error = extent_alloc_region(ex, bpa, size,
            EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) != 0)
                return (error);

	*bshp = (bus_space_handle_t)mapiodev(t->pbs_base + bpa, size);

        return (0);
}

static void
prep_memio_unmap(t, bsh, size)
        bus_space_tag_t t;
        bus_space_handle_t bsh;
        bus_size_t size;
{
        struct extent *ex;
        bus_addr_t bpa;

        /*
         * Find the correct extent and bus physical address.
         */
        if (t->pbs_type == PREP_BUS_SPACE_IO)
                ex = ioport_ex;
        else if (t->pbs_type == PREP_BUS_SPACE_MEM)
                ex = iomem_ex;
        else
                panic("prep_memio_unmap: bad bus space tag");

	pmap_extract(pmap_kernel(), (vaddr_t)bsh, (paddr_t *)&bpa);
	unmapiodev((void *)bsh, size);

        if (extent_free(ex, bpa, size,
            EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
                printf("prep_memio_unmap: %s 0x%lx, size 0x%lx\n",
                    (t->pbs_type == PREP_BUS_SPACE_IO) ? "port" : "mem",
                    (unsigned long)bpa, (unsigned long)size);
                printf("prep_memio_unmap: can't free region\n");
        }
}

static int
prep_memio_alloc(t, rstart, rend, size, alignment, boundary, flags,
    bpap, bshp)
        bus_space_tag_t t;
        bus_addr_t rstart, rend;
        bus_size_t size, alignment, boundary;
        int flags;
        bus_addr_t *bpap;
        bus_space_handle_t *bshp;
{
        struct extent *ex;
        u_long bpa;
        int error;

        if (rstart + size > t->pbs_limit)
                return (EINVAL);

        if (t->pbs_type == PREP_BUS_SPACE_IO) {
                if (flags & BUS_SPACE_MAP_LINEAR)
                        return (EOPNOTSUPP);
                ex = ioport_ex;
        } else if (t->pbs_type == PREP_BUS_SPACE_MEM) {
                ex = iomem_ex;
        } else
                panic("prep_memio_alloc: bad bus space tag");

        if (rstart < ex->ex_start || rend > ex->ex_end)
                panic("prep_memio_alloc: bad region start/end");

	error = extent_alloc_subregion(ex, rstart, rend, size, alignment, 0,
            boundary,
            EX_FAST | EX_NOWAIT | (ioport_malloc_safe ?  EX_MALLOCOK : 0),
            &bpa);
        
	if (error)
                return (error);

        *bpap = bpa;
        *bshp = t->pbs_base + bpa;

        return (0);
}

static void    
prep_memio_free(t, bsh, size)
        bus_space_tag_t t;
        bus_space_handle_t bsh;
        bus_size_t size;
{

        /* prep_memio_unmap() does all that we need to do. */
        prep_memio_unmap(t, bsh, size);
}