revert extraction of buffer_state
[debian/gnuradio] / usrp2 / firmware / lib / bsm12.c
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2009 Free Software Foundation, Inc.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include "bsm12.h"
24 #include "memory_map.h"
25 #include "buffer_pool.h"
26 #include "bool.h"
27 #include "nonstdio.h"
28 #include <stdlib.h>
29
30 typedef enum {
31   BS_EMPTY,
32   BS_FILLING,
33   BS_FULL,
34   BS_EMPTYING,
35 } buffer_state_t;
36
37 static buffer_state_t buffer_state[NBUFFERS];
38 static unsigned char  buffer_dst[NBUFFERS];     // 0 or 1
39 static uint32_t last_send_ctrl[NBUFFERS];
40
41 void
42 bsm12_init(bsm12_t *sm, int buf0,
43            const buf_cmd_args_t *recv,
44            const buf_cmd_args_t *send0,
45            const buf_cmd_args_t *send1,
46            bsm12_inspector_t inspect)
47 {
48   if (buf0 & 0x3)       // precondition: buf0 % 4 == 0
49     abort();
50
51   sm->buf0 = buf0;
52   sm->running = false;
53   sm->recv_args = *recv;
54   sm->send_args[0] = *send0;
55   sm->send_args[1] = *send1;
56
57   sm->rx_idle = true;
58   sm->tx_idle[0] = true;
59   sm->tx_idle[1] = true;
60
61   sm->inspect = inspect;
62
63   sm->bps_error = BPS_ERROR(buf0 + 0) | BPS_ERROR(buf0 + 1) | BPS_ERROR(buf0 + 2);
64   sm->bps_done  = BPS_DONE(buf0 + 0)  | BPS_DONE(buf0 + 1)  | BPS_DONE(buf0 + 2);
65   sm->bps_error_or_done = sm->bps_error | sm->bps_done;
66
67   // How much to adjust the last_line register.
68   // It's 1 for everything but the ethernet.
69   sm->last_line_adj = recv->port == PORT_ETH ? 3 : 1;
70
71   buffer_state[sm->buf0 + 0] = BS_EMPTY;
72   buffer_state[sm->buf0 + 1] = BS_EMPTY;
73   buffer_state[sm->buf0 + 2] = BS_EMPTY;
74
75   for (int i = 0; i < 3; i++){
76     sm->precomputed_receive_to_buf_ctrl_word[i] =
77       (BPC_READ
78        | BPC_BUFFER(sm->buf0 + i)
79        | BPC_PORT(sm->recv_args.port)
80        | BPC_STEP(1)
81        | BPC_FIRST_LINE(sm->recv_args.first_line)
82        | BPC_LAST_LINE(sm->recv_args.last_line));
83     
84     for (int j = 0; j < 2; j++){
85       sm->precomputed_send_from_buf_ctrl_word[i][j] =
86         (BPC_WRITE
87          | BPC_BUFFER(sm->buf0 + i)
88          | BPC_PORT(sm->send_args[j].port)
89          | BPC_STEP(1)
90          | BPC_FIRST_LINE(sm->send_args[j].first_line)
91          | BPC_LAST_LINE(0));           // last line filled in at runtime
92     }
93   }
94 }
95
96 static inline void
97 bsm12_receive_to_buf(bsm12_t *sm, int bufno)
98 {
99   buffer_pool_ctrl->ctrl = sm->precomputed_receive_to_buf_ctrl_word[bufno & 0x3];
100 }
101
102 static inline void
103 bsm12_send_from_buf(bsm12_t *sm, int bufno, int dst_idx)
104 {
105   uint32_t t = (sm->precomputed_send_from_buf_ctrl_word[bufno & 0x3][dst_idx]
106                 | BPC_LAST_LINE(buffer_pool_status->last_line[bufno] - sm->last_line_adj));
107
108   buffer_pool_ctrl->ctrl = t;
109   last_send_ctrl[bufno] = t;
110 }
111
112 static inline void
113 bsm12_resend_from_buf(bsm12_t *sm, int bufno)
114 {
115   buffer_pool_ctrl->ctrl = last_send_ctrl[bufno];
116 }
117
118 void
119 bsm12_start(bsm12_t *sm)
120 {
121   sm->running = true;
122
123   buffer_state[sm->buf0 + 0] = BS_EMPTY;
124   buffer_state[sm->buf0 + 1] = BS_EMPTY;
125   buffer_state[sm->buf0 + 2] = BS_EMPTY;
126
127   bp_clear_buf(sm->buf0 + 0);
128   bp_clear_buf(sm->buf0 + 1);
129   bp_clear_buf(sm->buf0 + 2);
130
131   sm->rx_idle = false;
132   sm->tx_idle[0] = true;
133   sm->tx_idle[1] = true;
134   bsm12_receive_to_buf(sm, sm->buf0);
135   buffer_state[sm->buf0] = BS_FILLING;
136 }
137
138 void
139 bsm12_stop(bsm12_t *sm)
140 {
141   sm->running = false;
142   bp_clear_buf(sm->buf0 + 0);
143   bp_clear_buf(sm->buf0 + 1);
144   bp_clear_buf(sm->buf0 + 2);
145   buffer_state[sm->buf0 + 0] = BS_EMPTY;
146   buffer_state[sm->buf0 + 1] = BS_EMPTY;
147   buffer_state[sm->buf0 + 2] = BS_EMPTY;
148 }
149
150 static void bsm12_process_helper(bsm12_t *sm, int buf_this);
151 static void bsm12_error_helper(bsm12_t *sm, int buf_this);
152
153 void
154 bsm12_process_status(bsm12_t *sm, uint32_t status)
155 {
156   // anything for us?
157   if ((status & sm->bps_error_or_done) == 0 || !sm->running)
158     return;
159
160   if (status & sm->bps_error){
161     // Most likely an ethernet Rx error.  We just restart the transfer.
162     if (status & (BPS_ERROR(sm->buf0 + 0)))
163       bsm12_error_helper(sm, sm->buf0 + 0);
164
165     if (status & (BPS_ERROR(sm->buf0 + 1)))
166       bsm12_error_helper(sm, sm->buf0 + 1);
167
168     if (status & (BPS_ERROR(sm->buf0 + 2)))
169       bsm12_error_helper(sm, sm->buf0 + 2);
170   }
171
172   if (status & BPS_DONE(sm->buf0 + 0))
173     bsm12_process_helper(sm, sm->buf0 + 0);
174
175   if (status & BPS_DONE(sm->buf0 + 1))
176     bsm12_process_helper(sm, sm->buf0 + 1);
177
178   if (status & BPS_DONE(sm->buf0 + 2))
179     bsm12_process_helper(sm, sm->buf0 + 2);
180 }
181
182 \fstatic void 
183 bsm12_process_helper(bsm12_t *sm, int buf_this)
184 {
185 }
186
187 static void
188 bsm12_error_helper(bsm12_t *sm, int buf_this)
189 {
190   bp_clear_buf(buf_this);                 // clears ERROR flag
191
192   if (buffer_state[buf_this] == BS_FILLING){
193     bsm12_receive_to_buf(sm, buf_this);   // restart the xfer
194   }
195   else { // buffer was emptying
196     bsm12_resend_from_buf(sm, buf_this);  // restart the xfer
197   }
198 }
199
200
201 void
202 bsm12_handle_tx_underrun(bsm12_t *sm)
203 {
204 }
205
206 void
207 bsm12_handle_rx_overrun(bsm12_t *sm)
208 {
209 }