dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cell / lib / ppu / Fifo.cpp
1 #include "Fifo.h"
2
3 /**
4  *
5  */
6 Fifo::Fifo(unsigned size = 18) {
7         //except at the beginning, _head and _tail must never overlap,
8         //otherwise one does not know whether the buffer is full or
9         //empty. To have nevertheless a buffer with the given capacity,
10         //a buffer with one more element is allocated.
11         _size = size;
12         _buffer = (char *) _malloc_align(_size, ALIGNMENT_FACTOR);
13         if(!_buffer) {
14             fprintf(stderr,"[FIFO] Memory allocation failure\n");
15             exit(-1);
16         }
17         
18         _tail = 0;
19         _pos = 0;
20         _blocked = 0;
21
22         _inTail = 0;
23         _activeDMA = false;
24 }
25
26 /**
27  *
28  */
29 Fifo::~Fifo() {
30         if (_buffer) {
31                 _free_align(_buffer);
32         }
33         _buffer = 0;
34         _tail = 0;
35         _pos = 0;
36 }
37
38 /**
39  *
40  */
41 unsigned Fifo::read(void *destination, unsigned len) {
42         char* buffer = (char*) destination;
43         unsigned read = (len <= used() ? len : used());
44
45         if (_tail + read < _size) {
46                 memcpy(buffer, _buffer + _tail, read);
47         } else {
48                 memcpy(buffer, _buffer + _tail, _size - _tail);
49                 memcpy(buffer + _size - _tail, _buffer, read - _size + _tail);
50         }
51
52         _tail = ((unsigned) (_tail + read) % _size);
53         _pos -= read;
54         return read;
55 }
56
57 /**
58  *
59  */
60 unsigned Fifo::write(const void *source, unsigned len) {
61
62         char* buffer = (char*) source;
63         unsigned write = (len <= unused() ? len : unused());
64         unsigned head = (_tail + _pos) % _size;
65
66         if (head + write < _size) {
67                 memcpy(_buffer + head, buffer, write);
68         } else {
69                 memcpy(_buffer + head, buffer, _size - head);
70                 memcpy(_buffer, buffer + _size - head, write - _size + head);
71         }
72
73         _pos += write;
74         return write;
75 }
76
77 /**
78  * Size of this fifo
79  */
80 unsigned Fifo::size() const {
81         return (_size);
82 }
83
84 /**
85  * How many bytes are currently free in the buffer
86  */
87 unsigned Fifo::unused() const {
88         return (_size) - used();
89 }
90
91 /**
92  * How many data are currently stored in the fifo
93  */
94 unsigned Fifo::used() const {
95         return _pos;
96 }
97
98 /*
99  * Get the pointer to the start of the queue
100  */
101 char *Fifo::getQueuePointer() {
102         return _buffer;
103 }
104
105 /*
106  * Has completed a dma read process, i.e. has read out of the queue
107  */
108 void Fifo::dmaRead(unsigned len) {
109         _activeDMA = false;
110
111         if (len == 0) {
112                 _blocked = BLOCKED_MAX_NR;
113         } else {
114                 _tail = ((unsigned) (_tail + len) % _size);
115                 _pos -= len;
116         }
117 }
118
119 /*
120  * Start a DMA request, returns the current space one have
121  */
122 unsigned Fifo::dmaStart() {
123         _activeDMA = true;
124
125         if (_tail + _pos > _size) {
126                 return _size - _tail;
127         } else {
128                 return _pos;
129         }
130 }
131
132 /*
133  * Is allowed to start a dma request
134  */
135 bool Fifo::dmaAllowed() {
136         if (_blocked > 0) {
137                 _blocked--;
138                 return false;
139         } else {
140                 return !_activeDMA;
141         }
142 }