1 | #ifndef KERNEL |
---|
2 | #define KERNEL |
---|
3 | #endif |
---|
4 | |
---|
5 | #include <rtems.h> |
---|
6 | #include <rtems/rtems_bsdnet_internal.h> |
---|
7 | #include <bsp.h> |
---|
8 | #include <sys/param.h> |
---|
9 | #include <sys/mbuf.h> |
---|
10 | |
---|
11 | #include "mv64340_eth_ll.h" |
---|
12 | |
---|
13 | #include <string.h> |
---|
14 | #include <assert.h> |
---|
15 | |
---|
16 | #include <netinet/in.h> |
---|
17 | #include <stdio.h> |
---|
18 | |
---|
19 | #define RX_SPACING 1 |
---|
20 | #define TX_SPACING 1 |
---|
21 | |
---|
22 | #define RX_RING_SIZE (MV64340_RX_QUEUE_SIZE*RX_SPACING) |
---|
23 | #define TX_RING_SIZE (MV64340_TX_QUEUE_SIZE*TX_SPACING) |
---|
24 | |
---|
25 | |
---|
26 | struct eth_rx_desc rx_ring[RX_RING_SIZE] __attribute__((aligned(32))); |
---|
27 | struct eth_rx_desc rx_ring[RX_RING_SIZE] = {{0},}; |
---|
28 | |
---|
29 | struct eth_tx_desc tx_ring[TX_RING_SIZE] __attribute__((aligned(32))); |
---|
30 | struct eth_tx_desc tx_ring[TX_RING_SIZE] = {{0},}; |
---|
31 | |
---|
32 | /* packet buffers */ |
---|
33 | char rx_buf[MV64340_RX_QUEUE_SIZE][2048] __attribute__((aligned(8))); |
---|
34 | char rx_buf[MV64340_RX_QUEUE_SIZE][2048]; |
---|
35 | |
---|
36 | char tx_buf[MV64340_RX_QUEUE_SIZE][2048] __attribute__((aligned(8))); |
---|
37 | char tx_buf[MV64340_RX_QUEUE_SIZE][2048]; |
---|
38 | |
---|
39 | char BcHeader[22] = { |
---|
40 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* dst */ |
---|
41 | 0x00, 0x01, 0xaf, 0x13, 0xb5, 0x3e, /* src */ |
---|
42 | 00, 00, /* len */ |
---|
43 | 0xAA, /* dsap */ |
---|
44 | 0xAA, /* ssap */ |
---|
45 | 0x03, /* ctrl */ |
---|
46 | 0x08, 0x00, 0x56, /* snap_org [stanford] */ |
---|
47 | 0x80, 0x5b, /* snap_type (stanford kernel) */ |
---|
48 | }; |
---|
49 | |
---|
50 | struct mv64340_private mveth = { |
---|
51 | port_num: 0, |
---|
52 | port_mac_addr: {0x00,0x01,0xAF,0x13,0xB5,0x3C}, |
---|
53 | /* port_config .. tx_resource_err are set by port_init */ |
---|
54 | 0 |
---|
55 | }; |
---|
56 | |
---|
57 | struct pkt_info p0,p1; |
---|
58 | |
---|
59 | static inline void rx_stopq(int port) |
---|
60 | { |
---|
61 | MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port), 0x0000ff00); |
---|
62 | } |
---|
63 | |
---|
64 | static inline void tx_stopq(int port) |
---|
65 | { |
---|
66 | MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port), 0x0000ff00); |
---|
67 | } |
---|
68 | |
---|
69 | #define MV64360_ENET2MEM_SNOOP_NONE 0x0000 |
---|
70 | #define MV64360_ENET2MEM_SNOOP_WT 0x1000 |
---|
71 | #define MV64360_ENET2MEM_SNOOP_WB 0x2000 |
---|
72 | |
---|
73 | #if 0 |
---|
74 | int |
---|
75 | mveth_init(struct mv64340_private *mp) |
---|
76 | { |
---|
77 | int i; |
---|
78 | mp->p_rx_desc_area = rx_ring; |
---|
79 | mp->p_tx_desc_area = tx_ring; |
---|
80 | |
---|
81 | rx_stopq(mp->port_num); |
---|
82 | tx_stopq(mp->port_num); |
---|
83 | |
---|
84 | /* MotLoad has cache snooping disabled on the ENET2MEM windows. |
---|
85 | * Some comments in (linux) indicate that there are errata |
---|
86 | * which cause problems which is a real bummer. |
---|
87 | * We try it anyways... |
---|
88 | */ |
---|
89 | { |
---|
90 | unsigned long disbl, bar; |
---|
91 | disbl = MV_READ(MV64340_ETH_BASE_ADDR_ENABLE_REG); |
---|
92 | /* disable all 6 windows */ |
---|
93 | MV_WRITE(MV64340_ETH_BASE_ADDR_ENABLE_REG, 0x3f); |
---|
94 | /* set WB snooping */ |
---|
95 | for ( i=0; i<6*8; i+=8 ) { |
---|
96 | if ( (bar = MV_READ(MV64340_ETH_BAR_0 + i)) && MV_READ(MV64340_ETH_SIZE_REG_0 + i) ) { |
---|
97 | MV_WRITE(MV64340_ETH_BAR_0 + i, bar | MV64360_ENET2MEM_SNOOP_WB); |
---|
98 | /* read back to flush fifo [linux comment] */ |
---|
99 | (void)MV_READ(MV64340_ETH_BAR_0 + i); |
---|
100 | } |
---|
101 | } |
---|
102 | /* restore/re-enable */ |
---|
103 | MV_WRITE(MV64340_ETH_BASE_ADDR_ENABLE_REG, disbl); |
---|
104 | } |
---|
105 | |
---|
106 | eth_port_init(mp); |
---|
107 | |
---|
108 | sleep(1); |
---|
109 | |
---|
110 | mveth_init_tx_desc_ring(mp); |
---|
111 | mveth_init_rx_desc_ring(mp); |
---|
112 | #if 0 |
---|
113 | for ( i = 0; i<MV64340_RX_QUEUE_SIZE; i++ ) { |
---|
114 | p0.byte_cnt = sizeof(rx_buf[0]); |
---|
115 | p0.buf_ptr = (dma_addr_t)rx_buf[i]; |
---|
116 | p0.return_info = (void*)i; |
---|
117 | /* other fields are not used by ll driver */ |
---|
118 | assert ( ETH_OK == eth_rx_return_buff(mp,&p0) ); |
---|
119 | } |
---|
120 | memset(&p0, 0, sizeof(p0)); |
---|
121 | #endif |
---|
122 | |
---|
123 | return eth_port_start(mp); |
---|
124 | } |
---|
125 | #endif |
---|
126 | |
---|
127 | void |
---|
128 | mveth_stop(struct mv64340_private *mp) |
---|
129 | { |
---|
130 | extern void mveth_stop_hw(); |
---|
131 | rtems_bsdnet_semaphore_obtain(); |
---|
132 | mveth_stop_hw(mp); |
---|
133 | rtems_bsdnet_semaphore_release(); |
---|
134 | } |
---|
135 | |
---|
136 | extern int mveth_send_mbuf(); |
---|
137 | extern int mveth_swipe_tx(); |
---|
138 | |
---|
139 | int |
---|
140 | mveth_tx(struct mv64340_private *mp, char *data, int len, int nbufs) |
---|
141 | { |
---|
142 | int rval = -1,l; |
---|
143 | char *p; |
---|
144 | struct mbuf *m; |
---|
145 | char *emsg = 0; |
---|
146 | |
---|
147 | rtems_bsdnet_semaphore_obtain(); |
---|
148 | MGETHDR(m, M_WAIT, MT_DATA); |
---|
149 | if ( !m ) { |
---|
150 | emsg="Unable to allocate header\n"; |
---|
151 | goto bail; |
---|
152 | } |
---|
153 | MCLGET(m, M_WAIT); |
---|
154 | if ( !(m->m_flags & M_EXT) ) { |
---|
155 | m_freem(m); |
---|
156 | emsg="Unable to allocate cluster\n"; |
---|
157 | goto bail; |
---|
158 | } |
---|
159 | p = mtod(m, char *); |
---|
160 | l = 0; |
---|
161 | switch (nbufs) { |
---|
162 | case 3: |
---|
163 | default: |
---|
164 | emsg="nbufs arg must be 1..3\n"; |
---|
165 | goto bail; |
---|
166 | |
---|
167 | case 1: |
---|
168 | l += sizeof(BcHeader); |
---|
169 | memcpy(p, &BcHeader, sizeof(BcHeader)); |
---|
170 | p += sizeof(BcHeader); |
---|
171 | |
---|
172 | case 2: |
---|
173 | memcpy(p,data,len); |
---|
174 | l += len; |
---|
175 | m->m_len = m->m_pkthdr.len = l; |
---|
176 | if ( 2 == nbufs ) { |
---|
177 | M_PREPEND(m, sizeof (BcHeader), M_WAIT); |
---|
178 | if (!m) { |
---|
179 | emsg = "Unable to prepend\n"; |
---|
180 | goto bail; |
---|
181 | } |
---|
182 | p = mtod(m, char*); |
---|
183 | memcpy(p,&BcHeader,sizeof(BcHeader)); |
---|
184 | l += sizeof(BcHeader); |
---|
185 | } |
---|
186 | break; |
---|
187 | } |
---|
188 | *(short*)(mtod(m, char*) + 12) = htons(l-14); |
---|
189 | rval = mveth_send_mbuf(mp,m); |
---|
190 | |
---|
191 | bail: |
---|
192 | rtems_bsdnet_semaphore_release(); |
---|
193 | if (emsg) |
---|
194 | printf(emsg); |
---|
195 | |
---|
196 | #if 0 |
---|
197 | /* |
---|
198 | * Add local net header. If no space in first mbuf, |
---|
199 | * allocate another. |
---|
200 | */ |
---|
201 | M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); |
---|
202 | if (m == 0) |
---|
203 | senderr(ENOBUFS); |
---|
204 | eh = mtod(m, struct ether_header *); |
---|
205 | (void)memcpy(&eh->ether_type, &type, |
---|
206 | sizeof(eh->ether_type)); |
---|
207 | (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); |
---|
208 | (void)memcpy(eh->ether_shost, ac->ac_enaddr, |
---|
209 | sizeof(eh->ether_shost)); |
---|
210 | #endif |
---|
211 | return rval; |
---|
212 | } |
---|
213 | |
---|
214 | int |
---|
215 | mveth_protected(int (*p)(struct mv64340_private*), struct mv64340_private *mp) |
---|
216 | { |
---|
217 | int rval; |
---|
218 | rtems_bsdnet_semaphore_obtain(); |
---|
219 | rval = p(mp); |
---|
220 | rtems_bsdnet_semaphore_release(); |
---|
221 | return rval; |
---|
222 | } |
---|
223 | |
---|
224 | int |
---|
225 | mveth_rx(struct mv64340_private *mp) |
---|
226 | { |
---|
227 | extern int mveth_swipe_rx(); |
---|
228 | return mveth_protected(mveth_swipe_rx,mp); |
---|
229 | } |
---|
230 | |
---|
231 | int |
---|
232 | mveth_reclaim(struct mv64340_private *mp) |
---|
233 | { |
---|
234 | extern int mveth_swipe_tx(); |
---|
235 | return mveth_protected(mveth_swipe_tx,mp); |
---|
236 | } |
---|
237 | |
---|
238 | |
---|
239 | int preth(FILE *f, char *p) |
---|
240 | { |
---|
241 | int i; |
---|
242 | for (i=0; i<4; i++) |
---|
243 | fprintf(f,"%02X:",p[i]); |
---|
244 | fprintf(f,"%02X",p[i]); |
---|
245 | return 6; |
---|
246 | } |
---|
247 | |
---|
248 | char *errcode2str(st) |
---|
249 | { |
---|
250 | char *rval; |
---|
251 | switch(st) { |
---|
252 | case ETH_OK: |
---|
253 | rval = "OK"; |
---|
254 | break; |
---|
255 | case ETH_ERROR: |
---|
256 | rval = "Fundamental error."; |
---|
257 | break; |
---|
258 | case ETH_RETRY: |
---|
259 | rval = "Could not process request. Try later."; |
---|
260 | break; |
---|
261 | case ETH_END_OF_JOB: |
---|
262 | rval = "Ring has nothing to process."; |
---|
263 | break; |
---|
264 | case ETH_QUEUE_FULL: |
---|
265 | rval = "Ring resource error."; |
---|
266 | break; |
---|
267 | case ETH_QUEUE_LAST_RESOURCE: |
---|
268 | rval = "Ring resources about to exhaust."; |
---|
269 | break; |
---|
270 | default: |
---|
271 | rval = "UNKNOWN"; break; |
---|
272 | } |
---|
273 | return rval; |
---|
274 | } |
---|
275 | |
---|
276 | |
---|
277 | #if 0 |
---|
278 | int |
---|
279 | mveth_rx(struct mv64340_private *mp) |
---|
280 | { |
---|
281 | int st; |
---|
282 | struct pkt_info p; |
---|
283 | if ( ETH_OK != (st=eth_port_receive(mp, &p)) ) { |
---|
284 | fprintf(stderr,"receive: %s\n", errcode2str(st)); |
---|
285 | return -1; |
---|
286 | } |
---|
287 | printf("%i bytes received from ", p.byte_cnt); |
---|
288 | preth(stdout,(char*)p.buf_ptr+6); |
---|
289 | printf(" (desc. stat: 0x%08x)\n", p.cmd_sts); |
---|
290 | |
---|
291 | p.byte_cnt = sizeof(rx_buf[0]); |
---|
292 | p.buf_ptr -= RX_BUF_OFFSET; |
---|
293 | if ( ETH_OK != (st=eth_rx_return_buff(mp,&p) ) ) { |
---|
294 | fprintf(stderr,"returning buffer: %s\n", errcode2str(st)); |
---|
295 | return -1; |
---|
296 | } |
---|
297 | return 0; |
---|
298 | } |
---|
299 | #endif |
---|
300 | |
---|
301 | int |
---|
302 | dring() |
---|
303 | { |
---|
304 | int i; |
---|
305 | if (1) { |
---|
306 | struct eth_rx_desc *pr; |
---|
307 | printf("RX:\n"); |
---|
308 | for (i=0, pr=rx_ring; i<RX_RING_SIZE; i+=RX_SPACING, pr+=RX_SPACING) { |
---|
309 | dcbi(pr); |
---|
310 | printf("cnt: 0x%04x, size: 0x%04x, stat: 0x%08x, next: 0x%08x, buf: 0x%08x\n", |
---|
311 | pr->byte_cnt, pr->buf_size, pr->cmd_sts, pr->next_desc_ptr, pr->buf_ptr); |
---|
312 | } |
---|
313 | } |
---|
314 | if (1) { |
---|
315 | struct eth_tx_desc *pt; |
---|
316 | printf("TX:\n"); |
---|
317 | for (i=0, pt=tx_ring; i<TX_RING_SIZE; i+=TX_SPACING, pt+=TX_SPACING) { |
---|
318 | dcbi(pt); |
---|
319 | printf("cnt: 0x%04x, stat: 0x%08x, next: 0x%08x, buf: 0x%08x\n", |
---|
320 | pt->byte_cnt, pt->cmd_sts, pt->next_desc_ptr, pt->buf_ptr); |
---|
321 | } |
---|
322 | } |
---|
323 | return 0; |
---|
324 | } |
---|