3 * Copyright 2009 Free Software Foundation, Inc.
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.
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.
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/>.
24 #include "memory_map.h"
25 #include "buffer_pool.h"
28 #include "buffer_state.h"
31 static uint32_t last_send_ctrl[NBUFFERS];
34 bsm12_init(bsm12_t *sm, int buf0,
35 const buf_cmd_args_t *recv,
36 const buf_cmd_args_t *send0,
37 const buf_cmd_args_t *send1,
38 bsm12_inspector_t inspect)
40 if (buf0 & 0x3) // precondition: buf0 % 4 == 0
45 sm->recv_args = *recv;
46 sm->send_args[0] = *send0;
47 sm->send_args[1] = *send1;
50 sm->tx_idle[0] = true;
51 sm->tx_idle[1] = true;
53 sm->inspect = inspect;
55 sm->bps_error = BPS_ERROR(buf0 + 0) | BPS_ERROR(buf0 + 1) | BPS_ERROR(buf0 + 2);
56 sm->bps_done = BPS_DONE(buf0 + 0) | BPS_DONE(buf0 + 1) | BPS_DONE(buf0 + 2);
57 sm->bps_error_or_done = sm->bps_error | sm->bps_done;
59 // How much to adjust the last_line register.
60 // It's 1 for everything but the ethernet.
61 sm->last_line_adj = recv->port == PORT_ETH ? 3 : 1;
63 buffer_state[sm->buf0 + 0] = BS_EMPTY;
64 buffer_state[sm->buf0 + 1] = BS_EMPTY;
65 buffer_state[sm->buf0 + 2] = BS_EMPTY;
67 for (int i = 0; i < 3; i++){
68 sm->precomputed_receive_to_buf_ctrl_word[i] =
70 | BPC_BUFFER(sm->buf0 + i)
71 | BPC_PORT(sm->recv_args.port)
73 | BPC_FIRST_LINE(sm->recv_args.first_line)
74 | BPC_LAST_LINE(sm->recv_args.last_line));
76 for (int j = 0; j < 2; j++){
77 sm->precomputed_send_from_buf_ctrl_word[i][j] =
79 | BPC_BUFFER(sm->buf0 + i)
80 | BPC_PORT(sm->send_args[j].port)
82 | BPC_FIRST_LINE(sm->send_args[j].first_line)
83 | BPC_LAST_LINE(0)); // last line filled in at runtime
89 bsm12_receive_to_buf(bsm12_t *sm, int bufno)
91 buffer_pool_ctrl->ctrl = sm->precomputed_receive_to_buf_ctrl_word[bufno & 0x3];
95 bsm12_send_from_buf(bsm12_t *sm, int bufno, int dst_idx)
97 uint32_t t = (sm->precomputed_send_from_buf_ctrl_word[bufno & 0x3][dst_idx]
98 | BPC_LAST_LINE(buffer_pool_status->last_line[bufno] - sm->last_line_adj));
100 buffer_pool_ctrl->ctrl = t;
101 last_send_ctrl[bufno] = t;
105 bsm12_resend_from_buf(bsm12_t *sm, int bufno)
107 buffer_pool_ctrl->ctrl = last_send_ctrl[bufno];
111 bsm12_start(bsm12_t *sm)
115 buffer_state[sm->buf0 + 0] = BS_EMPTY;
116 buffer_state[sm->buf0 + 1] = BS_EMPTY;
117 buffer_state[sm->buf0 + 2] = BS_EMPTY;
119 bp_clear_buf(sm->buf0 + 0);
120 bp_clear_buf(sm->buf0 + 1);
121 bp_clear_buf(sm->buf0 + 2);
124 sm->tx_idle[0] = true;
125 sm->tx_idle[1] = true;
126 bsm12_receive_to_buf(sm, sm->buf0);
127 buffer_state[sm->buf0] = BS_FILLING;
131 bsm12_stop(bsm12_t *sm)
134 bp_clear_buf(sm->buf0 + 0);
135 bp_clear_buf(sm->buf0 + 1);
136 bp_clear_buf(sm->buf0 + 2);
137 buffer_state[sm->buf0 + 0] = BS_EMPTY;
138 buffer_state[sm->buf0 + 1] = BS_EMPTY;
139 buffer_state[sm->buf0 + 2] = BS_EMPTY;
142 static void bsm12_process_helper(bsm12_t *sm, int buf_this);
143 static void bsm12_error_helper(bsm12_t *sm, int buf_this);
146 bsm12_process_status(bsm12_t *sm, uint32_t status)
149 if ((status & sm->bps_error_or_done) == 0 || !sm->running)
152 if (status & sm->bps_error){
153 // Most likely an ethernet Rx error. We just restart the transfer.
154 if (status & (BPS_ERROR(sm->buf0 + 0)))
155 bsm12_error_helper(sm, sm->buf0 + 0);
157 if (status & (BPS_ERROR(sm->buf0 + 1)))
158 bsm12_error_helper(sm, sm->buf0 + 1);
160 if (status & (BPS_ERROR(sm->buf0 + 2)))
161 bsm12_error_helper(sm, sm->buf0 + 2);
164 if (status & BPS_DONE(sm->buf0 + 0))
165 bsm12_process_helper(sm, sm->buf0 + 0);
167 if (status & BPS_DONE(sm->buf0 + 1))
168 bsm12_process_helper(sm, sm->buf0 + 1);
170 if (status & BPS_DONE(sm->buf0 + 2))
171 bsm12_process_helper(sm, sm->buf0 + 2);
175 bsm12_process_helper(bsm12_t *sm, int buf_this)
180 bsm12_error_helper(bsm12_t *sm, int buf_this)
182 bp_clear_buf(buf_this); // clears ERROR flag
184 if (buffer_state[buf_this] == BS_FILLING){
185 bsm12_receive_to_buf(sm, buf_this); // restart the xfer
187 else { // buffer was emptying
188 bsm12_resend_from_buf(sm, buf_this); // restart the xfer
194 bsm12_handle_tx_underrun(bsm12_t *sm)
199 bsm12_handle_rx_overrun(bsm12_t *sm)