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

📄 device-init.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  PS3 device registration routines. * *  Copyright (C) 2007 Sony Computer Entertainment Inc. *  Copyright 2007 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/delay.h>#include <linux/freezer.h>#include <linux/kernel.h>#include <linux/kthread.h>#include <linux/init.h>#include <asm/firmware.h>#include <asm/lv1call.h>#include <asm/ps3stor.h>#include "platform.h"/** * ps3_setup_gelic_device - Setup and register a gelic device instance. * * Allocates memory for a struct ps3_system_bus_device instance, initialises the * structure members, and registers the device instance with the system bus. */static int __init ps3_setup_gelic_device(	const struct ps3_repository_device *repo){	int result;	struct layout {		struct ps3_system_bus_device dev;		struct ps3_dma_region d_region;	} *p;	pr_debug(" -> %s:%d\n", __func__, __LINE__);	BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);	BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_GELIC);	p = kzalloc(sizeof(struct layout), GFP_KERNEL);	if (!p) {		result = -ENOMEM;		goto fail_malloc;	}	p->dev.match_id = PS3_MATCH_ID_GELIC;	p->dev.dev_type = PS3_DEVICE_TYPE_SB;	p->dev.bus_id = repo->bus_id;	p->dev.dev_id = repo->dev_id;	p->dev.d_region = &p->d_region;	result = ps3_repository_find_interrupt(repo,		PS3_INTERRUPT_TYPE_EVENT_PORT, &p->dev.interrupt_id);	if (result) {		pr_debug("%s:%d ps3_repository_find_interrupt failed\n",			__func__, __LINE__);		goto fail_find_interrupt;	}	BUG_ON(p->dev.interrupt_id != 0);	result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,		PS3_DMA_OTHER, NULL, 0);	if (result) {		pr_debug("%s:%d ps3_dma_region_init failed\n",			__func__, __LINE__);		goto fail_dma_init;	}	result = ps3_system_bus_device_register(&p->dev);	if (result) {		pr_debug("%s:%d ps3_system_bus_device_register failed\n",			__func__, __LINE__);		goto fail_device_register;	}	pr_debug(" <- %s:%d\n", __func__, __LINE__);	return result;fail_device_register:fail_dma_init:fail_find_interrupt:	kfree(p);fail_malloc:	pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);	return result;}static int __init_refok ps3_setup_uhc_device(	const struct ps3_repository_device *repo, enum ps3_match_id match_id,	enum ps3_interrupt_type interrupt_type, enum ps3_reg_type reg_type){	int result;	struct layout {		struct ps3_system_bus_device dev;		struct ps3_dma_region d_region;		struct ps3_mmio_region m_region;	} *p;	u64 bus_addr;	u64 len;	pr_debug(" -> %s:%d\n", __func__, __LINE__);	BUG_ON(repo->bus_type != PS3_BUS_TYPE_SB);	BUG_ON(repo->dev_type != PS3_DEV_TYPE_SB_USB);	p = kzalloc(sizeof(struct layout), GFP_KERNEL);	if (!p) {		result = -ENOMEM;		goto fail_malloc;	}	p->dev.match_id = match_id;	p->dev.dev_type = PS3_DEVICE_TYPE_SB;	p->dev.bus_id = repo->bus_id;	p->dev.dev_id = repo->dev_id;	p->dev.d_region = &p->d_region;	p->dev.m_region = &p->m_region;	result = ps3_repository_find_interrupt(repo,		interrupt_type, &p->dev.interrupt_id);	if (result) {		pr_debug("%s:%d ps3_repository_find_interrupt failed\n",			__func__, __LINE__);		goto fail_find_interrupt;	}	result = ps3_repository_find_reg(repo, reg_type,		&bus_addr, &len);	if (result) {		pr_debug("%s:%d ps3_repository_find_reg failed\n",			__func__, __LINE__);		goto fail_find_reg;	}	result = ps3_dma_region_init(&p->dev, p->dev.d_region, PS3_DMA_64K,		PS3_DMA_INTERNAL, NULL, 0);	if (result) {		pr_debug("%s:%d ps3_dma_region_init failed\n",			__func__, __LINE__);		goto fail_dma_init;	}	result = ps3_mmio_region_init(&p->dev, p->dev.m_region, bus_addr, len,		PS3_MMIO_4K);	if (result) {		pr_debug("%s:%d ps3_mmio_region_init failed\n",			__func__, __LINE__);		goto fail_mmio_init;	}	result = ps3_system_bus_device_register(&p->dev);	if (result) {		pr_debug("%s:%d ps3_system_bus_device_register failed\n",			__func__, __LINE__);		goto fail_device_register;	}	pr_debug(" <- %s:%d\n", __func__, __LINE__);	return result;fail_device_register:fail_mmio_init:fail_dma_init:fail_find_reg:fail_find_interrupt:	kfree(p);fail_malloc:	pr_debug(" <- %s:%d: fail.\n", __func__, __LINE__);	return result;}static int __init ps3_setup_ehci_device(	const struct ps3_repository_device *repo){	return ps3_setup_uhc_device(repo, PS3_MATCH_ID_EHCI,		PS3_INTERRUPT_TYPE_SB_EHCI, PS3_REG_TYPE_SB_EHCI);}static int __init ps3_setup_ohci_device(	const struct ps3_repository_device *repo){	return ps3_setup_uhc_device(repo, PS3_MATCH_ID_OHCI,		PS3_INTERRUPT_TYPE_SB_OHCI, PS3_REG_TYPE_SB_OHCI);}static int __init ps3_setup_vuart_device(enum ps3_match_id match_id,	unsigned int port_number){	int result;	struct layout {		struct ps3_system_bus_device dev;	} *p;	pr_debug(" -> %s:%d: match_id %u, port %u\n", __func__, __LINE__,		match_id, port_number);	p = kzalloc(sizeof(struct layout), GFP_KERNEL);	if (!p)		return -ENOMEM;	p->dev.match_id = match_id;	p->dev.dev_type = PS3_DEVICE_TYPE_VUART;	p->dev.port_number = port_number;	result = ps3_system_bus_device_register(&p->dev);	if (result)		pr_debug("%s:%d ps3_system_bus_device_register failed\n",			__func__, __LINE__);	pr_debug(" <- %s:%d\n", __func__, __LINE__);	return result;}static int ps3stor_wait_for_completion(u64 dev_id, u64 tag,				       unsigned int timeout){	int result = -1;	unsigned int retries = 0;	u64 status;	for (retries = 0; retries < timeout; retries++) {		result = lv1_storage_check_async_status(dev_id, tag, &status);		if (!result)			break;		msleep(1);	}	if (result)		pr_debug("%s:%u: check_async_status: %s, status %lx\n",			 __func__, __LINE__, ps3_result(result), status);	return result;}/** * ps3_storage_wait_for_device - Wait for a storage device to become ready. * @repo: The repository device to wait for. * * Uses the hypervisor's storage device notification mechanism to wait until * a storage device is ready.  The device notification mechanism uses a * psuedo device (id = -1) to asynchronously notify the guest when storage * devices become ready.  The notification device has a block size of 512 * bytes. */static int ps3_storage_wait_for_device(const struct ps3_repository_device *repo){	int error = -ENODEV;	int result;	const u64 notification_dev_id = (u64)-1LL;	const unsigned int timeout = HZ;	u64 lpar;	u64 tag;	void *buf;	enum ps3_notify_type {		notify_device_ready = 0,		notify_region_probe = 1,		notify_region_update = 2,	};	struct {		u64 operation_code;	/* must be zero */		u64 event_mask;		/* OR of 1UL << enum ps3_notify_type */	} *notify_cmd;	struct {		u64 event_type;		/* enum ps3_notify_type */		u64 bus_id;		u64 dev_id;		u64 dev_type;		u64 dev_port;	} *notify_event;	pr_debug(" -> %s:%u: (%u:%u:%u)\n", __func__, __LINE__, repo->bus_id,		 repo->dev_id, repo->dev_type);	buf = kzalloc(512, GFP_KERNEL);	if (!buf)		return -ENOMEM;	lpar = ps3_mm_phys_to_lpar(__pa(buf));	notify_cmd = buf;	notify_event = buf;	result = lv1_open_device(repo->bus_id, notification_dev_id, 0);	if (result) {		printk(KERN_ERR "%s:%u: lv1_open_device %s\n", __func__,		       __LINE__, ps3_result(result));		goto fail_free;	}	/* Setup and write the request for device notification. */	notify_cmd->operation_code = 0; /* must be zero */	notify_cmd->event_mask = 1UL << notify_region_probe;	result = lv1_storage_write(notification_dev_id, 0, 0, 1, 0, lpar,				   &tag);	if (result) {		printk(KERN_ERR "%s:%u: write failed %s\n", __func__, __LINE__,		       ps3_result(result));		goto fail_close;	}	/* Wait for the write completion */	result = ps3stor_wait_for_completion(notification_dev_id, tag,					     timeout);	if (result) {		printk(KERN_ERR "%s:%u: write not completed %s\n", __func__,		       __LINE__, ps3_result(result));		goto fail_close;	}	/* Loop here processing the requested notification events. */	while (1) {		memset(notify_event, 0, sizeof(*notify_event));		result = lv1_storage_read(notification_dev_id, 0, 0, 1, 0,					  lpar, &tag);		if (result) {			printk(KERN_ERR "%s:%u: write failed %s\n", __func__,			       __LINE__, ps3_result(result));			break;		}		result = ps3stor_wait_for_completion(notification_dev_id, tag,						     timeout);		if (result) {			printk(KERN_ERR "%s:%u: read not completed %s\n",			       __func__, __LINE__, ps3_result(result));			break;		}		pr_debug("%s:%d: notify event (%u:%u:%u): event_type 0x%lx, "			 "port %lu\n", __func__, __LINE__, repo->bus_index,			 repo->dev_index, repo->dev_type,			 notify_event->event_type, notify_event->dev_port);		if (notify_event->event_type != notify_region_probe ||		    notify_event->bus_id != repo->bus_id) {			pr_debug("%s:%u: bad notify_event: event %lu, "				 "dev_id %lu, dev_type %lu\n",				 __func__, __LINE__, notify_event->event_type,				 notify_event->dev_id, notify_event->dev_type);			break;		}		if (notify_event->dev_id == repo->dev_id &&		    notify_event->dev_type == repo->dev_type) {			pr_debug("%s:%u: device ready (%u:%u:%u)\n", __func__,				 __LINE__, repo->bus_index, repo->dev_index,				 repo->dev_type);			error = 0;			break;		}		if (notify_event->dev_id == repo->dev_id &&		    notify_event->dev_type == PS3_DEV_TYPE_NOACCESS) {			pr_debug("%s:%u: no access: dev_id %u\n", __func__,				 __LINE__, repo->dev_id);			break;		}	}fail_close:	lv1_close_device(repo->bus_id, notification_dev_id);fail_free:	kfree(buf);	pr_debug(" <- %s:%u\n", __func__, __LINE__);	return error;

⌨️ 快捷键说明

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