Fake pci bus manager for m68k.

We will fake hardcoded devices depending on the platform.
Hopefully that will help some generic drivers (ide) to work without major modification.
Synced to r22648.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22655 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol 2007-10-22 00:13:10 +00:00
parent 188b43270e
commit 5bbe87abba
12 changed files with 897 additions and 0 deletions

View File

@ -0,0 +1,19 @@
SubDir HAIKU_TOP src add-ons kernel bus_managers pci arch m68k ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) ] ;
UsePrivateHeaders kernel [ FDirName kernel arch $(TARGET_ARCH) ]
[ FDirName kernel boot platform $(HAIKU_BOOT_PLATFORM) ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) amiga ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) apple ] ;
SEARCH_SOURCE += [ FDirName $(SUBDIR) atari ] ;
KernelStaticLibrary pci_arch_bus_manager :
pci_controller.cpp
pci_io.c
# platforms
pci_amiga.cpp
pci_apple.cpp
pci_atari.cpp
;

View File

@ -0,0 +1,23 @@
/*
* Copyright 2007, François Revol <revol@free.fr>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "pci_amiga.h"
#include <stdlib.h>
#include <string.h>
#include <KernelExport.h>
status_t
m68k_amiga_pci_controller_init(void)
{
return B_OK;
}
// #pragma mark - support functions

View File

@ -0,0 +1,13 @@
/*
* Copyright 2007, François Revol <revol@free.fr>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef PCI_BUS_MANAGER_M68K_AMIGA_H
#define PCI_BUS_MANAGER_M68K_AMIGA_H
#include <SupportDefs.h>
status_t m68k_amiga_pci_controller_init(void);
#endif // PCI_BUS_MANAGER_M68K_AMIGA_H

View File

@ -0,0 +1,23 @@
/*
* Copyright 2007, François Revol <revol@free.fr>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "pci_apple.h"
#include <stdlib.h>
#include <string.h>
#include <KernelExport.h>
status_t
m68k_apple_pci_controller_init(void)
{
return B_OK;
}
// #pragma mark - support functions

View File

@ -0,0 +1,13 @@
/*
* Copyright 2007, François Revol <revol@free.fr>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef PCI_BUS_MANAGER_M68K_APPLE_H
#define PCI_BUS_MANAGER_M68K_APPLE_H
#include <SupportDefs.h>
status_t m68k_apple_pci_controller_init(void);
#endif // PCI_BUS_MANAGER_M68K_APPLE_H

View File

@ -0,0 +1,262 @@
/*
* Copyright 2007, François Revol <revol@free.fr>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "pci_atari.h"
#include <stdlib.h>
#include <string.h>
#include <KernelExport.h>
#include <PCI.h>
#include "pci_controller.h"
//XXX:find one and put in shared priv header!
// 0x68xx is free according to pci.ids
// 68fx (f=fake) x = 0:amiga, 1:apple, 2:atari
#define FAKEV 0x68f2
// bus number
#define BN 0
// default line size
#define DLL 1
// default latency
#define DL 0
// default bist
#define DB 0
#define PEI {0}
#define INVV 0xffff //0x0000 ??
#define INVD 0xffff
struct fake_pci_device {
pci_info info;
};
static struct fake_pci_device gFakePCIDevices[] = {
{ {FAKEV, 0x0000, BN, 0, 0, 0, 0xff, PCI_host, PCI_bridge, DLL, DL, DB, 0, PEI }}, /* cpu */
{ {FAKEV, 0x0001, BN, 1, 0, 0, 0xff, 0x68/*fake*/, PCI_processor, DLL, DL, DB, 0, PEI }}, /* cpu */
{ {FAKEV, 0x0002, BN, 2, 0, 0, 0xff, PCI_display_other, PCI_display, DLL, DL, DB, 0, $FFFF8200, PEI }}, /* gfx */
{ {FAKEV, 0x0003, BN, 3, 0, 0, 0xff, PCI_ide, PCI_mass_storage, DLL, DL, DB, 0, $FFF00000, PEI }}, /* ide */
{ {FAKEV, 0x0004, BN, 4, 0, 0, 0xff, PCI_scsi, PCI_mass_storage, DLL, DL, DB, 0, PEI }}, /* scsi */
{ {FAKEV, 0x0005, BN, 5, 0, 0, 0xff, 0x, PCI_multimedia, DLL, DL, DB, 0x00, 0, $FFFF8900, PEI }}, /* snd */
//UART ?
//centronics?
{ {INVV, INVD} }
};
#define FAKE_DEVICES_COUNT ((sizeof(gFakePCIDevices)/sizeof(struct fake_pci_device)-1)
#define out8rb(address, value) m68k_out8((vuint8*)(address), value)
#define out16rb(address, value) m68k_out16_reverse((vuint16*)(address), value)
#define out32rb(address, value) m68k_out32_reverse((vuint32*)(address), value)
#define in8rb(address) m68k_in8((const vuint8*)(address))
#define in16rb(address) m68k_in16_reverse((const vuint16*)(address))
#define in32rb(address) m68k_in32_reverse((const vuint32*)(address))
static int m68k_atari_enable_config(struct m68k_atari_host_bridge *bridge,
uint8 bus, uint8 slot, uint8 function, uint8 offset);
static status_t m68k_atari_read_pci_config(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 offset, uint8 size, uint32 *value);
static status_t m68k_atari_write_pci_config(void *cookie, uint8 bus,
uint8 device, uint8 function, uint8 offset, uint8 size,
uint32 value);
static status_t m68k_atari_get_max_bus_devices(void *cookie, int32 *count);
static status_t m68k_atari_read_pci_irq(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 pin, uint8 *irq);
static status_t m68k_atari_write_pci_irq(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 pin, uint8 irq);
static pci_controller sM68kAtariPCIController = {
m68k_atari_read_pci_config,
m68k_atari_write_pci_config,
m68k_atari_get_max_bus_devices,
m68k_atari_read_pci_irq,
m68k_atari_write_pci_irq,
};
static status_t
m68k_atari_read_pci_config(void *cookie, uint8 bus, uint8 device, uint8 function,
uint8 offset, uint8 size, uint32 *value)
{
struct fake_pci_device *devices = (struct fake_pci_device *)cookie;
struct fake_pci_device *dev;
if (bus != 0)
return EINVAL;
if (device >= FAKE_DEVICES_COUNT)
return EINVAL;
if (function != 0)
return EINVAL;
dev = &devices[device];
#define O(pn,n,s) \
case pn: \
if (size != s) { \
panic("invalid pci config size %d for offset %d", size, offset); \
return EINVAL; \
*value = dev->n; \
return B_OK
if (1) {
switch (offset) {
O(PCI_vendor_id, vendor_id, 2);
O(PCI_device_id, device_id, 2);
O(PCI_revision, revision, 1);
O(PCI_class_api, class_api, 1);
O(PCI_class_sub, class_sub, 1);
O(PCI_class_base, class_base, 1);
O(PCI_line_size, line_size, 1);
O(PCI_latency, latency, 1);
O(PCI_header_type, header_type, 1);
O(PCI_bist, bist, 1);
}
}
//#undef O
#if 0
#define PCI_command 0x04 /* (2 byte) command */
#define PCI_status 0x06 /* (2 byte) status */
#endif
if (dev->header_type == 0x00 || dev->header_type == 0x01) {
switch (offset) {
case PCI_base_registers:
return EINVAL;
O(PCI_interrupt_line, h0.interrupt_line, 1);
O(PCI_interrupt_pin, h0.interrupt_pin, 1);
default:
break;
}
if (dev->header_type == 0x00) {
switch (offset) {
default:
break;
}
if (dev->header_type == 0x01) {
switch (offset) {
O(PCI_primary_bus, h1.primary_bus, 1);
O(PCI_secondary_bus, h1.secondary_bus, 1);
O(PCI_subordinate_bus, h1.subordinate_bus, 1);
O(PCI_secondary_latency, h1.secondary_latency, 1);
default:
break;
}
*value = 0xffffffff;
panic("invalid pci config offset %d", offset);
return EINVAL;
//return B_OK;
}
static status_t m68k_atari_write_pci_config(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 offset, uint8 size, uint32 value)
{
#if 0
if (m68k_atari_enable_config(bridge, bus, device, function, offset)) {
switch (size) {
case 1:
out8rb(caoff, (uint8)value);
(void)in8rb(caoff);
break;
case 2:
out16rb(caoff, (uint16)value);
(void)in16rb(caoff);
break;
case 4:
out32rb(caoff, value);
(void)in32rb(caoff);
break;
}
}
#endif
panic("write pci config dev %d offset %d", device, offset);
return B_OK;
}
static status_t m68k_atari_get_max_bus_devices(void *cookie, int32 *count)
{
*count = 32;
return B_OK;
}
static status_t m68k_atari_read_pci_irq(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 pin, uint8 *irq)
{
return B_ERROR;
}
static status_t m68k_atari_write_pci_irq(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 pin, uint8 irq)
{
return B_ERROR;
}
// #pragma mark -
static int
m68k_atari_enable_config(struct m68k_atari_host_bridge *bridge, uint8 bus,
uint8 slot, uint8 function, uint8 offset)
{
// uint32 pass;
// if (resource_int_value(device_get_name(sc->sc_dev),
// device_get_unit(sc->sc_dev), "skipslot", &pass) == 0) {
// if (pass == slot)
// return (0);
// }
uint32 cfgval;
if (bridge->bus == bus) {
/*
* No slots less than 11 on the primary bus
*/
if (slot < 11)
return (0);
cfgval = (1 << slot) | (function << 8) | (offset & 0xfc);
} else {
cfgval = (bus << 16) | (slot << 11) | (function << 8) |
(offset & 0xfc) | 1;
}
do {
out32rb(bridge->address_registers, cfgval);
} while (in32rb(bridge->address_registers) != cfgval);
return (1);
}
// #pragma mark -
status_t
m68k_atari_pci_controller_init(void)
{
status_t error = pci_controller_add(&sM68kAtariPCIController, /*cookie*/);
/* if (error != B_OK)
free(bridge);*/
return error;
}
// #pragma mark - support functions

View File

@ -0,0 +1,13 @@
/*
* Copyright 2007, François Revol <revol@free.fr>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef PCI_BUS_MANAGER_M68K_ATARI_H
#define PCI_BUS_MANAGER_M68K_ATARI_H
#include <SupportDefs.h>
status_t m68k_atari_pci_controller_init(void);
#endif // PCI_BUS_MANAGER_M68K_ATARI_H

View File

@ -0,0 +1,50 @@
/*
* Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef PCI_BUS_MANAGER_PPC_OPEN_FIRMWARE_PRIV_H
#define PCI_BUS_MANAGER_PPC_OPEN_FIRMWARE_PRIV_H
#include <stdlib.h>
#include <string.h>
#include <SupportDefs.h>
struct StringArrayPropertyValue;
// implementations
status_t ppc_openfirmware_probe_uninorth(int deviceNode,
const StringArrayPropertyValue &compatibleValue);
// property support
struct PropertyValue {
PropertyValue()
: value(NULL)
{
}
~PropertyValue()
{
free(value);
}
char *value;
int length;
};
struct StringArrayPropertyValue : PropertyValue {
char *NextElement(int &cookie) const;
bool ContainsElement(const char *value) const;
};
status_t openfirmware_get_property(int package, const char *propertyName,
PropertyValue &value);
#endif // PCI_BUS_MANAGER_PPC_OPEN_FIRMWARE_PRIV_H

View File

@ -0,0 +1,284 @@
/*
* Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
/*-
* Copyright (C) 2002 Benno Rice.
* 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 Benno Rice ``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 TOOLS GMBH 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.
*
* $FreeBSD$
*/
#include <stdlib.h>
#include <string.h>
#include <KernelExport.h>
#include <platform/openfirmware/devices.h>
#include <platform/openfirmware/openfirmware.h>
#include <platform/openfirmware/pci.h>
#include "pci_controller.h"
#include "pci_io.h"
#include "pci_openfirmware_priv.h"
struct uninorth_range {
uint32 pci_hi;
uint32 pci_mid;
uint32 pci_lo;
uint32 host;
uint32 size_hi;
uint32 size_lo;
};
struct uninorth_host_bridge {
int device_node;
addr_t address_registers;
addr_t data_registers;
uint32 bus;
struct uninorth_range ranges[6];
int range_count;
};
#define out8rb(address, value) ppc_out8((vuint8*)(address), value)
#define out16rb(address, value) ppc_out16_reverse((vuint16*)(address), value)
#define out32rb(address, value) ppc_out32_reverse((vuint32*)(address), value)
#define in8rb(address) ppc_in8((const vuint8*)(address))
#define in16rb(address) ppc_in16_reverse((const vuint16*)(address))
#define in32rb(address) ppc_in32_reverse((const vuint32*)(address))
static int uninorth_enable_config(struct uninorth_host_bridge *bridge,
uint8 bus, uint8 slot, uint8 function, uint8 offset);
static status_t uninorth_read_pci_config(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 offset, uint8 size, uint32 *value);
static status_t uninorth_write_pci_config(void *cookie, uint8 bus,
uint8 device, uint8 function, uint8 offset, uint8 size,
uint32 value);
static status_t uninorth_get_max_bus_devices(void *cookie, int32 *count);
static status_t uninorth_read_pci_irq(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 pin, uint8 *irq);
static status_t uninorth_write_pci_irq(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 pin, uint8 irq);
static pci_controller sUniNorthPCIController = {
uninorth_read_pci_config,
uninorth_write_pci_config,
uninorth_get_max_bus_devices,
uninorth_read_pci_irq,
uninorth_write_pci_irq,
};
static status_t
uninorth_read_pci_config(void *cookie, uint8 bus, uint8 device, uint8 function,
uint8 offset, uint8 size, uint32 *value)
{
uninorth_host_bridge *bridge = (uninorth_host_bridge*)cookie;
addr_t caoff = bridge->data_registers + (offset & 0x07);
if (uninorth_enable_config(bridge, bus, device, function, offset) != 0) {
switch (size) {
case 1:
*value = in8rb(caoff);
break;
case 2:
*value = in16rb(caoff);
break;
case 4:
*value = in32rb(caoff);
break;
default:
*value = 0xffffffff;
break;
}
} else
*value = 0xffffffff;
return B_OK;
}
static status_t uninorth_write_pci_config(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 offset, uint8 size, uint32 value)
{
uninorth_host_bridge *bridge = (uninorth_host_bridge*)cookie;
addr_t caoff = bridge->data_registers + (offset & 0x07);
if (uninorth_enable_config(bridge, bus, device, function, offset)) {
switch (size) {
case 1:
out8rb(caoff, (uint8)value);
(void)in8rb(caoff);
break;
case 2:
out16rb(caoff, (uint16)value);
(void)in16rb(caoff);
break;
case 4:
out32rb(caoff, value);
(void)in32rb(caoff);
break;
}
}
return B_OK;
}
static status_t uninorth_get_max_bus_devices(void *cookie, int32 *count)
{
*count = 32;
return B_OK;
}
static status_t uninorth_read_pci_irq(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 pin, uint8 *irq)
{
return B_ERROR;
}
static status_t uninorth_write_pci_irq(void *cookie, uint8 bus, uint8 device,
uint8 function, uint8 pin, uint8 irq)
{
return B_ERROR;
}
// #pragma mark -
static int
uninorth_enable_config(struct uninorth_host_bridge *bridge, uint8 bus,
uint8 slot, uint8 function, uint8 offset)
{
// uint32 pass;
// if (resource_int_value(device_get_name(sc->sc_dev),
// device_get_unit(sc->sc_dev), "skipslot", &pass) == 0) {
// if (pass == slot)
// return (0);
// }
uint32 cfgval;
if (bridge->bus == bus) {
/*
* No slots less than 11 on the primary bus
*/
if (slot < 11)
return (0);
cfgval = (1 << slot) | (function << 8) | (offset & 0xfc);
} else {
cfgval = (bus << 16) | (slot << 11) | (function << 8) |
(offset & 0xfc) | 1;
}
do {
out32rb(bridge->address_registers, cfgval);
} while (in32rb(bridge->address_registers) != cfgval);
return (1);
}
// #pragma mark -
status_t
ppc_openfirmware_probe_uninorth(int deviceNode,
const StringArrayPropertyValue &compatibleValue)
{
if (!compatibleValue.ContainsElement("uni-north"))
return B_ERROR;
uint32 reg[2];
if (of_getprop(deviceNode, "reg", reg, sizeof(reg)) < 8)
return B_ERROR;
uint32 busrange[2];
if (of_getprop(deviceNode, "bus-range", busrange, sizeof(busrange)) != 8)
return B_ERROR;
uninorth_host_bridge *bridge
= (uninorth_host_bridge*)malloc(sizeof(uninorth_host_bridge));
if (!bridge)
return B_NO_MEMORY;
bridge->device_node = deviceNode;
bridge->address_registers = reg[0] + 0x800000;
bridge->data_registers = reg[0] + 0xc00000;
bridge->bus = busrange[0];
// TODO: Check whether address and data registers have already been mapped by
// the Open Firmware. If not, map them ourselves.
memset(bridge->ranges, 0, sizeof(bridge->ranges));
int bytesRead = of_getprop(deviceNode, "ranges", bridge->ranges,
sizeof(bridge->ranges));
if (bytesRead < 0) {
dprintf("ppc_openfirmware_probe_uninorth: Could not get ranges.\n");
return B_ERROR;
}
bridge->range_count = bytesRead / sizeof(uninorth_range);
uninorth_range *ioRange = NULL;
uninorth_range *memoryRanges[2];
int memoryRangeCount = 0;
for (int i = 0; i < bridge->range_count; i++) {
uninorth_range *range = bridge->ranges + i;
switch (range->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
case OFW_PCI_PHYS_HI_SPACE_CONFIG:
break;
case OFW_PCI_PHYS_HI_SPACE_IO:
ioRange = range;
break;
case OFW_PCI_PHYS_HI_SPACE_MEM32:
memoryRanges[memoryRangeCount++] = range;
break;
case OFW_PCI_PHYS_HI_SPACE_MEM64:
break;
}
}
if (ioRange == NULL) {
dprintf("ppc_openfirmware_probe_uninorth: Can't find io range.\n");
return B_ERROR;
}
if (memoryRangeCount == 0) {
dprintf("ppc_openfirmware_probe_uninorth: Can't find mem ranges.\n");
return B_ERROR;
}
status_t error = pci_controller_add(&sUniNorthPCIController, bridge);
if (error != B_OK)
free(bridge);
return error;
}

View File

@ -0,0 +1,41 @@
#include "pci_controller.h"
#include <arch_platform.h>
#include "pci_priv.h"
/*
* As we don't have any real PCI bus in any of the supported m68k platforms,
* we fake one, with hardcoded devices.
*/
#include "amiga/pci_amiga.h"
#include "apple/pci_apple.h"
#include "atari/pci_atari.h"
status_t
pci_controller_init(void)
{
switch (PPCPlatform::Default()->PlatformType()) {
/* case M68K_PLATFORM_AMIGA:
return m68k_amiga_pci_controller_init();
break;
case M68K_PLATFORM_APPLE:
return m68k_apple_pci_controller_init();
break;*/
case M68K_PLATFORM_ATARI:
return m68k_atari_pci_controller_init();
break;
default:
return EINVAL;
}
return B_OK;
}
void *
pci_ram_address(const void *physical_address_in_system_memory)
{
return (void *)physical_address_in_system_memory;
}

View File

@ -0,0 +1,50 @@
#include "pci_io.h"
#include "pci_priv.h"
status_t
pci_io_init()
{
return B_OK;
}
uint8
pci_read_io_8(int mapped_io_addr)
{
return m68k_in8((vuint8*)mapped_io_addr);
}
void
pci_write_io_8(int mapped_io_addr, uint8 value)
{
m68k_out8((vuint8*)mapped_io_addr, value);
}
uint16
pci_read_io_16(int mapped_io_addr)
{
return m68k_in16((vuint16*)mapped_io_addr);
}
void
pci_write_io_16(int mapped_io_addr, uint16 value)
{
m68k_out16((vuint16*)mapped_io_addr, value);
}
uint32
pci_read_io_32(int mapped_io_addr)
{
return m68k_in32((vuint32*)mapped_io_addr);
}
void
pci_write_io_32(int mapped_io_addr, uint32 value)
{
m68k_out32((vuint32*)mapped_io_addr, value);
}

View File

@ -0,0 +1,106 @@
/*
* Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef PCI_BUS_MANAGER_M68K_IO_H
#define PCI_BUS_MANAGER_M68K_IO_H
#include <SupportDefs.h>
#define IOBARRIER() asm volatile("nop") /* nop flushes the instruction pipeline */
/*XXX: sync cache/pmmu?*/
static inline void
m68k_out8(vuint8 *address, uint8 value)
{
*address = value;
IOBARRIER();
}
static inline void
m68k_out16(vuint16 *address, uint16 value)
{
*address = value;
IOBARRIER();
}
#if _XXX_HAS_REVERSE_IO
static inline void
m68k_out16_reverse(vuint16 *address, uint16 value)
{
asm volatile("sthbrx %1, 0, %0" : : "r"(address), "r"(value));
IOBARRIER();
}
#endif
static inline void
m68k_out32(vuint32 *address, uint32 value)
{
*address = value;
IOBARRIER();
}
#if _XXX_HAS_REVERSE_IO
static inline void
m68k_out32_reverse(vuint32 *address, uint32 value)
{
asm volatile("stwbrx %1, 0, %0" : : "r"(address), "r"(value));
IOBARRIER();
}
#endif
static inline uint8
m68k_in8(const vuint8 *address)
{
uint8 value = *address;
IOBARRIER();
return value;
}
static inline uint16
m68k_in16(const vuint16 *address)
{
uint16 value = *address;
IOBARRIER();
return value;
}
#if _XXX_HAS_REVERSE_IO
static inline uint16
m68k_in16_reverse(const vuint16 *address)
{
uint16 value;
asm volatile("lhbrx %0, 0, %1" : "=r"(value) : "r"(address));
IOBARRIER();
return value;
}
#endif
static inline uint32
m68k_in32(const vuint32 *address)
{
uint32 value = *address;
IOBARRIER();
return value;
}
#if _XXX_HAS_REVERSE_IO
static inline uint32
m68k_in32_reverse(const vuint32 *address)
{
uint32 value;
asm volatile("lwbrx %0, 0, %1" : "=r"(value) : "r"(address));
IOBARRIER();
return value;
}
#endif
#endif // PCI_BUS_MANAGER_M68K_IO_H