3 #include "../comedidev.h"
5 #include "amcc_s5933.h"
7 #include "addi-data/addi_common.h"
9 #include "addi-data/hwdrv_apci3120.c"
11 enum apci3120_boardid
{
16 static const struct addi_board apci3120_boardtypes
[] = {
18 .pc_DriverName
= "apci3120",
20 .i_NbrAiChannelDiff
= 8,
21 .i_AiChannelList
= 16,
23 .i_AiMaxdata
= 0xffff,
24 .i_AoMaxdata
= 0x3fff,
28 .interrupt
= v_APCI3120_Interrupt
,
31 .pc_DriverName
= "apci3001",
33 .i_NbrAiChannelDiff
= 8,
34 .i_AiChannelList
= 16,
39 .interrupt
= v_APCI3120_Interrupt
,
43 static irqreturn_t
v_ADDI_Interrupt(int irq
, void *d
)
45 struct comedi_device
*dev
= d
;
46 const struct addi_board
*this_board
= comedi_board(dev
);
48 this_board
->interrupt(irq
, d
);
52 static int apci3120_auto_attach(struct comedi_device
*dev
,
53 unsigned long context
)
55 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
56 const struct addi_board
*this_board
= NULL
;
57 struct addi_private
*devpriv
;
58 struct comedi_subdevice
*s
;
61 if (context
< ARRAY_SIZE(apci3120_boardtypes
))
62 this_board
= &apci3120_boardtypes
[context
];
65 dev
->board_ptr
= this_board
;
66 dev
->board_name
= this_board
->pc_DriverName
;
68 devpriv
= kzalloc(sizeof(*devpriv
), GFP_KERNEL
);
71 dev
->private = devpriv
;
73 ret
= comedi_pci_enable(dev
);
76 pci_set_master(pcidev
);
78 dev
->iobase
= pci_resource_start(pcidev
, 1);
79 devpriv
->iobase
= dev
->iobase
;
80 devpriv
->i_IobaseAmcc
= pci_resource_start(pcidev
, 0);
81 devpriv
->i_IobaseAddon
= pci_resource_start(pcidev
, 2);
82 devpriv
->i_IobaseReserved
= pci_resource_start(pcidev
, 3);
84 if (pcidev
->irq
> 0) {
85 ret
= request_irq(pcidev
->irq
, v_ADDI_Interrupt
, IRQF_SHARED
,
86 dev
->board_name
, dev
);
88 dev
->irq
= pcidev
->irq
;
91 devpriv
->us_UseDma
= ADDI_ENABLE
;
93 /* Allocate DMA buffers */
94 devpriv
->b_DmaDoubleBuffer
= 0;
95 for (i
= 0; i
< 2; i
++) {
96 for (pages
= 4; pages
>= 0; pages
--) {
97 devpriv
->ul_DmaBufferVirtual
[i
] =
98 (void *) __get_free_pages(GFP_KERNEL
, pages
);
100 if (devpriv
->ul_DmaBufferVirtual
[i
])
103 if (devpriv
->ul_DmaBufferVirtual
[i
]) {
104 devpriv
->ui_DmaBufferPages
[i
] = pages
;
105 devpriv
->ui_DmaBufferSize
[i
] = PAGE_SIZE
* pages
;
106 devpriv
->ui_DmaBufferSamples
[i
] =
107 devpriv
->ui_DmaBufferSize
[i
] >> 1;
108 devpriv
->ul_DmaBufferHw
[i
] =
109 virt_to_bus((void *)devpriv
->
110 ul_DmaBufferVirtual
[i
]);
113 if (!devpriv
->ul_DmaBufferVirtual
[0])
114 devpriv
->us_UseDma
= ADDI_DISABLE
;
116 if (devpriv
->ul_DmaBufferVirtual
[1])
117 devpriv
->b_DmaDoubleBuffer
= 1;
119 ret
= comedi_alloc_subdevices(dev
, 5);
123 /* Allocate and Initialise AI Subdevice Structures */
124 s
= &dev
->subdevices
[0];
125 dev
->read_subdev
= s
;
126 s
->type
= COMEDI_SUBD_AI
;
128 SDF_READABLE
| SDF_COMMON
| SDF_GROUND
130 if (this_board
->i_NbrAiChannel
) {
131 s
->n_chan
= this_board
->i_NbrAiChannel
;
132 devpriv
->b_SingelDiff
= 0;
134 s
->n_chan
= this_board
->i_NbrAiChannelDiff
;
135 devpriv
->b_SingelDiff
= 1;
137 s
->maxdata
= this_board
->i_AiMaxdata
;
138 s
->len_chanlist
= this_board
->i_AiChannelList
;
139 s
->range_table
= &range_apci3120_ai
;
141 /* Set the initialisation flag */
142 devpriv
->b_AiInitialisation
= 1;
144 s
->insn_config
= i_APCI3120_InsnConfigAnalogInput
;
145 s
->insn_read
= i_APCI3120_InsnReadAnalogInput
;
146 s
->do_cmdtest
= i_APCI3120_CommandTestAnalogInput
;
147 s
->do_cmd
= i_APCI3120_CommandAnalogInput
;
148 s
->cancel
= i_APCI3120_StopCyclicAcquisition
;
150 /* Allocate and Initialise AO Subdevice Structures */
151 s
= &dev
->subdevices
[1];
152 if (this_board
->i_NbrAoChannel
) {
153 s
->type
= COMEDI_SUBD_AO
;
154 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
155 s
->n_chan
= this_board
->i_NbrAoChannel
;
156 s
->maxdata
= this_board
->i_AoMaxdata
;
157 s
->len_chanlist
= this_board
->i_NbrAoChannel
;
158 s
->range_table
= &range_apci3120_ao
;
159 s
->insn_write
= i_APCI3120_InsnWriteAnalogOutput
;
161 s
->type
= COMEDI_SUBD_UNUSED
;
164 /* Allocate and Initialise DI Subdevice Structures */
165 s
= &dev
->subdevices
[2];
166 s
->type
= COMEDI_SUBD_DI
;
167 s
->subdev_flags
= SDF_READABLE
| SDF_GROUND
| SDF_COMMON
;
168 s
->n_chan
= this_board
->i_NbrDiChannel
;
170 s
->len_chanlist
= this_board
->i_NbrDiChannel
;
171 s
->range_table
= &range_digital
;
172 s
->io_bits
= 0; /* all bits input */
173 s
->insn_bits
= apci3120_di_insn_bits
;
175 /* Allocate and Initialise DO Subdevice Structures */
176 s
= &dev
->subdevices
[3];
177 s
->type
= COMEDI_SUBD_DO
;
179 SDF_READABLE
| SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
180 s
->n_chan
= this_board
->i_NbrDoChannel
;
181 s
->maxdata
= this_board
->i_DoMaxdata
;
182 s
->len_chanlist
= this_board
->i_NbrDoChannel
;
183 s
->range_table
= &range_digital
;
184 s
->io_bits
= 0xf; /* all bits output */
185 s
->insn_bits
= apci3120_do_insn_bits
;
187 /* Allocate and Initialise Timer Subdevice Structures */
188 s
= &dev
->subdevices
[4];
189 s
->type
= COMEDI_SUBD_TIMER
;
190 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
194 s
->range_table
= &range_digital
;
196 s
->insn_write
= i_APCI3120_InsnWriteTimer
;
197 s
->insn_read
= i_APCI3120_InsnReadTimer
;
198 s
->insn_config
= i_APCI3120_InsnConfigTimer
;
200 i_APCI3120_Reset(dev
);
204 static void apci3120_detach(struct comedi_device
*dev
)
206 struct addi_private
*devpriv
= dev
->private;
210 i_APCI3120_Reset(dev
);
212 free_irq(dev
->irq
, dev
);
213 if (devpriv
->ul_DmaBufferVirtual
[0]) {
214 free_pages((unsigned long)devpriv
->
215 ul_DmaBufferVirtual
[0],
216 devpriv
->ui_DmaBufferPages
[0]);
218 if (devpriv
->ul_DmaBufferVirtual
[1]) {
219 free_pages((unsigned long)devpriv
->
220 ul_DmaBufferVirtual
[1],
221 devpriv
->ui_DmaBufferPages
[1]);
224 comedi_pci_disable(dev
);
227 static struct comedi_driver apci3120_driver
= {
228 .driver_name
= "addi_apci_3120",
229 .module
= THIS_MODULE
,
230 .auto_attach
= apci3120_auto_attach
,
231 .detach
= apci3120_detach
,
234 static int apci3120_pci_probe(struct pci_dev
*dev
,
235 const struct pci_device_id
*id
)
237 return comedi_pci_auto_config(dev
, &apci3120_driver
, id
->driver_data
);
240 static DEFINE_PCI_DEVICE_TABLE(apci3120_pci_table
) = {
241 { PCI_VDEVICE(AMCC
, 0x818d), BOARD_APCI3120
},
242 { PCI_VDEVICE(AMCC
, 0x828d), BOARD_APCI3001
},
245 MODULE_DEVICE_TABLE(pci
, apci3120_pci_table
);
247 static struct pci_driver apci3120_pci_driver
= {
248 .name
= "addi_apci_3120",
249 .id_table
= apci3120_pci_table
,
250 .probe
= apci3120_pci_probe
,
251 .remove
= comedi_pci_auto_unconfig
,
253 module_comedi_pci_driver(apci3120_driver
, apci3120_pci_driver
);
255 MODULE_AUTHOR("Comedi http://www.comedi.org");
256 MODULE_DESCRIPTION("Comedi low-level driver");
257 MODULE_LICENSE("GPL");