| 1 | \ ========== Copyright Header Begin ========================================== |
| 2 | \ |
| 3 | \ Hypervisor Software File: methods.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: @(#)methods.fth 1.5 07/06/22 |
| 43 | purpose: |
| 44 | copyright: Copyright 2007 Sun Microsystems, Inc. All rights reserved. |
| 45 | copyright: Use is subject to license terms. |
| 46 | |
| 47 | headerless |
| 48 | |
| 49 | fload ${BP}/dev/sun4v-devices/ldc/methods.fth |
| 50 | |
| 51 | false value debug-vnet? |
| 52 | false value debug-tcp? |
| 53 | |
| 54 | fload ${BP}/dev/sun4v-devices/vcommon/vio-struct.fth |
| 55 | fload ${BP}/dev/sun4v-devices/vcommon/vio-methods.fth |
| 56 | |
| 57 | vdev-net-client to current-vio-dev |
| 58 | h# 1000 value vnet-sid \ Variable to hold sequence id |
| 59 | 0 value vnet-seq \ seq# for the next request |
| 60 | 0 value cur-vnet-seq \ seq# of the current request |
| 61 | 0 value vnet-tmpbuf |
| 62 | d# 200 value vnet-retries \ Variable to hold number of retries |
| 63 | 0 value vnet-opened? \ Variable to indicate if vnet has established |
| 64 | \ connection with vswitch |
| 65 | |
| 66 | d# 1514 constant frame-size |
| 67 | |
| 68 | 0 value rx-buffer \ Transmit buffer |
| 69 | 0 value tx-buffer \ receive buffer |
| 70 | |
| 71 | 8 pagesize 0 claim to rx-buffer |
| 72 | 8 pagesize 0 claim to tx-buffer |
| 73 | |
| 74 | 0 value vnet-descr-buf \ Variable to hold Vnet descritor buffer |
| 75 | |
| 76 | /vnet-attr-msg /vnet-descr-msg max value /vnet-descr-buf |
| 77 | 0 value obp-tftp |
| 78 | 0 value ldc-up? \ flag, Set if LDC is up |
| 79 | |
| 80 | 6 buffer: mac-buf \ Variable to hold MAC Address |
| 81 | |
| 82 | 0 value vn-ldcid \ Variable to hold LDC id |
| 83 | |
| 84 | : inspect-vnet-port-nodes ( nptr -- ) |
| 85 | dup " switch-port" ascii v md-find-prop if ( port-ptr ptr|0 ) |
| 86 | " fwd" ascii a md-find-prop ( ldc-nptr|0 ) |
| 87 | dup if |
| 88 | md-decode-prop drop ( ldc-nptr ) |
| 89 | " id" ascii v md-find-prop ( idptr|0 ) |
| 90 | dup if |
| 91 | md-decode-prop drop to vn-ldcid |
| 92 | else |
| 93 | drop |
| 94 | then |
| 95 | else |
| 96 | drop |
| 97 | then |
| 98 | else |
| 99 | drop |
| 100 | then |
| 101 | ; |
| 102 | |
| 103 | : look-for-vn-ldcid ( -- ) |
| 104 | ['] inspect-vnet-port-nodes my-node md-applyto-fwds |
| 105 | ; |
| 106 | |
| 107 | look-for-vn-ldcid |
| 108 | |
| 109 | : init-obp-tftp ( tftp-args$ -- okay? ) |
| 110 | " obp-tftp" $open-package dup to obp-tftp ( pkg ) |
| 111 | if |
| 112 | true |
| 113 | else |
| 114 | cmn-warn[ " Can't open OBP standard TFTP package" ]cmn-end |
| 115 | false |
| 116 | then |
| 117 | ; |
| 118 | |
| 119 | \ The service domain may be down or rebooting... Keep retrying for 5 minutes |
| 120 | : open-vnet-ldc ( -- error? ) |
| 121 | get-msecs d# 300.000 + \ 5 minutes later |
| 122 | begin ( finish-time ) |
| 123 | get-msecs over < ( finish-time keep-trying? ) |
| 124 | while ( finish-time ) |
| 125 | vn-ldcid ldc-mode-unreliable ldc-open if ( finish-time ) |
| 126 | true to ldc-up? ( finish-time ) |
| 127 | drop false exit ( false ) |
| 128 | then ( finish-time ) |
| 129 | cmn-warn[ |
| 130 | " Timeout connecting to virtual switch... retrying" |
| 131 | ]cmn-end |
| 132 | d# 5000 ms ( finish-time ) |
| 133 | repeat |
| 134 | cmn-warn[ " Unable to connect to virtual switch" ]cmn-end |
| 135 | drop true ( true ) |
| 136 | ; |
| 137 | |
| 138 | : close-vnet-ldc ( -- ) |
| 139 | ldc-close 0 to ldc-up? |
| 140 | ; |
| 141 | |
| 142 | : receive-ready? ( -- ready? ) |
| 143 | ldc-pkt-available? |
| 144 | ; |
| 145 | |
| 146 | \ Only update seqid upon successful return because Solaris counter part |
| 147 | \ doesn't like new seqid if OBP higher level module do retries |
| 148 | : send-to-ldc ( buf len -- #sent ) |
| 149 | debug-vnet? if |
| 150 | cr ." vnet write : " 2dup swap u. u. cr |
| 151 | then |
| 152 | 0 vnet-retries 0 do ( buf len status ) |
| 153 | drop 2dup ( buf len buf len ) |
| 154 | ldc-write ( buf len #sent status ) |
| 155 | dup HV-EOK <> if ( buf len #sent status ) |
| 156 | dup HV-EWOULDBLOCK <> if ( buf len #sent status ) |
| 157 | dup LDC-NOTUP = if ( buf len #sent status ) |
| 158 | cmn-warn[ " Sending packet to LDC but LDC is Not Up!" ]cmn-end |
| 159 | 2drop 2drop 0 unloop exit ( 0 ) |
| 160 | then |
| 161 | cmn-warn[ " Sending packet to LDC, status: %d" ]cmn-end |
| 162 | 3drop 0 unloop exit |
| 163 | then |
| 164 | else ( buf len #sent status ) |
| 165 | cur-vnet-seq 1+ to vnet-seq |
| 166 | drop nip nip unloop exit ( #sent ) |
| 167 | then |
| 168 | nip ( buf len status ) |
| 169 | \ Every 20 loops, roughly 20 seconds (ldc-write can take @ 1s), |
| 170 | \ print a retrying message |
| 171 | i 1+ d# 20 mod 0= if |
| 172 | cmn-warn[ |
| 173 | " Timeout sending package to LDC ... retrying" |
| 174 | ]cmn-end |
| 175 | then |
| 176 | loop ( buf len status ) |
| 177 | 3drop 0 |
| 178 | cmn-warn[ " Sending packet to LDC timed out!" ]cmn-end |
| 179 | ; |
| 180 | |
| 181 | : receive-from-ldc ( buf len -- #bytes ) |
| 182 | 0 vnet-retries 0 do ( buf len status ) |
| 183 | drop 2dup ( buf len buf len ) |
| 184 | ldc-read ( buf len alen status ) |
| 185 | dup HV-EOK <> if ( buf len alen status ) |
| 186 | dup HV-EWOULDBLOCK <> if ( buf len alen status ) |
| 187 | dup LDC-NOTUP = if ( buf len alen status ) |
| 188 | cmn-warn[ |
| 189 | " Receiving packet from LDC but LDC is Not Up!" |
| 190 | ]cmn-end |
| 191 | 2drop 2drop 0 unloop exit ( 0 ) |
| 192 | then |
| 193 | cmn-warn[ " Receiving packet from LDC, status: %d" ]cmn-end 3drop 0 unloop exit ( 0 ) |
| 194 | then |
| 195 | else ( buf len alen status ) |
| 196 | \ If vnet-opened? is false and if we get EOK with Length = 0 then |
| 197 | \ treat it as EWOULDBLOCK at LDC layer and just retry |
| 198 | over vnet-opened? or if ( buf len alen status ) |
| 199 | drop nip nip unloop exit ( alen ) |
| 200 | then |
| 201 | then |
| 202 | nip ( buf len status ) |
| 203 | \ Every 20 loops, roughly 20 seconds (ldc-read can take @ 1s), |
| 204 | \ print a retrying message |
| 205 | i 1+ d# 20 mod 0= if |
| 206 | cmn-warn[ |
| 207 | " Timeout receiving packet from LDC ... retrying" |
| 208 | ]cmn-end |
| 209 | then |
| 210 | loop ( buf len status ) |
| 211 | 3drop 0 |
| 212 | cmn-warn[ " Receiving packet from LDC timed out!" ]cmn-end |
| 213 | ; |
| 214 | ' receive-from-ldc is retrieve-packet |
| 215 | |
| 216 | : receive ( -- len' ) |
| 217 | rx-buffer frame-size receive-from-ldc |
| 218 | ; |
| 219 | |
| 220 | : ldc-copy-in ( buf cookie size -- len ) |
| 221 | 0 vnet-retries 0 do ( buf cookie size status ) |
| 222 | drop 3dup |
| 223 | ldc-copy-in ( buf cookie size len status ) |
| 224 | dup HV-EOK <> if |
| 225 | dup HV-EWOULDBLOCK <> if |
| 226 | cmn-warn[ " Vnet-copy-in: status: %d" ]cmn-end |
| 227 | 2drop 2drop 0 unloop exit |
| 228 | then |
| 229 | else |
| 230 | drop nip nip nip unloop exit ( len ) |
| 231 | then ( buf cookie size len status ) |
| 232 | nip |
| 233 | loop ( buf cookie size status ) |
| 234 | 2drop 2drop 0 |
| 235 | cmn-warn[ " ldc-copy-in timed out!" ]cmn-end |
| 236 | ; |
| 237 | |
| 238 | : send-vnet-ver-msg ( -- ok? ) |
| 239 | vnet-descr-buf /vio-ver-msg erase |
| 240 | |
| 241 | \ vnet session id is only updated once during version negotiation |
| 242 | vnet-sid 1+ dup to vnet-sid |
| 243 | vnet-descr-buf >vio-sid l! |
| 244 | |
| 245 | vio-msg-type-ctrl vio-subtype-info vio-ver-info |
| 246 | vnet-descr-buf set-vio-msg-tag |
| 247 | |
| 248 | vdev-net-client vnet-minor vnet-major |
| 249 | vnet-descr-buf set-vio-msg-ver |
| 250 | |
| 251 | vnet-descr-buf /vio-ver-msg send-to-ldc |
| 252 | /vio-ver-msg = |
| 253 | ; |
| 254 | |
| 255 | ' send-vnet-ver-msg is send-vio-ver-msg |
| 256 | |
| 257 | \ The ack parameter may be ack or nack |
| 258 | : send-vnet-ack-msg ( buf ack -- ok? ) |
| 259 | over >vio-subtype c! ( buf ) |
| 260 | vnet-sid over >vio-sid l! ( buf ) |
| 261 | /vio-ver-msg send-to-ldc ( rlen ) |
| 262 | /vio-ver-msg = |
| 263 | ; |
| 264 | |
| 265 | ' send-vnet-ack-msg is send-vio-ack-msg |
| 266 | |
| 267 | : vnet-compatible-ver? ( buf -- yes? ) |
| 268 | dup >vio-ver-major w@ vnet-major = ( buf flag1 ) |
| 269 | swap >vio-ver-minor w@ vnet-minor = ( flag1 flag2 ) |
| 270 | and |
| 271 | ; |
| 272 | |
| 273 | ' vnet-compatible-ver? is vio-compatible-ver? |
| 274 | |
| 275 | : get-vnet-mac ( -- x ) |
| 276 | mac-buf x@ xlsplit swap lwsplit nip swap lwsplit -rot wljoin swap lxjoin |
| 277 | ; |
| 278 | |
| 279 | \ Send our attributes |
| 280 | : send-vnet-attr ( -- ok? ) |
| 281 | vnet-descr-buf /vnet-attr-msg erase ( ) |
| 282 | |
| 283 | vio-msg-type-ctrl vio-subtype-info vio-attr-info |
| 284 | vnet-descr-buf set-vio-msg-tag ( ) |
| 285 | vnet-sid vnet-descr-buf >vio-sid l! ( ) |
| 286 | |
| 287 | vnet-descr-buf frame-size over >vnet-attr-mtu x! ( buf ) |
| 288 | 1 over >vnet-ack-freq w! ( buf ) |
| 289 | |
| 290 | get-vnet-mac over >vnet-attr-addr x! ( buf ) |
| 291 | addr-type-mac over >vnet-addr-type c! ( buf ) |
| 292 | vio-desc-mode swap >vnet-xfer-mode c! ( ) |
| 293 | |
| 294 | vnet-descr-buf /vnet-attr-msg send-to-ldc ( rlen ) |
| 295 | /vnet-attr-msg = |
| 296 | ; |
| 297 | ' send-vnet-attr is send-vio-attr |
| 298 | |
| 299 | : send-vnet-rdx ( buf -- ok? ) |
| 300 | dup /vnet-attr-msg erase ( buf ) |
| 301 | >r vio-msg-type-ctrl vio-subtype-info vio-rdx |
| 302 | r@ set-vio-msg-tag ( R: buf ) |
| 303 | vnet-sid r@ >vio-sid l! ( R: buf ) |
| 304 | r> /vnet-attr-msg send-to-ldc ( rlen ) |
| 305 | /vnet-attr-msg = |
| 306 | ; |
| 307 | |
| 308 | ' send-vnet-rdx is send-vio-rdx |
| 309 | |
| 310 | \ Stages: |
| 311 | \ Version negotiation -> Vnet Attr info -> Dring info -> RDX |
| 312 | : init-vnet-conn ( -- ok? ) |
| 313 | debug-vnet? if ." Vnet version negotiation... " cr then |
| 314 | vnet-descr-buf version-negotiation if |
| 315 | debug-vnet? if ." Vnet Attr Exchange..." cr then |
| 316 | vnet-descr-buf /vnet-attr-msg vio-exchange-attr if |
| 317 | true exit |
| 318 | then |
| 319 | then |
| 320 | false |
| 321 | ; |
| 322 | |
| 323 | \ Set up sid and seq |
| 324 | : set-descr-req-header ( type stype env -- ) |
| 325 | vnet-descr-buf /vnet-descr-msg erase ( type stype env ) |
| 326 | |
| 327 | vnet-descr-buf set-vio-msg-tag ( ) |
| 328 | vnet-sid vnet-descr-buf >vio-sid l! ( ) |
| 329 | |
| 330 | vnet-seq vnet-descr-buf >vnet-seq x! ( ) |
| 331 | vnet-seq to cur-vnet-seq ( ) |
| 332 | ; |
| 333 | |
| 334 | : send-descr-req ( len -- ok? ) |
| 335 | vnet-descr-buf over send-to-ldc = ( ok? ) |
| 336 | ; |
| 337 | |
| 338 | : fill-in-vnet-args ( len cadr #ck -- ) |
| 339 | 2dup 4 pick vnet-descr-buf >vnet-cookie ( len cadr #ck cadr #ck len buf ) |
| 340 | fill-in-vio-cookie ( len cadr #ck ) |
| 341 | nip vnet-descr-buf tuck ( len buf #ck buf ) |
| 342 | >vnet-ctrl-#cookies l! ( len buf ) |
| 343 | >vnet-ctrl-nbytes l! ( ) |
| 344 | ; |
| 345 | |
| 346 | \ Fill in & send the cookie pkt, number of cookies may vary |
| 347 | : vnet-xmit-msg ( len cadr #ck -- ok? ) |
| 348 | vio-msg-type-data vio-subtype-info vio-desc-data |
| 349 | set-descr-req-header ( len cadr #ck ) |
| 350 | dup 2swap rot ( #ck len cadr #ck ) |
| 351 | fill-in-vnet-args ( #ck ) |
| 352 | /ldc-mem-cookie * /vnet-descr-short + ( slen ) |
| 353 | send-descr-req ( ok? ) |
| 354 | ; |
| 355 | |
| 356 | \ map-table entry should be page aligned, copy output to tx-buffer and |
| 357 | \ add tx-buffer to the map table |
| 358 | : vnet-xmit ( buf len -- #sent ) |
| 359 | tuck tx-buffer swap move ( len ) |
| 360 | debug-vnet? if |
| 361 | ." vnet xmit buf: len: " tx-buffer 2dup u. u. cr over |
| 362 | " dump" evaluate |
| 363 | then |
| 364 | tx-buffer 2dup over ( len buf len buf len ) |
| 365 | ldc-add-map-table-entries ( len buf len cadr #ck ) |
| 366 | vnet-xmit-msg if ( len buf ) |
| 367 | drop |
| 368 | else |
| 369 | cmn-warn[ " Can't send vnet write request!" ]cmn-end |
| 370 | 2drop 0 |
| 371 | then |
| 372 | ; |
| 373 | |
| 374 | \ Check to see if tag DATA/INFO/OBP_DATA, ctrl flag is READY |
| 375 | : vnet-data-pkt? ( -- yes? ) |
| 376 | vnet-descr-buf get-vio-msg-tag ( env subt type ) |
| 377 | vio-desc-data vio-subtype-info vio-msg-type-data vio-tag-match? ( yes? ) |
| 378 | ; |
| 379 | |
| 380 | |
| 381 | \ If two cookies span contiguous pages the ldc framework will only give us |
| 382 | \ one extra-large cookie with a size that overflows into the next page |
| 383 | : supercookie? ( ck -- supercookie? ) |
| 384 | dup >ldc-mem-csize x@ ( ck total-size ) |
| 385 | swap >ldc-mem-caddr x@ ( total-size ck-adr ) |
| 386 | dup pagesize round-up swap - ( total-size next-page ) |
| 387 | dup if ( total-size next-page ) |
| 388 | \ total-size spans two pages? |
| 389 | > ( true|false ) |
| 390 | else |
| 391 | \ already page aligned |
| 392 | nip ( false ) |
| 393 | then |
| 394 | ; |
| 395 | |
| 396 | \ An ethernet frame (NON-JUMBO) can span at most 2 pages |
| 397 | \ so we split the cookie into hypervisor-edible cookies |
| 398 | : split-supercookie ( ck -- ck0 sz0 ck1 sz1 ) |
| 399 | dup >ldc-mem-csize x@ >r ( ck ) ( r: total-size ) |
| 400 | >ldc-mem-caddr x@ ( ck0 ) ( r: total-size ) |
| 401 | dup pagesize round-up over - ( ck0 sz0 ) ( r: total-size ) |
| 402 | 2dup + ( ck0 sz0 ck1 ) ( r: total-size ) |
| 403 | over r> swap - ( ck0 sz0 ck1 sz1 ) |
| 404 | ; |
| 405 | |
| 406 | \ recreate the vnet-descr-buf with the weenie cookies |
| 407 | : sort-supercookies ( ck -- ) |
| 408 | dup supercookie? if |
| 409 | split-supercookie 2swap ( ck1 sz1 ck0 sz0 ) |
| 410 | vnet-descr-buf ( ck1 sz1 ck0 sz0 buf ) |
| 411 | 2 over >vnet-ctrl-#cookies l! ( ck1 sz1 ck0 sz0 buf ) |
| 412 | >vnet-cookie ( ck1 sz1 ck0 sz0 buf ) |
| 413 | tuck >ldc-mem-csize x! ( ck1 sz1 ck0 buf ) |
| 414 | tuck >ldc-mem-caddr x! ( ck1 sz1 buf ) |
| 415 | /ldc-mem-cookie + ( ck1 sz1 buf' ) |
| 416 | tuck >ldc-mem-csize x! ( ck1 buf' ) |
| 417 | >ldc-mem-caddr x! |
| 418 | else |
| 419 | drop |
| 420 | then |
| 421 | ; |
| 422 | |
| 423 | \ Read cookies, copy in data |
| 424 | \ Even though we have at most 2 cookies right now, put in a loop |
| 425 | \ so that it can handle more cookies in the future |
| 426 | : vnet-copy-in ( buf len -- rlen ) |
| 427 | vnet-descr-buf >vnet-cookie sort-supercookies ( buf len ) |
| 428 | vnet-descr-buf >vnet-ctrl-nbytes l@ ( buf len rlen ) |
| 429 | \ Copy multiple cookies |
| 430 | min 0 -rot ( rlen buf len' ) |
| 431 | vnet-descr-buf >vnet-ctrl-#cookies l@ 0 do ( rlen buf len' ) |
| 432 | vnet-descr-buf >vnet-cookie |
| 433 | /ldc-mem-cookie i * + ( rlen buf len' addr ) |
| 434 | dup >ldc-mem-caddr x@ ( rlen buf len' addr ck ) |
| 435 | swap >ldc-mem-csize x@ ( rlen buf len' ck size ) |
| 436 | |
| 437 | debug-vnet? if |
| 438 | dup ." Retrieved cookie size: " u. cr |
| 439 | then |
| 440 | |
| 441 | rx-buffer -rot ldc-copy-in ( rlen buf len' clen ) |
| 442 | |
| 443 | debug-vnet? if |
| 444 | dup ." ldc copy in cookie size: " u. cr |
| 445 | rx-buffer over " dump" evaluate |
| 446 | then |
| 447 | |
| 448 | \ For alignment, cookie size maybe bigger than requested size |
| 449 | over min >r ( rlen buf len' ) ( R: clen' ) |
| 450 | over rx-buffer swap r@ move ( rlen buf len' ) ( R: clen' ) |
| 451 | r@ - swap r@ + rot r> + ( len'' buf' rlen' ) |
| 452 | -rot swap ( rlen' buf' len'' ) |
| 453 | loop |
| 454 | 2drop ( rlen ) |
| 455 | ; |
| 456 | |
| 457 | \ Send back ACK packet |
| 458 | : vnet-send-ack ( idx #ck -- ) |
| 459 | vio-msg-type-data vio-subtype-ack vio-desc-data ( idx #ck ) |
| 460 | set-descr-req-header ( idx #ck ) |
| 461 | swap vnet-descr-buf >vnet-desc-hdl x! ( #ck ) |
| 462 | /ldc-mem-cookie * /vnet-descr-short + ( slen ) |
| 463 | send-descr-req drop |
| 464 | ; |
| 465 | |
| 466 | \ Read a packet if it's available, skip the ACK packets, for DATA packet, |
| 467 | \ Send an ACK packet after the memory content is retrieved. |
| 468 | : vnet-poll ( buf len -- #rcvd ) |
| 469 | begin |
| 470 | vnet-descr-buf /vnet-descr-msg retrieve-packet ( buf len rlen ) |
| 471 | dup 0= if nip nip exit then ( 0 ) |
| 472 | drop vnet-data-pkt? ( buf len yes? ) |
| 473 | until |
| 474 | |
| 475 | vnet-copy-in ( #rcvd ) |
| 476 | vnet-descr-buf dup >vnet-desc-hdl x@ ( #rcvd buf idx ) |
| 477 | swap >vnet-ctrl-#cookies l@ ( #rcvd idx #ck ) |
| 478 | vnet-send-ack ( #rcvd ) |
| 479 | ; |
| 480 | |
| 481 | : short-send ( buf,len -- error? ) |
| 482 | tuck vnet-xmit ( len #sent ) |
| 483 | <> |
| 484 | ; |
| 485 | |
| 486 | \ Dump pkts with 0x800 (IP), 0x11 (UDP) and port 0x44 (BOOTP/DHCP) |
| 487 | : dump-udp-bootp ( pkt len -- pkt len ) |
| 488 | dup if ( pkt len ) |
| 489 | over d# 12 + w@ h# 800 = if ( pkt len ) |
| 490 | over d# 23 + c@ h# 11 = if ( pkt len ) |
| 491 | over d# 36 + w@ h# 44 = if |
| 492 | ." udp pkt received!" cr |
| 493 | 2dup " dump" evaluate cr |
| 494 | then |
| 495 | then |
| 496 | then |
| 497 | then |
| 498 | ; |
| 499 | |
| 500 | \ offset 34: source port (2 bytes) |
| 501 | \ 36: destination port (2 bytes) |
| 502 | \ 38: seq number (4 bytes) |
| 503 | \ 42: ack number (4 bytes) |
| 504 | : dump-tcp-headers ( pkt len -- pkt len ) |
| 505 | dup if ( pkt len ) |
| 506 | over d# 12 + w@ h# 800 = if ( pkt len ) |
| 507 | over d# 23 + c@ d# 6 = if ( pkt len ) |
| 508 | over d# 34 + w@ u. over d# 36 + w@ u. |
| 509 | over d# 38 + w@ >r over d# 40 + w@ r> wljoin u. |
| 510 | over d# 42 + w@ >r over d# 44 + w@ r> wljoin u. cr |
| 511 | then |
| 512 | then |
| 513 | then |
| 514 | ; |
| 515 | |
| 516 | \ Allocate vnet descriptor buffer |
| 517 | : allocate-vnet-descr-buf |
| 518 | 8 /vnet-descr-buf 0 claim to vnet-descr-buf ( ) |
| 519 | ; |
| 520 | |
| 521 | \ Release and reset vnet descriptor buffer |
| 522 | : deallocate-vnet-descr-buf |
| 523 | /vnet-descr-buf vnet-descr-buf release ( ) |
| 524 | 0 to vnet-descr-buf |
| 525 | ; |
| 526 | |
| 527 | external |
| 528 | |
| 529 | : open ( -- ok? ) |
| 530 | open-vnet-ldc if ( ) |
| 531 | false exit ( false ) |
| 532 | then |
| 533 | |
| 534 | " local-mac-address" get-my-property if ( adr len | ) |
| 535 | cmn-warn[ " Can not find local-mac-address property" ]cmn-end |
| 536 | false exit ( false ) |
| 537 | then ( adr len ) |
| 538 | over mac-address comp 0= if ( adr len ) |
| 539 | \ Save a copy of mac address to mac-buf, used in vnet version negotiation |
| 540 | 2dup mac-buf swap cmove ( adr len ) |
| 541 | " mac-address" property ( ) |
| 542 | else ( adr len ) |
| 543 | cmn-warn[ " MAC Address does not match local-mac-address, " cmn-append |
| 544 | " Virtual Networks do not support variable local-mac-address? = false." |
| 545 | ]cmn-end |
| 546 | 2drop false exit ( false ) |
| 547 | then |
| 548 | |
| 549 | allocate-vnet-descr-buf ( ) |
| 550 | |
| 551 | my-args init-obp-tftp 0= if |
| 552 | deallocate-vnet-descr-buf ( ) |
| 553 | close-vnet-ldc ( ) |
| 554 | false exit ( false ) |
| 555 | then |
| 556 | |
| 557 | init-vnet-conn 0= if ( ) |
| 558 | deallocate-vnet-descr-buf ( ) |
| 559 | obp-tftp ?dup if close-package then ( ) |
| 560 | close-vnet-ldc ( ) |
| 561 | false exit ( false ) |
| 562 | then |
| 563 | |
| 564 | debug-vnet? if ( ) |
| 565 | ." mac-address shows: " ( ) |
| 566 | mac-address bounds do i c@ u. loop cr ( ) |
| 567 | then |
| 568 | |
| 569 | true to vnet-opened? ( ) |
| 570 | true ( true ) |
| 571 | ; |
| 572 | |
| 573 | : close ( -- ) |
| 574 | deallocate-vnet-descr-buf ( ) |
| 575 | |
| 576 | obp-tftp ?dup if close-package then |
| 577 | ldc-up? if |
| 578 | close-vnet-ldc |
| 579 | then |
| 580 | |
| 581 | false to vnet-opened? |
| 582 | ; |
| 583 | |
| 584 | : read ( buf,len -- -2|len ) |
| 585 | receive-ready? 0= if 2drop -2 exit then |
| 586 | |
| 587 | over swap ( buf buf len ) |
| 588 | vnet-poll ?dup 0= if -2 then ( buf len' ) |
| 589 | |
| 590 | debug-tcp? if ( buf len' ) |
| 591 | dump-udp-bootp ( buf len' ) |
| 592 | dump-tcp-headers ( buf len' ) |
| 593 | nip ( len' ) |
| 594 | else |
| 595 | nip ( len' ) |
| 596 | then |
| 597 | ; |
| 598 | |
| 599 | : write ( buf,len -- len ) |
| 600 | vnet-xmit |
| 601 | ; |
| 602 | |
| 603 | : load ( adr -- len ) |
| 604 | " load" obp-tftp $call-method |
| 605 | ; |
| 606 | |
| 607 | : watch-net ( -- ) |
| 608 | open 0= if exit then |
| 609 | frame-size alloc-mem to vnet-tmpbuf |
| 610 | |
| 611 | ." Looking for Ethernet packets." cr |
| 612 | ." '.' is a good packet. 'X' is a bad packet." cr |
| 613 | ." Type any key to stop." cr |
| 614 | |
| 615 | begin |
| 616 | key? 0= |
| 617 | while |
| 618 | receive-ready? if |
| 619 | vnet-tmpbuf frame-size vnet-poll if ." ." else ." X" then |
| 620 | then |
| 621 | repeat |
| 622 | key drop |
| 623 | |
| 624 | vnet-tmpbuf frame-size free-mem |
| 625 | close |
| 626 | ; |
| 627 | |
| 628 | headerless |