Esempio n. 1
0
static int me8200_do_io_single_write(me_subdevice_t * subdevice,
				     struct file *filep,
				     int channel,
				     int value, int time_out, int flags)
{
	me8200_do_subdevice_t *instance;
	int err = ME_ERRNO_SUCCESS;
	uint8_t state;
	unsigned long status;

	PDEBUG("executed.\n");

	instance = (me8200_do_subdevice_t *) subdevice;

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, status);
	switch (flags) {
	case ME_IO_SINGLE_TYPE_DIO_BIT:
		if ((channel >= 0) && (channel < 8)) {
			state = inb(instance->port_reg);
			state =
			    value ? (state | (0x1 << channel)) : (state &
								  ~(0x1 <<
								    channel));
			outb(state, instance->port_reg);
			PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n",
				   instance->reg_base,
				   instance->port_reg - instance->reg_base,
				   state);
		} else {
			PERROR("Invalid bit number specified.\n");
			err = ME_ERRNO_INVALID_CHANNEL;
		}
		break;

	case ME_IO_SINGLE_NO_FLAGS:
	case ME_IO_SINGLE_TYPE_DIO_BYTE:
		if (channel == 0) {
			outb(value, instance->port_reg);
			PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n",
				   instance->reg_base,
				   instance->port_reg - instance->reg_base,
				   value);
		} else {
			PERROR("Invalid byte number specified.\n");
			err = ME_ERRNO_INVALID_CHANNEL;
		}
		break;

	default:
		PERROR("Invalid flags specified.\n");
		err = ME_ERRNO_INVALID_FLAGS;
	}
	spin_unlock_irqrestore(&instance->subdevice_lock, status);

	ME_SUBDEVICE_EXIT;

	return err;
}
static int me6000_dio_io_reset_subdevice(struct me_subdevice *subdevice,
					 struct file *filep, int flags)
{
	me6000_dio_subdevice_t *instance;
	uint8_t mode;

	PDEBUG("executed.\n");

	instance = (me6000_dio_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock(&instance->subdevice_lock);
	spin_lock(instance->ctrl_reg_lock);
	mode = inb(instance->ctrl_reg);
	mode &= ~(0x3 << (instance->dio_idx * 2));
	outb(mode, instance->ctrl_reg);
	PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->ctrl_reg - instance->reg_base, mode);
	spin_unlock(instance->ctrl_reg_lock);

	outb(0x00, instance->port_reg);
	PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->ctrl_reg - instance->reg_base, 0x00);
	spin_unlock(&instance->subdevice_lock);

	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}
static int me0600_relay_io_reset_subdevice(struct me_subdevice *subdevice,
					   struct file *filep, int flags)
{
	me0600_relay_subdevice_t *instance;

	PDEBUG("executed.\n");

	instance = (me0600_relay_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock(&instance->subdevice_lock);
	outb(0x0, instance->port_0_reg);
	PDEBUG_REG("port_0_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->port_0_reg - instance->reg_base, 0);
	outb(0x0, instance->port_1_reg);
	PDEBUG_REG("port_1_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->port_1_reg - instance->reg_base, 0);
	spin_unlock(&instance->subdevice_lock);

	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}
static int me1400_ext_irq_io_irq_stop(struct me_subdevice *subdevice,
				      struct file *filep,
				      int channel, int flags)
{
	me1400_ext_irq_subdevice_t *instance;
	unsigned long cpu_flags;
	uint8_t tmp;
	int err = ME_ERRNO_SUCCESS;

	PDEBUG("executed.\n");

	instance = (me1400_ext_irq_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	if (channel) {
		PERROR("Invalid channel.\n");
		return ME_ERRNO_INVALID_CHANNEL;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
	spin_lock(instance->clk_src_reg_lock);
//                      // Disable IRQ on PLX
//                      tmp = inb(instance->plx_intcs_reg) & ( ~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN));
//                      outb(tmp, instance->plx_intcs_reg);
//                      PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp);

	switch (instance->device_id) {
	case PCI_DEVICE_ID_MEILHAUS_ME140C:
	case PCI_DEVICE_ID_MEILHAUS_ME140D:
		tmp = inb(instance->ctrl_reg);
		tmp &= ~ME1400CD_EXT_IRQ_CLK_EN;
		outb(tmp, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base, tmp);

		break;

	default:
		outb(0x00, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base, 0x00);
		break;
	}
	spin_unlock(instance->clk_src_reg_lock);
	instance->rised = -1;
	spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
	wake_up_interruptible_all(&instance->wait_queue);

	ME_SUBDEVICE_EXIT;

	return err;
}
Esempio n. 5
0
static int me8100_do_io_reset_subdevice(struct me_subdevice *subdevice,
					struct file *filep, int flags)
{
	me8100_do_subdevice_t *instance;
	uint16_t ctrl;

	PDEBUG("executed.\n");

	instance = (me8100_do_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock(&instance->subdevice_lock);
	spin_lock(instance->ctrl_reg_lock);
	ctrl = inw(instance->ctrl_reg);
	ctrl &= ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0;
	outw(ctrl, instance->ctrl_reg);
	PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->ctrl_reg - instance->reg_base, ctrl);
	spin_unlock(instance->ctrl_reg_lock);
	outw(0, instance->port_reg);
	instance->port_reg_mirror = 0;
	PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->port_reg - instance->reg_base, 0);
	spin_unlock(&instance->subdevice_lock);

	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}
static int me1000_dio_io_reset_subdevice(struct me_subdevice *subdevice,
					 struct file *filep, int flags)
{
	me1000_dio_subdevice_t *instance;
	uint32_t tmp;

	PDEBUG("executed.\n");

	instance = (me1000_dio_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock(&instance->subdevice_lock);
	spin_lock(instance->ctrl_reg_lock);
	tmp = inl(instance->ctrl_reg);
	tmp &= ~(0x1 << instance->dio_idx);
	outl(tmp, instance->ctrl_reg);
	PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->ctrl_reg - instance->reg_base, tmp);
	spin_unlock(instance->ctrl_reg_lock);

	outl(0x00000000, instance->port_reg);
	PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->ctrl_reg - instance->reg_base, 0);
	spin_unlock(&instance->subdevice_lock);

	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}
Esempio n. 7
0
static int me8100_di_io_reset_subdevice(struct me_subdevice *subdevice,
					struct file *filep, int flags)
{
	me8100_di_subdevice_t *instance;
	unsigned short ctrl;
	unsigned long cpu_flags;

	PDEBUG("executed.\n");

	instance = (me8100_di_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
	spin_lock(instance->ctrl_reg_lock);
	ctrl = inw(instance->ctrl_reg);
	ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0);
	outw(ctrl, instance->ctrl_reg);
	PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->ctrl_reg - instance->reg_base, ctrl);
	spin_unlock(instance->ctrl_reg_lock);

	outw(0, instance->mask_reg);
	PDEBUG_REG("mask_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->mask_reg - instance->reg_base, 0);
	outw(0, instance->pattern_reg);
	PDEBUG_REG("pattern_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->pattern_reg - instance->reg_base, 0);
	instance->rised = -1;
	instance->irq_count = 0;
	instance->filtering_flag = 0;
	spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);

	outl(PLX_INTCSR_LOCAL_INT1_EN |
	     PLX_INTCSR_LOCAL_INT1_POL |
	     PLX_INTCSR_LOCAL_INT2_EN |
	     PLX_INTCSR_LOCAL_INT2_POL |
	     PLX_INTCSR_PCI_INT_EN, instance->irq_status_reg);
	PDEBUG_REG("plx:irq_status_reg outl(0x%lX)=0x%x\n",
		   instance->irq_status_reg,
		   PLX_INTCSR_LOCAL_INT1_EN | PLX_INTCSR_LOCAL_INT1_POL |
		   PLX_INTCSR_LOCAL_INT2_EN | PLX_INTCSR_LOCAL_INT2_POL |
		   PLX_INTCSR_PCI_INT_EN);

	wake_up_interruptible_all(&instance->wait_queue);
	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}
static int me8200_di_io_irq_stop(me_subdevice_t * subdevice,
				 struct file *filep, int channel, int flags)
{
	me8200_di_subdevice_t *instance;
	uint8_t tmp;
	unsigned long status;

	PDEBUG("executed.\n");

	instance = (me8200_di_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	if (channel) {
		PERROR("Invalid channel specified.\n");
		return ME_ERRNO_INVALID_CHANNEL;
	}

	ME_SUBDEVICE_ENTER spin_lock_irqsave(&instance->subdevice_lock, status);
	spin_lock(instance->irq_ctrl_lock);
	tmp = inb(instance->irq_ctrl_reg);
	tmp |=
	    (ME8200_DI_IRQ_CTRL_BIT_ENABLE <<
	     (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
	outb(tmp, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, tmp);
	tmp &=
	    ~(ME8200_DI_IRQ_CTRL_BIT_ENABLE <<
	      (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
	tmp |=
	    (ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
	     (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
//                      tmp &= ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
	outb(tmp, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, tmp);
	spin_unlock(instance->irq_ctrl_lock);

	instance->rised = -1;
	instance->status_value = 0;
	instance->status_value_edges = 0;
	instance->filtering_flag = 0;
	spin_unlock_irqrestore(&instance->subdevice_lock, status);
	wake_up_interruptible_all(&instance->wait_queue);

	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}
Esempio n. 9
0
static irqreturn_t me8200_do_isr(int irq, void *dev_id, struct pt_regs *regs)
#endif
{
	me8200_do_subdevice_t *instance;
	uint16_t ctrl;
	uint8_t irq_status;

	instance = (me8200_do_subdevice_t *) dev_id;

	if (irq != instance->irq) {
		PERROR("Incorrect interrupt num: %d.\n", irq);
		return IRQ_NONE;
	}

	irq_status = inb(instance->irq_status_reg);
	if (!
	    (irq_status &
	     (ME8200_DO_IRQ_STATUS_BIT_ACTIVE << instance->do_idx))) {
		PINFO
		    ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n",
		     jiffies, __func__, instance->do_idx, irq_status);
		return IRQ_NONE;
	}

	PDEBUG("executed.\n");

	spin_lock(&instance->subdevice_lock);
	instance->rised = 1;
	instance->count++;

	spin_lock(instance->irq_mode_lock);
	ctrl = inw(instance->irq_ctrl_reg);
	ctrl |= ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx;
	outw(ctrl, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, ctrl);
	ctrl &= ~(ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx);
	outw(ctrl, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, ctrl);
	spin_unlock(instance->irq_mode_lock);
	spin_unlock(&instance->subdevice_lock);
	wake_up_interruptible_all(&instance->wait_queue);

	return IRQ_HANDLED;
}
Esempio n. 10
0
static int me8200_do_io_reset_subdevice(struct me_subdevice *subdevice,
					struct file *filep, int flags)
{
	me8200_do_subdevice_t *instance;
	unsigned long cpu_flags;
	uint8_t tmp;

	PDEBUG("executed.\n");

	instance = (me8200_do_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
	outb(0x00, instance->port_reg);
	PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->port_reg - instance->reg_base, 0x00);
	spin_lock(instance->irq_mode_lock);
	tmp = inb(instance->irq_ctrl_reg);
	tmp &=
	    ~(ME8200_IRQ_MODE_BIT_ENABLE_POWER <<
	      (ME8200_IRQ_MODE_POWER_SHIFT * instance->do_idx));
	outb(tmp, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, tmp);
	spin_unlock(instance->irq_mode_lock);
	instance->rised = -1;
	instance->count = 0;
	spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
	wake_up_interruptible_all(&instance->wait_queue);

	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}
Esempio n. 11
0
static int me0600_ext_irq_io_irq_stop(struct me_subdevice *subdevice,
				      struct file *filep,
				      int channel, int flags)
{
	me0600_ext_irq_subdevice_t *instance;
	int err = ME_ERRNO_SUCCESS;
	uint32_t tmp;
	unsigned long cpu_flags;

	PDEBUG("executed.\n");

	instance = (me0600_ext_irq_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	if (instance->lintno > 1) {
		PERROR("Wrong idx=%d.\n", instance->lintno);
		return ME_ERRNO_INVALID_SUBDEVICE;
	}

	if (channel) {
		PERROR("Invalid channel specified.\n");
		return ME_ERRNO_INVALID_CHANNEL;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
	spin_lock(instance->intcsr_lock);
	tmp = inl(instance->intcsr);
	switch (instance->lintno) {
	case 0:
		tmp &= ~PLX_INTCSR_LOCAL_INT1_EN;
		break;
	case 1:
		tmp &= ~PLX_INTCSR_LOCAL_INT2_EN;
		break;
	}
	outl(tmp, instance->intcsr);
	PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp);
	spin_unlock(instance->intcsr_lock);
	instance->rised = -1;
	spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
	wake_up_interruptible_all(&instance->wait_queue);

	ME_SUBDEVICE_EXIT;

	return err;
}
Esempio n. 12
0
static int me8200_do_io_irq_start(me_subdevice_t * subdevice,
				  struct file *filep,
				  int channel,
				  int irq_source,
				  int irq_edge, int irq_arg, int flags)
{
	me8200_do_subdevice_t *instance;
	int err = ME_ERRNO_SUCCESS;
	uint8_t tmp;
	unsigned long status;

	if (flags & ~ME_IO_IRQ_START_DIO_BYTE) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	if (channel != 0) {
		PERROR("Invalid channel specified.\n");
		return ME_ERRNO_INVALID_CHANNEL;
	}

	if (irq_source != ME_IRQ_SOURCE_DIO_OVER_TEMP) {
		PERROR("Invalid interrupt source specified.\n");
		return ME_ERRNO_INVALID_IRQ_SOURCE;
	}

	PDEBUG("executed.\n");

	instance = (me8200_do_subdevice_t *) subdevice;

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, status);
	spin_lock(instance->irq_mode_lock);
	tmp = inb(instance->irq_ctrl_reg);
	tmp |=
	    ME8200_IRQ_MODE_BIT_ENABLE_POWER << (ME8200_IRQ_MODE_POWER_SHIFT *
						 instance->do_idx);
	outb(tmp, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, tmp);
	spin_unlock(instance->irq_mode_lock);
	instance->rised = 0;
	spin_unlock_irqrestore(&instance->subdevice_lock, status);

	ME_SUBDEVICE_EXIT;

	return err;
}
Esempio n. 13
0
static int me8100_di_io_irq_stop(me_subdevice_t *subdevice,
				 struct file *filep, int channel, int flags)
{
	me8100_di_subdevice_t *instance;
	uint16_t ctrl;
	unsigned long cpu_flags;

	PDEBUG("executed.\n");

	instance = (me8100_di_subdevice_t *) subdevice;

	if (flags) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	if (channel) {
		PERROR("Invalid channel specified.\n");
		return ME_ERRNO_INVALID_CHANNEL;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
	spin_lock(instance->ctrl_reg_lock);
	ctrl = inw(instance->ctrl_reg);
	ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0);
	outw(ctrl, instance->ctrl_reg);
	PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->ctrl_reg - instance->reg_base, ctrl);
	spin_unlock(instance->ctrl_reg_lock);
	instance->rised = -1;
	instance->status_value = 0;
	instance->status_value_edges = 0;
	instance->filtering_flag = 0;
	spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
	wake_up_interruptible_all(&instance->wait_queue);

	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}
static void me1400_ext_irq_destructor(struct me_subdevice *subdevice)
{
	me1400_ext_irq_subdevice_t *instance;
	uint8_t tmp;

	PDEBUG("executed.\n");

	instance = (me1400_ext_irq_subdevice_t *) subdevice;

	// Disable IRQ on PLX
	tmp =
	    inb(instance->
		plx_intcs_reg) & (~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL |
				    PLX_PCI_INT_EN));
	outb(tmp, instance->plx_intcs_reg);
	PDEBUG_REG("ctrl_reg outb(plx:0x%lX)=0x%x\n", instance->plx_intcs_reg,
		   tmp);

	free_irq(instance->irq, (void *)instance);
	me_subdevice_deinit(&instance->base);
	kfree(instance);
}
Esempio n. 15
0
static int me8100_do_io_single_config(me_subdevice_t * subdevice,
				      struct file *filep,
				      int channel,
				      int single_config,
				      int ref,
				      int trig_chan,
				      int trig_type, int trig_edge, int flags)
{
	me8100_do_subdevice_t *instance;
	int err = ME_ERRNO_SUCCESS;
	int config;

	PDEBUG("executed.\n");

	instance = (me8100_do_subdevice_t *) subdevice;

	ME_SUBDEVICE_ENTER;

	spin_lock(&instance->subdevice_lock);
	spin_lock(instance->ctrl_reg_lock);
	config = inw(instance->ctrl_reg);
	switch (flags) {
	case ME_IO_SINGLE_CONFIG_NO_FLAGS:
	case ME_IO_SINGLE_CONFIG_DIO_WORD:
		if (channel == 0) {
			if (single_config ==
			    ME_SINGLE_CONFIG_DIO_HIGH_IMPEDANCE) {
				config &= ~(ME8100_DIO_CTRL_BIT_ENABLE_DIO);
			} else if (single_config == ME_SINGLE_CONFIG_DIO_SINK) {
				config |= ME8100_DIO_CTRL_BIT_ENABLE_DIO;
				config &= ~ME8100_DIO_CTRL_BIT_SOURCE;
			} else if (single_config == ME_SINGLE_CONFIG_DIO_SOURCE) {
				config |=
				    ME8100_DIO_CTRL_BIT_ENABLE_DIO |
				    ME8100_DIO_CTRL_BIT_SOURCE;
			} else {
				PERROR
				    ("Invalid port configuration specified.\n");
				err = ME_ERRNO_INVALID_SINGLE_CONFIG;
			}
		} else {
			PERROR("Invalid word number specified.\n");
			err = ME_ERRNO_INVALID_CHANNEL;
		}
		break;

	default:
		PERROR("Invalid flags specified.\n");
		err = ME_ERRNO_INVALID_FLAGS;
	}

	if (!err) {
		outw(config, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base, config);
	}

	spin_unlock(instance->ctrl_reg_lock);
	spin_unlock(&instance->subdevice_lock);

	ME_SUBDEVICE_EXIT;

	return err;
}
static int me1000_dio_io_single_config(struct me_subdevice *subdevice,
				       struct file *filep,
				       int channel,
				       int single_config,
				       int ref,
				       int trig_chan,
				       int trig_type, int trig_edge, int flags)
{
	me1000_dio_subdevice_t *instance;
	int err = ME_ERRNO_SUCCESS;
	int ctrl;
	int size =
	    flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
		     | ME_IO_SINGLE_CONFIG_DIO_WORD |
		     ME_IO_SINGLE_CONFIG_DIO_DWORD);

	PDEBUG("executed.\n");

	instance = (me1000_dio_subdevice_t *) subdevice;

	ME_SUBDEVICE_ENTER;

	spin_lock(&instance->subdevice_lock);
	spin_lock(instance->ctrl_reg_lock);
	ctrl = inl(instance->ctrl_reg);

	switch (size) {
	case ME_IO_SINGLE_CONFIG_NO_FLAGS:
	case ME_IO_SINGLE_CONFIG_DIO_DWORD:
		if (channel == 0) {
			if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
				ctrl &= ~(0x1 << instance->dio_idx);
			} else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
				ctrl |= 0x1 << instance->dio_idx;
			} else {
				PERROR("Invalid port direction.\n");
				err = ME_ERRNO_INVALID_SINGLE_CONFIG;
			}
		} else {
			PERROR("Invalid channel number.\n");
			err = ME_ERRNO_INVALID_CHANNEL;
		}
		break;

	default:
		PERROR("Invalid flags.\n");
		err = ME_ERRNO_INVALID_FLAGS;
	}

	if (!err) {
		outl(ctrl, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base, ctrl);
	}
	spin_unlock(instance->ctrl_reg_lock);
	spin_unlock(&instance->subdevice_lock);

	ME_SUBDEVICE_EXIT;

	return err;
}
static int me1400_ext_irq_io_irq_start(struct me_subdevice *subdevice,
				       struct file *filep,
				       int channel,
				       int irq_source,
				       int irq_edge, int irq_arg, int flags)
{
	me1400_ext_irq_subdevice_t *instance;
	unsigned long cpu_flags;
	uint8_t tmp;

	PDEBUG("executed.\n");

	instance = (me1400_ext_irq_subdevice_t *) subdevice;

	if (flags & ~ME_IO_IRQ_START_DIO_BIT) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	if (channel) {
		PERROR("Invalid channel.\n");
		return ME_ERRNO_INVALID_CHANNEL;
	}

	if (irq_source != ME_IRQ_SOURCE_DIO_LINE) {
		PERROR("Invalid irq source.\n");
		return ME_ERRNO_INVALID_IRQ_SOURCE;
	}

	if (irq_edge != ME_IRQ_EDGE_RISING) {
		PERROR("Invalid irq edge.\n");
		return ME_ERRNO_INVALID_IRQ_EDGE;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);

	spin_lock(instance->clk_src_reg_lock);
//                      // Enable IRQ on PLX
//                      tmp = inb(instance->plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN);
//                      outb(tmp, instance->plx_intcs_reg);
//                      PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp);

	// Enable IRQ
	switch (instance->device_id) {
	case PCI_DEVICE_ID_MEILHAUS_ME140C:
	case PCI_DEVICE_ID_MEILHAUS_ME140D:
		tmp = inb(instance->ctrl_reg);
		tmp |= ME1400CD_EXT_IRQ_CLK_EN;
		outb(tmp, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base, tmp);
		break;

	default:
		outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base,
			   ME1400AB_EXT_IRQ_IRQ_EN);
		break;
	}
	spin_unlock(instance->clk_src_reg_lock);
	instance->rised = 0;
	spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);

	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}
me1400_ext_irq_subdevice_t *me1400_ext_irq_constructor(uint32_t device_id,
						       uint32_t plx_reg_base,
						       uint32_t me1400_reg_base,
						       spinlock_t *
						       clk_src_reg_lock,
						       int irq)
{
	me1400_ext_irq_subdevice_t *subdevice;
	int err;
	uint8_t tmp;

	PDEBUG("executed.\n");

	/* Allocate memory for subdevice instance */
	subdevice = kmalloc(sizeof(me1400_ext_irq_subdevice_t), GFP_KERNEL);

	if (!subdevice) {
		PERROR("Cannot get memory for 1400_ext_irq instance.\n");
		return NULL;
	}

	memset(subdevice, 0, sizeof(me1400_ext_irq_subdevice_t));

	/* Initialize subdevice base class */
	err = me_subdevice_init(&subdevice->base);

	if (err) {
		PERROR("Cannot initialize subdevice base class instance.\n");
		kfree(subdevice);
		return NULL;
	}
	// Initialize spin locks.
	spin_lock_init(&subdevice->subdevice_lock);
	subdevice->clk_src_reg_lock = clk_src_reg_lock;

	/* Initialize wait queue */
	init_waitqueue_head(&subdevice->wait_queue);

	subdevice->irq = irq;

	err = request_irq(irq, me1400_ext_irq_isr,
#ifdef IRQF_DISABLED
			  IRQF_DISABLED | IRQF_SHARED,
#else
			  SA_INTERRUPT | SA_SHIRQ,
#endif
			  ME1400_NAME, (void *)subdevice);

	if (err) {
		PERROR("Can't get irq.\n");
		me_subdevice_deinit(&subdevice->base);
		kfree(subdevice);
		return NULL;
	}
	PINFO("Registered irq=%d.\n", subdevice->irq);

	/* Initialize registers */
	subdevice->plx_intcs_reg = plx_reg_base + PLX_INTCSR_REG;
	subdevice->ctrl_reg = me1400_reg_base + ME1400AB_EXT_IRQ_CTRL_REG;
#ifdef MEDEBUG_DEBUG_REG
	subdevice->reg_base = me1400_reg_base;
#endif

	// Enable IRQ on PLX
	tmp =
	    inb(subdevice->
		plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL |
				  PLX_PCI_INT_EN);
	outb(tmp, subdevice->plx_intcs_reg);
	PDEBUG_REG("ctrl_reg outb(Pplx:0x%lX)=0x%x\n", subdevice->plx_intcs_reg,
		   tmp);

	/* Initialize the subdevice methods */
	subdevice->base.me_subdevice_io_irq_start = me1400_ext_irq_io_irq_start;
	subdevice->base.me_subdevice_io_irq_wait = me1400_ext_irq_io_irq_wait;
	subdevice->base.me_subdevice_io_irq_stop = me1400_ext_irq_io_irq_stop;
	subdevice->base.me_subdevice_io_reset_subdevice =
	    me1400_ext_irq_io_reset_subdevice;
	subdevice->base.me_subdevice_query_number_channels =
	    me1400_ext_irq_query_number_channels;
	subdevice->base.me_subdevice_query_subdevice_type =
	    me1400_ext_irq_query_subdevice_type;
	subdevice->base.me_subdevice_query_subdevice_caps =
	    me1400_ext_irq_query_subdevice_caps;
	subdevice->base.me_subdevice_query_subdevice_caps_args =
	    me1400_ext_irq_query_subdevice_caps_args;
	subdevice->base.me_subdevice_destructor = me1400_ext_irq_destructor;

	subdevice->rised = 0;
	subdevice->n = 0;

	return subdevice;
}
static irqreturn_t me1400_ext_irq_isr(int irq, void *dev_id)
{
	me1400_ext_irq_subdevice_t *instance;
	uint32_t status;
	uint8_t tmp;

	instance = (me1400_ext_irq_subdevice_t *) dev_id;

	if (irq != instance->irq) {
		PERROR("Incorrect interrupt num: %d.\n", irq);
		return IRQ_NONE;
	}

	spin_lock(&instance->subdevice_lock);
	status = inl(instance->plx_intcs_reg);
//              if (!((status & PLX_LOCAL_INT1_STATE) && (status & PLX_LOCAL_INT1_EN) && (status & PLX_PCI_INT_EN)))
	if ((status &
	     (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) !=
	    (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) {
		spin_unlock(&instance->subdevice_lock);
		PINFO("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n",
		      jiffies, __func__, status);
		return IRQ_NONE;
	}

	inl(instance->ctrl_reg);

	PDEBUG("executed.\n");

	instance->n++;
	instance->rised = 1;

	switch (instance->device_id) {

	case PCI_DEVICE_ID_MEILHAUS_ME140C:
	case PCI_DEVICE_ID_MEILHAUS_ME140D:
		spin_lock(instance->clk_src_reg_lock);
		tmp = inb(instance->ctrl_reg);
		tmp &= ~ME1400CD_EXT_IRQ_CLK_EN;
		outb(tmp, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base, tmp);
		tmp |= ME1400CD_EXT_IRQ_CLK_EN;
		outb(tmp, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base, tmp);
		spin_unlock(instance->clk_src_reg_lock);

		break;

	default:
		outb(0, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base, 0);
		outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base,
			   ME1400AB_EXT_IRQ_IRQ_EN);
		break;
	}

	spin_unlock(&instance->subdevice_lock);
	wake_up_interruptible_all(&instance->wait_queue);

	return IRQ_HANDLED;
}
me_device_t *me1400_pci_constructor(struct pci_dev *pci_device)
{
	int err;
	me1400_device_t *me1400_device;
	me_subdevice_t *subdevice;
	unsigned int version_idx;
	unsigned int me8255_idx;
	unsigned int dio_idx;
	unsigned int me8254_idx;
	unsigned int ctr_idx;
	unsigned int ext_irq_idx;

	PDEBUG("executed.\n");

	// Allocate structure for device instance.
	me1400_device = kmalloc(sizeof(me1400_device_t), GFP_KERNEL);

	if (!me1400_device) {
		PERROR("Cannot get memory for 1400ate device instance.\n");
		return NULL;
	}

	memset(me1400_device, 0, sizeof(me1400_device_t));

	// Initialize base class structure.
	err = me_device_pci_init((me_device_t *) me1400_device, pci_device);

	if (err) {
		kfree(me1400_device);
		PERROR("Cannot initialize device base class.\n");
		return NULL;
	}

	/* Check for ME1400 extension device. If detected we fake a ME-1400 D device id. */
	if (me1400_device->base.info.pci.device_id ==
	    PCI_DEVICE_ID_MEILHAUS_ME140C) {
		uint8_t ctrl;
		ctrl =
		    inb(me1400_device->base.info.pci.reg_bases[2] +
			ME1400D_CLK_SRC_2_REG);
		PDEBUG_REG("xxx_reg inb(0x%X+0x%X)=0x%x\n",
			   me1400_device->base.info.pci.reg_bases[2],
			   ME1400D_CLK_SRC_2_REG, ctrl);
		outb(ctrl | 0xF0,
		     me1400_device->base.info.pci.reg_bases[2] +
		     ME1400D_CLK_SRC_2_REG);
		PDEBUG_REG("xxx_reg outb(0x%X+0x%X)=0x%x\n",
			   me1400_device->base.info.pci.reg_bases[2],
			   ME1400D_CLK_SRC_2_REG, ctrl | 0xF0);
		ctrl =
		    inb(me1400_device->base.info.pci.reg_bases[2] +
			ME1400D_CLK_SRC_2_REG);
		PDEBUG_REG("xxx_reg inb(0x%X+0x%X)=0x%x\n",
			   me1400_device->base.info.pci.reg_bases[2],
			   ME1400D_CLK_SRC_2_REG, ctrl);

		if ((ctrl & 0xF0) == 0xF0) {
			PINFO("ME1400 D detected.\n");
			me1400_device->base.info.pci.device_id =
			    PCI_DEVICE_ID_MEILHAUS_ME140D;
		}
	}

	/* Initialize global stuff of digital i/o subdevices. */
	for (me8255_idx = 0; me8255_idx < ME1400_MAX_8255; me8255_idx++) {
		me1400_device->dio_current_mode[me8255_idx] = 0;
		spin_lock_init(&me1400_device->dio_ctrl_reg_lock[me8255_idx]);
	}

	/* Initialize global stuff of counter subdevices. */
	spin_lock_init(&me1400_device->clk_src_reg_lock);

	for (me8254_idx = 0; me8254_idx < ME1400_MAX_8254; me8254_idx++)
		spin_lock_init(&me1400_device->ctr_ctrl_reg_lock[me8254_idx]);

	/* Get the index in the device version information table. */
	version_idx =
	    me1400_versions_get_device_index(me1400_device->base.info.pci.
					     device_id);

	/* Generate DIO subdevice instances. */
	for (me8255_idx = 0;
	     me8255_idx < me1400_versions[version_idx].dio_chips;
	     me8255_idx++) {
		for (dio_idx = 0; dio_idx < 3; dio_idx++) {
			subdevice =
			    (me_subdevice_t *)
			    me8255_constructor(me1400_versions[version_idx].
					       device_id,
					       me1400_device->base.info.pci.
					       reg_bases[2], me8255_idx,
					       dio_idx,
					       &me1400_device->
					       dio_current_mode[me8255_idx],
					       &me1400_device->
					       dio_ctrl_reg_lock[me8255_idx]);

			if (!subdevice) {
				me_device_deinit((me_device_t *) me1400_device);
				kfree(me1400_device);
				PERROR("Cannot get memory for subdevice.\n");
				return NULL;
			}

			me_slist_add_subdevice_tail(&me1400_device->base.slist,
						    subdevice);
		}
	}

	/* Generate counter subdevice instances. */
	for (me8254_idx = 0;
	     me8254_idx < me1400_versions[version_idx].ctr_chips;
	     me8254_idx++) {
		for (ctr_idx = 0; ctr_idx < 3; ctr_idx++) {
			subdevice =
			    (me_subdevice_t *)
			    me8254_constructor(me1400_device->base.info.pci.
					       device_id,
					       me1400_device->base.info.pci.
					       reg_bases[2], me8254_idx,
					       ctr_idx,
					       &me1400_device->
					       ctr_ctrl_reg_lock[me8254_idx],
					       &me1400_device->
					       clk_src_reg_lock);

			if (!subdevice) {
				me_device_deinit((me_device_t *) me1400_device);
				kfree(me1400_device);
				PERROR("Cannot get memory for subdevice.\n");
				return NULL;
			}

			me_slist_add_subdevice_tail(&me1400_device->base.slist,
						    subdevice);
		}
	}

	/* Generate external interrupt subdevice instances. */
	for (ext_irq_idx = 0;
	     ext_irq_idx < me1400_versions[version_idx].ext_irq_subdevices;
	     ext_irq_idx++) {
		subdevice =
		    (me_subdevice_t *)
		    me1400_ext_irq_constructor(me1400_device->base.info.pci.
					       device_id,
					       me1400_device->base.info.pci.
					       reg_bases[1],
					       me1400_device->base.info.pci.
					       reg_bases[2],
					       &me1400_device->clk_src_reg_lock,
					       me1400_device->base.irq);

		if (!subdevice) {
			me_device_deinit((me_device_t *) me1400_device);
			kfree(me1400_device);
			PERROR("Cannot get memory for subdevice.\n");
			return NULL;
		}

		me_slist_add_subdevice_tail(&me1400_device->base.slist,
					    subdevice);
	}

	return (me_device_t *) me1400_device;
}
static int me6000_dio_io_single_config(me_subdevice_t * subdevice,
				       struct file *filep,
				       int channel,
				       int single_config,
				       int ref,
				       int trig_chan,
				       int trig_type, int trig_edge, int flags)
{
	me6000_dio_subdevice_t *instance;
	int err = ME_ERRNO_SUCCESS;
	uint8_t mode;
	int size =
	    flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
		     | ME_IO_SINGLE_CONFIG_DIO_WORD |
		     ME_IO_SINGLE_CONFIG_DIO_DWORD);

	PDEBUG("executed.\n");

	instance = (me6000_dio_subdevice_t *) subdevice;

	ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
	spin_lock(instance->ctrl_reg_lock);
	mode = inb(instance->ctrl_reg);
	switch (size) {
	case ME_IO_SINGLE_CONFIG_NO_FLAGS:
	case ME_IO_SINGLE_CONFIG_DIO_BYTE:
		if (channel == 0) {
			if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
				mode &=
				    ~((ME6000_DIO_CTRL_BIT_MODE_0 |
				       ME6000_DIO_CTRL_BIT_MODE_1) <<
				      (instance->dio_idx * 2));
			} else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
				mode &=
				    ~((ME6000_DIO_CTRL_BIT_MODE_0 |
				       ME6000_DIO_CTRL_BIT_MODE_1) <<
				      (instance->dio_idx * 2));
				mode |=
				    ME6000_DIO_CTRL_BIT_MODE_0 << (instance->
								   dio_idx * 2);
			} else {
				PERROR
				    ("Invalid port configuration specified.\n");
				err = ME_ERRNO_INVALID_SINGLE_CONFIG;
			}
		} else {
			PERROR("Invalid channel number.\n");
			err = ME_ERRNO_INVALID_CHANNEL;
		}
		break;

	default:
		PERROR("Invalid flags.\n");
		err = ME_ERRNO_INVALID_FLAGS;
	}

	if (!err) {
		outb(mode, instance->ctrl_reg);
		PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->ctrl_reg - instance->reg_base, mode);
	}
	spin_unlock(instance->ctrl_reg_lock);
	spin_unlock(&instance->subdevice_lock);

	ME_SUBDEVICE_EXIT;

	return err;
}
Esempio n. 22
0
static int me8100_di_io_irq_start(me_subdevice_t *subdevice,
				  struct file *filep,
				  int channel,
				  int irq_source,
				  int irq_edge, int irq_arg, int flags)
{
	me8100_di_subdevice_t *instance;
	int err = ME_ERRNO_SUCCESS;
	uint16_t ctrl;
	unsigned long cpu_flags;

	PDEBUG("executed.\n");

	instance = (me8100_di_subdevice_t *) subdevice;

	if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
		if (flags &
		    ~(ME_IO_IRQ_START_PATTERN_FILTERING |
		      ME_IO_IRQ_START_DIO_WORD)) {
			PERROR("Invalid flag specified.\n");
			return ME_ERRNO_INVALID_FLAGS;
		}

		if (irq_edge != ME_IRQ_EDGE_NOT_USED) {
			PERROR("Invalid irq edge specified.\n");
			return ME_ERRNO_INVALID_IRQ_EDGE;
		}
	} else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
		if (flags &
		    ~(ME_IO_IRQ_START_EXTENDED_STATUS |
		      ME_IO_IRQ_START_DIO_WORD)) {
			PERROR("Invalid flag specified.\n");
			return ME_ERRNO_INVALID_FLAGS;
		}

		if (irq_edge != ME_IRQ_EDGE_ANY) {
			PERROR("Invalid irq edge specified.\n");
			return ME_ERRNO_INVALID_IRQ_EDGE;
		}

		if (!(irq_arg & 0xFFFF)) {
			PERROR("No mask specified.\n");
			return ME_ERRNO_INVALID_IRQ_ARG;
		}
	} else {
		PERROR("Invalid irq source specified.\n");
		return ME_ERRNO_INVALID_IRQ_SOURCE;
	}

	if (channel) {
		PERROR("Invalid channel specified.\n");
		return ME_ERRNO_INVALID_CHANNEL;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
	if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
		outw(irq_arg, instance->pattern_reg);
		instance->compare_value = irq_arg;
		instance->filtering_flag =
		    (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0;
	}
	if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
		outw(irq_arg, instance->mask_reg);
	}

	spin_lock(instance->ctrl_reg_lock);
	ctrl = inw(instance->ctrl_reg);
	ctrl |= ME8100_DIO_CTRL_BIT_INTB_0;
	if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
		ctrl &= ~ME8100_DIO_CTRL_BIT_INTB_1;
	}

	if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
		ctrl |= ME8100_DIO_CTRL_BIT_INTB_1;
	}
	outw(ctrl, instance->ctrl_reg);
	PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->ctrl_reg - instance->reg_base, ctrl);
	spin_unlock(instance->ctrl_reg_lock);

	instance->rised = 0;
	instance->status_value = 0;
	instance->status_value_edges = 0;
	instance->line_value = inw(instance->port_reg);
	instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS;
	spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);

	ME_SUBDEVICE_EXIT;

	return err;
}
Esempio n. 23
0
///Functions
static int me8200_di_io_irq_start(me_subdevice_t * subdevice,
				  struct file *filep,
				  int channel,
				  int irq_source,
				  int irq_edge, int irq_arg, int flags)
{
	me8200_di_subdevice_t *instance;
	int err = ME_ERRNO_SUCCESS;
	volatile uint8_t tmp;
	unsigned long status;

	PDEBUG("executed.\n");

	instance = (me8200_di_subdevice_t *) subdevice;

	if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
		if (flags &
		    ~(ME_IO_IRQ_START_PATTERN_FILTERING |
		      ME_IO_IRQ_START_DIO_BYTE)) {
			PERROR("Invalid flag specified.\n");
			return ME_ERRNO_INVALID_FLAGS;
		}

		if (irq_edge != ME_IRQ_EDGE_NOT_USED) {
			PERROR("Invalid irq edge specified.\n");
			return ME_ERRNO_INVALID_IRQ_EDGE;
		}
	} else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
		if (flags &
		    ~(ME_IO_IRQ_START_EXTENDED_STATUS |
		      ME_IO_IRQ_START_DIO_BYTE)) {
			PERROR("Invalid flag specified.\n");
			return ME_ERRNO_INVALID_FLAGS;
		}

		if ((irq_edge != ME_IRQ_EDGE_RISING)
		    && (irq_edge != ME_IRQ_EDGE_FALLING)
		    && (irq_edge != ME_IRQ_EDGE_ANY)) {
			PERROR("Invalid irq edge specified.\n");
			return ME_ERRNO_INVALID_IRQ_EDGE;
		}

		if (!(irq_arg & 0xFF)) {
			PERROR("No mask specified.\n");
			return ME_ERRNO_INVALID_IRQ_ARG;
		}
	} else {
		PERROR("Invalid irq source specified.\n");
		return ME_ERRNO_INVALID_IRQ_SOURCE;
	}

	if (channel) {
		PERROR("Invalid channel specified.\n");
		return ME_ERRNO_INVALID_CHANNEL;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, status);
	if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
		outb(irq_arg, instance->compare_reg);
		PDEBUG_REG("compare_reg outb(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->compare_reg - instance->reg_base, irq_arg);
		outb(0xFF, instance->mask_reg);
		PDEBUG_REG("mask_reg outb(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->mask_reg - instance->reg_base, 0xff);
		instance->compare_value = irq_arg;
		instance->filtering_flag =
		    (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0;
	}
	if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
		outb(irq_arg, instance->mask_reg);
		PDEBUG_REG("mask_reg outb(0x%lX+0x%lX)=0x%x\n",
			   instance->reg_base,
			   instance->mask_reg - instance->reg_base, irq_arg);
		instance->filtering_flag = 0;
	}

	spin_lock(instance->irq_mode_lock);
	tmp = inb(instance->irq_mode_reg);
	tmp &=
	    ~(ME8200_IRQ_MODE_MASK <<
	      (ME8200_IRQ_MODE_DI_SHIFT * instance->di_idx));
	if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
		tmp |=
		    ME8200_IRQ_MODE_MASK_COMPARE << (ME8200_IRQ_MODE_DI_SHIFT *
						     instance->di_idx);
	}

	if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
		tmp |=
		    ME8200_IRQ_MODE_MASK_MASK << (ME8200_IRQ_MODE_DI_SHIFT *
						  instance->di_idx);
	}
	outb(tmp, instance->irq_mode_reg);
	PDEBUG_REG("irq_mode_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_mode_reg - instance->reg_base, tmp);
	spin_unlock(instance->irq_mode_lock);

	spin_lock(instance->irq_ctrl_lock);
	tmp = inb(instance->irq_ctrl_reg);
	tmp |=
	    (ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
	     (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
	tmp |=
	    ME8200_DI_IRQ_CTRL_BIT_ENABLE << (ME8200_DI_IRQ_CTRL_SHIFT *
					      instance->di_idx);

	if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
		tmp &=
		    ~(ME8200_DI_IRQ_CTRL_MASK_EDGE <<
		      (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
		if (irq_edge == ME_IRQ_EDGE_RISING) {
			tmp |=
			    ME8200_DI_IRQ_CTRL_MASK_EDGE_RISING <<
			    (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx);
		} else if (irq_edge == ME_IRQ_EDGE_FALLING) {
			tmp |=
			    ME8200_DI_IRQ_CTRL_MASK_EDGE_FALLING <<
			    (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx);
		} else if (irq_edge == ME_IRQ_EDGE_ANY) {
			tmp |=
			    ME8200_DI_IRQ_CTRL_MASK_EDGE_ANY <<
			    (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx);
		}
	}
	outb(tmp, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, tmp);
	tmp &=
	    ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
	      (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
	outb(tmp, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, tmp);

	instance->line_value = inb(instance->port_reg);
	spin_unlock(instance->irq_ctrl_lock);

	instance->rised = 0;
	instance->status_value = 0;
	instance->status_value_edges = 0;
	instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS;
	spin_unlock_irqrestore(&instance->subdevice_lock, status);
	ME_SUBDEVICE_EXIT;

	return err;
}
Esempio n. 24
0
static irqreturn_t me8200_isr_EX(int irq, void *dev_id, struct pt_regs *regs)
#endif
{
	me8200_di_subdevice_t *instance;
	uint8_t irq_status = 0;
	uint16_t irq_status_EX = 0;
	uint32_t status_val = 0;
	int i, j;

	instance = (me8200_di_subdevice_t *) dev_id;

	if (irq != instance->irq) {
		PERROR("Incorrect interrupt num: %d.\n", irq);
		return IRQ_NONE;
	}

	PDEBUG("executed.\n");

	//Reset latches. Copy status to extended registers.
	irq_status = inb(instance->irq_status_reg);
	PDEBUG_REG("idx=%d irq_status_reg=0x%02X\n", instance->di_idx,
		   irq_status);

	if (!irq_status) {
		PINFO
		    ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n",
		     jiffies, __func__, instance->di_idx, irq_status);
		return IRQ_NONE;
	}

	irq_status_EX = inb(instance->irq_status_low_reg);
	irq_status_EX |= (inb(instance->irq_status_high_reg) << 8);

	PDEVELOP("EXTENDED REG: 0x%04x\n", irq_status_EX);
	instance->line_value = inb(instance->port_reg);

	// Format extended information.
	for (i = 0, j = 0; i < 8; i++, j += 2) {
		status_val |= ((0x01 << j) & irq_status_EX) >> (j - i);	//Fall
		status_val |= ((0x01 << (j + 1)) & irq_status_EX) << (15 - j + i);	//Raise
	}

	spin_lock(&instance->subdevice_lock);
	if (instance->rised == 0) {
		instance->status_value = irq_status;
		instance->status_value_edges = status_val;
	} else {
		instance->status_value |= irq_status;
		instance->status_value_edges |= status_val;
	}

	if (instance->filtering_flag) {	// For compare mode only.
		if (instance->compare_value == instance->line_value) {
			instance->rised = 1;
			instance->count++;
		}
	} else {
		instance->rised = 1;
		instance->count++;
	}
	spin_unlock(&instance->subdevice_lock);

	wake_up_interruptible_all(&instance->wait_queue);

	return IRQ_HANDLED;
}
Esempio n. 25
0
static irqreturn_t me8200_isr(int irq, void *dev_id, struct pt_regs *regs)
#endif
{
	me8200_di_subdevice_t *instance;
	uint8_t ctrl;
	uint8_t irq_status;
	uint8_t line_value = 0;
	uint8_t line_status = 0;
	uint32_t status_val = 0;

	instance = (me8200_di_subdevice_t *) dev_id;

	if (irq != instance->irq) {
		PERROR("Incorrect interrupt num: %d.\n", irq);
		return IRQ_NONE;
	}

	irq_status = inb(instance->irq_status_reg);
	if (!irq_status) {
		PINFO
		    ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n",
		     jiffies, __func__, instance->di_idx, irq_status);
		return IRQ_NONE;
	}

	PDEBUG("executed.\n");

	spin_lock(&instance->subdevice_lock);
	spin_lock(instance->irq_ctrl_lock);
	ctrl = inb(instance->irq_ctrl_reg);
	ctrl |=
	    ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT *
					     instance->di_idx);
	outb(ctrl, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, ctrl);
	ctrl &=
	    ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
	      (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
	outb(ctrl, instance->irq_ctrl_reg);
	PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
		   instance->irq_ctrl_reg - instance->reg_base, ctrl);

	line_value = inb(instance->port_reg);
	spin_unlock(instance->irq_ctrl_lock);

	line_status = ((uint8_t) instance->line_value ^ line_value);

	// Make extended information.
	status_val |= (0x00FF & (~(uint8_t) instance->line_value & line_value)) << 16;	//Raise
	status_val |= (0x00FF & ((uint8_t) instance->line_value & ~line_value));	//Fall

	instance->line_value = (int)line_value;

	if (instance->rised == 0) {
		instance->status_value = irq_status | line_status;
		instance->status_value_edges = status_val;
	} else {
		instance->status_value |= irq_status | line_status;
		instance->status_value_edges |= status_val;
	}

	if (instance->filtering_flag) {	// For compare mode only.
		if (instance->compare_value == instance->line_value) {
			instance->rised = 1;
			instance->count++;
		}
	} else {
		instance->rised = 1;
		instance->count++;
	}
	spin_unlock(&instance->subdevice_lock);

	spin_unlock(&instance->subdevice_lock);

	wake_up_interruptible_all(&instance->wait_queue);

	return IRQ_HANDLED;
}
Esempio n. 26
0
static int me0600_ext_irq_io_irq_start(struct me_subdevice *subdevice,
				       struct file *filep,
				       int channel,
				       int irq_source,
				       int irq_edge, int irq_arg, int flags)
{
	me0600_ext_irq_subdevice_t *instance;
	uint32_t tmp;
	unsigned long cpu_flags;

	PDEBUG("executed.\n");

	instance = (me0600_ext_irq_subdevice_t *) subdevice;

	if (flags & ~ME_IO_IRQ_START_DIO_BIT) {
		PERROR("Invalid flag specified.\n");
		return ME_ERRNO_INVALID_FLAGS;
	}

	if (instance->lintno > 1) {
		PERROR("Wrong idx=%d.\n", instance->lintno);
		return ME_ERRNO_INVALID_SUBDEVICE;
	}

	if (channel) {
		PERROR("Invalid channel specified.\n");
		return ME_ERRNO_INVALID_CHANNEL;
	}

	if (irq_source != ME_IRQ_SOURCE_DIO_LINE) {
		PERROR("Invalid irq source specified.\n");
		return ME_ERRNO_INVALID_IRQ_SOURCE;
	}

	if (irq_edge != ME_IRQ_EDGE_RISING) {
		PERROR("Invalid irq edge specified.\n");
		return ME_ERRNO_INVALID_IRQ_EDGE;
	}

	ME_SUBDEVICE_ENTER;

	spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
	spin_lock(instance->intcsr_lock);
	tmp = inl(instance->intcsr);
	switch (instance->lintno) {
	case 0:
		tmp |=
		    PLX_INTCSR_LOCAL_INT1_EN | PLX_INTCSR_LOCAL_INT1_POL |
		    PLX_INTCSR_PCI_INT_EN;
		break;
	case 1:
		tmp |=
		    PLX_INTCSR_LOCAL_INT2_EN | PLX_INTCSR_LOCAL_INT2_POL |
		    PLX_INTCSR_PCI_INT_EN;
		break;
	}
	outl(tmp, instance->intcsr);
	PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp);
	spin_unlock(instance->intcsr_lock);
	instance->rised = 0;
	spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);

	ME_SUBDEVICE_EXIT;

	return ME_ERRNO_SUCCESS;
}