Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: core.fth | |
4 | \ | |
5 | \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | \ | |
7 | \ - Do no alter or remove copyright notices | |
8 | \ | |
9 | \ - Redistribution and use of this software in source and binary forms, with | |
10 | \ or without modification, are permitted provided that the following | |
11 | \ conditions are met: | |
12 | \ | |
13 | \ - Redistribution of source code must retain the above copyright notice, | |
14 | \ this list of conditions and the following disclaimer. | |
15 | \ | |
16 | \ - Redistribution in binary form must reproduce the above copyright notice, | |
17 | \ this list of conditions and the following disclaimer in the | |
18 | \ documentation and/or other materials provided with the distribution. | |
19 | \ | |
20 | \ Neither the name of Sun Microsystems, Inc. or the names of contributors | |
21 | \ may be used to endorse or promote products derived from this software | |
22 | \ without specific prior written permission. | |
23 | \ | |
24 | \ This software is provided "AS IS," without a warranty of any kind. | |
25 | \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
26 | \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
27 | \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
28 | \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
29 | \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
30 | \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
31 | \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
32 | \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
33 | \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
34 | \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
35 | \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
36 | \ | |
37 | \ You acknowledge that this software is not designed, licensed or | |
38 | \ intended for use in the design, construction, operation or maintenance of | |
39 | \ any nuclear facility. | |
40 | \ | |
41 | \ ========== Copyright Header End ============================================ | |
42 | id: @(#)core.fth 1.2 06/05/11 | |
43 | purpose: Intel Ophir/82571 Core routines | |
44 | copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved | |
45 | copyright: Use is subject to license terms. | |
46 | ||
47 | headerless | |
48 | 0 instance value restart? | |
49 | defer restart-net ['] true to restart-net | |
50 | \ ============================================================================ | |
51 | \ Data structures | |
52 | \ ---------------------------------------------------------------------------- | |
53 | ||
54 | \ RX descriptor | |
55 | struct | |
56 | /x field >rx-buf \ Pointer to data buffer | |
57 | /w field >rx-length \ Length of data buffer | |
58 | /w field >rx-csum \ Checksum | |
59 | /c field >rx-status | |
60 | /c field >rx-error | |
61 | /w field >rx-special \ Special - unused (needed for VLAN) | |
62 | constant /rxd | |
63 | ||
64 | \ RX Status bits | |
65 | h# 01 constant rxstat.dd \ Descriptor done | |
66 | h# 02 constant rxstat.eop \ End of packet | |
67 | h# 04 constant rxstat.ixsm \ Ignore checksum indication | |
68 | \ Ignore bits 3-7. | |
69 | \ RX Error bits | |
70 | h# 01 constant rxerr.ce \ CRC or alignment error | |
71 | h# 02 constant rxerr.se \ Symbol error (TBI) | |
72 | h# 04 constant rxerr.seq \ Sequence error (TBI) | |
73 | \ Ignore other errors - applicable to | |
74 | \ offload features. | |
75 | ||
76 | \ Miscellaneous rx constants and pointers | |
77 | h# 40 constant #rxds \ Number of rx descriptors | |
78 | #rxds /rxd * constant /rxd-ring \ Size of rx descriptor table | |
79 | 0 value rxd-base \ Base of descriptor table | |
80 | 0 value rxd-end \ End of descriptor table in bytes. | |
81 | 0 value rxd-tail \ Shadow of hardware tail pointer. | |
82 | 0 value rxd-dma-base \ Hardware address of descriptor array. | |
83 | d# 2048 constant /rx-buf \ Size of one rx buffer | |
84 | /rx-buf #rxds * | |
85 | constant /rx-buf-array \ Total amount of memory allocated for | |
86 | \ rx buffers. | |
87 | 0 value rx-buf-base \ Base of rx buffer array | |
88 | ||
89 | \ TX descriptor | |
90 | struct | |
91 | /x field >tx-buf \ Pointer to data buffer | |
92 | /w field >tx-length \ Length of data buffer | |
93 | /c field >tx-cso \ Checksum offset (optional) | |
94 | /c field >tx-cmd \ Command | |
95 | /c field >tx-status | |
96 | /c field >tx-css \ Checksum Start field (optional) | |
97 | /w field >tx-special \ Special - unused (needed for VLAN) | |
98 | constant /txd | |
99 | ||
100 | \ TX command bits | |
101 | h# 01 constant txcmd.eop \ End of packet | |
102 | h# 02 constant txcmd.ifcs \ Insert Frame checksum | |
103 | h# 08 constant txcmd.rs \ Report status | |
104 | \ All other bits ignored | |
105 | ||
106 | \ TX status bits | |
107 | h# 01 constant txstat.dd \ Descriptor done. | |
108 | h# 02 constant txstat.ec \ Excess collisions | |
109 | h# 04 constant txstat.lc \ Late collision | |
110 | ||
111 | \ TX constants and pointers | |
112 | h# 8 constant #txds \ Number of tx descriptors | |
113 | \ (8 is the smallest possible) | |
114 | #txds /txd * constant /tx-ring \ Size of tx descriptor table | |
115 | 0 value txd-base \ Base of descriptor table | |
116 | 0 value txd-end \ End of descriptor table in bytes | |
117 | 0 value txd-current \ Currently being transmitted buffer | |
118 | 0 value txd-tail \ Shadow of hardware tail pointer | |
119 | 0 value txd-dma-base \ Hardware address of descriptor array | |
120 | ||
121 | d# 2048 constant /tx-buf \ Size of one tx buffer | |
122 | /tx-buf #txds * | |
123 | constant /tx-buf-array \ Total amount of memory | |
124 | \ allocated for tx buffers. | |
125 | 0 value tx-buf-base \ Base of tx buffer array | |
126 | ||
127 | \ | |
128 | \ Memory layout: starting from cpu-dma-blk (which is therefore the same | |
129 | \ as rxd-base) | |
130 | \ Base Size Comments | |
131 | \ ========== ===== ======== | |
132 | \ rxd-base /rxd-ring rx descriptors | |
133 | \ rx-buf-base /rx-buf-array rx data buffers | |
134 | \ txd-base /tx-ring tx descriptors | |
135 | \ tx-buf-base /tx-buf-array tx buffers | |
136 | \ | |
137 | \ Set value of /dma-blk for "map-buffers" | |
138 | \ | |
139 | /rxd-ring /rx-buf-array + ( /rx-data ) | |
140 | /tx-ring /tx-buf-array + ( /rx-data /tx-data ) | |
141 | + /rxd + is /dma-blk \ Add /rxd to allow for alignment rounding. | |
142 | ||
143 | : rxd>d# ( desc -- index ) | |
144 | rxd-base - /rxd / | |
145 | ; | |
146 | ||
147 | \ Write a value to the rx tail register | |
148 | : rx-tail! ( desc -- ) | |
149 | rxd>d# h# 2818 reg! | |
150 | ; | |
151 | ||
152 | : txd>d# ( desc -- index ) | |
153 | txd-base - /txd / | |
154 | ; | |
155 | ||
156 | \ Write a value to the tx tail register | |
157 | : tx-tail! ( desc -- ) | |
158 | txd-base - /txd / h# 3818 reg! | |
159 | ; | |
160 | ||
161 | \ | |
162 | \ Initialize the rx and tx descriptor rings and buffers. | |
163 | \ We aren't telling the hardware about these yet. | |
164 | \ | |
165 | : .rx-ring ( -- ) | |
166 | ." Head: " h# 2810 reg@ .x | |
167 | ." Tail: " h# 2818 reg@ .x cr | |
168 | rxd-base #rxds 0 do | |
169 | dup i /rxd * + ( adr desc ) | |
170 | dup local-x@ .x /x + local-x@ .x cr | |
171 | loop | |
172 | drop | |
173 | ; | |
174 | ||
175 | : .tx-ring ( -- ) | |
176 | ." Head: " h# 3810 reg@ .x | |
177 | ." Tail: " h# 3818 reg@ .x cr | |
178 | txd-base #txds 0 do | |
179 | dup i /txd * + | |
180 | dup local-x@ .x /x + local-x@ .x cr | |
181 | loop | |
182 | drop | |
183 | ; | |
184 | ||
185 | : init-rings ( base -- ) | |
186 | dup >r ( base ) ( r: base ) | |
187 | /rxd round-up ( desc-base ) \ Align descriptor base | |
188 | dup is rxd-base | |
189 | \ Tail starts off as first descriptor (head will be second) | |
190 | \ That is, all buffers start off belonging to the chip, | |
191 | \ except the tail itself. | |
192 | dup is rxd-tail ( desc ) | |
193 | cpu>io-adr is rxd-dma-base ( ) | |
194 | ||
195 | rxd-base /rxd-ring + dup is rx-buf-base is rxd-end | |
196 | #rxds 0 do | |
197 | i /rx-buf * rx-buf-base + cpu>io-adr ( dma-adr ) | |
198 | i /rxd * rxd-base + tuck ( desc-adr dma-adr desc-adr ) | |
199 | \ Write the buffer address to the descriptor | |
200 | >rx-buf local-x! ( desc-adr ) | |
201 | \ Clear the flags (buffer belongs to hw) | |
202 | 0 swap >rx-length local-x! ( ) | |
203 | loop | |
204 | ||
205 | rx-buf-base /rx-buf-array + is txd-base | |
206 | txd-base is txd-tail | |
207 | txd-base /tx-ring + dup is tx-buf-base is txd-end | |
208 | txd-base cpu>io-adr is txd-dma-base | |
209 | #txds 0 do | |
210 | i /tx-buf * tx-buf-base + cpu>io-adr ( dma-adr ) | |
211 | i /txd * txd-base + tuck ( desc dma-adr desc ) | |
212 | \ Write the buffer address to the descriptor | |
213 | >tx-buf local-x! ( desc ) | |
214 | \ Clear the rest of the descriptor | |
215 | 0 over >tx-length local-x! ( desc ) | |
216 | \ Initialize command register. | |
217 | txcmd.rs txcmd.eop or txcmd.ifcs or swap >tx-cmd local-c! | |
218 | loop | |
219 | \ Sync it all back to mem. | |
220 | r> dup cpu>io-adr /dma-blk dma-sync ( ) ( r: ) | |
221 | ; | |
222 | ||
223 | \ ============================================================================ | |
224 | \ Receive routines. | |
225 | \ ---------------------------------------------------------------------------- | |
226 | ||
227 | \ Move to the next rx descriptor in the ring (ie | |
228 | \ wrap if needed). | |
229 | : next-rxd ( desc -- next-desc ) | |
230 | /rxd + | |
231 | dup rxd-end >= if | |
232 | drop rxd-base | |
233 | then | |
234 | ; | |
235 | ||
236 | : sync-rxd ( desc -- ) dup cpu>io-adr /rxd dma-sync ; | |
237 | : sync-rx-buf ( desc -- ) >rx-buf local@ dup io>cpu-adr swap /rx-buf dma-sync ; | |
238 | ||
239 | : return-buffer ( handle -- ) | |
240 | \ Clear status | |
241 | 0 over >rx-status local-c! ( desc ) | |
242 | 0 over >rx-length local-w! | |
243 | dup sync-rx-buf | |
244 | dup rx-tail! ( desc ) | |
245 | is rxd-tail ( ) | |
246 | ; | |
247 | ||
248 | : receive-ready? ( -- pkt-waiting? ) | |
249 | rxd-tail next-rxd | |
250 | dup sync-rxd ( desc ) | |
251 | >rx-status local-c@ ( status ) | |
252 | rxstat.dd and 0<> ( pkt-waiting? ) | |
253 | ; | |
254 | ||
255 | : receive ( -- pkt-handle pkt pktlen ) | |
256 | rxd-tail next-rxd ( desc ) | |
257 | dup >rx-buf local-x@ io>cpu-adr ( desc pkt ) | |
258 | over >rx-length local-w@ ( desc pkt len desc ) | |
259 | ; | |
260 | ||
261 | \ ============================================================================ | |
262 | \ Main transmit routines | |
263 | \ ---------------------------------------------------------------------------- | |
264 | ||
265 | \ Move to the next tx descriptor in the ring (ie | |
266 | \ wrap if needed). | |
267 | : next-txd ( desc -- next-desc ) | |
268 | /txd + | |
269 | dup txd-end >= if | |
270 | drop txd-base | |
271 | then | |
272 | ; | |
273 | ||
274 | : sync-tx-buf ( desc -- ) | |
275 | \ Might as well sync the descriptor here also. | |
276 | dup dup cpu>io-adr /txd dma-sync | |
277 | >tx-buf local-x@ dup io>cpu-adr swap /tx-buf dma-sync | |
278 | ; | |
279 | ||
280 | : transmit-complete? ( desc -- complete? ) | |
281 | >tx-status local-c@ txstat.dd and 0<> | |
282 | ; | |
283 | ||
284 | \ Wait for up to 4 seconds for the transmit to complete. | |
285 | : send-wait ( desc -- ok? ) | |
286 | d# 4000 get-msecs + ( desc tout ) | |
287 | begin | |
288 | dup get-msecs >= while ( desc tout ) | |
289 | over transmit-complete? if | |
290 | 2drop true exit | |
291 | then | |
292 | repeat ( desc tout ) | |
293 | 2drop | |
294 | " Timeout waiting for transmit completion" diag-type-cr | |
295 | true to restart? | |
296 | false | |
297 | ; | |
298 | ||
299 | : transmit ( buf len -- ok? ) | |
300 | txd-tail >r ( buf len ) ( r: desc ) | |
301 | dup r@ >tx-length local-w! \ Set length | |
302 | r@ >tx-buf local-x@ io>cpu-adr swap cmove ( ) \ Copy data | |
303 | 0 r@ >tx-status local-c! | |
304 | r@ sync-tx-buf | |
305 | ||
306 | \ Increment shadow tail pointer. | |
307 | r> dup next-txd dup to txd-tail ( desc desc' ) ( r: ) | |
308 | \ Write updated tail pointer to hardware (starts transmit) | |
309 | tx-tail! ( desc ) | |
310 | \ Wait for the transmit to complete. | |
311 | send-wait ( ok? ) | |
312 | \ At this point, errors we can see are: | |
313 | \ Timeout waiting for send to complete - maybe need to restart net | |
314 | \ Excess collisions. | |
315 | \ Late collision. | |
316 | ; | |
317 | ||
318 | : get-tx-buffer ( -- adr ) | |
319 | txd-tail >tx-buf local@ io>cpu-adr | |
320 | ; | |
321 | ||
322 | \ ============================================================================ | |
323 | \ Initialization routines | |
324 | \ ---------------------------------------------------------------------------- | |
325 | ||
326 | \ Control register: address 0x0000 | |
327 | : ctrl@ ( -- value ) 0 reg@ ; | |
328 | : ctrl! ( value -- ) 0 reg! ; | |
329 | 1 d# 26 << constant ctrl.rst | |
330 | 1 d# 05 << constant ctrl.asde | |
331 | 1 d# 06 << constant ctrl.slu | |
332 | ||
333 | \ Receive address registers: | |
334 | \ Low: 5400 + 8*i | |
335 | \ Hi: 5404 + 8*i | |
336 | ||
337 | \ Set receive address low register[i] | |
338 | : ral! ( val i -- ) | |
339 | 8 * h# 5400 + reg! | |
340 | ; | |
341 | \ Set the i'th receive address hi register[i] | |
342 | : rah! ( val i -- ) | |
343 | 8 * h# 5404 + reg! | |
344 | ; | |
345 | : ra! ( val i -- ) | |
346 | 8 * h# 5400 + regx! | |
347 | ; | |
348 | ||
349 | ||
350 | : reset-chip ( -- ) | |
351 | ctrl.rst ctrl! | |
352 | 10 ms | |
353 | \ Assume reset has completed. | |
354 | ; | |
355 | ||
356 | : clear-multicast-table ( -- ) | |
357 | h# 5400 h# 5200 do | |
358 | 0 i reg! | |
359 | /l +loop | |
360 | ; | |
361 | ||
362 | ||
363 | \ Set the mac address in the receive address 0 registers. | |
364 | \ Clear the remaining registers and the multicast table array. | |
365 | ||
366 | : set-mac-address ( -- ) | |
367 | clear-multicast-table | |
368 | mac-address drop ( mac-adr-ptr ) | |
369 | dup w@ wbflip | |
370 | over 2 + w@ wbflip wljoin 0 ral! ( mac-adr-ptr ) | |
371 | 4 + w@ wbflip h# 8000.0000 or 0 rah! | |
372 | \ Clear remaining receive address registers. | |
373 | d# 16 1 do | |
374 | 0 i ral! | |
375 | 0 i rah! | |
376 | loop | |
377 | ; | |
378 | ||
379 | : set-promis-mode ( -- ) | |
380 | h# 18 h# 0100 reg-bset \ Set upe and mpe | |
381 | ; | |
382 | ||
383 | : init-mac-mode ( -- ) | |
384 | mac-mode case | |
385 | promiscuous of set-promis-mode endof | |
386 | endcase | |
387 | ; | |
388 | ||
389 | : init-receive ( -- ) | |
390 | set-mac-address | |
391 | 0 h# 2820 reg! \ Clear receive delay timer | |
392 | 0 h# 282c reg! \ Clear receive absolute timer reg | |
393 | /rxd-ring h# 2808 reg! \ Set receive descriptor length reg | |
394 | \ Set the rx descriptor base address | |
395 | rxd-base cpu>io-adr xlsplit h# 2804 reg! ( base.lo ) \ hi | |
396 | h# 2800 reg! \ lo | |
397 | rxd-tail rx-tail! \ Set tail (precalculated in init-rings) | |
398 | \ Give all the buffers to the chip: the tail pointer has already | |
399 | \ been initialized by init-rings - set the head to be the next descriptor. | |
400 | rxd-tail next-rxd | |
401 | rxd>d# h# 2810 reg! | |
402 | h# 0001.0101 h# 2828 reg! \ rx descriptor control | |
403 | \ Receive control: | |
404 | \ Enable: 0000.0002 On. | |
405 | \ Store bad packets: 0000.0004 Off. | |
406 | \ Promiscuous bits: 0000.0018 Off. | |
407 | \ Long packet enable: 0000.0020 Off. | |
408 | \ Loopback mode: 0000.00c0 No loopback | |
409 | \ RDMTS 0000.0300 Don't care. 0 is ok. | |
410 | \ Multicast offset: 0000.3000 Don't care. 0 is ok. | |
411 | \ Accept broadcast: 0000.8000 On. | |
412 | \ Receive buf size: 0003.0000 0 == 2048 byte buffers. | |
413 | \ Vlan Filter: 0004.0000 Off | |
414 | \ CFI bits: 0018.0000 Off. | |
415 | \ Discard pause frames: 0040.0000 On. | |
416 | \ Pass mac control: 0080.0000 Off. | |
417 | \ BSEX: 0200.0000 Off. None of that thank you! | |
418 | \ Strip crc: 0400.0000 Off. | |
419 | \ | |
420 | h# 0040.8002 h# 0100 reg-bset \ Now receiving! | |
421 | init-mac-mode | |
422 | ; | |
423 | ||
424 | : init-transmit ( -- ) | |
425 | \ Set transmit descriptor base address | |
426 | txd-base cpu>io-adr xlsplit h# 3804 reg! ( base.lo ) \ hi | |
427 | h# 3800 reg! ( ) \ lo | |
428 | /tx-ring h# 3808 reg! \ Transmit descriptor ring length | |
429 | \ Start the head and tail pointers pointing to the same value | |
430 | \ (doesn't matter which it is). | |
431 | txd-tail tx-tail! \ Transmit descriptor tail | |
432 | txd-tail txd>d# h# 3810 reg! \ Transmit descriptor head | |
433 | h# 60200a h# 0410 reg! \ Inter-packet gap register. | |
434 | \ Transmit control: | |
435 | \ Enable: 0000.0002 On | |
436 | \ Pad short packets: 0000.0004 On (per manual) | |
437 | \ Collision threshold: 0000.00f0 Value = 0xf (recommended) | |
438 | \ Collision distance: 0020.0000 0x40 bytes (half-duplex) | |
439 | \ Software xoff 0040.0000 Off | |
440 | \ Retransmit on late col: 0100.0000 Off | |
441 | h# 0004.00fe h# 400 reg! | |
442 | ; | |
443 | ||
444 | : init-chip ( -- ) | |
445 | ctrl.slu ctrl.asde or ctrl! \ Set control register - enable PHY | |
446 | 0 h# 00c8 reg! \ Clear all interrupt cause set bits | |
447 | h# ffff.ffff h# 00d8 reg! \ Mask all interrupts. | |
448 | 0 h# 0178 reg! \ Clear txcw | |
449 | cpu-dma-base init-rings \ Initialize the memory structures | |
450 | init-receive | |
451 | init-transmit | |
452 | ; | |
453 | ||
454 | : net-on ( -- ok? ) | |
455 | reset-chip | |
456 | init-chip | |
457 | true | |
458 | ; | |
459 | ||
460 | : net-off ( -- ) | |
461 | 2 h# 100 reg-bclear \ Disable rx | |
462 | 2 h# 400 reg-bclear \ Disable tx | |
463 | reset-chip | |
464 | ; |