?? system-bus.c
字號:
/* * PS3 system bus driver. * * 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/init.h>#include <linux/module.h>#include <linux/dma-mapping.h>#include <linux/err.h>#include <asm/udbg.h>#include <asm/lv1call.h>#include <asm/firmware.h>#include "platform.h"static struct device ps3_system_bus = { .bus_id = "ps3_system",};/* FIXME: need device usage counters! */struct { struct mutex mutex; int sb_11; /* usb 0 */ int sb_12; /* usb 0 */ int gpu;} static usage_hack;static int ps3_is_device(struct ps3_system_bus_device *dev, unsigned int bus_id, unsigned int dev_id){ return dev->bus_id == bus_id && dev->dev_id == dev_id;}static int ps3_open_hv_device_sb(struct ps3_system_bus_device *dev){ int result; BUG_ON(!dev->bus_id); mutex_lock(&usage_hack.mutex); if (ps3_is_device(dev, 1, 1)) { usage_hack.sb_11++; if (usage_hack.sb_11 > 1) { result = 0; goto done; } } if (ps3_is_device(dev, 1, 2)) { usage_hack.sb_12++; if (usage_hack.sb_12 > 1) { result = 0; goto done; } } result = lv1_open_device(dev->bus_id, dev->dev_id, 0); if (result) { pr_debug("%s:%d: lv1_open_device failed: %s\n", __func__, __LINE__, ps3_result(result)); result = -EPERM; }done: mutex_unlock(&usage_hack.mutex); return result;}static int ps3_close_hv_device_sb(struct ps3_system_bus_device *dev){ int result; BUG_ON(!dev->bus_id); mutex_lock(&usage_hack.mutex); if (ps3_is_device(dev, 1, 1)) { usage_hack.sb_11--; if (usage_hack.sb_11) { result = 0; goto done; } } if (ps3_is_device(dev, 1, 2)) { usage_hack.sb_12--; if (usage_hack.sb_12) { result = 0; goto done; } } result = lv1_close_device(dev->bus_id, dev->dev_id); BUG_ON(result);done: mutex_unlock(&usage_hack.mutex); return result;}static int ps3_open_hv_device_gpu(struct ps3_system_bus_device *dev){ int result; mutex_lock(&usage_hack.mutex); usage_hack.gpu++; if (usage_hack.gpu > 1) { result = 0; goto done; } result = lv1_gpu_open(0); if (result) { pr_debug("%s:%d: lv1_gpu_open failed: %s\n", __func__, __LINE__, ps3_result(result)); result = -EPERM; }done: mutex_unlock(&usage_hack.mutex); return result;}static int ps3_close_hv_device_gpu(struct ps3_system_bus_device *dev){ int result; mutex_lock(&usage_hack.mutex); usage_hack.gpu--; if (usage_hack.gpu) { result = 0; goto done; } result = lv1_gpu_close(); BUG_ON(result);done: mutex_unlock(&usage_hack.mutex); return result;}int ps3_open_hv_device(struct ps3_system_bus_device *dev){ BUG_ON(!dev); pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); switch (dev->match_id) { case PS3_MATCH_ID_EHCI: case PS3_MATCH_ID_OHCI: case PS3_MATCH_ID_GELIC: case PS3_MATCH_ID_STOR_DISK: case PS3_MATCH_ID_STOR_ROM: case PS3_MATCH_ID_STOR_FLASH: return ps3_open_hv_device_sb(dev); case PS3_MATCH_ID_SOUND: case PS3_MATCH_ID_GRAPHICS: return ps3_open_hv_device_gpu(dev); case PS3_MATCH_ID_AV_SETTINGS: case PS3_MATCH_ID_SYSTEM_MANAGER: pr_debug("%s:%d: unsupported match_id: %u\n", __func__, __LINE__, dev->match_id); pr_debug("%s:%d: bus_id: %u\n", __func__, __LINE__, dev->bus_id); BUG(); return -EINVAL; default: break; } pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, dev->match_id); BUG(); return -ENODEV;}EXPORT_SYMBOL_GPL(ps3_open_hv_device);int ps3_close_hv_device(struct ps3_system_bus_device *dev){ BUG_ON(!dev); pr_debug("%s:%d: match_id: %u\n", __func__, __LINE__, dev->match_id); switch (dev->match_id) { case PS3_MATCH_ID_EHCI: case PS3_MATCH_ID_OHCI: case PS3_MATCH_ID_GELIC: case PS3_MATCH_ID_STOR_DISK: case PS3_MATCH_ID_STOR_ROM: case PS3_MATCH_ID_STOR_FLASH: return ps3_close_hv_device_sb(dev); case PS3_MATCH_ID_SOUND: case PS3_MATCH_ID_GRAPHICS: return ps3_close_hv_device_gpu(dev); case PS3_MATCH_ID_AV_SETTINGS: case PS3_MATCH_ID_SYSTEM_MANAGER: pr_debug("%s:%d: unsupported match_id: %u\n", __func__, __LINE__, dev->match_id); pr_debug("%s:%d: bus_id: %u\n", __func__, __LINE__, dev->bus_id); BUG(); return -EINVAL; default: break; } pr_debug("%s:%d: unknown match_id: %u\n", __func__, __LINE__, dev->match_id); BUG(); return -ENODEV;}EXPORT_SYMBOL_GPL(ps3_close_hv_device);#define dump_mmio_region(_a) _dump_mmio_region(_a, __func__, __LINE__)static void _dump_mmio_region(const struct ps3_mmio_region* r, const char* func, int line){ pr_debug("%s:%d: dev %u:%u\n", func, line, r->dev->bus_id, r->dev->dev_id); pr_debug("%s:%d: bus_addr %lxh\n", func, line, r->bus_addr); pr_debug("%s:%d: len %lxh\n", func, line, r->len); pr_debug("%s:%d: lpar_addr %lxh\n", func, line, r->lpar_addr);}static int ps3_sb_mmio_region_create(struct ps3_mmio_region *r){ int result; result = lv1_map_device_mmio_region(r->dev->bus_id, r->dev->dev_id, r->bus_addr, r->len, r->page_size, &r->lpar_addr); if (result) { pr_debug("%s:%d: lv1_map_device_mmio_region failed: %s\n", __func__, __LINE__, ps3_result(result)); r->lpar_addr = 0; } dump_mmio_region(r); return result;}static int ps3_ioc0_mmio_region_create(struct ps3_mmio_region *r){ /* device specific; do nothing currently */ return 0;}int ps3_mmio_region_create(struct ps3_mmio_region *r){ return r->mmio_ops->create(r);}EXPORT_SYMBOL_GPL(ps3_mmio_region_create);static int ps3_sb_free_mmio_region(struct ps3_mmio_region *r){ int result; dump_mmio_region(r);; result = lv1_unmap_device_mmio_region(r->dev->bus_id, r->dev->dev_id, r->lpar_addr); if (result) pr_debug("%s:%d: lv1_unmap_device_mmio_region failed: %s\n", __func__, __LINE__, ps3_result(result)); r->lpar_addr = 0; return result;}static int ps3_ioc0_free_mmio_region(struct ps3_mmio_region *r){ /* device specific; do nothing currently */ return 0;}int ps3_free_mmio_region(struct ps3_mmio_region *r){ return r->mmio_ops->free(r);}EXPORT_SYMBOL_GPL(ps3_free_mmio_region);static const struct ps3_mmio_region_ops ps3_mmio_sb_region_ops = { .create = ps3_sb_mmio_region_create, .free = ps3_sb_free_mmio_region};static const struct ps3_mmio_region_ops ps3_mmio_ioc0_region_ops = { .create = ps3_ioc0_mmio_region_create, .free = ps3_ioc0_free_mmio_region};int ps3_mmio_region_init(struct ps3_system_bus_device *dev, struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, enum ps3_mmio_page_size page_size){ r->dev = dev; r->bus_addr = bus_addr; r->len = len; r->page_size = page_size; switch (dev->dev_type) { case PS3_DEVICE_TYPE_SB: r->mmio_ops = &ps3_mmio_sb_region_ops; break; case PS3_DEVICE_TYPE_IOC0: r->mmio_ops = &ps3_mmio_ioc0_region_ops; break; default: BUG(); return -EINVAL; } return 0;}EXPORT_SYMBOL_GPL(ps3_mmio_region_init);static int ps3_system_bus_match(struct device *_dev, struct device_driver *_drv){ int result; struct ps3_system_bus_driver *drv = ps3_drv_to_system_bus_drv(_drv); struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); result = dev->match_id == drv->match_id; pr_info("%s:%d: dev=%u(%s), drv=%u(%s): %s\n", __func__, __LINE__, dev->match_id, dev->core.bus_id, drv->match_id, drv->core.name, (result ? "match" : "miss")); return result;}static int ps3_system_bus_probe(struct device *_dev){ int result = 0; struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); struct ps3_system_bus_driver *drv; BUG_ON(!dev); pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); drv = ps3_system_bus_dev_to_system_bus_drv(dev); BUG_ON(!drv); if (drv->probe) result = drv->probe(dev); else pr_info("%s:%d: %s no probe method\n", __func__, __LINE__, dev->core.bus_id); pr_info(" <- %s:%d: %s\n", __func__, __LINE__, dev->core.bus_id); return result;}static int ps3_system_bus_remove(struct device *_dev){ int result = 0; struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); struct ps3_system_bus_driver *drv; BUG_ON(!dev); pr_info(" -> %s:%d: %s\n", __func__, __LINE__, _dev->bus_id); drv = ps3_system_bus_dev_to_system_bus_drv(dev); BUG_ON(!drv);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -