anchor.diff:                 (hsync-a (reg +hsync-a+))
                  (vtotal-a (reg +vtotal-a+))
                  (vblank-a (reg +vblank-a+))
  -               (vsync-a (reg +vsync-a+))
  -               (pipeasrc (reg +pipeasrc+))
  -               (dspacntr (reg +dspacntr+)))
  -          (make-mode-parameters
  -           :width (1+ (ldb +pipesrc-horz+ pipeasrc))
  -           :height (1+ (ldb +pipesrc-vert+ pipeasrc))
  -           :format (case (ldb +dspcntr-format+ dspacntr)
  -                     (#b0110 :x8r8g8b8)
  -                     (t (ldb +dspcntr-format+ dspacntr)))
  -           :n (ldb +pll-n-divisor+ fpa0)
  -           :m1 (ldb +pll-m1-divisor+ fpa0)
  -           :m2 (ldb +pll-m2-divisor+ fpa0)
  -           :p1 (ldb +dpll-ctrl-p1+ dplla-ctrl)
  -           :p2 (ldb +dpll-ctrl-p2+ dplla-ctrl)
  -           :htotal-active (ldb +htotal-active+ htotal-a)
  -           :htotal-total (ldb +htotal-total+ htotal-a)
  -           :hblank-start (ldb +hblank-start+ hblank-a)
  -           :hblank-end (ldb +hblank-end+ hblank-a)
  -           :hsync-start (ldb +hsync-start+ hsync-a)
  -           :hsync-end (ldb +hsync-end+ hsync-a)
  -           :vtotal-active (ldb +vtotal-active+ vtotal-a)
  -           :vtotal-total (ldb +vtotal-total+ vtotal-a)
  -           :vblank-start (ldb +vblank-start+ vblank-a)
  -           :vblank-end (ldb +vblank-end+ vblank-a)
  -           :vsync-start (ldb +vsync-start+ vsync-a)
  -           :vsync-end (ldb +vsync-end+ vsync-a)))))))
  -
  -(defun framebuffer-address (device)
  -  (logand (pci:pci-io-region (i945-device device) 2) (lognot #xF)))
  +               (vsync-a (reg +vsync-a+)))
  +          (make-timing
  +           :pixel-clock (pll-parameters-to-dot-clock
  +                         (ldb +pll-n-divisor+ fpa0)
  +                         (ldb +pll-m1-divisor+ fpa0)
  +                         (ldb +pll-m2-divisor+ fpa0)
  +                         (ldb +dpll-ctrl-p1+ dplla-ctrl)
  +                         (ldb +dpll-ctrl-p2+ dplla-ctrl))
  +           :horz-left-border (- (1+ (ldb +htotal-total+ htotal-a))
  +                                (1+ (ldb +hblank-end+ hblank-a)))
  +           :horz-active (1+ (ldb +htotal-active+ htotal-a))
  +           :horz-right-border (- (1+ (ldb +htotal-active+ htotal-a))
  +                                 (1+ (ldb +hblank-start+ hblank-a)))
  +           :horz-front-porch (- (1+ (ldb +hsync-start+ hsync-a))
  +                                (1+ (ldb +hblank-start+ hblank-a)))
  +           :horz-sync (- (1+ (ldb +hsync-end+ hsync-a))
  +                         (1+ (ldb +hsync-start+ hsync-a)))
  +           :horz-back-porch (- (1+ (ldb +hblank-end+ hblank-a))
  +                               (1+ (ldb +hsync-end+ hsync-a)))
  +           :horz-image-size (truncate (* (/ (1+ (ldb +htotal-active+ htotal-a)) 72) 25.4)) ; Assume 72dpi
  +           :vert-top-border (- (1+ (ldb +vtotal-total+ vtotal-a))
  +                               (1+ (ldb +vblank-end+ vblank-a)))
  +           :vert-active (1+ (ldb +vtotal-active+ vtotal-a))
  +           :vert-bottom-border (- (1+ (ldb +vtotal-active+ vtotal-a))
  +                                  (1+ (ldb +vblank-start+ vblank-a)))
  +           :vert-front-porch (- (1+ (ldb +vsync-start+ vsync-a))
  +                                (1+ (ldb +vblank-start+ vblank-a)))
  +           :vert-sync (- (1+ (ldb +vsync-end+ vsync-a))
  +                         (1+ (ldb +vsync-start+ vsync-a)))
  +           :vert-back-porch (- (1+ (ldb +vblank-end+ vblank-a))
  +                               (1+ (ldb +vsync-end+ vsync-a)))
  +           :vert-image-size (truncate (* (/ (1+ (ldb +vtotal-active+ vtotal-a)) 72) 25.4)) ; Assume 72dpi
  +           ;; TODO: Pick up interlaced modes
  +           :interlaced nil
  +           ;; TODO: Pick up stereo modes
  +           :stereo nil
  +           ;; TODO: Sync...
  +           :sync-config 15)))))) ; Digital, serrated +vsync, +hsync.
   
   (defun mode-switch (device mode)
  -  (when (not (eql (mode-parameters-format mode) :x8r8g8b8))
  -    (error "Mode ~S has unsupported format." mode))
     (with-i945-access (device)
       ;; Update the video framebuffer.
       ;; Do this first so that the compositor updates display before
       ;; the new mode is set and nothing is displayed with the wrong stride.
       (sup::video-set-framebuffer
        (framebuffer-address device)
  -     (mode-parameters-width mode)
  -     (mode-parameters-height mode)
  -     (* (mode-parameters-width mode) 4)
  +     (timing-horz-active mode)
  +     (timing-vert-active mode)
  +     (* (timing-horz-active mode) 4)
        :x8r8g8b8
        :device device)
       (mezzano.gui.compositor:force-redisplay t)
  
positive.code:       (let ((mode (save-current-mode-parameters card))
              (framebuffer (framebuffer-address card)))
          ;; Take ownership of the compositor framebuffer.
          (when (and (eql (mode-parameters-format mode) :x8r8g8b8)
                     (eql (framebuffer-address card)
                          (sup::framebuffer-base-address (sup:current-framebuffer))))
            (sup::video-set-framebuffer
             framebuffer
             (mode-parameters-width mode)
             (mode-parameters-height mode)
             (* (mode-parameters-width mode) 4)
             :x8r8g8b8
             :device card)
            (mezzano.gui.compositor:force-redisplay t)))
  
negative.code: (defconstant +dspcntr-180-rotation+ (byte 1 15))
  (defconstant +dspcntr-tiled+ (byte 1 10))
  
  (defstruct timing
    pixel-clock
    horz-left-border
    horz-active ; width
    horz-right-border
    horz-front-porch
    horz-sync
    horz-back-porch
    horz-image-size
    vert-top-border
    vert-active ; height
    vert-bottom-border
    vert-front-porch
    vert-sync
    vert-back-porch
    vert-image-size
    interlaced
    stereo
    ;; FIXME: Figure this out.
    sync-config)
  
  (defun timing-refresh-rate (timing)
    (round (timing-pixel-clock timing)
           (* (+ (timing-horz-sync timing)
                 (timing-horz-back-porch timing)
                 (timing-horz-front-porch timing))
              (+ (timing-vert-sync timing)
                 (timing-vert-back-porch timing)
                 (timing-vert-front-porch timing)))))
  
  (defmacro with-i945-access ((device) &body body)
    `(sup:with-device-access ((pci:pci-device-boot-id (i945-device ,device))
                              (error "~S is stale" ,device))
       (sup:with-mutex ((i945-lock ,device))
         ,@body)))
  
  (defun framebuffer-address (device)
    (logand (pci:pci-io-region (i945-device device) 2) (lognot #xF)))
  
  (defconstant +reference-frequency+ 96000000)
  
  (defun pll-parameters-to-dot-clock (n m1 m2 p1 p2 &key (refclk +reference-frequency+))
    (let* ((p1 (ecase p1
                 (#b00000001 1)
                 (#b00000010 2)
                 (#b00000100 3)
                 (#b00001000 4)
                 (#b00010000 5)
                 (#b00100000 6)
                 (#b01000000 7)
                 (#b10000000 8)))
           (p2 (ecase p2
                 (#b00 10)
                 (#b01 5)))
           (m (+ (* 5 (+ m1 2)) (+ m2 2)))
           (p-div (* p1 p2)))
      (truncate (/ (* refclk m) (+ n 2) p-div))))
  
  (defun compute-pll-parameters (target-clock)
    "Calculate the best PLL paramters for TARGET-CLOCK.
  Returns the N, M1, M2, P1, P2, and the actual dot clock frequency."
    (let ((best-clock 0)
          (best-n 0) (best-m1 0) (best-m2 0)
          ;; p1 raw value, not register value
          (best-p1 0)
          ;; p2 raw value, not register value.
          (p2 10))
      ;; Cycle through all PLL values looking for the closest frequency.
      (loop
         for n from 3 to 8
         do (loop
               for m1 from 10 to 20
               do (loop
                     for m2 from 5 to 9
                     for m = (+ (* 5 (+ m1 2)) (+ m2 2))
                     when (<= 70 m 120)
                     do
                       (loop
                          for p1 from 1 to 8
                          for p-div = (* p1 p2)
                          when (<= 5 p-div 80)
                          do
                            (let* ((vco (/ (* +reference-frequency+ m) (+ n 2)))
                                   (clock (/ vco p-div)))
                              (when (and
                                     ;; Must be in range.
                                     (<= 1400000000 vco 2800000000)
                                     ;; Must be better.
                                     (< (abs (- target-clock clock))
                                        (abs (- target-clock best-clock))))
                                (setf best-clock clock
                                      best-n n
                                      best-m1 m1
                                      best-m2 m2
                                      best-p1 p1)))))))
      (let ((error (float (abs (- 1 (/ target-clock best-clock))))))
        ;; TODO: This should bail if the error is too great. It's not clear
        ;; what "too great" is though.
        (values best-n best-m1 best-m2
                (ash 1 (1- best-p1)) ; Convert to register value.
                #b00 ; p2 register value
                (truncate best-clock)
                error))))
  
  (defun save-current-mode-parameters (device)
    "Return a MODE-PARAMETERS object for the device's currently configured mode."
  