Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC64]: Fix show_stack() when stack argument is NULL. [SPARC]: Fix serial console node string creation. [SPARC]: Mark SBUS framebuffer ioctls as IGNORE in compat_ioctl.c [SPARC64]: asm-sparc64/floppy.h needs linux/pci.h [SPARC64]: Fix conflicts in SBUS/PCI/EBUS/ISA DMA handling. [VIDEO]: Fix OOPS in all SBUS framebuffer drivers. [SPARC64]: Handle mostek clock type in mini_rtc driver. [PARTITION]: Sun/Solaris VTOC table corrections [SPARC]: Fix floppy on some sun4c systems. [SPARC64]: Fix sun4u PCI config space accesses on sun4u. [PARTITION] MSDOS: Fix Sun num_partitions handling. [SPARC]: Update defconfig.
This commit is contained in:
commit
9c837fb692
41 changed files with 1602 additions and 2103 deletions
|
@ -1,12 +1,14 @@
|
|||
#
|
||||
# Automatically generated make config: don't edit
|
||||
# Linux kernel version: 2.6.22-rc1
|
||||
# Mon May 14 03:25:14 2007
|
||||
# Linux kernel version: 2.6.23-rc1
|
||||
# Wed Jul 25 15:30:21 2007
|
||||
#
|
||||
CONFIG_MMU=y
|
||||
CONFIG_HIGHMEM=y
|
||||
CONFIG_ZONE_DMA=y
|
||||
CONFIG_GENERIC_ISA_DMA=y
|
||||
CONFIG_ARCH_NO_VIRT_TO_BUS=y
|
||||
CONFIG_OF=y
|
||||
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
|
||||
|
||||
#
|
||||
|
@ -23,12 +25,11 @@ CONFIG_LOCALVERSION=""
|
|||
CONFIG_LOCALVERSION_AUTO=y
|
||||
CONFIG_SWAP=y
|
||||
CONFIG_SYSVIPC=y
|
||||
# CONFIG_IPC_NS is not set
|
||||
CONFIG_SYSVIPC_SYSCTL=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
||||
# CONFIG_TASKSTATS is not set
|
||||
# CONFIG_UTS_NS is not set
|
||||
# CONFIG_USER_NS is not set
|
||||
# CONFIG_AUDIT is not set
|
||||
# CONFIG_IKCONFIG is not set
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
|
@ -63,24 +64,17 @@ CONFIG_SLAB=y
|
|||
CONFIG_RT_MUTEXES=y
|
||||
# CONFIG_TINY_SHMEM is not set
|
||||
CONFIG_BASE_SMALL=0
|
||||
|
||||
#
|
||||
# Loadable module support
|
||||
#
|
||||
CONFIG_MODULES=y
|
||||
CONFIG_MODULE_UNLOAD=y
|
||||
# CONFIG_MODULE_FORCE_UNLOAD is not set
|
||||
# CONFIG_MODVERSIONS is not set
|
||||
# CONFIG_MODULE_SRCVERSION_ALL is not set
|
||||
CONFIG_KMOD=y
|
||||
|
||||
#
|
||||
# Block layer
|
||||
#
|
||||
CONFIG_BLOCK=y
|
||||
# CONFIG_LBD is not set
|
||||
# CONFIG_BLK_DEV_IO_TRACE is not set
|
||||
# CONFIG_LSF is not set
|
||||
# CONFIG_BLK_DEV_BSG is not set
|
||||
|
||||
#
|
||||
# IO Schedulers
|
||||
|
@ -113,11 +107,14 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
|
|||
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
|
||||
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
|
||||
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
||||
CONFIG_EMULATED_CMPXCHG=y
|
||||
CONFIG_SUN_PM=y
|
||||
# CONFIG_SUN4 is not set
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_SYSCALL=y
|
||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
||||
# CONFIG_PCI_DEBUG is not set
|
||||
# CONFIG_NO_DMA is not set
|
||||
CONFIG_SUN_OPENPROMFS=m
|
||||
# CONFIG_SPARC_LED is not set
|
||||
CONFIG_BINFMT_ELF=y
|
||||
|
@ -134,6 +131,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
|
|||
CONFIG_SPLIT_PTLOCK_CPUS=4
|
||||
# CONFIG_RESOURCES_64BIT is not set
|
||||
CONFIG_ZONE_DMA_FLAG=1
|
||||
CONFIG_BOUNCE=y
|
||||
|
||||
#
|
||||
# Networking
|
||||
|
@ -197,25 +195,13 @@ CONFIG_IPV6_TUNNEL=m
|
|||
# CONFIG_IPV6_MULTIPLE_TABLES is not set
|
||||
# CONFIG_NETWORK_SECMARK is not set
|
||||
# CONFIG_NETFILTER is not set
|
||||
|
||||
#
|
||||
# DCCP Configuration (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_IP_DCCP is not set
|
||||
|
||||
#
|
||||
# SCTP Configuration (EXPERIMENTAL)
|
||||
#
|
||||
CONFIG_IP_SCTP=m
|
||||
# CONFIG_SCTP_DBG_MSG is not set
|
||||
CONFIG_SCTP_DBG_OBJCNT=y
|
||||
# CONFIG_SCTP_HMAC_NONE is not set
|
||||
# CONFIG_SCTP_HMAC_SHA1 is not set
|
||||
CONFIG_SCTP_HMAC_MD5=y
|
||||
|
||||
#
|
||||
# TIPC Configuration (EXPERIMENTAL)
|
||||
#
|
||||
# CONFIG_TIPC is not set
|
||||
# CONFIG_ATM is not set
|
||||
# CONFIG_BRIDGE is not set
|
||||
|
@ -253,6 +239,7 @@ CONFIG_AF_RXRPC=m
|
|||
# CONFIG_MAC80211 is not set
|
||||
# CONFIG_IEEE80211 is not set
|
||||
# CONFIG_RFKILL is not set
|
||||
# CONFIG_NET_9P is not set
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
|
@ -267,28 +254,12 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
|
|||
# CONFIG_DEBUG_DRIVER is not set
|
||||
# CONFIG_DEBUG_DEVRES is not set
|
||||
# CONFIG_SYS_HYPERVISOR is not set
|
||||
|
||||
#
|
||||
# Connector - unified userspace <-> kernelspace linker
|
||||
#
|
||||
# CONFIG_CONNECTOR is not set
|
||||
# CONFIG_MTD is not set
|
||||
|
||||
#
|
||||
# Parallel port support
|
||||
#
|
||||
CONFIG_OF_DEVICE=y
|
||||
# CONFIG_PARPORT is not set
|
||||
|
||||
#
|
||||
# Plug and Play support
|
||||
#
|
||||
# CONFIG_PNPACPI is not set
|
||||
|
||||
#
|
||||
# Block devices
|
||||
#
|
||||
CONFIG_BLK_DEV=y
|
||||
# CONFIG_BLK_DEV_FD is not set
|
||||
# CONFIG_BLK_CPQ_DA is not set
|
||||
# CONFIG_BLK_CPQ_CISS_DA is not set
|
||||
# CONFIG_BLK_DEV_DAC960 is not set
|
||||
# CONFIG_BLK_DEV_UMEM is not set
|
||||
|
@ -303,18 +274,11 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
|
|||
CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
|
||||
# CONFIG_CDROM_PKTCDVD is not set
|
||||
# CONFIG_ATA_OVER_ETH is not set
|
||||
|
||||
#
|
||||
# Misc devices
|
||||
#
|
||||
CONFIG_MISC_DEVICES=y
|
||||
# CONFIG_PHANTOM is not set
|
||||
# CONFIG_EEPROM_93CX6 is not set
|
||||
# CONFIG_SGI_IOC4 is not set
|
||||
# CONFIG_TIFM_CORE is not set
|
||||
# CONFIG_BLINK is not set
|
||||
|
||||
#
|
||||
# ATA/ATAPI/MFM/RLL support
|
||||
#
|
||||
# CONFIG_IDE is not set
|
||||
|
||||
#
|
||||
|
@ -322,6 +286,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
|
|||
#
|
||||
# CONFIG_RAID_ATTRS is not set
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_SCSI_DMA=y
|
||||
# CONFIG_SCSI_TGT is not set
|
||||
# CONFIG_SCSI_NETLINK is not set
|
||||
CONFIG_SCSI_PROC_FS=y
|
||||
|
@ -352,12 +317,8 @@ CONFIG_SCSI_WAIT_SCAN=m
|
|||
CONFIG_SCSI_SPI_ATTRS=y
|
||||
# CONFIG_SCSI_FC_ATTRS is not set
|
||||
# CONFIG_SCSI_ISCSI_ATTRS is not set
|
||||
# CONFIG_SCSI_SAS_ATTRS is not set
|
||||
# CONFIG_SCSI_SAS_LIBSAS is not set
|
||||
|
||||
#
|
||||
# SCSI low-level drivers
|
||||
#
|
||||
CONFIG_SCSI_LOWLEVEL=y
|
||||
# CONFIG_ISCSI_TCP is not set
|
||||
# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
|
||||
# CONFIG_SCSI_3W_9XXX is not set
|
||||
|
@ -367,7 +328,6 @@ CONFIG_SCSI_SPI_ATTRS=y
|
|||
# CONFIG_SCSI_AIC7XXX_OLD is not set
|
||||
# CONFIG_SCSI_AIC79XX is not set
|
||||
# CONFIG_SCSI_AIC94XX is not set
|
||||
# CONFIG_SCSI_DPT_I2O is not set
|
||||
# CONFIG_SCSI_ARCMSR is not set
|
||||
# CONFIG_MEGARAID_NEWGEN is not set
|
||||
# CONFIG_MEGARAID_LEGACY is not set
|
||||
|
@ -389,14 +349,9 @@ CONFIG_SCSI_QLOGICPTI=m
|
|||
# CONFIG_SCSI_DC390T is not set
|
||||
# CONFIG_SCSI_NSP32 is not set
|
||||
# CONFIG_SCSI_DEBUG is not set
|
||||
CONFIG_SCSI_ESP_CORE=y
|
||||
CONFIG_SCSI_SUNESP=y
|
||||
# CONFIG_SCSI_SRP is not set
|
||||
# CONFIG_ATA is not set
|
||||
|
||||
#
|
||||
# Multi-device support (RAID and LVM)
|
||||
#
|
||||
# CONFIG_MD is not set
|
||||
|
||||
#
|
||||
|
@ -412,30 +367,16 @@ CONFIG_SCSI_SUNESP=y
|
|||
#
|
||||
# CONFIG_FIREWIRE is not set
|
||||
# CONFIG_IEEE1394 is not set
|
||||
|
||||
#
|
||||
# I2O device support
|
||||
#
|
||||
# CONFIG_I2O is not set
|
||||
|
||||
#
|
||||
# Network device support
|
||||
#
|
||||
CONFIG_NETDEVICES=y
|
||||
# CONFIG_NETDEVICES_MULTIQUEUE is not set
|
||||
CONFIG_DUMMY=m
|
||||
# CONFIG_BONDING is not set
|
||||
# CONFIG_MACVLAN is not set
|
||||
# CONFIG_EQUALIZER is not set
|
||||
CONFIG_TUN=m
|
||||
|
||||
#
|
||||
# ARCnet devices
|
||||
#
|
||||
# CONFIG_ARCNET is not set
|
||||
# CONFIG_PHYLIB is not set
|
||||
|
||||
#
|
||||
# Ethernet (10 or 100Mbit)
|
||||
#
|
||||
CONFIG_NET_ETHERNET=y
|
||||
CONFIG_MII=m
|
||||
CONFIG_SUNLANCE=y
|
||||
|
@ -445,10 +386,6 @@ CONFIG_SUNQE=m
|
|||
# CONFIG_SUNGEM is not set
|
||||
# CONFIG_CASSINI is not set
|
||||
# CONFIG_NET_VENDOR_3COM is not set
|
||||
|
||||
#
|
||||
# Tulip family network device support
|
||||
#
|
||||
# CONFIG_NET_TULIP is not set
|
||||
# CONFIG_HP100 is not set
|
||||
# CONFIG_NET_PCI is not set
|
||||
|
@ -464,7 +401,7 @@ CONFIG_NETDEV_1000=y
|
|||
# CONFIG_SIS190 is not set
|
||||
# CONFIG_SKGE is not set
|
||||
# CONFIG_SKY2 is not set
|
||||
# CONFIG_SK98LIN is not set
|
||||
# CONFIG_VIA_VELOCITY is not set
|
||||
# CONFIG_TIGON3 is not set
|
||||
# CONFIG_BNX2 is not set
|
||||
# CONFIG_QLA3XXX is not set
|
||||
|
@ -477,11 +414,6 @@ CONFIG_NETDEV_10000=y
|
|||
# CONFIG_MYRI10GE is not set
|
||||
# CONFIG_NETXEN_NIC is not set
|
||||
# CONFIG_MLX4_CORE is not set
|
||||
CONFIG_MLX4_DEBUG=y
|
||||
|
||||
#
|
||||
# Token Ring devices
|
||||
#
|
||||
# CONFIG_TR is not set
|
||||
|
||||
#
|
||||
|
@ -499,15 +431,7 @@ CONFIG_MLX4_DEBUG=y
|
|||
# CONFIG_NETCONSOLE is not set
|
||||
# CONFIG_NETPOLL is not set
|
||||
# CONFIG_NET_POLL_CONTROLLER is not set
|
||||
|
||||
#
|
||||
# ISDN subsystem
|
||||
#
|
||||
# CONFIG_ISDN is not set
|
||||
|
||||
#
|
||||
# Telephony Support
|
||||
#
|
||||
# CONFIG_PHONE is not set
|
||||
|
||||
#
|
||||
|
@ -515,6 +439,7 @@ CONFIG_MLX4_DEBUG=y
|
|||
#
|
||||
CONFIG_INPUT=y
|
||||
# CONFIG_INPUT_FF_MEMLESS is not set
|
||||
# CONFIG_INPUT_POLLDEV is not set
|
||||
|
||||
#
|
||||
# Userland interfaces
|
||||
|
@ -593,22 +518,13 @@ CONFIG_SERIAL_CORE_CONSOLE=y
|
|||
CONFIG_UNIX98_PTYS=y
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=256
|
||||
|
||||
#
|
||||
# IPMI
|
||||
#
|
||||
# CONFIG_IPMI_HANDLER is not set
|
||||
# CONFIG_WATCHDOG is not set
|
||||
CONFIG_HW_RANDOM=m
|
||||
CONFIG_JS_RTC=m
|
||||
# CONFIG_R3964 is not set
|
||||
# CONFIG_APPLICOM is not set
|
||||
# CONFIG_DRM is not set
|
||||
# CONFIG_RAW_DRIVER is not set
|
||||
|
||||
#
|
||||
# TPM devices
|
||||
#
|
||||
# CONFIG_TCG_TPM is not set
|
||||
CONFIG_DEVPORT=y
|
||||
# CONFIG_I2C is not set
|
||||
|
@ -618,20 +534,24 @@ CONFIG_DEVPORT=y
|
|||
#
|
||||
# CONFIG_SPI is not set
|
||||
# CONFIG_SPI_MASTER is not set
|
||||
|
||||
#
|
||||
# Dallas's 1-wire bus
|
||||
#
|
||||
# CONFIG_W1 is not set
|
||||
# CONFIG_POWER_SUPPLY is not set
|
||||
CONFIG_HWMON=y
|
||||
# CONFIG_HWMON_VID is not set
|
||||
# CONFIG_SENSORS_ABITUGURU is not set
|
||||
# CONFIG_SENSORS_ABITUGURU3 is not set
|
||||
# CONFIG_SENSORS_F71805F is not set
|
||||
# CONFIG_SENSORS_IT87 is not set
|
||||
# CONFIG_SENSORS_PC87360 is not set
|
||||
# CONFIG_SENSORS_PC87427 is not set
|
||||
# CONFIG_SENSORS_SIS5595 is not set
|
||||
# CONFIG_SENSORS_SMSC47M1 is not set
|
||||
# CONFIG_SENSORS_SMSC47B397 is not set
|
||||
# CONFIG_SENSORS_VIA686A is not set
|
||||
# CONFIG_SENSORS_VT1211 is not set
|
||||
# CONFIG_SENSORS_VT8231 is not set
|
||||
# CONFIG_SENSORS_W83627HF is not set
|
||||
# CONFIG_SENSORS_W83627EHF is not set
|
||||
# CONFIG_HWMON_DEBUG_CHIP is not set
|
||||
|
||||
#
|
||||
|
@ -656,6 +576,7 @@ CONFIG_HWMON=y
|
|||
#
|
||||
# CONFIG_DISPLAY_SUPPORT is not set
|
||||
# CONFIG_VGASTATE is not set
|
||||
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
|
||||
# CONFIG_FB is not set
|
||||
|
||||
#
|
||||
|
@ -668,16 +589,10 @@ CONFIG_DUMMY_CONSOLE=y
|
|||
# Sound
|
||||
#
|
||||
# CONFIG_SOUND is not set
|
||||
|
||||
#
|
||||
# HID Devices
|
||||
#
|
||||
CONFIG_HID_SUPPORT=y
|
||||
CONFIG_HID=y
|
||||
# CONFIG_HID_DEBUG is not set
|
||||
|
||||
#
|
||||
# USB support
|
||||
#
|
||||
CONFIG_USB_SUPPORT=y
|
||||
CONFIG_USB_ARCH_HAS_HCD=y
|
||||
CONFIG_USB_ARCH_HAS_OHCI=y
|
||||
CONFIG_USB_ARCH_HAS_EHCI=y
|
||||
|
@ -692,29 +607,9 @@ CONFIG_USB_ARCH_HAS_EHCI=y
|
|||
#
|
||||
# CONFIG_USB_GADGET is not set
|
||||
# CONFIG_MMC is not set
|
||||
|
||||
#
|
||||
# LED devices
|
||||
#
|
||||
# CONFIG_NEW_LEDS is not set
|
||||
|
||||
#
|
||||
# LED drivers
|
||||
#
|
||||
|
||||
#
|
||||
# LED Triggers
|
||||
#
|
||||
|
||||
#
|
||||
# InfiniBand support
|
||||
#
|
||||
# CONFIG_INFINIBAND is not set
|
||||
|
||||
#
|
||||
# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
|
||||
#
|
||||
|
||||
#
|
||||
# Real Time Clock
|
||||
#
|
||||
|
@ -733,6 +628,11 @@ CONFIG_USB_ARCH_HAS_EHCI=y
|
|||
# DMA Devices
|
||||
#
|
||||
|
||||
#
|
||||
# Userspace I/O
|
||||
#
|
||||
# CONFIG_UIO is not set
|
||||
|
||||
#
|
||||
# Misc Linux/SPARC drivers
|
||||
#
|
||||
|
@ -853,7 +753,6 @@ CONFIG_CIFS=m
|
|||
# CONFIG_CODA_FS is not set
|
||||
CONFIG_AFS_FS=m
|
||||
# CONFIG_AFS_DEBUG is not set
|
||||
# CONFIG_9P_FS is not set
|
||||
|
||||
#
|
||||
# Partition Types
|
||||
|
@ -927,6 +826,7 @@ CONFIG_MAGIC_SYSRQ=y
|
|||
# CONFIG_HEADERS_CHECK is not set
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_DETECT_SOFTLOCKUP=y
|
||||
# CONFIG_SCHED_DEBUG is not set
|
||||
# CONFIG_SCHEDSTATS is not set
|
||||
# CONFIG_TIMER_STATS is not set
|
||||
# CONFIG_DEBUG_SLAB is not set
|
||||
|
@ -953,10 +853,6 @@ CONFIG_FORCED_INLINING=y
|
|||
CONFIG_KEYS=y
|
||||
# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
|
||||
# CONFIG_SECURITY is not set
|
||||
|
||||
#
|
||||
# Cryptographic options
|
||||
#
|
||||
CONFIG_CRYPTO=y
|
||||
CONFIG_CRYPTO_ALGAPI=y
|
||||
CONFIG_CRYPTO_BLKCIPHER=y
|
||||
|
@ -996,10 +892,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=m
|
|||
CONFIG_CRYPTO_CRC32C=m
|
||||
# CONFIG_CRYPTO_CAMELLIA is not set
|
||||
# CONFIG_CRYPTO_TEST is not set
|
||||
|
||||
#
|
||||
# Hardware crypto devices
|
||||
#
|
||||
# CONFIG_CRYPTO_HW is not set
|
||||
|
||||
#
|
||||
# Library routines
|
||||
|
@ -1009,6 +902,7 @@ CONFIG_BITREVERSE=y
|
|||
# CONFIG_CRC16 is not set
|
||||
# CONFIG_CRC_ITU_T is not set
|
||||
CONFIG_CRC32=y
|
||||
# CONFIG_CRC7 is not set
|
||||
CONFIG_LIBCRC32C=m
|
||||
CONFIG_ZLIB_INFLATE=y
|
||||
CONFIG_ZLIB_DEFLATE=y
|
||||
|
|
|
@ -415,7 +415,7 @@ static void __init of_console_init(void)
|
|||
unsigned long flags;
|
||||
const char *type;
|
||||
phandle node;
|
||||
int skip, fd;
|
||||
int skip, tmp, fd;
|
||||
|
||||
of_console_path = prom_early_alloc(256);
|
||||
|
||||
|
@ -442,8 +442,9 @@ static void __init of_console_init(void)
|
|||
prom_halt();
|
||||
}
|
||||
|
||||
tmp = skip;
|
||||
for_each_node_by_type(dp, type) {
|
||||
if (!skip--)
|
||||
if (!tmp--)
|
||||
break;
|
||||
}
|
||||
if (!dp) {
|
||||
|
|
|
@ -8,14 +8,14 @@ EXTRA_CFLAGS := -Werror
|
|||
extra-y := head.o init_task.o vmlinux.lds
|
||||
|
||||
obj-y := process.o setup.o cpu.o idprom.o \
|
||||
traps.o auxio.o una_asm.o sysfs.o \
|
||||
traps.o auxio.o una_asm.o sysfs.o iommu.o \
|
||||
irq.o ptrace.o time.o sys_sparc.o signal.o \
|
||||
unaligned.o central.o pci.o starfire.o semaphore.o \
|
||||
power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
|
||||
visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
|
||||
|
||||
obj-$(CONFIG_STACKTRACE) += stacktrace.o
|
||||
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o pci_iommu.o \
|
||||
obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \
|
||||
pci_psycho.o pci_sabre.o pci_schizo.o \
|
||||
pci_sun4v.o pci_sun4v_asm.o pci_fire.o
|
||||
obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o
|
||||
|
|
|
@ -391,6 +391,8 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de
|
|||
sd = &dev->ofdev.dev.archdata;
|
||||
sd->prom_node = dp;
|
||||
sd->op = &dev->ofdev;
|
||||
sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu;
|
||||
sd->stc = dev->bus->ofdev.dev.parent->archdata.stc;
|
||||
|
||||
dev->ofdev.node = dp;
|
||||
dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
|
||||
|
|
|
@ -1,28 +1,32 @@
|
|||
/* pci_iommu.c: UltraSparc PCI controller IOM/STC support.
|
||||
/* iommu.c: Generic sparc64 IOMMU support.
|
||||
*
|
||||
* Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
|
||||
* Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <asm/oplib.h>
|
||||
#ifdef CONFIG_PCI
|
||||
#include <linux/pci.h>
|
||||
#endif
|
||||
|
||||
#include <asm/iommu.h>
|
||||
|
||||
#include "iommu_common.h"
|
||||
#include "pci_impl.h"
|
||||
|
||||
#define PCI_STC_CTXMATCH_ADDR(STC, CTX) \
|
||||
#define STC_CTXMATCH_ADDR(STC, CTX) \
|
||||
((STC)->strbuf_ctxmatch_base + ((CTX) << 3))
|
||||
#define STC_FLUSHFLAG_INIT(STC) \
|
||||
(*((STC)->strbuf_flushflag) = 0UL)
|
||||
#define STC_FLUSHFLAG_SET(STC) \
|
||||
(*((STC)->strbuf_flushflag) != 0UL)
|
||||
|
||||
/* Accessing IOMMU and Streaming Buffer registers.
|
||||
* REG parameter is a physical address. All registers
|
||||
* are 64-bits in size.
|
||||
*/
|
||||
#define pci_iommu_read(__reg) \
|
||||
#define iommu_read(__reg) \
|
||||
({ u64 __ret; \
|
||||
__asm__ __volatile__("ldxa [%1] %2, %0" \
|
||||
: "=r" (__ret) \
|
||||
|
@ -30,7 +34,7 @@
|
|||
: "memory"); \
|
||||
__ret; \
|
||||
})
|
||||
#define pci_iommu_write(__reg, __val) \
|
||||
#define iommu_write(__reg, __val) \
|
||||
__asm__ __volatile__("stxa %0, [%1] %2" \
|
||||
: /* no outputs */ \
|
||||
: "r" (__val), "r" (__reg), \
|
||||
|
@ -40,19 +44,19 @@
|
|||
static void __iommu_flushall(struct iommu *iommu)
|
||||
{
|
||||
if (iommu->iommu_flushinv) {
|
||||
pci_iommu_write(iommu->iommu_flushinv, ~(u64)0);
|
||||
iommu_write(iommu->iommu_flushinv, ~(u64)0);
|
||||
} else {
|
||||
unsigned long tag;
|
||||
int entry;
|
||||
|
||||
tag = iommu->iommu_flush + (0xa580UL - 0x0210UL);
|
||||
tag = iommu->iommu_tags;
|
||||
for (entry = 0; entry < 16; entry++) {
|
||||
pci_iommu_write(tag, 0);
|
||||
iommu_write(tag, 0);
|
||||
tag += 8;
|
||||
}
|
||||
|
||||
/* Ensure completion of previous PIO writes. */
|
||||
(void) pci_iommu_read(iommu->write_complete_reg);
|
||||
(void) iommu_read(iommu->write_complete_reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +84,7 @@ static inline void iopte_make_dummy(struct iommu *iommu, iopte_t *iopte)
|
|||
}
|
||||
|
||||
/* Based largely upon the ppc64 iommu allocator. */
|
||||
static long pci_arena_alloc(struct iommu *iommu, unsigned long npages)
|
||||
static long arena_alloc(struct iommu *iommu, unsigned long npages)
|
||||
{
|
||||
struct iommu_arena *arena = &iommu->arena;
|
||||
unsigned long n, i, start, end, limit;
|
||||
|
@ -121,7 +125,7 @@ static long pci_arena_alloc(struct iommu *iommu, unsigned long npages)
|
|||
return n;
|
||||
}
|
||||
|
||||
static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
|
||||
static void arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
|
@ -129,7 +133,8 @@ static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsign
|
|||
__clear_bit(i, arena->map);
|
||||
}
|
||||
|
||||
void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask)
|
||||
int iommu_table_init(struct iommu *iommu, int tsbsize,
|
||||
u32 dma_offset, u32 dma_addr_mask)
|
||||
{
|
||||
unsigned long i, tsbbase, order, sz, num_tsb_entries;
|
||||
|
||||
|
@ -146,8 +151,8 @@ void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32
|
|||
sz = (sz + 7UL) & ~7UL;
|
||||
iommu->arena.map = kzalloc(sz, GFP_KERNEL);
|
||||
if (!iommu->arena.map) {
|
||||
prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n");
|
||||
prom_halt();
|
||||
printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
iommu->arena.limit = num_tsb_entries;
|
||||
|
||||
|
@ -156,8 +161,8 @@ void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32
|
|||
*/
|
||||
iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
|
||||
if (!iommu->dummy_page) {
|
||||
prom_printf("PCI_IOMMU: Error, gfp(dummy_page) failed.\n");
|
||||
prom_halt();
|
||||
printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n");
|
||||
goto out_free_map;
|
||||
}
|
||||
memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
|
||||
iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
|
||||
|
@ -166,20 +171,32 @@ void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32
|
|||
order = get_order(tsbsize);
|
||||
tsbbase = __get_free_pages(GFP_KERNEL, order);
|
||||
if (!tsbbase) {
|
||||
prom_printf("PCI_IOMMU: Error, gfp(tsb) failed.\n");
|
||||
prom_halt();
|
||||
printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n");
|
||||
goto out_free_dummy_page;
|
||||
}
|
||||
iommu->page_table = (iopte_t *)tsbbase;
|
||||
|
||||
for (i = 0; i < num_tsb_entries; i++)
|
||||
iopte_make_dummy(iommu, &iommu->page_table[i]);
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_dummy_page:
|
||||
free_page(iommu->dummy_page);
|
||||
iommu->dummy_page = 0UL;
|
||||
|
||||
out_free_map:
|
||||
kfree(iommu->arena.map);
|
||||
iommu->arena.map = NULL;
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
|
||||
{
|
||||
long entry;
|
||||
|
||||
entry = pci_arena_alloc(iommu, npages);
|
||||
entry = arena_alloc(iommu, npages);
|
||||
if (unlikely(entry < 0))
|
||||
return NULL;
|
||||
|
||||
|
@ -188,7 +205,7 @@ static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
|
|||
|
||||
static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
|
||||
{
|
||||
pci_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
|
||||
arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
|
||||
}
|
||||
|
||||
static int iommu_alloc_ctx(struct iommu *iommu)
|
||||
|
@ -219,11 +236,8 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
|
|||
}
|
||||
}
|
||||
|
||||
/* Allocate and map kernel buffer of size SIZE using consistent mode
|
||||
* DMA for PCI device PDEV. Return non-NULL cpu-side address if
|
||||
* successful and set *DMA_ADDRP to the PCI side dma address.
|
||||
*/
|
||||
static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
|
||||
static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_addrp, gfp_t gfp)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
iopte_t *iopte;
|
||||
|
@ -241,7 +255,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
|
|||
return NULL;
|
||||
memset((char *)first_page, 0, PAGE_SIZE << order);
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
iommu = dev->archdata.iommu;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
|
||||
|
@ -268,15 +282,15 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Free and unmap a consistent DMA translation. */
|
||||
static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
|
||||
static void dma_4u_free_coherent(struct device *dev, size_t size,
|
||||
void *cpu, dma_addr_t dvma)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
iopte_t *iopte;
|
||||
unsigned long flags, order, npages;
|
||||
|
||||
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
iommu = dev->archdata.iommu;
|
||||
iopte = iommu->page_table +
|
||||
((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
|
||||
|
||||
|
@ -291,10 +305,8 @@ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
|
|||
free_pages((unsigned long)cpu, order);
|
||||
}
|
||||
|
||||
/* Map a single buffer at PTR of SZ bytes for PCI DMA
|
||||
* in streaming mode.
|
||||
*/
|
||||
static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
|
||||
static dma_addr_t dma_4u_map_single(struct device *dev, void *ptr, size_t sz,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
|
@ -304,10 +316,10 @@ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
|
|||
u32 bus_addr, ret;
|
||||
unsigned long iopte_protection;
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
strbuf = pdev->dev.archdata.stc;
|
||||
iommu = dev->archdata.iommu;
|
||||
strbuf = dev->archdata.stc;
|
||||
|
||||
if (unlikely(direction == PCI_DMA_NONE))
|
||||
if (unlikely(direction == DMA_NONE))
|
||||
goto bad_no_ctx;
|
||||
|
||||
oaddr = (unsigned long)ptr;
|
||||
|
@ -332,7 +344,7 @@ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
|
|||
iopte_protection = IOPTE_STREAMING(ctx);
|
||||
else
|
||||
iopte_protection = IOPTE_CONSISTENT(ctx);
|
||||
if (direction != PCI_DMA_TODEVICE)
|
||||
if (direction != DMA_TO_DEVICE)
|
||||
iopte_protection |= IOPTE_WRITE;
|
||||
|
||||
for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE)
|
||||
|
@ -345,10 +357,12 @@ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
|
|||
bad_no_ctx:
|
||||
if (printk_ratelimit())
|
||||
WARN_ON(1);
|
||||
return PCI_DMA_ERROR_CODE;
|
||||
return DMA_ERROR_CODE;
|
||||
}
|
||||
|
||||
static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction)
|
||||
static void strbuf_flush(struct strbuf *strbuf, struct iommu *iommu,
|
||||
u32 vaddr, unsigned long ctx, unsigned long npages,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
int limit;
|
||||
|
||||
|
@ -358,22 +372,22 @@ static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vad
|
|||
u64 val;
|
||||
|
||||
flushreg = strbuf->strbuf_ctxflush;
|
||||
matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
|
||||
matchreg = STC_CTXMATCH_ADDR(strbuf, ctx);
|
||||
|
||||
pci_iommu_write(flushreg, ctx);
|
||||
val = pci_iommu_read(matchreg);
|
||||
iommu_write(flushreg, ctx);
|
||||
val = iommu_read(matchreg);
|
||||
val &= 0xffff;
|
||||
if (!val)
|
||||
goto do_flush_sync;
|
||||
|
||||
while (val) {
|
||||
if (val & 0x1)
|
||||
pci_iommu_write(flushreg, ctx);
|
||||
iommu_write(flushreg, ctx);
|
||||
val >>= 1;
|
||||
}
|
||||
val = pci_iommu_read(matchreg);
|
||||
val = iommu_read(matchreg);
|
||||
if (unlikely(val)) {
|
||||
printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
|
||||
printk(KERN_WARNING "strbuf_flush: ctx flush "
|
||||
"timeout matchreg[%lx] ctx[%lx]\n",
|
||||
val, ctx);
|
||||
goto do_page_flush;
|
||||
|
@ -383,7 +397,7 @@ static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vad
|
|||
|
||||
do_page_flush:
|
||||
for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
|
||||
pci_iommu_write(strbuf->strbuf_pflush, vaddr);
|
||||
iommu_write(strbuf->strbuf_pflush, vaddr);
|
||||
}
|
||||
|
||||
do_flush_sync:
|
||||
|
@ -391,15 +405,15 @@ static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vad
|
|||
* the streaming cache, no flush-flag synchronization needs
|
||||
* to be performed.
|
||||
*/
|
||||
if (direction == PCI_DMA_TODEVICE)
|
||||
if (direction == DMA_TO_DEVICE)
|
||||
return;
|
||||
|
||||
PCI_STC_FLUSHFLAG_INIT(strbuf);
|
||||
pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
|
||||
(void) pci_iommu_read(iommu->write_complete_reg);
|
||||
STC_FLUSHFLAG_INIT(strbuf);
|
||||
iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
|
||||
(void) iommu_read(iommu->write_complete_reg);
|
||||
|
||||
limit = 100000;
|
||||
while (!PCI_STC_FLUSHFLAG_SET(strbuf)) {
|
||||
while (!STC_FLUSHFLAG_SET(strbuf)) {
|
||||
limit--;
|
||||
if (!limit)
|
||||
break;
|
||||
|
@ -407,37 +421,32 @@ static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vad
|
|||
rmb();
|
||||
}
|
||||
if (!limit)
|
||||
printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
|
||||
printk(KERN_WARNING "strbuf_flush: flushflag timeout "
|
||||
"vaddr[%08x] ctx[%lx] npages[%ld]\n",
|
||||
vaddr, ctx, npages);
|
||||
}
|
||||
|
||||
/* Unmap a single streaming mode DMA translation. */
|
||||
static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
|
||||
static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
|
||||
size_t sz, enum dma_data_direction direction)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
iopte_t *base;
|
||||
unsigned long flags, npages, ctx, i;
|
||||
|
||||
if (unlikely(direction == PCI_DMA_NONE)) {
|
||||
if (unlikely(direction == DMA_NONE)) {
|
||||
if (printk_ratelimit())
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
strbuf = pdev->dev.archdata.stc;
|
||||
iommu = dev->archdata.iommu;
|
||||
strbuf = dev->archdata.stc;
|
||||
|
||||
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
|
||||
npages >>= IO_PAGE_SHIFT;
|
||||
base = iommu->page_table +
|
||||
((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
|
||||
#ifdef DEBUG_PCI_IOMMU
|
||||
if (IOPTE_IS_DUMMY(iommu, base))
|
||||
printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n",
|
||||
bus_addr, sz, __builtin_return_address(0));
|
||||
#endif
|
||||
bus_addr &= IO_PAGE_MASK;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
@ -449,8 +458,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
|
|||
|
||||
/* Step 1: Kick data out of streaming buffers if necessary. */
|
||||
if (strbuf->strbuf_enabled)
|
||||
pci_strbuf_flush(strbuf, iommu, bus_addr, ctx,
|
||||
npages, direction);
|
||||
strbuf_flush(strbuf, iommu, bus_addr, ctx,
|
||||
npages, direction);
|
||||
|
||||
/* Step 2: Clear out TSB entries. */
|
||||
for (i = 0; i < npages; i++)
|
||||
|
@ -467,7 +476,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
|
|||
(__pa(page_address((SG)->page)) + (SG)->offset)
|
||||
|
||||
static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
|
||||
int nused, int nelems, unsigned long iopte_protection)
|
||||
int nused, int nelems,
|
||||
unsigned long iopte_protection)
|
||||
{
|
||||
struct scatterlist *dma_sg = sg;
|
||||
struct scatterlist *sg_end = sg + nelems;
|
||||
|
@ -539,12 +549,8 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
|
|||
}
|
||||
}
|
||||
|
||||
/* Map a set of buffers described by SGLIST with NELEMS array
|
||||
* elements in streaming mode for PCI DMA.
|
||||
* When making changes here, inspect the assembly output. I was having
|
||||
* hard time to keep this routine out of using stack slots for holding variables.
|
||||
*/
|
||||
static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
|
||||
static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
|
||||
int nelems, enum dma_data_direction direction)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
|
@ -557,19 +563,20 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
|
|||
/* Fast path single entry scatterlists. */
|
||||
if (nelems == 1) {
|
||||
sglist->dma_address =
|
||||
pci_4u_map_single(pdev,
|
||||
(page_address(sglist->page) + sglist->offset),
|
||||
dma_4u_map_single(dev,
|
||||
(page_address(sglist->page) +
|
||||
sglist->offset),
|
||||
sglist->length, direction);
|
||||
if (unlikely(sglist->dma_address == PCI_DMA_ERROR_CODE))
|
||||
if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
|
||||
return 0;
|
||||
sglist->dma_length = sglist->length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
strbuf = pdev->dev.archdata.stc;
|
||||
|
||||
if (unlikely(direction == PCI_DMA_NONE))
|
||||
iommu = dev->archdata.iommu;
|
||||
strbuf = dev->archdata.stc;
|
||||
|
||||
if (unlikely(direction == DMA_NONE))
|
||||
goto bad_no_ctx;
|
||||
|
||||
/* Step 1: Prepare scatter list. */
|
||||
|
@ -609,7 +616,7 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
|
|||
iopte_protection = IOPTE_STREAMING(ctx);
|
||||
else
|
||||
iopte_protection = IOPTE_CONSISTENT(ctx);
|
||||
if (direction != PCI_DMA_TODEVICE)
|
||||
if (direction != DMA_TO_DEVICE)
|
||||
iopte_protection |= IOPTE_WRITE;
|
||||
|
||||
fill_sg(base, sglist, used, nelems, iopte_protection);
|
||||
|
@ -628,8 +635,8 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Unmap a set of streaming mode DMA translations. */
|
||||
static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
|
||||
static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
|
||||
int nelems, enum dma_data_direction direction)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
|
@ -637,14 +644,14 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
|
|||
unsigned long flags, ctx, i, npages;
|
||||
u32 bus_addr;
|
||||
|
||||
if (unlikely(direction == PCI_DMA_NONE)) {
|
||||
if (unlikely(direction == DMA_NONE)) {
|
||||
if (printk_ratelimit())
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
strbuf = pdev->dev.archdata.stc;
|
||||
|
||||
iommu = dev->archdata.iommu;
|
||||
strbuf = dev->archdata.stc;
|
||||
|
||||
bus_addr = sglist->dma_address & IO_PAGE_MASK;
|
||||
|
||||
for (i = 1; i < nelems; i++)
|
||||
|
@ -657,11 +664,6 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
|
|||
base = iommu->page_table +
|
||||
((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
|
||||
|
||||
#ifdef DEBUG_PCI_IOMMU
|
||||
if (IOPTE_IS_DUMMY(iommu, base))
|
||||
printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", sglist->dma_address, nelems, __builtin_return_address(0));
|
||||
#endif
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
||||
/* Record the context, if any. */
|
||||
|
@ -671,7 +673,7 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
|
|||
|
||||
/* Step 1: Kick data out of streaming buffers if necessary. */
|
||||
if (strbuf->strbuf_enabled)
|
||||
pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
|
||||
strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
|
||||
|
||||
/* Step 2: Clear out the TSB entries. */
|
||||
for (i = 0; i < npages; i++)
|
||||
|
@ -684,17 +686,16 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
|
|||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
/* Make physical memory consistent for a single
|
||||
* streaming mode DMA translation after a transfer.
|
||||
*/
|
||||
static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
|
||||
static void dma_4u_sync_single_for_cpu(struct device *dev,
|
||||
dma_addr_t bus_addr, size_t sz,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
unsigned long flags, ctx, npages;
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
strbuf = pdev->dev.archdata.stc;
|
||||
iommu = dev->archdata.iommu;
|
||||
strbuf = dev->archdata.stc;
|
||||
|
||||
if (!strbuf->strbuf_enabled)
|
||||
return;
|
||||
|
@ -717,23 +718,22 @@ static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_
|
|||
}
|
||||
|
||||
/* Step 2: Kick data out of streaming buffers. */
|
||||
pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
|
||||
strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
|
||||
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
/* Make physical memory consistent for a set of streaming
|
||||
* mode DMA translations after a transfer.
|
||||
*/
|
||||
static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
|
||||
static void dma_4u_sync_sg_for_cpu(struct device *dev,
|
||||
struct scatterlist *sglist, int nelems,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
unsigned long flags, ctx, npages, i;
|
||||
u32 bus_addr;
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
strbuf = pdev->dev.archdata.stc;
|
||||
iommu = dev->archdata.iommu;
|
||||
strbuf = dev->archdata.stc;
|
||||
|
||||
if (!strbuf->strbuf_enabled)
|
||||
return;
|
||||
|
@ -759,65 +759,51 @@ static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist
|
|||
i--;
|
||||
npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
|
||||
- bus_addr) >> IO_PAGE_SHIFT;
|
||||
pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
|
||||
strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
|
||||
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
const struct pci_iommu_ops pci_sun4u_iommu_ops = {
|
||||
.alloc_consistent = pci_4u_alloc_consistent,
|
||||
.free_consistent = pci_4u_free_consistent,
|
||||
.map_single = pci_4u_map_single,
|
||||
.unmap_single = pci_4u_unmap_single,
|
||||
.map_sg = pci_4u_map_sg,
|
||||
.unmap_sg = pci_4u_unmap_sg,
|
||||
.dma_sync_single_for_cpu = pci_4u_dma_sync_single_for_cpu,
|
||||
.dma_sync_sg_for_cpu = pci_4u_dma_sync_sg_for_cpu,
|
||||
const struct dma_ops sun4u_dma_ops = {
|
||||
.alloc_coherent = dma_4u_alloc_coherent,
|
||||
.free_coherent = dma_4u_free_coherent,
|
||||
.map_single = dma_4u_map_single,
|
||||
.unmap_single = dma_4u_unmap_single,
|
||||
.map_sg = dma_4u_map_sg,
|
||||
.unmap_sg = dma_4u_unmap_sg,
|
||||
.sync_single_for_cpu = dma_4u_sync_single_for_cpu,
|
||||
.sync_sg_for_cpu = dma_4u_sync_sg_for_cpu,
|
||||
};
|
||||
|
||||
static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
|
||||
const struct dma_ops *dma_ops = &sun4u_dma_ops;
|
||||
EXPORT_SYMBOL(dma_ops);
|
||||
|
||||
int dma_supported(struct device *dev, u64 device_mask)
|
||||
{
|
||||
struct pci_dev *ali_isa_bridge;
|
||||
u8 val;
|
||||
|
||||
/* ALI sound chips generate 31-bits of DMA, a special register
|
||||
* determines what bit 31 is emitted as.
|
||||
*/
|
||||
ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL,
|
||||
PCI_DEVICE_ID_AL_M1533,
|
||||
NULL);
|
||||
|
||||
pci_read_config_byte(ali_isa_bridge, 0x7e, &val);
|
||||
if (set_bit)
|
||||
val |= 0x01;
|
||||
else
|
||||
val &= ~0x01;
|
||||
pci_write_config_byte(ali_isa_bridge, 0x7e, val);
|
||||
pci_dev_put(ali_isa_bridge);
|
||||
}
|
||||
|
||||
int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
|
||||
{
|
||||
u64 dma_addr_mask;
|
||||
|
||||
if (pdev == NULL) {
|
||||
dma_addr_mask = 0xffffffff;
|
||||
} else {
|
||||
struct iommu *iommu = pdev->dev.archdata.iommu;
|
||||
|
||||
dma_addr_mask = iommu->dma_addr_mask;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_AL &&
|
||||
pdev->device == PCI_DEVICE_ID_AL_M5451 &&
|
||||
device_mask == 0x7fffffff) {
|
||||
ali_sound_dma_hack(pdev,
|
||||
(dma_addr_mask & 0x80000000) != 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
struct iommu *iommu = dev->archdata.iommu;
|
||||
u64 dma_addr_mask = iommu->dma_addr_mask;
|
||||
|
||||
if (device_mask >= (1UL << 32UL))
|
||||
return 0;
|
||||
|
||||
return (device_mask & dma_addr_mask) == dma_addr_mask;
|
||||
if ((device_mask & dma_addr_mask) == dma_addr_mask)
|
||||
return 1;
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (dev->bus == &pci_bus_type)
|
||||
return pci_dma_supported(to_pci_dev(dev), device_mask);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_supported);
|
||||
|
||||
int dma_set_mask(struct device *dev, u64 dma_mask)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
if (dev->bus == &pci_bus_type)
|
||||
return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
|
||||
#endif
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(dma_set_mask);
|
|
@ -90,6 +90,8 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
|
|||
sd = &isa_dev->ofdev.dev.archdata;
|
||||
sd->prom_node = dp;
|
||||
sd->op = &isa_dev->ofdev;
|
||||
sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu;
|
||||
sd->stc = isa_br->ofdev.dev.parent->archdata.stc;
|
||||
|
||||
isa_dev->ofdev.node = dp;
|
||||
isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
|
||||
|
|
|
@ -283,12 +283,6 @@ int __init pcic_present(void)
|
|||
return pci_controller_scan(pci_is_controller);
|
||||
}
|
||||
|
||||
const struct pci_iommu_ops *pci_iommu_ops;
|
||||
EXPORT_SYMBOL(pci_iommu_ops);
|
||||
|
||||
extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
|
||||
pci_sun4v_iommu_ops;
|
||||
|
||||
/* Find each controller in the system, attach and initialize
|
||||
* software state structure for each and link into the
|
||||
* pci_pbm_root. Setup the controller enough such
|
||||
|
@ -296,11 +290,6 @@ extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
|
|||
*/
|
||||
static void __init pci_controller_probe(void)
|
||||
{
|
||||
if (tlb_type == hypervisor)
|
||||
pci_iommu_ops = &pci_sun4v_iommu_ops;
|
||||
else
|
||||
pci_iommu_ops = &pci_sun4u_iommu_ops;
|
||||
|
||||
printk("PCI: Probing for controllers.\n");
|
||||
|
||||
pci_controller_scan(pci_controller_init);
|
||||
|
@ -406,6 +395,10 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
|
|||
sd->op = of_find_device_by_node(node);
|
||||
sd->msi_num = 0xffffffff;
|
||||
|
||||
sd = &sd->op->dev.archdata;
|
||||
sd->iommu = pbm->iommu;
|
||||
sd->stc = &pbm->stc;
|
||||
|
||||
type = of_get_property(node, "device_type", NULL);
|
||||
if (type == NULL)
|
||||
type = "";
|
||||
|
@ -422,10 +415,15 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
|
|||
dev->multifunction = 0; /* maybe a lie? */
|
||||
|
||||
if (host_controller) {
|
||||
dev->vendor = 0x108e;
|
||||
dev->device = 0x8000;
|
||||
dev->subsystem_vendor = 0x0000;
|
||||
dev->subsystem_device = 0x0000;
|
||||
if (tlb_type != hypervisor) {
|
||||
pci_read_config_word(dev, PCI_VENDOR_ID,
|
||||
&dev->vendor);
|
||||
pci_read_config_word(dev, PCI_DEVICE_ID,
|
||||
&dev->device);
|
||||
} else {
|
||||
dev->vendor = PCI_VENDOR_ID_SUN;
|
||||
dev->device = 0x80f0;
|
||||
}
|
||||
dev->cfg_size = 256;
|
||||
dev->class = PCI_CLASS_BRIDGE_HOST << 8;
|
||||
sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
|
||||
|
@ -818,7 +816,7 @@ int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
|
|||
{
|
||||
static u8 fake_pci_config[] = {
|
||||
0x8e, 0x10, /* Vendor: 0x108e (Sun) */
|
||||
0x00, 0x80, /* Device: 0x8000 (PBM) */
|
||||
0xf0, 0x80, /* Device: 0x80f0 (Fire) */
|
||||
0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */
|
||||
0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */
|
||||
0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */
|
||||
|
@ -1221,4 +1219,51 @@ struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
|
|||
}
|
||||
EXPORT_SYMBOL(pci_device_to_OF_node);
|
||||
|
||||
static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
|
||||
{
|
||||
struct pci_dev *ali_isa_bridge;
|
||||
u8 val;
|
||||
|
||||
/* ALI sound chips generate 31-bits of DMA, a special register
|
||||
* determines what bit 31 is emitted as.
|
||||
*/
|
||||
ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL,
|
||||
PCI_DEVICE_ID_AL_M1533,
|
||||
NULL);
|
||||
|
||||
pci_read_config_byte(ali_isa_bridge, 0x7e, &val);
|
||||
if (set_bit)
|
||||
val |= 0x01;
|
||||
else
|
||||
val &= ~0x01;
|
||||
pci_write_config_byte(ali_isa_bridge, 0x7e, val);
|
||||
pci_dev_put(ali_isa_bridge);
|
||||
}
|
||||
|
||||
int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
|
||||
{
|
||||
u64 dma_addr_mask;
|
||||
|
||||
if (pdev == NULL) {
|
||||
dma_addr_mask = 0xffffffff;
|
||||
} else {
|
||||
struct iommu *iommu = pdev->dev.archdata.iommu;
|
||||
|
||||
dma_addr_mask = iommu->dma_addr_mask;
|
||||
|
||||
if (pdev->vendor == PCI_VENDOR_ID_AL &&
|
||||
pdev->device == PCI_DEVICE_ID_AL_M5451 &&
|
||||
device_mask == 0x7fffffff) {
|
||||
ali_sound_dma_hack(pdev,
|
||||
(dma_addr_mask & 0x80000000) != 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (device_mask >= (1UL << 32UL))
|
||||
return 0;
|
||||
|
||||
return (device_mask & dma_addr_mask) == dma_addr_mask;
|
||||
}
|
||||
|
||||
#endif /* !(CONFIG_PCI) */
|
||||
|
|
|
@ -44,6 +44,67 @@ static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm,
|
|||
return (void *) (pbm->config_space | bus | devfn | reg);
|
||||
}
|
||||
|
||||
/* At least on Sabre, it is necessary to access all PCI host controller
|
||||
* registers at their natural size, otherwise zeros are returned.
|
||||
* Strange but true, and I see no language in the UltraSPARC-IIi
|
||||
* programmer's manual that mentions this even indirectly.
|
||||
*/
|
||||
static int sun4u_read_pci_cfg_host(struct pci_pbm_info *pbm,
|
||||
unsigned char bus, unsigned int devfn,
|
||||
int where, int size, u32 *value)
|
||||
{
|
||||
u32 tmp32, *addr;
|
||||
u16 tmp16;
|
||||
u8 tmp8;
|
||||
|
||||
addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
|
||||
if (!addr)
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
if (where < 8) {
|
||||
unsigned long align = (unsigned long) addr;
|
||||
|
||||
align &= ~1;
|
||||
pci_config_read16((u16 *)align, &tmp16);
|
||||
if (where & 1)
|
||||
*value = tmp16 >> 8;
|
||||
else
|
||||
*value = tmp16 & 0xff;
|
||||
} else {
|
||||
pci_config_read8((u8 *)addr, &tmp8);
|
||||
*value = (u32) tmp8;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (where < 8) {
|
||||
pci_config_read16((u16 *)addr, &tmp16);
|
||||
*value = (u32) tmp16;
|
||||
} else {
|
||||
pci_config_read8((u8 *)addr, &tmp8);
|
||||
*value = (u32) tmp8;
|
||||
pci_config_read8(((u8 *)addr) + 1, &tmp8);
|
||||
*value |= ((u32) tmp8) << 8;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
tmp32 = 0xffffffff;
|
||||
sun4u_read_pci_cfg_host(pbm, bus, devfn,
|
||||
where, 2, &tmp32);
|
||||
*value = tmp32;
|
||||
|
||||
tmp32 = 0xffffffff;
|
||||
sun4u_read_pci_cfg_host(pbm, bus, devfn,
|
||||
where + 2, 2, &tmp32);
|
||||
*value |= tmp32 << 16;
|
||||
break;
|
||||
}
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
||||
int where, int size, u32 *value)
|
||||
{
|
||||
|
@ -53,10 +114,6 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|||
u16 tmp16;
|
||||
u8 tmp8;
|
||||
|
||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
||||
return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
|
||||
size, value);
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
*value = 0xff;
|
||||
|
@ -69,6 +126,10 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!bus_dev->number && !PCI_SLOT(devfn))
|
||||
return sun4u_read_pci_cfg_host(pbm, bus, devfn, where,
|
||||
size, value);
|
||||
|
||||
addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
|
||||
if (!addr)
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
|
@ -101,6 +162,53 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int sun4u_write_pci_cfg_host(struct pci_pbm_info *pbm,
|
||||
unsigned char bus, unsigned int devfn,
|
||||
int where, int size, u32 value)
|
||||
{
|
||||
u32 *addr;
|
||||
|
||||
addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
|
||||
if (!addr)
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
|
||||
switch (size) {
|
||||
case 1:
|
||||
if (where < 8) {
|
||||
unsigned long align = (unsigned long) addr;
|
||||
u16 tmp16;
|
||||
|
||||
align &= ~1;
|
||||
pci_config_read16((u16 *)align, &tmp16);
|
||||
if (where & 1) {
|
||||
tmp16 &= 0x00ff;
|
||||
tmp16 |= value << 8;
|
||||
} else {
|
||||
tmp16 &= 0xff00;
|
||||
tmp16 |= value;
|
||||
}
|
||||
pci_config_write16((u16 *)align, tmp16);
|
||||
} else
|
||||
pci_config_write8((u8 *)addr, value);
|
||||
break;
|
||||
case 2:
|
||||
if (where < 8) {
|
||||
pci_config_write16((u16 *)addr, value);
|
||||
} else {
|
||||
pci_config_write8((u8 *)addr, value & 0xff);
|
||||
pci_config_write8(((u8 *)addr) + 1, value >> 8);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
sun4u_write_pci_cfg_host(pbm, bus, devfn,
|
||||
where, 2, value & 0xffff);
|
||||
sun4u_write_pci_cfg_host(pbm, bus, devfn,
|
||||
where + 2, 2, value >> 16);
|
||||
break;
|
||||
}
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
||||
int where, int size, u32 value)
|
||||
{
|
||||
|
@ -108,9 +216,10 @@ static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
|
|||
unsigned char bus = bus_dev->number;
|
||||
u32 *addr;
|
||||
|
||||
if (bus_dev == pbm->pci_bus && devfn == 0x00)
|
||||
return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
|
||||
size, value);
|
||||
if (!bus_dev->number && !PCI_SLOT(devfn))
|
||||
return sun4u_write_pci_cfg_host(pbm, bus, devfn, where,
|
||||
size, value);
|
||||
|
||||
addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
|
||||
if (!addr)
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
|
|
|
@ -39,12 +39,12 @@ static void pci_fire_scan_bus(struct pci_pbm_info *pbm)
|
|||
#define FIRE_IOMMU_FLUSH 0x40100UL
|
||||
#define FIRE_IOMMU_FLUSHINV 0x40108UL
|
||||
|
||||
static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
|
||||
static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
|
||||
{
|
||||
struct iommu *iommu = pbm->iommu;
|
||||
u32 vdma[2], dma_mask;
|
||||
u64 control;
|
||||
int tsbsize;
|
||||
int tsbsize, err;
|
||||
|
||||
/* No virtual-dma property on these guys, use largest size. */
|
||||
vdma[0] = 0xc0000000; /* base */
|
||||
|
@ -68,7 +68,9 @@ static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
|
|||
*/
|
||||
fire_write(iommu->iommu_flushinv, ~(u64)0);
|
||||
|
||||
pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
|
||||
err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fire_write(iommu->iommu_tsbbase, __pa(iommu->page_table) | 0x7UL);
|
||||
|
||||
|
@ -78,6 +80,8 @@ static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
|
|||
0x00000002 /* Bypass enable */ |
|
||||
0x00000001 /* Translation enable */);
|
||||
fire_write(iommu->iommu_control, control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Based at pbm->controller_regs */
|
||||
|
@ -167,8 +171,8 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm)
|
|||
fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0);
|
||||
}
|
||||
|
||||
static void pci_fire_pbm_init(struct pci_controller_info *p,
|
||||
struct device_node *dp, u32 portid)
|
||||
static int pci_fire_pbm_init(struct pci_controller_info *p,
|
||||
struct device_node *dp, u32 portid)
|
||||
{
|
||||
const struct linux_prom64_registers *regs;
|
||||
struct pci_pbm_info *pbm;
|
||||
|
@ -203,7 +207,8 @@ static void pci_fire_pbm_init(struct pci_controller_info *p,
|
|||
pci_get_pbm_props(pbm);
|
||||
|
||||
pci_fire_hw_init(pbm);
|
||||
pci_fire_pbm_iommu_init(pbm);
|
||||
|
||||
return pci_fire_pbm_iommu_init(pbm);
|
||||
}
|
||||
|
||||
static inline int portid_compare(u32 x, u32 y)
|
||||
|
@ -222,7 +227,8 @@ void fire_pci_init(struct device_node *dp, const char *model_name)
|
|||
|
||||
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
|
||||
if (portid_compare(pbm->portid, portid)) {
|
||||
pci_fire_pbm_init(pbm->parent, dp, portid);
|
||||
if (pci_fire_pbm_init(pbm->parent, dp, portid))
|
||||
goto fatal_memory_error;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +256,9 @@ void fire_pci_init(struct device_node *dp, const char *model_name)
|
|||
*/
|
||||
pci_memspace_mask = 0x7fffffffUL;
|
||||
|
||||
pci_fire_pbm_init(p, dp, portid);
|
||||
if (pci_fire_pbm_init(p, dp, portid))
|
||||
goto fatal_memory_error;
|
||||
|
||||
return;
|
||||
|
||||
fatal_memory_error:
|
||||
|
|
|
@ -813,16 +813,19 @@ static void psycho_scan_bus(struct pci_pbm_info *pbm)
|
|||
psycho_register_error_handlers(pbm);
|
||||
}
|
||||
|
||||
static void psycho_iommu_init(struct pci_pbm_info *pbm)
|
||||
static int psycho_iommu_init(struct pci_pbm_info *pbm)
|
||||
{
|
||||
struct iommu *iommu = pbm->iommu;
|
||||
unsigned long i;
|
||||
u64 control;
|
||||
int err;
|
||||
|
||||
/* Register addresses. */
|
||||
iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL;
|
||||
iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE;
|
||||
iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH;
|
||||
iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL);
|
||||
|
||||
/* PSYCHO's IOMMU lacks ctx flushing. */
|
||||
iommu->iommu_ctxflush = 0;
|
||||
|
||||
|
@ -845,7 +848,9 @@ static void psycho_iommu_init(struct pci_pbm_info *pbm)
|
|||
/* Leave diag mode enabled for full-flushing done
|
||||
* in pci_iommu.c
|
||||
*/
|
||||
pci_iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff);
|
||||
err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE,
|
||||
__pa(iommu->page_table));
|
||||
|
@ -858,6 +863,8 @@ static void psycho_iommu_init(struct pci_pbm_info *pbm)
|
|||
/* If necessary, hook us up for starfire IRQ translations. */
|
||||
if (this_is_starfire)
|
||||
starfire_hookup(pbm->portid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PSYCHO_IRQ_RETRY 0x1a00UL
|
||||
|
@ -1031,15 +1038,12 @@ void psycho_init(struct device_node *dp, char *model_name)
|
|||
}
|
||||
|
||||
p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
|
||||
if (!p) {
|
||||
prom_printf("PSYCHO: Fatal memory allocation error.\n");
|
||||
prom_halt();
|
||||
}
|
||||
if (!p)
|
||||
goto fatal_memory_error;
|
||||
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
|
||||
if (!iommu) {
|
||||
prom_printf("PSYCHO: Fatal memory allocation error.\n");
|
||||
prom_halt();
|
||||
}
|
||||
if (!iommu)
|
||||
goto fatal_memory_error;
|
||||
|
||||
p->pbm_A.iommu = p->pbm_B.iommu = iommu;
|
||||
|
||||
p->pbm_A.portid = upa_portid;
|
||||
|
@ -1062,8 +1066,14 @@ void psycho_init(struct device_node *dp, char *model_name)
|
|||
|
||||
psycho_controller_hwinit(&p->pbm_A);
|
||||
|
||||
psycho_iommu_init(&p->pbm_A);
|
||||
if (psycho_iommu_init(&p->pbm_A))
|
||||
goto fatal_memory_error;
|
||||
|
||||
is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
|
||||
psycho_pbm_init(p, dp, is_pbm_a);
|
||||
return;
|
||||
|
||||
fatal_memory_error:
|
||||
prom_printf("PSYCHO: Fatal memory allocation error.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
|
|
@ -672,18 +672,20 @@ static void sabre_scan_bus(struct pci_pbm_info *pbm)
|
|||
sabre_register_error_handlers(pbm);
|
||||
}
|
||||
|
||||
static void sabre_iommu_init(struct pci_pbm_info *pbm,
|
||||
int tsbsize, unsigned long dvma_offset,
|
||||
u32 dma_mask)
|
||||
static int sabre_iommu_init(struct pci_pbm_info *pbm,
|
||||
int tsbsize, unsigned long dvma_offset,
|
||||
u32 dma_mask)
|
||||
{
|
||||
struct iommu *iommu = pbm->iommu;
|
||||
unsigned long i;
|
||||
u64 control;
|
||||
int err;
|
||||
|
||||
/* Register addresses. */
|
||||
iommu->iommu_control = pbm->controller_regs + SABRE_IOMMU_CONTROL;
|
||||
iommu->iommu_tsbbase = pbm->controller_regs + SABRE_IOMMU_TSBBASE;
|
||||
iommu->iommu_flush = pbm->controller_regs + SABRE_IOMMU_FLUSH;
|
||||
iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL);
|
||||
iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC;
|
||||
/* Sabre's IOMMU lacks ctx flushing. */
|
||||
iommu->iommu_ctxflush = 0;
|
||||
|
@ -701,7 +703,10 @@ static void sabre_iommu_init(struct pci_pbm_info *pbm,
|
|||
/* Leave diag mode enabled for full-flushing done
|
||||
* in pci_iommu.c
|
||||
*/
|
||||
pci_iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask);
|
||||
err = iommu_table_init(iommu, tsbsize * 1024 * 8,
|
||||
dvma_offset, dma_mask);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE,
|
||||
__pa(iommu->page_table));
|
||||
|
@ -722,6 +727,8 @@ static void sabre_iommu_init(struct pci_pbm_info *pbm,
|
|||
break;
|
||||
}
|
||||
sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *pbm, struct device_node *dp)
|
||||
|
@ -775,16 +782,12 @@ void sabre_init(struct device_node *dp, char *model_name)
|
|||
}
|
||||
|
||||
p = kzalloc(sizeof(*p), GFP_ATOMIC);
|
||||
if (!p) {
|
||||
prom_printf("SABRE: Error, kmalloc(pci_controller_info) failed.\n");
|
||||
prom_halt();
|
||||
}
|
||||
if (!p)
|
||||
goto fatal_memory_error;
|
||||
|
||||
iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC);
|
||||
if (!iommu) {
|
||||
prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n");
|
||||
prom_halt();
|
||||
}
|
||||
if (!iommu)
|
||||
goto fatal_memory_error;
|
||||
pbm = &p->pbm_A;
|
||||
pbm->iommu = iommu;
|
||||
|
||||
|
@ -847,10 +850,16 @@ void sabre_init(struct device_node *dp, char *model_name)
|
|||
prom_halt();
|
||||
}
|
||||
|
||||
sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask);
|
||||
if (sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask))
|
||||
goto fatal_memory_error;
|
||||
|
||||
/*
|
||||
* Look for APB underneath.
|
||||
*/
|
||||
sabre_pbm_init(p, pbm, dp);
|
||||
return;
|
||||
|
||||
fatal_memory_error:
|
||||
prom_printf("SABRE: Fatal memory allocation error.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
|
|
@ -1148,14 +1148,14 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm)
|
|||
#define SCHIZO_IOMMU_FLUSH (0x00210UL)
|
||||
#define SCHIZO_IOMMU_CTXFLUSH (0x00218UL)
|
||||
|
||||
static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
||||
static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
||||
{
|
||||
struct iommu *iommu = pbm->iommu;
|
||||
unsigned long i, tagbase, database;
|
||||
struct property *prop;
|
||||
u32 vdma[2], dma_mask;
|
||||
int tsbsize, err;
|
||||
u64 control;
|
||||
int tsbsize;
|
||||
|
||||
prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
|
||||
if (prop) {
|
||||
|
@ -1195,6 +1195,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
|||
iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
|
||||
iommu->iommu_tsbbase = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE;
|
||||
iommu->iommu_flush = pbm->pbm_regs + SCHIZO_IOMMU_FLUSH;
|
||||
iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL);
|
||||
iommu->iommu_ctxflush = pbm->pbm_regs + SCHIZO_IOMMU_CTXFLUSH;
|
||||
|
||||
/* We use the main control/status register of SCHIZO as the write
|
||||
|
@ -1219,7 +1220,9 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
|||
/* Leave diag mode enabled for full-flushing done
|
||||
* in pci_iommu.c
|
||||
*/
|
||||
pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
|
||||
err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table));
|
||||
|
||||
|
@ -1236,6 +1239,8 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
|||
|
||||
control |= SCHIZO_IOMMU_CTRL_ENAB;
|
||||
schizo_write(iommu->iommu_control, control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SCHIZO_PCI_IRQ_RETRY (0x1a00UL)
|
||||
|
@ -1328,14 +1333,14 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
|
|||
}
|
||||
}
|
||||
|
||||
static void schizo_pbm_init(struct pci_controller_info *p,
|
||||
struct device_node *dp, u32 portid,
|
||||
int chip_type)
|
||||
static int schizo_pbm_init(struct pci_controller_info *p,
|
||||
struct device_node *dp, u32 portid,
|
||||
int chip_type)
|
||||
{
|
||||
const struct linux_prom64_registers *regs;
|
||||
struct pci_pbm_info *pbm;
|
||||
const char *chipset_name;
|
||||
int is_pbm_a;
|
||||
int is_pbm_a, err;
|
||||
|
||||
switch (chip_type) {
|
||||
case PBM_CHIP_TYPE_TOMATILLO:
|
||||
|
@ -1406,8 +1411,13 @@ static void schizo_pbm_init(struct pci_controller_info *p,
|
|||
|
||||
pci_get_pbm_props(pbm);
|
||||
|
||||
schizo_pbm_iommu_init(pbm);
|
||||
err = schizo_pbm_iommu_init(pbm);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
schizo_pbm_strbuf_init(pbm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int portid_compare(u32 x, u32 y, int chip_type)
|
||||
|
@ -1431,34 +1441,38 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ
|
|||
|
||||
for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
|
||||
if (portid_compare(pbm->portid, portid, chip_type)) {
|
||||
schizo_pbm_init(pbm->parent, dp, portid, chip_type);
|
||||
if (schizo_pbm_init(pbm->parent, dp,
|
||||
portid, chip_type))
|
||||
goto fatal_memory_error;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
|
||||
if (!p)
|
||||
goto memfail;
|
||||
goto fatal_memory_error;
|
||||
|
||||
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
|
||||
if (!iommu)
|
||||
goto memfail;
|
||||
goto fatal_memory_error;
|
||||
|
||||
p->pbm_A.iommu = iommu;
|
||||
|
||||
iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
|
||||
if (!iommu)
|
||||
goto memfail;
|
||||
goto fatal_memory_error;
|
||||
|
||||
p->pbm_B.iommu = iommu;
|
||||
|
||||
/* Like PSYCHO we have a 2GB aligned area for memory space. */
|
||||
pci_memspace_mask = 0x7fffffffUL;
|
||||
|
||||
schizo_pbm_init(p, dp, portid, chip_type);
|
||||
if (schizo_pbm_init(p, dp, portid, chip_type))
|
||||
goto fatal_memory_error;
|
||||
|
||||
return;
|
||||
|
||||
memfail:
|
||||
fatal_memory_error:
|
||||
prom_printf("SCHIZO: Fatal memory allocation error.\n");
|
||||
prom_halt();
|
||||
}
|
||||
|
|
|
@ -33,30 +33,30 @@ static unsigned long vpci_minor = 1;
|
|||
#define PGLIST_NENTS (PAGE_SIZE / sizeof(u64))
|
||||
|
||||
struct iommu_batch {
|
||||
struct pci_dev *pdev; /* Device mapping is for. */
|
||||
struct device *dev; /* Device mapping is for. */
|
||||
unsigned long prot; /* IOMMU page protections */
|
||||
unsigned long entry; /* Index into IOTSB. */
|
||||
u64 *pglist; /* List of physical pages */
|
||||
unsigned long npages; /* Number of pages in list. */
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct iommu_batch, pci_iommu_batch);
|
||||
static DEFINE_PER_CPU(struct iommu_batch, iommu_batch);
|
||||
|
||||
/* Interrupts must be disabled. */
|
||||
static inline void pci_iommu_batch_start(struct pci_dev *pdev, unsigned long prot, unsigned long entry)
|
||||
static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry)
|
||||
{
|
||||
struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
|
||||
struct iommu_batch *p = &__get_cpu_var(iommu_batch);
|
||||
|
||||
p->pdev = pdev;
|
||||
p->dev = dev;
|
||||
p->prot = prot;
|
||||
p->entry = entry;
|
||||
p->npages = 0;
|
||||
}
|
||||
|
||||
/* Interrupts must be disabled. */
|
||||
static long pci_iommu_batch_flush(struct iommu_batch *p)
|
||||
static long iommu_batch_flush(struct iommu_batch *p)
|
||||
{
|
||||
struct pci_pbm_info *pbm = p->pdev->dev.archdata.host_controller;
|
||||
struct pci_pbm_info *pbm = p->dev->archdata.host_controller;
|
||||
unsigned long devhandle = pbm->devhandle;
|
||||
unsigned long prot = p->prot;
|
||||
unsigned long entry = p->entry;
|
||||
|
@ -70,7 +70,7 @@ static long pci_iommu_batch_flush(struct iommu_batch *p)
|
|||
npages, prot, __pa(pglist));
|
||||
if (unlikely(num < 0)) {
|
||||
if (printk_ratelimit())
|
||||
printk("pci_iommu_batch_flush: IOMMU map of "
|
||||
printk("iommu_batch_flush: IOMMU map of "
|
||||
"[%08lx:%08lx:%lx:%lx:%lx] failed with "
|
||||
"status %ld\n",
|
||||
devhandle, HV_PCI_TSBID(0, entry),
|
||||
|
@ -90,30 +90,30 @@ static long pci_iommu_batch_flush(struct iommu_batch *p)
|
|||
}
|
||||
|
||||
/* Interrupts must be disabled. */
|
||||
static inline long pci_iommu_batch_add(u64 phys_page)
|
||||
static inline long iommu_batch_add(u64 phys_page)
|
||||
{
|
||||
struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
|
||||
struct iommu_batch *p = &__get_cpu_var(iommu_batch);
|
||||
|
||||
BUG_ON(p->npages >= PGLIST_NENTS);
|
||||
|
||||
p->pglist[p->npages++] = phys_page;
|
||||
if (p->npages == PGLIST_NENTS)
|
||||
return pci_iommu_batch_flush(p);
|
||||
return iommu_batch_flush(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Interrupts must be disabled. */
|
||||
static inline long pci_iommu_batch_end(void)
|
||||
static inline long iommu_batch_end(void)
|
||||
{
|
||||
struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
|
||||
struct iommu_batch *p = &__get_cpu_var(iommu_batch);
|
||||
|
||||
BUG_ON(p->npages >= PGLIST_NENTS);
|
||||
|
||||
return pci_iommu_batch_flush(p);
|
||||
return iommu_batch_flush(p);
|
||||
}
|
||||
|
||||
static long pci_arena_alloc(struct iommu_arena *arena, unsigned long npages)
|
||||
static long arena_alloc(struct iommu_arena *arena, unsigned long npages)
|
||||
{
|
||||
unsigned long n, i, start, end, limit;
|
||||
int pass;
|
||||
|
@ -152,7 +152,8 @@ static long pci_arena_alloc(struct iommu_arena *arena, unsigned long npages)
|
|||
return n;
|
||||
}
|
||||
|
||||
static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
|
||||
static void arena_free(struct iommu_arena *arena, unsigned long base,
|
||||
unsigned long npages)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
|
@ -160,7 +161,8 @@ static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsign
|
|||
__clear_bit(i, arena->map);
|
||||
}
|
||||
|
||||
static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
|
||||
static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_addrp, gfp_t gfp)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
unsigned long flags, order, first_page, npages, n;
|
||||
|
@ -180,10 +182,10 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
|
|||
|
||||
memset((char *)first_page, 0, PAGE_SIZE << order);
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
iommu = dev->archdata.iommu;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
entry = pci_arena_alloc(&iommu->arena, npages);
|
||||
entry = arena_alloc(&iommu->arena, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
if (unlikely(entry < 0L))
|
||||
|
@ -196,18 +198,18 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
|
|||
|
||||
local_irq_save(flags);
|
||||
|
||||
pci_iommu_batch_start(pdev,
|
||||
(HV_PCI_MAP_ATTR_READ |
|
||||
HV_PCI_MAP_ATTR_WRITE),
|
||||
entry);
|
||||
iommu_batch_start(dev,
|
||||
(HV_PCI_MAP_ATTR_READ |
|
||||
HV_PCI_MAP_ATTR_WRITE),
|
||||
entry);
|
||||
|
||||
for (n = 0; n < npages; n++) {
|
||||
long err = pci_iommu_batch_add(first_page + (n * PAGE_SIZE));
|
||||
long err = iommu_batch_add(first_page + (n * PAGE_SIZE));
|
||||
if (unlikely(err < 0L))
|
||||
goto iommu_map_fail;
|
||||
}
|
||||
|
||||
if (unlikely(pci_iommu_batch_end() < 0L))
|
||||
if (unlikely(iommu_batch_end() < 0L))
|
||||
goto iommu_map_fail;
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
@ -217,7 +219,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
|
|||
iommu_map_fail:
|
||||
/* Interrupts are disabled. */
|
||||
spin_lock(&iommu->lock);
|
||||
pci_arena_free(&iommu->arena, entry, npages);
|
||||
arena_free(&iommu->arena, entry, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
arena_alloc_fail:
|
||||
|
@ -225,7 +227,8 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
|
||||
static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
|
||||
dma_addr_t dvma)
|
||||
{
|
||||
struct pci_pbm_info *pbm;
|
||||
struct iommu *iommu;
|
||||
|
@ -233,14 +236,14 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
|
|||
u32 devhandle;
|
||||
|
||||
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
pbm = pdev->dev.archdata.host_controller;
|
||||
iommu = dev->archdata.iommu;
|
||||
pbm = dev->archdata.host_controller;
|
||||
devhandle = pbm->devhandle;
|
||||
entry = ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
||||
pci_arena_free(&iommu->arena, entry, npages);
|
||||
arena_free(&iommu->arena, entry, npages);
|
||||
|
||||
do {
|
||||
unsigned long num;
|
||||
|
@ -258,7 +261,8 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
|
|||
free_pages((unsigned long)cpu, order);
|
||||
}
|
||||
|
||||
static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
|
||||
static dma_addr_t dma_4v_map_single(struct device *dev, void *ptr, size_t sz,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
unsigned long flags, npages, oaddr;
|
||||
|
@ -267,9 +271,9 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
|
|||
unsigned long prot;
|
||||
long entry;
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
iommu = dev->archdata.iommu;
|
||||
|
||||
if (unlikely(direction == PCI_DMA_NONE))
|
||||
if (unlikely(direction == DMA_NONE))
|
||||
goto bad;
|
||||
|
||||
oaddr = (unsigned long)ptr;
|
||||
|
@ -277,7 +281,7 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
|
|||
npages >>= IO_PAGE_SHIFT;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
entry = pci_arena_alloc(&iommu->arena, npages);
|
||||
entry = arena_alloc(&iommu->arena, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
if (unlikely(entry < 0L))
|
||||
|
@ -288,19 +292,19 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
|
|||
ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
|
||||
base_paddr = __pa(oaddr & IO_PAGE_MASK);
|
||||
prot = HV_PCI_MAP_ATTR_READ;
|
||||
if (direction != PCI_DMA_TODEVICE)
|
||||
if (direction != DMA_TO_DEVICE)
|
||||
prot |= HV_PCI_MAP_ATTR_WRITE;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
pci_iommu_batch_start(pdev, prot, entry);
|
||||
iommu_batch_start(dev, prot, entry);
|
||||
|
||||
for (i = 0; i < npages; i++, base_paddr += IO_PAGE_SIZE) {
|
||||
long err = pci_iommu_batch_add(base_paddr);
|
||||
long err = iommu_batch_add(base_paddr);
|
||||
if (unlikely(err < 0L))
|
||||
goto iommu_map_fail;
|
||||
}
|
||||
if (unlikely(pci_iommu_batch_end() < 0L))
|
||||
if (unlikely(iommu_batch_end() < 0L))
|
||||
goto iommu_map_fail;
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
@ -310,18 +314,19 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
|
|||
bad:
|
||||
if (printk_ratelimit())
|
||||
WARN_ON(1);
|
||||
return PCI_DMA_ERROR_CODE;
|
||||
return DMA_ERROR_CODE;
|
||||
|
||||
iommu_map_fail:
|
||||
/* Interrupts are disabled. */
|
||||
spin_lock(&iommu->lock);
|
||||
pci_arena_free(&iommu->arena, entry, npages);
|
||||
arena_free(&iommu->arena, entry, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
return PCI_DMA_ERROR_CODE;
|
||||
return DMA_ERROR_CODE;
|
||||
}
|
||||
|
||||
static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
|
||||
static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
|
||||
size_t sz, enum dma_data_direction direction)
|
||||
{
|
||||
struct pci_pbm_info *pbm;
|
||||
struct iommu *iommu;
|
||||
|
@ -329,14 +334,14 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
|
|||
long entry;
|
||||
u32 devhandle;
|
||||
|
||||
if (unlikely(direction == PCI_DMA_NONE)) {
|
||||
if (unlikely(direction == DMA_NONE)) {
|
||||
if (printk_ratelimit())
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
pbm = pdev->dev.archdata.host_controller;
|
||||
iommu = dev->archdata.iommu;
|
||||
pbm = dev->archdata.host_controller;
|
||||
devhandle = pbm->devhandle;
|
||||
|
||||
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
|
||||
|
@ -346,7 +351,7 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
|
|||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
||||
entry = (bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
|
||||
pci_arena_free(&iommu->arena, entry, npages);
|
||||
arena_free(&iommu->arena, entry, npages);
|
||||
|
||||
do {
|
||||
unsigned long num;
|
||||
|
@ -363,7 +368,7 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
|
|||
#define SG_ENT_PHYS_ADDRESS(SG) \
|
||||
(__pa(page_address((SG)->page)) + (SG)->offset)
|
||||
|
||||
static inline long fill_sg(long entry, struct pci_dev *pdev,
|
||||
static inline long fill_sg(long entry, struct device *dev,
|
||||
struct scatterlist *sg,
|
||||
int nused, int nelems, unsigned long prot)
|
||||
{
|
||||
|
@ -374,7 +379,7 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
|
|||
|
||||
local_irq_save(flags);
|
||||
|
||||
pci_iommu_batch_start(pdev, prot, entry);
|
||||
iommu_batch_start(dev, prot, entry);
|
||||
|
||||
for (i = 0; i < nused; i++) {
|
||||
unsigned long pteval = ~0UL;
|
||||
|
@ -415,7 +420,7 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
|
|||
while (len > 0) {
|
||||
long err;
|
||||
|
||||
err = pci_iommu_batch_add(pteval);
|
||||
err = iommu_batch_add(pteval);
|
||||
if (unlikely(err < 0L))
|
||||
goto iommu_map_failed;
|
||||
|
||||
|
@ -446,7 +451,7 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
|
|||
dma_sg++;
|
||||
}
|
||||
|
||||
if (unlikely(pci_iommu_batch_end() < 0L))
|
||||
if (unlikely(iommu_batch_end() < 0L))
|
||||
goto iommu_map_failed;
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
@ -457,7 +462,8 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
|
|||
return -1L;
|
||||
}
|
||||
|
||||
static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
|
||||
static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
|
||||
int nelems, enum dma_data_direction direction)
|
||||
{
|
||||
struct iommu *iommu;
|
||||
unsigned long flags, npages, prot;
|
||||
|
@ -469,18 +475,19 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
|
|||
/* Fast path single entry scatterlists. */
|
||||
if (nelems == 1) {
|
||||
sglist->dma_address =
|
||||
pci_4v_map_single(pdev,
|
||||
(page_address(sglist->page) + sglist->offset),
|
||||
dma_4v_map_single(dev,
|
||||
(page_address(sglist->page) +
|
||||
sglist->offset),
|
||||
sglist->length, direction);
|
||||
if (unlikely(sglist->dma_address == PCI_DMA_ERROR_CODE))
|
||||
if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
|
||||
return 0;
|
||||
sglist->dma_length = sglist->length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
iommu = dev->archdata.iommu;
|
||||
|
||||
if (unlikely(direction == PCI_DMA_NONE))
|
||||
if (unlikely(direction == DMA_NONE))
|
||||
goto bad;
|
||||
|
||||
/* Step 1: Prepare scatter list. */
|
||||
|
@ -488,7 +495,7 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
|
|||
|
||||
/* Step 2: Allocate a cluster and context, if necessary. */
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
entry = pci_arena_alloc(&iommu->arena, npages);
|
||||
entry = arena_alloc(&iommu->arena, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
if (unlikely(entry < 0L))
|
||||
|
@ -510,10 +517,10 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
|
|||
|
||||
/* Step 4: Create the mappings. */
|
||||
prot = HV_PCI_MAP_ATTR_READ;
|
||||
if (direction != PCI_DMA_TODEVICE)
|
||||
if (direction != DMA_TO_DEVICE)
|
||||
prot |= HV_PCI_MAP_ATTR_WRITE;
|
||||
|
||||
err = fill_sg(entry, pdev, sglist, used, nelems, prot);
|
||||
err = fill_sg(entry, dev, sglist, used, nelems, prot);
|
||||
if (unlikely(err < 0L))
|
||||
goto iommu_map_failed;
|
||||
|
||||
|
@ -526,13 +533,14 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
|
|||
|
||||
iommu_map_failed:
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
pci_arena_free(&iommu->arena, entry, npages);
|
||||
arena_free(&iommu->arena, entry, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
|
||||
static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
|
||||
int nelems, enum dma_data_direction direction)
|
||||
{
|
||||
struct pci_pbm_info *pbm;
|
||||
struct iommu *iommu;
|
||||
|
@ -540,13 +548,13 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
|
|||
long entry;
|
||||
u32 devhandle, bus_addr;
|
||||
|
||||
if (unlikely(direction == PCI_DMA_NONE)) {
|
||||
if (unlikely(direction == DMA_NONE)) {
|
||||
if (printk_ratelimit())
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
iommu = pdev->dev.archdata.iommu;
|
||||
pbm = pdev->dev.archdata.host_controller;
|
||||
iommu = dev->archdata.iommu;
|
||||
pbm = dev->archdata.host_controller;
|
||||
devhandle = pbm->devhandle;
|
||||
|
||||
bus_addr = sglist->dma_address & IO_PAGE_MASK;
|
||||
|
@ -562,7 +570,7 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
|
|||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
||||
pci_arena_free(&iommu->arena, entry, npages);
|
||||
arena_free(&iommu->arena, entry, npages);
|
||||
|
||||
do {
|
||||
unsigned long num;
|
||||
|
@ -576,25 +584,29 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
|
|||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
static void pci_4v_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
|
||||
static void dma_4v_sync_single_for_cpu(struct device *dev,
|
||||
dma_addr_t bus_addr, size_t sz,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
/* Nothing to do... */
|
||||
}
|
||||
|
||||
static void pci_4v_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
|
||||
static void dma_4v_sync_sg_for_cpu(struct device *dev,
|
||||
struct scatterlist *sglist, int nelems,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
/* Nothing to do... */
|
||||
}
|
||||
|
||||
const struct pci_iommu_ops pci_sun4v_iommu_ops = {
|
||||
.alloc_consistent = pci_4v_alloc_consistent,
|
||||
.free_consistent = pci_4v_free_consistent,
|
||||
.map_single = pci_4v_map_single,
|
||||
.unmap_single = pci_4v_unmap_single,
|
||||
.map_sg = pci_4v_map_sg,
|
||||
.unmap_sg = pci_4v_unmap_sg,
|
||||
.dma_sync_single_for_cpu = pci_4v_dma_sync_single_for_cpu,
|
||||
.dma_sync_sg_for_cpu = pci_4v_dma_sync_sg_for_cpu,
|
||||
const struct dma_ops sun4v_dma_ops = {
|
||||
.alloc_coherent = dma_4v_alloc_coherent,
|
||||
.free_coherent = dma_4v_free_coherent,
|
||||
.map_single = dma_4v_map_single,
|
||||
.unmap_single = dma_4v_unmap_single,
|
||||
.map_sg = dma_4v_map_sg,
|
||||
.unmap_sg = dma_4v_unmap_sg,
|
||||
.sync_single_for_cpu = dma_4v_sync_single_for_cpu,
|
||||
.sync_sg_for_cpu = dma_4v_sync_sg_for_cpu,
|
||||
};
|
||||
|
||||
static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
|
||||
|
@ -1186,6 +1198,8 @@ void __init sun4v_pci_init(struct device_node *dp, char *model_name)
|
|||
}
|
||||
printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n",
|
||||
vpci_major, vpci_minor);
|
||||
|
||||
dma_ops = &sun4v_dma_ops;
|
||||
}
|
||||
|
||||
prop = of_find_property(dp, "reg", NULL);
|
||||
|
@ -1206,7 +1220,7 @@ void __init sun4v_pci_init(struct device_node *dp, char *model_name)
|
|||
if (!page)
|
||||
goto fatal_memory_error;
|
||||
|
||||
per_cpu(pci_iommu_batch, i).pglist = (u64 *) page;
|
||||
per_cpu(iommu_batch, i).pglist = (u64 *) page;
|
||||
}
|
||||
|
||||
p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
|
||||
|
|
|
@ -26,11 +26,6 @@
|
|||
|
||||
#define MAP_BASE ((u32)0xc0000000)
|
||||
|
||||
struct sbus_info {
|
||||
struct iommu iommu;
|
||||
struct strbuf strbuf;
|
||||
};
|
||||
|
||||
/* Offsets from iommu_regs */
|
||||
#define SYSIO_IOMMUREG_BASE 0x2400UL
|
||||
#define IOMMU_CONTROL (0x2400UL - 0x2400UL) /* IOMMU control register */
|
||||
|
@ -44,19 +39,6 @@ struct sbus_info {
|
|||
|
||||
#define IOMMU_DRAM_VALID (1UL << 30UL)
|
||||
|
||||
static void __iommu_flushall(struct iommu *iommu)
|
||||
{
|
||||
unsigned long tag;
|
||||
int entry;
|
||||
|
||||
tag = iommu->iommu_control + (IOMMU_TAGDIAG - IOMMU_CONTROL);
|
||||
for (entry = 0; entry < 16; entry++) {
|
||||
upa_writeq(0, tag);
|
||||
tag += 8UL;
|
||||
}
|
||||
upa_readq(iommu->write_complete_reg);
|
||||
}
|
||||
|
||||
/* Offsets from strbuf_regs */
|
||||
#define SYSIO_STRBUFREG_BASE 0x2800UL
|
||||
#define STRBUF_CONTROL (0x2800UL - 0x2800UL) /* Control */
|
||||
|
@ -69,511 +51,10 @@ static void __iommu_flushall(struct iommu *iommu)
|
|||
|
||||
#define STRBUF_TAG_VALID 0x02UL
|
||||
|
||||
static void sbus_strbuf_flush(struct iommu *iommu, struct strbuf *strbuf, u32 base, unsigned long npages, int direction)
|
||||
{
|
||||
unsigned long n;
|
||||
int limit;
|
||||
|
||||
n = npages;
|
||||
while (n--)
|
||||
upa_writeq(base + (n << IO_PAGE_SHIFT), strbuf->strbuf_pflush);
|
||||
|
||||
/* If the device could not have possibly put dirty data into
|
||||
* the streaming cache, no flush-flag synchronization needs
|
||||
* to be performed.
|
||||
*/
|
||||
if (direction == SBUS_DMA_TODEVICE)
|
||||
return;
|
||||
|
||||
*(strbuf->strbuf_flushflag) = 0UL;
|
||||
|
||||
/* Whoopee cushion! */
|
||||
upa_writeq(strbuf->strbuf_flushflag_pa, strbuf->strbuf_fsync);
|
||||
upa_readq(iommu->write_complete_reg);
|
||||
|
||||
limit = 100000;
|
||||
while (*(strbuf->strbuf_flushflag) == 0UL) {
|
||||
limit--;
|
||||
if (!limit)
|
||||
break;
|
||||
udelay(1);
|
||||
rmb();
|
||||
}
|
||||
if (!limit)
|
||||
printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
|
||||
"vaddr[%08x] npages[%ld]\n",
|
||||
base, npages);
|
||||
}
|
||||
|
||||
/* Based largely upon the ppc64 iommu allocator. */
|
||||
static long sbus_arena_alloc(struct iommu *iommu, unsigned long npages)
|
||||
{
|
||||
struct iommu_arena *arena = &iommu->arena;
|
||||
unsigned long n, i, start, end, limit;
|
||||
int pass;
|
||||
|
||||
limit = arena->limit;
|
||||
start = arena->hint;
|
||||
pass = 0;
|
||||
|
||||
again:
|
||||
n = find_next_zero_bit(arena->map, limit, start);
|
||||
end = n + npages;
|
||||
if (unlikely(end >= limit)) {
|
||||
if (likely(pass < 1)) {
|
||||
limit = start;
|
||||
start = 0;
|
||||
__iommu_flushall(iommu);
|
||||
pass++;
|
||||
goto again;
|
||||
} else {
|
||||
/* Scanned the whole thing, give up. */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = n; i < end; i++) {
|
||||
if (test_bit(i, arena->map)) {
|
||||
start = i + 1;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = n; i < end; i++)
|
||||
__set_bit(i, arena->map);
|
||||
|
||||
arena->hint = end;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void sbus_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = base; i < (base + npages); i++)
|
||||
__clear_bit(i, arena->map);
|
||||
}
|
||||
|
||||
static void sbus_iommu_table_init(struct iommu *iommu, unsigned int tsbsize)
|
||||
{
|
||||
unsigned long tsbbase, order, sz, num_tsb_entries;
|
||||
|
||||
num_tsb_entries = tsbsize / sizeof(iopte_t);
|
||||
|
||||
/* Setup initial software IOMMU state. */
|
||||
spin_lock_init(&iommu->lock);
|
||||
iommu->page_table_map_base = MAP_BASE;
|
||||
|
||||
/* Allocate and initialize the free area map. */
|
||||
sz = num_tsb_entries / 8;
|
||||
sz = (sz + 7UL) & ~7UL;
|
||||
iommu->arena.map = kzalloc(sz, GFP_KERNEL);
|
||||
if (!iommu->arena.map) {
|
||||
prom_printf("SBUS_IOMMU: Error, kmalloc(arena.map) failed.\n");
|
||||
prom_halt();
|
||||
}
|
||||
iommu->arena.limit = num_tsb_entries;
|
||||
|
||||
/* Now allocate and setup the IOMMU page table itself. */
|
||||
order = get_order(tsbsize);
|
||||
tsbbase = __get_free_pages(GFP_KERNEL, order);
|
||||
if (!tsbbase) {
|
||||
prom_printf("IOMMU: Error, gfp(tsb) failed.\n");
|
||||
prom_halt();
|
||||
}
|
||||
iommu->page_table = (iopte_t *)tsbbase;
|
||||
memset(iommu->page_table, 0, tsbsize);
|
||||
}
|
||||
|
||||
static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
|
||||
{
|
||||
long entry;
|
||||
|
||||
entry = sbus_arena_alloc(iommu, npages);
|
||||
if (unlikely(entry < 0))
|
||||
return NULL;
|
||||
|
||||
return iommu->page_table + entry;
|
||||
}
|
||||
|
||||
static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
|
||||
{
|
||||
sbus_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
|
||||
}
|
||||
|
||||
void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma_addr)
|
||||
{
|
||||
struct sbus_info *info;
|
||||
struct iommu *iommu;
|
||||
iopte_t *iopte;
|
||||
unsigned long flags, order, first_page;
|
||||
void *ret;
|
||||
int npages;
|
||||
|
||||
size = IO_PAGE_ALIGN(size);
|
||||
order = get_order(size);
|
||||
if (order >= 10)
|
||||
return NULL;
|
||||
|
||||
first_page = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
|
||||
if (first_page == 0UL)
|
||||
return NULL;
|
||||
memset((char *)first_page, 0, PAGE_SIZE << order);
|
||||
|
||||
info = sdev->bus->iommu;
|
||||
iommu = &info->iommu;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
if (unlikely(iopte == NULL)) {
|
||||
free_pages(first_page, order);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*dvma_addr = (iommu->page_table_map_base +
|
||||
((iopte - iommu->page_table) << IO_PAGE_SHIFT));
|
||||
ret = (void *) first_page;
|
||||
npages = size >> IO_PAGE_SHIFT;
|
||||
first_page = __pa(first_page);
|
||||
while (npages--) {
|
||||
iopte_val(*iopte) = (IOPTE_VALID | IOPTE_CACHE |
|
||||
IOPTE_WRITE |
|
||||
(first_page & IOPTE_PAGE));
|
||||
iopte++;
|
||||
first_page += IO_PAGE_SIZE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_addr_t dvma)
|
||||
{
|
||||
struct sbus_info *info;
|
||||
struct iommu *iommu;
|
||||
iopte_t *iopte;
|
||||
unsigned long flags, order, npages;
|
||||
|
||||
npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
|
||||
info = sdev->bus->iommu;
|
||||
iommu = &info->iommu;
|
||||
iopte = iommu->page_table +
|
||||
((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
|
||||
free_npages(iommu, dvma - iommu->page_table_map_base, npages);
|
||||
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
order = get_order(size);
|
||||
if (order < 10)
|
||||
free_pages((unsigned long)cpu, order);
|
||||
}
|
||||
|
||||
dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t sz, int direction)
|
||||
{
|
||||
struct sbus_info *info;
|
||||
struct iommu *iommu;
|
||||
iopte_t *base;
|
||||
unsigned long flags, npages, oaddr;
|
||||
unsigned long i, base_paddr;
|
||||
u32 bus_addr, ret;
|
||||
unsigned long iopte_protection;
|
||||
|
||||
info = sdev->bus->iommu;
|
||||
iommu = &info->iommu;
|
||||
|
||||
if (unlikely(direction == SBUS_DMA_NONE))
|
||||
BUG();
|
||||
|
||||
oaddr = (unsigned long)ptr;
|
||||
npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
|
||||
npages >>= IO_PAGE_SHIFT;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
base = alloc_npages(iommu, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
if (unlikely(!base))
|
||||
BUG();
|
||||
|
||||
bus_addr = (iommu->page_table_map_base +
|
||||
((base - iommu->page_table) << IO_PAGE_SHIFT));
|
||||
ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
|
||||
base_paddr = __pa(oaddr & IO_PAGE_MASK);
|
||||
|
||||
iopte_protection = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE;
|
||||
if (direction != SBUS_DMA_TODEVICE)
|
||||
iopte_protection |= IOPTE_WRITE;
|
||||
|
||||
for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE)
|
||||
iopte_val(*base) = iopte_protection | base_paddr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction)
|
||||
{
|
||||
struct sbus_info *info = sdev->bus->iommu;
|
||||
struct iommu *iommu = &info->iommu;
|
||||
struct strbuf *strbuf = &info->strbuf;
|
||||
iopte_t *base;
|
||||
unsigned long flags, npages, i;
|
||||
|
||||
if (unlikely(direction == SBUS_DMA_NONE))
|
||||
BUG();
|
||||
|
||||
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
|
||||
npages >>= IO_PAGE_SHIFT;
|
||||
base = iommu->page_table +
|
||||
((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
|
||||
|
||||
bus_addr &= IO_PAGE_MASK;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
|
||||
for (i = 0; i < npages; i++)
|
||||
iopte_val(base[i]) = 0UL;
|
||||
free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
#define SG_ENT_PHYS_ADDRESS(SG) \
|
||||
(__pa(page_address((SG)->page)) + (SG)->offset)
|
||||
|
||||
static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
|
||||
int nused, int nelems, unsigned long iopte_protection)
|
||||
{
|
||||
struct scatterlist *dma_sg = sg;
|
||||
struct scatterlist *sg_end = sg + nelems;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nused; i++) {
|
||||
unsigned long pteval = ~0UL;
|
||||
u32 dma_npages;
|
||||
|
||||
dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) +
|
||||
dma_sg->dma_length +
|
||||
((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT;
|
||||
do {
|
||||
unsigned long offset;
|
||||
signed int len;
|
||||
|
||||
/* If we are here, we know we have at least one
|
||||
* more page to map. So walk forward until we
|
||||
* hit a page crossing, and begin creating new
|
||||
* mappings from that spot.
|
||||
*/
|
||||
for (;;) {
|
||||
unsigned long tmp;
|
||||
|
||||
tmp = SG_ENT_PHYS_ADDRESS(sg);
|
||||
len = sg->length;
|
||||
if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) {
|
||||
pteval = tmp & IO_PAGE_MASK;
|
||||
offset = tmp & (IO_PAGE_SIZE - 1UL);
|
||||
break;
|
||||
}
|
||||
if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) {
|
||||
pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK;
|
||||
offset = 0UL;
|
||||
len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
|
||||
break;
|
||||
}
|
||||
sg++;
|
||||
}
|
||||
|
||||
pteval = iopte_protection | (pteval & IOPTE_PAGE);
|
||||
while (len > 0) {
|
||||
*iopte++ = __iopte(pteval);
|
||||
pteval += IO_PAGE_SIZE;
|
||||
len -= (IO_PAGE_SIZE - offset);
|
||||
offset = 0;
|
||||
dma_npages--;
|
||||
}
|
||||
|
||||
pteval = (pteval & IOPTE_PAGE) + len;
|
||||
sg++;
|
||||
|
||||
/* Skip over any tail mappings we've fully mapped,
|
||||
* adjusting pteval along the way. Stop when we
|
||||
* detect a page crossing event.
|
||||
*/
|
||||
while (sg < sg_end &&
|
||||
(pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
|
||||
(pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
|
||||
((pteval ^
|
||||
(SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
|
||||
pteval += sg->length;
|
||||
sg++;
|
||||
}
|
||||
if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
|
||||
pteval = ~0UL;
|
||||
} while (dma_npages != 0);
|
||||
dma_sg++;
|
||||
}
|
||||
}
|
||||
|
||||
int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction)
|
||||
{
|
||||
struct sbus_info *info;
|
||||
struct iommu *iommu;
|
||||
unsigned long flags, npages, iopte_protection;
|
||||
iopte_t *base;
|
||||
u32 dma_base;
|
||||
struct scatterlist *sgtmp;
|
||||
int used;
|
||||
|
||||
/* Fast path single entry scatterlists. */
|
||||
if (nelems == 1) {
|
||||
sglist->dma_address =
|
||||
sbus_map_single(sdev,
|
||||
(page_address(sglist->page) + sglist->offset),
|
||||
sglist->length, direction);
|
||||
sglist->dma_length = sglist->length;
|
||||
return 1;
|
||||
}
|
||||
|
||||
info = sdev->bus->iommu;
|
||||
iommu = &info->iommu;
|
||||
|
||||
if (unlikely(direction == SBUS_DMA_NONE))
|
||||
BUG();
|
||||
|
||||
npages = prepare_sg(sglist, nelems);
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
base = alloc_npages(iommu, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
|
||||
if (unlikely(base == NULL))
|
||||
BUG();
|
||||
|
||||
dma_base = iommu->page_table_map_base +
|
||||
((base - iommu->page_table) << IO_PAGE_SHIFT);
|
||||
|
||||
/* Normalize DVMA addresses. */
|
||||
used = nelems;
|
||||
|
||||
sgtmp = sglist;
|
||||
while (used && sgtmp->dma_length) {
|
||||
sgtmp->dma_address += dma_base;
|
||||
sgtmp++;
|
||||
used--;
|
||||
}
|
||||
used = nelems - used;
|
||||
|
||||
iopte_protection = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE;
|
||||
if (direction != SBUS_DMA_TODEVICE)
|
||||
iopte_protection |= IOPTE_WRITE;
|
||||
|
||||
fill_sg(base, sglist, used, nelems, iopte_protection);
|
||||
|
||||
#ifdef VERIFY_SG
|
||||
verify_sglist(sglist, nelems, base, npages);
|
||||
#endif
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction)
|
||||
{
|
||||
struct sbus_info *info;
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
iopte_t *base;
|
||||
unsigned long flags, i, npages;
|
||||
u32 bus_addr;
|
||||
|
||||
if (unlikely(direction == SBUS_DMA_NONE))
|
||||
BUG();
|
||||
|
||||
info = sdev->bus->iommu;
|
||||
iommu = &info->iommu;
|
||||
strbuf = &info->strbuf;
|
||||
|
||||
bus_addr = sglist->dma_address & IO_PAGE_MASK;
|
||||
|
||||
for (i = 1; i < nelems; i++)
|
||||
if (sglist[i].dma_length == 0)
|
||||
break;
|
||||
i--;
|
||||
npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) -
|
||||
bus_addr) >> IO_PAGE_SHIFT;
|
||||
|
||||
base = iommu->page_table +
|
||||
((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
|
||||
for (i = 0; i < npages; i++)
|
||||
iopte_val(base[i]) = 0UL;
|
||||
free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction)
|
||||
{
|
||||
struct sbus_info *info;
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
unsigned long flags, npages;
|
||||
|
||||
info = sdev->bus->iommu;
|
||||
iommu = &info->iommu;
|
||||
strbuf = &info->strbuf;
|
||||
|
||||
npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
|
||||
npages >>= IO_PAGE_SHIFT;
|
||||
bus_addr &= IO_PAGE_MASK;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t base, size_t size, int direction)
|
||||
{
|
||||
}
|
||||
|
||||
void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction)
|
||||
{
|
||||
struct sbus_info *info;
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
unsigned long flags, npages, i;
|
||||
u32 bus_addr;
|
||||
|
||||
info = sdev->bus->iommu;
|
||||
iommu = &info->iommu;
|
||||
strbuf = &info->strbuf;
|
||||
|
||||
bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
|
||||
for (i = 0; i < nelems; i++) {
|
||||
if (!sglist[i].dma_length)
|
||||
break;
|
||||
}
|
||||
i--;
|
||||
npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
|
||||
- bus_addr) >> IO_PAGE_SHIFT;
|
||||
|
||||
spin_lock_irqsave(&iommu->lock, flags);
|
||||
sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
|
||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||
}
|
||||
|
||||
void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction)
|
||||
{
|
||||
}
|
||||
|
||||
/* Enable 64-bit DVMA mode for the given device. */
|
||||
void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
|
||||
{
|
||||
struct sbus_info *info = sdev->bus->iommu;
|
||||
struct iommu *iommu = &info->iommu;
|
||||
struct iommu *iommu = sdev->ofdev.dev.archdata.iommu;
|
||||
int slot = sdev->slot;
|
||||
unsigned long cfg_reg;
|
||||
u64 val;
|
||||
|
@ -713,8 +194,7 @@ static unsigned long sysio_imap_to_iclr(unsigned long imap)
|
|||
unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
|
||||
{
|
||||
struct sbus_bus *sbus = (struct sbus_bus *)buscookie;
|
||||
struct sbus_info *info = sbus->iommu;
|
||||
struct iommu *iommu = &info->iommu;
|
||||
struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
|
||||
unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
|
||||
unsigned long imap, iclr;
|
||||
int sbus_level = 0;
|
||||
|
@ -776,8 +256,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
|
|||
static irqreturn_t sysio_ue_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct sbus_bus *sbus = dev_id;
|
||||
struct sbus_info *info = sbus->iommu;
|
||||
struct iommu *iommu = &info->iommu;
|
||||
struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
|
||||
unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
|
||||
unsigned long afsr_reg, afar_reg;
|
||||
unsigned long afsr, afar, error_bits;
|
||||
|
@ -849,8 +328,7 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id)
|
|||
static irqreturn_t sysio_ce_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct sbus_bus *sbus = dev_id;
|
||||
struct sbus_info *info = sbus->iommu;
|
||||
struct iommu *iommu = &info->iommu;
|
||||
struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
|
||||
unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
|
||||
unsigned long afsr_reg, afar_reg;
|
||||
unsigned long afsr, afar, error_bits;
|
||||
|
@ -927,8 +405,7 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id)
|
|||
static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct sbus_bus *sbus = dev_id;
|
||||
struct sbus_info *info = sbus->iommu;
|
||||
struct iommu *iommu = &info->iommu;
|
||||
struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
|
||||
unsigned long afsr_reg, afar_reg, reg_base;
|
||||
unsigned long afsr, afar, error_bits;
|
||||
int reported;
|
||||
|
@ -995,8 +472,7 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id)
|
|||
|
||||
static void __init sysio_register_error_handlers(struct sbus_bus *sbus)
|
||||
{
|
||||
struct sbus_info *info = sbus->iommu;
|
||||
struct iommu *iommu = &info->iommu;
|
||||
struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
|
||||
unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
|
||||
unsigned int irq;
|
||||
u64 control;
|
||||
|
@ -1041,7 +517,6 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
|
|||
{
|
||||
const struct linux_prom64_registers *pr;
|
||||
struct device_node *dp;
|
||||
struct sbus_info *info;
|
||||
struct iommu *iommu;
|
||||
struct strbuf *strbuf;
|
||||
unsigned long regs, reg_base;
|
||||
|
@ -1054,25 +529,28 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
|
|||
|
||||
pr = of_get_property(dp, "reg", NULL);
|
||||
if (!pr) {
|
||||
prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n");
|
||||
prom_printf("sbus_iommu_init: Cannot map SYSIO "
|
||||
"control registers.\n");
|
||||
prom_halt();
|
||||
}
|
||||
regs = pr->phys_addr;
|
||||
|
||||
info = kzalloc(sizeof(*info), GFP_ATOMIC);
|
||||
if (info == NULL) {
|
||||
prom_printf("sbus_iommu_init: Fatal error, "
|
||||
"kmalloc(info) failed\n");
|
||||
prom_halt();
|
||||
}
|
||||
iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC);
|
||||
if (!iommu)
|
||||
goto fatal_memory_error;
|
||||
strbuf = kzalloc(sizeof(*strbuf), GFP_ATOMIC);
|
||||
if (!strbuf)
|
||||
goto fatal_memory_error;
|
||||
|
||||
iommu = &info->iommu;
|
||||
strbuf = &info->strbuf;
|
||||
sbus->ofdev.dev.archdata.iommu = iommu;
|
||||
sbus->ofdev.dev.archdata.stc = strbuf;
|
||||
|
||||
reg_base = regs + SYSIO_IOMMUREG_BASE;
|
||||
iommu->iommu_control = reg_base + IOMMU_CONTROL;
|
||||
iommu->iommu_tsbbase = reg_base + IOMMU_TSBBASE;
|
||||
iommu->iommu_flush = reg_base + IOMMU_FLUSH;
|
||||
iommu->iommu_tags = iommu->iommu_control +
|
||||
(IOMMU_TAGDIAG - IOMMU_CONTROL);
|
||||
|
||||
reg_base = regs + SYSIO_STRBUFREG_BASE;
|
||||
strbuf->strbuf_control = reg_base + STRBUF_CONTROL;
|
||||
|
@ -1093,14 +571,12 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
|
|||
*/
|
||||
iommu->write_complete_reg = regs + 0x2000UL;
|
||||
|
||||
/* Link into SYSIO software state. */
|
||||
sbus->iommu = info;
|
||||
|
||||
printk("SYSIO: UPA portID %x, at %016lx\n",
|
||||
sbus->portid, regs);
|
||||
|
||||
/* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */
|
||||
sbus_iommu_table_init(iommu, IO_TSB_SIZE);
|
||||
if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff))
|
||||
goto fatal_memory_error;
|
||||
|
||||
control = upa_readq(iommu->iommu_control);
|
||||
control = ((7UL << 16UL) |
|
||||
|
@ -1157,6 +633,10 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
|
|||
starfire_hookup(sbus->portid);
|
||||
|
||||
sysio_register_error_handlers(sbus);
|
||||
return;
|
||||
|
||||
fatal_memory_error:
|
||||
prom_printf("sbus_iommu_init: Fatal memory allocation error.\n");
|
||||
}
|
||||
|
||||
void sbus_fill_device_irq(struct sbus_dev *sdev)
|
||||
|
|
|
@ -1460,6 +1460,74 @@ static int cmos_set_rtc_time(struct rtc_time *rtc_tm)
|
|||
}
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
static void mostek_get_rtc_time(struct rtc_time *rtc_tm)
|
||||
{
|
||||
void __iomem *regs = mstk48t02_regs;
|
||||
u8 tmp;
|
||||
|
||||
spin_lock_irq(&mostek_lock);
|
||||
|
||||
tmp = mostek_read(regs + MOSTEK_CREG);
|
||||
tmp |= MSTK_CREG_READ;
|
||||
mostek_write(regs + MOSTEK_CREG, tmp);
|
||||
|
||||
rtc_tm->tm_sec = MSTK_REG_SEC(regs);
|
||||
rtc_tm->tm_min = MSTK_REG_MIN(regs);
|
||||
rtc_tm->tm_hour = MSTK_REG_HOUR(regs);
|
||||
rtc_tm->tm_mday = MSTK_REG_DOM(regs);
|
||||
rtc_tm->tm_mon = MSTK_REG_MONTH(regs);
|
||||
rtc_tm->tm_year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) );
|
||||
rtc_tm->tm_wday = MSTK_REG_DOW(regs);
|
||||
|
||||
tmp = mostek_read(regs + MOSTEK_CREG);
|
||||
tmp &= ~MSTK_CREG_READ;
|
||||
mostek_write(regs + MOSTEK_CREG, tmp);
|
||||
|
||||
spin_unlock_irq(&mostek_lock);
|
||||
|
||||
rtc_tm->tm_mon--;
|
||||
rtc_tm->tm_wday--;
|
||||
rtc_tm->tm_year -= 1900;
|
||||
}
|
||||
|
||||
static int mostek_set_rtc_time(struct rtc_time *rtc_tm)
|
||||
{
|
||||
unsigned char mon, day, hrs, min, sec, wday;
|
||||
void __iomem *regs = mstk48t02_regs;
|
||||
unsigned int yrs;
|
||||
u8 tmp;
|
||||
|
||||
yrs = rtc_tm->tm_year + 1900;
|
||||
mon = rtc_tm->tm_mon + 1;
|
||||
day = rtc_tm->tm_mday;
|
||||
wday = rtc_tm->tm_wday + 1;
|
||||
hrs = rtc_tm->tm_hour;
|
||||
min = rtc_tm->tm_min;
|
||||
sec = rtc_tm->tm_sec;
|
||||
|
||||
spin_lock_irq(&mostek_lock);
|
||||
|
||||
tmp = mostek_read(regs + MOSTEK_CREG);
|
||||
tmp |= MSTK_CREG_WRITE;
|
||||
mostek_write(regs + MOSTEK_CREG, tmp);
|
||||
|
||||
MSTK_SET_REG_SEC(regs, sec);
|
||||
MSTK_SET_REG_MIN(regs, min);
|
||||
MSTK_SET_REG_HOUR(regs, hrs);
|
||||
MSTK_SET_REG_DOW(regs, wday);
|
||||
MSTK_SET_REG_DOM(regs, day);
|
||||
MSTK_SET_REG_MONTH(regs, mon);
|
||||
MSTK_SET_REG_YEAR(regs, yrs - MSTK_YEAR_ZERO);
|
||||
|
||||
tmp = mostek_read(regs + MOSTEK_CREG);
|
||||
tmp &= ~MSTK_CREG_WRITE;
|
||||
mostek_write(regs + MOSTEK_CREG, tmp);
|
||||
|
||||
spin_unlock_irq(&mostek_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mini_rtc_ops {
|
||||
void (*get_rtc_time)(struct rtc_time *);
|
||||
int (*set_rtc_time)(struct rtc_time *);
|
||||
|
@ -1487,6 +1555,11 @@ static struct mini_rtc_ops cmos_rtc_ops = {
|
|||
};
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
static struct mini_rtc_ops mostek_rtc_ops = {
|
||||
.get_rtc_time = mostek_get_rtc_time,
|
||||
.set_rtc_time = mostek_set_rtc_time,
|
||||
};
|
||||
|
||||
static struct mini_rtc_ops *mini_rtc_ops;
|
||||
|
||||
static inline void mini_get_rtc_time(struct rtc_time *time)
|
||||
|
@ -1615,6 +1688,8 @@ static int __init rtc_mini_init(void)
|
|||
else if (ds1287_regs)
|
||||
mini_rtc_ops = &cmos_rtc_ops;
|
||||
#endif /* CONFIG_PCI */
|
||||
else if (mstk48t02_regs)
|
||||
mini_rtc_ops = &mostek_rtc_ops;
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
|
|
|
@ -2134,12 +2134,20 @@ static void user_instruction_dump (unsigned int __user *pc)
|
|||
void show_stack(struct task_struct *tsk, unsigned long *_ksp)
|
||||
{
|
||||
unsigned long pc, fp, thread_base, ksp;
|
||||
void *tp = task_stack_page(tsk);
|
||||
struct thread_info *tp;
|
||||
struct reg_window *rw;
|
||||
int count = 0;
|
||||
|
||||
ksp = (unsigned long) _ksp;
|
||||
|
||||
if (!tsk)
|
||||
tsk = current;
|
||||
tp = task_thread_info(tsk);
|
||||
if (ksp == 0UL) {
|
||||
if (tsk == current)
|
||||
asm("mov %%fp, %0" : "=r" (ksp));
|
||||
else
|
||||
ksp = tp->ksp;
|
||||
}
|
||||
if (tp == current_thread_info())
|
||||
flushw_all();
|
||||
|
||||
|
@ -2168,11 +2176,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
|
|||
|
||||
void dump_stack(void)
|
||||
{
|
||||
unsigned long *ksp;
|
||||
|
||||
__asm__ __volatile__("mov %%fp, %0"
|
||||
: "=r" (ksp));
|
||||
show_stack(current, ksp);
|
||||
show_stack(current, NULL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dump_stack);
|
||||
|
|
|
@ -112,15 +112,12 @@ static void __kprobes unhandled_fault(unsigned long address,
|
|||
|
||||
static void bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr)
|
||||
{
|
||||
unsigned long *ksp;
|
||||
|
||||
printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n",
|
||||
regs->tpc);
|
||||
printk(KERN_CRIT "OOPS: RPC [%016lx]\n", regs->u_regs[15]);
|
||||
print_symbol("RPC: <%s>\n", regs->u_regs[15]);
|
||||
printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr);
|
||||
__asm__("mov %%sp, %0" : "=r" (ksp));
|
||||
show_stack(current, ksp);
|
||||
dump_stack();
|
||||
unhandled_fault(regs->tpc, current, regs);
|
||||
}
|
||||
|
||||
|
|
|
@ -210,6 +210,10 @@ static void __init walk_children(struct device_node *dp, struct sbus_dev *parent
|
|||
|
||||
sdev->bus = sbus;
|
||||
sdev->parent = parent;
|
||||
sdev->ofdev.dev.archdata.iommu =
|
||||
sbus->ofdev.dev.archdata.iommu;
|
||||
sdev->ofdev.dev.archdata.stc =
|
||||
sbus->ofdev.dev.archdata.stc;
|
||||
|
||||
fill_sbus_device(dp, sdev);
|
||||
|
||||
|
@ -269,6 +273,11 @@ static void __init build_one_sbus(struct device_node *dp, int num_sbus)
|
|||
|
||||
sdev->bus = sbus;
|
||||
sdev->parent = NULL;
|
||||
sdev->ofdev.dev.archdata.iommu =
|
||||
sbus->ofdev.dev.archdata.iommu;
|
||||
sdev->ofdev.dev.archdata.stc =
|
||||
sbus->ofdev.dev.archdata.stc;
|
||||
|
||||
fill_sbus_device(dev_dp, sdev);
|
||||
|
||||
walk_children(dev_dp, sdev, sbus);
|
||||
|
|
|
@ -279,90 +279,91 @@ static void __devinit bw2_do_default_mode(struct bw2_par *par,
|
|||
}
|
||||
}
|
||||
|
||||
struct all_info {
|
||||
struct fb_info info;
|
||||
struct bw2_par par;
|
||||
};
|
||||
|
||||
static int __devinit bw2_init_one(struct of_device *op)
|
||||
static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->node;
|
||||
struct all_info *all;
|
||||
struct fb_info *info;
|
||||
struct bw2_par *par;
|
||||
int linebytes, err;
|
||||
|
||||
all = kzalloc(sizeof(*all), GFP_KERNEL);
|
||||
if (!all)
|
||||
return -ENOMEM;
|
||||
info = framebuffer_alloc(sizeof(struct bw2_par), &op->dev);
|
||||
|
||||
spin_lock_init(&all->par.lock);
|
||||
err = -ENOMEM;
|
||||
if (!info)
|
||||
goto out_err;
|
||||
par = info->par;
|
||||
|
||||
all->par.physbase = op->resource[0].start;
|
||||
all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
spin_lock_init(&par->lock);
|
||||
|
||||
sbusfb_fill_var(&all->info.var, dp->node, 1);
|
||||
par->physbase = op->resource[0].start;
|
||||
par->which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
|
||||
sbusfb_fill_var(&info->var, dp->node, 1);
|
||||
linebytes = of_getintprop_default(dp, "linebytes",
|
||||
all->info.var.xres);
|
||||
info->var.xres);
|
||||
|
||||
all->info.var.red.length = all->info.var.green.length =
|
||||
all->info.var.blue.length = all->info.var.bits_per_pixel;
|
||||
all->info.var.red.offset = all->info.var.green.offset =
|
||||
all->info.var.blue.offset = 0;
|
||||
info->var.red.length = info->var.green.length =
|
||||
info->var.blue.length = info->var.bits_per_pixel;
|
||||
info->var.red.offset = info->var.green.offset =
|
||||
info->var.blue.offset = 0;
|
||||
|
||||
all->par.regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
|
||||
sizeof(struct bw2_regs), "bw2 regs");
|
||||
par->regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
|
||||
sizeof(struct bw2_regs), "bw2 regs");
|
||||
if (!par->regs)
|
||||
goto out_release_fb;
|
||||
|
||||
if (!of_find_property(dp, "width", NULL))
|
||||
bw2_do_default_mode(&all->par, &all->info, &linebytes);
|
||||
bw2_do_default_mode(par, info, &linebytes);
|
||||
|
||||
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
|
||||
par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
|
||||
|
||||
all->info.flags = FBINFO_DEFAULT;
|
||||
all->info.fbops = &bw2_ops;
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
info->fbops = &bw2_ops;
|
||||
|
||||
all->info.screen_base =
|
||||
of_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram");
|
||||
all->info.par = &all->par;
|
||||
info->screen_base = of_ioremap(&op->resource[0], 0,
|
||||
par->fbsize, "bw2 ram");
|
||||
if (!info->screen_base)
|
||||
goto out_unmap_regs;
|
||||
|
||||
bw2_blank(0, &all->info);
|
||||
bw2_blank(0, info);
|
||||
|
||||
bw2_init_fix(&all->info, linebytes);
|
||||
bw2_init_fix(info, linebytes);
|
||||
|
||||
err= register_framebuffer(&all->info);
|
||||
if (err < 0) {
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.regs, sizeof(struct bw2_regs));
|
||||
of_iounmap(&op->resource[0],
|
||||
all->info.screen_base, all->par.fbsize);
|
||||
kfree(all);
|
||||
return err;
|
||||
}
|
||||
err = register_framebuffer(info);
|
||||
if (err < 0)
|
||||
goto out_unmap_screen;
|
||||
|
||||
dev_set_drvdata(&op->dev, all);
|
||||
dev_set_drvdata(&op->dev, info);
|
||||
|
||||
printk("%s: bwtwo at %lx:%lx\n",
|
||||
dp->full_name,
|
||||
all->par.which_io, all->par.physbase);
|
||||
dp->full_name, par->which_io, par->physbase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit bw2_probe(struct of_device *dev, const struct of_device_id *match)
|
||||
{
|
||||
struct of_device *op = to_of_device(&dev->dev);
|
||||
out_unmap_screen:
|
||||
of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
|
||||
|
||||
return bw2_init_one(op);
|
||||
out_unmap_regs:
|
||||
of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
|
||||
|
||||
out_release_fb:
|
||||
framebuffer_release(info);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit bw2_remove(struct of_device *op)
|
||||
{
|
||||
struct all_info *all = dev_get_drvdata(&op->dev);
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct bw2_par *par = info->par;
|
||||
|
||||
unregister_framebuffer(&all->info);
|
||||
unregister_framebuffer(info);
|
||||
|
||||
of_iounmap(&op->resource[0], all->par.regs, sizeof(struct bw2_regs));
|
||||
of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize);
|
||||
of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
|
||||
of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
|
||||
|
||||
kfree(all);
|
||||
framebuffer_release(info);
|
||||
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
|
||||
|
|
|
@ -448,81 +448,79 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = {
|
|||
{ .size = 0 }
|
||||
};
|
||||
|
||||
struct all_info {
|
||||
struct fb_info info;
|
||||
struct cg14_par par;
|
||||
};
|
||||
|
||||
static void cg14_unmap_regs(struct of_device *op, struct all_info *all)
|
||||
static void cg14_unmap_regs(struct of_device *op, struct fb_info *info,
|
||||
struct cg14_par *par)
|
||||
{
|
||||
if (all->par.regs)
|
||||
if (par->regs)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.regs, sizeof(struct cg14_regs));
|
||||
if (all->par.clut)
|
||||
par->regs, sizeof(struct cg14_regs));
|
||||
if (par->clut)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.clut, sizeof(struct cg14_clut));
|
||||
if (all->par.cursor)
|
||||
par->clut, sizeof(struct cg14_clut));
|
||||
if (par->cursor)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.cursor, sizeof(struct cg14_cursor));
|
||||
if (all->info.screen_base)
|
||||
par->cursor, sizeof(struct cg14_cursor));
|
||||
if (info->screen_base)
|
||||
of_iounmap(&op->resource[1],
|
||||
all->info.screen_base, all->par.fbsize);
|
||||
info->screen_base, par->fbsize);
|
||||
}
|
||||
|
||||
static int __devinit cg14_init_one(struct of_device *op)
|
||||
static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->node;
|
||||
struct all_info *all;
|
||||
struct fb_info *info;
|
||||
struct cg14_par *par;
|
||||
int is_8mb, linebytes, i, err;
|
||||
|
||||
all = kzalloc(sizeof(*all), GFP_KERNEL);
|
||||
if (!all)
|
||||
return -ENOMEM;
|
||||
info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev);
|
||||
|
||||
spin_lock_init(&all->par.lock);
|
||||
err = -ENOMEM;
|
||||
if (!info)
|
||||
goto out_err;
|
||||
par = info->par;
|
||||
|
||||
sbusfb_fill_var(&all->info.var, dp->node, 8);
|
||||
all->info.var.red.length = 8;
|
||||
all->info.var.green.length = 8;
|
||||
all->info.var.blue.length = 8;
|
||||
spin_lock_init(&par->lock);
|
||||
|
||||
sbusfb_fill_var(&info->var, dp->node, 8);
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
|
||||
linebytes = of_getintprop_default(dp, "linebytes",
|
||||
all->info.var.xres);
|
||||
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
|
||||
info->var.xres);
|
||||
par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
|
||||
|
||||
if (!strcmp(dp->parent->name, "sbus") ||
|
||||
!strcmp(dp->parent->name, "sbi")) {
|
||||
all->par.physbase = op->resource[0].start;
|
||||
all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
|
||||
par->physbase = op->resource[0].start;
|
||||
par->iospace = op->resource[0].flags & IORESOURCE_BITS;
|
||||
} else {
|
||||
all->par.physbase = op->resource[1].start;
|
||||
all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
|
||||
par->physbase = op->resource[1].start;
|
||||
par->iospace = op->resource[0].flags & IORESOURCE_BITS;
|
||||
}
|
||||
|
||||
all->par.regs = of_ioremap(&op->resource[0], 0,
|
||||
sizeof(struct cg14_regs), "cg14 regs");
|
||||
all->par.clut = of_ioremap(&op->resource[0], CG14_CLUT1,
|
||||
sizeof(struct cg14_clut), "cg14 clut");
|
||||
all->par.cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
|
||||
sizeof(struct cg14_cursor), "cg14 cursor");
|
||||
par->regs = of_ioremap(&op->resource[0], 0,
|
||||
sizeof(struct cg14_regs), "cg14 regs");
|
||||
par->clut = of_ioremap(&op->resource[0], CG14_CLUT1,
|
||||
sizeof(struct cg14_clut), "cg14 clut");
|
||||
par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
|
||||
sizeof(struct cg14_cursor), "cg14 cursor");
|
||||
|
||||
all->info.screen_base = of_ioremap(&op->resource[1], 0,
|
||||
all->par.fbsize, "cg14 ram");
|
||||
info->screen_base = of_ioremap(&op->resource[1], 0,
|
||||
par->fbsize, "cg14 ram");
|
||||
|
||||
if (!all->par.regs || !all->par.clut || !all->par.cursor ||
|
||||
!all->info.screen_base)
|
||||
cg14_unmap_regs(op, all);
|
||||
if (!par->regs || !par->clut || !par->cursor || !info->screen_base)
|
||||
goto out_unmap_regs;
|
||||
|
||||
is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
|
||||
(8 * 1024 * 1024));
|
||||
|
||||
BUILD_BUG_ON(sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map));
|
||||
BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map));
|
||||
|
||||
memcpy(&all->par.mmap_map, &__cg14_mmap_map,
|
||||
sizeof(all->par.mmap_map));
|
||||
memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map));
|
||||
|
||||
for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
|
||||
struct sbus_mmap_map *map = &all->par.mmap_map[i];
|
||||
struct sbus_mmap_map *map = &par->mmap_map[i];
|
||||
|
||||
if (!map->size)
|
||||
break;
|
||||
|
@ -536,59 +534,55 @@ static int __devinit cg14_init_one(struct of_device *op)
|
|||
map->size *= 2;
|
||||
}
|
||||
|
||||
all->par.mode = MDI_8_PIX;
|
||||
all->par.ramsize = (is_8mb ? 0x800000 : 0x400000);
|
||||
par->mode = MDI_8_PIX;
|
||||
par->ramsize = (is_8mb ? 0x800000 : 0x400000);
|
||||
|
||||
all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
|
||||
all->info.fbops = &cg14_ops;
|
||||
all->info.par = &all->par;
|
||||
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
|
||||
info->fbops = &cg14_ops;
|
||||
|
||||
__cg14_reset(&all->par);
|
||||
__cg14_reset(par);
|
||||
|
||||
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
|
||||
cg14_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
fb_set_cmap(&all->info.cmap, &all->info);
|
||||
if (fb_alloc_cmap(&info->cmap, 256, 0))
|
||||
goto out_unmap_regs;
|
||||
|
||||
cg14_init_fix(&all->info, linebytes, dp);
|
||||
fb_set_cmap(&info->cmap, info);
|
||||
|
||||
err = register_framebuffer(&all->info);
|
||||
if (err < 0) {
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
cg14_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return err;
|
||||
}
|
||||
cg14_init_fix(info, linebytes, dp);
|
||||
|
||||
dev_set_drvdata(&op->dev, all);
|
||||
err = register_framebuffer(info);
|
||||
if (err < 0)
|
||||
goto out_dealloc_cmap;
|
||||
|
||||
dev_set_drvdata(&op->dev, info);
|
||||
|
||||
printk("%s: cgfourteen at %lx:%lx, %dMB\n",
|
||||
dp->full_name,
|
||||
all->par.iospace, all->par.physbase,
|
||||
all->par.ramsize >> 20);
|
||||
par->iospace, par->physbase,
|
||||
par->ramsize >> 20);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit cg14_probe(struct of_device *dev, const struct of_device_id *match)
|
||||
{
|
||||
struct of_device *op = to_of_device(&dev->dev);
|
||||
out_dealloc_cmap:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
return cg14_init_one(op);
|
||||
out_unmap_regs:
|
||||
cg14_unmap_regs(op, info, par);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit cg14_remove(struct of_device *op)
|
||||
{
|
||||
struct all_info *all = dev_get_drvdata(&op->dev);
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct cg14_par *par = info->par;
|
||||
|
||||
unregister_framebuffer(&all->info);
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
unregister_framebuffer(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
cg14_unmap_regs(op, all);
|
||||
cg14_unmap_regs(op, info, par);
|
||||
|
||||
kfree(all);
|
||||
framebuffer_release(info);
|
||||
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
|
||||
|
|
|
@ -353,104 +353,102 @@ static void __devinit cg3_do_default_mode(struct cg3_par *par)
|
|||
}
|
||||
}
|
||||
|
||||
struct all_info {
|
||||
struct fb_info info;
|
||||
struct cg3_par par;
|
||||
};
|
||||
|
||||
static int __devinit cg3_init_one(struct of_device *op)
|
||||
{
|
||||
struct device_node *dp = op->node;
|
||||
struct all_info *all;
|
||||
int linebytes, err;
|
||||
|
||||
all = kzalloc(sizeof(*all), GFP_KERNEL);
|
||||
if (!all)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&all->par.lock);
|
||||
|
||||
all->par.physbase = op->resource[0].start;
|
||||
all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
|
||||
sbusfb_fill_var(&all->info.var, dp->node, 8);
|
||||
all->info.var.red.length = 8;
|
||||
all->info.var.green.length = 8;
|
||||
all->info.var.blue.length = 8;
|
||||
if (!strcmp(dp->name, "cgRDI"))
|
||||
all->par.flags |= CG3_FLAG_RDI;
|
||||
if (all->par.flags & CG3_FLAG_RDI)
|
||||
cg3_rdi_maybe_fixup_var(&all->info.var, dp);
|
||||
|
||||
linebytes = of_getintprop_default(dp, "linebytes",
|
||||
all->info.var.xres);
|
||||
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
|
||||
|
||||
all->par.regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET,
|
||||
sizeof(struct cg3_regs), "cg3 regs");
|
||||
|
||||
all->info.flags = FBINFO_DEFAULT;
|
||||
all->info.fbops = &cg3_ops;
|
||||
all->info.screen_base =
|
||||
of_ioremap(&op->resource[0], CG3_RAM_OFFSET,
|
||||
all->par.fbsize, "cg3 ram");
|
||||
all->info.par = &all->par;
|
||||
|
||||
cg3_blank(0, &all->info);
|
||||
|
||||
if (!of_find_property(dp, "width", NULL))
|
||||
cg3_do_default_mode(&all->par);
|
||||
|
||||
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.regs, sizeof(struct cg3_regs));
|
||||
of_iounmap(&op->resource[0],
|
||||
all->info.screen_base, all->par.fbsize);
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
fb_set_cmap(&all->info.cmap, &all->info);
|
||||
|
||||
cg3_init_fix(&all->info, linebytes, dp);
|
||||
|
||||
err = register_framebuffer(&all->info);
|
||||
if (err < 0) {
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.regs, sizeof(struct cg3_regs));
|
||||
of_iounmap(&op->resource[0],
|
||||
all->info.screen_base, all->par.fbsize);
|
||||
kfree(all);
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&op->dev, all);
|
||||
|
||||
printk("%s: cg3 at %lx:%lx\n",
|
||||
dp->full_name, all->par.which_io, all->par.physbase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit cg3_probe(struct of_device *dev,
|
||||
static int __devinit cg3_probe(struct of_device *op,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
struct of_device *op = to_of_device(&dev->dev);
|
||||
struct device_node *dp = op->node;
|
||||
struct fb_info *info;
|
||||
struct cg3_par *par;
|
||||
int linebytes, err;
|
||||
|
||||
return cg3_init_one(op);
|
||||
info = framebuffer_alloc(sizeof(struct cg3_par), &op->dev);
|
||||
|
||||
err = -ENOMEM;
|
||||
if (!info)
|
||||
goto out_err;
|
||||
par = info->par;
|
||||
|
||||
spin_lock_init(&par->lock);
|
||||
|
||||
par->physbase = op->resource[0].start;
|
||||
par->which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
|
||||
sbusfb_fill_var(&info->var, dp->node, 8);
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
if (!strcmp(dp->name, "cgRDI"))
|
||||
par->flags |= CG3_FLAG_RDI;
|
||||
if (par->flags & CG3_FLAG_RDI)
|
||||
cg3_rdi_maybe_fixup_var(&info->var, dp);
|
||||
|
||||
linebytes = of_getintprop_default(dp, "linebytes",
|
||||
info->var.xres);
|
||||
par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
|
||||
|
||||
par->regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET,
|
||||
sizeof(struct cg3_regs), "cg3 regs");
|
||||
if (!par->regs)
|
||||
goto out_release_fb;
|
||||
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
info->fbops = &cg3_ops;
|
||||
info->screen_base = of_ioremap(&op->resource[0], CG3_RAM_OFFSET,
|
||||
par->fbsize, "cg3 ram");
|
||||
if (!info->screen_base)
|
||||
goto out_unmap_regs;
|
||||
|
||||
cg3_blank(0, info);
|
||||
|
||||
if (!of_find_property(dp, "width", NULL))
|
||||
cg3_do_default_mode(par);
|
||||
|
||||
if (fb_alloc_cmap(&info->cmap, 256, 0))
|
||||
goto out_unmap_screen;
|
||||
|
||||
fb_set_cmap(&info->cmap, info);
|
||||
|
||||
cg3_init_fix(info, linebytes, dp);
|
||||
|
||||
err = register_framebuffer(info);
|
||||
if (err < 0)
|
||||
goto out_dealloc_cmap;
|
||||
|
||||
dev_set_drvdata(&op->dev, info);
|
||||
|
||||
printk("%s: cg3 at %lx:%lx\n",
|
||||
dp->full_name, par->which_io, par->physbase);
|
||||
|
||||
return 0;
|
||||
|
||||
out_dealloc_cmap:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
out_unmap_screen:
|
||||
of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
|
||||
|
||||
out_unmap_regs:
|
||||
of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
|
||||
|
||||
out_release_fb:
|
||||
framebuffer_release(info);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit cg3_remove(struct of_device *op)
|
||||
{
|
||||
struct all_info *all = dev_get_drvdata(&op->dev);
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct cg3_par *par = info->par;
|
||||
|
||||
unregister_framebuffer(&all->info);
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
unregister_framebuffer(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
of_iounmap(&op->resource[0], all->par.regs, sizeof(struct cg3_regs));
|
||||
of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize);
|
||||
of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
|
||||
of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
|
||||
|
||||
kfree(all);
|
||||
framebuffer_release(info);
|
||||
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
|
||||
|
|
|
@ -653,135 +653,120 @@ static void cg6_chip_init(struct fb_info *info)
|
|||
sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
|
||||
}
|
||||
|
||||
struct all_info {
|
||||
struct fb_info info;
|
||||
struct cg6_par par;
|
||||
};
|
||||
|
||||
static void cg6_unmap_regs(struct of_device *op, struct all_info *all)
|
||||
static void cg6_unmap_regs(struct of_device *op, struct fb_info *info,
|
||||
struct cg6_par *par)
|
||||
{
|
||||
if (all->par.fbc)
|
||||
of_iounmap(&op->resource[0], all->par.fbc, 4096);
|
||||
if (all->par.tec)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.tec, sizeof(struct cg6_tec));
|
||||
if (all->par.thc)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.thc, sizeof(struct cg6_thc));
|
||||
if (all->par.bt)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.bt, sizeof(struct bt_regs));
|
||||
if (all->par.fhc)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.fhc, sizeof(u32));
|
||||
if (par->fbc)
|
||||
of_iounmap(&op->resource[0], par->fbc, 4096);
|
||||
if (par->tec)
|
||||
of_iounmap(&op->resource[0], par->tec, sizeof(struct cg6_tec));
|
||||
if (par->thc)
|
||||
of_iounmap(&op->resource[0], par->thc, sizeof(struct cg6_thc));
|
||||
if (par->bt)
|
||||
of_iounmap(&op->resource[0], par->bt, sizeof(struct bt_regs));
|
||||
if (par->fhc)
|
||||
of_iounmap(&op->resource[0], par->fhc, sizeof(u32));
|
||||
|
||||
if (all->info.screen_base)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->info.screen_base, all->par.fbsize);
|
||||
if (info->screen_base)
|
||||
of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
|
||||
}
|
||||
|
||||
static int __devinit cg6_init_one(struct of_device *op)
|
||||
static int __devinit cg6_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->node;
|
||||
struct all_info *all;
|
||||
struct fb_info *info;
|
||||
struct cg6_par *par;
|
||||
int linebytes, err;
|
||||
|
||||
all = kzalloc(sizeof(*all), GFP_KERNEL);
|
||||
if (!all)
|
||||
return -ENOMEM;
|
||||
info = framebuffer_alloc(sizeof(struct cg6_par), &op->dev);
|
||||
|
||||
spin_lock_init(&all->par.lock);
|
||||
err = -ENOMEM;
|
||||
if (!info)
|
||||
goto out_err;
|
||||
par = info->par;
|
||||
|
||||
all->par.physbase = op->resource[0].start;
|
||||
all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
spin_lock_init(&par->lock);
|
||||
|
||||
sbusfb_fill_var(&all->info.var, dp->node, 8);
|
||||
all->info.var.red.length = 8;
|
||||
all->info.var.green.length = 8;
|
||||
all->info.var.blue.length = 8;
|
||||
par->physbase = op->resource[0].start;
|
||||
par->which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
|
||||
sbusfb_fill_var(&info->var, dp->node, 8);
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
|
||||
linebytes = of_getintprop_default(dp, "linebytes",
|
||||
all->info.var.xres);
|
||||
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
|
||||
info->var.xres);
|
||||
par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
|
||||
if (of_find_property(dp, "dblbuf", NULL))
|
||||
all->par.fbsize *= 4;
|
||||
par->fbsize *= 4;
|
||||
|
||||
all->par.fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
|
||||
par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
|
||||
4096, "cgsix fbc");
|
||||
all->par.tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
|
||||
par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
|
||||
sizeof(struct cg6_tec), "cgsix tec");
|
||||
all->par.thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
|
||||
par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
|
||||
sizeof(struct cg6_thc), "cgsix thc");
|
||||
all->par.bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
|
||||
par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
|
||||
sizeof(struct bt_regs), "cgsix dac");
|
||||
all->par.fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
|
||||
par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
|
||||
sizeof(u32), "cgsix fhc");
|
||||
|
||||
all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
|
||||
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
|
||||
FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
|
||||
all->info.fbops = &cg6_ops;
|
||||
info->fbops = &cg6_ops;
|
||||
|
||||
all->info.screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
|
||||
all->par.fbsize, "cgsix ram");
|
||||
if (!all->par.fbc || !all->par.tec || !all->par.thc ||
|
||||
!all->par.bt || !all->par.fhc || !all->info.screen_base) {
|
||||
cg6_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
info->screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
|
||||
par->fbsize, "cgsix ram");
|
||||
if (!par->fbc || !par->tec || !par->thc ||
|
||||
!par->bt || !par->fhc || !info->screen_base)
|
||||
goto out_unmap_regs;
|
||||
|
||||
all->info.par = &all->par;
|
||||
info->var.accel_flags = FB_ACCELF_TEXT;
|
||||
|
||||
all->info.var.accel_flags = FB_ACCELF_TEXT;
|
||||
cg6_bt_init(par);
|
||||
cg6_chip_init(info);
|
||||
cg6_blank(0, info);
|
||||
|
||||
cg6_bt_init(&all->par);
|
||||
cg6_chip_init(&all->info);
|
||||
cg6_blank(0, &all->info);
|
||||
if (fb_alloc_cmap(&info->cmap, 256, 0))
|
||||
goto out_unmap_regs;
|
||||
|
||||
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
|
||||
cg6_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
fb_set_cmap(&info->cmap, info);
|
||||
cg6_init_fix(info, linebytes);
|
||||
|
||||
fb_set_cmap(&all->info.cmap, &all->info);
|
||||
cg6_init_fix(&all->info, linebytes);
|
||||
err = register_framebuffer(info);
|
||||
if (err < 0)
|
||||
goto out_dealloc_cmap;
|
||||
|
||||
err = register_framebuffer(&all->info);
|
||||
if (err < 0) {
|
||||
cg6_unmap_regs(op, all);
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
kfree(all);
|
||||
return err;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&op->dev, all);
|
||||
dev_set_drvdata(&op->dev, info);
|
||||
|
||||
printk("%s: CGsix [%s] at %lx:%lx\n",
|
||||
dp->full_name,
|
||||
all->info.fix.id,
|
||||
all->par.which_io, all->par.physbase);
|
||||
dp->full_name, info->fix.id,
|
||||
par->which_io, par->physbase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit cg6_probe(struct of_device *dev, const struct of_device_id *match)
|
||||
{
|
||||
struct of_device *op = to_of_device(&dev->dev);
|
||||
out_dealloc_cmap:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
return cg6_init_one(op);
|
||||
out_unmap_regs:
|
||||
cg6_unmap_regs(op, info, par);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit cg6_remove(struct of_device *op)
|
||||
{
|
||||
struct all_info *all = dev_get_drvdata(&op->dev);
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct cg6_par *par = info->par;
|
||||
|
||||
unregister_framebuffer(&all->info);
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
unregister_framebuffer(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
cg6_unmap_regs(op, all);
|
||||
cg6_unmap_regs(op, info, par);
|
||||
|
||||
kfree(all);
|
||||
framebuffer_release(info);
|
||||
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
|
||||
|
|
|
@ -371,6 +371,8 @@ struct ffb_par {
|
|||
unsigned long fbsize;
|
||||
|
||||
int board_type;
|
||||
|
||||
u32 pseudo_palette[16];
|
||||
};
|
||||
|
||||
static void FFBFifo(struct ffb_par *par, int n)
|
||||
|
@ -900,75 +902,67 @@ ffb_init_fix(struct fb_info *info)
|
|||
info->fix.accel = FB_ACCEL_SUN_CREATOR;
|
||||
}
|
||||
|
||||
struct all_info {
|
||||
struct fb_info info;
|
||||
struct ffb_par par;
|
||||
u32 pseudo_palette[16];
|
||||
};
|
||||
|
||||
static int ffb_init_one(struct of_device *op)
|
||||
static int __devinit ffb_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->node;
|
||||
struct ffb_fbc __iomem *fbc;
|
||||
struct ffb_dac __iomem *dac;
|
||||
struct all_info *all;
|
||||
int err;
|
||||
struct fb_info *info;
|
||||
struct ffb_par *par;
|
||||
u32 dac_pnum, dac_rev, dac_mrev;
|
||||
int err;
|
||||
|
||||
all = kzalloc(sizeof(*all), GFP_KERNEL);
|
||||
if (!all)
|
||||
return -ENOMEM;
|
||||
info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev);
|
||||
|
||||
spin_lock_init(&all->par.lock);
|
||||
all->par.fbc = of_ioremap(&op->resource[2], 0,
|
||||
sizeof(struct ffb_fbc), "ffb fbc");
|
||||
if (!all->par.fbc) {
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
err = -ENOMEM;
|
||||
if (!info)
|
||||
goto out_err;
|
||||
|
||||
all->par.dac = of_ioremap(&op->resource[1], 0,
|
||||
sizeof(struct ffb_dac), "ffb dac");
|
||||
if (!all->par.dac) {
|
||||
of_iounmap(&op->resource[2],
|
||||
all->par.fbc, sizeof(struct ffb_fbc));
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
par = info->par;
|
||||
|
||||
all->par.rop_cache = FFB_ROP_NEW;
|
||||
all->par.physbase = op->resource[0].start;
|
||||
spin_lock_init(&par->lock);
|
||||
par->fbc = of_ioremap(&op->resource[2], 0,
|
||||
sizeof(struct ffb_fbc), "ffb fbc");
|
||||
if (!par->fbc)
|
||||
goto out_release_fb;
|
||||
|
||||
par->dac = of_ioremap(&op->resource[1], 0,
|
||||
sizeof(struct ffb_dac), "ffb dac");
|
||||
if (!par->dac)
|
||||
goto out_unmap_fbc;
|
||||
|
||||
par->rop_cache = FFB_ROP_NEW;
|
||||
par->physbase = op->resource[0].start;
|
||||
|
||||
/* Don't mention copyarea, so SCROLL_REDRAW is always
|
||||
* used. It is the fastest on this chip.
|
||||
*/
|
||||
all->info.flags = (FBINFO_DEFAULT |
|
||||
/* FBINFO_HWACCEL_COPYAREA | */
|
||||
FBINFO_HWACCEL_FILLRECT |
|
||||
FBINFO_HWACCEL_IMAGEBLIT);
|
||||
all->info.fbops = &ffb_ops;
|
||||
all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF;
|
||||
all->info.par = &all->par;
|
||||
all->info.pseudo_palette = all->pseudo_palette;
|
||||
info->flags = (FBINFO_DEFAULT |
|
||||
/* FBINFO_HWACCEL_COPYAREA | */
|
||||
FBINFO_HWACCEL_FILLRECT |
|
||||
FBINFO_HWACCEL_IMAGEBLIT);
|
||||
|
||||
sbusfb_fill_var(&all->info.var, dp->node, 32);
|
||||
all->par.fbsize = PAGE_ALIGN(all->info.var.xres *
|
||||
all->info.var.yres *
|
||||
4);
|
||||
ffb_fixup_var_rgb(&all->info.var);
|
||||
info->fbops = &ffb_ops;
|
||||
|
||||
all->info.var.accel_flags = FB_ACCELF_TEXT;
|
||||
info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;
|
||||
info->pseudo_palette = par->pseudo_palette;
|
||||
|
||||
sbusfb_fill_var(&info->var, dp->node, 32);
|
||||
par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);
|
||||
ffb_fixup_var_rgb(&info->var);
|
||||
|
||||
info->var.accel_flags = FB_ACCELF_TEXT;
|
||||
|
||||
if (!strcmp(dp->name, "SUNW,afb"))
|
||||
all->par.flags |= FFB_FLAG_AFB;
|
||||
par->flags |= FFB_FLAG_AFB;
|
||||
|
||||
all->par.board_type = of_getintprop_default(dp, "board_type", 0);
|
||||
par->board_type = of_getintprop_default(dp, "board_type", 0);
|
||||
|
||||
fbc = all->par.fbc;
|
||||
fbc = par->fbc;
|
||||
if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
|
||||
upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
|
||||
|
||||
dac = all->par.dac;
|
||||
dac = par->dac;
|
||||
upa_writel(FFB_DAC_DID, &dac->type);
|
||||
dac_pnum = upa_readl(&dac->value);
|
||||
dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
|
||||
|
@ -985,76 +979,70 @@ static int ffb_init_one(struct of_device *op)
|
|||
* cursor logic. We identify Pacifica 1 as not Pacifica 2, the
|
||||
* latter having a part number value of 0x236e.
|
||||
*/
|
||||
if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
|
||||
all->par.flags &= ~FFB_FLAG_INVCURSOR;
|
||||
if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
|
||||
par->flags &= ~FFB_FLAG_INVCURSOR;
|
||||
} else {
|
||||
if (dac_mrev < 3)
|
||||
all->par.flags |= FFB_FLAG_INVCURSOR;
|
||||
par->flags |= FFB_FLAG_INVCURSOR;
|
||||
}
|
||||
|
||||
ffb_switch_from_graph(&all->par);
|
||||
ffb_switch_from_graph(par);
|
||||
|
||||
/* Unblank it just to be sure. When there are multiple
|
||||
* FFB/AFB cards in the system, or it is not the OBP
|
||||
* chosen console, it will have video outputs off in
|
||||
* the DAC.
|
||||
*/
|
||||
ffb_blank(0, &all->info);
|
||||
ffb_blank(0, info);
|
||||
|
||||
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
|
||||
printk(KERN_ERR "ffb: Could not allocate color map.\n");
|
||||
of_iounmap(&op->resource[2],
|
||||
all->par.fbc, sizeof(struct ffb_fbc));
|
||||
of_iounmap(&op->resource[1],
|
||||
all->par.dac, sizeof(struct ffb_dac));
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (fb_alloc_cmap(&info->cmap, 256, 0))
|
||||
goto out_unmap_dac;
|
||||
|
||||
ffb_init_fix(&all->info);
|
||||
ffb_init_fix(info);
|
||||
|
||||
err = register_framebuffer(&all->info);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "ffb: Could not register framebuffer.\n");
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
of_iounmap(&op->resource[2],
|
||||
all->par.fbc, sizeof(struct ffb_fbc));
|
||||
of_iounmap(&op->resource[1],
|
||||
all->par.dac, sizeof(struct ffb_dac));
|
||||
kfree(all);
|
||||
return err;
|
||||
}
|
||||
err = register_framebuffer(info);
|
||||
if (err < 0)
|
||||
goto out_dealloc_cmap;
|
||||
|
||||
dev_set_drvdata(&op->dev, all);
|
||||
dev_set_drvdata(&op->dev, info);
|
||||
|
||||
printk("%s: %s at %016lx, type %d, "
|
||||
"DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
|
||||
dp->full_name,
|
||||
((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
|
||||
all->par.physbase, all->par.board_type,
|
||||
((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
|
||||
par->physbase, par->board_type,
|
||||
dac_pnum, dac_rev, dac_mrev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit ffb_probe(struct of_device *dev, const struct of_device_id *match)
|
||||
{
|
||||
struct of_device *op = to_of_device(&dev->dev);
|
||||
out_dealloc_cmap:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
return ffb_init_one(op);
|
||||
out_unmap_dac:
|
||||
of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
|
||||
|
||||
out_unmap_fbc:
|
||||
of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
|
||||
|
||||
out_release_fb:
|
||||
framebuffer_release(info);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit ffb_remove(struct of_device *op)
|
||||
{
|
||||
struct all_info *all = dev_get_drvdata(&op->dev);
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct ffb_par *par = info->par;
|
||||
|
||||
unregister_framebuffer(&all->info);
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
unregister_framebuffer(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
of_iounmap(&op->resource[2], all->par.fbc, sizeof(struct ffb_fbc));
|
||||
of_iounmap(&op->resource[1], all->par.dac, sizeof(struct ffb_dac));
|
||||
of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
|
||||
of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
|
||||
|
||||
kfree(all);
|
||||
framebuffer_release(info);
|
||||
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
|
||||
|
|
|
@ -525,130 +525,123 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
|
|||
var->transp.length = 0;
|
||||
}
|
||||
|
||||
struct all_info {
|
||||
struct fb_info info;
|
||||
struct leo_par par;
|
||||
};
|
||||
|
||||
static void leo_unmap_regs(struct of_device *op, struct all_info *all)
|
||||
static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
|
||||
struct leo_par *par)
|
||||
{
|
||||
if (all->par.lc_ss0_usr)
|
||||
of_iounmap(&op->resource[0], all->par.lc_ss0_usr, 0x1000);
|
||||
if (all->par.ld_ss0)
|
||||
of_iounmap(&op->resource[0], all->par.ld_ss0, 0x1000);
|
||||
if (all->par.ld_ss1)
|
||||
of_iounmap(&op->resource[0], all->par.ld_ss1, 0x1000);
|
||||
if (all->par.lx_krn)
|
||||
of_iounmap(&op->resource[0], all->par.lx_krn, 0x1000);
|
||||
if (all->par.cursor)
|
||||
if (par->lc_ss0_usr)
|
||||
of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000);
|
||||
if (par->ld_ss0)
|
||||
of_iounmap(&op->resource[0], par->ld_ss0, 0x1000);
|
||||
if (par->ld_ss1)
|
||||
of_iounmap(&op->resource[0], par->ld_ss1, 0x1000);
|
||||
if (par->lx_krn)
|
||||
of_iounmap(&op->resource[0], par->lx_krn, 0x1000);
|
||||
if (par->cursor)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.cursor, sizeof(struct leo_cursor));
|
||||
if (all->info.screen_base)
|
||||
of_iounmap(&op->resource[0], all->info.screen_base, 0x800000);
|
||||
par->cursor, sizeof(struct leo_cursor));
|
||||
if (info->screen_base)
|
||||
of_iounmap(&op->resource[0], info->screen_base, 0x800000);
|
||||
}
|
||||
|
||||
static int __devinit leo_init_one(struct of_device *op)
|
||||
static int __devinit leo_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->node;
|
||||
struct all_info *all;
|
||||
struct fb_info *info;
|
||||
struct leo_par *par;
|
||||
int linebytes, err;
|
||||
|
||||
all = kzalloc(sizeof(*all), GFP_KERNEL);
|
||||
if (!all)
|
||||
return -ENOMEM;
|
||||
info = framebuffer_alloc(sizeof(struct leo_par), &op->dev);
|
||||
|
||||
spin_lock_init(&all->par.lock);
|
||||
err = -ENOMEM;
|
||||
if (!info)
|
||||
goto out_err;
|
||||
par = info->par;
|
||||
|
||||
all->par.physbase = op->resource[0].start;
|
||||
all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
spin_lock_init(&par->lock);
|
||||
|
||||
sbusfb_fill_var(&all->info.var, dp->node, 32);
|
||||
leo_fixup_var_rgb(&all->info.var);
|
||||
par->physbase = op->resource[0].start;
|
||||
par->which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
|
||||
sbusfb_fill_var(&info->var, dp->node, 32);
|
||||
leo_fixup_var_rgb(&info->var);
|
||||
|
||||
linebytes = of_getintprop_default(dp, "linebytes",
|
||||
all->info.var.xres);
|
||||
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
|
||||
info->var.xres);
|
||||
par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
|
||||
|
||||
all->par.lc_ss0_usr =
|
||||
par->lc_ss0_usr =
|
||||
of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR,
|
||||
0x1000, "leolc ss0usr");
|
||||
all->par.ld_ss0 =
|
||||
par->ld_ss0 =
|
||||
of_ioremap(&op->resource[0], LEO_OFF_LD_SS0,
|
||||
0x1000, "leold ss0");
|
||||
all->par.ld_ss1 =
|
||||
par->ld_ss1 =
|
||||
of_ioremap(&op->resource[0], LEO_OFF_LD_SS1,
|
||||
0x1000, "leold ss1");
|
||||
all->par.lx_krn =
|
||||
par->lx_krn =
|
||||
of_ioremap(&op->resource[0], LEO_OFF_LX_KRN,
|
||||
0x1000, "leolx krn");
|
||||
all->par.cursor =
|
||||
par->cursor =
|
||||
of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR,
|
||||
sizeof(struct leo_cursor), "leolx cursor");
|
||||
all->info.screen_base =
|
||||
info->screen_base =
|
||||
of_ioremap(&op->resource[0], LEO_OFF_SS0,
|
||||
0x800000, "leo ram");
|
||||
if (!all->par.lc_ss0_usr ||
|
||||
!all->par.ld_ss0 ||
|
||||
!all->par.ld_ss1 ||
|
||||
!all->par.lx_krn ||
|
||||
!all->par.cursor ||
|
||||
!all->info.screen_base) {
|
||||
leo_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!par->lc_ss0_usr ||
|
||||
!par->ld_ss0 ||
|
||||
!par->ld_ss1 ||
|
||||
!par->lx_krn ||
|
||||
!par->cursor ||
|
||||
!info->screen_base)
|
||||
goto out_unmap_regs;
|
||||
|
||||
all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
|
||||
all->info.fbops = &leo_ops;
|
||||
all->info.par = &all->par;
|
||||
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
|
||||
info->fbops = &leo_ops;
|
||||
|
||||
leo_init_wids(&all->info);
|
||||
leo_init_hw(&all->info);
|
||||
leo_init_wids(info);
|
||||
leo_init_hw(info);
|
||||
|
||||
leo_blank(0, &all->info);
|
||||
leo_blank(0, info);
|
||||
|
||||
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
|
||||
leo_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return -ENOMEM;;
|
||||
}
|
||||
if (fb_alloc_cmap(&info->cmap, 256, 0))
|
||||
goto out_unmap_regs;
|
||||
|
||||
leo_init_fix(&all->info, dp);
|
||||
leo_init_fix(info, dp);
|
||||
|
||||
err = register_framebuffer(&all->info);
|
||||
if (err < 0) {
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
leo_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return err;
|
||||
}
|
||||
err = register_framebuffer(info);
|
||||
if (err < 0)
|
||||
goto out_dealloc_cmap;
|
||||
|
||||
dev_set_drvdata(&op->dev, all);
|
||||
dev_set_drvdata(&op->dev, info);
|
||||
|
||||
printk("%s: leo at %lx:%lx\n",
|
||||
dp->full_name,
|
||||
all->par.which_io, all->par.physbase);
|
||||
par->which_io, par->physbase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit leo_probe(struct of_device *dev, const struct of_device_id *match)
|
||||
{
|
||||
struct of_device *op = to_of_device(&dev->dev);
|
||||
out_dealloc_cmap:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
return leo_init_one(op);
|
||||
out_unmap_regs:
|
||||
leo_unmap_regs(op, info, par);
|
||||
framebuffer_release(info);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit leo_remove(struct of_device *op)
|
||||
{
|
||||
struct all_info *all = dev_get_drvdata(&op->dev);
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct leo_par *par = info->par;
|
||||
|
||||
unregister_framebuffer(&all->info);
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
unregister_framebuffer(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
leo_unmap_regs(op, all);
|
||||
leo_unmap_regs(op, info, par);
|
||||
|
||||
kfree(all);
|
||||
framebuffer_release(info);
|
||||
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
|
||||
|
|
|
@ -255,107 +255,95 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
|
|||
info->fix.accel = FB_ACCEL_SUN_CGTHREE;
|
||||
}
|
||||
|
||||
struct all_info {
|
||||
struct fb_info info;
|
||||
struct p9100_par par;
|
||||
};
|
||||
|
||||
static int __devinit p9100_init_one(struct of_device *op)
|
||||
static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct device_node *dp = op->node;
|
||||
struct all_info *all;
|
||||
struct fb_info *info;
|
||||
struct p9100_par *par;
|
||||
int linebytes, err;
|
||||
|
||||
all = kzalloc(sizeof(*all), GFP_KERNEL);
|
||||
if (!all)
|
||||
return -ENOMEM;
|
||||
info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev);
|
||||
|
||||
spin_lock_init(&all->par.lock);
|
||||
err = -ENOMEM;
|
||||
if (!info)
|
||||
goto out_err;
|
||||
par = info->par;
|
||||
|
||||
spin_lock_init(&par->lock);
|
||||
|
||||
/* This is the framebuffer and the only resource apps can mmap. */
|
||||
all->par.physbase = op->resource[2].start;
|
||||
all->par.which_io = op->resource[2].flags & IORESOURCE_BITS;
|
||||
par->physbase = op->resource[2].start;
|
||||
par->which_io = op->resource[2].flags & IORESOURCE_BITS;
|
||||
|
||||
sbusfb_fill_var(&all->info.var, dp->node, 8);
|
||||
all->info.var.red.length = 8;
|
||||
all->info.var.green.length = 8;
|
||||
all->info.var.blue.length = 8;
|
||||
sbusfb_fill_var(&info->var, dp->node, 8);
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
|
||||
linebytes = of_getintprop_default(dp, "linebytes",
|
||||
all->info.var.xres);
|
||||
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
|
||||
linebytes = of_getintprop_default(dp, "linebytes", info->var.xres);
|
||||
par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
|
||||
|
||||
all->par.regs = of_ioremap(&op->resource[0], 0,
|
||||
sizeof(struct p9100_regs), "p9100 regs");
|
||||
if (!all->par.regs) {
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
par->regs = of_ioremap(&op->resource[0], 0,
|
||||
sizeof(struct p9100_regs), "p9100 regs");
|
||||
if (!par->regs)
|
||||
goto out_release_fb;
|
||||
|
||||
all->info.flags = FBINFO_DEFAULT;
|
||||
all->info.fbops = &p9100_ops;
|
||||
all->info.screen_base = of_ioremap(&op->resource[2], 0,
|
||||
all->par.fbsize, "p9100 ram");
|
||||
if (!all->info.screen_base) {
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.regs, sizeof(struct p9100_regs));
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
all->info.par = &all->par;
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
info->fbops = &p9100_ops;
|
||||
info->screen_base = of_ioremap(&op->resource[2], 0,
|
||||
par->fbsize, "p9100 ram");
|
||||
if (!info->screen_base)
|
||||
goto out_unmap_regs;
|
||||
|
||||
p9100_blank(0, &all->info);
|
||||
p9100_blank(0, info);
|
||||
|
||||
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.regs, sizeof(struct p9100_regs));
|
||||
of_iounmap(&op->resource[2],
|
||||
all->info.screen_base, all->par.fbsize);
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (fb_alloc_cmap(&info->cmap, 256, 0))
|
||||
goto out_unmap_screen;
|
||||
|
||||
p9100_init_fix(&all->info, linebytes, dp);
|
||||
p9100_init_fix(info, linebytes, dp);
|
||||
|
||||
err = register_framebuffer(&all->info);
|
||||
if (err < 0) {
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
of_iounmap(&op->resource[0],
|
||||
all->par.regs, sizeof(struct p9100_regs));
|
||||
of_iounmap(&op->resource[2],
|
||||
all->info.screen_base, all->par.fbsize);
|
||||
kfree(all);
|
||||
return err;
|
||||
}
|
||||
fb_set_cmap(&all->info.cmap, &all->info);
|
||||
err = register_framebuffer(info);
|
||||
if (err < 0)
|
||||
goto out_dealloc_cmap;
|
||||
|
||||
dev_set_drvdata(&op->dev, all);
|
||||
fb_set_cmap(&info->cmap, info);
|
||||
|
||||
dev_set_drvdata(&op->dev, info);
|
||||
|
||||
printk("%s: p9100 at %lx:%lx\n",
|
||||
dp->full_name,
|
||||
all->par.which_io, all->par.physbase);
|
||||
par->which_io, par->physbase);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit p9100_probe(struct of_device *dev, const struct of_device_id *match)
|
||||
{
|
||||
struct of_device *op = to_of_device(&dev->dev);
|
||||
out_dealloc_cmap:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
return p9100_init_one(op);
|
||||
out_unmap_screen:
|
||||
of_iounmap(&op->resource[2], info->screen_base, par->fbsize);
|
||||
|
||||
out_unmap_regs:
|
||||
of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
|
||||
|
||||
out_release_fb:
|
||||
framebuffer_release(info);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit p9100_remove(struct of_device *op)
|
||||
{
|
||||
struct all_info *all = dev_get_drvdata(&op->dev);
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct p9100_par *par = info->par;
|
||||
|
||||
unregister_framebuffer(&all->info);
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
unregister_framebuffer(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
of_iounmap(&op->resource[0], all->par.regs, sizeof(struct p9100_regs));
|
||||
of_iounmap(&op->resource[2], all->info.screen_base, all->par.fbsize);
|
||||
of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
|
||||
of_iounmap(&op->resource[2], info->screen_base, par->fbsize);
|
||||
|
||||
kfree(all);
|
||||
framebuffer_release(info);
|
||||
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
|
||||
|
|
|
@ -190,17 +190,6 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
|
|||
EXPORT_SYMBOL(sbusfb_ioctl_helper);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct fbcmap32 {
|
||||
int index; /* first element (0 origin) */
|
||||
int count;
|
||||
u32 red;
|
||||
u32 green;
|
||||
u32 blue;
|
||||
};
|
||||
|
||||
#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
|
||||
#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
|
||||
|
||||
static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct fbcmap32 __user *argp = (void __user *)arg;
|
||||
|
@ -223,20 +212,6 @@ static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long
|
|||
(unsigned long)p);
|
||||
}
|
||||
|
||||
struct fbcursor32 {
|
||||
short set; /* what to set, choose from the list above */
|
||||
short enable; /* cursor on/off */
|
||||
struct fbcurpos pos; /* cursor position */
|
||||
struct fbcurpos hot; /* cursor hot spot */
|
||||
struct fbcmap32 cmap; /* color map info */
|
||||
struct fbcurpos size; /* cursor bit map size */
|
||||
u32 image; /* cursor image bits */
|
||||
u32 mask; /* cursor mask bits */
|
||||
};
|
||||
|
||||
#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
|
||||
#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
|
||||
|
||||
static int fbiogscursor(struct fb_info *info, unsigned long arg)
|
||||
{
|
||||
struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));
|
||||
|
|
|
@ -345,88 +345,82 @@ tcx_init_fix(struct fb_info *info, int linebytes)
|
|||
info->fix.accel = FB_ACCEL_SUN_TCX;
|
||||
}
|
||||
|
||||
struct all_info {
|
||||
struct fb_info info;
|
||||
struct tcx_par par;
|
||||
};
|
||||
|
||||
static void tcx_unmap_regs(struct of_device *op, struct all_info *all)
|
||||
static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
|
||||
struct tcx_par *par)
|
||||
{
|
||||
if (all->par.tec)
|
||||
if (par->tec)
|
||||
of_iounmap(&op->resource[7],
|
||||
all->par.tec, sizeof(struct tcx_tec));
|
||||
if (all->par.thc)
|
||||
par->tec, sizeof(struct tcx_tec));
|
||||
if (par->thc)
|
||||
of_iounmap(&op->resource[9],
|
||||
all->par.thc, sizeof(struct tcx_thc));
|
||||
if (all->par.bt)
|
||||
par->thc, sizeof(struct tcx_thc));
|
||||
if (par->bt)
|
||||
of_iounmap(&op->resource[8],
|
||||
all->par.bt, sizeof(struct bt_regs));
|
||||
if (all->par.cplane)
|
||||
par->bt, sizeof(struct bt_regs));
|
||||
if (par->cplane)
|
||||
of_iounmap(&op->resource[4],
|
||||
all->par.cplane, all->par.fbsize * sizeof(u32));
|
||||
if (all->info.screen_base)
|
||||
par->cplane, par->fbsize * sizeof(u32));
|
||||
if (info->screen_base)
|
||||
of_iounmap(&op->resource[0],
|
||||
all->info.screen_base, all->par.fbsize);
|
||||
info->screen_base, par->fbsize);
|
||||
}
|
||||
|
||||
static int __devinit tcx_init_one(struct of_device *op)
|
||||
{
|
||||
struct device_node *dp = op->node;
|
||||
struct all_info *all;
|
||||
struct fb_info *info;
|
||||
struct tcx_par *par;
|
||||
int linebytes, i, err;
|
||||
|
||||
all = kzalloc(sizeof(*all), GFP_KERNEL);
|
||||
if (!all)
|
||||
return -ENOMEM;
|
||||
info = framebuffer_alloc(sizeof(struct tcx_par), &op->dev);
|
||||
|
||||
spin_lock_init(&all->par.lock);
|
||||
err = -ENOMEM;
|
||||
if (!info)
|
||||
goto out_err;
|
||||
par = info->par;
|
||||
|
||||
all->par.lowdepth =
|
||||
spin_lock_init(&par->lock);
|
||||
|
||||
par->lowdepth =
|
||||
(of_find_property(dp, "tcx-8-bit", NULL) != NULL);
|
||||
|
||||
sbusfb_fill_var(&all->info.var, dp->node, 8);
|
||||
all->info.var.red.length = 8;
|
||||
all->info.var.green.length = 8;
|
||||
all->info.var.blue.length = 8;
|
||||
sbusfb_fill_var(&info->var, dp->node, 8);
|
||||
info->var.red.length = 8;
|
||||
info->var.green.length = 8;
|
||||
info->var.blue.length = 8;
|
||||
|
||||
linebytes = of_getintprop_default(dp, "linebytes",
|
||||
all->info.var.xres);
|
||||
all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
|
||||
info->var.xres);
|
||||
par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
|
||||
|
||||
all->par.tec = of_ioremap(&op->resource[7], 0,
|
||||
par->tec = of_ioremap(&op->resource[7], 0,
|
||||
sizeof(struct tcx_tec), "tcx tec");
|
||||
all->par.thc = of_ioremap(&op->resource[9], 0,
|
||||
par->thc = of_ioremap(&op->resource[9], 0,
|
||||
sizeof(struct tcx_thc), "tcx thc");
|
||||
all->par.bt = of_ioremap(&op->resource[8], 0,
|
||||
par->bt = of_ioremap(&op->resource[8], 0,
|
||||
sizeof(struct bt_regs), "tcx dac");
|
||||
all->info.screen_base = of_ioremap(&op->resource[0], 0,
|
||||
all->par.fbsize, "tcx ram");
|
||||
if (!all->par.tec || !all->par.thc ||
|
||||
!all->par.bt || !all->info.screen_base) {
|
||||
tcx_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
info->screen_base = of_ioremap(&op->resource[0], 0,
|
||||
par->fbsize, "tcx ram");
|
||||
if (!par->tec || !par->thc ||
|
||||
!par->bt || !info->screen_base)
|
||||
goto out_unmap_regs;
|
||||
|
||||
memcpy(&all->par.mmap_map, &__tcx_mmap_map, sizeof(all->par.mmap_map));
|
||||
if (!all->par.lowdepth) {
|
||||
all->par.cplane = of_ioremap(&op->resource[4], 0,
|
||||
all->par.fbsize * sizeof(u32),
|
||||
memcpy(&par->mmap_map, &__tcx_mmap_map, sizeof(par->mmap_map));
|
||||
if (!par->lowdepth) {
|
||||
par->cplane = of_ioremap(&op->resource[4], 0,
|
||||
par->fbsize * sizeof(u32),
|
||||
"tcx cplane");
|
||||
if (!all->par.cplane) {
|
||||
tcx_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!par->cplane)
|
||||
goto out_unmap_regs;
|
||||
} else {
|
||||
all->par.mmap_map[1].size = SBUS_MMAP_EMPTY;
|
||||
all->par.mmap_map[4].size = SBUS_MMAP_EMPTY;
|
||||
all->par.mmap_map[5].size = SBUS_MMAP_EMPTY;
|
||||
all->par.mmap_map[6].size = SBUS_MMAP_EMPTY;
|
||||
par->mmap_map[1].size = SBUS_MMAP_EMPTY;
|
||||
par->mmap_map[4].size = SBUS_MMAP_EMPTY;
|
||||
par->mmap_map[5].size = SBUS_MMAP_EMPTY;
|
||||
par->mmap_map[6].size = SBUS_MMAP_EMPTY;
|
||||
}
|
||||
|
||||
all->par.physbase = 0;
|
||||
all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
par->physbase = 0;
|
||||
par->which_io = op->resource[0].flags & IORESOURCE_BITS;
|
||||
|
||||
for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
|
||||
int j;
|
||||
|
@ -444,53 +438,54 @@ static int __devinit tcx_init_one(struct of_device *op)
|
|||
j = i;
|
||||
break;
|
||||
};
|
||||
all->par.mmap_map[i].poff = op->resource[j].start;
|
||||
par->mmap_map[i].poff = op->resource[j].start;
|
||||
}
|
||||
|
||||
all->info.flags = FBINFO_DEFAULT;
|
||||
all->info.fbops = &tcx_ops;
|
||||
all->info.par = &all->par;
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
info->fbops = &tcx_ops;
|
||||
|
||||
/* Initialize brooktree DAC. */
|
||||
sbus_writel(0x04 << 24, &all->par.bt->addr); /* color planes */
|
||||
sbus_writel(0xff << 24, &all->par.bt->control);
|
||||
sbus_writel(0x05 << 24, &all->par.bt->addr);
|
||||
sbus_writel(0x00 << 24, &all->par.bt->control);
|
||||
sbus_writel(0x06 << 24, &all->par.bt->addr); /* overlay plane */
|
||||
sbus_writel(0x73 << 24, &all->par.bt->control);
|
||||
sbus_writel(0x07 << 24, &all->par.bt->addr);
|
||||
sbus_writel(0x00 << 24, &all->par.bt->control);
|
||||
sbus_writel(0x04 << 24, &par->bt->addr); /* color planes */
|
||||
sbus_writel(0xff << 24, &par->bt->control);
|
||||
sbus_writel(0x05 << 24, &par->bt->addr);
|
||||
sbus_writel(0x00 << 24, &par->bt->control);
|
||||
sbus_writel(0x06 << 24, &par->bt->addr); /* overlay plane */
|
||||
sbus_writel(0x73 << 24, &par->bt->control);
|
||||
sbus_writel(0x07 << 24, &par->bt->addr);
|
||||
sbus_writel(0x00 << 24, &par->bt->control);
|
||||
|
||||
tcx_reset(&all->info);
|
||||
tcx_reset(info);
|
||||
|
||||
tcx_blank(FB_BLANK_UNBLANK, &all->info);
|
||||
tcx_blank(FB_BLANK_UNBLANK, info);
|
||||
|
||||
if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
|
||||
tcx_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (fb_alloc_cmap(&info->cmap, 256, 0))
|
||||
goto out_unmap_regs;
|
||||
|
||||
fb_set_cmap(&all->info.cmap, &all->info);
|
||||
tcx_init_fix(&all->info, linebytes);
|
||||
fb_set_cmap(&info->cmap, info);
|
||||
tcx_init_fix(info, linebytes);
|
||||
|
||||
err = register_framebuffer(&all->info);
|
||||
if (err < 0) {
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
tcx_unmap_regs(op, all);
|
||||
kfree(all);
|
||||
return err;
|
||||
}
|
||||
err = register_framebuffer(info);
|
||||
if (err < 0)
|
||||
goto out_dealloc_cmap;
|
||||
|
||||
dev_set_drvdata(&op->dev, all);
|
||||
dev_set_drvdata(&op->dev, info);
|
||||
|
||||
printk("%s: TCX at %lx:%lx, %s\n",
|
||||
dp->full_name,
|
||||
all->par.which_io,
|
||||
par->which_io,
|
||||
op->resource[0].start,
|
||||
all->par.lowdepth ? "8-bit only" : "24-bit depth");
|
||||
par->lowdepth ? "8-bit only" : "24-bit depth");
|
||||
|
||||
return 0;
|
||||
|
||||
out_dealloc_cmap:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
out_unmap_regs:
|
||||
tcx_unmap_regs(op, info, par);
|
||||
|
||||
out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id *match)
|
||||
|
@ -502,14 +497,15 @@ static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id
|
|||
|
||||
static int __devexit tcx_remove(struct of_device *op)
|
||||
{
|
||||
struct all_info *all = dev_get_drvdata(&op->dev);
|
||||
struct fb_info *info = dev_get_drvdata(&op->dev);
|
||||
struct tcx_par *par = info->par;
|
||||
|
||||
unregister_framebuffer(&all->info);
|
||||
fb_dealloc_cmap(&all->info.cmap);
|
||||
unregister_framebuffer(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
tcx_unmap_regs(op, all);
|
||||
tcx_unmap_regs(op, info, par);
|
||||
|
||||
kfree(all);
|
||||
framebuffer_release(info);
|
||||
|
||||
dev_set_drvdata(&op->dev, NULL);
|
||||
|
||||
|
|
|
@ -115,6 +115,10 @@
|
|||
#include <linux/dvb/video.h>
|
||||
#include <linux/lp.h>
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
#include <asm/fbio.h>
|
||||
#endif
|
||||
|
||||
static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
|
||||
unsigned long arg, struct file *f)
|
||||
{
|
||||
|
@ -3493,6 +3497,22 @@ IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
|
|||
|
||||
/* loop */
|
||||
IGNORE_IOCTL(LOOP_CLR_FD)
|
||||
|
||||
#ifdef CONFIG_SPARC
|
||||
/* Sparc framebuffers, handled in sbusfb_compat_ioctl() */
|
||||
IGNORE_IOCTL(FBIOGTYPE)
|
||||
IGNORE_IOCTL(FBIOSATTR)
|
||||
IGNORE_IOCTL(FBIOGATTR)
|
||||
IGNORE_IOCTL(FBIOSVIDEO)
|
||||
IGNORE_IOCTL(FBIOGVIDEO)
|
||||
IGNORE_IOCTL(FBIOSCURPOS)
|
||||
IGNORE_IOCTL(FBIOGCURPOS)
|
||||
IGNORE_IOCTL(FBIOGCURMAX)
|
||||
IGNORE_IOCTL(FBIOPUTCMAP32)
|
||||
IGNORE_IOCTL(FBIOGETCMAP32)
|
||||
IGNORE_IOCTL(FBIOSCURSOR32)
|
||||
IGNORE_IOCTL(FBIOGCURSOR32)
|
||||
#endif
|
||||
};
|
||||
|
||||
#define IOCTL_HASHSIZE 256
|
||||
|
|
|
@ -203,6 +203,7 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
|
|||
Sector sect;
|
||||
struct solaris_x86_vtoc *v;
|
||||
int i;
|
||||
short max_nparts;
|
||||
|
||||
v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, §);
|
||||
if (!v)
|
||||
|
@ -218,7 +219,9 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
|
|||
put_dev_sector(sect);
|
||||
return;
|
||||
}
|
||||
for (i=0; i<SOLARIS_X86_NUMSLICE && state->next<state->limit; i++) {
|
||||
/* Ensure we can handle previous case of VTOC with 8 entries gracefully */
|
||||
max_nparts = le16_to_cpu (v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
|
||||
for (i=0; i<max_nparts && state->next<state->limit; i++) {
|
||||
struct solaris_x86_slice *s = &v->v_slice[i];
|
||||
if (s->s_size == 0)
|
||||
continue;
|
||||
|
|
|
@ -19,34 +19,47 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
|
|||
Sector sect;
|
||||
struct sun_disklabel {
|
||||
unsigned char info[128]; /* Informative text string */
|
||||
unsigned char spare0[14];
|
||||
struct sun_info {
|
||||
unsigned char spare1;
|
||||
unsigned char id;
|
||||
unsigned char spare2;
|
||||
unsigned char flags;
|
||||
} infos[8];
|
||||
unsigned char spare[246]; /* Boot information etc. */
|
||||
struct sun_vtoc {
|
||||
__be32 version; /* Layout version */
|
||||
char volume[8]; /* Volume name */
|
||||
__be16 nparts; /* Number of partitions */
|
||||
struct sun_info { /* Partition hdrs, sec 2 */
|
||||
__be16 id;
|
||||
__be16 flags;
|
||||
} infos[8];
|
||||
__be16 padding; /* Alignment padding */
|
||||
__be32 bootinfo[3]; /* Info needed by mboot */
|
||||
__be32 sanity; /* To verify vtoc sanity */
|
||||
__be32 reserved[10]; /* Free space */
|
||||
__be32 timestamp[8]; /* Partition timestamp */
|
||||
} vtoc;
|
||||
__be32 write_reinstruct; /* sectors to skip, writes */
|
||||
__be32 read_reinstruct; /* sectors to skip, reads */
|
||||
unsigned char spare[148]; /* Padding */
|
||||
__be16 rspeed; /* Disk rotational speed */
|
||||
__be16 pcylcount; /* Physical cylinder count */
|
||||
__be16 sparecyl; /* extra sects per cylinder */
|
||||
unsigned char spare2[4]; /* More magic... */
|
||||
__be16 obs1; /* gap1 */
|
||||
__be16 obs2; /* gap2 */
|
||||
__be16 ilfact; /* Interleave factor */
|
||||
__be16 ncyl; /* Data cylinder count */
|
||||
__be16 nacyl; /* Alt. cylinder count */
|
||||
__be16 ntrks; /* Tracks per cylinder */
|
||||
__be16 nsect; /* Sectors per track */
|
||||
unsigned char spare3[4]; /* Even more magic... */
|
||||
__be16 obs3; /* bhead - Label head offset */
|
||||
__be16 obs4; /* ppart - Physical Partition */
|
||||
struct sun_partition {
|
||||
__be32 start_cylinder;
|
||||
__be32 num_sectors;
|
||||
} partitions[8];
|
||||
__be16 magic; /* Magic number */
|
||||
__be16 csum; /* Label xor'd checksum */
|
||||
} * label;
|
||||
} * label;
|
||||
struct sun_partition *p;
|
||||
unsigned long spc;
|
||||
char b[BDEVNAME_SIZE];
|
||||
int use_vtoc;
|
||||
int nparts;
|
||||
|
||||
label = (struct sun_disklabel *)read_dev_sector(bdev, 0, §);
|
||||
if (!label)
|
||||
|
@ -70,9 +83,22 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* All Sun disks have 8 partition entries */
|
||||
/* Check to see if we can use the VTOC table */
|
||||
use_vtoc = ((be32_to_cpu(label->vtoc.sanity) == SUN_VTOC_SANITY) &&
|
||||
(be32_to_cpu(label->vtoc.version) == 1) &&
|
||||
(be16_to_cpu(label->vtoc.nparts) <= 8));
|
||||
|
||||
/* Use 8 partition entries if not specified in validated VTOC */
|
||||
nparts = (use_vtoc) ? be16_to_cpu(label->vtoc.nparts) : 8;
|
||||
|
||||
/*
|
||||
* So that old Linux-Sun partitions continue to work,
|
||||
* alow the VTOC to be used under the additional condition ...
|
||||
*/
|
||||
use_vtoc = use_vtoc || !(label->vtoc.sanity |
|
||||
label->vtoc.version | label->vtoc.nparts);
|
||||
spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
|
||||
for (i = 0; i < 8; i++, p++) {
|
||||
for (i = 0; i < nparts; i++, p++) {
|
||||
unsigned long st_sector;
|
||||
unsigned int num_sectors;
|
||||
|
||||
|
@ -81,10 +107,12 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
|
|||
if (num_sectors) {
|
||||
put_partition(state, slot, st_sector, num_sectors);
|
||||
state->parts[slot].flags = 0;
|
||||
if (label->infos[i].id == LINUX_RAID_PARTITION)
|
||||
state->parts[slot].flags |= ADDPART_FLAG_RAID;
|
||||
if (label->infos[i].id == SUN_WHOLE_DISK)
|
||||
state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK;
|
||||
if (use_vtoc) {
|
||||
if (be16_to_cpu(label->vtoc.infos[i].id) == LINUX_RAID_PARTITION)
|
||||
state->parts[slot].flags |= ADDPART_FLAG_RAID;
|
||||
else if (be16_to_cpu(label->vtoc.infos[i].id) == SUN_WHOLE_DISK)
|
||||
state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK;
|
||||
}
|
||||
}
|
||||
slot++;
|
||||
}
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
*/
|
||||
|
||||
#define SUN_LABEL_MAGIC 0xDABE
|
||||
#define SUN_VTOC_SANITY 0x600DDEEE
|
||||
|
||||
int sun_partition(struct parsed_partitions *state, struct block_device *bdev);
|
||||
|
|
|
@ -10,6 +10,10 @@ struct device_node;
|
|||
struct of_device;
|
||||
|
||||
struct dev_archdata {
|
||||
void *iommu;
|
||||
void *stc;
|
||||
void *host_controller;
|
||||
|
||||
struct device_node *prom_node;
|
||||
struct of_device *op;
|
||||
};
|
||||
|
|
|
@ -101,6 +101,29 @@ static struct sun_floppy_ops sun_fdops;
|
|||
#define CROSS_64KB(a,s) (0)
|
||||
|
||||
/* Routines unique to each controller type on a Sun. */
|
||||
static void sun_set_dor(unsigned char value, int fdc_82077)
|
||||
{
|
||||
if (sparc_cpu_model == sun4c) {
|
||||
unsigned int bits = 0;
|
||||
if (value & 0x10)
|
||||
bits |= AUXIO_FLPY_DSEL;
|
||||
if ((value & 0x80) == 0)
|
||||
bits |= AUXIO_FLPY_EJCT;
|
||||
set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
|
||||
}
|
||||
if (fdc_82077) {
|
||||
sun_fdc->dor_82077 = value;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char sun_read_dir(void)
|
||||
{
|
||||
if (sparc_cpu_model == sun4c)
|
||||
return (get_auxio() & AUXIO_FLPY_DCHG) ? 0x80 : 0;
|
||||
else
|
||||
return sun_fdc->dir_82077;
|
||||
}
|
||||
|
||||
static unsigned char sun_82072_fd_inb(int port)
|
||||
{
|
||||
udelay(5);
|
||||
|
@ -113,7 +136,7 @@ static unsigned char sun_82072_fd_inb(int port)
|
|||
case 5: /* FD_DATA */
|
||||
return sun_fdc->data_82072;
|
||||
case 7: /* FD_DIR */
|
||||
return (get_auxio() & AUXIO_FLPY_DCHG)? 0x80: 0;
|
||||
return sun_read_dir();
|
||||
};
|
||||
panic("sun_82072_fd_inb: How did I get here?");
|
||||
}
|
||||
|
@ -126,20 +149,7 @@ static void sun_82072_fd_outb(unsigned char value, int port)
|
|||
printk("floppy: Asked to write to unknown port %d\n", port);
|
||||
panic("floppy: Port bolixed.");
|
||||
case 2: /* FD_DOR */
|
||||
/* Oh geese, 82072 on the Sun has no DOR register,
|
||||
* the functionality is implemented via the AUXIO
|
||||
* I/O register. So we must emulate the behavior.
|
||||
*
|
||||
* ASSUMPTIONS: There will only ever be one floppy
|
||||
* drive attached to a Sun controller
|
||||
* and it will be at drive zero.
|
||||
*/
|
||||
{
|
||||
unsigned bits = 0;
|
||||
if (value & 0x10) bits |= AUXIO_FLPY_DSEL;
|
||||
if ((value & 0x80) == 0) bits |= AUXIO_FLPY_EJCT;
|
||||
set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
|
||||
}
|
||||
sun_set_dor(value, 0);
|
||||
break;
|
||||
case 5: /* FD_DATA */
|
||||
sun_fdc->data_82072 = value;
|
||||
|
@ -161,15 +171,22 @@ static unsigned char sun_82077_fd_inb(int port)
|
|||
default:
|
||||
printk("floppy: Asked to read unknown port %d\n", port);
|
||||
panic("floppy: Port bolixed.");
|
||||
case 0: /* FD_STATUS_0 */
|
||||
return sun_fdc->status1_82077;
|
||||
case 1: /* FD_STATUS_1 */
|
||||
return sun_fdc->status2_82077;
|
||||
case 2: /* FD_DOR */
|
||||
return sun_fdc->dor_82077;
|
||||
case 3: /* FD_TDR */
|
||||
return sun_fdc->tapectl_82077;
|
||||
case 4: /* FD_STATUS */
|
||||
return sun_fdc->status_82077 & ~STATUS_DMA;
|
||||
case 5: /* FD_DATA */
|
||||
return sun_fdc->data_82077;
|
||||
case 7: /* FD_DIR */
|
||||
/* XXX: Is DCL on 0x80 in sun4m? */
|
||||
return sun_fdc->dir_82077;
|
||||
return sun_read_dir();
|
||||
};
|
||||
panic("sun_82072_fd_inb: How did I get here?");
|
||||
panic("sun_82077_fd_inb: How did I get here?");
|
||||
}
|
||||
|
||||
static void sun_82077_fd_outb(unsigned char value, int port)
|
||||
|
@ -180,8 +197,7 @@ static void sun_82077_fd_outb(unsigned char value, int port)
|
|||
printk("floppy: Asked to write to unknown port %d\n", port);
|
||||
panic("floppy: Port bolixed.");
|
||||
case 2: /* FD_DOR */
|
||||
/* Happily, the 82077 has a real DOR register. */
|
||||
sun_fdc->dor_82077 = value;
|
||||
sun_set_dor(value, 1);
|
||||
break;
|
||||
case 5: /* FD_DATA */
|
||||
sun_fdc->data_82077 = value;
|
||||
|
@ -192,6 +208,9 @@ static void sun_82077_fd_outb(unsigned char value, int port)
|
|||
case 4: /* FD_STATUS */
|
||||
sun_fdc->status_82077 = value;
|
||||
break;
|
||||
case 3: /* FD_TDR */
|
||||
sun_fdc->tapectl_82077 = value;
|
||||
break;
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
@ -332,16 +351,17 @@ static int sun_floppy_init(void)
|
|||
goto no_sun_fdc;
|
||||
}
|
||||
|
||||
if(sparc_cpu_model == sun4c) {
|
||||
sun_fdops.fd_inb = sun_82072_fd_inb;
|
||||
sun_fdops.fd_outb = sun_82072_fd_outb;
|
||||
fdc_status = &sun_fdc->status_82072;
|
||||
/* printk("AUXIO @0x%lx\n", auxio_register); */ /* P3 */
|
||||
} else {
|
||||
sun_fdops.fd_inb = sun_82077_fd_inb;
|
||||
sun_fdops.fd_outb = sun_82077_fd_outb;
|
||||
fdc_status = &sun_fdc->status_82077;
|
||||
/* printk("DOR @0x%p\n", &sun_fdc->dor_82077); */ /* P3 */
|
||||
sun_fdops.fd_inb = sun_82077_fd_inb;
|
||||
sun_fdops.fd_outb = sun_82077_fd_outb;
|
||||
fdc_status = &sun_fdc->status_82077;
|
||||
|
||||
if (sun_fdc->dor_82077 == 0x80) {
|
||||
sun_fdc->dor_82077 = 0x02;
|
||||
if (sun_fdc->dor_82077 == 0x80) {
|
||||
sun_fdops.fd_inb = sun_82072_fd_inb;
|
||||
sun_fdops.fd_outb = sun_82072_fd_outb;
|
||||
fdc_status = &sun_fdc->status_82072;
|
||||
}
|
||||
}
|
||||
|
||||
/* Success... */
|
||||
|
|
|
@ -1,307 +1,134 @@
|
|||
#ifndef _ASM_SPARC64_DMA_MAPPING_H
|
||||
#define _ASM_SPARC64_DMA_MAPPING_H
|
||||
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
||||
/* we implement the API below in terms of the existing PCI one,
|
||||
* so include it */
|
||||
#include <linux/pci.h>
|
||||
/* need struct page definitions */
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <asm/of_device.h>
|
||||
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
|
||||
|
||||
static inline int
|
||||
dma_supported(struct device *dev, u64 mask)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
struct dma_ops {
|
||||
void *(*alloc_coherent)(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flag);
|
||||
void (*free_coherent)(struct device *dev, size_t size,
|
||||
void *cpu_addr, dma_addr_t dma_handle);
|
||||
dma_addr_t (*map_single)(struct device *dev, void *cpu_addr,
|
||||
size_t size,
|
||||
enum dma_data_direction direction);
|
||||
void (*unmap_single)(struct device *dev, dma_addr_t dma_addr,
|
||||
size_t size,
|
||||
enum dma_data_direction direction);
|
||||
int (*map_sg)(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction direction);
|
||||
void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
|
||||
int nhwentries,
|
||||
enum dma_data_direction direction);
|
||||
void (*sync_single_for_cpu)(struct device *dev,
|
||||
dma_addr_t dma_handle, size_t size,
|
||||
enum dma_data_direction direction);
|
||||
void (*sync_single_for_device)(struct device *dev,
|
||||
dma_addr_t dma_handle, size_t size,
|
||||
enum dma_data_direction direction);
|
||||
void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
|
||||
int nelems,
|
||||
enum dma_data_direction direction);
|
||||
void (*sync_sg_for_device)(struct device *dev, struct scatterlist *sg,
|
||||
int nelems,
|
||||
enum dma_data_direction direction);
|
||||
};
|
||||
extern const struct dma_ops *dma_ops;
|
||||
|
||||
return pci_dma_supported(to_pci_dev(dev), mask);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dma_set_mask(struct device *dev, u64 dma_mask)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
|
||||
gfp_t flag)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
return pci_iommu_ops->alloc_consistent(to_pci_dev(dev), size, dma_handle, flag);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
|
||||
dma_addr_t dma_handle)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
|
||||
}
|
||||
|
||||
static inline dma_addr_t
|
||||
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
|
||||
}
|
||||
|
||||
static inline dma_addr_t
|
||||
dma_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
|
||||
size, (int)direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
|
||||
size, (int)direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG_ON(dev->bus != &pci_bus_type);
|
||||
|
||||
pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dma_mapping_error(dma_addr_t dma_addr)
|
||||
{
|
||||
return pci_dma_mapping_error(dma_addr);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct device;
|
||||
struct page;
|
||||
struct scatterlist;
|
||||
|
||||
static inline int
|
||||
dma_supported(struct device *dev, u64 mask)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
dma_set_mask(struct device *dev, u64 dma_mask)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
extern int dma_supported(struct device *dev, u64 mask);
|
||||
extern int dma_set_mask(struct device *dev, u64 dma_mask);
|
||||
|
||||
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||
dma_addr_t *dma_handle, gfp_t flag)
|
||||
dma_addr_t *dma_handle, gfp_t flag)
|
||||
{
|
||||
BUG();
|
||||
return NULL;
|
||||
return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
|
||||
}
|
||||
|
||||
static inline void dma_free_coherent(struct device *dev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle)
|
||||
void *cpu_addr, dma_addr_t dma_handle)
|
||||
{
|
||||
BUG();
|
||||
dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
|
||||
}
|
||||
|
||||
static inline dma_addr_t
|
||||
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
|
||||
size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
return dma_ops->map_single(dev, cpu_addr, size, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
|
||||
size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
dma_ops->unmap_single(dev, dma_addr, size, direction);
|
||||
}
|
||||
|
||||
static inline dma_addr_t
|
||||
dma_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
return dma_ops->map_single(dev, page_address(page) + offset,
|
||||
size, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
|
||||
size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
dma_ops->unmap_single(dev, dma_address, size, direction);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
|
||||
enum dma_data_direction direction)
|
||||
static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
|
||||
int nents, enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
return dma_ops->map_sg(dev, sg, nents, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
|
||||
enum dma_data_direction direction)
|
||||
static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
|
||||
int nents, enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
dma_ops->unmap_sg(dev, sg, nents, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
static inline void dma_sync_single_for_cpu(struct device *dev,
|
||||
dma_addr_t dma_handle, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
dma_ops->sync_single_for_cpu(dev, dma_handle, size, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
static inline void dma_sync_single_for_device(struct device *dev,
|
||||
dma_addr_t dma_handle,
|
||||
size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
dma_ops->sync_single_for_device(dev, dma_handle, size, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
|
||||
enum dma_data_direction direction)
|
||||
static inline void dma_sync_sg_for_cpu(struct device *dev,
|
||||
struct scatterlist *sg, int nelems,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
dma_ops->sync_sg_for_cpu(dev, sg, nelems, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
|
||||
enum dma_data_direction direction)
|
||||
static inline void dma_sync_sg_for_device(struct device *dev,
|
||||
struct scatterlist *sg, int nelems,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
BUG();
|
||||
dma_ops->sync_sg_for_device(dev, sg, nelems, direction);
|
||||
}
|
||||
|
||||
static inline int
|
||||
dma_mapping_error(dma_addr_t dma_addr)
|
||||
static inline int dma_mapping_error(dma_addr_t dma_addr)
|
||||
{
|
||||
BUG();
|
||||
return 0;
|
||||
return (dma_addr == DMA_ERROR_CODE);
|
||||
}
|
||||
|
||||
#endif /* PCI */
|
||||
|
||||
|
||||
/* Now for the API extensions over the pci_ one */
|
||||
|
||||
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
|
||||
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
|
||||
#define dma_is_consistent(d, h) (1)
|
||||
|
||||
static inline int
|
||||
dma_get_cache_alignment(void)
|
||||
{
|
||||
/* no easy way to get cache size on all processors, so return
|
||||
* the maximum possible, to be safe */
|
||||
return (1 << INTERNODE_CACHE_SHIFT);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
/* just sync everything, that's all the pci API can do */
|
||||
dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
|
||||
unsigned long offset, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
/* just sync everything, that's all the pci API can do */
|
||||
dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
dma_cache_sync(struct device *dev, void *vaddr, size_t size,
|
||||
enum dma_data_direction direction)
|
||||
{
|
||||
/* could define this in terms of the dma_cache ... operations,
|
||||
* but if you get this on a platform, you should convert the platform
|
||||
* to using the generic device DMA API */
|
||||
BUG();
|
||||
}
|
||||
|
||||
#endif /* _ASM_SPARC64_DMA_MAPPING_H */
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __LINUX_FBIO_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Constants used for fbio SunOS compatibility */
|
||||
/* (C) 1996 Miguel de Icaza */
|
||||
|
@ -299,4 +300,31 @@ struct fb_clut32 {
|
|||
#define LEO_LD_GBL_MAP 0x01009000
|
||||
#define LEO_UNK2_MAP 0x0100a000
|
||||
|
||||
#ifdef __KERNEL__
|
||||
struct fbcmap32 {
|
||||
int index; /* first element (0 origin) */
|
||||
int count;
|
||||
u32 red;
|
||||
u32 green;
|
||||
u32 blue;
|
||||
};
|
||||
|
||||
#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
|
||||
#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
|
||||
|
||||
struct fbcursor32 {
|
||||
short set; /* what to set, choose from the list above */
|
||||
short enable; /* cursor on/off */
|
||||
struct fbcurpos pos; /* cursor position */
|
||||
struct fbcurpos hot; /* cursor hot spot */
|
||||
struct fbcmap32 cmap; /* color map info */
|
||||
struct fbcurpos size; /* cursor bit map size */
|
||||
u32 image; /* cursor image bits */
|
||||
u32 mask; /* cursor mask bits */
|
||||
};
|
||||
|
||||
#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
|
||||
#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_FBIO_H */
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* $Id: floppy.h,v 1.32 2001/10/26 17:59:36 davem Exp $
|
||||
* asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
|
||||
/* floppy.h: Sparc specific parts of the Floppy driver.
|
||||
*
|
||||
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
|
||||
* Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
|
||||
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
|
||||
*
|
||||
* Ultra/PCI support added: Sep 1997 Eddie C. Dost (ecd@skynet.be)
|
||||
|
@ -11,6 +10,7 @@
|
|||
#define __ASM_SPARC64_FLOPPY_H
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* $Id: iommu.h,v 1.10 2001/03/08 09:55:56 davem Exp $
|
||||
* iommu.h: Definitions for the sun5 IOMMU.
|
||||
/* iommu.h: Definitions for the sun5 IOMMU.
|
||||
*
|
||||
* Copyright (C) 1996, 1999 David S. Miller (davem@caip.rutgers.edu)
|
||||
* Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
|
||||
*/
|
||||
#ifndef _SPARC64_IOMMU_H
|
||||
#define _SPARC64_IOMMU_H
|
||||
|
@ -33,6 +32,7 @@ struct iommu {
|
|||
unsigned long iommu_tsbbase;
|
||||
unsigned long iommu_flush;
|
||||
unsigned long iommu_flushinv;
|
||||
unsigned long iommu_tags;
|
||||
unsigned long iommu_ctxflush;
|
||||
unsigned long write_complete_reg;
|
||||
unsigned long dummy_page;
|
||||
|
@ -54,4 +54,7 @@ struct strbuf {
|
|||
volatile unsigned long __flushflag_buf[(64+(64-1)) / sizeof(long)];
|
||||
};
|
||||
|
||||
#endif /* !(_SPARC_IOMMU_H) */
|
||||
extern int iommu_table_init(struct iommu *iommu, int tsbsize,
|
||||
u32 dma_offset, u32 dma_addr_mask);
|
||||
|
||||
#endif /* !(_SPARC64_IOMMU_H) */
|
||||
|
|
|
@ -117,7 +117,7 @@ static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id
|
|||
if (!strcmp(parent->name, "dma")) {
|
||||
p = parport_pc_probe_port(base, base + 0x400,
|
||||
op->irqs[0], PARPORT_DMA_NOFIFO,
|
||||
op->dev.parent);
|
||||
op->dev.parent->parent);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
dev_set_drvdata(&op->dev, p);
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
/* Can be used to override the logic in pci_scan_bus for skipping
|
||||
* already-configured bus numbers - to be used for buggy BIOSes
|
||||
|
@ -30,80 +29,42 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
|
|||
/* We don't do dynamic PCI IRQ allocation */
|
||||
}
|
||||
|
||||
/* Dynamic DMA mapping stuff.
|
||||
*/
|
||||
|
||||
/* The PCI address space does not equal the physical memory
|
||||
* address space. The networking and block device layers use
|
||||
* this boolean for bounce buffer decisions.
|
||||
*/
|
||||
#define PCI_DMA_BUS_IS_PHYS (0)
|
||||
|
||||
#include <asm/scatterlist.h>
|
||||
|
||||
struct pci_dev;
|
||||
|
||||
struct pci_iommu_ops {
|
||||
void *(*alloc_consistent)(struct pci_dev *, size_t, dma_addr_t *, gfp_t);
|
||||
void (*free_consistent)(struct pci_dev *, size_t, void *, dma_addr_t);
|
||||
dma_addr_t (*map_single)(struct pci_dev *, void *, size_t, int);
|
||||
void (*unmap_single)(struct pci_dev *, dma_addr_t, size_t, int);
|
||||
int (*map_sg)(struct pci_dev *, struct scatterlist *, int, int);
|
||||
void (*unmap_sg)(struct pci_dev *, struct scatterlist *, int, int);
|
||||
void (*dma_sync_single_for_cpu)(struct pci_dev *, dma_addr_t, size_t, int);
|
||||
void (*dma_sync_sg_for_cpu)(struct pci_dev *, struct scatterlist *, int, int);
|
||||
};
|
||||
|
||||
extern const struct pci_iommu_ops *pci_iommu_ops;
|
||||
|
||||
/* Allocate and map kernel buffer using consistent mode DMA for a device.
|
||||
* hwdev should be valid struct pci_dev pointer for PCI devices.
|
||||
*/
|
||||
static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
|
||||
static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size,
|
||||
dma_addr_t *dma_handle)
|
||||
{
|
||||
return pci_iommu_ops->alloc_consistent(hwdev, size, dma_handle, GFP_ATOMIC);
|
||||
return dma_alloc_coherent(&pdev->dev, size, dma_handle, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
/* Free and unmap a consistent DMA buffer.
|
||||
* cpu_addr is what was returned from pci_alloc_consistent,
|
||||
* size must be the same as what as passed into pci_alloc_consistent,
|
||||
* and likewise dma_addr must be the same as what *dma_addrp was set to.
|
||||
*
|
||||
* References to the memory and mappings associated with cpu_addr/dma_addr
|
||||
* past this call are illegal.
|
||||
*/
|
||||
static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
|
||||
static inline void pci_free_consistent(struct pci_dev *pdev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle)
|
||||
{
|
||||
return pci_iommu_ops->free_consistent(hwdev, size, vaddr, dma_handle);
|
||||
return dma_free_coherent(&pdev->dev, size, vaddr, dma_handle);
|
||||
}
|
||||
|
||||
/* Map a single buffer of the indicated size for DMA in streaming mode.
|
||||
* The 32-bit bus address to use is returned.
|
||||
*
|
||||
* Once the device is given the dma address, the device owns this memory
|
||||
* until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed.
|
||||
*/
|
||||
static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
|
||||
static inline dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr,
|
||||
size_t size, int direction)
|
||||
{
|
||||
return pci_iommu_ops->map_single(hwdev, ptr, size, direction);
|
||||
return dma_map_single(&pdev->dev, ptr, size,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
/* Unmap a single streaming mode DMA translation. The dma_addr and size
|
||||
* must match what was provided for in a previous pci_map_single call. All
|
||||
* other usages are undefined.
|
||||
*
|
||||
* After this call, reads by the cpu to the buffer are guaranteed to see
|
||||
* whatever the device wrote there.
|
||||
*/
|
||||
static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction)
|
||||
static inline void pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr,
|
||||
size_t size, int direction)
|
||||
{
|
||||
pci_iommu_ops->unmap_single(hwdev, dma_addr, size, direction);
|
||||
dma_unmap_single(&pdev->dev, dma_addr, size,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
/* No highmem on sparc64, plus we have an IOMMU, so mapping pages is easy. */
|
||||
#define pci_map_page(dev, page, off, size, dir) \
|
||||
pci_map_single(dev, (page_address(page) + (off)), size, dir)
|
||||
#define pci_unmap_page(dev,addr,sz,dir) pci_unmap_single(dev,addr,sz,dir)
|
||||
#define pci_unmap_page(dev,addr,sz,dir) \
|
||||
pci_unmap_single(dev,addr,sz,dir)
|
||||
|
||||
/* pci_unmap_{single,page} is not a nop, thus... */
|
||||
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
|
||||
|
@ -119,75 +80,48 @@ static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
|
|||
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
|
||||
(((PTR)->LEN_NAME) = (VAL))
|
||||
|
||||
/* Map a set of buffers described by scatterlist in streaming
|
||||
* mode for DMA. This is the scatter-gather version of the
|
||||
* above pci_map_single interface. Here the scatter gather list
|
||||
* elements are each tagged with the appropriate dma address
|
||||
* and length. They are obtained via sg_dma_{address,length}(SG).
|
||||
*
|
||||
* NOTE: An implementation may be able to use a smaller number of
|
||||
* DMA address/length pairs than there are SG table elements.
|
||||
* (for example via virtual mapping capabilities)
|
||||
* The routine returns the number of addr/length pairs actually
|
||||
* used, at most nents.
|
||||
*
|
||||
* Device ownership issues as mentioned above for pci_map_single are
|
||||
* the same here.
|
||||
*/
|
||||
static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction)
|
||||
static inline int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
{
|
||||
return pci_iommu_ops->map_sg(hwdev, sg, nents, direction);
|
||||
return dma_map_sg(&pdev->dev, sg, nents,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
/* Unmap a set of streaming mode DMA translations.
|
||||
* Again, cpu read rules concerning calls here are the same as for
|
||||
* pci_unmap_single() above.
|
||||
*/
|
||||
static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents, int direction)
|
||||
static inline void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
{
|
||||
pci_iommu_ops->unmap_sg(hwdev, sg, nhwents, direction);
|
||||
dma_unmap_sg(&pdev->dev, sg, nents,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
/* Make physical memory consistent for a single
|
||||
* streaming mode DMA translation after a transfer.
|
||||
*
|
||||
* If you perform a pci_map_single() but wish to interrogate the
|
||||
* buffer using the cpu, yet do not wish to teardown the PCI dma
|
||||
* mapping, you must call this function before doing so. At the
|
||||
* next point you give the PCI dma address back to the card, you
|
||||
* must first perform a pci_dma_sync_for_device, and then the
|
||||
* device again owns the buffer.
|
||||
*/
|
||||
static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction)
|
||||
static inline void pci_dma_sync_single_for_cpu(struct pci_dev *pdev,
|
||||
dma_addr_t dma_handle,
|
||||
size_t size, int direction)
|
||||
{
|
||||
pci_iommu_ops->dma_sync_single_for_cpu(hwdev, dma_handle, size, direction);
|
||||
dma_sync_single_for_cpu(&pdev->dev, dma_handle, size,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
|
||||
size_t size, int direction)
|
||||
static inline void pci_dma_sync_single_for_device(struct pci_dev *pdev,
|
||||
dma_addr_t dma_handle,
|
||||
size_t size, int direction)
|
||||
{
|
||||
/* No flushing needed to sync cpu writes to the device. */
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
}
|
||||
|
||||
/* Make physical memory consistent for a set of streaming
|
||||
* mode DMA translations after a transfer.
|
||||
*
|
||||
* The same as pci_dma_sync_single_* but for a scatter-gather list,
|
||||
* same rules and usage.
|
||||
*/
|
||||
static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
|
||||
static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev,
|
||||
struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
{
|
||||
pci_iommu_ops->dma_sync_sg_for_cpu(hwdev, sg, nelems, direction);
|
||||
dma_sync_sg_for_cpu(&pdev->dev, sg, nents,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
static inline void
|
||||
pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
|
||||
int nelems, int direction)
|
||||
static inline void pci_dma_sync_sg_for_device(struct pci_dev *pdev,
|
||||
struct scatterlist *sg,
|
||||
int nelems, int direction)
|
||||
{
|
||||
/* No flushing needed to sync cpu writes to the device. */
|
||||
BUG_ON(direction == PCI_DMA_NONE);
|
||||
}
|
||||
|
||||
/* Return whether the given PCI device DMA address mask can
|
||||
|
@ -206,11 +140,9 @@ extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
|
|||
#define PCI64_REQUIRED_MASK (~(dma64_addr_t)0)
|
||||
#define PCI64_ADDR_BASE 0xfffc000000000000UL
|
||||
|
||||
#define PCI_DMA_ERROR_CODE (~(dma_addr_t)0x0)
|
||||
|
||||
static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
|
||||
{
|
||||
return (dma_addr == PCI_DMA_ERROR_CODE);
|
||||
return dma_mapping_error(dma_addr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* $Id: sbus.h,v 1.14 2000/02/18 13:50:55 davem Exp $
|
||||
* sbus.h: Defines for the Sun SBus.
|
||||
/* sbus.h: Defines for the Sun SBus.
|
||||
*
|
||||
* Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
|
||||
* Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
|
||||
*/
|
||||
|
||||
#ifndef _SPARC64_SBUS_H
|
||||
|
@ -69,7 +68,6 @@ struct sbus_dev {
|
|||
/* This struct describes the SBus(s) found on this machine. */
|
||||
struct sbus_bus {
|
||||
struct of_device ofdev;
|
||||
void *iommu; /* Opaque IOMMU cookie */
|
||||
struct sbus_dev *devices; /* Tree of SBUS devices */
|
||||
struct sbus_bus *next; /* Next SBUS in system */
|
||||
int prom_node; /* OBP node of SBUS */
|
||||
|
@ -102,9 +100,18 @@ extern struct sbus_bus *sbus_root;
|
|||
extern void sbus_set_sbus64(struct sbus_dev *, int);
|
||||
extern void sbus_fill_device_irq(struct sbus_dev *);
|
||||
|
||||
/* These yield IOMMU mappings in consistent mode. */
|
||||
extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp);
|
||||
extern void sbus_free_consistent(struct sbus_dev *, size_t, void *, dma_addr_t);
|
||||
static inline void *sbus_alloc_consistent(struct sbus_dev *sdev , size_t size,
|
||||
dma_addr_t *dma_handle)
|
||||
{
|
||||
return dma_alloc_coherent(&sdev->ofdev.dev, size,
|
||||
dma_handle, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static inline void sbus_free_consistent(struct sbus_dev *sdev, size_t size,
|
||||
void *vaddr, dma_addr_t dma_handle)
|
||||
{
|
||||
return dma_free_coherent(&sdev->ofdev.dev, size, vaddr, dma_handle);
|
||||
}
|
||||
|
||||
#define SBUS_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL
|
||||
#define SBUS_DMA_TODEVICE DMA_TO_DEVICE
|
||||
|
@ -112,18 +119,67 @@ extern void sbus_free_consistent(struct sbus_dev *, size_t, void *, dma_addr_t);
|
|||
#define SBUS_DMA_NONE DMA_NONE
|
||||
|
||||
/* All the rest use streaming mode mappings. */
|
||||
extern dma_addr_t sbus_map_single(struct sbus_dev *, void *, size_t, int);
|
||||
extern void sbus_unmap_single(struct sbus_dev *, dma_addr_t, size_t, int);
|
||||
extern int sbus_map_sg(struct sbus_dev *, struct scatterlist *, int, int);
|
||||
extern void sbus_unmap_sg(struct sbus_dev *, struct scatterlist *, int, int);
|
||||
static inline dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr,
|
||||
size_t size, int direction)
|
||||
{
|
||||
return dma_map_single(&sdev->ofdev.dev, ptr, size,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
static inline void sbus_unmap_single(struct sbus_dev *sdev,
|
||||
dma_addr_t dma_addr, size_t size,
|
||||
int direction)
|
||||
{
|
||||
dma_unmap_single(&sdev->ofdev.dev, dma_addr, size,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
static inline int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
{
|
||||
return dma_map_sg(&sdev->ofdev.dev, sg, nents,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
static inline void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
{
|
||||
dma_unmap_sg(&sdev->ofdev.dev, sg, nents,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
|
||||
/* Finally, allow explicit synchronization of streamable mappings. */
|
||||
extern void sbus_dma_sync_single_for_cpu(struct sbus_dev *, dma_addr_t, size_t, int);
|
||||
static inline void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev,
|
||||
dma_addr_t dma_handle,
|
||||
size_t size, int direction)
|
||||
{
|
||||
dma_sync_single_for_cpu(&sdev->ofdev.dev, dma_handle, size,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
#define sbus_dma_sync_single sbus_dma_sync_single_for_cpu
|
||||
extern void sbus_dma_sync_single_for_device(struct sbus_dev *, dma_addr_t, size_t, int);
|
||||
extern void sbus_dma_sync_sg_for_cpu(struct sbus_dev *, struct scatterlist *, int, int);
|
||||
|
||||
static inline void sbus_dma_sync_single_for_device(struct sbus_dev *sdev,
|
||||
dma_addr_t dma_handle,
|
||||
size_t size, int direction)
|
||||
{
|
||||
/* No flushing needed to sync cpu writes to the device. */
|
||||
}
|
||||
|
||||
static inline void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev,
|
||||
struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
{
|
||||
dma_sync_sg_for_cpu(&sdev->ofdev.dev, sg, nents,
|
||||
(enum dma_data_direction) direction);
|
||||
}
|
||||
#define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu
|
||||
extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int);
|
||||
|
||||
static inline void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev,
|
||||
struct scatterlist *sg,
|
||||
int nents, int direction)
|
||||
{
|
||||
/* No flushing needed to sync cpu writes to the device. */
|
||||
}
|
||||
|
||||
extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
|
||||
extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);
|
||||
|
|
|
@ -264,7 +264,7 @@ static inline void set_capacity(struct gendisk *disk, sector_t size)
|
|||
|
||||
#ifdef CONFIG_SOLARIS_X86_PARTITION
|
||||
|
||||
#define SOLARIS_X86_NUMSLICE 8
|
||||
#define SOLARIS_X86_NUMSLICE 16
|
||||
#define SOLARIS_X86_VTOC_SANE (0x600DDEEEUL)
|
||||
|
||||
struct solaris_x86_slice {
|
||||
|
|
Loading…
Reference in a new issue