This source file includes following definitions.
- parport_data_reg_insn_bits
- parport_data_reg_insn_config
- parport_status_reg_insn_bits
- parport_ctrl_reg_insn_bits
- parport_intr_insn_bits
- parport_intr_cmdtest
- parport_intr_cmd
- parport_intr_cancel
- parport_interrupt
- parport_attach
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 #include <linux/module.h>
  59 #include <linux/interrupt.h>
  60 
  61 #include "../comedidev.h"
  62 
  63 
  64 
  65 
  66 #define PARPORT_DATA_REG        0x00
  67 #define PARPORT_STATUS_REG      0x01
  68 #define PARPORT_CTRL_REG        0x02
  69 #define PARPORT_CTRL_IRQ_ENA    BIT(4)
  70 #define PARPORT_CTRL_BIDIR_ENA  BIT(5)
  71 
  72 static int parport_data_reg_insn_bits(struct comedi_device *dev,
  73                                       struct comedi_subdevice *s,
  74                                       struct comedi_insn *insn,
  75                                       unsigned int *data)
  76 {
  77         if (comedi_dio_update_state(s, data))
  78                 outb(s->state, dev->iobase + PARPORT_DATA_REG);
  79 
  80         data[1] = inb(dev->iobase + PARPORT_DATA_REG);
  81 
  82         return insn->n;
  83 }
  84 
  85 static int parport_data_reg_insn_config(struct comedi_device *dev,
  86                                         struct comedi_subdevice *s,
  87                                         struct comedi_insn *insn,
  88                                         unsigned int *data)
  89 {
  90         unsigned int ctrl;
  91         int ret;
  92 
  93         ret = comedi_dio_insn_config(dev, s, insn, data, 0xff);
  94         if (ret)
  95                 return ret;
  96 
  97         ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
  98         if (s->io_bits)
  99                 ctrl &= ~PARPORT_CTRL_BIDIR_ENA;
 100         else
 101                 ctrl |= PARPORT_CTRL_BIDIR_ENA;
 102         outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
 103 
 104         return insn->n;
 105 }
 106 
 107 static int parport_status_reg_insn_bits(struct comedi_device *dev,
 108                                         struct comedi_subdevice *s,
 109                                         struct comedi_insn *insn,
 110                                         unsigned int *data)
 111 {
 112         data[1] = inb(dev->iobase + PARPORT_STATUS_REG) >> 3;
 113 
 114         return insn->n;
 115 }
 116 
 117 static int parport_ctrl_reg_insn_bits(struct comedi_device *dev,
 118                                       struct comedi_subdevice *s,
 119                                       struct comedi_insn *insn,
 120                                       unsigned int *data)
 121 {
 122         unsigned int ctrl;
 123 
 124         if (comedi_dio_update_state(s, data)) {
 125                 ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
 126                 ctrl &= (PARPORT_CTRL_IRQ_ENA | PARPORT_CTRL_BIDIR_ENA);
 127                 ctrl |= s->state;
 128                 outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
 129         }
 130 
 131         data[1] = s->state;
 132 
 133         return insn->n;
 134 }
 135 
 136 static int parport_intr_insn_bits(struct comedi_device *dev,
 137                                   struct comedi_subdevice *s,
 138                                   struct comedi_insn *insn,
 139                                   unsigned int *data)
 140 {
 141         data[1] = 0;
 142         return insn->n;
 143 }
 144 
 145 static int parport_intr_cmdtest(struct comedi_device *dev,
 146                                 struct comedi_subdevice *s,
 147                                 struct comedi_cmd *cmd)
 148 {
 149         int err = 0;
 150 
 151         
 152 
 153         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
 154         err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
 155         err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
 156         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 157         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
 158 
 159         if (err)
 160                 return 1;
 161 
 162         
 163         
 164 
 165         
 166 
 167         err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 168         err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 169         err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 170         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 171                                            cmd->chanlist_len);
 172         err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 173 
 174         if (err)
 175                 return 3;
 176 
 177         
 178 
 179         
 180 
 181         return 0;
 182 }
 183 
 184 static int parport_intr_cmd(struct comedi_device *dev,
 185                             struct comedi_subdevice *s)
 186 {
 187         unsigned int ctrl;
 188 
 189         ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
 190         ctrl |= PARPORT_CTRL_IRQ_ENA;
 191         outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
 192 
 193         return 0;
 194 }
 195 
 196 static int parport_intr_cancel(struct comedi_device *dev,
 197                                struct comedi_subdevice *s)
 198 {
 199         unsigned int ctrl;
 200 
 201         ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
 202         ctrl &= ~PARPORT_CTRL_IRQ_ENA;
 203         outb(ctrl, dev->iobase + PARPORT_CTRL_REG);
 204 
 205         return 0;
 206 }
 207 
 208 static irqreturn_t parport_interrupt(int irq, void *d)
 209 {
 210         struct comedi_device *dev = d;
 211         struct comedi_subdevice *s = dev->read_subdev;
 212         unsigned int ctrl;
 213 
 214         ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
 215         if (!(ctrl & PARPORT_CTRL_IRQ_ENA))
 216                 return IRQ_NONE;
 217 
 218         comedi_buf_write_samples(s, &s->state, 1);
 219         comedi_handle_events(dev, s);
 220 
 221         return IRQ_HANDLED;
 222 }
 223 
 224 static int parport_attach(struct comedi_device *dev,
 225                           struct comedi_devconfig *it)
 226 {
 227         struct comedi_subdevice *s;
 228         int ret;
 229 
 230         ret = comedi_request_region(dev, it->options[0], 0x03);
 231         if (ret)
 232                 return ret;
 233 
 234         if (it->options[1]) {
 235                 ret = request_irq(it->options[1], parport_interrupt, 0,
 236                                   dev->board_name, dev);
 237                 if (ret == 0)
 238                         dev->irq = it->options[1];
 239         }
 240 
 241         ret = comedi_alloc_subdevices(dev, dev->irq ? 4 : 3);
 242         if (ret)
 243                 return ret;
 244 
 245         
 246         s = &dev->subdevices[0];
 247         s->type         = COMEDI_SUBD_DIO;
 248         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 249         s->n_chan       = 8;
 250         s->maxdata      = 1;
 251         s->range_table  = &range_digital;
 252         s->insn_bits    = parport_data_reg_insn_bits;
 253         s->insn_config  = parport_data_reg_insn_config;
 254 
 255         
 256         s = &dev->subdevices[1];
 257         s->type         = COMEDI_SUBD_DI;
 258         s->subdev_flags = SDF_READABLE;
 259         s->n_chan       = 5;
 260         s->maxdata      = 1;
 261         s->range_table  = &range_digital;
 262         s->insn_bits    = parport_status_reg_insn_bits;
 263 
 264         
 265         s = &dev->subdevices[2];
 266         s->type         = COMEDI_SUBD_DO;
 267         s->subdev_flags = SDF_WRITABLE;
 268         s->n_chan       = 4;
 269         s->maxdata      = 1;
 270         s->range_table  = &range_digital;
 271         s->insn_bits    = parport_ctrl_reg_insn_bits;
 272 
 273         if (dev->irq) {
 274                 
 275                 s = &dev->subdevices[3];
 276                 dev->read_subdev = s;
 277                 s->type         = COMEDI_SUBD_DI;
 278                 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
 279                 s->n_chan       = 1;
 280                 s->maxdata      = 1;
 281                 s->range_table  = &range_digital;
 282                 s->insn_bits    = parport_intr_insn_bits;
 283                 s->len_chanlist = 1;
 284                 s->do_cmdtest   = parport_intr_cmdtest;
 285                 s->do_cmd       = parport_intr_cmd;
 286                 s->cancel       = parport_intr_cancel;
 287         }
 288 
 289         outb(0, dev->iobase + PARPORT_DATA_REG);
 290         outb(0, dev->iobase + PARPORT_CTRL_REG);
 291 
 292         return 0;
 293 }
 294 
 295 static struct comedi_driver parport_driver = {
 296         .driver_name    = "comedi_parport",
 297         .module         = THIS_MODULE,
 298         .attach         = parport_attach,
 299         .detach         = comedi_legacy_detach,
 300 };
 301 module_comedi_driver(parport_driver);
 302 
 303 MODULE_AUTHOR("Comedi http://www.comedi.org");
 304 MODULE_DESCRIPTION("Comedi: Standard parallel port driver");
 305 MODULE_LICENSE("GPL");