Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 337231
b: refs/heads/master
c: 57054dc
h: refs/heads/master
i:
  337229: a66a4a9
  337227: a7d1fc9
  337223: 91e941b
  337215: cf01e63
v: v3
  • Loading branch information
Ian Abbott authored and Greg Kroah-Hartman committed Oct 24, 2012
1 parent d393cb6 commit 9aa9343
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 155857cd5488d6287724ad560f063e568a077940
refs/heads/master: 57054dcaec4848d5f6ce2fddaebfd0fc110e0c53
147 changes: 143 additions & 4 deletions trunk/drivers/staging/comedi/drivers/amplc_dio200.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@
#include "../comedidev.h"

#include "comedi_fc.h"
#include "8255.h"
#include "8253.h"

#define DIO200_DRIVER_NAME "amplc_dio200"
Expand All @@ -221,6 +220,15 @@
#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
#define PCI_DEVICE_ID_INVALID 0xffff

/* 8255 control register bits */
#define CR_C_LO_IO 0x01
#define CR_B_IO 0x02
#define CR_B_MODE 0x04
#define CR_C_HI_IO 0x08
#define CR_A_IO 0x10
#define CR_A_MODE(a) ((a)<<5)
#define CR_CW 0x80

/* 200 series registers */
#define DIO200_IO_SIZE 0x20
#define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */
Expand Down Expand Up @@ -430,6 +438,10 @@ struct dio200_subdev_8254 {
spinlock_t spinlock;
};

struct dio200_subdev_8255 {
unsigned int ofs; /* DIO base offset */
};

struct dio200_subdev_intr {
unsigned int ofs;
spinlock_t spinlock;
Expand Down Expand Up @@ -1245,6 +1257,133 @@ dio200_subdev_8254_cleanup(struct comedi_device *dev,
kfree(subpriv);
}

/*
* This function sets I/O directions for an '8255' DIO subdevice.
*/
static void dio200_subdev_8255_set_dir(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct dio200_subdev_8255 *subpriv = s->private;
int config;

config = CR_CW;
/* 1 in io_bits indicates output, 1 in config indicates input */
if (!(s->io_bits & 0x0000ff))
config |= CR_A_IO;
if (!(s->io_bits & 0x00ff00))
config |= CR_B_IO;
if (!(s->io_bits & 0x0f0000))
config |= CR_C_LO_IO;
if (!(s->io_bits & 0xf00000))
config |= CR_C_HI_IO;
outb(config, dev->iobase + subpriv->ofs + 3);
}

/*
* Handle 'insn_bits' for an '8255' DIO subdevice.
*/
static int dio200_subdev_8255_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
struct dio200_subdev_8255 *subpriv = s->private;

if (data[0]) {
s->state &= ~data[0];
s->state |= (data[0] & data[1]);
if (data[0] & 0xff)
outb(s->state & 0xff, dev->iobase + subpriv->ofs);
if (data[0] & 0xff00)
outb((s->state >> 8) & 0xff,
dev->iobase + subpriv->ofs + 1);
if (data[0] & 0xff0000)
outb((s->state >> 16) & 0xff,
dev->iobase + subpriv->ofs + 2);
}
data[1] = inb(dev->iobase + subpriv->ofs);
data[1] |= inb(dev->iobase + subpriv->ofs + 1) << 8;
data[1] |= inb(dev->iobase + subpriv->ofs + 2) << 16;
return 2;
}

/*
* Handle 'insn_config' for an '8255' DIO subdevice.
*/
static int dio200_subdev_8255_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
unsigned int mask;
unsigned int bits;

mask = 1 << CR_CHAN(insn->chanspec);
if (mask & 0x0000ff)
bits = 0x0000ff;
else if (mask & 0x00ff00)
bits = 0x00ff00;
else if (mask & 0x0f0000)
bits = 0x0f0000;
else
bits = 0xf00000;
switch (data[0]) {
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~bits;
break;
case INSN_CONFIG_DIO_OUTPUT:
s->io_bits |= bits;
break;
case INSN_CONFIG_DIO_QUERY:
data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
return insn->n;
break;
default:
return -EINVAL;
}
dio200_subdev_8255_set_dir(dev, s);
return 1;
}

/*
* This function initializes an '8255' DIO subdevice.
*
* offset is the offset to the 8255 chip.
*/
static int dio200_subdev_8255_init(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int offset)
{
struct dio200_subdev_8255 *subpriv;

subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
if (!subpriv)
return -ENOMEM;
subpriv->ofs = offset;
s->private = subpriv;
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 24;
s->range_table = &range_digital;
s->maxdata = 1;
s->insn_bits = dio200_subdev_8255_bits;
s->insn_config = dio200_subdev_8255_config;
s->state = 0;
s->io_bits = 0;
dio200_subdev_8255_set_dir(dev, s);
return 0;
}

/*
* This function cleans up an '8255' DIO subdevice.
*/
static void dio200_subdev_8255_cleanup(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct dio200_subdev_8255 *subpriv = s->private;

kfree(subpriv);
}

static void dio200_report_attach(struct comedi_device *dev, unsigned int irq)
{
const struct dio200_board *thisboard = comedi_board(dev);
Expand Down Expand Up @@ -1301,8 +1440,8 @@ static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
break;
case sd_8255:
/* digital i/o subdevice (8255) */
ret = subdev_8255_init(dev, s, NULL,
iobase + layout->sdinfo[n]);
ret = dio200_subdev_8255_init(dev, s,
layout->sdinfo[n]);
if (ret < 0)
return ret;
break;
Expand Down Expand Up @@ -1438,7 +1577,7 @@ static void dio200_detach(struct comedi_device *dev)
dio200_subdev_8254_cleanup(dev, s);
break;
case sd_8255:
subdev_8255_cleanup(dev, s);
dio200_subdev_8255_cleanup(dev, s);
break;
case sd_intr:
dio200_subdev_intr_cleanup(dev, s);
Expand Down

0 comments on commit 9aa9343

Please sign in to comment.