[openfirmware] r1049 - cpu/x86/pc/olpc

svn at openfirmware.info svn at openfirmware.info
Wed Dec 24 22:16:22 CET 2008


Author: wmb
Date: 2008-12-24 22:16:22 +0100 (Wed, 24 Dec 2008)
New Revision: 1049

Modified:
   cpu/x86/pc/olpc/addrs.fth
   cpu/x86/pc/olpc/resume.bth
   cpu/x86/pc/olpc/suspend.fth
Log:
OLPC suspend/resume:
a) Fixed a problem in the SD register restore code
b) Added "forget-msr" directives after ecx modifications
to ensure that the correct MSR is read thereafter.
c) Fixed the "save-display" portion of the suspend/resume
code (which is commented-out by default) which had stopped
working some time ago.  The main fix was to change the value
of the address constant "resume-data" to prevent it overwriting
the save/restore code, which is longer when save-display is
defined.  This was done while investigating how to eliminate
display glitches.
d) Added code to save/restore the state of graphics processor
registers (part of the commented-out "save-display" code).
e) Added a "kb-suspend" test for testing suspend-between-keystrokes.


Modified: cpu/x86/pc/olpc/addrs.fth
===================================================================
--- cpu/x86/pc/olpc/addrs.fth	2008-12-24 21:05:15 UTC (rev 1048)
+++ cpu/x86/pc/olpc/addrs.fth	2008-12-24 21:16:22 UTC (rev 1049)
@@ -80,7 +80,7 @@
 
 h# f.0000 constant suspend-base      \ In the DOS hole
 h# f.0008 constant resume-entry
-h# f.0800 constant resume-data
+h# f.1000 constant resume-data
 
 \ If you change these, also change {g/l}xmsrs.fth and {g/l}xearly.fth
 h# fd00.0000 constant fw-map-base

Modified: cpu/x86/pc/olpc/resume.bth
===================================================================
--- cpu/x86/pc/olpc/resume.bth	2008-12-24 21:05:15 UTC (rev 1048)
+++ cpu/x86/pc/olpc/resume.bth	2008-12-24 21:16:22 UTC (rev 1049)
@@ -19,6 +19,7 @@
 
 \ This code will be copied to RAM at suspend-base
 
+\ create measure-suspend
 \ create save-display
 \ create reset-smbus
 \ create reset-smbus-bitbang
@@ -61,7 +62,7 @@
 
    \ Page directory VA in AX
    ax      si  mov                \ Save PDIR VA
-   0 [si]  cx  mov                \ Save old PDIR entry 0
+   0 [si]  cx  mov  forget-msr    \ Save old PDIR entry 0
    h# 83 # 0 [ax] mov             \ Punch a 4M mapping 0->0 into the page directory
    cr3 ax mov  ax cr3 mov         \ Invalide the TLB to activate the mapping
    h# f0060 # ax mov  ax jmp      \ Jump to suspend-physical, disabling paging
@@ -101,19 +102,23 @@
    cld
    h# 38 [bp]  di  lea    \ Save area
 
+[ifdef] measure-suspend
+   rdtsc  eax h# 10 #) mov  edx h# 14 #) mov
+[then]
+
 [ifdef] save-msrs
    h# 30 [bp]  si  mov    \ MSR table
    0 [si] bl mov
 
    begin
-      1 [si] cx mov
+      1 [si] cx mov  forget-msr
       5 # si add
       begin
          \ loop count in bl, msr# in cx
          rdmsr
          \ msr.lo in ax, msr.hi in dx
          ax stos   dx ax mov  ax stos
-         cx inc
+         cx inc  forget-msr
          bl dec
       0= until
       0 [si] bl mov
@@ -130,8 +135,28 @@
    h# 4c00.0015 rmsr  ax stos  dx ax mov  ax stos   \ DOTPLL
 
 [ifdef] save-display
+   \ Wait until it's safe to set the DCONLOAD bit; if you do it at the wrong time
+   \ you get screen artifacts
+
+   \ Wait for VSYNC
+   begin
+      dc-pci-base h# 6c + #)  ax mov   \ DC_LINE_CNT/STATUS Register
+      h# 2000.0000 # ax test           \ VSYNC bit
+   0<> until
+
+   \ Wait until the line count is 38.
+   \ Testing shows that it suffices to wait for any line in the range 36..911
+   \ If DCONLOAD is cleared during lines 0..35, display artifacts will appear
+   \ at the bottom of the screen.
+   begin
+      dc-pci-base h# 6c + #)  ax mov   \ DC_LINE_CNT/STATUS Register
+      h# 3ff # ax and                  \ DOT_LINE_CNT field
+      d# 38 # ax cmp
+   = until             \ Loop until line count is 38 (empirically good)
+
    \ Freeze image by clearing the DCONLOAD bit (0x800) in the GPIO output register
-   h# 0800.0000 h# 1000 port-wl
+   h# 5140.000c rmsr  h# 00 [ax] dx lea       \ GPIO output port
+   h# 0800.0000 # ax mov  ax dx out
 [then]
 
    \ Save the GPIO setup   
@@ -146,7 +171,7 @@
    h# e0 [bx] dx lea  dx ax in  ax stos  \ GPIO_MAP_Z
 
    h# 38 [bx]  dx  lea   \ Low bank - first contiguous GPIO register
-   h# 3c /l / #  cx  mov  \ Register count (stop at lock register)
+   h# 3c /l / #  cx  mov  forget-msr  \ Register count (stop at lock register)
    begin
       dx  ax   in   \ Read GPIO control register
       ax stos       \ Save
@@ -160,7 +185,7 @@
 [ifndef] omit-high-gpio-restore
    \ This is probably unnecessary, as these registers may be in the suspend well
    h# b8 [bx] dx lea  \ High bank - first contiguous GPIO register
-   h# 3c /l / #  cx  mov  \ Register count (stop at lock register)
+   h# 3c /l / #  cx  mov  forget-msr  \ Register count (stop at lock register)
    begin
       ax   dx  in   \ Read GPIO control register
       ax stos       \ Save
@@ -178,13 +203,22 @@
 
 [ifdef] save-display
 \ \ h# 3c 0  do  i gp@ l!+  4 +loop  h# 4c gp@ l!+
-\  h# f # cx mov  gp-pci-base set-base  begin  0 [bx] ax mov  ax stos  4 # bx add  loopa
+\  h# f # cx mov  forget-msr  gp-pci-base set-base  begin  0 [bx] ax mov  ax stos  4 # bx add  loopa
 \  gp-pci-base h# 4c + #) ax mov  ax stos
+   gp-pci-base set-base
+   h# 00 reg-save  h# 04 reg-save  h# 08 reg-save  h# 0c reg-save
+   h# 10 reg-save  h# 14 reg-save  h# 18 reg-save  h# 1c reg-save
+   h# 20 reg-save  h# 24 reg-save  h# 28 reg-save  h# 2c reg-save
+   h# 30 reg-save  h# 34 reg-save  h# 38 reg-save  ( h# 3c reg-save )
+   ( h# 40 reg-save  h# 44 reg-save  h# 48 reg-save ) h# 4c reg-save
+   h# 50 reg-save  h# 54 reg-save  ( h# 58 reg-save  h# 5c reg-save )
+   h# 60 reg-save  h# 64 reg-save  h# 68 reg-save  h# 6c reg-save
+   h# 70 reg-save  h# 74 reg-save  h# 78 reg-save  ( h# 7c reg-save )
 
    vp-pci-base set-base
    h# 400 reg-save  h# 408 reg-save  h# 418 reg-save
    h#   8 reg-save
-   0 # h# 38 [bx] mov  h# 100 # cx mov  begin  h# 40 reg-save  loopa  \ Gamma
+   0 # h# 38 [bx] mov  h# 100 # cx mov  forget-msr  begin  h# 40 reg-save  loopa  \ Gamma
    h# 410 reg-save
 
    dc-pci-base set-base
@@ -195,7 +229,7 @@
    h# 40 reg-save  h# 44 reg-save  h# 48 reg-save
    h# 50 reg-save  h# 54 reg-save  h# 58 reg-save
    h# 60 reg-save  h# 64 reg-save  h# 68 reg-save
-   0 # h# 70 [bx] mov  h# 100 # cx mov  begin  h# 74 reg-save  loopa
+   0 # h# 70 [bx] mov  h# 100 # cx mov  forget-msr  begin  h# 74 reg-save  loopa
    h# 80 reg-save  h# 84 reg-save
    h#  8 reg-save  h#  4 reg-save
 
@@ -246,7 +280,7 @@
 
    \ MFGPTs 0-5.  MFGPT 6 and 7 are in the standby domain, live during suspend
    h# 1800 # dx mov  \ MFGPT base port
-   h# 18 # cx mov    \ Save registers up to h# 30.
+   h# 18 # cx mov  forget-msr   \ Save registers up to h# 30.
    begin
       op: dx ax in
       op: ax stos
@@ -286,8 +320,8 @@
 
 [ifdef] save-display
    \ Wait until the DCON has loaded a frame - DCONIRQ=1 and DCONSTAT=10
-   d# 50,000 # cx mov  \ 50K spins is about 40 mS
-   h# 1030 # dx mov
+   h# 5140.000c rmsr  h# 30 [ax] dx lea       \ GPIO data port
+   d# 50,000 # cx mov  forget-msr  \ 50K spins is about 40 mS
    begin  dx ax in  h# e0 # al and  h# c0 # al cmp  loopne
 [then]
 
@@ -295,11 +329,16 @@
    \ Checksum memory from 1M to top (excluding framebuffer)
    bx bx xor
    h# 0010.0000 #  si  mov
-   h# 0ef0.0000 2 rshift #  cx  mov  \ Word count
+   h# 0ef0.0000 2 rshift #  cx  mov  forget-msr  \ Word count
    begin  ax lods  ax bx add  loopa
    bx  resume-data h# 10 - #)  mov   \ Save checksum
 [then]
 
+[ifdef] measure-suspend
+   di 0 #) mov
+   rdtsc ax h# 18 #) mov  dx h# 1c #) mov
+[then]
+
    \ Stop video refresh
    h# 4758 #  dc-pci-base     #)  mov  \ Unlock DC registers
    h#    0 #  dc-pci-base 4 + #)  mov  \ Turn off access to display memory
@@ -333,7 +372,7 @@
    \ Setup the register values in advance so the active instruction sequence
    \ is as short as possible, thus keeping all the activity in one cache line.
    h# 4. # dx mov # ax mov              \ Value to write to MSR
-   h# 2000.2004 # cx mov                \ GLD_MSR_PM MSR number
+   h# 2000.2004 # cx mov  forget-msr    \ GLD_MSR_PM MSR number
    h# 2000 # bx mov                     \ Value to write to PM1_CNT register
    h# 1848 # di mov                     \ PM1_CNT I/O port number
 
@@ -345,7 +384,7 @@
    wrmsr                                \ Write GLD_MSR_PM to self-refresh memory
    di dx mov  bx ax mov  ax dx out      \ Write PM1_CNT to initial suspend
 
-   h# fff # cx mov begin  nop  loopa   \ Spin in this cache line while going down
+   h# fff # cx mov  forget-msr  begin  nop  loopa   \ Spin in this cache line while going down
 
    \ If the processor didn't really go down, perhaps because a wakeup event was
    \ already pending, restart the memory clocks and proceed as with a wakeup
@@ -371,6 +410,10 @@
 
    h# 20 resume-progress
 
+[ifdef] measure-suspend
+   rdtsc  eax h# 20 #) mov  edx h# 24 #) mov
+[then]
+
 [ifndef] save-msrs
    \ MSR init
    h# 30 [bp]  si  mov   \ MSR table start address
@@ -378,7 +421,7 @@
    h# 34 [bp]  bx  add   \ MSR table end address
 
    begin
-      ax lods  ax cx  mov   \ msr#
+      ax lods  ax cx  mov   forget-msr  \ msr#
       ax lods  ax dx  mov   \ msr.hi
       ax lods               \ msr.lo
       wrmsr
@@ -392,7 +435,7 @@
    \ Checksum memory from 1M to top (excluding framebuffer)
    bx bx xor
    h# 0010.0000 #  si  mov
-   h# 0ef0.0000 2 rshift #  cx  mov  \ Word count
+   h# 0ef0.0000 2 rshift #  cx  mov  forget-msr  \ Word count
    begin  ax lods  ax bx add  loopa
    bx  resume-data h# 10 - #)  cmp  <>  if  ret  then
 [then]
@@ -404,14 +447,14 @@
    0 [di]  bl  mov
 
    begin
-      1 [di]  cx  mov
+      1 [di]  cx  mov  forget-msr
       5 #  di  add
       begin
          \ loop count in bl, msr# in cx
          ax lods  ax dx mov  ax lods  ax dx xchg
          \ msr.lo in ax, msr.hi in dx
          wrmsr
-         cx inc
+         cx inc  forget-msr
          bl dec
       0= until
       0 [di] bl mov
@@ -441,7 +484,7 @@
    h# 14 [bx] dx lea  ax dx out  \ Deselect OUT AUX2
    h# 34 [bx] dx lea  ax dx out  \ Deselect IN AUX1
 
-   d# 16 # cx mov  \ Generate 8 low pulses on SMB_CLOCK
+   d# 16 # cx mov  forget-msr  \ Generate 8 low pulses on SMB_CLOCK
    begin
       \ 5 uS delay (slightly longer for GX)
       rdtsc  ax bx mov  d# 5 d# 500 * #  bx  add
@@ -450,7 +493,7 @@
       cx bx mov                          \ Save cx for use by rmsr
       h# 5140.000c rmsr  ax dx  mov      \ GPIO output register
       h# 40000000 # ax mov  ax dx out    \ Clear SMB_CLOCK
-      bx cx mov                          \ Restore cx
+      bx cx mov  forget-ms               \ Restore cx
 
       \ 5 uS delay (slightly longer for GX)
       rdtsc  ax bx mov  d# 5 d# 500 * #  bx  add
@@ -459,7 +502,7 @@
       cx bx mov                          \ Save cx for use by rmsr
       h# 5140.000c rmsr  ax dx  mov      \ GPIO output register
       h#     4000 # ax mov  ax dx out    \ Set SMB_CLOCK
-      bx cx mov                          \ Restore cx
+      bx cx mov  forget-msr              \ Restore cx
    loopa
 
    \ 5 uS delay (slightly longer for GX)
@@ -477,7 +520,7 @@
    ax lods  h# e0 [bx] dx lea  ax dx out  \ GPIO_MAP_Z
 
    h# 38 [bx]  dx  lea   \ Low bank - first contiguous GPIO register
-   h# 3c /l / #  cx  mov  \ Register count (stop at lock register)
+   h# 3c /l / #  cx  mov  forget-msr  \ Register count (stop at lock register)
    begin
       ax lods
       ax   dx  out  \ Write to GPIO control register
@@ -496,7 +539,7 @@
 [ifndef] omit-high-gpio-restore
    \ This is probably unnecessary, as these registers may be in the suspend well
    h# b8 [bx]    dx  lea  \ High bank - first contiguous GPIO register
-   h# 3c /l / #  cx  mov  \ Register count (stop at lock register)
+   h# 3c /l / #  cx  mov  forget-msr  \ Register count (stop at lock register)
    begin
       ax lods
       ax   dx  out  \ Write to GPIO control register
@@ -519,24 +562,36 @@
 [ifdef] save-display
 
 \ \ h# 3c 0  do  l at + i gp!  4 +loop   l at + h# 4c gp! 
-\  h# f # cx mov   gp-pci-base set-base  begin  ax lods  ax 0 [bx] mov  4 # bx add  loopa
+\  h# f # cx mov  forget-msr  gp-pci-base set-base  begin  ax lods  ax 0 [bx] mov  4 # bx add  loopa
 \  ax lods  ax  gp-pci-base h# 4c + #)  mov
 
 \ Synchronize the flat panel turn-on with the DCON blanking
-\   d# 50,000 # cx mov  \ 50K spins is about 40 mS
-\   h# 1030 # dx mov  \ GPIO data port
+\   h# 5140.000c rmsr  h# 30 [ax] dx lea    \ GPIO data port
+\   h# 1030 # dx mov
+\   d# 50,000 # cx mov  forget-msr  \ 50K spins is about 40 mS
 \   begin  dx ax in  h# 1000 # ax test  loope  \ Wait for blanking
 
+   gp-pci-base set-base
+   h# 00 reg-restore  h# 04 reg-restore  h# 08 reg-restore  h# 0c reg-restore
+   h# 10 reg-restore  h# 14 reg-restore  h# 18 reg-restore  h# 1c reg-restore
+   h# 20 reg-restore  h# 24 reg-restore  h# 28 reg-restore  h# 2c reg-restore
+   h# 30 reg-restore  h# 34 reg-restore  h# 38 reg-restore  ( h# 3c reg-restore )
+   ( h# 40 reg-restore  h# 44 reg-restore  h# 48 reg-restore )    h# 4c reg-restore
+   h# 50 reg-restore  h# 54 reg-restore  ( h# 58 reg-restore  h# 5c reg-restore )
+   h# 60 reg-restore  h# 64 reg-restore  h# 68 reg-restore  h# 6c reg-restore
+   h# 70 reg-restore  h# 74 reg-restore  h# 78 reg-restore  ( h# 7c reg-save )
+
    vp-pci-base set-base
    0 #  h# 50 [bx] mov  \ Power on for DACs, enable gamma correction 
    h# 400 reg-restore
    h# 408 reg-restore
    h# 418 reg-restore
    h#   8 reg-restore
-   0 #  h# 38 [bx] mov  h# 100 # cx mov  begin  h# 40 reg-restore  loopa  \ Gamma
+   0 #  h# 38 [bx] mov  h# 100 # cx mov  forget-msr  begin  h# 40 reg-restore  loopa  \ Gamma
    h# 410 reg-restore
 
-\   d# 1,000,000 # cx mov  begin  h# 410 [bx] ax mov  1 # al test  loope  \ Panel power up
+h# 34 resume-progress
+\   d# 1,000,000 # cx mov  forget-msr  begin  h# 410 [bx] ax mov  1 # al test  loope  \ Panel power up
 
    dc-pci-base set-base
    
@@ -548,25 +603,34 @@
    h# 40 reg-restore   h# 44 reg-restore   h# 48 reg-restore
    h# 50 reg-restore   h# 54 reg-restore   h# 58 reg-restore
    h# 60 reg-restore   h# 64 reg-restore   h# 68 reg-restore
-   0 #  h# 70  [bx] mov   h# 100 # cx mov   begin  h# 74 reg-restore  loopa
+   0 #  h# 70  [bx] mov   h# 100 # cx mov  forget-msr  begin  h# 74 reg-restore  loopa
    h# 80 reg-restore   h# 84 reg-restore
 
+h# 35 resume-progress
 \ Synchronize the VGA turn-on with the DCON blanking
-   d# 50,000 # cx mov  \ 50K spins is about 40 mS
    h# 5140.000c rmsr  h# 30 [ax] dx lea       \ GPIO data port
+   d# 50,000 # cx mov  forget-msr \ 50K spins is about 40 mS
    begin  dx ax in  h# 1000 # ax test  loope  \ Wait for blanking
 
    h#  8 reg-restore   h#  4 reg-restore
 
+h# 36 resume-progress
    0 #  dc-pci-base #)  mov  \ Lock
 
-\   d# 100,000 # cx mov  begin  h# 80 #  ax in  loopa  \ Delay about 100 ms
+   \ Turn on the flat panel power as soon as possible
+   \ The 400.0000 bit make the panel power-up timers use the 14 MHz clock
+   \ instead of the 32 kHz clock.  That is supposed to be only for simulation,
+   \ but we have DCON between the CPU and the panel, so we don't need delays.
+   h# 500.0000 #  vp-pci-base h# 410 + #)  mov
 
-   d# 80,000 # cx mov  begin  h# 80 # a in  loopa  \ Wait for panel power up
+\ XX    d# 80,000 # cx mov  forget-msr  begin  h# 80 # ax in  loopa  \ Wait for panel power up
+   d# 1,000 # cx mov  forget-msr  begin  h# 80 # ax in  loopa  \ Wait for panel power up
 
+h# 36 resume-progress
    \ Unfreeze image by setting the DCONLOAD bit (0x800) in the GPIO output register
    h# 5140.000c rmsr  ax dx mov   \ GPIO output register
    h# 0800 # ax mov   ax dx out
+h# 37 resume-progress
 [else]
    \ Turn on the flat panel power as soon as possible
    \ The 400.0000 bit make the panel power-up timers use the 14 MHz clock
@@ -661,7 +725,7 @@
    \ the delay time with other work, but it doesn't matter because the
    \ later CaFe chip setup will stall anyway.
 
-   d#   32 # cx mov  \ Loop count (usually ready in 20 uS)
+   d#   32 # cx mov  forget-msr \ Loop count (usually ready in 20 uS)
    dx dec  dx dec    \ SMBUS reg1 (status)
    begin
       dx al in
@@ -673,7 +737,7 @@
    al dx out         \ Initiate address out cycle
 
    \ Another possible split point, in case we should need to overlap
-   d#  256 # cx mov  \ Loop count (usually ready in 172 uS)
+   d#  256 # cx mov  forget-msr  \ Loop count (usually ready in 172 uS)
    dx inc            \ SMBUS reg1 (status)
    begin
       dx al in
@@ -694,7 +758,7 @@
 
    \ MFGPTs 0-5.  MFGPT 6 and 7 are in the standby domain, live during suspend
    h# 1800 # dx mov  \ MFGPT base port
-   h# 18 # cx mov
+   h# 18 # cx mov  forget-msr
    begin
       op: ax lods  ax ax test  0<>  if  op: ax dx out  then
       dx inc  dx inc
@@ -719,7 +783,6 @@
 [then]
 
    h# 2a resume-progress
-
    \ Restore CaFe configuration
 
    h# 6010 config-setup  ax lods  ax dx out        \ NAND BAR
@@ -730,7 +793,7 @@
    ax lods  ax  h# 2c [bx]  mov                    \ NAND Timing 3
    h# 6004 config-setup  op: ax lods  op: ax dx out    \ NAND enables
 
-   op: ax lods  ax cx mov                          \ SDHCI enables - save for later
+   op: ax lods  ax cx mov forget-msr               \ SDHCI enables - save for later
    h# 6110 config-setup  ax lods  ax dx out        \ SDHCI BAR
    ax bx mov                                       \ Base address
    6  h# 6104 config-ww                            \ Enable access
@@ -743,7 +806,7 @@
    \ Empirically, they are readable!
    op: h# 0004 #  h# 6a [bx]  mov                  \ Magic recipe from Marvell
    op: h# 7fff #  h# 60 [bx]  mov                  \ Magic recipe from Marvell
-   h# 6104 config-setup  ax lods  op: ax dx out    \ SDHCI enables
+\   h# 6104 config-setup  ax lods  op: ax dx out    \ SDHCI enables
    h# 610d config-setup  al lods  al dx out        \ SDHCI latency timer
    h# 613c config-setup  al lods  al dx out        \ SDHCI IRQ
    h# 6104 config-setup  cx ax mov  op: ax dx out  \ Set SDHCI enables after restoring mapped registers
@@ -774,7 +837,9 @@
    ax  dc-pci-base h# 88 + #)  mov  \ DV_CTL register - sets framebuffer mem offset
 
    fb-pci-base #  dc-pci-base h#  84 + #)  mov   \ GLIU0 Memory offset
+[ifndef] save-display
    fb-pci-base #  gp-pci-base h#  4c + #)  mov   \ GP base
+[then]
    fb-pci-base h# 80.0000 + #  vp-pci-base h# 460 + #)  mov   \ Flat panel base (GX only)
 
    \ There is a lot of other stuff that must be done to turn on the
@@ -784,11 +849,16 @@
    \ DCON fiddling
    \ USB
 
+[ifdef] measure-suspend
+   rdtsc  eax h# 28 #) mov  edx h# 2c #) mov
+   si 4 #) mov
+[then]
+
    h# 2c resume-progress
 
    h# 2c [bp]  di mov               \ VA of suspend-base in di
    h# 28 [bp]  si mov               \ PDIR VA
-   h# 24 [bp]  cx mov               \ PDIR entry 0
+   h# 24 [bp]  cx mov forget-msr    \ PDIR entry 0
    h# 20 [bp]  ax mov  ax cr4 mov  
    h# 1c [bp]  ax mov  ax cr3 mov  
    h# 18 [bp]  ax mov

Modified: cpu/x86/pc/olpc/suspend.fth
===================================================================
--- cpu/x86/pc/olpc/suspend.fth	2008-12-24 21:05:15 UTC (rev 1048)
+++ cpu/x86/pc/olpc/suspend.fth	2008-12-24 21:16:22 UTC (rev 1049)
@@ -49,6 +49,31 @@
 [then]
 \  sum-forth
 ;
+dev screen
+   : gp-wait-idle  ( -- )  begin  h# 44 gp@ h# 15 and  h# 10 =  until  ;
+   : wait-vsync  ( -- )  begin  6c dc@ h# 2000.0000 and  until  ;
+   : wait-!vsync  ( -- )  begin  6c dc@ h# 2000.0000 and 0=  until  ;
+   : wait-frames  ( n -- )  0 ?do  wait-vsync  wait-!vsync wait-vsync  loop  ;
+   : dot-line  ( -- n )  6c dc@  h# 3ff and  ;
+   : wait-suspend  ( -- )
+      disable-interrupts
+      dot-line  d# 28 <  if  wait-vsync  then
+      begin  dot-line  d# 25  d# 27  between  until
+   ;
+dend
+: kb-suspend  ( -- )
+   sci-wakeup
+   begin
+      begin  1 ms key?  while  key  dup [char] q = abort" Quit"  emit  repeat
+\      " gp-wait-idle" screen-ih $call-method
+\      2 " wait-frames" screen-ih $call-method
+      noop
+\      " wait-vsync" screen-ih $call-method
+\      " wait-suspend" screen-ih $call-method
+\      d# 550 us  \ 520 is sufficient
+      s3
+   again   
+;
 : suspend
   " video-save" screen-ih $call-method  \ Freeze display
   s3




More information about the openfirmware mailing list