1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-03 09:00:21 +00:00

Revamp bus_space access functions:

o   Optimize for memory mapped I/O by making all I/O port acceses function
    calls and marking the test for the IA64_BUS_SPACE_IO tag with
    __predict_false(). Implement the I/O port access functions in a new
    file, called bus_machdep.c.
o   Change the bus_space_handle_t for memory mapped I/O to the virtual
    address rather than the physical address. This eliminates the PA->VA
    translation for every I/O access. The handle for I/O port access is
    still the port number.
o   Move inb(), outb(), inw(), outw(), inl(), outl(), and their string
    variants from cpufunc.h and define them in bus.h. On ia64 these are
    not CPU functions at all. In bus.h they are merely aliases for the
    new I/O port access functions defined in bus_machdep.h.
o   Handle the ACPI resource bug in nexus_set_resource(). There we can
    do it once so that we don't have to worry about it whenever we need
    to write to an I/O port that is really a memory mapped address.

The upshot of this change is that the KBI is better defined and that I/O
port access always involves a function call, allowing us to change the
actual implementation without breaking the KBI. For memory mapped I/O the
virtual address is abstracted, so that we can change the VA->PA mapping
in the kernel without causing an KBI breakage. The exception at this time
is for bus_space_map() and bus_space_unmap().

MFC after:	1 week.
This commit is contained in:
Marcel Moolenaar 2009-12-30 18:15:25 +00:00
parent 0d883b11e3
commit 938026e334
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=201269
8 changed files with 772 additions and 520 deletions

View File

@ -72,6 +72,7 @@ ia64/ia32/ia32_reg.c optional compat_ia32
ia64/ia32/ia32_signal.c optional compat_ia32
ia64/ia32/ia32_trap.c optional compat_ia32
ia64/ia64/autoconf.c standard
ia64/ia64/bus_machdep.c standard
ia64/ia64/busdma_machdep.c standard
ia64/ia64/clock.c standard
ia64/ia64/context.S standard

356
sys/ia64/ia64/bus_machdep.c Normal file
View File

@ -0,0 +1,356 @@
/*-
* 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>
extern u_long ia64_port_base;
#define __PIO_ADDR(port) \
(void *)(ia64_port_base | (((port) & 0xfffc) << 10) | ((port) & 0xFFF))
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

View File

@ -930,16 +930,6 @@ ia64_init(void)
return (ret);
}
void *
ia64_ioport_address(u_int port)
{
uint64_t addr;
addr = (port > 0xffff) ? IA64_PHYS_TO_RR6((uint64_t)port) :
ia64_port_base | ((port & 0xfffc) << 10) | (port & 0xFFF);
return ((void *)addr);
}
uint64_t
ia64_get_hcdp(void)
{

View File

@ -366,7 +366,7 @@ ipi_send(struct pcpu *cpu, int ipi)
volatile uint64_t *pipi;
uint64_t vector;
pipi = __MEMIO_ADDR(ia64_lapic_address |
pipi = (void *)IA64_PHYS_TO_RR6(ia64_lapic_address |
((cpu->pc_md.lid & LID_SAPIC_MASK) >> 12));
vector = (uint64_t)(ipi_vector[ipi] & 0xff);
KASSERT(vector != 0, ("IPI %d is not assigned a vector", ipi));

View File

@ -389,26 +389,23 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
static int
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
struct resource *r)
{
vm_paddr_t paddr, psize;
vm_paddr_t paddr;
void *vaddr;
/*
* If this is a memory resource, map it into the kernel.
*/
paddr = rman_get_start(r);
switch (type) {
case SYS_RES_IOPORT:
rman_set_bustag(r, IA64_BUS_SPACE_IO);
rman_set_bushandle(r, rman_get_start(r));
rman_set_bushandle(r, paddr);
break;
case SYS_RES_MEMORY:
paddr = rman_get_start(r);
psize = rman_get_size(r);
vaddr = pmap_mapdev(paddr, psize);
rman_set_virtual(r, vaddr);
vaddr = pmap_mapdev(paddr, rman_get_size(r));
rman_set_bustag(r, IA64_BUS_SPACE_MEM);
rman_set_bushandle(r, (bus_space_handle_t) paddr);
rman_set_bushandle(r, (bus_space_handle_t) vaddr);
rman_set_virtual(r, vaddr);
break;
}
return (rman_activate_resource(r));
@ -488,11 +485,27 @@ nexus_get_reslist(device_t dev, device_t child)
}
static int
nexus_set_resource(device_t dev, device_t child, int type, int rid, u_long start, u_long count)
nexus_set_resource(device_t dev, device_t child, int type, int rid,
u_long start, u_long count)
{
struct nexus_device *ndev = DEVTONX(child);
struct resource_list *rl = &ndev->nx_resources;
if (type == SYS_RES_IOPORT && start > (0x10000 - count)) {
/*
* Work around a firmware bug in the HP rx2660, where in ACPI
* an I/O port is really a memory mapped I/O address. The bug
* is in the GAS that describes the address and in particular
* the SpaceId field. The field should not say the address is
* an I/O port when it is in fact an I/O memory address.
*/
if (bootverbose)
printf("%s: invalid port range (%#lx-%#lx); "
"assuming I/O memory range.\n", __func__, start,
start + count - 1);
type = SYS_RES_MEMORY;
}
/* XXX this should return a success/failure indicator */
resource_list_add(rl, type, rid, start, start + count - 1, count);
return(0);

View File

@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysproto.h>
#include <sys/sysent.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/sysarch.h>

File diff suppressed because it is too large Load Diff

View File

@ -54,126 +54,6 @@ breakpoint(void)
#define HAVE_INLINE_FFS
#define ffs(x) __builtin_ffs(x)
#define __MEMIO_ADDR(x) (void*)(IA64_PHYS_TO_RR6(x))
extern void *ia64_ioport_address(u_int);
#define __PIO_ADDR(x) ia64_ioport_address(x)
/*
* I/O port reads with ia32 semantics.
*/
static __inline uint8_t
inb(unsigned int port)
{
uint8_t v;
ia64_mf();
v = ia64_ld1(__PIO_ADDR(port));
ia64_mf_a();
ia64_mf();
return (v);
}
static __inline uint16_t
inw(unsigned int port)
{
uint16_t v;
ia64_mf();
v = ia64_ld2(__PIO_ADDR(port));
ia64_mf_a();
ia64_mf();
return (v);
}
static __inline uint32_t
inl(unsigned int port)
{
uint32_t v;
ia64_mf();
v = ia64_ld4(__PIO_ADDR(port));
ia64_mf_a();
ia64_mf();
return (v);
}
static __inline void
insb(unsigned int port, void *addr, size_t count)
{
uint8_t *buf = addr;
while (count--)
*buf++ = inb(port);
}
static __inline void
insw(unsigned int port, void *addr, size_t count)
{
uint16_t *buf = addr;
while (count--)
*buf++ = inw(port);
}
static __inline void
insl(unsigned int port, void *addr, size_t count)
{
uint32_t *buf = addr;
while (count--)
*buf++ = inl(port);
}
static __inline void
outb(unsigned int port, uint8_t data)
{
ia64_mf();
ia64_st1(__PIO_ADDR(port), data);
ia64_mf_a();
ia64_mf();
}
static __inline void
outw(unsigned int port, uint16_t data)
{
ia64_mf();
ia64_st2(__PIO_ADDR(port), data);
ia64_mf_a();
ia64_mf();
}
static __inline void
outl(unsigned int port, uint32_t data)
{
ia64_mf();
ia64_st4(__PIO_ADDR(port), data);
ia64_mf_a();
ia64_mf();
}
static __inline void
outsb(unsigned int port, const void *addr, size_t count)
{
const uint8_t *buf = addr;
while (count--)
outb(port, *buf++);
}
static __inline void
outsw(unsigned int port, const void *addr, size_t count)
{
const uint16_t *buf = addr;
while (count--)
outw(port, *buf++);
}
static __inline void
outsl(unsigned int port, const void *addr, size_t count)
{
const uint32_t *buf = addr;
while (count--)
outl(port, *buf++);
}
static __inline void
disable_intr(void)