summaryrefslogtreecommitdiffstats
path: root/qemu/roms/SLOF/slof/fs/xmodem.fs
blob: 1221922128302f65c294f151d719440697c93bcf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
\ *****************************************************************************
\ * Copyright (c) 2004, 2008 IBM Corporation
\ * All rights reserved.
\ * This program and the accompanying materials
\ * are made available under the terms of the BSD License
\ * which accompanies this distribution, and is available at
\ * http://www.opensource.org/licenses/bsd-license.php
\ *
\ * Contributors:
\ *     IBM Corporation - initial implementation
\ ****************************************************************************/


01 CONSTANT XM-SOH   \ Start of header
04 CONSTANT XM-EOT   \ End-of-transmission
06 CONSTANT XM-ACK   \ Acknowledge
15 CONSTANT XM-NAK   \ Neg. acknowledge

0 VALUE xm-retries   \ Retry count
0 VALUE xm-block#


\ *
\ * Internal function:
\ * wait <timeout> seconds for a new character
\ *
: xmodem-get-byte  ( timeout -- byte|-1 )
   d# 1000 *
   0 DO
      key? IF key UNLOOP EXIT THEN
      1 ms
   LOOP
   -1
;


\ *
\ * Internal function:
\ * Receive one XMODEM packet, check block number and check sum.
\ *
: xmodem-rx-packet  ( address -- success? )
   1 xmodem-get-byte    \ Get block number
   dup 0 < IF
      2drop false EXIT  \ Timeout
   THEN
   1 xmodem-get-byte    \ Get neg. block number
   dup 0 < IF
      3drop false EXIT  \ Timeout
   THEN
   rot 0                ( blk# ~blk# address chksum )
   80 0 DO
      1 xmodem-get-byte dup 0 < IF     ( blk# ~blk# address chksum byte )
         3drop 2drop UNLOOP FALSE EXIT
      THEN
      dup 3 pick c!            ( blk# ~blk# address chksum byte )
      + swap 1+ swap           ( blk# ~blk# address+1 chksum' )
   LOOP
   ( blk# ~blk# address chksum )
   \ Check sum:
   0ff and
   1 xmodem-get-byte <> IF
      \ CRC failed!
      3drop FALSE EXIT
   THEN
   drop                        ( blk# ~blk# )
   \ finally check if block numbers are ok:
   over xm-block# <> IF
      \ Wrong block number!
      2drop FALSE EXIT
   THEN                        ( blk# ~blk# )
   ff xor =
;


\ *
\ * Internal function:
\ * Load file to given address via XMODEM protocol
\ *
: (xmodem-load)  ( address -- bytes )
   1 to xm-block#
   0 to xm-retries
   dup
   BEGIN
      d# 10 xmodem-get-byte dup >r
      CASE
         XM-SOH OF
            dup xmodem-rx-packet IF
               \ A packet has been received successfully
               XM-ACK emit
               80 +                     ( start-addr next-addr  R: rx-byte )
               0 to xm-retries                    \ Reset retry count
               xm-block# 1+ ff and to xm-block#   \ Increase current block#
            ELSE
               \ Error while receiving packet
               XM-NAK emit
               xm-retries 1+ to xm-retries  \ Increase retry count
            THEN
         ENDOF
         XM-EOT OF
            XM-ACK emit
         ENDOF
         dup OF
            XM-NAK emit
            xm-retries 1+ to xm-retries  \ Increase retry count
         ENDOF
      ENDCASE
      r> XM-EOT =
      xm-retries d# 10 >= OR
   UNTIL                         ( start-address end-address )
   swap -                        ( bytes received )
;


\ *
\ * Load file to load-base via XMODEM protocol
\ *
: xmodem-load  ( -- bytes )
   cr ." Waiting for start of XMODEM upload..." cr
   get-load-base (xmodem-load)
;