1e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe/* 2e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * A simple kernel FIFO implementation. 3e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * 4e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * Copyright (C) 2004 Stelian Pop <stelian@popies.net> 5e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * 6e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * This program is free software; you can redistribute it and/or modify 7e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * it under the terms of the GNU General Public License as published by 8e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * the Free Software Foundation; either version 2 of the License, or 9e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * (at your option) any later version. 10e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * 11e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * This program is distributed in the hope that it will be useful, 12e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * but WITHOUT ANY WARRANTY; without even the implied warranty of 13e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * GNU General Public License for more details. 15e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * 16e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * You should have received a copy of the GNU General Public License 17e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * along with this program; if not, write to the Free Software 18e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * 20e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe */ 21e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 22e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe#include <stdio.h> 23e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe#include <stdlib.h> 24e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe#include <string.h> 25e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 26e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe#include "fifo.h" 27e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 28e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboestruct fifo *fifo_alloc(unsigned int size) 29e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe{ 30e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe struct fifo *fifo; 31e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 32e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe fifo = malloc(sizeof(struct fifo)); 33e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe if (!fifo) 34cc62ea704e4de10eb595b551f29af41266cf225dJens Axboe return NULL; 35e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 36e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe fifo->buffer = malloc(size); 37e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe fifo->size = size; 38f12b323f5d5ca40cd966ebbcfbbfcdf0a1fc229eJens Axboe fifo->in = fifo->out = 0; 39e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 40e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe return fifo; 41e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe} 42e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 43e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboevoid fifo_free(struct fifo *fifo) 44e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe{ 45e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe free(fifo->buffer); 46e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe free(fifo); 47e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe} 48e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 49e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboeunsigned int fifo_put(struct fifo *fifo, void *buffer, unsigned int len) 50e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe{ 51e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe unsigned int l; 52e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 53104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe len = min(len, fifo_room(fifo)); 54e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 55e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe /* first put the data starting from fifo->in to buffer end */ 56e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); 57e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l); 58e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 59e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe /* then put the rest (if any) at the beginning of the buffer */ 60e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe memcpy(fifo->buffer, buffer + l, len - l); 61e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 62e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe /* 63e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * Ensure that we add the bytes to the fifo -before- 64e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe * we update the fifo->in index. 65e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe */ 66e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 67e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe fifo->in += len; 68e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 69e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe return len; 70e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe} 71e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 725ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboeunsigned int fifo_get(struct fifo *fifo, void *buf, unsigned int len) 73e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe{ 74e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe len = min(len, fifo->in - fifo->out); 75e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 765ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe if (buf) { 77104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe unsigned int l; 78e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 79104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe /* 80104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe * first get the data from fifo->out until the end of the buffer 81104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe */ 82104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); 835ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe memcpy(buf, fifo->buffer + (fifo->out & (fifo->size - 1)), l); 84104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe 85104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe /* 86104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe * then get the rest (if any) from the beginning of the buffer 87104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe */ 885ec10eaad3b09875b91e19a20bbdfa06f2117562Jens Axboe memcpy(buf + l, fifo->buffer, len - l); 89104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe } 90e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 91e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe fifo->out += len; 92e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe 93104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe if (fifo->in == fifo->out) 94104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe fifo->in = fifo->out = 0; 95104bc4bdf55bd79c2b3f9087601c3df4aa884b2aJens Axboe 96e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe return len; 97e28875637094451a3c5ec4071f964c1a02dd8f5bJens Axboe} 98