Example #1
0
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;
}
Example #2
0
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);
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}