⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 repository.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  PS3 repository 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 <asm/lv1call.h>#include "platform.h"enum ps3_vendor_id {	PS3_VENDOR_ID_NONE = 0,	PS3_VENDOR_ID_SONY = 0x8000000000000000UL,};enum ps3_lpar_id {	PS3_LPAR_ID_CURRENT = 0,	PS3_LPAR_ID_PME = 1,};#define dump_field(_a, _b) _dump_field(_a, _b, __func__, __LINE__)static void _dump_field(const char *hdr, u64 n, const char* func, int line){#if defined(DEBUG)	char s[16];	const char *const in = (const char *)&n;	unsigned int i;	for (i = 0; i < 8; i++)		s[i] = (in[i] <= 126 && in[i] >= 32) ? in[i] : '.';	s[i] = 0;	pr_debug("%s:%d: %s%016lx : %s\n", func, line, hdr, n, s);#endif}#define dump_node_name(_a, _b, _c, _d, _e) \	_dump_node_name(_a, _b, _c, _d, _e, __func__, __LINE__)static void _dump_node_name (unsigned int lpar_id, u64 n1, u64 n2, u64 n3,	u64 n4, const char* func, int line){	pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);	_dump_field("n1: ", n1, func, line);	_dump_field("n2: ", n2, func, line);	_dump_field("n3: ", n3, func, line);	_dump_field("n4: ", n4, func, line);}#define dump_node(_a, _b, _c, _d, _e, _f, _g) \	_dump_node(_a, _b, _c, _d, _e, _f, _g, __func__, __LINE__)static void _dump_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,	u64 v1, u64 v2, const char* func, int line){	pr_debug("%s:%d: lpar: %u\n", func, line, lpar_id);	_dump_field("n1: ", n1, func, line);	_dump_field("n2: ", n2, func, line);	_dump_field("n3: ", n3, func, line);	_dump_field("n4: ", n4, func, line);	pr_debug("%s:%d: v1: %016lx\n", func, line, v1);	pr_debug("%s:%d: v2: %016lx\n", func, line, v2);}/** * make_first_field - Make the first field of a repository node name. * @text: Text portion of the field. * @index: Numeric index portion of the field.  Use zero for 'don't care'. * * This routine sets the vendor id to zero (non-vendor specific). * Returns field value. */static u64 make_first_field(const char *text, u64 index){	u64 n;	strncpy((char *)&n, text, 8);	return PS3_VENDOR_ID_NONE + (n >> 32) + index;}/** * make_field - Make subsequent fields of a repository node name. * @text: Text portion of the field.  Use "" for 'don't care'. * @index: Numeric index portion of the field.  Use zero for 'don't care'. * * Returns field value. */static u64 make_field(const char *text, u64 index){	u64 n;	strncpy((char *)&n, text, 8);	return n + index;}/** * read_node - Read a repository node from raw fields. * @n1: First field of node name. * @n2: Second field of node name.  Use zero for 'don't care'. * @n3: Third field of node name.  Use zero for 'don't care'. * @n4: Fourth field of node name.  Use zero for 'don't care'. * @v1: First repository value (high word). * @v2: Second repository value (low word).  Optional parameter, use zero *      for 'don't care'. */static int read_node(unsigned int lpar_id, u64 n1, u64 n2, u64 n3, u64 n4,	u64 *_v1, u64 *_v2){	int result;	u64 v1;	u64 v2;	if (lpar_id == PS3_LPAR_ID_CURRENT) {		u64 id;		lv1_get_logical_partition_id(&id);		lpar_id = id;	}	result = lv1_get_repository_node_value(lpar_id, n1, n2, n3, n4, &v1,		&v2);	if (result) {		pr_debug("%s:%d: lv1_get_repository_node_value failed: %s\n",			__func__, __LINE__, ps3_result(result));		dump_node_name(lpar_id, n1, n2, n3, n4);		return -ENOENT;	}	dump_node(lpar_id, n1, n2, n3, n4, v1, v2);	if (_v1)		*_v1 = v1;	if (_v2)		*_v2 = v2;	if (v1 && !_v1)		pr_debug("%s:%d: warning: discarding non-zero v1: %016lx\n",			__func__, __LINE__, v1);	if (v2 && !_v2)		pr_debug("%s:%d: warning: discarding non-zero v2: %016lx\n",			__func__, __LINE__, v2);	return 0;}int ps3_repository_read_bus_str(unsigned int bus_index, const char *bus_str,	u64 *value){	return read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field(bus_str, 0),		0, 0,		value, 0);}int ps3_repository_read_bus_id(unsigned int bus_index, unsigned int *bus_id){	int result;	u64 v1;	u64 v2; /* unused */	result = read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field("id", 0),		0, 0,		&v1, &v2);	*bus_id = v1;	return result;}int ps3_repository_read_bus_type(unsigned int bus_index,	enum ps3_bus_type *bus_type){	int result;	u64 v1;	result = read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field("type", 0),		0, 0,		&v1, 0);	*bus_type = v1;	return result;}int ps3_repository_read_bus_num_dev(unsigned int bus_index,	unsigned int *num_dev){	int result;	u64 v1;	result = read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field("num_dev", 0),		0, 0,		&v1, 0);	*num_dev = v1;	return result;}int ps3_repository_read_dev_str(unsigned int bus_index,	unsigned int dev_index, const char *dev_str, u64 *value){	return read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field("dev", dev_index),		make_field(dev_str, 0),		0,		value, 0);}int ps3_repository_read_dev_id(unsigned int bus_index, unsigned int dev_index,	unsigned int *dev_id){	int result;	u64 v1;	result = read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field("dev", dev_index),		make_field("id", 0),		0,		&v1, 0);	*dev_id = v1;	return result;}int ps3_repository_read_dev_type(unsigned int bus_index,	unsigned int dev_index, enum ps3_dev_type *dev_type){	int result;	u64 v1;	result = read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field("dev", dev_index),		make_field("type", 0),		0,		&v1, 0);	*dev_type = v1;	return result;}int ps3_repository_read_dev_intr(unsigned int bus_index,	unsigned int dev_index, unsigned int intr_index,	enum ps3_interrupt_type *intr_type, unsigned int* interrupt_id){	int result;	u64 v1;	u64 v2;	result = read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field("dev", dev_index),		make_field("intr", intr_index),		0,		&v1, &v2);	*intr_type = v1;	*interrupt_id = v2;	return result;}int ps3_repository_read_dev_reg_type(unsigned int bus_index,	unsigned int dev_index, unsigned int reg_index,	enum ps3_reg_type *reg_type){	int result;	u64 v1;	result = read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field("dev", dev_index),		make_field("reg", reg_index),		make_field("type", 0),		&v1, 0);	*reg_type = v1;	return result;}int ps3_repository_read_dev_reg_addr(unsigned int bus_index,	unsigned int dev_index, unsigned int reg_index, u64 *bus_addr, u64 *len){	return read_node(PS3_LPAR_ID_PME,		make_first_field("bus", bus_index),		make_field("dev", dev_index),		make_field("reg", reg_index),		make_field("data", 0),		bus_addr, len);}int ps3_repository_read_dev_reg(unsigned int bus_index,	unsigned int dev_index, unsigned int reg_index,	enum ps3_reg_type *reg_type, u64 *bus_addr, u64 *len){	int result = ps3_repository_read_dev_reg_type(bus_index, dev_index,		reg_index, reg_type);	return result ? result		: ps3_repository_read_dev_reg_addr(bus_index, dev_index,		reg_index, bus_addr, len);}int ps3_repository_find_device(struct ps3_repository_device *repo){	int result;	struct ps3_repository_device tmp = *repo;	unsigned int num_dev;	BUG_ON(repo->bus_index > 10);	BUG_ON(repo->dev_index > 10);	result = ps3_repository_read_bus_num_dev(tmp.bus_index, &num_dev);	if (result) {		pr_debug("%s:%d read_bus_num_dev failed\n", __func__, __LINE__);		return result;	}	pr_debug("%s:%d: bus_type %u, bus_index %u, bus_id %u, num_dev %u\n",		__func__, __LINE__, tmp.bus_type, tmp.bus_index, tmp.bus_id,		num_dev);	if (tmp.dev_index >= num_dev) {		pr_debug("%s:%d: no device found\n", __func__, __LINE__);		return -ENODEV;	}	result = ps3_repository_read_dev_type(tmp.bus_index, tmp.dev_index,		&tmp.dev_type);	if (result) {		pr_debug("%s:%d read_dev_type failed\n", __func__, __LINE__);		return result;	}	if (tmp.bus_type == PS3_BUS_TYPE_STORAGE) {		/*		 * A storage device may show up in the repository before the		 * hypervisor has finished probing its type and regions		 */		unsigned int num_regions;		if (tmp.dev_type == PS3_DEV_TYPE_STOR_DUMMY) {			pr_debug("%s:%u storage device not ready\n", __func__,				 __LINE__);			return -ENODEV;		}		result = ps3_repository_read_stor_dev_num_regions(tmp.bus_index,								  tmp.dev_index,								  &num_regions);		if (result) {			pr_debug("%s:%d read_stor_dev_num_regions failed\n",				 __func__, __LINE__);			return result;		}		if (!num_regions) {			pr_debug("%s:%u storage device has no regions yet\n",				 __func__, __LINE__);			return -ENODEV;		}	}	result = ps3_repository_read_dev_id(tmp.bus_index, tmp.dev_index,		&tmp.dev_id);	if (result) {		pr_debug("%s:%d ps3_repository_read_dev_id failed\n", __func__,		__LINE__);		return result;	}	pr_debug("%s:%d: found: dev_type %u, dev_index %u, dev_id %u\n",		__func__, __LINE__, tmp.dev_type, tmp.dev_index, tmp.dev_id);	*repo = tmp;	return 0;}int __devinit ps3_repository_find_devices(enum ps3_bus_type bus_type,	int (*callback)(const struct ps3_repository_device *repo)){	int result = 0;	struct ps3_repository_device repo;	pr_debug(" -> %s:%d: find bus_type %u\n", __func__, __LINE__, bus_type);	for (repo.bus_index = 0; repo.bus_index < 10; repo.bus_index++) {		result = ps3_repository_read_bus_type(repo.bus_index,			&repo.bus_type);		if (result) {			pr_debug("%s:%d read_bus_type(%u) failed\n",				__func__, __LINE__, repo.bus_index);			break;		}		if (repo.bus_type != bus_type) {			pr_debug("%s:%d: skip, bus_type %u\n", __func__,				__LINE__, repo.bus_type);			continue;		}		result = ps3_repository_read_bus_id(repo.bus_index,			&repo.bus_id);		if (result) {			pr_debug("%s:%d read_bus_id(%u) failed\n",				__func__, __LINE__, repo.bus_index);			continue;		}		for (repo.dev_index = 0; ; repo.dev_index++) {			result = ps3_repository_find_device(&repo);			if (result == -ENODEV) {				result = 0;				break;			} else if (result)				break;			result = callback(&repo);			if (result) {				pr_debug("%s:%d: abort at callback\n", __func__,					__LINE__);				break;			}		}		break;	}	pr_debug(" <- %s:%d\n", __func__, __LINE__);	return result;}int ps3_repository_find_bus(enum ps3_bus_type bus_type, unsigned int from,	unsigned int *bus_index){	unsigned int i;	enum ps3_bus_type type;	int error;	for (i = from; i < 10; i++) {		error = ps3_repository_read_bus_type(i, &type);		if (error) {			pr_debug("%s:%d read_bus_type failed\n",				__func__, __LINE__);			*bus_index = UINT_MAX;			return error;		}		if (type == bus_type) {			*bus_index = i;			return 0;		}	}	*bus_index = UINT_MAX;	return -ENODEV;}int ps3_repository_find_interrupt(const struct ps3_repository_device *repo,	enum ps3_interrupt_type intr_type, unsigned int *interrupt_id){	int result = 0;	unsigned int res_index;	pr_debug("%s:%d: find intr_type %u\n", __func__, __LINE__, intr_type);	*interrupt_id = UINT_MAX;	for (res_index = 0; res_index < 10; res_index++) {		enum ps3_interrupt_type t;		unsigned int id;		result = ps3_repository_read_dev_intr(repo->bus_index,			repo->dev_index, res_index, &t, &id);		if (result) {			pr_debug("%s:%d read_dev_intr failed\n",				__func__, __LINE__);			return result;		}		if (t == intr_type) {			*interrupt_id = id;			break;		}	}	if (res_index == 10)		return -ENODEV;	pr_debug("%s:%d: found intr_type %u at res_index %u\n",		__func__, __LINE__, intr_type, res_index);	return result;}int ps3_repository_find_reg(const struct ps3_repository_device *repo,	enum ps3_reg_type reg_type, u64 *bus_addr, u64 *len){	int result = 0;	unsigned int res_index;	pr_debug("%s:%d: find reg_type %u\n", __func__, __LINE__, reg_type);	*bus_addr = *len = 0;	for (res_index = 0; res_index < 10; res_index++) {		enum ps3_reg_type t;		u64 a;		u64 l;		result = ps3_repository_read_dev_reg(repo->bus_index,			repo->dev_index, res_index, &t, &a, &l);		if (result) {			pr_debug("%s:%d read_dev_reg failed\n",				__func__, __LINE__);			return result;		}		if (t == reg_type) {			*bus_addr = a;			*len = l;			break;		}	}	if (res_index == 10)		return -ENODEV;	pr_debug("%s:%d: found reg_type %u at res_index %u\n",		__func__, __LINE__, reg_type, res_index);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -