static irqreturn_t me0600_isr(int irq, void *dev_id) { me0600_ext_irq_subdevice_t *instance; uint32_t status; uint32_t mask = PLX_INTCSR_PCI_INT_EN; irqreturn_t ret = IRQ_HANDLED; instance = (me0600_ext_irq_subdevice_t *) dev_id; if (irq != instance->irq) { PERROR("Incorrect interrupt num: %d.\n", irq); return IRQ_NONE; } PDEBUG("executed.\n"); if (instance->lintno > 1) { PERROR_CRITICAL ("%s():Wrong subdevice index=%d plx:irq_status_reg=0x%04X.\n", __func__, instance->lintno, inl(instance->intcsr)); return IRQ_NONE; } spin_lock(&instance->subdevice_lock); spin_lock(instance->intcsr_lock); status = inl(instance->intcsr); switch (instance->lintno) { case 0: mask |= PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_LOCAL_INT1_EN; break; case 1: mask |= PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_LOCAL_INT2_EN; break; } if ((status & mask) == mask) { instance->rised = 1; instance->n++; inb(instance->reset_reg); PDEBUG("Interrupt detected.\n"); } else { PINFO ("%ld Shared interrupt. %s(): idx=0 plx:irq_status_reg=0x%04X\n", jiffies, __func__, status); ret = IRQ_NONE; } spin_unlock(instance->intcsr_lock); spin_unlock(&instance->subdevice_lock); wake_up_interruptible_all(&instance->wait_queue); return ret; }
static void me_remove_pci(struct pci_dev* raw_dev) { me_device_t* device; struct pci_local_dev* dev; PDEBUG("executed.\n"); dev = kzalloc(sizeof(struct pci_local_dev), GFP_KERNEL); if (!dev) { PERROR_CRITICAL("Can't get memory for device's instance.\n"); return; } dev->dev = raw_dev; dev->vendor = raw_dev->vendor; dev->device = raw_dev->device; dev->serial_no = (raw_dev->subsystem_device << 16) | raw_dev->subsystem_vendor; PLOG("DISCONNECT: PCI VENDOR ID:0x%04x PCI DEVICE ID:0x%04x SERIAL NUMBER:0x%08x\n", dev->vendor, dev->device, dev->serial_no); device = find_device_on_list(dev, ME_PLUGGED_IN); if(device) { device->me_device_disconnect(device); // Mark as unplugged. device->bus.plugged = ME_PLUGGED_OUT; } else { PERROR("Device not found!\n"); } kfree(dev); }
static int mephisto_probe(struct usb_interface *interface, const struct usb_device_id *id) { int err = ME_ERRNO_SUCCESS; mephisto_usb_device_t* dev; /// The usb device. me_device_t* n_device = NULL; me_device_t* o_device = NULL; long unsigned int serial_no; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) char* tmp; #endif PDEBUG("executed.\n"); /// Allocate structures. dev = kzalloc(sizeof(mephisto_usb_device_t), GFP_KERNEL); if (!dev) { PERROR_CRITICAL("Can't get memory for device's instance.\n"); err = -ENOMEM; goto ERROR_0; } /// Initialize USB lock. dev->usb_semaphore = kzalloc(sizeof(struct semaphore), GFP_KERNEL); if (!dev->usb_semaphore) { PERROR_CRITICAL("Can't get memory for usb lock.\n"); err = -ENOMEM; goto ERROR_1; } #ifndef init_MUTEX sema_init(dev->usb_semaphore, 1); #else init_MUTEX(dev->usb_semaphore); #endif /// Initialize variables. dev->dev = usb_get_dev(interface_to_usbdev(interface)); if(!dev->dev) { PERROR("Error while request for usb device.\n"); err = -ENODEV; goto ERROR_2; } /// Initialize hardware usb_set_intfdata(interface, dev); /// Read serial number #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) tmp = (dev->dev->serial + strlen(dev->dev->serial)); serial_no = simple_strtoul(dev->dev->serial + 2, &tmp, 16); #else if (strict_strtoul(dev->dev->serial + 2, 16, &serial_no)) { serial_no = 0; } #endif dev->serial_no = serial_no; /// Hardware init mephisto_endpoints_reset(dev); /** Choice: a) New device connected. Add to device list. b) Old device reconected. Refresh device structure. */ o_device = find_device_on_list(dev, ME_PLUGGED_ANY); if(o_device) { PDEBUG("Old device.\n"); // Old device. if (o_device->bus.plugged == ME_PLUGGED_IN) { // Error device is already on list mark as active! PERROR("Device is already on list mark as active!\n"); o_device->me_device_disconnect(o_device); } } else { PDEBUG("New device.\n"); } PINFO("CALLING %s constructor\n", "mephisto_constr"); n_device = mephisto_constr(dev, o_device); if (!n_device) { PERROR("Executing '%s()' failed.\n", "mephisto_constr"); err = -ENODEV; goto ERROR_3; } else if (!o_device) { PINFO("Adding new entry to device list.\n"); insert_to_device_list(n_device); } if (n_device->me_device_postinit) { if (n_device->me_device_postinit(n_device, NULL)) { PERROR("Error while calling me_device_postinit().\n"); /// This error can be ignored. } else { PDEBUG("me_device_postinit() was sucessful.\n"); } } else { PERROR("me_device_postinit() not registred!\n"); } return 0; ERROR_3: usb_put_dev(interface_to_usbdev(interface)); ERROR_2: kfree(dev->usb_semaphore); ERROR_1: kfree(dev); ERROR_0: return err; }
me8254_subdevice_t* me8254_constr(uint16_t device_id, void* reg_base, unsigned int me8254_idx, unsigned int ctr_idx, me_lock_t* ctrl_reg_lock, me_lock_t* clk_src_reg_lock) { me8254_subdevice_t *subdevice; PDEBUG("executed.\n"); /** @todo Checkings should be removed. We can safetly assume that data passed from upper level are correct. */ // Check if counter index is out of range if (ctr_idx > 2) { PERROR("Counter index is out of range.\n"); return NULL; } // Check device specific values. switch (device_id) { case PCI_DEVICE_ID_MEILHAUS_ME140A: case PCI_DEVICE_ID_MEILHAUS_ME14EA: case PCI_DEVICE_ID_MEILHAUS_ME4610: case PCI_DEVICE_ID_MEILHAUS_ME4660: case PCI_DEVICE_ID_MEILHAUS_ME4660I: case PCI_DEVICE_ID_MEILHAUS_ME4660S: case PCI_DEVICE_ID_MEILHAUS_ME4660IS: case PCI_DEVICE_ID_MEILHAUS_ME4670: case PCI_DEVICE_ID_MEILHAUS_ME4670I: case PCI_DEVICE_ID_MEILHAUS_ME4670S: case PCI_DEVICE_ID_MEILHAUS_ME4670IS: case PCI_DEVICE_ID_MEILHAUS_ME4680: case PCI_DEVICE_ID_MEILHAUS_ME4680I: case PCI_DEVICE_ID_MEILHAUS_ME4680S: case PCI_DEVICE_ID_MEILHAUS_ME4680IS: case PCI_DEVICE_ID_MEILHAUS_ME4560: case PCI_DEVICE_ID_MEILHAUS_ME4560I: case PCI_DEVICE_ID_MEILHAUS_ME4560S: case PCI_DEVICE_ID_MEILHAUS_ME4560IS: case PCI_DEVICE_ID_MEILHAUS_ME4570: case PCI_DEVICE_ID_MEILHAUS_ME4570I: case PCI_DEVICE_ID_MEILHAUS_ME4570S: case PCI_DEVICE_ID_MEILHAUS_ME4570IS: case PCI_DEVICE_ID_MEILHAUS_ME4760: case PCI_DEVICE_ID_MEILHAUS_ME4760I: case PCI_DEVICE_ID_MEILHAUS_ME4760S: case PCI_DEVICE_ID_MEILHAUS_ME4760IS: case PCI_DEVICE_ID_MEILHAUS_ME4770: case PCI_DEVICE_ID_MEILHAUS_ME4770I: case PCI_DEVICE_ID_MEILHAUS_ME4770S: case PCI_DEVICE_ID_MEILHAUS_ME4770IS: case PCI_DEVICE_ID_MEILHAUS_ME4780: case PCI_DEVICE_ID_MEILHAUS_ME4780I: case PCI_DEVICE_ID_MEILHAUS_ME4780S: case PCI_DEVICE_ID_MEILHAUS_ME4780IS: case PCI_DEVICE_ID_MEILHAUS_ME4860: case PCI_DEVICE_ID_MEILHAUS_ME4860I: case PCI_DEVICE_ID_MEILHAUS_ME4860S: case PCI_DEVICE_ID_MEILHAUS_ME4860IS: case PCI_DEVICE_ID_MEILHAUS_ME4870: case PCI_DEVICE_ID_MEILHAUS_ME4870I: case PCI_DEVICE_ID_MEILHAUS_ME4870S: case PCI_DEVICE_ID_MEILHAUS_ME4870IS: case PCI_DEVICE_ID_MEILHAUS_ME4880: case PCI_DEVICE_ID_MEILHAUS_ME4880I: case PCI_DEVICE_ID_MEILHAUS_ME4880S: case PCI_DEVICE_ID_MEILHAUS_ME4880IS: case PCI_DEVICE_ID_MEILHAUS_ME0752: case PCI_DEVICE_ID_MEILHAUS_ME0754: case PCI_DEVICE_ID_MEILHAUS_ME0762: case PCI_DEVICE_ID_MEILHAUS_ME0764: case PCI_DEVICE_ID_MEILHAUS_ME0772: case PCI_DEVICE_ID_MEILHAUS_ME0774: case PCI_DEVICE_ID_MEILHAUS_ME0782: case PCI_DEVICE_ID_MEILHAUS_ME0784: case PCI_DEVICE_ID_MEILHAUS_ME8100_A: case PCI_DEVICE_ID_MEILHAUS_ME8100_B: if (me8254_idx > 0) { PERROR("8254 index is out of range. Must be 0.\n"); return NULL; } break; case PCI_DEVICE_ID_MEILHAUS_ME140B: case PCI_DEVICE_ID_MEILHAUS_ME14EB: if (me8254_idx > 1) { PERROR("8254 index is out of range. Must be 0 or 1.\n"); return NULL; } break; case PCI_DEVICE_ID_MEILHAUS_ME140C: if (me8254_idx > 4) { PERROR("8254 index is out of range. Must be between 0 and 3.\n"); return NULL; } case PCI_DEVICE_ID_MEILHAUS_ME140D: if (me8254_idx > 9) { PERROR("8254 index is out of range. Must be between 0 and 8.\n"); return NULL; } break; default: PERROR_CRITICAL("8254 registred for %x!\n", device_id); return NULL; } // Allocate memory for subdevice instance subdevice = kzalloc(sizeof(me8254_subdevice_t), GFP_KERNEL); if (!subdevice) { PERROR("Cannot get memory for 8254 instance.\n"); return NULL; } // Initialize subdevice base class if (me_subdevice_init(&subdevice->base)) { PERROR("Cannot initialize subdevice base class instance.\n"); kfree(subdevice); return NULL; } // Initialize spin locks. subdevice->ctrl_reg_lock = ctrl_reg_lock; subdevice->clk_src_reg_lock = clk_src_reg_lock; // Save type of Meilhaus device subdevice->device_id = device_id; // Save the subdevice indexes. subdevice->me8254_idx = me8254_idx; subdevice->ctr_idx = ctr_idx; subdevice->base.idx = ctr_idx + (me8254_idx * 3); /** @todo Setting flags for particular implementations create portibility problem. Flags should be passed from upper level. Also registers should be some how provided by upper level call. */ // Do device specific initialization switch (device_id) { case PCI_DEVICE_ID_MEILHAUS_ME140A: case PCI_DEVICE_ID_MEILHAUS_ME14EA: case PCI_DEVICE_ID_MEILHAUS_ME140B: case PCI_DEVICE_ID_MEILHAUS_ME14EB: // Initialize the counters capabilities subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL; if (ctr_idx == 0) subdevice->caps |= ME_CAPS_CTR_CLK_INTERNAL_1MHZ | ME_CAPS_CTR_CLK_INTERNAL_10MHZ; else subdevice->caps |= ME_CAPS_CTR_CLK_PREVIOUS; // Get the counters registers subdevice->val_reg = me1400AB_get_val_reg(reg_base, me8254_idx, ctr_idx); subdevice->ctrl_reg = me1400AB_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); subdevice->clk_src_reg = me1400AB_get_clk_src_reg(reg_base, me8254_idx, ctr_idx); break; case PCI_DEVICE_ID_MEILHAUS_ME140C: case PCI_DEVICE_ID_MEILHAUS_ME140D: // Initialize the counters capabilities subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL | ME_CAPS_CTR_CLK_PREVIOUS; if (ctr_idx == 0) { subdevice->caps |= ME_CAPS_CTR_CLK_INTERNAL_1MHZ | ME_CAPS_CTR_CLK_INTERNAL_10MHZ; if ((me8254_idx == 0) || (me8254_idx == 5)) {// No cascading for first counter on first chips. subdevice->caps &= ~ME_CAPS_CTR_CLK_PREVIOUS; } } // Get the counters registers subdevice->val_reg = me1400CD_get_val_reg(reg_base, me8254_idx, ctr_idx); subdevice->ctrl_reg = me1400CD_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); subdevice->clk_src_reg = me1400CD_get_clk_src_reg(reg_base, me8254_idx, ctr_idx); break; case PCI_DEVICE_ID_MEILHAUS_ME4610: case PCI_DEVICE_ID_MEILHAUS_ME4660: case PCI_DEVICE_ID_MEILHAUS_ME4660I: case PCI_DEVICE_ID_MEILHAUS_ME4660S: case PCI_DEVICE_ID_MEILHAUS_ME4660IS: case PCI_DEVICE_ID_MEILHAUS_ME4670: case PCI_DEVICE_ID_MEILHAUS_ME4670I: case PCI_DEVICE_ID_MEILHAUS_ME4670S: case PCI_DEVICE_ID_MEILHAUS_ME4670IS: case PCI_DEVICE_ID_MEILHAUS_ME4680: case PCI_DEVICE_ID_MEILHAUS_ME4680I: case PCI_DEVICE_ID_MEILHAUS_ME4680S: case PCI_DEVICE_ID_MEILHAUS_ME4680IS: case PCI_DEVICE_ID_MEILHAUS_ME4560: case PCI_DEVICE_ID_MEILHAUS_ME4560I: case PCI_DEVICE_ID_MEILHAUS_ME4560S: case PCI_DEVICE_ID_MEILHAUS_ME4560IS: case PCI_DEVICE_ID_MEILHAUS_ME4570: case PCI_DEVICE_ID_MEILHAUS_ME4570I: case PCI_DEVICE_ID_MEILHAUS_ME4570S: case PCI_DEVICE_ID_MEILHAUS_ME4570IS: case PCI_DEVICE_ID_MEILHAUS_ME4760: case PCI_DEVICE_ID_MEILHAUS_ME4760I: case PCI_DEVICE_ID_MEILHAUS_ME4760S: case PCI_DEVICE_ID_MEILHAUS_ME4760IS: case PCI_DEVICE_ID_MEILHAUS_ME4770: case PCI_DEVICE_ID_MEILHAUS_ME4770I: case PCI_DEVICE_ID_MEILHAUS_ME4770S: case PCI_DEVICE_ID_MEILHAUS_ME4770IS: case PCI_DEVICE_ID_MEILHAUS_ME4780: case PCI_DEVICE_ID_MEILHAUS_ME4780I: case PCI_DEVICE_ID_MEILHAUS_ME4780S: case PCI_DEVICE_ID_MEILHAUS_ME4780IS: case PCI_DEVICE_ID_MEILHAUS_ME4860: case PCI_DEVICE_ID_MEILHAUS_ME4860I: case PCI_DEVICE_ID_MEILHAUS_ME4860S: case PCI_DEVICE_ID_MEILHAUS_ME4860IS: case PCI_DEVICE_ID_MEILHAUS_ME4870: case PCI_DEVICE_ID_MEILHAUS_ME4870I: case PCI_DEVICE_ID_MEILHAUS_ME4870S: case PCI_DEVICE_ID_MEILHAUS_ME4870IS: case PCI_DEVICE_ID_MEILHAUS_ME4880: case PCI_DEVICE_ID_MEILHAUS_ME4880I: case PCI_DEVICE_ID_MEILHAUS_ME4880S: case PCI_DEVICE_ID_MEILHAUS_ME4880IS: case PCI_DEVICE_ID_MEILHAUS_ME0752: case PCI_DEVICE_ID_MEILHAUS_ME0754: case PCI_DEVICE_ID_MEILHAUS_ME0762: case PCI_DEVICE_ID_MEILHAUS_ME0764: case PCI_DEVICE_ID_MEILHAUS_ME0772: case PCI_DEVICE_ID_MEILHAUS_ME0774: case PCI_DEVICE_ID_MEILHAUS_ME0782: case PCI_DEVICE_ID_MEILHAUS_ME0784: // Initialize the counters capabilities subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL; // Get the counters registers subdevice->val_reg = me4600_get_val_reg(reg_base, me8254_idx, ctr_idx); subdevice->ctrl_reg = me4600_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); subdevice->clk_src_reg = 0; // Not used break; case PCI_DEVICE_ID_MEILHAUS_ME8100_A: case PCI_DEVICE_ID_MEILHAUS_ME8100_B: // Initialize the counters capabilities subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL; // Get the counters registers subdevice->val_reg = me8100_get_val_reg(reg_base, me8254_idx, ctr_idx); subdevice->ctrl_reg = me8100_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); subdevice->clk_src_reg = 0; // Not used break; default: PERROR("Unknown device type.\n"); me_subdevice_deinit(&subdevice->base); kfree(subdevice); return NULL; } // Overload subdevice base class methods. subdevice->base.me_subdevice_io_reset_subdevice = me8254_io_reset_subdevice; subdevice->base.me_subdevice_io_single_config = me8254_io_single_config; subdevice->base.me_subdevice_io_single_read = me8254_io_single_read; subdevice->base.me_subdevice_io_single_write = me8254_io_single_write; subdevice->base.me_subdevice_query_number_channels = me8254_query_number_channels; subdevice->base.me_subdevice_query_subdevice_type = me8254_query_subdevice_type; subdevice->base.me_subdevice_query_subdevice_caps = me8254_query_subdevice_caps; subdevice->base.me_subdevice_query_subdevice_caps_args = me8254_query_subdevice_caps_args; return subdevice; }
int me8254_io_single_config(struct me_subdevice* subdevice, struct file* filep, int channel, int single_config, int ref, int trig_chain, int trig_type, int trig_edge, int flags) { me8254_subdevice_t* instance; uint8_t ctrl = ME8254_CTRL_LM | ME8254_CTRL_BIN; int err; instance = (me8254_subdevice_t *) subdevice; PDEBUG("executed.\n"); if (flags) { PERROR("Invalid flags. Should be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n"); return ME_ERRNO_INVALID_FLAGS; } if (trig_edge) { PERROR("Invalid trigger edge. Must be ME_TRIG_EDGE_NONE.\n"); return ME_ERRNO_INVALID_TRIG_EDGE; } switch (trig_type) { case ME_TRIG_TYPE_NONE: if (trig_chain != ME_TRIG_CHAN_NONE) { PERROR("Invalid trigger chain specified. Must be ME_TRIG_CHAN_NONE.\n"); return ME_ERRNO_INVALID_TRIG_CHAN; } break; case ME_TRIG_TYPE_SW: if (trig_chain != ME_TRIG_CHAN_DEFAULT) { PERROR("Invalid trigger chain specified. Must be ME_TRIG_CHAN_DEFAULT.\n"); return ME_ERRNO_INVALID_TRIG_CHAN; } break; default: PERROR("Invalid trigger type.\n"); return ME_ERRNO_INVALID_TRIG_TYPE; } switch (single_config) { case ME_SINGLE_CONFIG_CTR_8254_MODE_DISABLE: return me8254_io_reset_subdevice(subdevice, filep, flags); break; case ME_SINGLE_CONFIG_CTR_8254_MODE_INTERRUPT_ON_TERMINAL_COUNT: case ME_SINGLE_CONFIG_CTR_8254_MODE_ONE_SHOT: case ME_SINGLE_CONFIG_CTR_8254_MODE_RATE_GENERATOR: case ME_SINGLE_CONFIG_CTR_8254_MODE_SQUARE_WAVE: case ME_SINGLE_CONFIG_CTR_8254_MODE_SOFTWARE_TRIGGER: case ME_SINGLE_CONFIG_CTR_8254_MODE_HARDWARE_TRIGGER: break; default: PERROR("Invalid single configuration.\n"); return ME_ERRNO_INVALID_SINGLE_CONFIG; } if (channel) { PERROR("Invalid channel number. Must be 0.\n"); return ME_ERRNO_INVALID_CHANNEL; } ME_SUBDEVICE_ENTER; ME_SUBDEVICE_LOCK; // Configure the counter modes switch (instance->ctr_idx) { case 0: ctrl |= ME8254_CTRL_SC0; break; case 1: ctrl |= ME8254_CTRL_SC1; break; default: ctrl |= ME8254_CTRL_SC2; } switch (single_config) { case ME_SINGLE_CONFIG_CTR_8254_MODE_INTERRUPT_ON_TERMINAL_COUNT: ctrl |= ME8254_CTRL_M0; break; case ME_SINGLE_CONFIG_CTR_8254_MODE_ONE_SHOT: ctrl |= ME8254_CTRL_M1; break; case ME_SINGLE_CONFIG_CTR_8254_MODE_RATE_GENERATOR: ctrl |= ME8254_CTRL_M2; break; case ME_SINGLE_CONFIG_CTR_8254_MODE_SQUARE_WAVE: ctrl |= ME8254_CTRL_M3; break; case ME_SINGLE_CONFIG_CTR_8254_MODE_SOFTWARE_TRIGGER: ctrl |= ME8254_CTRL_M4; break; case ME_SINGLE_CONFIG_CTR_8254_MODE_HARDWARE_TRIGGER: ctrl |= ME8254_CTRL_M5; break; } me_writeb(instance->base.dev, ctrl, instance->ctrl_reg); /** @todo Instead of ID related calls features flags should be used. */ switch (instance->device_id) { case PCI_DEVICE_ID_MEILHAUS_ME1400: case PCI_DEVICE_ID_MEILHAUS_ME14E0: case PCI_DEVICE_ID_MEILHAUS_ME140A: case PCI_DEVICE_ID_MEILHAUS_ME14EA: case PCI_DEVICE_ID_MEILHAUS_ME140B: case PCI_DEVICE_ID_MEILHAUS_ME14EB: err = me1400_ab_ref_config(instance, ref); break; case PCI_DEVICE_ID_MEILHAUS_ME140C: case PCI_DEVICE_ID_MEILHAUS_ME140D: err = me1400_cd_ref_config(instance, ref); break; case PCI_DEVICE_ID_MEILHAUS_ME4610: case PCI_DEVICE_ID_MEILHAUS_ME4660: case PCI_DEVICE_ID_MEILHAUS_ME4660I: case PCI_DEVICE_ID_MEILHAUS_ME4660S: case PCI_DEVICE_ID_MEILHAUS_ME4660IS: case PCI_DEVICE_ID_MEILHAUS_ME4670: case PCI_DEVICE_ID_MEILHAUS_ME4670I: case PCI_DEVICE_ID_MEILHAUS_ME4670S: case PCI_DEVICE_ID_MEILHAUS_ME4670IS: case PCI_DEVICE_ID_MEILHAUS_ME4680: case PCI_DEVICE_ID_MEILHAUS_ME4680I: case PCI_DEVICE_ID_MEILHAUS_ME4680S: case PCI_DEVICE_ID_MEILHAUS_ME4680IS: case PCI_DEVICE_ID_MEILHAUS_ME8100_A: case PCI_DEVICE_ID_MEILHAUS_ME8100_B: err = me_ref_config(instance, ref); break; default: PERROR_CRITICAL("Invalid device type. 8254 registred for %x.\n", instance->device_id); err = ME_ERRNO_INVALID_SINGLE_CONFIG; } ME_SUBDEVICE_UNLOCK; ME_SUBDEVICE_EXIT; return err; }
static int me_probe_pci(struct pci_dev* raw_dev, const struct pci_device_id* id) { int err = ME_ERRNO_SUCCESS; struct pci_local_dev* dev; me_constr_t constructor = NULL; me_device_t* n_device = NULL; me_device_t* o_device = NULL; char constructor_name[20]="me0000_pci_constr\0"; char module_name[16]="me0000PCI\0"; PDEBUG("executed.\n"); /// Allocate structures. dev = kzalloc(sizeof(struct pci_local_dev), GFP_KERNEL); if (!dev) { PERROR("Can't get memory for device's instance."); err = -ENOMEM; goto ERROR; } /// Check this board if (me_pci_board_check(dev, raw_dev)) { PERROR("NOT SUPPORTED! This is not Meilhaus board.\n"); err = -ENODEV; goto ERROR; } constructor_name[2] += (char)((dev->device >> 12) & 0x000F); constructor_name[3] += (char)((dev->device >> 8) & 0x000F); PDEBUG("constructor_name: %s\n", constructor_name); module_name[2] += (char)((dev->device >> 12) & 0x000F); module_name[3] += (char)((dev->device >> 8) & 0x000F); if (module_name[2] == '6') {// Exceptions: me61xx, me62xx, me63xx are handled by one driver. module_name[3] = '0'; } if (module_name[2] == '4') { if (module_name[3] == '8') {// Exceptions: me46xx and me48xx are handled by one driver. module_name[3] = '6'; } else if (module_name[3] == '5') {// Exceptions: me45xx and me47xx are handled by one driver. module_name[3] = '7'; } } PDEBUG("module_name: %s\n", module_name); /** Choice: a) New device connected. Add to device list. b) Old device reconected. Refresh device structure. */ o_device = find_device_on_list(dev, ME_PLUGGED_ANY); if(o_device) { PDEBUG("Device already registred.\n"); // Old device. if (o_device->bus.plugged == ME_PLUGGED_IN) { // Error device is already on list mark as active! PERROR("Device is already on list mark as active!\n"); o_device->me_device_disconnect(o_device); } } else { PDEBUG("New device.\n"); } constructor = (me_constr_t) __symbol_get(constructor_name); if (!constructor) { PDEBUG("request_module: '%s'.\n", module_name); if (!request_module("%s", module_name)) { constructor = (me_constr_t) __symbol_get(constructor_name); if (!constructor) { if(o_device) { PERROR_CRITICAL("Module loaded. Failed to get %s driver module constructor!\n", module_name); } else { PERROR("Can't get %s driver module constructor.\n", module_name); } err = -ENODEV; goto ERROR; } } else { PERROR("Can't get requested module: %s.\n", module_name); err = -ENODEV; goto ERROR; } } n_device = (*constructor)(dev, o_device); if (!n_device) { PERROR("Executing '%s()' failed.\n", constructor_name); __symbol_put(constructor_name); err = -ENODEV; goto ERROR; } else if (!o_device) { insert_to_device_list(n_device); } if (n_device->me_device_postinit) { if (n_device->me_device_postinit(n_device, NULL)) { PERROR("Error while calling me_device_postinit().\n"); /// This error can be ignored. } else { PDEBUG("me_device_postinit() was sucessful.\n"); } } else { PERROR("me_device_postinit() not registred!\n"); } ERROR: if (dev) kfree(dev); dev = NULL; return err; }