usbdux, usbduxfast, usbduxsigma: Drop the '.o' in module name
[comedi.git] / patches / patch-scxi
1 Index: comedi/drivers/ni_mio_common.c
2 ===================================================================
3 RCS file: /var/cvs/comedi/comedi/drivers/ni_mio_common.c,v
4 retrieving revision 1.43
5 diff -u -r1.43 ni_mio_common.c
6 --- comedi/drivers/ni_mio_common.c      2001/02/05 02:58:40     1.43
7 +++ comedi/drivers/ni_mio_common.c      2001/02/05 02:59:48
8 @@ -161,6 +161,11 @@
9  static int ni_dio(comedi_device *dev,comedi_subdevice *s,comedi_trig *it);
10  #endif
11  
12 +static int ni_serial_insn_config(comedi_device *dev,comedi_subdevice *s,
13 +                                comedi_insn *insn,lsampl_t *data);
14 +static int ni_serial_insn_bits(comedi_device *dev,comedi_subdevice *s,
15 +                              comedi_insn *insn,lsampl_t *data);
16 +
17  #ifdef USE_TRIG
18  static int ni_eeprom(comedi_device *dev,comedi_subdevice *s,comedi_trig *it);
19  #endif
20 @@ -203,6 +208,11 @@
21  #define AIMODE_SCAN            2
22  #define AIMODE_SAMPLE          3
23  
24 +/* supported serial clock intervals */
25 +#define SERIAL_DISABLED         0
26 +#define SERIAL_600NS          600
27 +#define SERIAL_1_2US         1200
28 +#define SERIAL_10US         10000
29  
30  static void ni_E_interrupt(int irq,void *d,struct pt_regs * regs)
31  {
32 @@ -1991,6 +2001,203 @@
33         return 2;
34  }
35  
36 +static int ni_serial_insn_config(comedi_device *dev,comedi_subdevice *s,
37 +                                comedi_insn *insn,lsampl_t *data)
38 +{
39 +#ifdef DEBUG_DIO
40 +       printk("SPI serial I/O Config %d\n", data[0]);
41 +#endif
42 +
43 +       if(insn->n!=1)return -EINVAL;
44 +       devpriv->serial_interval_ns = data[0];
45 +       devpriv->serial_hw_mode = 1;
46 +       devpriv->dio_control |= DIO_HW_Serial_Enable;
47 +       switch(data[0]) {
48 +       default:
49 +       case SERIAL_DISABLED:
50 +               /* Disable (or use software serial) */
51 +               devpriv->serial_hw_mode = 0;
52 +               devpriv->dio_control &= ~(DIO_HW_Serial_Enable |
53 +                                         DIO_Software_Serial_Control);
54 +               break;
55 +       case SERIAL_600NS:
56 +               /* Warning: this clock speed is too fast to reliably
57 +                  control SCXI. */
58 +               devpriv->dio_control &= ~DIO_HW_Serial_Timebase;
59 +               devpriv->clock_and_fout |= Slow_Internal_Timebase;
60 +               devpriv->clock_and_fout &= ~DIO_Serial_Out_Divide_By_2;
61 +               break;
62 +       case SERIAL_1_2US:
63 +               devpriv->dio_control &= ~DIO_HW_Serial_Timebase;
64 +               devpriv->clock_and_fout |= Slow_Internal_Timebase |
65 +                       DIO_Serial_Out_Divide_By_2;
66 +               break;
67 +       case SERIAL_10US:
68 +               devpriv->dio_control |= DIO_HW_Serial_Timebase;
69 +               devpriv->clock_and_fout |= Slow_Internal_Timebase |
70 +                       DIO_Serial_Out_Divide_By_2;
71 +               /* Note: DIO_Serial_Out_Divide_By_2 only affects
72 +                  600ns/1.2us. If you turn divide_by_2 off with the
73 +                  slow clock, you will still get 10us, except then
74 +                  all your delays are wrong. */
75 +               break;
76 +       }
77 +       win_out(devpriv->dio_control,DIO_Control_Register);
78 +       win_out(devpriv->clock_and_fout,Clock_and_FOUT_Register);
79 +       return 1;
80 +}
81 +
82 +static int ni_serial_hw_readwrite8(comedi_device *dev,comedi_subdevice *s,
83 +                                  unsigned char data_out, 
84 +                                  unsigned char *data_in)
85 +{
86 +       unsigned int status1;
87 +       int err = 0, count = 20;
88 +
89 +#ifdef DEBUG_DIO
90 +       printk("ni_serial_hw_readwrite8: outputting 0x%x\n", data_out);
91 +#endif
92 +
93 +       if(devpriv->serial_interval_ns == 0) {
94 +               err = -EINVAL;
95 +               goto Error;
96 +       }
97 +
98 +       devpriv->dio_output &= ~DIO_Serial_Data_Mask;
99 +       devpriv->dio_output |= DIO_Serial_Data_Out(data_out);
100 +       win_out(devpriv->dio_output,DIO_Output_Register);
101 +
102 +       status1 = win_in(Joint_Status_1_Register);
103 +       if(status1 & DIO_Serial_IO_In_Progress_St) {
104 +               err = -EBUSY;
105 +               goto Error;
106 +       }
107 +
108 +       devpriv->dio_control |= DIO_HW_Serial_Start;
109 +       win_out(devpriv->dio_control,DIO_Control_Register);
110 +       devpriv->dio_control &= ~DIO_HW_Serial_Start;
111 +       
112 +       /* Wait until STC says we're done, but don't loop infinitely. Also,
113 +          we don't have to keep updating the window address for this. */
114 +       ni_writew(Joint_Status_1_Register,Window_Address);
115 +       while((status1 = ni_readw(Window_Data)) & DIO_Serial_IO_In_Progress_St) {
116 +               /* Delay one bit per loop */
117 +               nanodelay(devpriv->serial_interval_ns);
118 +               if(--count < 0) {
119 +                       printk("ni_serial_hw_readwrite8: SPI serial I/O didn't finish in time!\n");
120 +                       err = -ETIME;
121 +                       goto Error;
122 +               }
123 +       }
124 +
125 +       /* Delay for last bit. This delay is absolutely necessary, because
126 +          DIO_Serial_IO_In_Progress_St goes high one bit too early. */
127 +       nanodelay(devpriv->serial_interval_ns);
128 +
129 +       if(data_in != NULL) {
130 +               *data_in = win_in(DIO_Serial_Input_Register);
131 +#ifdef DEBUG_DIO
132 +               printk("ni_serial_hw_readwrite8: inputted 0x%x\n", *data_in);
133 +#endif
134 +       }
135 +       
136 + Error:
137 +       win_out(devpriv->dio_control,DIO_Control_Register);
138 +       
139 +       return err;
140 +}
141 +
142 +static int ni_serial_sw_readwrite8(comedi_device *dev,comedi_subdevice *s,
143 +                                  unsigned char data_out, 
144 +                                  unsigned char *data_in)
145 +{
146 +       unsigned char mask, input = 0;
147 +
148 +#ifdef DEBUG_DIO
149 +       printk("ni_serial_sw_readwrite8: outputting 0x%x\n", data_out);
150 +#endif
151 +
152 +       /* Wait for one bit before transfer */
153 +       nanodelay(devpriv->serial_interval_ns);
154 +
155 +       for(mask = 0x80; mask; mask >>= 1) {
156 +               /* Output current bit; note that we cannot touch s->state
157 +                  because it is a per-subdevice field, and serial is
158 +                  a separate subdevice from DIO. */
159 +               devpriv->dio_output &= ~DIO_SDOUT;
160 +               if(data_out & mask) {
161 +                       devpriv->dio_output |= DIO_SDOUT;
162 +               }
163 +               win_out(devpriv->dio_output,DIO_Output_Register);
164 +
165 +               /* Assert SDCLK (active low, inverted), wait for half of
166 +                  the delay, deassert SDCLK, and wait for the other half. */
167 +               devpriv->dio_control |= DIO_Software_Serial_Control;
168 +               win_out(devpriv->dio_control,DIO_Control_Register);
169 +
170 +               nanodelay(devpriv->serial_interval_ns / 2);
171 +
172 +               devpriv->dio_control &= ~DIO_Software_Serial_Control;
173 +               win_out(devpriv->dio_control,DIO_Control_Register);
174 +
175 +               nanodelay(devpriv->serial_interval_ns / 2);
176 +
177 +               /* Input current bit */
178 +               if(ni_readw(DIO_Parallel_Input) & DIO_SDIN) {
179 +                       input |= mask;
180 +               }
181 +       }
182 +#ifdef DEBUG_DIO
183 +       printk("ni_serial_sw_readwrite8: inputted 0x%x\n", input);
184 +#endif
185 +       if(data_in) *data_in = input;
186 +
187 +       return 0;
188 +}
189 +
190 +static int ni_serial_insn_bits(comedi_device *dev,comedi_subdevice *s,
191 +                              comedi_insn *insn,lsampl_t *data)
192 +{
193 +       int err = insn->n;
194 +       lsampl_t data_out, data_in, num_bits;
195 +       unsigned char byteOut, byteIn;
196 +
197 +#ifdef DEBUG_DIO
198 +       printk("ni_serial_insn_bits: num_bits=0x%x data_out=0x%x\n", data[0],
199 +              data[1]);
200 +#endif
201 +
202 +       if(insn->n!=2) return -EINVAL;
203 +
204 +       num_bits = data[0];
205 +
206 +       if((num_bits % 8) != 0) return -EINVAL;
207 +
208 +       data_out = data[1];
209 +       data_in = 0;
210 +       while(num_bits > 0) {
211 +               /* Read from MSB to LSB */
212 +               data_in <<= 8;
213 +
214 +               byteOut = (data_out >> (num_bits - 8)) & 0xff;
215 +               if(devpriv->serial_hw_mode) {
216 +                       err = ni_serial_hw_readwrite8(dev,s,byteOut,&byteIn);
217 +               } else if(devpriv->serial_interval_ns > 0) {
218 +                       err = ni_serial_sw_readwrite8(dev,s,byteOut,&byteIn);
219 +               } else {
220 +                       printk("ni_serial_insn_bits: serial disabled!\n");
221 +                       return -EINVAL;
222 +               }
223 +               if(err < 0) return err;
224 +               data_in |= byteIn;
225 +
226 +               /* Write from MSB to LSB */
227 +               num_bits -= 8;
228 +       }
229 +       data[1] = data_in;
230 +       return insn->n;
231 +}
232 +
233  /*
234         HACK! 
235  
236 @@ -2031,7 +2238,7 @@
237  {
238         comedi_subdevice *s;
239         
240 -       dev->n_subdevices=7;
241 +       dev->n_subdevices=8;
242         
243         if(alloc_subdevices(dev)<0)
244                 return -ENOMEM;
245 @@ -2144,11 +2351,24 @@
246  #ifdef USE_TRIG
247         s->trig[0]=ni_eeprom;
248  #endif
249 -       
250 +
251 +       /* SPI serial I/O */
252 +       s=dev->subdevices+7;
253 +       s->type=COMEDI_SUBD_SERIAL;
254 +       s->subdev_flags=SDF_READABLE|SDF_WRITEABLE|SDF_INTERNAL;
255 +       s->n_chan=1;
256 +       s->maxdata=0xff;
257 +       s->insn_bits=ni_serial_insn_bits;
258 +       s->insn_config=ni_serial_insn_config;
259 +
260 +       /* serial configuration */
261 +       devpriv->serial_interval_ns = 0;
262 +       devpriv->serial_hw_mode = 0;
263 +
264         /* ai configuration */
265         ni_ai_reset(dev,dev->subdevices+0);
266 -       win_out(0x1ba0,Clock_and_FOUT_Register);
267 -
268 +       devpriv->clock_and_fout = 0x1ba0;
269 +       win_out(devpriv->clock_and_fout,Clock_and_FOUT_Register);
270  
271         /* analog output configuration */
272         
273 Index: include/linux/comedi.h
274 ===================================================================
275 RCS file: /var/cvs/comedi/include/linux/comedi.h,v
276 retrieving revision 1.5
277 diff -u -r1.5 comedi.h
278 --- include/linux/comedi.h      2001/01/30 20:19:39     1.5
279 +++ include/linux/comedi.h      2001/02/05 02:59:50
280 @@ -148,7 +148,7 @@
281  #define COMEDI_SUBD_MEMORY              8      /* memory, EEPROM, DPRAM */
282  #define COMEDI_SUBD_CALIB               9      /* calibration DACs */
283  #define COMEDI_SUBD_PROC                10     /* processor, DSP */
284 -
285 +#define COMEDI_SUBD_SERIAL              11      /* SPI serial I/O */
286  
287  #define COMEDI_INPUT                   0
288  #define COMEDI_OUTPUT                  1
289 Index: include/linux/comedidev.h
290 ===================================================================
291 RCS file: /var/cvs/comedi/include/linux/comedidev.h,v
292 retrieving revision 1.8
293 diff -u -r1.8 comedidev.h
294 --- include/linux/comedidev.h   2001/02/05 02:09:19     1.8
295 +++ include/linux/comedidev.h   2001/02/05 02:59:51
296 @@ -276,6 +276,18 @@
297         return 0;
298  }
299  
300 +static inline int nanodelay(unsigned long ns)
301 +{
302 +       /* We round up, so the result should always be longer than the
303 +        * specified time. It's probably not much more precise than
304 +        * using udelay(). Hopefully, one day Linux will have an
305 +        * nanodelay() function. */
306 +       unsigned long loops_per_us = (loops_per_sec + 999999) / 1000000;
307 +       unsigned long loops = ((ns * loops_per_us) + 999) / 1000; 
308 +       /* printk("nanodelay: ns=%ld loops=%ld\n", ns, loops); */
309 +       __delay(loops);
310 +}
311 +
312  
313  #ifdef LINUX_V20
314  extern struct symbol_table comedi_syms;