Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 304516
b: refs/heads/master
c: 924f468
h: refs/heads/master
v: v3
  • Loading branch information
H Hartley Sweeten authored and Greg Kroah-Hartman committed Apr 30, 2012
1 parent 05ade93 commit 19825cc
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 136 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: 3496cb9fac149ce5a17a048c020224a964224558
refs/heads/master: 924f4685f47f160ddb0927c0ccb012ccf615a644
216 changes: 81 additions & 135 deletions trunk/drivers/staging/comedi/drivers/pcmda12.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,6 @@ static const struct comedi_lrange pcmda12_ranges = {
}
};

static const struct pcmda12_board pcmda12_boards[] = {
{
.name = "pcmda12",
},
};

/*
* Useful for shorthand access to the particular board structure
*/
Expand All @@ -99,57 +93,77 @@ struct pcmda12_private {

#define devpriv ((struct pcmda12_private *)(dev->private))

/*
* The struct comedi_driver structure tells the Comedi core module
* which functions to call to configure/deconfigure (attach/detach)
* the board, and also about the kernel module that contains
* the device code.
*/
static int pcmda12_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
static int pcmda12_detach(struct comedi_device *dev);
static void zero_chans(struct comedi_device *dev)
{ /* sets up an
ASIC chip to defaults */
int i;
for (i = 0; i < CHANS; ++i) {
/* /\* do this as one instruction?? *\/ */
/* outw(0, LSB_PORT(chan)); */
outb(0, LSB_PORT(i));
outb(0, MSB_PORT(i));
}
inb(LSB_PORT(0)); /* update chans. */
}

static void zero_chans(struct comedi_device *dev);
static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
int i;
int chan = CR_CHAN(insn->chanspec);

static struct comedi_driver driver = {
.driver_name = "pcmda12",
.module = THIS_MODULE,
.attach = pcmda12_attach,
.detach = pcmda12_detach,
/* It is not necessary to implement the following members if you are
* writing a driver for a ISA PnP or PCI card */
/* Most drivers will support multiple types of boards by
* having an array of board structures. These were defined
* in pcmda12_boards[] above. Note that the element 'name'
* was first in the structure -- Comedi uses this fact to
* extract the name of the board without knowing any details
* about the structure except for its length.
* When a device is attached (by comedi_config), the name
* of the device is given to Comedi, and Comedi tries to
* match it by going through the list of board names. If
* there is a match, the address of the pointer is put
* into dev->board_ptr and driver->attach() is called.
*
* Note that these are not necessary if you can determine
* the type of board in software. ISA PnP, PCI, and PCMCIA
* devices are such boards.
*/
.board_name = &pcmda12_boards[0].name,
.offset = sizeof(struct pcmda12_board),
.num_names = ARRAY_SIZE(pcmda12_boards),
};
/* Writing a list of values to an AO channel is probably not
* very useful, but that's how the interface is defined. */
for (i = 0; i < insn->n; ++i) {

static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/* /\* do this as one instruction?? *\/ */
/* outw(data[i], LSB_PORT(chan)); */

/* Need to do this as two instructions due to 8-bit bus?? */
/* first, load the low byte */
outb(LSB(data[i]), LSB_PORT(chan));
/* next, write the high byte */
outb(MSB(data[i]), MSB_PORT(chan));

/* save shadow register */
devpriv->ao_readback[chan] = data[i];

if (!devpriv->simultaneous_xfer_mode)
inb(LSB_PORT(chan));
}

/* return the number of samples written */
return i;
}

/* AO subdevices should have a read insn as well as a write insn.
Usually this means copying a value stored in devpriv->ao_readback.
However, since this driver supports simultaneous xfer then sometimes
this function actually accomplishes work.
Simultaneaous xfer mode is accomplished by loading ALL the values
you want for AO in all the channels, then READing off one of the AO
registers to initiate the instantaneous simultaneous update of all
DAC outputs, which makes all AO channels update simultaneously.
This is useful for some control applications, I would imagine.
*/
static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
struct comedi_insn *insn, unsigned int *data)
{
int i;
int chan = CR_CHAN(insn->chanspec);

for (i = 0; i < insn->n; i++) {
if (devpriv->simultaneous_xfer_mode)
inb(LSB_PORT(chan));
/* read back shadow register */
data[i] = devpriv->ao_readback[chan];
}

return i;
}

/*
* Attach is called by the Comedi core to configure the driver
* for a particular board. If you specified a board_name array
* in the driver structure, dev->board_ptr contains that
* address.
*/
static int pcmda12_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
Expand Down Expand Up @@ -213,14 +227,6 @@ static int pcmda12_attach(struct comedi_device *dev,
return 1;
}

/*
* _detach is called to deconfigure a device. It should deallocate
* resources.
* This function is also called when _attach() fails, so it should be
* careful not to release resources that were not necessarily
* allocated by _attach(). dev->private and dev->subdevices are
* deallocated automatically by the core.
*/
static int pcmda12_detach(struct comedi_device *dev)
{
printk(KERN_INFO
Expand All @@ -230,92 +236,32 @@ static int pcmda12_detach(struct comedi_device *dev)
return 0;
}

static void zero_chans(struct comedi_device *dev)
{ /* sets up an
ASIC chip to defaults */
int i;
for (i = 0; i < CHANS; ++i) {
/* /\* do this as one instruction?? *\/ */
/* outw(0, LSB_PORT(chan)); */
outb(0, LSB_PORT(i));
outb(0, MSB_PORT(i));
}
inb(LSB_PORT(0)); /* update chans. */
}

static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
int i;
int chan = CR_CHAN(insn->chanspec);

/* Writing a list of values to an AO channel is probably not
* very useful, but that's how the interface is defined. */
for (i = 0; i < insn->n; ++i) {

/* /\* do this as one instruction?? *\/ */
/* outw(data[i], LSB_PORT(chan)); */

/* Need to do this as two instructions due to 8-bit bus?? */
/* first, load the low byte */
outb(LSB(data[i]), LSB_PORT(chan));
/* next, write the high byte */
outb(MSB(data[i]), MSB_PORT(chan));

/* save shadow register */
devpriv->ao_readback[chan] = data[i];

if (!devpriv->simultaneous_xfer_mode)
inb(LSB_PORT(chan));
}

/* return the number of samples written */
return i;
}

/* AO subdevices should have a read insn as well as a write insn.
Usually this means copying a value stored in devpriv->ao_readback.
However, since this driver supports simultaneous xfer then sometimes
this function actually accomplishes work.
Simultaneaous xfer mode is accomplished by loading ALL the values
you want for AO in all the channels, then READing off one of the AO
registers to initiate the instantaneous simultaneous update of all
DAC outputs, which makes all AO channels update simultaneously.
This is useful for some control applications, I would imagine.
*/
static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
int i;
int chan = CR_CHAN(insn->chanspec);

for (i = 0; i < insn->n; i++) {
if (devpriv->simultaneous_xfer_mode)
inb(LSB_PORT(chan));
/* read back shadow register */
data[i] = devpriv->ao_readback[chan];
}
static const struct pcmda12_board pcmda12_boards[] = {
{
.name = "pcmda12",
},
};

return i;
}
static struct comedi_driver driver = {
.driver_name = "pcmda12",
.module = THIS_MODULE,
.attach = pcmda12_attach,
.detach = pcmda12_detach,
.board_name = &pcmda12_boards[0].name,
.offset = sizeof(struct pcmda12_board),
.num_names = ARRAY_SIZE(pcmda12_boards),
};

/*
* A convenient macro that defines init_module() and cleanup_module(),
* as necessary.
*/
static int __init driver_init_module(void)
{
return comedi_driver_register(&driver);
}
module_init(driver_init_module);

static void __exit driver_cleanup_module(void)
{
comedi_driver_unregister(&driver);
}

module_init(driver_init_module);
module_exit(driver_cleanup_module);

MODULE_AUTHOR("Comedi http://www.comedi.org");
Expand Down

0 comments on commit 19825cc

Please sign in to comment.