static int insn_inval(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
static int mode0_emulate(comedi_device *dev,comedi_subdevice *s,comedi_trig *trig);
static int mode0_emulate_config(comedi_device *dev,comedi_subdevice *s,comedi_trig *trig);
+static int comedi_recognize(comedi_driver *driv, const char *name);
+static void comedi_report_boards(comedi_driver *driv);
comedi_driver *comedi_drivers;
dev->write_subdev=-1;
for(driv=comedi_drivers;driv;driv=driv->next){
- if(driv->recognize){
+ if(driv->register_boards && driv->num_boards){
+ i=comedi_recognize(driv, it->board_name);
+ if(i < 0) continue;
+ }else if(driv->recognize){
i=driv->recognize(it->board_name);
if(i<0)continue;
}else{
goto attached;
}
+ // recognize has failed if we get here
+ // report valid board names before returning error
+ for(driv=comedi_drivers;driv;driv=driv->next){
+ comedi_report_boards(driv);
+ }
return -EIO;
attached:
int comedi_driver_register(comedi_driver *driver)
{
+ int ret;
+
driver->next=comedi_drivers;
comedi_drivers=driver;
+ if(driver->register_boards)
+ {
+ ret = driver->register_boards();
+ if(ret < 0)
+ {
+ DPRINTK("failed to register supported board names\n");
+ driver->num_boards = 0;
+ }
+ }
+
return 0;
}
}
}
+ // deallocate arrays
+ if(driver->board_name){
+ kfree(driver->board_name);
+ }
+ if(driver->board_id){
+ kfree(driver->board_id);
+ }
+
if(comedi_drivers==driver){
comedi_drivers=driver->next;
return 0;
}
+// generic recognize function for drivers that register their supported board names
+int comedi_recognize(comedi_driver *driv, const char *name)
+{
+ unsigned int i = 0;
+
+ for(i = 0; i < driv->num_boards; i++)
+ {
+ if(strcmp(driv->board_name[i], name) == 0)
+ return driv->board_id[i];
+ }
+
+ return -1;
+}
+
+void comedi_report_boards(comedi_driver *driv)
+{
+ unsigned int i;
+
+ if(driv->num_boards == 0) return;
+
+ printk("comedi: valid board names for %s driver are:\n", driv->driver_name);
+ for(i = 0; i < driv->num_boards; i++)
+ {
+ printk(" %s\n", driv->board_name[i]);
+ }
+
+ return;
+}
+
/* helper functions for drivers */
int di_unpack(unsigned int bits,comedi_trig *it)
typedef struct das800_board_struct{
char *name;
+ int id;
int ai_speed;
}das800_board;
{
{
name: "das-800",
+ id: das800,
ai_speed: 25000,
},
{
name: "cio-das800",
+ id: ciodas800,
ai_speed: 20000,
},
{
name: "das-801",
+ id: das801,
ai_speed: 25000,
},
{
name: "cio-das801",
+ id: ciodas801,
ai_speed: 20000,
},
{
name: "das-802",
+ id: das802,
ai_speed: 25000,
},
{
name: "cio-das802",
+ id: ciodas802,
ai_speed: 20000,
},
};
static int das800_attach(comedi_device *dev,comedi_devconfig *it);
static int das800_detach(comedi_device *dev);
static int das800_recognize(char *name);
+static int das800_register_boards(void);
static int das800_cancel(comedi_device *dev, comedi_subdevice *s);
comedi_driver driver_das800={
attach: das800_attach,
detach: das800_detach,
recognize: das800_recognize,
+ register_boards: das800_register_boards,
};
static void das800_interrupt(int irq, void *d, struct pt_regs *regs);
int das800_set_frequency(comedi_device *dev);
int das800_load_counter(unsigned int counterNumber, unsigned int counterValue, comedi_device *dev);
+static int das800_register_boards(void)
+{
+ unsigned int i;
+ unsigned int num_boards = sizeof(das800_boards) / sizeof(das800_boards[0]);
+ char **board_name;
+ int *board_id;
+
+ board_name = kmalloc(num_boards * sizeof(char*), GFP_KERNEL);
+ if(board_name == NULL)
+ return -ENOMEM;
+
+ board_id = kmalloc(num_boards * sizeof(int), GFP_KERNEL);
+ if(board_id == NULL)
+ {
+ kfree(board_name);
+ return -ENOMEM;
+ }
+
+ for(i = 0; i < num_boards; i++)
+ {
+ board_name[i] = das800_boards[i].name;
+ board_id[i] = das800_boards[i].id;
+ }
+
+ driver_das800.num_boards = num_boards;
+ driver_das800.board_name = board_name;
+ driver_das800.board_id = board_id;
+
+ return 0;
+}
+
static int das800_recognize(char *name)
{
if(!strcmp(name, "das-800") || !strcmp(name, "das800"))
}
printk("\n");
+ dev->board = das800_probe(dev);
+ if(dev->board < 0)
+ {
+ printk("unable to determine board type\n");
+ return -ENODEV;
+ }
+
if(iobase == 0)
{
printk("io base address required for das800\n");
}
dev->irq = irq;
- dev->board = das800_probe(dev);
- if(dev->board < 0)
- {
- printk("unable to determine board type\n");
- return -ENODEV;
- }
-
dev->board_ptr = das800_boards + dev->board;
dev->board_name = thisboard->name;
static int das800_do_winsn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
{
- int mux_bits;
int chan = CR_CHAN(insn->chanspec);
unsigned long irq_flags;
- mux_bits = inb(dev->iobase + DAS800_STATUS) & 0x7;
// set channel to 1
if(data[0])
devpriv->do_bits |= (1 << (chan + 4)) & 0xf0;
comedi_spin_lock_irqsave(&devpriv->spinlock, irq_flags);
outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */
- outb(devpriv->do_bits | CONTROL1_INTE | mux_bits, dev->iobase + DAS800_CONTROL1);
+ outb(devpriv->do_bits | CONTROL1_INTE, dev->iobase + DAS800_CONTROL1);
comedi_spin_unlock_irqrestore(&devpriv->spinlock, irq_flags);
return 1;
static int das800_do_wbits(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data)
{
- int mux_bits;
int wbits;
unsigned long irq_flags;
- mux_bits = inb(dev->iobase + DAS800_STATUS) & 0x7;
// only set bits that have been masked
data[0] &= 0xf;
comedi_spin_lock_irqsave(&devpriv->spinlock, irq_flags);
outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */
- outb(devpriv->do_bits | CONTROL1_INTE | mux_bits, dev->iobase + DAS800_CONTROL1);
+ outb(devpriv->do_bits | CONTROL1_INTE, dev->iobase + DAS800_CONTROL1);
comedi_spin_unlock_irqrestore(&devpriv->spinlock, irq_flags);
data[1] = wbits;
*/
static int skel_attach(comedi_device *dev,comedi_devconfig *it);
static int skel_detach(comedi_device *dev);
-static int skel_recognize(char *name);
+//static int skel_recognize(char *name);
+static int skel_register_boards(void);
comedi_driver driver_skel={
driver_name: "dummy",
module: THIS_MODULE,
attach: skel_attach,
detach: skel_detach,
- recognize: skel_recognize,
+// recognize: skel_recognize,
+ register_boards: skel_register_boards, // replacement for recognize
};
static int skel_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
* driver can service, then a non-negative index should be returned.
* This index is put into dev->board, and then _attach() is called.
*/
+
+/*
static int skel_recognize(char *name)
{
if(!strcmp("skel-100",name))return 0;
return -1;
}
+*/
+
+/* The function register_boards() is a replacement for recognize
+ * that allows comedi to report back valid board names when it doesn't
+ * recognize a board name. The job of register_boards is to
+ * initialize the board_name, board_id and num_boards members of
+ * the the comedi_driver_struct for this driver. The arrays
+ * don't need to be deallocated as that is done in
+ * comedi_driver_unregister() in the drivers.c file
+ */
+static int skel_register_boards(void)
+{
+ unsigned int i;
+ unsigned int num_boards = sizeof(skel_boards) / sizeof(skel_board);
+ char **board_name;
+ int *board_id;
+
+ board_name = kmalloc(num_boards * sizeof(char*), GFP_KERNEL);
+ if(board_name == NULL)
+ return -ENOMEM;
+
+ board_id = kmalloc(num_boards * sizeof(int), GFP_KERNEL);
+ if(board_id == NULL)
+ {
+ kfree(board_name);
+ return -ENOMEM;
+ }
+
+ for(i = 0; i < num_boards; i++)
+ {
+ board_name[i] = skel_boards[i].name;
+ board_id[i] = i;
+ }
+
+ driver_skel.num_boards = num_boards;
+ driver_skel.board_name = board_name;
+ driver_skel.board_id = board_id;
+
+ return 0;
+}
/*
* Attach is called by the Comedi core to configure the driver
s->type = COMEDI_SUBD_UNUSED;
}
+ printk("attached\n");
+
return 1;
}
int (*attach)(comedi_device *,comedi_devconfig *);
int (*detach)(comedi_device *);
int (*recognize)(char *name);
+
+ /* register_boards, board_name, board_id, num_boards provide alternative
+ * to recognize which allows reporting back to user recognized board
+ * names
+ */
+ int (*register_boards)(void); // initializes board_name and board_id arrays
+ char **board_name;
+ int *board_id;
+ unsigned int num_boards; // number of elements in board_name and board_id arrays
};
struct comedi_device_struct{