diff options
Diffstat (limited to 'drivers/staging/comedi/comedidev.h')
-rw-r--r-- | drivers/staging/comedi/comedidev.h | 152 |
1 files changed, 117 insertions, 35 deletions
diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 8f4e44bfbe00..58e58a32e93d 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -75,13 +75,9 @@ struct comedi_subdevice { struct comedi_cmd *); int (*poll)(struct comedi_device *, struct comedi_subdevice *); int (*cancel)(struct comedi_device *, struct comedi_subdevice *); - /* int (*do_lock)(struct comedi_device *, struct comedi_subdevice *); */ - /* int (*do_unlock)(struct comedi_device *, \ - struct comedi_subdevice *); */ /* called when the buffer changes */ - int (*buf_change)(struct comedi_device *dev, - struct comedi_subdevice *s, unsigned long new_size); + int (*buf_change)(struct comedi_device *, struct comedi_subdevice *); void (*munge)(struct comedi_device *dev, struct comedi_subdevice *s, void *data, unsigned int num_bytes, @@ -107,43 +103,110 @@ struct comedi_buf_map { struct kref refcount; }; +/** + * struct comedi_async - control data for asynchronous comedi commands + * @prealloc_buf: preallocated buffer + * @prealloc_bufsz: buffer size (in bytes) + * @buf_map: map of buffer pages + * @max_bufsize: maximum buffer size (in bytes) + * @buf_write_count: "write completed" count (in bytes, modulo 2**32) + * @buf_write_alloc_count: "allocated for writing" count (in bytes, + * modulo 2**32) + * @buf_read_count: "read completed" count (in bytes, modulo 2**32) + * @buf_read_alloc_count: "allocated for reading" count (in bytes, + * modulo 2**32) + * @buf_write_ptr: buffer position for writer + * @buf_read_ptr: buffer position for reader + * @cur_chan: current position in chanlist for scan (for those + * drivers that use it) + * @scan_progress: amount received or sent for current scan (in bytes) + * @munge_chan: current position in chanlist for "munging" + * @munge_count: "munge" count (in bytes, modulo 2**32) + * @munge_ptr: buffer position for "munging" + * @events: bit-vector of events that have occurred + * @cmd: details of comedi command in progress + * @wait_head: task wait queue for file reader or writer + * @cb_mask: bit-vector of events that should wake waiting tasks + * @inttrig: software trigger function for command, or NULL + * + * Note about the ..._count and ..._ptr members: + * + * Think of the _Count values being integers of unlimited size, indexing + * into a buffer of infinite length (though only an advancing portion + * of the buffer of fixed length prealloc_bufsz is accessible at any time). + * Then: + * + * Buf_Read_Count <= Buf_Read_Alloc_Count <= Munge_Count <= + * Buf_Write_Count <= Buf_Write_Alloc_Count <= + * (Buf_Read_Count + prealloc_bufsz) + * + * (Those aren't the actual members, apart from prealloc_bufsz.) When + * the buffer is reset, those _Count values start at 0 and only increase + * in value, maintaining the above inequalities until the next time the + * buffer is reset. The buffer is divided into the following regions by + * the inequalities: + * + * [0, Buf_Read_Count): + * old region no longer accessible + * [Buf_Read_Count, Buf_Read_Alloc_Count): + * filled and munged region allocated for reading but not yet read + * [Buf_Read_Alloc_Count, Munge_Count): + * filled and munged region not yet allocated for reading + * [Munge_Count, Buf_Write_Count): + * filled region not yet munged + * [Buf_Write_Count, Buf_Write_Alloc_Count): + * unfilled region allocated for writing but not yet written + * [Buf_Write_Alloc_Count, Buf_Read_Count + prealloc_bufsz): + * unfilled region not yet allocated for writing + * [Buf_Read_Count + prealloc_bufsz, infinity): + * unfilled region not yet accessible + * + * Data needs to be written into the buffer before it can be read out, + * and may need to be converted (or "munged") between the two + * operations. Extra unfilled buffer space may need to allocated for + * writing (advancing Buf_Write_Alloc_Count) before new data is written. + * After writing new data, the newly filled space needs to be released + * (advancing Buf_Write_Count). This also results in the new data being + * "munged" (advancing Munge_Count). Before data is read out of the + * buffer, extra space may need to be allocated for reading (advancing + * Buf_Read_Alloc_Count). After the data has been read out, the space + * needs to be released (advancing Buf_Read_Count). + * + * The actual members, buf_read_count, buf_read_alloc_count, + * munge_count, buf_write_count, and buf_write_alloc_count take the + * value of the corresponding capitalized _Count values modulo 2^32 + * (UINT_MAX+1). Subtracting a "higher" _count value from a "lower" + * _count value gives the same answer as subtracting a "higher" _Count + * value from a lower _Count value because prealloc_bufsz < UINT_MAX+1. + * The modulo operation is done implicitly. + * + * The buf_read_ptr, munge_ptr, and buf_write_ptr members take the value + * of the corresponding capitalized _Count values modulo prealloc_bufsz. + * These correspond to byte indices in the physical buffer. The modulo + * operation is done by subtracting prealloc_bufsz when the value + * exceeds prealloc_bufsz (assuming prealloc_bufsz plus the increment is + * less than or equal to UINT_MAX). + */ struct comedi_async { - void *prealloc_buf; /* pre-allocated buffer */ - unsigned int prealloc_bufsz; /* buffer size, in bytes */ - struct comedi_buf_map *buf_map; /* map of buffer pages */ - - unsigned int max_bufsize; /* maximum buffer size, bytes */ - - /* byte count for writer (write completed) */ + void *prealloc_buf; + unsigned int prealloc_bufsz; + struct comedi_buf_map *buf_map; + unsigned int max_bufsize; unsigned int buf_write_count; - /* byte count for writer (allocated for writing) */ unsigned int buf_write_alloc_count; - /* byte count for reader (read completed) */ unsigned int buf_read_count; - /* byte count for reader (allocated for reading) */ unsigned int buf_read_alloc_count; - - unsigned int buf_write_ptr; /* buffer marker for writer */ - unsigned int buf_read_ptr; /* buffer marker for reader */ - - unsigned int cur_chan; /* useless channel marker for interrupt */ - /* number of bytes that have been received for current scan */ + unsigned int buf_write_ptr; + unsigned int buf_read_ptr; + unsigned int cur_chan; unsigned int scan_progress; - /* keeps track of where we are in chanlist as for munging */ unsigned int munge_chan; - /* number of bytes that have been munged */ unsigned int munge_count; - /* buffer marker for munging */ unsigned int munge_ptr; - - unsigned int events; /* events that have occurred */ - + unsigned int events; struct comedi_cmd cmd; - wait_queue_head_t wait_head; - unsigned int cb_mask; - int (*inttrig)(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int x); }; @@ -190,6 +253,7 @@ struct comedi_device { struct comedi_subdevice *subdevices; /* dumb */ + void __iomem *mmio; unsigned long iobase; unsigned long iolen; unsigned int irq; @@ -213,7 +277,6 @@ static inline const void *comedi_board(const struct comedi_device *dev) */ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s); -void comedi_error(const struct comedi_device *dev, const char *s); /* we can expand the number of bits used to encode devices/subdevices into the minor number soon, after more distros support > 8 bit minor numbers @@ -222,6 +285,7 @@ enum comedi_minor_bits { COMEDI_DEVICE_MINOR_MASK = 0xf, COMEDI_SUBDEVICE_MINOR_MASK = 0xf0 }; + static const unsigned COMEDI_SUBDEVICE_MINOR_SHIFT = 4; static const unsigned COMEDI_SUBDEVICE_MINOR_OFFSET = 1; @@ -296,6 +360,12 @@ static inline bool comedi_range_is_unipolar(struct comedi_subdevice *s, return s->range_table->range[range].min >= 0; } +static inline bool comedi_range_is_external(struct comedi_subdevice *s, + unsigned int range) +{ + return !!(s->range_table->range[range].flags & RF_EXTERNAL); +} + static inline bool comedi_chan_range_is_bipolar(struct comedi_subdevice *s, unsigned int chan, unsigned int range) @@ -310,6 +380,13 @@ static inline bool comedi_chan_range_is_unipolar(struct comedi_subdevice *s, return s->range_table_list[chan]->range[range].min >= 0; } +static inline bool comedi_chan_range_is_external(struct comedi_subdevice *s, + unsigned int chan, + unsigned int range) +{ + return !!(s->range_table_list[chan]->range[range].flags & RF_EXTERNAL); +} + /* munge between offset binary and two's complement values */ static inline unsigned int comedi_offset_munge(struct comedi_subdevice *s, unsigned int val) @@ -321,8 +398,8 @@ static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd) { if (subd->subdev_flags & SDF_LSAMPL) return sizeof(unsigned int); - else - return sizeof(short); + + return sizeof(short); } /* @@ -333,6 +410,11 @@ static inline unsigned int bytes_per_sample(const struct comedi_subdevice *subd) */ int comedi_set_hw_dev(struct comedi_device *dev, struct device *hw_dev); +static inline unsigned int comedi_buf_n_bytes_ready(struct comedi_subdevice *s) +{ + return s->async->buf_write_count - s->async->buf_read_count; +} + unsigned int comedi_buf_write_alloc(struct comedi_subdevice *s, unsigned int n); unsigned int comedi_buf_write_free(struct comedi_subdevice *s, unsigned int n); @@ -484,9 +566,9 @@ int comedi_pcmcia_auto_config(struct pcmcia_device *, struct comedi_driver *); void comedi_pcmcia_auto_unconfig(struct pcmcia_device *); int comedi_pcmcia_driver_register(struct comedi_driver *, - struct pcmcia_driver *); + struct pcmcia_driver *); void comedi_pcmcia_driver_unregister(struct comedi_driver *, - struct pcmcia_driver *); + struct pcmcia_driver *); /** * module_comedi_pcmcia_driver() - Helper macro for registering a comedi PCMCIA driver |