00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #ifdef HAVE_CONFIG_H
00030 #include "config/config.h"
00031 #endif
00032 #ifndef USP_TEST
00033 # include <asm/uaccess.h>
00034 # include <linux/module.h>
00035 # include <linux/wait.h>
00036 # include <linux/vmalloc.h>
00037 # include "most-constants.h"
00038 #else
00039 # include "usp-test.h"
00040 #endif
00041
00042 #include "most-txbuf.h"
00043
00044
00048 #define PR "txbuf: "
00049
00050
00051
00052
00053
00054 struct tx_buffer *txbuf_alloc(unsigned int writer_count,
00055 unsigned int frame_count,
00056 unsigned int bytes_per_frame)
00057 {
00058 int i;
00059 struct tx_buffer *ret;
00060
00061
00062 frame_count++;
00063
00064
00065 ret = ker_malloc(sizeof(struct tx_buffer));
00066 if (unlikely(!ret)) {
00067 rtnrt_err(PR "Allocating struct tx_buffer failed\n");
00068 return NULL;
00069 }
00070 memset(ret, 0, sizeof(struct tx_buffer));
00071
00072
00073 ret->writer_count = writer_count;
00074 ret->frame_count = frame_count;
00075 ret->bytes_per_frame = bytes_per_frame;
00076 ret->full_count = 0;
00077 rtnrt_lock_init(&ret->lock);
00078
00079
00080 ret->buffer = vmalloc(bytes_per_frame * frame_count);
00081 pr_txbuf_debug(PR "Allocating %d bytes ringbuffer (0x%p)\n",
00082 bytes_per_frame * frame_count, ret->buffer);
00083 if (unlikely(!ret->buffer)) {
00084 pr_txbuf_debug(PR "Allocating ring buffer failed\n");
00085 goto err_buf;
00086 }
00087 #ifdef DEBUG
00088 memset(ret->buffer, 0, bytes_per_frame * frame_count);
00089 #endif
00090
00091
00092 for (i = 0; i < ret->writer_count; i++) {
00093 ret->writeptr[i] = ret->buffer;
00094 }
00095 ret->readptr = ret->buffer;
00096
00097 return ret;
00098
00099 err_buf:
00100 kfree(ret);
00101 return NULL;
00102 }
00103
00104
00105
00106
00107 void txbuf_free(struct tx_buffer *ring)
00108 {
00109 if (ring) {
00110 if (ring->buffer) {
00111 vfree(ring->buffer);
00112 }
00113 kfree(ring);
00114 }
00115 }
00116
00117
00118
00119
00120 ssize_t txbuf_get(struct tx_buffer *ring,
00121 unsigned char *buffer,
00122 size_t bytes)
00123 {
00124 int to_copy;
00125 unsigned long flags;
00126 int byte_count;
00127 unsigned int ring_size = ring->frame_count * ring->bytes_per_frame;
00128
00129 if ((bytes % ring->bytes_per_frame != 0) || (bytes > ring_size)) {
00130 rtnrt_err(PR "bytes (%d) must be dividable by %d\n",
00131 (int)bytes, ring->bytes_per_frame);
00132 return -EINVAL;
00133 }
00134
00135
00136 byte_count = min((size_t)ring->full_count, bytes);
00137
00138
00139 to_copy = min(byte_count,
00140 (int)(ring_size - (unsigned long)(ring->readptr - ring->buffer)));
00141
00142
00143 if (to_copy == 0) {
00144 return 0;
00145 }
00146
00147
00148 memcpy(buffer, ring->readptr, to_copy);
00149
00150
00151 if (to_copy == byte_count) {
00152
00153 if ((ring->readptr + to_copy) >= (ring->buffer + ring_size)) {
00154 ring->readptr = ring->buffer;
00155 } else {
00156 ring->readptr += to_copy;
00157 }
00158 } else {
00159
00160 buffer += to_copy;
00161 to_copy = byte_count - to_copy;
00162
00163 memcpy(buffer, ring->buffer, to_copy);
00164
00165
00166 ring->readptr = ring->buffer + to_copy;
00167 }
00168
00169 rtnrt_lock_get_irqsave(&ring->lock, flags);
00170 ring->full_count -= byte_count;
00171 rtnrt_lock_put_irqrestore(&ring->lock, flags);
00172
00173 return byte_count;
00174 }
00175
00181 static void txbuf_update_full_frame_count(struct tx_buffer *ring)
00182 {
00183 unsigned int ring_size = ring->frame_count * ring->bytes_per_frame;
00184 int min_val = ring_size;
00185 int i;
00186
00187 for (i = 0; i < ring->writer_count; i++) {
00188 int bytes_full = ring->writeptr[i] - ring->readptr;
00189 if (bytes_full < 0) {
00190 bytes_full = ring_size + bytes_full;
00191 }
00192 min_val = min(min_val, bytes_full);
00193 }
00194 ring->full_count = min_val;
00195 }
00196
00197
00198
00199
00200 bool txbuf_is_full(struct tx_buffer *ring, int writer_index)
00201 {
00202 unsigned int ring_size = ring->frame_count * ring->bytes_per_frame;
00203 int bytes_full;
00204
00205 bytes_full = ring->writeptr[writer_index] - ring->readptr;
00206 if (bytes_full < 0) {
00207 bytes_full = ring_size + bytes_full;
00208 }
00209
00210 return bytes_full == (int)(ring_size - ring->bytes_per_frame);
00211 }
00212
00213
00214
00215
00216 ssize_t txbuf_put(struct tx_buffer *ring,
00217 int writer_index,
00218 struct frame_part frame_part,
00219 const char *buffer,
00220 size_t bytes,
00221 struct rtnrt_memcopy_desc *copy)
00222 {
00223 int frames_to_copy, still_to_copy;
00224 unsigned long flags;
00225 int bytes_full;
00226 unsigned int elements_free;
00227 int err;
00228 int offset_bytes = frame_part.offset;
00229 int count_bytes = frame_part.count;
00230 unsigned int ring_size = ring->frame_count * ring->bytes_per_frame;
00231 unsigned char *writep = ring->writeptr[writer_index];
00232 unsigned char *ring_end = ring->buffer + ring_size;
00233
00234 #ifdef DEBUG
00235
00236 if (bytes % count_bytes != 0) {
00237 rtnrt_err(PR "bytes (%d) must be dividable by %d\n",
00238 bytes, count_bytes);
00239 return -EINVAL;
00240 }
00241 #endif
00242
00243
00244 bytes_full = writep - ring->readptr;
00245 if (bytes_full < 0) {
00246 bytes_full = ring_size + bytes_full;
00247 }
00248 elements_free = ring->frame_count - (bytes_full / (ring->bytes_per_frame));
00249 frames_to_copy = min((size_t)elements_free - 1, bytes / count_bytes);
00250
00251 pr_txbuf_debug(PR "elements free: %d, frames to copy: %d\n",
00252 elements_free, frames_to_copy);
00253
00254
00255 if (elements_free == 0) {
00256 return 0;
00257 }
00258
00259
00260 still_to_copy = frames_to_copy;
00261 while (still_to_copy > 0) {
00262 err = rtnrt_copy(copy, writep + offset_bytes, buffer, count_bytes);
00263
00264 if (err != 0) {
00265 rtnrt_err(PR "Error %d in copy, copied %d frames\n",
00266 err, frames_to_copy - still_to_copy);
00267 return (frames_to_copy - still_to_copy) * count_bytes;
00268 }
00269
00270 writep += ring->bytes_per_frame;
00271
00272
00273 if (writep >= ring_end) {
00274 writep = ring->buffer;
00275 }
00276 buffer += count_bytes;
00277 still_to_copy--;
00278 }
00279
00280
00281 rtnrt_lock_get_irqsave(&ring->lock, flags);
00282 ring->writeptr[writer_index] = writep;
00283 txbuf_update_full_frame_count(ring);
00284 rtnrt_lock_put_irqrestore(&ring->lock, flags);
00285
00286 return frames_to_copy * count_bytes;
00287
00288 }
00289
00290 #ifdef DEBUG
00291 static spinlock_t print_lock = RTNRT_LSPINLOCK_UNLOCKED(print_lock);
00292
00293
00294
00295
00296 void txbuf_print_debug(struct tx_buffer *ring)
00297 {
00298 unsigned int ring_size = ring->bytes_per_frame * ring->frame_count;
00299 int i;
00300
00301 spin_lock(&print_lock);
00302 rtnrt_debug("Frames in ring : %d\n", ring->frame_count);
00303 rtnrt_debug("Full bytes : %d\n", ring->full_count);
00304 rtnrt_debug("Bytes per frame : %d\n", ring->bytes_per_frame);
00305 rtnrt_debug("Read offset : %d\n", ring->readptr - ring->buffer);
00306
00307
00308 for (i = 0; i < ring->writer_count; i++) {
00309 rtnrt_debug("Write offset [%2d] : %d\n", i,
00310 ring->writeptr[i] - ring->buffer);
00311 }
00312
00313 for (i = 0; i < min(16, (int)ring_size); i++) {
00314 rtnrt_printk("%-2.2X ", ring->buffer[i]);
00315 }
00316
00317 printk("\n");
00318 spin_unlock(&print_lock);
00319 }
00320 #endif
00321
00322
00323 #ifdef USP_TEST
00324
00325 int main(int argc, char *argv[])
00326 {
00327 struct frame_part frame_part;
00328 unsigned char user_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
00329 10, 11, 12, 13, 14, 15, 16 };
00330 unsigned char data[1024];
00331 struct tx_buffer *buffer;
00332 int err;
00333
00334 pr_debugm("BEGIN\n");
00335
00336 buffer = txbuf_alloc(2, 5, 6);
00337 if (!buffer) {
00338 pr_err("Error in tvbuf_alloc\n\n\n");
00339 return -1;
00340 }
00341
00342 frame_part.offset = 0;
00343 frame_part.count = 4;
00344 err = txbuf_put(buffer, 0, frame_part, user_data, 4);
00345 pr_debugm("Err=%d\n", err);
00346 printf("==Full=%d, %d\n", txbuf_is_full(buffer, 0), txbuf_is_full(buffer, 1));
00347
00348 err = txbuf_put(buffer, 0, frame_part, user_data + 4, 8);
00349 pr_debugm("Err=%d\n", err);
00350 printf("==Full=%d, %d\n", txbuf_is_full(buffer, 0), txbuf_is_full(buffer, 1));
00351
00352 err = txbuf_put(buffer, 0, frame_part, user_data, 12);
00353 pr_debugm("Err=%d\n", err);
00354 printf("==Full=%d, %d\n", txbuf_is_full(buffer, 0), txbuf_is_full(buffer, 1));
00355
00356 frame_part.offset = 4;
00357 frame_part.count = 2;
00358 err = txbuf_put(buffer, 1, frame_part, user_data, 6);
00359 pr_debugm("Err=%d\n", err);
00360
00361 err = txbuf_get(buffer, data, 24);
00362 pr_debugm("Err=*%d\n", err);
00363
00364 txbuf_print_debug(buffer);
00365
00366 frame_part.offset = 0;
00367 frame_part.count = 4;
00368 err = txbuf_put(buffer, 0, frame_part, user_data, 12);
00369 pr_debugm("Err=%d\n", err);
00370 txbuf_print_debug(buffer);
00371
00372 txbuf_free(buffer);
00373
00374 return 0;
00375 }
00376 #endif
00377
00378