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"
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];
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)
48 if (buf0 & 0x3) // precondition: buf0 % 4 == 0
53 sm->recv_args = *recv;
54 sm->send_args[0] = *send0;
55 sm->send_args[1] = *send1;
58 sm->tx_idle[0] = true;
59 sm->tx_idle[1] = true;
61 sm->inspect = inspect;
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;
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;
71 buffer_state[sm->buf0 + 0] = BS_EMPTY;
72 buffer_state[sm->buf0 + 1] = BS_EMPTY;
73 buffer_state[sm->buf0 + 2] = BS_EMPTY;
75 for (int i = 0; i < 3; i++){
76 sm->precomputed_receive_to_buf_ctrl_word[i] =
78 | BPC_BUFFER(sm->buf0 + i)
79 | BPC_PORT(sm->recv_args.port)
81 | BPC_FIRST_LINE(sm->recv_args.first_line)
82 | BPC_LAST_LINE(sm->recv_args.last_line));
84 for (int j = 0; j < 2; j++){
85 sm->precomputed_send_from_buf_ctrl_word[i][j] =
87 | BPC_BUFFER(sm->buf0 + i)
88 | BPC_PORT(sm->send_args[j].port)
90 | BPC_FIRST_LINE(sm->send_args[j].first_line)
91 | BPC_LAST_LINE(0)); // last line filled in at runtime
97 bsm12_receive_to_buf(bsm12_t *sm, int bufno)
99 buffer_pool_ctrl->ctrl = sm->precomputed_receive_to_buf_ctrl_word[bufno & 0x3];
103 bsm12_send_from_buf(bsm12_t *sm, int bufno, int dst_idx)
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));
108 buffer_pool_ctrl->ctrl = t;
109 last_send_ctrl[bufno] = t;
113 bsm12_resend_from_buf(bsm12_t *sm, int bufno)
115 buffer_pool_ctrl->ctrl = last_send_ctrl[bufno];
119 bsm12_start(bsm12_t *sm)
123 buffer_state[sm->buf0 + 0] = BS_EMPTY;
124 buffer_state[sm->buf0 + 1] = BS_EMPTY;
125 buffer_state[sm->buf0 + 2] = BS_EMPTY;
127 bp_clear_buf(sm->buf0 + 0);
128 bp_clear_buf(sm->buf0 + 1);
129 bp_clear_buf(sm->buf0 + 2);
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;
139 bsm12_stop(bsm12_t *sm)
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;
150 static void bsm12_process_helper(bsm12_t *sm, int buf_this);
151 static void bsm12_error_helper(bsm12_t *sm, int buf_this);
154 bsm12_process_status(bsm12_t *sm, uint32_t status)
157 if ((status & sm->bps_error_or_done) == 0 || !sm->running)
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);
165 if (status & (BPS_ERROR(sm->buf0 + 1)))
166 bsm12_error_helper(sm, sm->buf0 + 1);
168 if (status & (BPS_ERROR(sm->buf0 + 2)))
169 bsm12_error_helper(sm, sm->buf0 + 2);
172 if (status & BPS_DONE(sm->buf0 + 0))
173 bsm12_process_helper(sm, sm->buf0 + 0);
175 if (status & BPS_DONE(sm->buf0 + 1))
176 bsm12_process_helper(sm, sm->buf0 + 1);
178 if (status & BPS_DONE(sm->buf0 + 2))
179 bsm12_process_helper(sm, sm->buf0 + 2);
183 bsm12_process_helper(bsm12_t *sm, int buf_this)
188 bsm12_error_helper(bsm12_t *sm, int buf_this)
190 bp_clear_buf(buf_this); // clears ERROR flag
192 if (buffer_state[buf_this] == BS_FILLING){
193 bsm12_receive_to_buf(sm, buf_this); // restart the xfer
195 else { // buffer was emptying
196 bsm12_resend_from_buf(sm, buf_this); // restart the xfer
202 bsm12_handle_tx_underrun(bsm12_t *sm)
207 bsm12_handle_rx_overrun(bsm12_t *sm)