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