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 static inline int __produce(a4l_cxt_t *cxt,
00097 a4l_buf_t *buf, void *pin, unsigned long count)
00098 {
00099 unsigned long start_ptr = (buf->prd_count % buf->size);
00100 unsigned long tmp_cnt = count;
00101 int ret = 0;
00102
00103 while (ret == 0 && tmp_cnt != 0) {
00104
00105 unsigned long blk_size = (start_ptr + tmp_cnt > buf->size) ?
00106 buf->size - start_ptr : tmp_cnt;
00107
00108
00109 if (cxt == NULL)
00110 memcpy(buf->buf + start_ptr, pin, blk_size);
00111 else
00112 ret = rtdm_safe_copy_from_user(cxt->user_info,
00113 buf->buf + start_ptr,
00114 pin, blk_size);
00115
00116
00117 pin += blk_size;
00118 tmp_cnt -= blk_size;
00119 start_ptr = 0;
00120 }
00121
00122 return ret;
00123 }
00124
00125
00126 static inline int __consume(a4l_cxt_t *cxt,
00127 a4l_buf_t *buf, void *pout, unsigned long count)
00128 {
00129 unsigned long start_ptr = (buf->cns_count % buf->size);
00130 unsigned long tmp_cnt = count;
00131 int ret = 0;
00132
00133 while (ret == 0 && tmp_cnt != 0) {
00134
00135 unsigned long blk_size = (start_ptr + tmp_cnt > buf->size) ?
00136 buf->size - start_ptr : tmp_cnt;
00137
00138
00139 if (cxt == NULL)
00140 memcpy(pout, buf->buf + start_ptr, blk_size);
00141 else
00142 ret = rtdm_safe_copy_to_user(cxt->user_info,
00143 pout,
00144 buf->buf + start_ptr,
00145 blk_size);
00146
00147
00148 pout += blk_size;
00149 tmp_cnt -= blk_size;
00150 start_ptr = 0;
00151 }
00152
00153 return ret;
00154 }
00155
00156
00157 static inline void __munge(struct a4l_subdevice * subd,
00158 void (*munge) (struct a4l_subdevice *,
00159 void *, unsigned long),
00160 a4l_buf_t * buf, unsigned long count)
00161 {
00162 unsigned long start_ptr = (buf->mng_count % buf->size);
00163 unsigned long tmp_cnt = count;
00164
00165 while (tmp_cnt != 0) {
00166
00167 unsigned long blk_size = (start_ptr + tmp_cnt > buf->size) ?
00168 buf->size - start_ptr : tmp_cnt;
00169
00170
00171 munge(subd, buf->buf + start_ptr, blk_size);
00172
00173
00174 tmp_cnt -= blk_size;
00175 start_ptr = 0;
00176 }
00177 }
00178
00179
00180 static inline int __handle_event(a4l_buf_t * buf)
00181 {
00182 int ret = 0;
00183
00184
00185
00186 if (test_bit(A4L_BUF_EOA_NR, &buf->flags)) {
00187 ret = -ENOENT;
00188 }
00189
00190 if (test_bit(A4L_BUF_ERROR_NR, &buf->flags)) {
00191 ret = -EPIPE;
00192 }
00193
00194 return ret;
00195 }
00196
00197
00198
00199 static inline int __pre_abs_put(a4l_buf_t * buf, unsigned long count)
00200 {
00201 if (count - buf->tmp_count > buf->size) {
00202 set_bit(A4L_BUF_ERROR_NR, &buf->flags);
00203 return -EPIPE;
00204 }
00205
00206 buf->tmp_count = buf->cns_count;
00207
00208 return 0;
00209 }
00210
00211 static inline int __pre_put(a4l_buf_t * buf, unsigned long count)
00212 {
00213 return __pre_abs_put(buf, buf->tmp_count + count);
00214 }
00215
00216 static inline int __pre_abs_get(a4l_buf_t * buf, unsigned long count)
00217 {
00218
00219
00220
00221 if (buf->tmp_count == 0 || buf->cns_count == 0)
00222 goto out;
00223
00224
00225
00226
00227
00228
00229 if (buf->end_count != 0 && (long)(count - buf->end_count) > 0)
00230 goto out;
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 if ((long)(count - buf->tmp_count) > 0) {
00242 set_bit(A4L_BUF_ERROR_NR, &buf->flags);
00243 return -EPIPE;
00244 }
00245
00246 out:
00247 buf->tmp_count = buf->prd_count;
00248
00249 return 0;
00250 }
00251
00252 static inline int __pre_get(a4l_buf_t * buf, unsigned long count)
00253 {
00254 return __pre_abs_get(buf, buf->tmp_count + count);
00255 }
00256
00257 static inline int __abs_put(a4l_buf_t * buf, unsigned long count)
00258 {
00259 unsigned long old = buf->prd_count;
00260
00261 if ((long)(buf->prd_count - count) >= 0)
00262 return -EINVAL;
00263
00264 buf->prd_count = count;
00265
00266 if ((old / buf->size) != (count / buf->size))
00267 set_bit(A4L_BUF_EOBUF_NR, &buf->flags);
00268
00269 if (buf->end_count != 0 && (long)(count - buf->end_count) >= 0)
00270 set_bit(A4L_BUF_EOA_NR, &buf->flags);
00271
00272 return 0;
00273 }
00274
00275 static inline int __put(a4l_buf_t * buf, unsigned long count)
00276 {
00277 return __abs_put(buf, buf->prd_count + count);
00278 }
00279
00280 static inline int __abs_get(a4l_buf_t * buf, unsigned long count)
00281 {
00282 unsigned long old = buf->cns_count;
00283
00284 if ((long)(buf->cns_count - count) >= 0)
00285 return -EINVAL;
00286
00287 buf->cns_count = count;
00288
00289 if ((old / buf->size) != count / buf->size)
00290 set_bit(A4L_BUF_EOBUF_NR, &buf->flags);
00291
00292 if (buf->end_count != 0 && (long)(count - buf->end_count) >= 0)
00293 set_bit(A4L_BUF_EOA_NR, &buf->flags);
00294
00295 return 0;
00296 }
00297
00298 static inline int __get(a4l_buf_t * buf, unsigned long count)
00299 {
00300 return __abs_get(buf, buf->cns_count + count);
00301 }
00302
00303 static inline unsigned long __count_to_put(a4l_buf_t * buf)
00304 {
00305 unsigned long ret;
00306
00307 if ((long) (buf->size + buf->cns_count - buf->prd_count) > 0)
00308 ret = buf->size + buf->cns_count - buf->prd_count;
00309 else
00310 ret = 0;
00311
00312 return ret;
00313 }
00314
00315 static inline unsigned long __count_to_get(a4l_buf_t * buf)
00316 {
00317 unsigned long ret;
00318
00319
00320
00321 if (buf->end_count == 0 || (long)(buf->end_count - buf->prd_count) > 0)
00322 ret = buf->prd_count;
00323 else
00324 ret = buf->end_count;
00325
00326 if ((long)(ret - buf->cns_count) > 0)
00327 ret -= buf->cns_count;
00328 else
00329 ret = 0;
00330
00331 return ret;
00332 }
00333
00334
00335
00336 int a4l_alloc_buffer(a4l_buf_t *buf_desc, int buf_size);
00337
00338 void a4l_free_buffer(a4l_buf_t *buf_desc);
00339
00340 void a4l_init_buffer(a4l_buf_t * buf_desc);
00341
00342 void a4l_cleanup_buffer(a4l_buf_t * buf_desc);
00343
00344 int a4l_setup_buffer(a4l_cxt_t *cxt, a4l_cmd_t *cmd);
00345
00346 int a4l_cancel_buffer(a4l_cxt_t *cxt);
00347
00348 int a4l_buf_prepare_absput(struct a4l_subdevice *subd,
00349 unsigned long count);
00350
00351 int a4l_buf_commit_absput(struct a4l_subdevice *subd,
00352 unsigned long count);
00353
00354 int a4l_buf_prepare_put(struct a4l_subdevice *subd,
00355 unsigned long count);
00356
00357 int a4l_buf_commit_put(struct a4l_subdevice *subd,
00358 unsigned long count);
00359
00360 int a4l_buf_put(struct a4l_subdevice *subd,
00361 void *bufdata, unsigned long count);
00362
00363 int a4l_buf_prepare_absget(struct a4l_subdevice *subd,
00364 unsigned long count);
00365
00366 int a4l_buf_commit_absget(struct a4l_subdevice *subd,
00367 unsigned long count);
00368
00369 int a4l_buf_prepare_get(struct a4l_subdevice *subd,
00370 unsigned long count);
00371
00372 int a4l_buf_commit_get(struct a4l_subdevice *subd,
00373 unsigned long count);
00374
00375 int a4l_buf_get(struct a4l_subdevice *subd,
00376 void *bufdata, unsigned long count);
00377
00378 int a4l_buf_evt(struct a4l_subdevice *subd, unsigned long evts);
00379
00380 unsigned long a4l_buf_count(struct a4l_subdevice *subd);
00381
00382
00383
00384 static inline a4l_cmd_t *a4l_get_cmd(a4l_subd_t *subd)
00385 {
00386 return (subd->buf) ? subd->buf->cur_cmd : NULL;
00387 }
00388
00389
00390
00391 int a4l_get_chan(struct a4l_subdevice *subd);
00392
00393
00394
00395 int a4l_ioctl_mmap(a4l_cxt_t * cxt, void *arg);
00396 int a4l_ioctl_bufcfg(a4l_cxt_t * cxt, void *arg);
00397 int a4l_ioctl_bufinfo(a4l_cxt_t * cxt, void *arg);
00398 int a4l_ioctl_poll(a4l_cxt_t * cxt, void *arg);
00399 ssize_t a4l_read_buffer(a4l_cxt_t * cxt, void *bufdata, size_t nbytes);
00400 ssize_t a4l_write_buffer(a4l_cxt_t * cxt, const void *bufdata, size_t nbytes);
00401 int a4l_select(a4l_cxt_t *cxt,
00402 rtdm_selector_t *selector,
00403 enum rtdm_selecttype type, unsigned fd_index);
00404
00405 #endif
00406
00407
00408 struct a4l_mmap_arg {
00409 unsigned int idx_subd;
00410 unsigned long size;
00411 void *ptr;
00412 };
00413 typedef struct a4l_mmap_arg a4l_mmap_t;
00414
00415
00416
00417 #define A4L_BUF_MAXSIZE 0x1000000
00418 #define A4L_BUF_DEFSIZE 0x10000
00419
00420
00421 struct a4l_buffer_config {
00422 unsigned int idx_subd;
00423 unsigned long buf_size;
00424 };
00425 typedef struct a4l_buffer_config a4l_bufcfg_t;
00426
00427
00428 struct a4l_buffer_info {
00429 unsigned int idx_subd;
00430 unsigned long buf_size;
00431 unsigned long rw_count;
00432 };
00433 typedef struct a4l_buffer_info a4l_bufinfo_t;
00434
00435
00436 struct a4l_poll {
00437 unsigned int idx_subd;
00438 unsigned long arg;
00439 };
00440 typedef struct a4l_poll a4l_poll_t;
00441
00442 #endif
00443
00444 #endif