1 #include "../comedidev.h"
3 #include "amcc_s5933.h"
5 #include "addi-data/addi_common.h"
7 #include "addi-data/hwdrv_apci3120.c"
9 static const struct addi_board apci3120_boardtypes
[] = {
11 .pc_DriverName
= "apci3120",
12 .i_VendorId
= PCI_VENDOR_ID_ADDIDATA_OLD
,
15 .i_NbrAiChannelDiff
= 8,
16 .i_AiChannelList
= 16,
18 .i_AiMaxdata
= 0xffff,
19 .i_AoMaxdata
= 0x3fff,
23 .interrupt
= v_APCI3120_Interrupt
,
25 .pc_DriverName
= "apci3001",
26 .i_VendorId
= PCI_VENDOR_ID_ADDIDATA_OLD
,
29 .i_NbrAiChannelDiff
= 8,
30 .i_AiChannelList
= 16,
35 .interrupt
= v_APCI3120_Interrupt
,
39 static irqreturn_t
v_ADDI_Interrupt(int irq
, void *d
)
41 struct comedi_device
*dev
= d
;
42 const struct addi_board
*this_board
= comedi_board(dev
);
44 this_board
->interrupt(irq
, d
);
48 static const void *apci3120_find_boardinfo(struct comedi_device
*dev
,
49 struct pci_dev
*pcidev
)
51 const struct addi_board
*this_board
;
54 for (i
= 0; i
< ARRAY_SIZE(apci3120_boardtypes
); i
++) {
55 this_board
= &apci3120_boardtypes
[i
];
56 if (this_board
->i_VendorId
== pcidev
->vendor
&&
57 this_board
->i_DeviceId
== pcidev
->device
)
63 static int apci3120_auto_attach(struct comedi_device
*dev
,
64 unsigned long context_unused
)
66 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
67 const struct addi_board
*this_board
;
68 struct addi_private
*devpriv
;
69 struct comedi_subdevice
*s
;
72 this_board
= apci3120_find_boardinfo(dev
, pcidev
);
75 dev
->board_ptr
= this_board
;
76 dev
->board_name
= this_board
->pc_DriverName
;
78 devpriv
= kzalloc(sizeof(*devpriv
), GFP_KERNEL
);
81 dev
->private = devpriv
;
83 ret
= comedi_pci_enable(pcidev
, dev
->board_name
);
86 pci_set_master(pcidev
);
88 dev
->iobase
= pci_resource_start(pcidev
, 1);
89 devpriv
->iobase
= dev
->iobase
;
90 devpriv
->i_IobaseAmcc
= pci_resource_start(pcidev
, 0);
91 devpriv
->i_IobaseAddon
= pci_resource_start(pcidev
, 2);
92 devpriv
->i_IobaseReserved
= pci_resource_start(pcidev
, 3);
94 if (pcidev
->irq
> 0) {
95 ret
= request_irq(pcidev
->irq
, v_ADDI_Interrupt
, IRQF_SHARED
,
96 dev
->board_name
, dev
);
98 dev
->irq
= pcidev
->irq
;
101 devpriv
->us_UseDma
= ADDI_ENABLE
;
103 /* Allocate DMA buffers */
104 devpriv
->b_DmaDoubleBuffer
= 0;
105 for (i
= 0; i
< 2; i
++) {
106 for (pages
= 4; pages
>= 0; pages
--) {
107 devpriv
->ul_DmaBufferVirtual
[i
] =
108 (void *) __get_free_pages(GFP_KERNEL
, pages
);
110 if (devpriv
->ul_DmaBufferVirtual
[i
])
113 if (devpriv
->ul_DmaBufferVirtual
[i
]) {
114 devpriv
->ui_DmaBufferPages
[i
] = pages
;
115 devpriv
->ui_DmaBufferSize
[i
] = PAGE_SIZE
* pages
;
116 devpriv
->ui_DmaBufferSamples
[i
] =
117 devpriv
->ui_DmaBufferSize
[i
] >> 1;
118 devpriv
->ul_DmaBufferHw
[i
] =
119 virt_to_bus((void *)devpriv
->
120 ul_DmaBufferVirtual
[i
]);
123 if (!devpriv
->ul_DmaBufferVirtual
[0])
124 devpriv
->us_UseDma
= ADDI_DISABLE
;
126 if (devpriv
->ul_DmaBufferVirtual
[1])
127 devpriv
->b_DmaDoubleBuffer
= 1;
129 ret
= comedi_alloc_subdevices(dev
, 5);
133 /* Allocate and Initialise AI Subdevice Structures */
134 s
= &dev
->subdevices
[0];
135 dev
->read_subdev
= s
;
136 s
->type
= COMEDI_SUBD_AI
;
138 SDF_READABLE
| SDF_COMMON
| SDF_GROUND
140 if (this_board
->i_NbrAiChannel
) {
141 s
->n_chan
= this_board
->i_NbrAiChannel
;
142 devpriv
->b_SingelDiff
= 0;
144 s
->n_chan
= this_board
->i_NbrAiChannelDiff
;
145 devpriv
->b_SingelDiff
= 1;
147 s
->maxdata
= this_board
->i_AiMaxdata
;
148 s
->len_chanlist
= this_board
->i_AiChannelList
;
149 s
->range_table
= &range_apci3120_ai
;
151 /* Set the initialisation flag */
152 devpriv
->b_AiInitialisation
= 1;
154 s
->insn_config
= i_APCI3120_InsnConfigAnalogInput
;
155 s
->insn_read
= i_APCI3120_InsnReadAnalogInput
;
156 s
->do_cmdtest
= i_APCI3120_CommandTestAnalogInput
;
157 s
->do_cmd
= i_APCI3120_CommandAnalogInput
;
158 s
->cancel
= i_APCI3120_StopCyclicAcquisition
;
160 /* Allocate and Initialise AO Subdevice Structures */
161 s
= &dev
->subdevices
[1];
162 if (this_board
->i_NbrAoChannel
) {
163 s
->type
= COMEDI_SUBD_AO
;
164 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
165 s
->n_chan
= this_board
->i_NbrAoChannel
;
166 s
->maxdata
= this_board
->i_AoMaxdata
;
167 s
->len_chanlist
= this_board
->i_NbrAoChannel
;
168 s
->range_table
= &range_apci3120_ao
;
169 s
->insn_write
= i_APCI3120_InsnWriteAnalogOutput
;
171 s
->type
= COMEDI_SUBD_UNUSED
;
174 /* Allocate and Initialise DI Subdevice Structures */
175 s
= &dev
->subdevices
[2];
176 s
->type
= COMEDI_SUBD_DI
;
177 s
->subdev_flags
= SDF_READABLE
| SDF_GROUND
| SDF_COMMON
;
178 s
->n_chan
= this_board
->i_NbrDiChannel
;
180 s
->len_chanlist
= this_board
->i_NbrDiChannel
;
181 s
->range_table
= &range_digital
;
182 s
->io_bits
= 0; /* all bits input */
183 s
->insn_bits
= apci3120_di_insn_bits
;
185 /* Allocate and Initialise DO Subdevice Structures */
186 s
= &dev
->subdevices
[3];
187 s
->type
= COMEDI_SUBD_DO
;
189 SDF_READABLE
| SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
190 s
->n_chan
= this_board
->i_NbrDoChannel
;
191 s
->maxdata
= this_board
->i_DoMaxdata
;
192 s
->len_chanlist
= this_board
->i_NbrDoChannel
;
193 s
->range_table
= &range_digital
;
194 s
->io_bits
= 0xf; /* all bits output */
195 s
->insn_bits
= apci3120_do_insn_bits
;
197 /* Allocate and Initialise Timer Subdevice Structures */
198 s
= &dev
->subdevices
[4];
199 s
->type
= COMEDI_SUBD_TIMER
;
200 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
204 s
->range_table
= &range_digital
;
206 s
->insn_write
= i_APCI3120_InsnWriteTimer
;
207 s
->insn_read
= i_APCI3120_InsnReadTimer
;
208 s
->insn_config
= i_APCI3120_InsnConfigTimer
;
210 i_APCI3120_Reset(dev
);
214 static void apci3120_detach(struct comedi_device
*dev
)
216 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
217 struct addi_private
*devpriv
= dev
->private;
221 i_APCI3120_Reset(dev
);
223 free_irq(dev
->irq
, dev
);
224 if (devpriv
->ul_DmaBufferVirtual
[0]) {
225 free_pages((unsigned long)devpriv
->
226 ul_DmaBufferVirtual
[0],
227 devpriv
->ui_DmaBufferPages
[0]);
229 if (devpriv
->ul_DmaBufferVirtual
[1]) {
230 free_pages((unsigned long)devpriv
->
231 ul_DmaBufferVirtual
[1],
232 devpriv
->ui_DmaBufferPages
[1]);
237 comedi_pci_disable(pcidev
);
241 static struct comedi_driver apci3120_driver
= {
242 .driver_name
= "addi_apci_3120",
243 .module
= THIS_MODULE
,
244 .auto_attach
= apci3120_auto_attach
,
245 .detach
= apci3120_detach
,
248 static int apci3120_pci_probe(struct pci_dev
*dev
,
249 const struct pci_device_id
*ent
)
251 return comedi_pci_auto_config(dev
, &apci3120_driver
);
254 static void apci3120_pci_remove(struct pci_dev
*dev
)
256 comedi_pci_auto_unconfig(dev
);
259 static DEFINE_PCI_DEVICE_TABLE(apci3120_pci_table
) = {
260 { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD
, 0x818d) },
261 { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA_OLD
, 0x828d) },
264 MODULE_DEVICE_TABLE(pci
, apci3120_pci_table
);
266 static struct pci_driver apci3120_pci_driver
= {
267 .name
= "addi_apci_3120",
268 .id_table
= apci3120_pci_table
,
269 .probe
= apci3120_pci_probe
,
270 .remove
= apci3120_pci_remove
,
272 module_comedi_pci_driver(apci3120_driver
, apci3120_pci_driver
);
274 MODULE_AUTHOR("Comedi http://www.comedi.org");
275 MODULE_DESCRIPTION("Comedi low-level driver");
276 MODULE_LICENSE("GPL");