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
->ul_DmaBufferHw
[i
] =
107 virt_to_bus((void *)devpriv
->
108 ul_DmaBufferVirtual
[i
]);
111 if (!devpriv
->ul_DmaBufferVirtual
[0])
112 devpriv
->us_UseDma
= ADDI_DISABLE
;
114 if (devpriv
->ul_DmaBufferVirtual
[1])
115 devpriv
->b_DmaDoubleBuffer
= 1;
117 ret
= comedi_alloc_subdevices(dev
, 5);
121 /* Allocate and Initialise AI Subdevice Structures */
122 s
= &dev
->subdevices
[0];
123 dev
->read_subdev
= s
;
124 s
->type
= COMEDI_SUBD_AI
;
126 SDF_READABLE
| SDF_COMMON
| SDF_GROUND
128 if (this_board
->i_NbrAiChannel
) {
129 s
->n_chan
= this_board
->i_NbrAiChannel
;
130 devpriv
->b_SingelDiff
= 0;
132 s
->n_chan
= this_board
->i_NbrAiChannelDiff
;
133 devpriv
->b_SingelDiff
= 1;
135 s
->maxdata
= this_board
->i_AiMaxdata
;
136 s
->len_chanlist
= this_board
->i_AiChannelList
;
137 s
->range_table
= &range_apci3120_ai
;
139 s
->insn_config
= i_APCI3120_InsnConfigAnalogInput
;
140 s
->insn_read
= i_APCI3120_InsnReadAnalogInput
;
141 s
->do_cmdtest
= i_APCI3120_CommandTestAnalogInput
;
142 s
->do_cmd
= i_APCI3120_CommandAnalogInput
;
143 s
->cancel
= i_APCI3120_StopCyclicAcquisition
;
145 /* Allocate and Initialise AO Subdevice Structures */
146 s
= &dev
->subdevices
[1];
147 if (this_board
->i_NbrAoChannel
) {
148 s
->type
= COMEDI_SUBD_AO
;
149 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
150 s
->n_chan
= this_board
->i_NbrAoChannel
;
151 s
->maxdata
= this_board
->i_AoMaxdata
;
152 s
->len_chanlist
= this_board
->i_NbrAoChannel
;
153 s
->range_table
= &range_apci3120_ao
;
154 s
->insn_write
= i_APCI3120_InsnWriteAnalogOutput
;
156 s
->type
= COMEDI_SUBD_UNUSED
;
159 /* Allocate and Initialise DI Subdevice Structures */
160 s
= &dev
->subdevices
[2];
161 s
->type
= COMEDI_SUBD_DI
;
162 s
->subdev_flags
= SDF_READABLE
| SDF_GROUND
| SDF_COMMON
;
163 s
->n_chan
= this_board
->i_NbrDiChannel
;
165 s
->len_chanlist
= this_board
->i_NbrDiChannel
;
166 s
->range_table
= &range_digital
;
167 s
->io_bits
= 0; /* all bits input */
168 s
->insn_bits
= apci3120_di_insn_bits
;
170 /* Allocate and Initialise DO Subdevice Structures */
171 s
= &dev
->subdevices
[3];
172 s
->type
= COMEDI_SUBD_DO
;
174 SDF_READABLE
| SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
175 s
->n_chan
= this_board
->i_NbrDoChannel
;
176 s
->maxdata
= this_board
->i_DoMaxdata
;
177 s
->len_chanlist
= this_board
->i_NbrDoChannel
;
178 s
->range_table
= &range_digital
;
179 s
->io_bits
= 0xf; /* all bits output */
180 s
->insn_bits
= apci3120_do_insn_bits
;
182 /* Allocate and Initialise Timer Subdevice Structures */
183 s
= &dev
->subdevices
[4];
184 s
->type
= COMEDI_SUBD_TIMER
;
185 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
| SDF_COMMON
;
189 s
->range_table
= &range_digital
;
191 s
->insn_write
= i_APCI3120_InsnWriteTimer
;
192 s
->insn_read
= i_APCI3120_InsnReadTimer
;
193 s
->insn_config
= i_APCI3120_InsnConfigTimer
;
195 i_APCI3120_Reset(dev
);
199 static void apci3120_detach(struct comedi_device
*dev
)
201 struct addi_private
*devpriv
= dev
->private;
205 i_APCI3120_Reset(dev
);
207 free_irq(dev
->irq
, dev
);
208 if (devpriv
->ul_DmaBufferVirtual
[0]) {
209 free_pages((unsigned long)devpriv
->
210 ul_DmaBufferVirtual
[0],
211 devpriv
->ui_DmaBufferPages
[0]);
213 if (devpriv
->ul_DmaBufferVirtual
[1]) {
214 free_pages((unsigned long)devpriv
->
215 ul_DmaBufferVirtual
[1],
216 devpriv
->ui_DmaBufferPages
[1]);
219 comedi_pci_disable(dev
);
222 static struct comedi_driver apci3120_driver
= {
223 .driver_name
= "addi_apci_3120",
224 .module
= THIS_MODULE
,
225 .auto_attach
= apci3120_auto_attach
,
226 .detach
= apci3120_detach
,
229 static int apci3120_pci_probe(struct pci_dev
*dev
,
230 const struct pci_device_id
*id
)
232 return comedi_pci_auto_config(dev
, &apci3120_driver
, id
->driver_data
);
235 static DEFINE_PCI_DEVICE_TABLE(apci3120_pci_table
) = {
236 { PCI_VDEVICE(AMCC
, 0x818d), BOARD_APCI3120
},
237 { PCI_VDEVICE(AMCC
, 0x828d), BOARD_APCI3001
},
240 MODULE_DEVICE_TABLE(pci
, apci3120_pci_table
);
242 static struct pci_driver apci3120_pci_driver
= {
243 .name
= "addi_apci_3120",
244 .id_table
= apci3120_pci_table
,
245 .probe
= apci3120_pci_probe
,
246 .remove
= comedi_pci_auto_unconfig
,
248 module_comedi_pci_driver(apci3120_driver
, apci3120_pci_driver
);
250 MODULE_AUTHOR("Comedi http://www.comedi.org");
251 MODULE_DESCRIPTION("Comedi low-level driver");
252 MODULE_LICENSE("GPL");