00001
00023 #ifndef __ANALOGY_BUFFER_H__
00024 #define __ANALOGY_BUFFER_H__
00025
00026 #ifndef DOXYGEN_CPP
00027
00028 #ifdef __KERNEL__
00029
00030 #include <linux/version.h>
00031 #include <linux/mm.h>
00032
00033 #include <rtdm/rtdm_driver.h>
00034
00035 #include <analogy/context.h>
00036
00037
00038 #define A4L_BUF_EOBUF_NR 0
00039 #define A4L_BUF_ERROR_NR 1
00040 #define A4L_BUF_EOA_NR 2
00041
00042 #define A4L_BUF_EOBUF (1 << A4L_BUF_EOBUF_NR)
00043 #define A4L_BUF_ERROR (1 << A4L_BUF_ERROR_NR)
00044 #define A4L_BUF_EOA (1 << A4L_BUF_EOA_NR)
00045
00046 struct a4l_subdevice;
00047
00048
00049 struct a4l_buffer {
00050
00051
00052 void *buf;
00053
00054
00055 unsigned long size;
00056
00057 unsigned long *pg_list;
00058
00059
00060 a4l_sync_t sync;
00061
00062
00063 unsigned long end_count;
00064 unsigned long prd_count;
00065 unsigned long cns_count;
00066 unsigned long tmp_count;
00067
00068
00069 unsigned long evt_flags;
00070
00071
00072 a4l_cmd_t *cur_cmd;
00073
00074
00075 unsigned long mng_count;
00076 };
00077 typedef struct a4l_buffer a4l_buf_t;
00078
00079
00080
00081
00082 static inline int __produce(a4l_cxt_t * cxt,
00083 a4l_buf_t * buf, void *pin, unsigned long count)
00084 {
00085 unsigned long start_ptr = (buf->prd_count % buf->size);
00086 unsigned long tmp_cnt = count;
00087 int ret = 0;
00088
00089 while (ret == 0 && tmp_cnt != 0) {
00090
00091 unsigned long blk_size = (start_ptr + tmp_cnt > buf->size) ?
00092 buf->size - start_ptr : tmp_cnt;
00093
00094
00095 if (cxt == NULL)
00096 memcpy(buf->buf + start_ptr, pin, blk_size);
00097 else
00098 ret = rtdm_safe_copy_from_user(cxt->user_info,
00099 buf->buf + start_ptr,
00100 pin, blk_size);
00101
00102
00103 pin += blk_size;
00104 tmp_cnt -= blk_size;
00105 start_ptr = 0;
00106 }
00107
00108 return ret;
00109 }
00110
00111
00112 static inline int __consume(a4l_cxt_t * cxt,
00113 a4l_buf_t * buf, void *pout, unsigned long count)
00114 {
00115 unsigned long start_ptr = (buf->cns_count % buf->size);
00116 unsigned long tmp_cnt = count;
00117 int ret = 0;
00118
00119 while (ret == 0 && tmp_cnt != 0) {
00120
00121 unsigned long blk_size = (start_ptr + tmp_cnt > buf->size) ?
00122 buf->size - start_ptr : tmp_cnt;
00123
00124
00125 if (cxt == NULL)
00126 memcpy(pout, buf->buf + start_ptr, blk_size);
00127 else
00128 ret = rtdm_safe_copy_to_user(cxt->user_info,
00129 pout,
00130 buf->buf + start_ptr,
00131 blk_size);
00132
00133
00134 pout += blk_size;
00135 tmp_cnt -= blk_size;
00136 start_ptr = 0;
00137 }
00138
00139 return ret;
00140 }
00141
00142
00143 static inline void __munge(struct a4l_subdevice * subd,
00144 void (*munge) (struct a4l_subdevice *,
00145 void *, unsigned long),
00146 a4l_buf_t * buf, unsigned long count)
00147 {
00148 unsigned long start_ptr = (buf->mng_count % buf->size);
00149 unsigned long tmp_cnt = count;
00150
00151 while (tmp_cnt != 0) {
00152
00153 unsigned long blk_size = (start_ptr + tmp_cnt > buf->size) ?
00154 buf->size - start_ptr : tmp_cnt;
00155
00156
00157 munge(subd, buf->buf + start_ptr, blk_size);
00158
00159
00160 tmp_cnt -= blk_size;
00161 start_ptr = 0;
00162 }
00163 }
00164
00165
00166 static inline int __handle_event(a4l_buf_t * buf)
00167 {
00168 int ret = 0;
00169
00170
00171
00172 if (test_bit(A4L_BUF_EOA_NR, &buf->evt_flags)) {
00173 ret = -ENOENT;
00174 }
00175
00176 if (test_bit(A4L_BUF_ERROR_NR, &buf->evt_flags)) {
00177 ret = -EPIPE;
00178 }
00179
00180 return ret;
00181 }
00182
00183
00184
00185 static inline int __pre_abs_put(a4l_buf_t * buf, unsigned long count)
00186 {
00187 if (count - buf->tmp_count > buf->size) {
00188 set_bit(A4L_BUF_ERROR_NR, &buf->evt_flags);
00189 return -EPIPE;
00190 }
00191
00192 buf->tmp_count = buf->cns_count;
00193
00194 return 0;
00195 }
00196
00197 static inline int __pre_put(a4l_buf_t * buf, unsigned long count)
00198 {
00199 return __pre_abs_put(buf, buf->tmp_count + count);
00200 }
00201
00202 static inline int __pre_abs_get(a4l_buf_t * buf, unsigned long count)
00203 {
00204
00205
00206
00207
00208 if (buf->tmp_count == 0 || buf->cns_count == 0)
00209 goto out;
00210
00211
00212
00213
00214
00215
00216 if ((long)(count - buf->end_count) > 0)
00217 goto out;
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 if ((long)(count - buf->tmp_count) > 0) {
00229 set_bit(A4L_BUF_ERROR_NR, &buf->evt_flags);
00230 return -EPIPE;
00231 }
00232
00233 out:
00234 buf->tmp_count = buf->prd_count;
00235
00236 return 0;
00237 }
00238
00239 static inline int __pre_get(a4l_buf_t * buf, unsigned long count)
00240 {
00241 return __pre_abs_get(buf, buf->tmp_count + count);
00242 }
00243
00244 static inline int __abs_put(a4l_buf_t * buf, unsigned long count)
00245 {
00246 unsigned long old = buf->prd_count;
00247
00248 if (buf->prd_count >= count)
00249 return -EINVAL;
00250
00251 buf->prd_count = count;
00252
00253 if ((old / buf->size) != (count / buf->size))
00254 set_bit(A4L_BUF_EOBUF_NR, &buf->evt_flags);
00255
00256 if (count >= buf->end_count)
00257 set_bit(A4L_BUF_EOA_NR, &buf->evt_flags);
00258
00259 return 0;
00260 }
00261
00262 static inline int __put(a4l_buf_t * buf, unsigned long count)
00263 {
00264 return __abs_put(buf, buf->prd_count + count);
00265 }
00266
00267 static inline int __abs_get(a4l_buf_t * buf, unsigned long count)
00268 {
00269 unsigned long old = buf->cns_count;
00270
00271 if (buf->cns_count >= count)
00272 return -EINVAL;
00273
00274 buf->cns_count = count;
00275
00276 if ((old / buf->size) != count / buf->size)
00277 set_bit(A4L_BUF_EOBUF_NR, &buf->evt_flags);
00278
00279 if (count >= buf->end_count)
00280 set_bit(A4L_BUF_EOA_NR, &buf->evt_flags);
00281
00282 return 0;
00283 }
00284
00285 static inline int __get(a4l_buf_t * buf, unsigned long count)
00286 {
00287 return __abs_get(buf, buf->cns_count + count);
00288 }
00289
00290 static inline unsigned long __count_to_put(a4l_buf_t * buf)
00291 {
00292 unsigned long ret;
00293
00294 if (buf->size + buf->cns_count > buf->prd_count)
00295 ret = buf->size + buf->cns_count - buf->prd_count;
00296 else
00297 ret = 0;
00298
00299 return ret;
00300 }
00301
00302 static inline unsigned long __count_to_get(a4l_buf_t * buf)
00303 {
00304 unsigned long ret;
00305
00306 if (buf->end_count != 0 && (buf->end_count > buf->prd_count))
00307 ret = buf->prd_count;
00308 else
00309 ret = buf->end_count;
00310
00311 if (ret > buf->cns_count)
00312 ret -= buf->cns_count;
00313 else
00314 ret = 0;
00315
00316 return ret;
00317 }
00318
00319
00320
00321 int a4l_alloc_buffer(a4l_buf_t * buf_desc);
00322
00323 void a4l_free_buffer(a4l_buf_t * buf_desc);
00324
00325 int a4l_buf_prepare_absput(struct a4l_subdevice *subd,
00326 unsigned long count);
00327
00328 int a4l_buf_commit_absput(struct a4l_subdevice *subd,
00329 unsigned long count);
00330
00331 int a4l_buf_prepare_put(struct a4l_subdevice *subd,
00332 unsigned long count);
00333
00334 int a4l_buf_commit_put(struct a4l_subdevice *subd,
00335 unsigned long count);
00336
00337 int a4l_buf_put(struct a4l_subdevice *subd,
00338 void *bufdata, unsigned long count);
00339
00340 int a4l_buf_prepare_absget(struct a4l_subdevice *subd,
00341 unsigned long count);
00342
00343 int a4l_buf_commit_absget(struct a4l_subdevice *subd,
00344 unsigned long count);
00345
00346 int a4l_buf_prepare_get(struct a4l_subdevice *subd,
00347 unsigned long count);
00348
00349 int a4l_buf_commit_get(struct a4l_subdevice *subd,
00350 unsigned long count);
00351
00352 int a4l_buf_get(struct a4l_subdevice *subd,
00353 void *bufdata, unsigned long count);
00354
00355 int a4l_buf_evt(struct a4l_subdevice *subd, unsigned long evts);
00356
00357 unsigned long a4l_buf_count(struct a4l_subdevice *subd);
00358
00359
00360
00361 a4l_cmd_t *a4l_get_cmd(struct a4l_subdevice *subd);
00362
00363
00364
00365 int a4l_get_chan(struct a4l_subdevice *subd);
00366
00367
00368
00369 int a4l_ioctl_mmap(a4l_cxt_t * cxt, void *arg);
00370 int a4l_ioctl_bufcfg(a4l_cxt_t * cxt, void *arg);
00371 int a4l_ioctl_bufinfo(a4l_cxt_t * cxt, void *arg);
00372 int a4l_ioctl_poll(a4l_cxt_t * cxt, void *arg);
00373 ssize_t a4l_read(a4l_cxt_t * cxt, void *bufdata, size_t nbytes);
00374 ssize_t a4l_write(a4l_cxt_t * cxt,
00375 const void *bufdata, size_t nbytes);
00376 int a4l_select(a4l_cxt_t *cxt,
00377 rtdm_selector_t *selector,
00378 enum rtdm_selecttype type, unsigned fd_index);
00379
00380 #endif
00381
00382
00383 struct a4l_mmap_arg {
00384 unsigned int idx_subd;
00385 unsigned long size;
00386 void *ptr;
00387 };
00388 typedef struct a4l_mmap_arg a4l_mmap_t;
00389
00390
00391
00392 #define A4L_BUF_MAXSIZE 0x1000000
00393 #define A4L_BUF_DEFSIZE 0x10000
00394
00395
00396 struct a4l_buffer_config {
00397 unsigned int idx_subd;
00398 unsigned long buf_size;
00399 };
00400 typedef struct a4l_buffer_config a4l_bufcfg_t;
00401
00402
00403 struct a4l_buffer_info {
00404 unsigned int idx_subd;
00405 unsigned long buf_size;
00406 unsigned long rw_count;
00407 };
00408 typedef struct a4l_buffer_info a4l_bufinfo_t;
00409
00410
00411 struct a4l_poll {
00412 unsigned int idx_subd;
00413 unsigned long arg;
00414 };
00415 typedef struct a4l_poll a4l_poll_t;
00416
00417 #endif
00418
00419 #endif