26279767e4
o Eliminate IA64_PHYS_TO_RR6 and change all places where the macro is used by calling either bus_space_map() or pmap_mapdev(). o Implement bus_space_map() in terms of pmap_mapdev() and implement bus_space_unmap() in terms of pmap_unmapdev(). o Have ia64_pib hold the uncached virtual address of the processor interrupt block throughout the kernel's life and access the elements of the PIB through this structure pointer. This is a non-functional change with the exception of using ia64_ld1() and ia64_st8() to write to the PIB. We were still using assignments, for which the compiler generates semaphore reads -- which cause undefined behaviour for uncacheable memory. Note also that the memory barriers in ipi_send() are critical for proper functioning. With all the mapping of uncached memory done by pmap_mapdev(), we can keep track of the translations and wire them in the CPU. This then eliminates the need to reserve a whole region for uncached I/O and it eliminates translation traps for device I/O accesses.
378 lines
6.6 KiB
C
378 lines
6.6 KiB
C
/*-
|
|
* Copyright (c) 2009 Marcel Moolenaar
|
|
* 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 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 AUTHOR 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/cdefs.h>
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
#include <sys/types.h>
|
|
#include <machine/bus.h>
|
|
#include <vm/vm.h>
|
|
#include <vm/pmap.h>
|
|
|
|
extern u_long ia64_port_base;
|
|
|
|
#define __PIO_ADDR(port) \
|
|
(void *)(ia64_port_base | (((port) & 0xfffc) << 10) | ((port) & 0xFFF))
|
|
|
|
int
|
|
bus_space_map(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size,
|
|
int flags __unused, bus_space_handle_t *bshp)
|
|
{
|
|
|
|
*bshp = (__predict_false(bst == IA64_BUS_SPACE_IO))
|
|
? addr : (uintptr_t)pmap_mapdev(addr, size);
|
|
return (0);
|
|
}
|
|
|
|
|
|
void
|
|
bus_space_unmap(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
|
|
bus_size_t size)
|
|
{
|
|
|
|
pmap_unmapdev(bsh, size);
|
|
}
|
|
|
|
uint8_t
|
|
bus_space_read_io_1(u_long port)
|
|
{
|
|
uint8_t v;
|
|
|
|
ia64_mf();
|
|
v = ia64_ld1(__PIO_ADDR(port));
|
|
ia64_mf_a();
|
|
ia64_mf();
|
|
return (v);
|
|
}
|
|
|
|
uint16_t
|
|
bus_space_read_io_2(u_long port)
|
|
{
|
|
uint16_t v;
|
|
|
|
ia64_mf();
|
|
v = ia64_ld2(__PIO_ADDR(port));
|
|
ia64_mf_a();
|
|
ia64_mf();
|
|
return (v);
|
|
}
|
|
|
|
uint32_t
|
|
bus_space_read_io_4(u_long port)
|
|
{
|
|
uint32_t v;
|
|
|
|
ia64_mf();
|
|
v = ia64_ld4(__PIO_ADDR(port));
|
|
ia64_mf_a();
|
|
ia64_mf();
|
|
return (v);
|
|
}
|
|
|
|
#if 0
|
|
uint64_t
|
|
bus_space_read_io_8(u_long port)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void
|
|
bus_space_write_io_1(u_long port, uint8_t val)
|
|
{
|
|
|
|
ia64_mf();
|
|
ia64_st1(__PIO_ADDR(port), val);
|
|
ia64_mf_a();
|
|
ia64_mf();
|
|
}
|
|
|
|
void
|
|
bus_space_write_io_2(u_long port, uint16_t val)
|
|
{
|
|
|
|
ia64_mf();
|
|
ia64_st2(__PIO_ADDR(port), val);
|
|
ia64_mf_a();
|
|
ia64_mf();
|
|
}
|
|
|
|
void
|
|
bus_space_write_io_4(u_long port, uint32_t val)
|
|
{
|
|
|
|
ia64_mf();
|
|
ia64_st4(__PIO_ADDR(port), val);
|
|
ia64_mf_a();
|
|
ia64_mf();
|
|
}
|
|
|
|
#if 0
|
|
void
|
|
bus_space_write_io_8(u_long port, uint64_t val)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void
|
|
bus_space_read_multi_io_1(u_long port, uint8_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0)
|
|
*ptr++ = bus_space_read_io_1(port);
|
|
}
|
|
|
|
void
|
|
bus_space_read_multi_io_2(u_long port, uint16_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0)
|
|
*ptr++ = bus_space_read_io_2(port);
|
|
}
|
|
|
|
void
|
|
bus_space_read_multi_io_4(u_long port, uint32_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0)
|
|
*ptr++ = bus_space_read_io_4(port);
|
|
}
|
|
|
|
#if 0
|
|
void
|
|
bus_space_read_multi_io_8(u_long port, uint64_t *ptr, size_t count)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void
|
|
bus_space_write_multi_io_1(u_long port, const uint8_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0)
|
|
bus_space_write_io_1(port, *ptr++);
|
|
}
|
|
|
|
void
|
|
bus_space_write_multi_io_2(u_long port, const uint16_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0)
|
|
bus_space_write_io_2(port, *ptr++);
|
|
}
|
|
|
|
void
|
|
bus_space_write_multi_io_4(u_long port, const uint32_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0)
|
|
bus_space_write_io_4(port, *ptr++);
|
|
}
|
|
|
|
#if 0
|
|
void
|
|
bus_space_write_multi_io_8(u_long port, const uint64_t *ptr, size_t count)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void
|
|
bus_space_read_region_io_1(u_long port, uint8_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0) {
|
|
*ptr++ = bus_space_read_io_1(port);
|
|
port += 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
bus_space_read_region_io_2(u_long port, uint16_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0) {
|
|
*ptr++ = bus_space_read_io_2(port);
|
|
port += 2;
|
|
}
|
|
}
|
|
|
|
void
|
|
bus_space_read_region_io_4(u_long port, uint32_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0) {
|
|
*ptr++ = bus_space_read_io_4(port);
|
|
port += 4;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
void bus_space_read_region_io_8(u_long, uint64_t *, size_t);
|
|
#endif
|
|
|
|
void
|
|
bus_space_write_region_io_1(u_long port, const uint8_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0) {
|
|
bus_space_write_io_1(port, *ptr++);
|
|
port += 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
bus_space_write_region_io_2(u_long port, const uint16_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0) {
|
|
bus_space_write_io_2(port, *ptr++);
|
|
port += 2;
|
|
}
|
|
}
|
|
|
|
void
|
|
bus_space_write_region_io_4(u_long port, const uint32_t *ptr, size_t count)
|
|
{
|
|
|
|
while (count-- > 0) {
|
|
bus_space_write_io_4(port, *ptr++);
|
|
port += 4;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
void
|
|
bus_space_write_region_io_8(u_long port, const uint64_t *ptr, size_t count)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void
|
|
bus_space_set_region_io_1(u_long port, uint8_t val, size_t count)
|
|
{
|
|
|
|
while (count-- > 0) {
|
|
bus_space_write_io_1(port, val);
|
|
port += 1;
|
|
}
|
|
}
|
|
|
|
void
|
|
bus_space_set_region_io_2(u_long port, uint16_t val, size_t count)
|
|
{
|
|
|
|
while (count-- > 0) {
|
|
bus_space_write_io_2(port, val);
|
|
port += 2;
|
|
}
|
|
}
|
|
|
|
void
|
|
bus_space_set_region_io_4(u_long port, uint32_t val, size_t count)
|
|
{
|
|
|
|
while (count-- > 0) {
|
|
bus_space_write_io_4(port, val);
|
|
port += 4;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
void
|
|
bus_space_set_region_io_8(u_long port, uint64_t val, size_t count)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
void
|
|
bus_space_copy_region_io_1(u_long src, u_long dst, size_t count)
|
|
{
|
|
long delta;
|
|
uint8_t val;
|
|
|
|
if (src < dst) {
|
|
src += count - 1;
|
|
dst += count - 1;
|
|
delta = -1;
|
|
} else
|
|
delta = 1;
|
|
|
|
while (count-- > 0) {
|
|
val = bus_space_read_io_1(src);
|
|
bus_space_write_io_1(dst, val);
|
|
src += delta;
|
|
dst += delta;
|
|
}
|
|
}
|
|
|
|
void
|
|
bus_space_copy_region_io_2(u_long src, u_long dst, size_t count)
|
|
{
|
|
long delta;
|
|
uint16_t val;
|
|
|
|
if (src < dst) {
|
|
src += 2 * (count - 1);
|
|
dst += 2 * (count - 1);
|
|
delta = -2;
|
|
} else
|
|
delta = 2;
|
|
|
|
while (count-- > 0) {
|
|
val = bus_space_read_io_2(src);
|
|
bus_space_write_io_2(dst, val);
|
|
src += delta;
|
|
dst += delta;
|
|
}
|
|
}
|
|
|
|
void
|
|
bus_space_copy_region_io_4(u_long src, u_long dst, size_t count)
|
|
{
|
|
long delta;
|
|
uint32_t val;
|
|
|
|
if (src < dst) {
|
|
src += 4 * (count - 1);
|
|
dst += 4 * (count - 1);
|
|
delta = -4;
|
|
} else
|
|
delta = 4;
|
|
|
|
while (count-- > 0) {
|
|
val = bus_space_read_io_4(src);
|
|
bus_space_write_io_4(dst, val);
|
|
src += delta;
|
|
dst += delta;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
void
|
|
bus_space_copy_region_io_8(u_long src, u_long dst, size_t count)
|
|
{
|
|
}
|
|
#endif
|