提交 f58a9d17 编写于 作者: G Geoff Levand 提交者: Paul Mackerras

[POWERPC] ps3: add support for ps3 platform

Adds the core platform support for the PS3 game console and other devices
using the PS3 hypervisor.
Signed-off-by: NGeoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: NArnd Bergmann <arnd.bergmann@de.ibm.com>
上级 a985239b
......@@ -2443,6 +2443,13 @@ M: promise@pnd-pc.demon.co.uk
W: http://www.pnd-pc.demon.co.uk/promise/
S: Maintained
PS3 PLATFORM SUPPORT
P: Geoff Levand
M: geoffrey.levand@am.sony.com
L: linuxppc-dev@ozlabs.org
L: cbe-oss-dev@ozlabs.org
S: Supported
PVRUSB2 VIDEO4LINUX DRIVER
P: Mike Isely
M: isely@pobox.com
......
......@@ -495,6 +495,14 @@ config UDBG_RTAS_CONSOLE
depends on PPC_RTAS
default n
config PPC_PS3
bool "Sony PS3"
depends on PPC_MULTIPLATFORM && PPC64
select PPC_CELL
help
This option enables support for the Sony PS3 game console
and other platforms using the PS3 hypervisor.
config XICS
depends on PPC_PSERIES
bool
......@@ -647,6 +655,7 @@ source arch/powerpc/platforms/85xx/Kconfig
source arch/powerpc/platforms/86xx/Kconfig
source arch/powerpc/platforms/8xx/Kconfig
source arch/powerpc/platforms/cell/Kconfig
source arch/powerpc/platforms/ps3/Kconfig
menu "Kernel options"
......@@ -917,7 +926,7 @@ config MCA
config PCI
bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
|| PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2
|| PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) || MPC7448HPC2 || PPC_PS3
default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx \
&& !PPC_85xx && !PPC_86xx
default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
......
......@@ -16,4 +16,5 @@ obj-$(CONFIG_PPC_ISERIES) += iseries/
obj-$(CONFIG_PPC_MAPLE) += maple/
obj-$(CONFIG_PPC_PASEMI) += pasemi/
obj-$(CONFIG_PPC_CELL) += cell/
obj-$(CONFIG_PS3) += ps3/
obj-$(CONFIG_EMBEDDED6xx) += embedded6xx/
menu "PS3 Platform Options"
depends on PPC_PS3
config PS3_HTAB_SIZE
depends on PPC_PS3
int "PS3 Platform pagetable size"
range 18 20
default 20
help
This option is only for experts who may have the desire to fine
tune the pagetable size on their system. The value here is
expressed as the log2 of the page table size. Valid values are
18, 19, and 20, corresponding to 256KB, 512KB and 1MB respectively.
If unsure, choose the default (20) with the confidence that your
system will have optimal runtime performance.
config PS3_DYNAMIC_DMA
depends on PPC_PS3 && EXPERIMENTAL
bool "PS3 Platform dynamic DMA page table management"
default n
help
This option will enable kernel support to take advantage of the
per device dynamic DMA page table management provided by the Cell
processor's IO Controller. This support incurs some runtime
overhead and also slightly increases kernel memory usage. The
current implementation should be considered experimental.
This support is mainly for Linux kernel development. If unsure,
say N.
endmenu
obj-y += setup.o mm.o smp.o time.o hvcall.o htab.o repository.o
obj-y += interrupt.o exports.o
此差异已折叠。
/*
* PS3 platform declarations.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined(_PS3_PLATFORM_H)
#define _PS3_PLATFORM_H
#include <linux/rtc.h>
/* htab */
void __init ps3_hpte_init(unsigned long htab_size);
void __init ps3_map_htab(void);
/* mm */
void __init ps3_mm_init(void);
void __init ps3_mm_vas_create(unsigned long* htab_size);
void ps3_mm_vas_destroy(void);
void ps3_mm_shutdown(void);
/* irq */
void ps3_init_IRQ(void);
void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
/* smp */
void smp_init_ps3(void);
void ps3_smp_cleanup_cpu(int cpu);
/* time */
void __init ps3_calibrate_decr(void);
unsigned long __init ps3_get_boot_time(void);
void ps3_get_rtc_time(struct rtc_time *time);
int ps3_set_rtc_time(struct rtc_time *time);
/* os area */
int __init ps3_os_area_init(void);
u64 ps3_os_area_rtc_diff(void);
#endif
/*
* PS3 platform setup routines.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/root_dev.h>
#include <linux/console.h>
#include <linux/kexec.h>
#include <asm/machdep.h>
#include <asm/firmware.h>
#include <asm/time.h>
#include <asm/iommu.h>
#include <asm/udbg.h>
#include <asm/prom.h>
#include <asm/lv1call.h>
#include "platform.h"
#if defined(DEBUG)
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
#endif
static void ps3_show_cpuinfo(struct seq_file *m)
{
seq_printf(m, "machine\t\t: %s\n", ppc_md.name);
}
static void ps3_power_save(void)
{
/*
* lv1_pause() puts the PPE thread into inactive state until an
* irq on an unmasked plug exists. MSR[EE] has no effect.
* flags: 0 = wake on DEC interrupt, 1 = ignore DEC interrupt.
*/
lv1_pause(0);
}
static void ps3_panic(char *str)
{
DBG("%s:%d %s\n", __func__, __LINE__, str);
#ifdef CONFIG_SMP
smp_send_stop();
#endif
printk("\n");
printk(" System does not reboot automatically.\n");
printk(" Please press POWER button.\n");
printk("\n");
for (;;) ;
}
static void __init ps3_setup_arch(void)
{
DBG(" -> %s:%d\n", __func__, __LINE__);
ps3_spu_set_platform();
ps3_map_htab();
#ifdef CONFIG_SMP
smp_init_ps3();
#endif
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
ppc_md.power_save = ps3_power_save;
DBG(" <- %s:%d\n", __func__, __LINE__);
}
static void __init ps3_progress(char *s, unsigned short hex)
{
printk("*** %04x : %s\n", hex, s ? s : "");
}
static int __init ps3_probe(void)
{
unsigned long htab_size;
unsigned long dt_root;
DBG(" -> %s:%d\n", __func__, __LINE__);
dt_root = of_get_flat_dt_root();
if (!of_flat_dt_is_compatible(dt_root, "PS3"))
return 0;
powerpc_firmware_features |= FW_FEATURE_LPAR;
ps3_os_area_init();
ps3_mm_init();
ps3_mm_vas_create(&htab_size);
ps3_hpte_init(htab_size);
DBG(" <- %s:%d\n", __func__, __LINE__);
return 1;
}
#if defined(CONFIG_KEXEC)
static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
{
DBG(" -> %s:%d\n", __func__, __LINE__);
if (secondary) {
int cpu;
for_each_online_cpu(cpu)
if (cpu)
ps3_smp_cleanup_cpu(cpu);
} else
ps3_smp_cleanup_cpu(0);
DBG(" <- %s:%d\n", __func__, __LINE__);
}
static void ps3_machine_kexec(struct kimage *image)
{
unsigned long ppe_id;
DBG(" -> %s:%d\n", __func__, __LINE__);
lv1_get_logical_ppe_id(&ppe_id);
lv1_configure_irq_state_bitmap(ppe_id, 0, 0);
ps3_mm_shutdown();
ps3_mm_vas_destroy();
default_machine_kexec(image);
DBG(" <- %s:%d\n", __func__, __LINE__);
}
#endif
define_machine(ps3) {
.name = "PS3",
.probe = ps3_probe,
.setup_arch = ps3_setup_arch,
.show_cpuinfo = ps3_show_cpuinfo,
.init_IRQ = ps3_init_IRQ,
.panic = ps3_panic,
.get_boot_time = ps3_get_boot_time,
.set_rtc_time = ps3_set_rtc_time,
.get_rtc_time = ps3_get_rtc_time,
.calibrate_decr = ps3_calibrate_decr,
.progress = ps3_progress,
#if defined(CONFIG_KEXEC)
.kexec_cpu_down = ps3_kexec_cpu_down,
.machine_kexec = ps3_machine_kexec,
.machine_kexec_prepare = default_machine_kexec_prepare,
.machine_crash_shutdown = default_machine_crash_shutdown,
#endif
};
/*
* PS3 SMP routines.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/smp.h>
#include <asm/machdep.h>
#include <asm/udbg.h>
#include <asm/ps3.h>
#include "platform.h"
#if defined(DEBUG)
#define DBG(fmt...) udbg_printf(fmt)
#else
#define DBG(fmt...) do{if(0)printk(fmt);}while(0)
#endif
static irqreturn_t ipi_function_handler(int irq, void *msg)
{
smp_message_recv((int)(long)msg);
return IRQ_HANDLED;
}
/**
* virqs - a per cpu array of virqs for ipi use
*/
#define MSG_COUNT 4
static DEFINE_PER_CPU(unsigned int, virqs[MSG_COUNT]);
static const char *names[MSG_COUNT] = {
"ipi call",
"ipi reschedule",
"ipi migrate",
"ipi debug brk"
};
static void do_message_pass(int target, int msg)
{
int result;
unsigned int virq;
if (msg >= MSG_COUNT) {
DBG("%s:%d: bad msg: %d\n", __func__, __LINE__, msg);
return;
}
virq = per_cpu(virqs, target)[msg];
result = ps3_send_event_locally(virq);
if (result)
DBG("%s:%d: ps3_send_event_locally(%d, %d) failed"
" (%d)\n", __func__, __LINE__, target, msg, result);
}
static void ps3_smp_message_pass(int target, int msg)
{
int cpu;
if (target < NR_CPUS)
do_message_pass(target, msg);
else if (target == MSG_ALL_BUT_SELF) {
for_each_online_cpu(cpu)
if (cpu != smp_processor_id())
do_message_pass(cpu, msg);
} else {
for_each_online_cpu(cpu)
do_message_pass(cpu, msg);
}
}
static int ps3_smp_probe(void)
{
return 2;
}
static void __init ps3_smp_setup_cpu(int cpu)
{
int result;
unsigned int *virqs = per_cpu(virqs, cpu);
int i;
DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
/*
* Check assumptions on virqs[] indexing. If this
* check fails, then a different mapping of PPC_MSG_
* to index needs to be setup.
*/
BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION != 0);
BUILD_BUG_ON(PPC_MSG_RESCHEDULE != 1);
BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK != 3);
for (i = 0; i < MSG_COUNT; i++) {
result = ps3_alloc_event_irq(&virqs[i]);
if (result)
continue;
DBG("%s:%d: (%d, %d) => virq %u\n",
__func__, __LINE__, cpu, i, virqs[i]);
request_irq(virqs[i], ipi_function_handler, IRQF_DISABLED,
names[i], (void*)(long)i);
}
ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
}
void ps3_smp_cleanup_cpu(int cpu)
{
unsigned int *virqs = per_cpu(virqs, cpu);
int i;
DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
for (i = 0; i < MSG_COUNT; i++) {
ps3_free_event_irq(virqs[i]);
free_irq(virqs[i], (void*)(long)i);
virqs[i] = NO_IRQ;
}
DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
}
static struct smp_ops_t ps3_smp_ops = {
.probe = ps3_smp_probe,
.message_pass = ps3_smp_message_pass,
.kick_cpu = smp_generic_kick_cpu,
.setup_cpu = ps3_smp_setup_cpu,
};
void smp_init_ps3(void)
{
DBG(" -> %s\n", __func__);
smp_ops = &ps3_smp_ops;
DBG(" <- %s\n", __func__);
}
/*
* PS3 time and rtc routines.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <asm/rtc.h>
#include <asm/lv1call.h>
#include <asm/ps3.h>
#include "platform.h"
#define dump_tm(_a) _dump_tm(_a, __func__, __LINE__)
static void _dump_tm(const struct rtc_time *tm, const char* func, int line)
{
pr_debug("%s:%d tm_sec %d\n", func, line, tm->tm_sec);
pr_debug("%s:%d tm_min %d\n", func, line, tm->tm_min);
pr_debug("%s:%d tm_hour %d\n", func, line, tm->tm_hour);
pr_debug("%s:%d tm_mday %d\n", func, line, tm->tm_mday);
pr_debug("%s:%d tm_mon %d\n", func, line, tm->tm_mon);
pr_debug("%s:%d tm_year %d\n", func, line, tm->tm_year);
pr_debug("%s:%d tm_wday %d\n", func, line, tm->tm_wday);
}
#define dump_time(_a) _dump_time(_a, __func__, __LINE__)
static void __attribute__ ((unused)) _dump_time(int time, const char* func,
int line)
{
struct rtc_time tm;
to_tm(time, &tm);
pr_debug("%s:%d time %d\n", func, line, time);
_dump_tm(&tm, func, line);
}
/**
* rtc_shift - Difference in seconds between 1970 and the ps3 rtc value.
*/
static s64 rtc_shift;
void __init ps3_calibrate_decr(void)
{
int result;
u64 tmp;
result = ps3_repository_read_be_tb_freq(0, &tmp);
BUG_ON(result);
ppc_tb_freq = tmp;
ppc_proc_freq = ppc_tb_freq * 40;
rtc_shift = ps3_os_area_rtc_diff();
}
static u64 read_rtc(void)
{
int result;
u64 rtc_val;
u64 tb_val;
result = lv1_get_rtc(&rtc_val, &tb_val);
BUG_ON(result);
return rtc_val;
}
int ps3_set_rtc_time(struct rtc_time *tm)
{
u64 now = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
rtc_shift = now - read_rtc();
return 0;
}
void ps3_get_rtc_time(struct rtc_time *tm)
{
to_tm(read_rtc() + rtc_shift, tm);
tm->tm_year -= 1900;
tm->tm_mon -= 1;
}
unsigned long __init ps3_get_boot_time(void)
{
return read_rtc() + rtc_shift;
}
/*
* PS3 platform declarations.
*
* Copyright (C) 2006 Sony Computer Entertainment Inc.
* Copyright 2006 Sony Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined(_ASM_POWERPC_PS3_H)
#define _ASM_POWERPC_PS3_H
#include <linux/compiler.h> /* for __deprecated */
#include <linux/init.h>
#include <linux/types.h>
#include <linux/device.h>
/**
* struct ps3_device_id - HV bus device identifier from the system repository
* @bus_id: HV bus id, {1..} (zero invalid)
* @dev_id: HV device id, {0..}
*/
struct ps3_device_id {
unsigned int bus_id;
unsigned int dev_id;
};
/* dma routines */
enum ps3_dma_page_size {
PS3_DMA_4K = 12U,
PS3_DMA_64K = 16U,
PS3_DMA_1M = 20U,
PS3_DMA_16M = 24U,
};
enum ps3_dma_region_type {
PS3_DMA_OTHER = 0,
PS3_DMA_INTERNAL = 2,
};
/**
* struct ps3_dma_region - A per device dma state variables structure
* @did: The HV device id.
* @page_size: The ioc pagesize.
* @region_type: The HV region type.
* @bus_addr: The 'translated' bus address of the region.
* @len: The length in bytes of the region.
* @chunk_list: Opaque variable used by the ioc page manager.
*/
struct ps3_dma_region {
struct ps3_device_id did;
enum ps3_dma_page_size page_size;
enum ps3_dma_region_type region_type;
unsigned long bus_addr;
unsigned long len;
struct {
spinlock_t lock;
struct list_head head;
} chunk_list;
};
/**
* struct ps3_dma_region_init - Helper to initialize structure variables
*
* Helper to properly initialize variables prior to calling
* ps3_system_bus_device_register.
*/
static inline void ps3_dma_region_init(struct ps3_dma_region *r,
const struct ps3_device_id* did, enum ps3_dma_page_size page_size,
enum ps3_dma_region_type region_type)
{
r->did = *did;
r->page_size = page_size;
r->region_type = region_type;
}
int ps3_dma_region_create(struct ps3_dma_region *r);
int ps3_dma_region_free(struct ps3_dma_region *r);
int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr,
unsigned long len, unsigned long *bus_addr);
int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr,
unsigned long len);
/* mmio routines */
enum ps3_mmio_page_size {
PS3_MMIO_4K = 12U,
PS3_MMIO_64K = 16U
};
/**
* struct ps3_mmio_region - a per device mmio state variables structure
*
* Current systems can be supported with a single region per device.
*/
struct ps3_mmio_region {
struct ps3_device_id did;
unsigned long bus_addr;
unsigned long len;
enum ps3_mmio_page_size page_size;
unsigned long lpar_addr;
};
/**
* struct ps3_mmio_region_init - Helper to initialize structure variables
*
* Helper to properly initialize variables prior to calling
* ps3_system_bus_device_register.
*/
static inline void ps3_mmio_region_init(struct ps3_mmio_region *r,
const struct ps3_device_id* did, unsigned long bus_addr,
unsigned long len, enum ps3_mmio_page_size page_size)
{
r->did = *did;
r->bus_addr = bus_addr;
r->len = len;
r->page_size = page_size;
}
int ps3_mmio_region_create(struct ps3_mmio_region *r);
int ps3_free_mmio_region(struct ps3_mmio_region *r);
unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr);
/* inrerrupt routines */
int ps3_alloc_io_irq(unsigned int interrupt_id, unsigned int *virq);
int ps3_free_io_irq(unsigned int virq);
int ps3_alloc_event_irq(unsigned int *virq);
int ps3_free_event_irq(unsigned int virq);
int ps3_send_event_locally(unsigned int virq);
int ps3_connect_event_irq(const struct ps3_device_id *did,
unsigned int interrupt_id, unsigned int *virq);
int ps3_disconnect_event_irq(const struct ps3_device_id *did,
unsigned int interrupt_id, unsigned int virq);
int ps3_alloc_vuart_irq(void* virt_addr_bmp, unsigned int *virq);
int ps3_free_vuart_irq(unsigned int virq);
int ps3_alloc_spe_irq(unsigned long spe_id, unsigned int class,
unsigned int *virq);
int ps3_free_spe_irq(unsigned int virq);
/* lv1 result codes */
enum lv1_result {
LV1_SUCCESS = 0,
/* not used -1 */
LV1_RESOURCE_SHORTAGE = -2,
LV1_NO_PRIVILEGE = -3,
LV1_DENIED_BY_POLICY = -4,
LV1_ACCESS_VIOLATION = -5,
LV1_NO_ENTRY = -6,
LV1_DUPLICATE_ENTRY = -7,
LV1_TYPE_MISMATCH = -8,
LV1_BUSY = -9,
LV1_EMPTY = -10,
LV1_WRONG_STATE = -11,
/* not used -12 */
LV1_NO_MATCH = -13,
LV1_ALREADY_CONNECTED = -14,
LV1_UNSUPPORTED_PARAMETER_VALUE = -15,
LV1_CONDITION_NOT_SATISFIED = -16,
LV1_ILLEGAL_PARAMETER_VALUE = -17,
LV1_BAD_OPTION = -18,
LV1_IMPLEMENTATION_LIMITATION = -19,
LV1_NOT_IMPLEMENTED = -20,
LV1_INVALID_CLASS_ID = -21,
LV1_CONSTRAINT_NOT_SATISFIED = -22,
LV1_ALIGNMENT_ERROR = -23,
LV1_INTERNAL_ERROR = -32768,
};
static inline const char* ps3_result(int result)
{
#if defined(DEBUG)
switch (result) {
case LV1_SUCCESS:
return "LV1_SUCCESS (0)";
case -1:
return "** unknown result ** (-1)";
case LV1_RESOURCE_SHORTAGE:
return "LV1_RESOURCE_SHORTAGE (-2)";
case LV1_NO_PRIVILEGE:
return "LV1_NO_PRIVILEGE (-3)";
case LV1_DENIED_BY_POLICY:
return "LV1_DENIED_BY_POLICY (-4)";
case LV1_ACCESS_VIOLATION:
return "LV1_ACCESS_VIOLATION (-5)";
case LV1_NO_ENTRY:
return "LV1_NO_ENTRY (-6)";
case LV1_DUPLICATE_ENTRY:
return "LV1_DUPLICATE_ENTRY (-7)";
case LV1_TYPE_MISMATCH:
return "LV1_TYPE_MISMATCH (-8)";
case LV1_BUSY:
return "LV1_BUSY (-9)";
case LV1_EMPTY:
return "LV1_EMPTY (-10)";
case LV1_WRONG_STATE:
return "LV1_WRONG_STATE (-11)";
case -12:
return "** unknown result ** (-12)";
case LV1_NO_MATCH:
return "LV1_NO_MATCH (-13)";
case LV1_ALREADY_CONNECTED:
return "LV1_ALREADY_CONNECTED (-14)";
case LV1_UNSUPPORTED_PARAMETER_VALUE:
return "LV1_UNSUPPORTED_PARAMETER_VALUE (-15)";
case LV1_CONDITION_NOT_SATISFIED:
return "LV1_CONDITION_NOT_SATISFIED (-16)";
case LV1_ILLEGAL_PARAMETER_VALUE:
return "LV1_ILLEGAL_PARAMETER_VALUE (-17)";
case LV1_BAD_OPTION:
return "LV1_BAD_OPTION (-18)";
case LV1_IMPLEMENTATION_LIMITATION:
return "LV1_IMPLEMENTATION_LIMITATION (-19)";
case LV1_NOT_IMPLEMENTED:
return "LV1_NOT_IMPLEMENTED (-20)";
case LV1_INVALID_CLASS_ID:
return "LV1_INVALID_CLASS_ID (-21)";
case LV1_CONSTRAINT_NOT_SATISFIED:
return "LV1_CONSTRAINT_NOT_SATISFIED (-22)";
case LV1_ALIGNMENT_ERROR:
return "LV1_ALIGNMENT_ERROR (-23)";
case LV1_INTERNAL_ERROR:
return "LV1_INTERNAL_ERROR (-32768)";
default:
BUG();
return "** unknown result **";
};
#else
return "";
#endif
}
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册