static int pcmcia_device_probe(struct device * dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; int ret = 0; dev = get_device(dev); if (!dev) return -ENODEV; p_dev = to_pcmcia_dev(dev); p_drv = to_pcmcia_drv(dev->driver); if (!try_module_get(p_drv->owner)) { ret = -EINVAL; goto put_dev; } if (p_drv->attach) { p_dev->instance = p_drv->attach(); if ((!p_dev->instance) || (p_dev->client.state & CLIENT_UNBOUND)) { printk(KERN_NOTICE "ds: unable to create instance " "of '%s'!\n", p_drv->drv.name); ret = -EINVAL; } } if (ret) module_put(p_drv->owner); put_dev: if ((ret) || !(p_drv->attach)) put_device(dev); return (ret); }
static int softingcs_enable_irq(struct platform_device *pdev, int v) { struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent); dev_dbg(&pdev->dev, "pcmcia config [0] %02x\n", v ? 0x60 : 0); return pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0); }
static int pcmcia_device_remove(struct device * dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; int i; /* detach the "instance" */ p_dev = to_pcmcia_dev(dev); p_drv = to_pcmcia_drv(dev->driver); if (!p_drv) return 0; if (p_drv->remove) p_drv->remove(p_dev); /* check for proper unloading */ if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) printk(KERN_INFO "pcmcia: driver %s did not release config properly\n", p_drv->drv.name); for (i = 0; i < MAX_WIN; i++) if (p_dev->state & CLIENT_WIN_REQ(i)) printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n", p_drv->drv.name); /* references from pcmcia_probe_device */ p_dev->state = CLIENT_UNBOUND; pcmcia_put_dev(p_dev); module_put(p_drv->owner); return 0; }
/* * platformdata callbacks */ static int softingcs_reset(struct platform_device *pdev, int v) { struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent); dev_dbg(&pdev->dev, "pcmcia config [2] %02x\n", v ? 0 : 0x20); return pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20); }
static void pcmcia_release_dev(struct device *dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); ds_dbg(1, "releasing dev %p\n", p_dev); pcmcia_put_bus_socket(p_dev->socket->pcmcia); kfree(p_dev); }
struct pcmcia_device * pcmcia_get_dev(struct pcmcia_device *p_dev) { struct device *tmp_dev; tmp_dev = get_device(&p_dev->dev); if (!tmp_dev) return NULL; return to_pcmcia_dev(tmp_dev); }
static int pcmcia_requery(struct device *dev, void * _data) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); if (!p_dev->dev.driver) pcmcia_device_query(p_dev); return 0; }
static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); if (p_dev->dev.power.power_state.event != PM_EVENT_ON) return sprintf(buf, "off\n"); else return sprintf(buf, "on\n"); }
static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { struct pcmcia_device * p_dev = to_pcmcia_dev(dev); struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); /* matching by cardmgr */ if (p_dev->cardmgr == p_drv) return 1; return 0; }
static int pcmcia_bus_suspend_callback(struct device *dev, void * _data) { struct pcmcia_socket *skt = _data; struct pcmcia_device *p_dev = to_pcmcia_dev(dev); if (p_dev->socket != skt) return 0; return dpm_runtime_suspend(dev, PMSG_SUSPEND); }
static int pcmcia_bus_resume_callback(struct device *dev, void * _data) { struct pcmcia_socket *skt = _data; struct pcmcia_device *p_dev = to_pcmcia_dev(dev); if (p_dev->socket != skt) return 0; dpm_runtime_resume(dev); return 0; }
static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { struct pcmcia_device *p_dev; int i, length = 0; u32 hash[4] = { 0, 0, 0, 0}; if (!dev) return -ENODEV; p_dev = to_pcmcia_dev(dev); /* calculate hashes */ for (i=0; i<4; i++) { if (!p_dev->prod_id[i]) continue; hash[i] = crc32(0, p_dev->prod_id[i], strlen(p_dev->prod_id[i])); } i = 0; if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "SOCKET_NO=%u", p_dev->socket->sock)) return -ENOMEM; if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "DEVICE_NO=%02X", p_dev->device_no)) return -ENOMEM; if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" "pa%08Xpb%08Xpc%08Xpd%08X", p_dev->has_manf_id ? p_dev->manf_id : 0, p_dev->has_card_id ? p_dev->card_id : 0, p_dev->has_func_id ? p_dev->func_id : 0, p_dev->func, p_dev->device_no, hash[0], hash[1], hash[2], hash[3])) return -ENOMEM; envp[i] = NULL; return 0; }
static int pcmcia_dev_suspend(struct device * dev, pm_message_t state) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_driver *p_drv = NULL; if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); if (p_drv && p_drv->suspend) return p_drv->suspend(p_dev); return 0; }
static int pcmcia_dev_resume(struct device * dev) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_driver *p_drv = NULL; if (dev->driver) p_drv = to_pcmcia_drv(dev->driver); if (p_drv && p_drv->resume) return p_drv->resume(p_dev); return 0; }
static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); if (!count) return -EINVAL; down(&p_dev->socket->skt_sem); p_dev->allow_func_id_match = 1; up(&p_dev->socket->skt_sem); bus_rescan_devices(&pcmcia_bus_type); return count; }
static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) { struct pcmcia_device * p_dev = to_pcmcia_dev(dev); struct pcmcia_driver * p_drv = to_pcmcia_drv(drv); struct pcmcia_device_id *did = p_drv->id_table; /* matching by cardmgr */ if (p_dev->cardmgr == p_drv) return 1; while (did && did->match_flags) { if (pcmcia_devmatch(p_dev, did)) return 1; did++; } return 0; }
static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); int ret = 0; if (!count) return -EINVAL; if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) && (!strncmp(buf, "off", 3))) ret = dpm_runtime_suspend(dev, PMSG_SUSPEND); else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) && (!strncmp(buf, "on", 2))) dpm_runtime_resume(dev); return ret ? ret : count; }
static int send_event_callback(struct device *dev, void * _data) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct send_event_data *data = _data; /* we get called for all sockets, but may only pass the event * for drivers _on the affected socket_ */ if (p_dev->socket != data->skt) return 0; if (p_dev->client.state & (CLIENT_UNBOUND|CLIENT_STALE)) return 0; if (p_dev->client.EventMask & data->event) return EVENT(&p_dev->client, data->event, data->priority); return 0; }
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); int i; u32 hash[4] = { 0, 0, 0, 0}; /* calculate hashes */ for (i=0; i<4; i++) { if (!p_dev->prod_id[i]) continue; hash[i] = crc32(0,p_dev->prod_id[i],strlen(p_dev->prod_id[i])); } return sprintf(buf, "pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X" "pa%08Xpb%08Xpc%08Xpd%08X\n", p_dev->has_manf_id ? p_dev->manf_id : 0, p_dev->has_card_id ? p_dev->card_id : 0, p_dev->has_func_id ? p_dev->func_id : 0, p_dev->func, p_dev->device_no, hash[0], hash[1], hash[2], hash[3]); }
static int pcmcia_device_remove(struct device * dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; /* detach the "instance" */ p_dev = to_pcmcia_dev(dev); p_drv = to_pcmcia_drv(dev->driver); if (p_drv) { if ((p_drv->detach) && (p_dev->instance)) { p_drv->detach(p_dev->instance); /* from pcmcia_probe_device */ put_device(&p_dev->dev); } module_put(p_drv->owner); } return 0; }
/** * comedi_to_pcmcia_dev() - comedi_device pointer to pcmcia_device pointer. * @dev: comedi_device struct */ struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *dev) { return dev->hw_dev ? to_pcmcia_dev(dev->hw_dev) : NULL; }
static int pcmcia_device_probe(struct device * dev) { struct pcmcia_device *p_dev; struct pcmcia_driver *p_drv; struct pcmcia_device_id *did; struct pcmcia_socket *s; int ret = 0; dev = get_device(dev); if (!dev) return -ENODEV; p_dev = to_pcmcia_dev(dev); p_drv = to_pcmcia_drv(dev->driver); s = p_dev->socket; if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) { ret = -EINVAL; goto put_dev; } p_dev->state &= ~CLIENT_UNBOUND; /* set up the device configuration, if it hasn't been done before */ if (!s->functions) { cistpl_longlink_mfc_t mfc; if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, &mfc) == CS_SUCCESS) s->functions = mfc.nfn; else s->functions = 1; s->config = kzalloc(sizeof(config_t) * s->functions, GFP_KERNEL); if (!s->config) { ret = -ENOMEM; goto put_module; } } ret = p_drv->probe(p_dev); if (ret) goto put_module; /* handle pseudo multifunction devices: * there are at most two pseudo multifunction devices. * if we're matching against the first, schedule a * call which will then check whether there are two * pseudo devices, and if not, add the second one. */ did = (struct pcmcia_device_id *) p_dev->dev.driver_data; if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) && (p_dev->socket->device_count == 1) && (p_dev->device_no == 0)) pcmcia_add_pseudo_device(p_dev->socket); put_module: if (ret) module_put(p_drv->owner); put_dev: if (ret) put_device(dev); return (ret); }