Merge tag 'tegra-for-3.8-fixes-for-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[firefly-linux-kernel-4.4.55.git] / drivers / staging / comedi / drivers.c
1 /*
2     module/drivers.c
3     functions for manipulating drivers
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23
24 #include <linux/device.h>
25 #include <linux/module.h>
26 #include <linux/pci.h>
27 #include <linux/usb.h>
28 #include <linux/errno.h>
29 #include <linux/kconfig.h>
30 #include <linux/kernel.h>
31 #include <linux/sched.h>
32 #include <linux/fcntl.h>
33 #include <linux/delay.h>
34 #include <linux/ioport.h>
35 #include <linux/mm.h>
36 #include <linux/slab.h>
37 #include <linux/highmem.h>      /* for SuSE brokenness */
38 #include <linux/vmalloc.h>
39 #include <linux/cdev.h>
40 #include <linux/dma-mapping.h>
41 #include <linux/io.h>
42
43 #include "comedidev.h"
44 #include "comedi_internal.h"
45
46 static int postconfig(struct comedi_device *dev);
47 static int insn_rw_emulate_bits(struct comedi_device *dev,
48                                 struct comedi_subdevice *s,
49                                 struct comedi_insn *insn, unsigned int *data);
50 static void *comedi_recognize(struct comedi_driver *driv, const char *name);
51 static void comedi_report_boards(struct comedi_driver *driv);
52 static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s);
53
54 struct comedi_driver *comedi_drivers;
55
56 int comedi_alloc_subdevices(struct comedi_device *dev, int num_subdevices)
57 {
58         struct comedi_subdevice *s;
59         int i;
60
61         if (num_subdevices < 1)
62                 return -EINVAL;
63
64         s = kcalloc(num_subdevices, sizeof(*s), GFP_KERNEL);
65         if (!s)
66                 return -ENOMEM;
67         dev->subdevices = s;
68         dev->n_subdevices = num_subdevices;
69
70         for (i = 0; i < num_subdevices; ++i) {
71                 s = &dev->subdevices[i];
72                 s->device = dev;
73                 s->async_dma_dir = DMA_NONE;
74                 spin_lock_init(&s->spin_lock);
75                 s->minor = -1;
76         }
77         return 0;
78 }
79 EXPORT_SYMBOL_GPL(comedi_alloc_subdevices);
80
81 static void cleanup_device(struct comedi_device *dev)
82 {
83         int i;
84         struct comedi_subdevice *s;
85
86         if (dev->subdevices) {
87                 for (i = 0; i < dev->n_subdevices; i++) {
88                         s = &dev->subdevices[i];
89                         comedi_free_subdevice_minor(s);
90                         if (s->async) {
91                                 comedi_buf_alloc(dev, s, 0);
92                                 kfree(s->async);
93                         }
94                 }
95                 kfree(dev->subdevices);
96                 dev->subdevices = NULL;
97                 dev->n_subdevices = 0;
98         }
99         kfree(dev->private);
100         dev->private = NULL;
101         dev->driver = NULL;
102         dev->board_name = NULL;
103         dev->board_ptr = NULL;
104         dev->iobase = 0;
105         dev->irq = 0;
106         dev->read_subdev = NULL;
107         dev->write_subdev = NULL;
108         dev->open = NULL;
109         dev->close = NULL;
110         comedi_set_hw_dev(dev, NULL);
111 }
112
113 static void __comedi_device_detach(struct comedi_device *dev)
114 {
115         dev->attached = 0;
116         if (dev->driver)
117                 dev->driver->detach(dev);
118         else
119                 dev_warn(dev->class_dev,
120                          "BUG: dev->driver=NULL in comedi_device_detach()\n");
121         cleanup_device(dev);
122 }
123
124 void comedi_device_detach(struct comedi_device *dev)
125 {
126         if (!dev->attached)
127                 return;
128         __comedi_device_detach(dev);
129 }
130
131 /* do a little post-config cleanup */
132 /* called with module refcount incremented, decrements it */
133 static int comedi_device_postconfig(struct comedi_device *dev)
134 {
135         int ret = postconfig(dev);
136         module_put(dev->driver->module);
137         if (ret < 0) {
138                 __comedi_device_detach(dev);
139                 return ret;
140         }
141         if (!dev->board_name) {
142                 dev_warn(dev->class_dev, "BUG: dev->board_name=NULL\n");
143                 dev->board_name = "BUG";
144         }
145         smp_wmb();
146         dev->attached = 1;
147         return 0;
148 }
149
150 int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
151 {
152         struct comedi_driver *driv;
153         int ret;
154
155         if (dev->attached)
156                 return -EBUSY;
157
158         for (driv = comedi_drivers; driv; driv = driv->next) {
159                 if (!try_module_get(driv->module))
160                         continue;
161                 if (driv->num_names) {
162                         dev->board_ptr = comedi_recognize(driv, it->board_name);
163                         if (dev->board_ptr)
164                                 break;
165                 } else if (strcmp(driv->driver_name, it->board_name) == 0)
166                         break;
167                 module_put(driv->module);
168         }
169         if (driv == NULL) {
170                 /*  recognize has failed if we get here */
171                 /*  report valid board names before returning error */
172                 for (driv = comedi_drivers; driv; driv = driv->next) {
173                         if (!try_module_get(driv->module))
174                                 continue;
175                         comedi_report_boards(driv);
176                         module_put(driv->module);
177                 }
178                 return -EIO;
179         }
180         if (driv->attach == NULL) {
181                 /* driver does not support manual configuration */
182                 dev_warn(dev->class_dev,
183                          "driver '%s' does not support attach using comedi_config\n",
184                          driv->driver_name);
185                 module_put(driv->module);
186                 return -ENOSYS;
187         }
188         /* initialize dev->driver here so
189          * comedi_error() can be called from attach */
190         dev->driver = driv;
191         ret = driv->attach(dev, it);
192         if (ret < 0) {
193                 module_put(dev->driver->module);
194                 __comedi_device_detach(dev);
195                 return ret;
196         }
197         return comedi_device_postconfig(dev);
198 }
199
200 int comedi_driver_register(struct comedi_driver *driver)
201 {
202         driver->next = comedi_drivers;
203         comedi_drivers = driver;
204
205         return 0;
206 }
207 EXPORT_SYMBOL(comedi_driver_register);
208
209 int comedi_driver_unregister(struct comedi_driver *driver)
210 {
211         struct comedi_driver *prev;
212         int i;
213
214         /* check for devices using this driver */
215         for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
216                 struct comedi_device_file_info *dev_file_info =
217                     comedi_get_device_file_info(i);
218                 struct comedi_device *dev;
219
220                 if (dev_file_info == NULL)
221                         continue;
222                 dev = dev_file_info->device;
223
224                 mutex_lock(&dev->mutex);
225                 if (dev->attached && dev->driver == driver) {
226                         if (dev->use_count)
227                                 dev_warn(dev->class_dev,
228                                          "BUG! detaching device with use_count=%d\n",
229                                          dev->use_count);
230                         comedi_device_detach(dev);
231                 }
232                 mutex_unlock(&dev->mutex);
233         }
234
235         if (comedi_drivers == driver) {
236                 comedi_drivers = driver->next;
237                 return 0;
238         }
239
240         for (prev = comedi_drivers; prev->next; prev = prev->next) {
241                 if (prev->next == driver) {
242                         prev->next = driver->next;
243                         return 0;
244                 }
245         }
246         return -EINVAL;
247 }
248 EXPORT_SYMBOL(comedi_driver_unregister);
249
250 static int postconfig(struct comedi_device *dev)
251 {
252         int i;
253         struct comedi_subdevice *s;
254         struct comedi_async *async = NULL;
255         int ret;
256
257         for (i = 0; i < dev->n_subdevices; i++) {
258                 s = &dev->subdevices[i];
259
260                 if (s->type == COMEDI_SUBD_UNUSED)
261                         continue;
262
263                 if (s->len_chanlist == 0)
264                         s->len_chanlist = 1;
265
266                 if (s->do_cmd) {
267                         unsigned int buf_size;
268
269                         BUG_ON((s->subdev_flags & (SDF_CMD_READ |
270                                                    SDF_CMD_WRITE)) == 0);
271                         BUG_ON(!s->do_cmdtest);
272
273                         async =
274                             kzalloc(sizeof(struct comedi_async), GFP_KERNEL);
275                         if (async == NULL) {
276                                 dev_warn(dev->class_dev,
277                                          "failed to allocate async struct\n");
278                                 return -ENOMEM;
279                         }
280                         init_waitqueue_head(&async->wait_head);
281                         async->subdevice = s;
282                         s->async = async;
283
284                         async->max_bufsize =
285                                 comedi_default_buf_maxsize_kb * 1024;
286                         buf_size = comedi_default_buf_size_kb * 1024;
287                         if (buf_size > async->max_bufsize)
288                                 buf_size = async->max_bufsize;
289
290                         async->prealloc_buf = NULL;
291                         async->prealloc_bufsz = 0;
292                         if (comedi_buf_alloc(dev, s, buf_size) < 0) {
293                                 dev_warn(dev->class_dev,
294                                          "Buffer allocation failed\n");
295                                 return -ENOMEM;
296                         }
297                         if (s->buf_change) {
298                                 ret = s->buf_change(dev, s, buf_size);
299                                 if (ret < 0)
300                                         return ret;
301                         }
302                         comedi_alloc_subdevice_minor(dev, s);
303                 }
304
305                 if (!s->range_table && !s->range_table_list)
306                         s->range_table = &range_unknown;
307
308                 if (!s->insn_read && s->insn_bits)
309                         s->insn_read = insn_rw_emulate_bits;
310                 if (!s->insn_write && s->insn_bits)
311                         s->insn_write = insn_rw_emulate_bits;
312
313                 if (!s->insn_read)
314                         s->insn_read = insn_inval;
315                 if (!s->insn_write)
316                         s->insn_write = insn_inval;
317                 if (!s->insn_bits)
318                         s->insn_bits = insn_inval;
319                 if (!s->insn_config)
320                         s->insn_config = insn_inval;
321
322                 if (!s->poll)
323                         s->poll = poll_invalid;
324         }
325
326         return 0;
327 }
328
329 /*
330  * Generic recognize function for drivers that register their supported
331  * board names.
332  *
333  * 'driv->board_name' points to a 'const char *' member within the
334  * zeroth element of an array of some private board information
335  * structure, say 'struct foo_board' containing a member 'const char
336  * *board_name' that is initialized to point to a board name string that
337  * is one of the candidates matched against this function's 'name'
338  * parameter.
339  *
340  * 'driv->offset' is the size of the private board information
341  * structure, say 'sizeof(struct foo_board)', and 'driv->num_names' is
342  * the length of the array of private board information structures.
343  *
344  * If one of the board names in the array of private board information
345  * structures matches the name supplied to this function, the function
346  * returns a pointer to the pointer to the board name, otherwise it
347  * returns NULL.  The return value ends up in the 'board_ptr' member of
348  * a 'struct comedi_device' that the low-level comedi driver's
349  * 'attach()' hook can convert to a point to a particular element of its
350  * array of private board information structures by subtracting the
351  * offset of the member that points to the board name.  (No subtraction
352  * is required if the board name pointer is the first member of the
353  * private board information structure, which is generally the case.)
354  */
355 static void *comedi_recognize(struct comedi_driver *driv, const char *name)
356 {
357         char **name_ptr = (char **)driv->board_name;
358         int i;
359
360         for (i = 0; i < driv->num_names; i++) {
361                 if (strcmp(*name_ptr, name) == 0)
362                         return name_ptr;
363                 name_ptr = (void *)name_ptr + driv->offset;
364         }
365
366         return NULL;
367 }
368
369 static void comedi_report_boards(struct comedi_driver *driv)
370 {
371         unsigned int i;
372         const char *const *name_ptr;
373
374         pr_info("comedi: valid board names for %s driver are:\n",
375                 driv->driver_name);
376
377         name_ptr = driv->board_name;
378         for (i = 0; i < driv->num_names; i++) {
379                 pr_info(" %s\n", *name_ptr);
380                 name_ptr = (const char **)((char *)name_ptr + driv->offset);
381         }
382
383         if (driv->num_names == 0)
384                 pr_info(" %s\n", driv->driver_name);
385 }
386
387 static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s)
388 {
389         return -EINVAL;
390 }
391
392 int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
393                struct comedi_insn *insn, unsigned int *data)
394 {
395         return -EINVAL;
396 }
397
398 static int insn_rw_emulate_bits(struct comedi_device *dev,
399                                 struct comedi_subdevice *s,
400                                 struct comedi_insn *insn, unsigned int *data)
401 {
402         struct comedi_insn new_insn;
403         int ret;
404         static const unsigned channels_per_bitfield = 32;
405
406         unsigned chan = CR_CHAN(insn->chanspec);
407         const unsigned base_bitfield_channel =
408             (chan < channels_per_bitfield) ? 0 : chan;
409         unsigned int new_data[2];
410         memset(new_data, 0, sizeof(new_data));
411         memset(&new_insn, 0, sizeof(new_insn));
412         new_insn.insn = INSN_BITS;
413         new_insn.chanspec = base_bitfield_channel;
414         new_insn.n = 2;
415         new_insn.subdev = insn->subdev;
416
417         if (insn->insn == INSN_WRITE) {
418                 if (!(s->subdev_flags & SDF_WRITABLE))
419                         return -EINVAL;
420                 new_data[0] = 1 << (chan - base_bitfield_channel); /* mask */
421                 new_data[1] = data[0] ? (1 << (chan - base_bitfield_channel))
422                               : 0; /* bits */
423         }
424
425         ret = s->insn_bits(dev, s, &new_insn, new_data);
426         if (ret < 0)
427                 return ret;
428
429         if (insn->insn == INSN_READ)
430                 data[0] = (new_data[1] >> (chan - base_bitfield_channel)) & 1;
431
432         return 1;
433 }
434
435 int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
436                      unsigned long new_size)
437 {
438         struct comedi_async *async = s->async;
439
440         /* Round up new_size to multiple of PAGE_SIZE */
441         new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
442
443         /* if no change is required, do nothing */
444         if (async->prealloc_buf && async->prealloc_bufsz == new_size)
445                 return 0;
446
447         /*  deallocate old buffer */
448         if (async->prealloc_buf) {
449                 vunmap(async->prealloc_buf);
450                 async->prealloc_buf = NULL;
451                 async->prealloc_bufsz = 0;
452         }
453         if (async->buf_page_list) {
454                 unsigned i;
455                 for (i = 0; i < async->n_buf_pages; ++i) {
456                         if (async->buf_page_list[i].virt_addr) {
457                                 clear_bit(PG_reserved,
458                                         &(virt_to_page(async->buf_page_list[i].
459                                                         virt_addr)->flags));
460                                 if (s->async_dma_dir != DMA_NONE) {
461                                         dma_free_coherent(dev->hw_dev,
462                                                           PAGE_SIZE,
463                                                           async->
464                                                           buf_page_list
465                                                           [i].virt_addr,
466                                                           async->
467                                                           buf_page_list
468                                                           [i].dma_addr);
469                                 } else {
470                                         free_page((unsigned long)
471                                                   async->buf_page_list[i].
472                                                   virt_addr);
473                                 }
474                         }
475                 }
476                 vfree(async->buf_page_list);
477                 async->buf_page_list = NULL;
478                 async->n_buf_pages = 0;
479         }
480         /*  allocate new buffer */
481         if (new_size) {
482                 unsigned i = 0;
483                 unsigned n_pages = new_size >> PAGE_SHIFT;
484                 struct page **pages = NULL;
485
486                 async->buf_page_list =
487                     vzalloc(sizeof(struct comedi_buf_page) * n_pages);
488                 if (async->buf_page_list)
489                         pages = vmalloc(sizeof(struct page *) * n_pages);
490
491                 if (pages) {
492                         for (i = 0; i < n_pages; i++) {
493                                 if (s->async_dma_dir != DMA_NONE) {
494                                         async->buf_page_list[i].virt_addr =
495                                             dma_alloc_coherent(dev->hw_dev,
496                                                                PAGE_SIZE,
497                                                                &async->
498                                                                buf_page_list
499                                                                [i].dma_addr,
500                                                                GFP_KERNEL |
501                                                                __GFP_COMP);
502                                 } else {
503                                         async->buf_page_list[i].virt_addr =
504                                             (void *)
505                                             get_zeroed_page(GFP_KERNEL);
506                                 }
507                                 if (async->buf_page_list[i].virt_addr == NULL)
508                                         break;
509
510                                 set_bit(PG_reserved,
511                                         &(virt_to_page(async->buf_page_list[i].
512                                                         virt_addr)->flags));
513                                 pages[i] = virt_to_page(async->buf_page_list[i].
514                                                                 virt_addr);
515                         }
516                 }
517                 if (i == n_pages) {
518                         async->prealloc_buf =
519 #ifdef PAGE_KERNEL_NOCACHE
520                             vmap(pages, n_pages, VM_MAP, PAGE_KERNEL_NOCACHE);
521 #else
522                             vmap(pages, n_pages, VM_MAP, PAGE_KERNEL);
523 #endif
524                 }
525                 vfree(pages);
526
527                 if (async->prealloc_buf == NULL) {
528                         /* Some allocation failed above. */
529                         if (async->buf_page_list) {
530                                 for (i = 0; i < n_pages; i++) {
531                                         if (async->buf_page_list[i].virt_addr ==
532                                             NULL) {
533                                                 break;
534                                         }
535                                         clear_bit(PG_reserved,
536                                                 &(virt_to_page(async->
537                                                         buf_page_list[i].
538                                                         virt_addr)->flags));
539                                         if (s->async_dma_dir != DMA_NONE) {
540                                                 dma_free_coherent(dev->hw_dev,
541                                                                   PAGE_SIZE,
542                                                                   async->
543                                                                   buf_page_list
544                                                                   [i].virt_addr,
545                                                                   async->
546                                                                   buf_page_list
547                                                                   [i].dma_addr);
548                                         } else {
549                                                 free_page((unsigned long)
550                                                           async->buf_page_list
551                                                           [i].virt_addr);
552                                         }
553                                 }
554                                 vfree(async->buf_page_list);
555                                 async->buf_page_list = NULL;
556                         }
557                         return -ENOMEM;
558                 }
559                 async->n_buf_pages = n_pages;
560         }
561         async->prealloc_bufsz = new_size;
562
563         return 0;
564 }
565
566 /* munging is applied to data by core as it passes between user
567  * and kernel space */
568 static unsigned int comedi_buf_munge(struct comedi_async *async,
569                                      unsigned int num_bytes)
570 {
571         struct comedi_subdevice *s = async->subdevice;
572         unsigned int count = 0;
573         const unsigned num_sample_bytes = bytes_per_sample(s);
574
575         if (s->munge == NULL || (async->cmd.flags & CMDF_RAWDATA)) {
576                 async->munge_count += num_bytes;
577                 BUG_ON((int)(async->munge_count - async->buf_write_count) > 0);
578                 return num_bytes;
579         }
580         /* don't munge partial samples */
581         num_bytes -= num_bytes % num_sample_bytes;
582         while (count < num_bytes) {
583                 int block_size;
584
585                 block_size = num_bytes - count;
586                 if (block_size < 0) {
587                         dev_warn(s->device->class_dev,
588                                  "%s: %s: bug! block_size is negative\n",
589                                  __FILE__, __func__);
590                         break;
591                 }
592                 if ((int)(async->munge_ptr + block_size -
593                           async->prealloc_bufsz) > 0)
594                         block_size = async->prealloc_bufsz - async->munge_ptr;
595
596                 s->munge(s->device, s, async->prealloc_buf + async->munge_ptr,
597                          block_size, async->munge_chan);
598
599                 smp_wmb();      /* barrier insures data is munged in buffer
600                                  * before munge_count is incremented */
601
602                 async->munge_chan += block_size / num_sample_bytes;
603                 async->munge_chan %= async->cmd.chanlist_len;
604                 async->munge_count += block_size;
605                 async->munge_ptr += block_size;
606                 async->munge_ptr %= async->prealloc_bufsz;
607                 count += block_size;
608         }
609         BUG_ON((int)(async->munge_count - async->buf_write_count) > 0);
610         return count;
611 }
612
613 unsigned int comedi_buf_write_n_available(struct comedi_async *async)
614 {
615         unsigned int free_end;
616         unsigned int nbytes;
617
618         if (async == NULL)
619                 return 0;
620
621         free_end = async->buf_read_count + async->prealloc_bufsz;
622         nbytes = free_end - async->buf_write_alloc_count;
623         nbytes -= nbytes % bytes_per_sample(async->subdevice);
624         /* barrier insures the read of buf_read_count in this
625            query occurs before any following writes to the buffer which
626            might be based on the return value from this query.
627          */
628         smp_mb();
629         return nbytes;
630 }
631
632 /* allocates chunk for the writer from free buffer space */
633 unsigned int comedi_buf_write_alloc(struct comedi_async *async,
634                                     unsigned int nbytes)
635 {
636         unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
637
638         if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0)
639                 nbytes = free_end - async->buf_write_alloc_count;
640
641         async->buf_write_alloc_count += nbytes;
642         /* barrier insures the read of buf_read_count above occurs before
643            we write data to the write-alloc'ed buffer space */
644         smp_mb();
645         return nbytes;
646 }
647 EXPORT_SYMBOL(comedi_buf_write_alloc);
648
649 /* allocates nothing unless it can completely fulfill the request */
650 unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
651                                            unsigned int nbytes)
652 {
653         unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
654
655         if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0)
656                 nbytes = 0;
657
658         async->buf_write_alloc_count += nbytes;
659         /* barrier insures the read of buf_read_count above occurs before
660            we write data to the write-alloc'ed buffer space */
661         smp_mb();
662         return nbytes;
663 }
664
665 /* transfers a chunk from writer to filled buffer space */
666 unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes)
667 {
668         if ((int)(async->buf_write_count + nbytes -
669                   async->buf_write_alloc_count) > 0) {
670                 dev_info(async->subdevice->device->class_dev,
671                          "attempted to write-free more bytes than have been write-allocated.\n");
672                 nbytes = async->buf_write_alloc_count - async->buf_write_count;
673         }
674         async->buf_write_count += nbytes;
675         async->buf_write_ptr += nbytes;
676         comedi_buf_munge(async, async->buf_write_count - async->munge_count);
677         if (async->buf_write_ptr >= async->prealloc_bufsz)
678                 async->buf_write_ptr %= async->prealloc_bufsz;
679
680         return nbytes;
681 }
682 EXPORT_SYMBOL(comedi_buf_write_free);
683
684 /* allocates a chunk for the reader from filled (and munged) buffer space */
685 unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes)
686 {
687         if ((int)(async->buf_read_alloc_count + nbytes - async->munge_count) >
688             0) {
689                 nbytes = async->munge_count - async->buf_read_alloc_count;
690         }
691         async->buf_read_alloc_count += nbytes;
692         /* barrier insures read of munge_count occurs before we actually read
693            data out of buffer */
694         smp_rmb();
695         return nbytes;
696 }
697 EXPORT_SYMBOL(comedi_buf_read_alloc);
698
699 /* transfers control of a chunk from reader to free buffer space */
700 unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes)
701 {
702         /* barrier insures data has been read out of
703          * buffer before read count is incremented */
704         smp_mb();
705         if ((int)(async->buf_read_count + nbytes -
706                   async->buf_read_alloc_count) > 0) {
707                 dev_info(async->subdevice->device->class_dev,
708                          "attempted to read-free more bytes than have been read-allocated.\n");
709                 nbytes = async->buf_read_alloc_count - async->buf_read_count;
710         }
711         async->buf_read_count += nbytes;
712         async->buf_read_ptr += nbytes;
713         async->buf_read_ptr %= async->prealloc_bufsz;
714         return nbytes;
715 }
716 EXPORT_SYMBOL(comedi_buf_read_free);
717
718 void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
719                           const void *data, unsigned int num_bytes)
720 {
721         unsigned int write_ptr = async->buf_write_ptr + offset;
722
723         if (write_ptr >= async->prealloc_bufsz)
724                 write_ptr %= async->prealloc_bufsz;
725
726         while (num_bytes) {
727                 unsigned int block_size;
728
729                 if (write_ptr + num_bytes > async->prealloc_bufsz)
730                         block_size = async->prealloc_bufsz - write_ptr;
731                 else
732                         block_size = num_bytes;
733
734                 memcpy(async->prealloc_buf + write_ptr, data, block_size);
735
736                 data += block_size;
737                 num_bytes -= block_size;
738
739                 write_ptr = 0;
740         }
741 }
742 EXPORT_SYMBOL(comedi_buf_memcpy_to);
743
744 void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
745                             void *dest, unsigned int nbytes)
746 {
747         void *src;
748         unsigned int read_ptr = async->buf_read_ptr + offset;
749
750         if (read_ptr >= async->prealloc_bufsz)
751                 read_ptr %= async->prealloc_bufsz;
752
753         while (nbytes) {
754                 unsigned int block_size;
755
756                 src = async->prealloc_buf + read_ptr;
757
758                 if (nbytes >= async->prealloc_bufsz - read_ptr)
759                         block_size = async->prealloc_bufsz - read_ptr;
760                 else
761                         block_size = nbytes;
762
763                 memcpy(dest, src, block_size);
764                 nbytes -= block_size;
765                 dest += block_size;
766                 read_ptr = 0;
767         }
768 }
769 EXPORT_SYMBOL(comedi_buf_memcpy_from);
770
771 unsigned int comedi_buf_read_n_available(struct comedi_async *async)
772 {
773         unsigned num_bytes;
774
775         if (async == NULL)
776                 return 0;
777         num_bytes = async->munge_count - async->buf_read_count;
778         /* barrier insures the read of munge_count in this
779            query occurs before any following reads of the buffer which
780            might be based on the return value from this query.
781          */
782         smp_rmb();
783         return num_bytes;
784 }
785 EXPORT_SYMBOL(comedi_buf_read_n_available);
786
787 int comedi_buf_get(struct comedi_async *async, short *x)
788 {
789         unsigned int n = comedi_buf_read_n_available(async);
790
791         if (n < sizeof(short))
792                 return 0;
793         comedi_buf_read_alloc(async, sizeof(short));
794         *x = *(short *)(async->prealloc_buf + async->buf_read_ptr);
795         comedi_buf_read_free(async, sizeof(short));
796         return 1;
797 }
798 EXPORT_SYMBOL(comedi_buf_get);
799
800 int comedi_buf_put(struct comedi_async *async, short x)
801 {
802         unsigned int n = comedi_buf_write_alloc_strict(async, sizeof(short));
803
804         if (n < sizeof(short)) {
805                 async->events |= COMEDI_CB_ERROR;
806                 return 0;
807         }
808         *(short *)(async->prealloc_buf + async->buf_write_ptr) = x;
809         comedi_buf_write_free(async, sizeof(short));
810         return 1;
811 }
812 EXPORT_SYMBOL(comedi_buf_put);
813
814 void comedi_reset_async_buf(struct comedi_async *async)
815 {
816         async->buf_write_alloc_count = 0;
817         async->buf_write_count = 0;
818         async->buf_read_alloc_count = 0;
819         async->buf_read_count = 0;
820
821         async->buf_write_ptr = 0;
822         async->buf_read_ptr = 0;
823
824         async->cur_chan = 0;
825         async->scan_progress = 0;
826         async->munge_chan = 0;
827         async->munge_count = 0;
828         async->munge_ptr = 0;
829
830         async->events = 0;
831 }
832
833 int comedi_auto_config(struct device *hardware_device,
834                        struct comedi_driver *driver, unsigned long context)
835 {
836         int minor;
837         struct comedi_device_file_info *dev_file_info;
838         struct comedi_device *comedi_dev;
839         int ret;
840
841         if (!comedi_autoconfig)
842                 return 0;
843
844         if (!driver->auto_attach) {
845                 dev_warn(hardware_device,
846                          "BUG! comedi driver '%s' has no auto_attach handler\n",
847                          driver->driver_name);
848                 return -EINVAL;
849         }
850
851         minor = comedi_alloc_board_minor(hardware_device);
852         if (minor < 0)
853                 return minor;
854
855         dev_file_info = comedi_get_device_file_info(minor);
856         comedi_dev = dev_file_info->device;
857
858         mutex_lock(&comedi_dev->mutex);
859         if (comedi_dev->attached)
860                 ret = -EBUSY;
861         else if (!try_module_get(driver->module))
862                 ret = -EIO;
863         else {
864                 comedi_set_hw_dev(comedi_dev, hardware_device);
865                 comedi_dev->driver = driver;
866                 ret = driver->auto_attach(comedi_dev, context);
867                 if (ret < 0) {
868                         module_put(driver->module);
869                         __comedi_device_detach(comedi_dev);
870                 } else {
871                         ret = comedi_device_postconfig(comedi_dev);
872                 }
873         }
874         mutex_unlock(&comedi_dev->mutex);
875
876         if (ret < 0)
877                 comedi_free_board_minor(minor);
878         return ret;
879 }
880 EXPORT_SYMBOL_GPL(comedi_auto_config);
881
882 void comedi_auto_unconfig(struct device *hardware_device)
883 {
884         int minor;
885
886         if (hardware_device == NULL)
887                 return;
888         minor = comedi_find_board_minor(hardware_device);
889         if (minor < 0)
890                 return;
891         BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
892         comedi_free_board_minor(minor);
893 }
894 EXPORT_SYMBOL_GPL(comedi_auto_unconfig);
895
896 /**
897  * comedi_pci_enable() - Enable the PCI device and request the regions.
898  * @pdev: pci_dev struct
899  * @res_name: name for the requested reqource
900  */
901 int comedi_pci_enable(struct pci_dev *pdev, const char *res_name)
902 {
903         int rc;
904
905         rc = pci_enable_device(pdev);
906         if (rc < 0)
907                 return rc;
908
909         rc = pci_request_regions(pdev, res_name);
910         if (rc < 0)
911                 pci_disable_device(pdev);
912
913         return rc;
914 }
915 EXPORT_SYMBOL_GPL(comedi_pci_enable);
916
917 /**
918  * comedi_pci_disable() - Release the regions and disable the PCI device.
919  * @pdev: pci_dev struct
920  *
921  * This must be matched with a previous successful call to comedi_pci_enable().
922  */
923 void comedi_pci_disable(struct pci_dev *pdev)
924 {
925         pci_release_regions(pdev);
926         pci_disable_device(pdev);
927 }
928 EXPORT_SYMBOL_GPL(comedi_pci_disable);
929
930 int comedi_pci_driver_register(struct comedi_driver *comedi_driver,
931                 struct pci_driver *pci_driver)
932 {
933         int ret;
934
935         ret = comedi_driver_register(comedi_driver);
936         if (ret < 0)
937                 return ret;
938
939         /* FIXME: Remove this test after auditing all comedi pci drivers */
940         if (!pci_driver->name)
941                 pci_driver->name = comedi_driver->driver_name;
942
943         ret = pci_register_driver(pci_driver);
944         if (ret < 0) {
945                 comedi_driver_unregister(comedi_driver);
946                 return ret;
947         }
948
949         return 0;
950 }
951 EXPORT_SYMBOL_GPL(comedi_pci_driver_register);
952
953 void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,
954                 struct pci_driver *pci_driver)
955 {
956         pci_unregister_driver(pci_driver);
957         comedi_driver_unregister(comedi_driver);
958 }
959 EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
960
961 #if IS_ENABLED(CONFIG_USB)
962
963 int comedi_usb_driver_register(struct comedi_driver *comedi_driver,
964                 struct usb_driver *usb_driver)
965 {
966         int ret;
967
968         ret = comedi_driver_register(comedi_driver);
969         if (ret < 0)
970                 return ret;
971
972         ret = usb_register(usb_driver);
973         if (ret < 0) {
974                 comedi_driver_unregister(comedi_driver);
975                 return ret;
976         }
977
978         return 0;
979 }
980 EXPORT_SYMBOL_GPL(comedi_usb_driver_register);
981
982 void comedi_usb_driver_unregister(struct comedi_driver *comedi_driver,
983                 struct usb_driver *usb_driver)
984 {
985         usb_deregister(usb_driver);
986         comedi_driver_unregister(comedi_driver);
987 }
988 EXPORT_SYMBOL_GPL(comedi_usb_driver_unregister);
989
990 #endif