📄 ocp.c
字号:
up_read(&ocp_devices_sem); return dev;}/** * ocp_get_one_device - Find a def by function & index * @vendor: vendor ID of the device (or OCP_ANY_ID) * @function: function code of the device (or OCP_ANY_ID) * @idx: index of the device (or OCP_ANY_INDEX) * * This function allows a lookup of a given ocp_def by it's * vendor, function, and index. The main purpose for is to * allow modification of the def before binding to the driver */struct ocp_def *ocp_get_one_device(unsigned int vendor, unsigned int function, int index){ struct ocp_device *dev; struct ocp_def *found = NULL; DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index)); dev = ocp_find_device(vendor, function, index); if (dev) found = dev->def; DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index)); return found;}/** * ocp_add_one_device - Add a device * @def: static device definition structure * * This function adds a device definition to the * device list. It may only be called before * ocp_driver_init() and will return an error * otherwise. */intocp_add_one_device(struct ocp_def *def){ struct ocp_device *dev; DBG(("ocp: ocp_add_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index)); /* Can't be called after ocp driver init */ if (ocp_inited) return 1; if (mem_init_done) dev = kmalloc(sizeof(*dev), GFP_KERNEL); else dev = alloc_bootmem(sizeof(*dev)); if (dev == NULL) return 1; memset(dev, 0, sizeof(*dev)); dev->def = def; dev->current_state = 4; sprintf(dev->name, "OCP device %04x:%04x:%04x", dev->def->vendor, dev->def->function, dev->def->index); down_write(&ocp_devices_sem); list_add_tail(&dev->link, &ocp_devices); up_write(&ocp_devices_sem); DBG(("ocp: ocp_add_one_device(vendor: %x, function: %x, index: %d)...done.\n", vendor, function, index)); return 0;}/** * ocp_remove_one_device - Remove a device by function & index * @vendor: vendor ID of the device (or OCP_ANY_ID) * @function: function code of the device (or OCP_ANY_ID) * @idx: index of the device (or OCP_ANY_INDEX) * * This function allows removal of a given function by its * index. It may only be called before ocp_driver_init() * and will return an error otherwise. */intocp_remove_one_device(unsigned int vendor, unsigned int function, int index){ struct ocp_device *dev; int rc = 0; DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index)); /* Can't be called after ocp driver init */ if (ocp_inited) return 1; down_write(&ocp_devices_sem); dev = __ocp_find_device(vendor, function, index); if (dev != NULL) list_del((struct list_head *)dev); else rc = 1; up_write(&ocp_devices_sem); DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index)); return rc;}#ifdef CONFIG_PM/** * OCP Power management.. * * This needs to be done centralized, so that we power manage PCI * devices in the right order: we should not shut down PCI bridges * before we've shut down the devices behind them, and we should * not wake up devices before we've woken up the bridge to the * device.. Eh? * * We do not touch devices that don't have a driver that exports * a suspend/resume function. That is just too dangerous. If the default * PCI suspend/resume functions work for a device, the driver can * easily implement them (ie just have a suspend function that calls * the pci_set_power_state() function). * * BenH: Implementation here couldn't work properly. This version * slightly modified and _might_ be more useable, but real * PM support will probably have to wait for 2.5 */static int ocp_pm_save_state_device(struct ocp_device *dev, u32 state){ int error = 0; if (dev) { struct ocp_driver *driver = dev->driver; if (driver && driver->save_state) error = driver->save_state(dev,state); } return error;}static int ocp_pm_suspend_device(struct ocp_device *dev, u32 state){ int error = 0; if (dev) { struct ocp_driver *driver = dev->driver; if (driver && driver->suspend) error = driver->suspend(dev,state); } return error;}static int ocp_pm_resume_device(struct ocp_device *dev){ int error = 0; if (dev) { struct ocp_driver *driver = dev->driver; if (driver && driver->resume) error = driver->resume(dev); } return error;}static intocp_pm_callback(struct pm_dev *pm_device, pm_request_t rqst, void *data){ int error = 0; struct list_head *entry; struct ocp_device *dev; down(&ocp_drivers_sem); down_read(&ocp_devices_sem); list_for_each(entry, &ocp_devices) { dev = list_entry(entry, struct ocp_device, link); switch (rqst) { case PM_SAVE_STATE: error = ocp_pm_save_state_device(dev, 3); break; case PM_SUSPEND: error = ocp_pm_suspend_device(dev, 3); break; case PM_RESUME: error = ocp_pm_resume_device(dev); break; default: break; } if (error) break; } return error;}/* * Is this ever used ? */voidppc4xx_cpm_fr(u32 bits, int val){ unsigned long flags; save_flags(flags); cli(); if (val) mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | bits); else mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~bits); restore_flags(flags);}#endif /* CONFIG_PM *//** * ocp_early_init - Init OCP device management * * This function builds the list of devices before setup_arch. * This allows platform code to modify the device lists before * they are bound to drivers (changes to paddr, removing devices * etc) */int __initocp_early_init(void){ struct ocp_def *def; DBG(("ocp: ocp_early_init()...\n")); /* Fill the devices list */ for (def = core_ocp; def->vendor != OCP_VENDOR_INVALID; def++) ocp_add_one_device(def); DBG(("ocp: ocp_early_init()... done.\n")); return 0;}/** * ocp_driver_init - Init OCP device management * * This function is meant to be called once, and only once to initialize * the OCP device management. Note that it can actually be called at any * time, it's perfectly legal to register drivers before * ocp_driver_init() is called */intocp_driver_init(void){ /* ocp_driver_init is by default an initcall. If your arch requires * this to be called earlier, then go on, ocp_driver_init is * non-static for that purpose, and can safely be called twice */ if (ocp_inited) return 0; ocp_inited = 1; DBG(("ocp: ocp_driver_init()...\n")); /* Call drivers probes */ down(&ocp_drivers_sem); ocp_bind_drivers(NULL); up(&ocp_drivers_sem);#ifdef CONFIG_PM pm_register(PM_SYS_DEV, 0, ocp_pm_callback);#endif DBG(("ocp: ocp_driver_init()... done.\n")); return 0;}__initcall(ocp_driver_init);EXPORT_SYMBOL(ocp_find_device);EXPORT_SYMBOL(ocp_register_driver);EXPORT_SYMBOL(ocp_unregister_driver);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -