aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/comedi/drivers/icp_multi.c279
1 files changed, 102 insertions, 177 deletions
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index 67b6f5aa1885..0f63fc04b5fd 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -121,15 +121,6 @@ static const char range_codes_analog[] = { 0x00, 0x20, 0x10, 0x30 };
121 121
122/* 122/*
123============================================================================== 123==============================================================================
124 Forward declarations
125==============================================================================
126*/
127static int icp_multi_attach(struct comedi_device *dev,
128 struct comedi_devconfig *it);
129static int icp_multi_detach(struct comedi_device *dev);
130
131/*
132==============================================================================
133 Data & Structure declarations 124 Data & Structure declarations
134============================================================================== 125==============================================================================
135*/ 126*/
@@ -154,48 +145,6 @@ struct boardtype {
154 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */ 145 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
155}; 146};
156 147
157static const struct boardtype boardtypes[] = {
158 {"icp_multi", /* Driver name */
159 DEVICE_ID, /* PCI device ID */
160 IORANGE_ICP_MULTI, /* I/O range length */
161 1, /* 1=Card supports interrupts */
162 TYPE_ICP_MULTI, /* Card type = ICP MULTI */
163 16, /* Num of A/D channels */
164 8, /* Num of A/D channels in diff mode */
165 4, /* Num of D/A channels */
166 16, /* Num of digital inputs */
167 8, /* Num of digital outputs */
168 4, /* Num of counters */
169 0x0fff, /* Resolution of A/D */
170 0x0fff, /* Resolution of D/A */
171 &range_analog, /* Rangelist for A/D */
172 range_codes_analog, /* Range codes for programming */
173 &range_analog}, /* Rangelist for D/A */
174};
175
176static struct comedi_driver driver_icp_multi = {
177 .driver_name = "icp_multi",
178 .module = THIS_MODULE,
179 .attach = icp_multi_attach,
180 .detach = icp_multi_detach,
181 .num_names = ARRAY_SIZE(boardtypes),
182 .board_name = &boardtypes[0].name,
183 .offset = sizeof(struct boardtype),
184};
185
186static int __init driver_icp_multi_init_module(void)
187{
188 return comedi_driver_register(&driver_icp_multi);
189}
190
191static void __exit driver_icp_multi_cleanup_module(void)
192{
193 comedi_driver_unregister(&driver_icp_multi);
194}
195
196module_init(driver_icp_multi_init_module);
197module_exit(driver_icp_multi_cleanup_module);
198
199struct icp_multi_private { 148struct icp_multi_private {
200 struct pcilst_struct *card; /* pointer to card */ 149 struct pcilst_struct *card; /* pointer to card */
201 char valid; /* card is usable */ 150 char valid; /* card is usable */
@@ -220,25 +169,81 @@ struct icp_multi_private {
220 169
221/* 170/*
222============================================================================== 171==============================================================================
223 More forward declarations 172
173Name: setup_channel_list
174
175Description:
176 This function sets the appropriate channel selection,
177 differential input mode and range bits in the ADC Command/
178 Status register.
179
180Parameters:
181 struct comedi_device *dev Pointer to current service structure
182 struct comedi_subdevice *s Pointer to current subdevice structure
183 unsigned int *chanlist Pointer to packed channel list
184 unsigned int n_chan Number of channels to scan
185
186Returns:Void
187
224============================================================================== 188==============================================================================
225*/ 189*/
226
227#if 0
228static int check_channel_list(struct comedi_device *dev,
229 struct comedi_subdevice *s,
230 unsigned int *chanlist, unsigned int n_chan);
231#endif
232static void setup_channel_list(struct comedi_device *dev, 190static void setup_channel_list(struct comedi_device *dev,
233 struct comedi_subdevice *s, 191 struct comedi_subdevice *s,
234 unsigned int *chanlist, unsigned int n_chan); 192 unsigned int *chanlist, unsigned int n_chan)
235static int icp_multi_reset(struct comedi_device *dev); 193{
194 unsigned int i, range, chanprog;
195 unsigned int diff;
236 196
237/* 197#ifdef ICP_MULTI_EXTDEBUG
238============================================================================== 198 printk(KERN_DEBUG
239 Functions 199 "icp multi EDBG: setup_channel_list(...,%d)\n", n_chan);
240============================================================================== 200#endif
241*/ 201 devpriv->act_chanlist_len = n_chan;
202 devpriv->act_chanlist_pos = 0;
203
204 for (i = 0; i < n_chan; i++) {
205 /* Get channel */
206 chanprog = CR_CHAN(chanlist[i]);
207
208 /* Determine if it is a differential channel (Bit 15 = 1) */
209 if (CR_AREF(chanlist[i]) == AREF_DIFF) {
210 diff = 1;
211 chanprog &= 0x0007;
212 } else {
213 diff = 0;
214 chanprog &= 0x000f;
215 }
216
217 /* Clear channel, range and input mode bits
218 * in A/D command/status register */
219 devpriv->AdcCmdStatus &= 0xf00f;
220
221 /* Set channel number and differential mode status bit */
222 if (diff) {
223 /* Set channel number, bits 9-11 & mode, bit 6 */
224 devpriv->AdcCmdStatus |= (chanprog << 9);
225 devpriv->AdcCmdStatus |= ADC_DI;
226 } else
227 /* Set channel number, bits 8-11 */
228 devpriv->AdcCmdStatus |= (chanprog << 8);
229
230 /* Get range for current channel */
231 range = this_board->rangecode[CR_RANGE(chanlist[i])];
232 /* Set range. bits 4-5 */
233 devpriv->AdcCmdStatus |= range;
234
235 /* Output channel, range, mode to ICP Multi */
236 writew(devpriv->AdcCmdStatus,
237 devpriv->io_addr + ICP_MULTI_ADC_CSR);
238
239#ifdef ICP_MULTI_EXTDEBUG
240 printk(KERN_DEBUG
241 "GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
242 devpriv->act_chanlist[i]);
243#endif
244 }
245
246}
242 247
243/* 248/*
244============================================================================== 249==============================================================================
@@ -762,84 +767,6 @@ static int check_channel_list(struct comedi_device *dev,
762/* 767/*
763============================================================================== 768==============================================================================
764 769
765Name: setup_channel_list
766
767Description:
768 This function sets the appropriate channel selection,
769 differential input mode and range bits in the ADC Command/
770 Status register.
771
772Parameters:
773 struct comedi_device *dev Pointer to current service structure
774 struct comedi_subdevice *s Pointer to current subdevice structure
775 unsigned int *chanlist Pointer to packed channel list
776 unsigned int n_chan Number of channels to scan
777
778Returns:Void
779
780==============================================================================
781*/
782static void setup_channel_list(struct comedi_device *dev,
783 struct comedi_subdevice *s,
784 unsigned int *chanlist, unsigned int n_chan)
785{
786 unsigned int i, range, chanprog;
787 unsigned int diff;
788
789#ifdef ICP_MULTI_EXTDEBUG
790 printk(KERN_DEBUG
791 "icp multi EDBG: setup_channel_list(...,%d)\n", n_chan);
792#endif
793 devpriv->act_chanlist_len = n_chan;
794 devpriv->act_chanlist_pos = 0;
795
796 for (i = 0; i < n_chan; i++) {
797 /* Get channel */
798 chanprog = CR_CHAN(chanlist[i]);
799
800 /* Determine if it is a differential channel (Bit 15 = 1) */
801 if (CR_AREF(chanlist[i]) == AREF_DIFF) {
802 diff = 1;
803 chanprog &= 0x0007;
804 } else {
805 diff = 0;
806 chanprog &= 0x000f;
807 }
808
809 /* Clear channel, range and input mode bits
810 * in A/D command/status register */
811 devpriv->AdcCmdStatus &= 0xf00f;
812
813 /* Set channel number and differential mode status bit */
814 if (diff) {
815 /* Set channel number, bits 9-11 & mode, bit 6 */
816 devpriv->AdcCmdStatus |= (chanprog << 9);
817 devpriv->AdcCmdStatus |= ADC_DI;
818 } else
819 /* Set channel number, bits 8-11 */
820 devpriv->AdcCmdStatus |= (chanprog << 8);
821
822 /* Get range for current channel */
823 range = this_board->rangecode[CR_RANGE(chanlist[i])];
824 /* Set range. bits 4-5 */
825 devpriv->AdcCmdStatus |= range;
826
827 /* Output channel, range, mode to ICP Multi */
828 writew(devpriv->AdcCmdStatus,
829 devpriv->io_addr + ICP_MULTI_ADC_CSR);
830
831#ifdef ICP_MULTI_EXTDEBUG
832 printk(KERN_DEBUG
833 "GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
834 devpriv->act_chanlist[i]);
835#endif
836 }
837
838}
839
840/*
841==============================================================================
842
843Name: icp_multi_reset 770Name: icp_multi_reset
844 771
845Description: 772Description:
@@ -895,23 +822,6 @@ static int icp_multi_reset(struct comedi_device *dev)
895 return 0; 822 return 0;
896} 823}
897 824
898/*
899==============================================================================
900
901Name: icp_multi_attach
902
903Description:
904 This function sets up all the appropriate data for the current
905 device.
906
907Parameters:
908 struct comedi_device *dev Pointer to current device structure
909 struct comedi_devconfig *it Pointer to current device configuration
910
911Returns:int 0 = success
912
913==============================================================================
914*/
915static int icp_multi_attach(struct comedi_device *dev, 825static int icp_multi_attach(struct comedi_device *dev,
916 struct comedi_devconfig *it) 826 struct comedi_devconfig *it)
917{ 827{
@@ -1097,25 +1007,8 @@ static int icp_multi_attach(struct comedi_device *dev,
1097 return 0; 1007 return 0;
1098} 1008}
1099 1009
1100/*
1101==============================================================================
1102
1103Name: icp_multi_detach
1104
1105Description:
1106 This function releases all the resources used by the current
1107 device.
1108
1109Parameters:
1110 struct comedi_device *dev Pointer to current device structure
1111
1112Returns:int 0 = success
1113
1114==============================================================================
1115*/
1116static int icp_multi_detach(struct comedi_device *dev) 1010static int icp_multi_detach(struct comedi_device *dev)
1117{ 1011{
1118
1119 if (dev->private) 1012 if (dev->private)
1120 if (devpriv->valid) 1013 if (devpriv->valid)
1121 icp_multi_reset(dev); 1014 icp_multi_reset(dev);
@@ -1135,6 +1028,38 @@ static int icp_multi_detach(struct comedi_device *dev)
1135 return 0; 1028 return 0;
1136} 1029}
1137 1030
1031static const struct boardtype boardtypes[] = {
1032 {
1033 .name = "icp_multi",
1034 .device_id = DEVICE_ID,
1035 .iorange = IORANGE_ICP_MULTI,
1036 .have_irq = 1,
1037 .cardtype = TYPE_ICP_MULTI,
1038 .n_aichan = 16,
1039 .n_aichand = 8,
1040 .n_aochan = 4,
1041 .n_dichan = 16,
1042 .n_dochan = 8,
1043 .n_ctrs = 4,
1044 .ai_maxdata = 0x0fff,
1045 .ao_maxdata = 0x0fff,
1046 .rangelist_ai = &range_analog,
1047 .rangecode = range_codes_analog,
1048 .rangelist_ao = &range_analog,
1049 },
1050};
1051
1052static struct comedi_driver icp_multi_driver = {
1053 .driver_name = "icp_multi",
1054 .module = THIS_MODULE,
1055 .attach = icp_multi_attach,
1056 .detach = icp_multi_detach,
1057 .num_names = ARRAY_SIZE(boardtypes),
1058 .board_name = &boardtypes[0].name,
1059 .offset = sizeof(struct boardtype),
1060};
1061module_comedi_driver(icp_multi_driver);
1062
1138MODULE_AUTHOR("Comedi http://www.comedi.org"); 1063MODULE_AUTHOR("Comedi http://www.comedi.org");
1139MODULE_DESCRIPTION("Comedi low-level driver"); 1064MODULE_DESCRIPTION("Comedi low-level driver");
1140MODULE_LICENSE("GPL"); 1065MODULE_LICENSE("GPL");