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:
parent
0d883b11e3
commit
938026e334
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=201269
@ -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
356
sys/ia64/ia64/bus_machdep.c
Normal 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
|
@ -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)
|
||||
{
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user