\
\ Fcode payload for QEMU CG3 graphics card
\
\ This is the Forth source for an Fcode payload to initialise
\ the QEMU CG3 graphics card.
\
\ (C) Copyright 2013 Mark Cave-Ayland
\

fcode-version3

\
\ Instead of using fixed values for the framebuffer address and the width
\ and height, grab the ones passed in by QEMU/generated by OpenBIOS
\

: (find-xt)   \ ( str len -- xt | -1 )
  $find if
    exit
  else
    -1
  then
;

" openbios-video-width" (find-xt) cell+ value openbios-video-width-xt
" openbios-video-height" (find-xt) cell+ value openbios-video-height-xt
" depth-bits" (find-xt) cell+ value depth-bits-xt
" line-bytes" (find-xt) cell+ value line-bytes-xt
" debug-type" (find-xt) value debug-type-xt

: openbios-video-width openbios-video-width-xt @ ;
: openbios-video-height openbios-video-height-xt @ ;
: depth-bits depth-bits-xt @ ;
: line-bytes line-bytes-xt @ ;
: debug-type debug-type-xt execute ;

\
\ Registers
\

h# 400000 constant cg3-off-dac
h# 20 constant /cg3-off-dac

h# 800000 constant cg3-off-fb
h# c0000 constant /cg3-off-fb

: >cg3-reg-spec ( offset size -- encoded-reg )
  >r 0 my-address d+ my-space encode-phys r> encode-int encode+
;

: cg3-reg
  \ A real cg3 rom appears to just map the entire region with a
  \ single entry
  h# 0 h# 1000000 >cg3-reg-spec
  " reg" property
;

: do-map-in ( offset size -- virt )
  >r my-space r> " map-in" $call-parent
;

: do-map-out ( virt size )
  " map-out" $call-parent
;

\
\ DAC
\

-1 value cg3-dac
-1 value fb-addr

: dac! ( data reg# -- )
  cg3-dac + c!
;

external

: color!  ( r g b c# -- )
  0 dac!       ( r g b )
  swap rot     ( b g r )
  4 dac!       ( b g )
  4 dac!       ( b )
  4 dac!       (  )
;

headerless

\
\ Mapping
\

: dac-map
  cg3-off-dac /cg3-off-dac do-map-in to cg3-dac
;

: fb-map
  cg3-off-fb h# c0000 do-map-in to fb-addr
;

: map-regs
  dac-map fb-map
;

\
\ Installation
\

" cgthree" device-name
" display" device-type
" SUNW,501-1415" model

: qemu-cg3-driver-install ( -- )
  cg3-dac -1 = if
    map-regs
    fb-addr to frame-buffer-adr
    default-font set-font

    frame-buffer-adr encode-int " address" property

    openbios-video-width openbios-video-height over char-width / over char-height /
    fb8-install
  then
;

: qemu-cg3-driver-init

  cg3-reg

  openbios-video-height encode-int " height" property
  openbios-video-width encode-int " width" property
  line-bytes encode-int " linebytes" property

  h# 39 encode-int 0 encode-int encode+ " intr" property

  \ Monitor sense. Some searching suggests that this is
  \ 5 for 1024x768 and 7 for 1152x900
  openbios-video-width h# 480 = if
    h# 7
  else
    h# 5
  then
  encode-int " monitor-sense" property

  " SUNW" encode-string " manufacturer" property
  " ISO8859-1" encode-string " character-set" property
  h# c encode-int " cursorshift" property

  ['] qemu-cg3-driver-install is-install
;

qemu-cg3-driver-init

end0
