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#include <linux/kernel.h>
46#include <linux/pci.h>
47#include <linux/delay.h>
48#include <linux/ctype.h>
49#include <linux/firmware.h>
50#include <linux/jiffies.h>
51#include <linux/slab.h>
52#include <linux/timer.h>
53
54#include "../comedidev.h"
55
56#include "jr3_pci.h"
57
58#define PCI_VENDOR_ID_JR3 0x1762
59#define PCI_DEVICE_ID_JR3_1_CHANNEL 0x3111
60#define PCI_DEVICE_ID_JR3_1_CHANNEL_NEW 0x1111
61#define PCI_DEVICE_ID_JR3_2_CHANNEL 0x3112
62#define PCI_DEVICE_ID_JR3_3_CHANNEL 0x3113
63#define PCI_DEVICE_ID_JR3_4_CHANNEL 0x3114
64
65struct jr3_pci_dev_private {
66 struct jr3_t __iomem *iobase;
67 int n_channels;
68 struct timer_list timer;
69};
70
71struct poll_delay_t {
72 int min;
73 int max;
74};
75
76struct jr3_pci_subdev_private {
77 struct jr3_channel __iomem *channel;
78 unsigned long next_time_min;
79 unsigned long next_time_max;
80 enum { state_jr3_poll,
81 state_jr3_init_wait_for_offset,
82 state_jr3_init_transform_complete,
83 state_jr3_init_set_full_scale_complete,
84 state_jr3_init_use_offset_complete,
85 state_jr3_done
86 } state;
87 int channel_no;
88 int serial_no;
89 int model_no;
90 struct {
91 int length;
92 struct comedi_krange range;
93 } range[9];
94 const struct comedi_lrange *range_table_list[8 * 7 + 2];
95 unsigned int maxdata_list[8 * 7 + 2];
96 u16 errors;
97 int retries;
98};
99
100
101static int comedi_load_firmware(struct comedi_device *dev, const char *name,
102 int (*cb)(struct comedi_device *dev,
103 const u8 *data, size_t size))
104{
105 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
106 int result = 0;
107 const struct firmware *fw;
108 char *firmware_path;
109 static const char *prefix = "comedi/";
110
111 firmware_path = kmalloc(strlen(prefix) + strlen(name) + 1, GFP_KERNEL);
112 if (!firmware_path) {
113 result = -ENOMEM;
114 } else {
115 firmware_path[0] = '\0';
116 strcat(firmware_path, prefix);
117 strcat(firmware_path, name);
118 result = request_firmware(&fw, firmware_path, &pcidev->dev);
119 if (result == 0) {
120 if (!cb)
121 result = -EINVAL;
122 else
123 result = cb(dev, fw->data, fw->size);
124 release_firmware(fw);
125 }
126 kfree(firmware_path);
127 }
128 return result;
129}
130
131static struct poll_delay_t poll_delay_min_max(int min, int max)
132{
133 struct poll_delay_t result;
134
135 result.min = min;
136 result.max = max;
137 return result;
138}
139
140static int is_complete(struct jr3_channel __iomem *channel)
141{
142 return get_s16(&channel->command_word0) == 0;
143}
144
145struct transform_t {
146 struct {
147 u16 link_type;
148 s16 link_amount;
149 } link[8];
150};
151
152static void set_transforms(struct jr3_channel __iomem *channel,
153 struct transform_t transf, short num)
154{
155 int i;
156
157 num &= 0x000f;
158 for (i = 0; i < 8; i++) {
159 set_u16(&channel->transforms[num].link[i].link_type,
160 transf.link[i].link_type);
161 udelay(1);
162 set_s16(&channel->transforms[num].link[i].link_amount,
163 transf.link[i].link_amount);
164 udelay(1);
165 if (transf.link[i].link_type == end_x_form)
166 break;
167 }
168}
169
170static void use_transform(struct jr3_channel __iomem *channel,
171 short transf_num)
172{
173 set_s16(&channel->command_word0, 0x0500 + (transf_num & 0x000f));
174}
175
176static void use_offset(struct jr3_channel __iomem *channel, short offset_num)
177{
178 set_s16(&channel->command_word0, 0x0600 + (offset_num & 0x000f));
179}
180
181static void set_offset(struct jr3_channel __iomem *channel)
182{
183 set_s16(&channel->command_word0, 0x0700);
184}
185
186struct six_axis_t {
187 s16 fx;
188 s16 fy;
189 s16 fz;
190 s16 mx;
191 s16 my;
192 s16 mz;
193};
194
195static void set_full_scales(struct jr3_channel __iomem *channel,
196 struct six_axis_t full_scale)
197{
198 set_s16(&channel->full_scale.fx, full_scale.fx);
199 set_s16(&channel->full_scale.fy, full_scale.fy);
200 set_s16(&channel->full_scale.fz, full_scale.fz);
201 set_s16(&channel->full_scale.mx, full_scale.mx);
202 set_s16(&channel->full_scale.my, full_scale.my);
203 set_s16(&channel->full_scale.mz, full_scale.mz);
204 set_s16(&channel->command_word0, 0x0a00);
205}
206
207static struct six_axis_t get_min_full_scales(struct jr3_channel __iomem
208 *channel)
209{
210 struct six_axis_t result;
211 result.fx = get_s16(&channel->min_full_scale.fx);
212 result.fy = get_s16(&channel->min_full_scale.fy);
213 result.fz = get_s16(&channel->min_full_scale.fz);
214 result.mx = get_s16(&channel->min_full_scale.mx);
215 result.my = get_s16(&channel->min_full_scale.my);
216 result.mz = get_s16(&channel->min_full_scale.mz);
217 return result;
218}
219
220static struct six_axis_t get_max_full_scales(struct jr3_channel __iomem
221 *channel)
222{
223 struct six_axis_t result;
224 result.fx = get_s16(&channel->max_full_scale.fx);
225 result.fy = get_s16(&channel->max_full_scale.fy);
226 result.fz = get_s16(&channel->max_full_scale.fz);
227 result.mx = get_s16(&channel->max_full_scale.mx);
228 result.my = get_s16(&channel->max_full_scale.my);
229 result.mz = get_s16(&channel->max_full_scale.mz);
230 return result;
231}
232
233static int jr3_pci_ai_insn_read(struct comedi_device *dev,
234 struct comedi_subdevice *s,
235 struct comedi_insn *insn, unsigned int *data)
236{
237 int result;
238 struct jr3_pci_subdev_private *p;
239 int channel;
240
241 p = s->private;
242 channel = CR_CHAN(insn->chanspec);
243 if (p == NULL || channel > 57) {
244 result = -EINVAL;
245 } else {
246 int i;
247
248 result = insn->n;
249 if (p->state != state_jr3_done ||
250 (get_u16(&p->channel->errors) & (watch_dog | watch_dog2 |
251 sensor_change))) {
252
253 if (p->state == state_jr3_done) {
254
255 p->state = state_jr3_poll;
256 }
257 result = -EAGAIN;
258 }
259 for (i = 0; i < insn->n; i++) {
260 if (channel < 56) {
261 int axis, filter;
262
263 axis = channel % 8;
264 filter = channel / 8;
265 if (p->state != state_jr3_done) {
266 data[i] = 0;
267 } else {
268 int F = 0;
269 switch (axis) {
270 case 0:
271 F = get_s16(&p->channel->
272 filter[filter].fx);
273 break;
274 case 1:
275 F = get_s16(&p->channel->
276 filter[filter].fy);
277 break;
278 case 2:
279 F = get_s16(&p->channel->
280 filter[filter].fz);
281 break;
282 case 3:
283 F = get_s16(&p->channel->
284 filter[filter].mx);
285 break;
286 case 4:
287 F = get_s16(&p->channel->
288 filter[filter].my);
289 break;
290 case 5:
291 F = get_s16(&p->channel->
292 filter[filter].mz);
293 break;
294 case 6:
295 F = get_s16(&p->channel->
296 filter[filter].v1);
297 break;
298 case 7:
299 F = get_s16(&p->channel->
300 filter[filter].v2);
301 break;
302 }
303 data[i] = F + 0x4000;
304 }
305 } else if (channel == 56) {
306 if (p->state != state_jr3_done)
307 data[i] = 0;
308 else
309 data[i] =
310 get_u16(&p->channel->model_no);
311 } else if (channel == 57) {
312 if (p->state != state_jr3_done)
313 data[i] = 0;
314 else
315 data[i] =
316 get_u16(&p->channel->serial_no);
317 }
318 }
319 }
320 return result;
321}
322
323static int jr3_pci_open(struct comedi_device *dev)
324{
325 int i;
326 struct jr3_pci_dev_private *devpriv = dev->private;
327
328 dev_dbg(dev->class_dev, "jr3_pci_open\n");
329 for (i = 0; i < devpriv->n_channels; i++) {
330 struct jr3_pci_subdev_private *p;
331
332 p = dev->subdevices[i].private;
333 if (p) {
334 dev_dbg(dev->class_dev, "serial: %p %d (%d)\n", p,
335 p->serial_no, p->channel_no);
336 }
337 }
338 return 0;
339}
340
341static int read_idm_word(const u8 *data, size_t size, int *pos,
342 unsigned int *val)
343{
344 int result = 0;
345 if (pos && val) {
346
347 for (; *pos < size && !isxdigit(data[*pos]); (*pos)++)
348 ;
349
350 *val = 0;
351 for (; *pos < size; (*pos)++) {
352 int value;
353 value = hex_to_bin(data[*pos]);
354 if (value >= 0) {
355 result = 1;
356 *val = (*val << 4) + value;
357 } else {
358 break;
359 }
360 }
361 }
362 return result;
363}
364
365static int jr3_download_firmware(struct comedi_device *dev, const u8 *data,
366 size_t size)
367{
368
369
370
371
372
373 int result, more, pos, OK;
374
375 result = 0;
376 more = 1;
377 pos = 0;
378 OK = 0;
379 while (more) {
380 unsigned int count, addr;
381
382 more = more && read_idm_word(data, size, &pos, &count);
383 if (more && count == 0xffff) {
384 OK = 1;
385 break;
386 }
387 more = more && read_idm_word(data, size, &pos, &addr);
388 while (more && count > 0) {
389 unsigned int dummy;
390 more = more && read_idm_word(data, size, &pos, &dummy);
391 count--;
392 }
393 }
394
395 if (!OK) {
396 result = -ENODATA;
397 } else {
398 int i;
399 struct jr3_pci_dev_private *p = dev->private;
400
401 for (i = 0; i < p->n_channels; i++) {
402 struct jr3_pci_subdev_private *sp;
403
404 sp = dev->subdevices[i].private;
405 more = 1;
406 pos = 0;
407 while (more) {
408 unsigned int count, addr;
409 more = more &&
410 read_idm_word(data, size, &pos, &count);
411 if (more && count == 0xffff)
412 break;
413 more = more &&
414 read_idm_word(data, size, &pos, &addr);
415 dev_dbg(dev->class_dev,
416 "Loading#%d %4.4x bytes at %4.4x\n",
417 i, count, addr);
418 while (more && count > 0) {
419 if (addr & 0x4000) {
420
421
422 unsigned int data1;
423
424 more = more &&
425 read_idm_word(data,
426 size, &pos,
427 &data1);
428 count--;
429
430
431 } else {
432
433 unsigned int data1, data2;
434
435 more = more &&
436 read_idm_word(data,
437 size, &pos,
438 &data1);
439 more = more &&
440 read_idm_word(data, size,
441 &pos,
442 &data2);
443 count -= 2;
444 if (more) {
445 set_u16(&p->
446 iobase->channel
447 [i].program_low
448 [addr], data1);
449 udelay(1);
450 set_u16(&p->
451 iobase->channel
452 [i].program_high
453 [addr], data2);
454 udelay(1);
455 }
456 }
457 addr++;
458 }
459 }
460 }
461 }
462 return result;
463}
464
465static struct poll_delay_t jr3_pci_poll_subdevice(struct comedi_subdevice *s)
466{
467 struct poll_delay_t result = poll_delay_min_max(1000, 2000);
468 struct jr3_pci_subdev_private *p = s->private;
469 int i;
470
471 if (p) {
472 struct jr3_channel __iomem *channel = p->channel;
473 int errors = get_u16(&channel->errors);
474
475 if (errors != p->errors)
476 p->errors = errors;
477
478 if (errors & (watch_dog | watch_dog2 | sensor_change))
479
480 p->state = state_jr3_poll;
481
482 switch (p->state) {
483 case state_jr3_poll: {
484 u16 model_no = get_u16(&channel->model_no);
485 u16 serial_no = get_u16(&channel->serial_no);
486 if ((errors & (watch_dog | watch_dog2)) ||
487 model_no == 0 || serial_no == 0) {
488
489
490
491
492
493
494 result = poll_delay_min_max(1000, 2000);
495 } else {
496 p->retries = 0;
497 p->state =
498 state_jr3_init_wait_for_offset;
499 result = poll_delay_min_max(1000, 2000);
500 }
501 }
502 break;
503 case state_jr3_init_wait_for_offset:
504 p->retries++;
505 if (p->retries < 10) {
506
507
508 result = poll_delay_min_max(1000, 2000);
509 } else {
510 struct transform_t transf;
511
512 p->model_no = get_u16(&channel->model_no);
513 p->serial_no = get_u16(&channel->serial_no);
514
515
516 for (i = 0; i < ARRAY_SIZE(transf.link); i++) {
517 transf.link[i].link_type =
518 (enum link_types)0;
519 transf.link[i].link_amount = 0;
520 }
521
522 set_transforms(channel, transf, 0);
523 use_transform(channel, 0);
524 p->state = state_jr3_init_transform_complete;
525
526 result = poll_delay_min_max(20, 100);
527 }
528 break;
529 case state_jr3_init_transform_complete:
530 if (!is_complete(channel)) {
531 result = poll_delay_min_max(20, 100);
532 } else {
533
534 struct six_axis_t min_full_scale;
535 struct six_axis_t max_full_scale;
536
537 min_full_scale = get_min_full_scales(channel);
538 max_full_scale = get_max_full_scales(channel);
539 set_full_scales(channel, max_full_scale);
540
541 p->state =
542 state_jr3_init_set_full_scale_complete;
543
544 result = poll_delay_min_max(20, 100);
545 }
546 break;
547 case state_jr3_init_set_full_scale_complete:
548 if (!is_complete(channel)) {
549 result = poll_delay_min_max(20, 100);
550 } else {
551 struct force_array __iomem *full_scale;
552
553
554
555 full_scale = &channel->full_scale;
556 p->range[0].range.min =
557 -get_s16(&full_scale->fx) * 1000;
558 p->range[0].range.max =
559 get_s16(&full_scale->fx) * 1000;
560 p->range[1].range.min =
561 -get_s16(&full_scale->fy) * 1000;
562 p->range[1].range.max =
563 get_s16(&full_scale->fy) * 1000;
564 p->range[2].range.min =
565 -get_s16(&full_scale->fz) * 1000;
566 p->range[2].range.max =
567 get_s16(&full_scale->fz) * 1000;
568 p->range[3].range.min =
569 -get_s16(&full_scale->mx) * 100;
570 p->range[3].range.max =
571 get_s16(&full_scale->mx) * 100;
572 p->range[4].range.min =
573 -get_s16(&full_scale->my) * 100;
574 p->range[4].range.max =
575 get_s16(&full_scale->my) * 100;
576 p->range[5].range.min =
577 -get_s16(&full_scale->mz) * 100;
578 p->range[5].range.max =
579 get_s16(&full_scale->mz) * 100;
580 p->range[6].range.min =
581 -get_s16(&full_scale->v1) * 100;
582 p->range[6].range.max =
583 get_s16(&full_scale->v1) * 100;
584 p->range[7].range.min =
585 -get_s16(&full_scale->v2) * 100;
586 p->range[7].range.max =
587 get_s16(&full_scale->v2) * 100;
588 p->range[8].range.min = 0;
589 p->range[8].range.max = 65535;
590
591 use_offset(channel, 0);
592 p->state = state_jr3_init_use_offset_complete;
593
594 result = poll_delay_min_max(40, 100);
595 }
596 break;
597 case state_jr3_init_use_offset_complete:
598 if (!is_complete(channel)) {
599 result = poll_delay_min_max(20, 100);
600 } else {
601 set_s16(&channel->offsets.fx, 0);
602 set_s16(&channel->offsets.fy, 0);
603 set_s16(&channel->offsets.fz, 0);
604 set_s16(&channel->offsets.mx, 0);
605 set_s16(&channel->offsets.my, 0);
606 set_s16(&channel->offsets.mz, 0);
607
608 set_offset(channel);
609
610 p->state = state_jr3_done;
611 }
612 break;
613 case state_jr3_done:
614 poll_delay_min_max(10000, 20000);
615 break;
616 default:
617 poll_delay_min_max(1000, 2000);
618 break;
619 }
620 }
621 return result;
622}
623
624static void jr3_pci_poll_dev(unsigned long data)
625{
626 unsigned long flags;
627 struct comedi_device *dev = (struct comedi_device *)data;
628 struct jr3_pci_dev_private *devpriv = dev->private;
629 unsigned long now;
630 int delay;
631 int i;
632
633 spin_lock_irqsave(&dev->spinlock, flags);
634 delay = 1000;
635 now = jiffies;
636
637 for (i = 0; i < devpriv->n_channels; i++) {
638 struct jr3_pci_subdev_private *subdevpriv =
639 dev->subdevices[i].private;
640 if (now > subdevpriv->next_time_min) {
641 struct poll_delay_t sub_delay;
642
643 sub_delay = jr3_pci_poll_subdevice(&dev->subdevices[i]);
644 subdevpriv->next_time_min =
645 jiffies + msecs_to_jiffies(sub_delay.min);
646 subdevpriv->next_time_max =
647 jiffies + msecs_to_jiffies(sub_delay.max);
648 if (sub_delay.max && sub_delay.max < delay)
649
650
651
652
653 delay = sub_delay.max;
654 }
655 }
656 spin_unlock_irqrestore(&dev->spinlock, flags);
657
658 devpriv->timer.expires = jiffies + msecs_to_jiffies(delay);
659 add_timer(&devpriv->timer);
660}
661
662static int jr3_pci_auto_attach(struct comedi_device *dev,
663 unsigned long context_unused)
664{
665 int result;
666 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
667 int i;
668 struct jr3_pci_dev_private *devpriv;
669
670 if (sizeof(struct jr3_channel) != 0xc00) {
671 dev_err(dev->class_dev,
672 "sizeof(struct jr3_channel) = %x [expected %x]\n",
673 (unsigned)sizeof(struct jr3_channel), 0xc00);
674 return -EINVAL;
675 }
676
677 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
678 if (!devpriv)
679 return -ENOMEM;
680 dev->private = devpriv;
681
682 init_timer(&devpriv->timer);
683 switch (pcidev->device) {
684 case PCI_DEVICE_ID_JR3_1_CHANNEL:
685 case PCI_DEVICE_ID_JR3_1_CHANNEL_NEW:
686 devpriv->n_channels = 1;
687 break;
688 case PCI_DEVICE_ID_JR3_2_CHANNEL:
689 devpriv->n_channels = 2;
690 break;
691 case PCI_DEVICE_ID_JR3_3_CHANNEL:
692 devpriv->n_channels = 3;
693 break;
694 case PCI_DEVICE_ID_JR3_4_CHANNEL:
695 devpriv->n_channels = 4;
696 break;
697 default:
698 dev_err(dev->class_dev, "jr3_pci: pci %s not supported\n",
699 pci_name(pcidev));
700 return -EINVAL;
701 break;
702 }
703
704 result = comedi_pci_enable(dev);
705 if (result)
706 return result;
707
708 devpriv->iobase = pci_ioremap_bar(pcidev, 0);
709 if (!devpriv->iobase)
710 return -ENOMEM;
711
712 result = comedi_alloc_subdevices(dev, devpriv->n_channels);
713 if (result)
714 return result;
715
716 dev->open = jr3_pci_open;
717 for (i = 0; i < devpriv->n_channels; i++) {
718 dev->subdevices[i].type = COMEDI_SUBD_AI;
719 dev->subdevices[i].subdev_flags = SDF_READABLE | SDF_GROUND;
720 dev->subdevices[i].n_chan = 8 * 7 + 2;
721 dev->subdevices[i].insn_read = jr3_pci_ai_insn_read;
722 dev->subdevices[i].private =
723 kzalloc(sizeof(struct jr3_pci_subdev_private),
724 GFP_KERNEL);
725 if (dev->subdevices[i].private) {
726 struct jr3_pci_subdev_private *p;
727 int j;
728
729 p = dev->subdevices[i].private;
730 p->channel = &devpriv->iobase->channel[i].data;
731 dev_dbg(dev->class_dev, "p->channel %p %p (%tx)\n",
732 p->channel, devpriv->iobase,
733 ((char __iomem *)p->channel -
734 (char __iomem *)devpriv->iobase));
735 p->channel_no = i;
736 for (j = 0; j < 8; j++) {
737 int k;
738
739 p->range[j].length = 1;
740 p->range[j].range.min = -1000000;
741 p->range[j].range.max = 1000000;
742 for (k = 0; k < 7; k++) {
743 p->range_table_list[j + k * 8] =
744 (struct comedi_lrange *)&p->
745 range[j];
746 p->maxdata_list[j + k * 8] = 0x7fff;
747 }
748 }
749 p->range[8].length = 1;
750 p->range[8].range.min = 0;
751 p->range[8].range.max = 65536;
752
753 p->range_table_list[56] =
754 (struct comedi_lrange *)&p->range[8];
755 p->range_table_list[57] =
756 (struct comedi_lrange *)&p->range[8];
757 p->maxdata_list[56] = 0xffff;
758 p->maxdata_list[57] = 0xffff;
759
760 dev->subdevices[i].range_table = NULL;
761 dev->subdevices[i].range_table_list =
762 p->range_table_list;
763 dev->subdevices[i].maxdata = 0;
764 dev->subdevices[i].maxdata_list = p->maxdata_list;
765 }
766 }
767
768
769 writel(0, &devpriv->iobase->channel[0].reset);
770
771 result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware);
772 dev_dbg(dev->class_dev, "Firmare load %d\n", result);
773
774 if (result < 0)
775 return result;
776
777
778
779
780
781
782
783
784
785
786
787
788
789 msleep_interruptible(25);
790 for (i = 0; i < 0x18; i++) {
791 dev_dbg(dev->class_dev, "%c\n",
792 get_u16(&devpriv->iobase->channel[0].
793 data.copyright[i]) >> 8);
794 }
795
796
797 for (i = 0; i < devpriv->n_channels; i++) {
798 struct jr3_pci_subdev_private *p = dev->subdevices[i].private;
799
800 p->next_time_min = jiffies + msecs_to_jiffies(500);
801 p->next_time_max = jiffies + msecs_to_jiffies(2000);
802 }
803
804 devpriv->timer.data = (unsigned long)dev;
805 devpriv->timer.function = jr3_pci_poll_dev;
806 devpriv->timer.expires = jiffies + msecs_to_jiffies(1000);
807 add_timer(&devpriv->timer);
808
809 return result;
810}
811
812static void jr3_pci_detach(struct comedi_device *dev)
813{
814 int i;
815 struct jr3_pci_dev_private *devpriv = dev->private;
816
817 if (devpriv) {
818 del_timer_sync(&devpriv->timer);
819
820 if (dev->subdevices) {
821 for (i = 0; i < devpriv->n_channels; i++)
822 kfree(dev->subdevices[i].private);
823 }
824 if (devpriv->iobase)
825 iounmap(devpriv->iobase);
826 }
827 comedi_pci_disable(dev);
828}
829
830static struct comedi_driver jr3_pci_driver = {
831 .driver_name = "jr3_pci",
832 .module = THIS_MODULE,
833 .auto_attach = jr3_pci_auto_attach,
834 .detach = jr3_pci_detach,
835};
836
837static int jr3_pci_pci_probe(struct pci_dev *dev,
838 const struct pci_device_id *id)
839{
840 return comedi_pci_auto_config(dev, &jr3_pci_driver, id->driver_data);
841}
842
843static DEFINE_PCI_DEVICE_TABLE(jr3_pci_pci_table) = {
844 { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL) },
845 { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_1_CHANNEL_NEW) },
846 { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_2_CHANNEL) },
847 { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_3_CHANNEL) },
848 { PCI_DEVICE(PCI_VENDOR_ID_JR3, PCI_DEVICE_ID_JR3_4_CHANNEL) },
849 { 0 }
850};
851MODULE_DEVICE_TABLE(pci, jr3_pci_pci_table);
852
853static struct pci_driver jr3_pci_pci_driver = {
854 .name = "jr3_pci",
855 .id_table = jr3_pci_pci_table,
856 .probe = jr3_pci_pci_probe,
857 .remove = comedi_pci_auto_unconfig,
858};
859module_comedi_pci_driver(jr3_pci_driver, jr3_pci_pci_driver);
860
861MODULE_AUTHOR("Comedi http://www.comedi.org");
862MODULE_DESCRIPTION("Comedi low-level driver");
863MODULE_LICENSE("GPL");
864MODULE_FIRMWARE("comedi/jr3pci.idm");
865