code:
;;;; unif.test --- tests guile's uniform arrays     -*- scheme -*-
;;;;
;;;; Copyright 2004, 2006 Free Software Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 2.1 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

(define-module (test-suite test-unif)
  #:use-module (test-suite lib))

;;;
;;; array?
;;;

(define exception:wrong-num-indices
  (cons 'misc-error "^wrong number of indices.*"))

(define exception:length-non-negative
  (cons 'read-error ".*array length must be non-negative.*"))

(with-test-prefix "array?"

  (let ((bool     (make-typed-array 'b    #t  '(5 6)))
	(char     (make-typed-array 'a    #\a '(5 6)))
	(byte     (make-typed-array 'u8   0   '(5 6)))
	(short    (make-typed-array 's16  0   '(5 6)))
	(ulong    (make-typed-array 'u32  0   '(5 6)))
	(long     (make-typed-array 's32  0   '(5 6)))
	(longlong (make-typed-array 's64  0   '(5 6)))
	(float    (make-typed-array 'f32  0   '(5 6)))
	(double   (make-typed-array 'f64  0   '(5 6)))
	(complex  (make-typed-array 'c64  0   '(5 6)))
	(scm      (make-typed-array #t    0   '(5 6))))

    (with-test-prefix "is bool"
      (pass-if (eq? #t (typed-array? bool     'b)))
      (pass-if (eq? #f (typed-array? char     'b)))
      (pass-if (eq? #f (typed-array? byte     'b)))
      (pass-if (eq? #f (typed-array? short    'b)))
      (pass-if (eq? #f (typed-array? ulong    'b)))
      (pass-if (eq? #f (typed-array? long     'b)))
      (pass-if (eq? #f (typed-array? longlong 'b)))
      (pass-if (eq? #f (typed-array? float    'b)))
      (pass-if (eq? #f (typed-array? double   'b)))
      (pass-if (eq? #f (typed-array? complex  'b)))
      (pass-if (eq? #f (typed-array? scm      'b))))

    (with-test-prefix "is char"
      (pass-if (eq? #f (typed-array? bool     'a)))
      (pass-if (eq? #t (typed-array? char     'a)))
      (pass-if (eq? #f (typed-array? byte     'a)))
      (pass-if (eq? #f (typed-array? short    'a)))
      (pass-if (eq? #f (typed-array? ulong    'a)))
      (pass-if (eq? #f (typed-array? long     'a)))
      (pass-if (eq? #f (typed-array? longlong 'a)))
      (pass-if (eq? #f (typed-array? float    'a)))
      (pass-if (eq? #f (typed-array? double   'a)))
      (pass-if (eq? #f (typed-array? complex  'a)))
      (pass-if (eq? #f (typed-array? scm      'a))))

    (with-test-prefix "is byte"
      (pass-if (eq? #f (typed-array? bool     'u8)))
      (pass-if (eq? #f (typed-array? char     'u8)))
      (pass-if (eq? #t (typed-array? byte     'u8)))
      (pass-if (eq? #f (typed-array? short    'u8)))
      (pass-if (eq? #f (typed-array? ulong    'u8)))
      (pass-if (eq? #f (typed-array? long     'u8)))
      (pass-if (eq? #f (typed-array? longlong 'u8)))
      (pass-if (eq? #f (typed-array? float    'u8)))
      (pass-if (eq? #f (typed-array? double   'u8)))
      (pass-if (eq? #f (typed-array? complex  'u8)))
      (pass-if (eq? #f (typed-array? scm      'u8))))

    (with-test-prefix "is short"
      (pass-if (eq? #f (typed-array? bool     's16)))
      (pass-if (eq? #f (typed-array? char     's16)))
      (pass-if (eq? #f (typed-array? byte     's16)))
      (pass-if (eq? #t (typed-array? short    's16)))
      (pass-if (eq? #f (typed-array? ulong    's16)))
      (pass-if (eq? #f (typed-array? long     's16)))
      (pass-if (eq? #f (typed-array? longlong 's16)))
      (pass-if (eq? #f (typed-array? float    's16)))
      (pass-if (eq? #f (typed-array? double   's16)))
      (pass-if (eq? #f (typed-array? complex  's16)))
      (pass-if (eq? #f (typed-array? scm      's16))))

    (with-test-prefix "is ulong"
      (pass-if (eq? #f (typed-array? bool     'u32)))
      (pass-if (eq? #f (typed-array? char     'u32)))
      (pass-if (eq? #f (typed-array? byte     'u32)))
      (pass-if (eq? #f (typed-array? short    'u32)))
      (pass-if (eq? #t (typed-array? ulong    'u32)))
      (pass-if (eq? #f (typed-array? long     'u32)))
      (pass-if (eq? #f (typed-array? longlong 'u32)))
      (pass-if (eq? #f (typed-array? float    'u32)))
      (pass-if (eq? #f (typed-array? double   'u32)))
      (pass-if (eq? #f (typed-array? complex  'u32)))
      (pass-if (eq? #f (typed-array? scm      'u32))))

    (with-test-prefix "is long"
      (pass-if (eq? #f (typed-array? bool     's32)))
      (pass-if (eq? #f (typed-array? char     's32)))
      (pass-if (eq? #f (typed-array? byte     's32)))
      (pass-if (eq? #f (typed-array? short    's32)))
      (pass-if (eq? #f (typed-array? ulong    's32)))
      (pass-if (eq? #t (typed-array? long     's32)))
      (pass-if (eq? #f (typed-array? longlong 's32)))
      (pass-if (eq? #f (typed-array? float    's32)))
      (pass-if (eq? #f (typed-array? double   's32)))
      (pass-if (eq? #f (typed-array? complex  's32)))
      (pass-if (eq? #f (typed-array? scm      's32))))

    (with-test-prefix "is long long"
      (pass-if (eq? #f (typed-array? bool     's64)))
      (pass-if (eq? #f (typed-array? char     's64)))
      (pass-if (eq? #f (typed-array? byte     's64)))
      (pass-if (eq? #f (typed-array? short    's64)))
      (pass-if (eq? #f (typed-array? ulong    's64)))
      (pass-if (eq? #f (typed-array? long     's64)))
      (pass-if (eq? #t (typed-array? longlong 's64)))
      (pass-if (eq? #f (typed-array? float    's64)))
      (pass-if (eq? #f (typed-array? double   's64)))
      (pass-if (eq? #f (typed-array? complex  's64)))
      (pass-if (eq? #f (typed-array? scm      's64))))

    (with-test-prefix "is float"
      (pass-if (eq? #f (typed-array? bool     'f32)))
      (pass-if (eq? #f (typed-array? char     'f32)))
      (pass-if (eq? #f (typed-array? byte     'f32)))
      (pass-if (eq? #f (typed-array? short    'f32)))
      (pass-if (eq? #f (typed-array? ulong    'f32)))
      (pass-if (eq? #f (typed-array? long     'f32)))
      (pass-if (eq? #f (typed-array? longlong 'f32)))
      (pass-if (eq? #t (typed-array? float    'f32)))
      (pass-if (eq? #f (typed-array? double   'f32)))
      (pass-if (eq? #f (typed-array? complex  'f32)))
      (pass-if (eq? #f (typed-array? scm      'f32))))

    (with-test-prefix "is double"
      (pass-if (eq? #f (typed-array? bool     'f64)))
      (pass-if (eq? #f (typed-array? char     'f64)))
      (pass-if (eq? #f (typed-array? byte     'f64)))
      (pass-if (eq? #f (typed-array? short    'f64)))
      (pass-if (eq? #f (typed-array? ulong    'f64)))
      (pass-if (eq? #f (typed-array? long     'f64)))
      (pass-if (eq? #f (typed-array? longlong 'f64)))
      (pass-if (eq? #f (typed-array? float    'f64)))
      (pass-if (eq? #t (typed-array? double   'f64)))
      (pass-if (eq? #f (typed-array? complex  'f64)))
      (pass-if (eq? #f (typed-array? scm      'f64))))

    (with-test-prefix "is complex"
      (pass-if (eq? #f (typed-array? bool     'c64)))
      (pass-if (eq? #f (typed-array? char     'c64)))
      (pass-if (eq? #f (typed-array? byte     'c64)))
      (pass-if (eq? #f (typed-array? short    'c64)))
      (pass-if (eq? #f (typed-array? ulong    'c64)))
      (pass-if (eq? #f (typed-array? long     'c64)))
      (pass-if (eq? #f (typed-array? longlong 'c64)))
      (pass-if (eq? #f (typed-array? float    'c64)))
      (pass-if (eq? #f (typed-array? double   'c64)))
      (pass-if (eq? #t (typed-array? complex  'c64)))
      (pass-if (eq? #f (typed-array? scm      'c64))))

    (with-test-prefix "is scm"
      (pass-if (eq? #f (typed-array? bool     #t)))
      (pass-if (eq? #f (typed-array? char     #t)))
      (pass-if (eq? #f (typed-array? byte     #t)))
      (pass-if (eq? #f (typed-array? short    #t)))
      (pass-if (eq? #f (typed-array? ulong    #t)))
      (pass-if (eq? #f (typed-array? long     #t)))
      (pass-if (eq? #f (typed-array? longlong #t)))
      (pass-if (eq? #f (typed-array? float    #t)))
      (pass-if (eq? #f (typed-array? double   #t)))
      (pass-if (eq? #f (typed-array? complex  #t)))
      (pass-if (eq? #t (typed-array? scm      #t))))))

;;;
;;; array-equal?
;;;

(with-test-prefix "array-equal?"

  (pass-if "#s16(...)"
    (array-equal? #s16(1 2 3) #s16(1 2 3))))

;;;
;;; array-fill!
;;;

(with-test-prefix "array-fill!"

  (with-test-prefix "bool"
    (let ((a (make-bitvector 1 #t)))
      (pass-if "#f" (array-fill! a #f) #t)
      (pass-if "#t" (array-fill! a #t) #t)))

  (with-test-prefix "char"
    (let ((a (make-string 1 #\a)))
      (pass-if "x" (array-fill! a #\x) #t)))

  (with-test-prefix "byte"
    (let ((a (make-s8vector 1 0)))
      (pass-if "0"    (array-fill! a 0)    #t)
      (pass-if "127" (array-fill! a 127)   #t)
      (pass-if "-128" (array-fill! a -128) #t)
      (pass-if-exception "128" exception:out-of-range
	(array-fill! a 128))
      (pass-if-exception "-129" exception:out-of-range
	(array-fill! a -129))
      (pass-if-exception "symbol" exception:wrong-type-arg
	(array-fill! a 'symbol))))

  (with-test-prefix "short"
    (let ((a (make-s16vector 1 0)))
      (pass-if "0"    (array-fill! a 0)    #t)
      (pass-if "123"  (array-fill! a 123)  #t)
      (pass-if "-123" (array-fill! a -123) #t)))

  (with-test-prefix "ulong"
    (let ((a (make-u32vector 1 1)))
      (pass-if "0"    (array-fill! a 0)   #t)
      (pass-if "123"  (array-fill! a 123) #t)
      (pass-if-exception "-123" exception:out-of-range
	(array-fill! a -123) #t)))

  (with-test-prefix "long"
    (let ((a (make-s32vector 1 -1)))
      (pass-if "0"    (array-fill! a 0)    #t)
      (pass-if "123"  (array-fill! a 123)  #t)
      (pass-if "-123" (array-fill! a -123) #t)))

  (with-test-prefix "float"
    (let ((a (make-f32vector 1 1.0)))
      (pass-if "0.0"    (array-fill! a 0)      #t)
      (pass-if "123.0"  (array-fill! a 123.0)  #t)
      (pass-if "-123.0" (array-fill! a -123.0) #t)
      (pass-if "0"      (array-fill! a 0)      #t)
      (pass-if "123"    (array-fill! a 123)    #t)
      (pass-if "-123"   (array-fill! a -123)   #t)
      (pass-if "5/8"    (array-fill! a 5/8)    #t)))

  (with-test-prefix "double"
    (let ((a (make-f64vector 1 1/3)))
      (pass-if "0.0"    (array-fill! a 0)      #t)
      (pass-if "123.0"  (array-fill! a 123.0)  #t)
      (pass-if "-123.0" (array-fill! a -123.0) #t)
      (pass-if "0"      (array-fill! a 0)      #t)
      (pass-if "123"    (array-fill! a 123)    #t)
      (pass-if "-123"   (array-fill! a -123)   #t)
      (pass-if "5/8"    (array-fill! a 5/8)    #t))))

;;;
;;; array-in-bounds?
;;;

(with-test-prefix "array-in-bounds?"

  (pass-if (let ((a (make-array #f '(425 425))))
	     (eq? #f (array-in-bounds? a 0)))))

;;;
;;; array-prototype
;;;

(with-test-prefix "array-type"

  (with-test-prefix "on make-foo-vector"

    (pass-if "bool"
      (eq? 'b (array-type (make-bitvector 1))))

    (pass-if "char"
      (eq? 'a (array-type (make-string 1))))

    (pass-if "byte"
      (eq? 'u8 (array-type (make-u8vector 1))))

    (pass-if "short"
      (eq? 's16 (array-type (make-s16vector 1))))

    (pass-if "ulong"
      (eq? 'u32 (array-type (make-u32vector 1))))

    (pass-if "long"
      (eq? 's32 (array-type (make-s32vector 1))))

    (pass-if "long long"
      (eq? 's64 (array-type (make-s64vector 1))))

    (pass-if "float"
      (eq? 'f32 (array-type (make-f32vector 1))))

    (pass-if "double"
      (eq? 'f64 (array-type (make-f64vector 1))))

    (pass-if "complex"
      (eq? 'c64 (array-type (make-c64vector 1))))

    (pass-if "scm"
      (eq? #t (array-type (make-vector 1)))))

  (with-test-prefix "on make-typed-array"

    (let ((types '(b a u8 s8 u16 s16 u32 s32 u64 u64 f32 f64 c32 c64)))
      (for-each (lambda (type)
		  (pass-if (symbol->string type)
		     (eq? type
			  (array-type (make-typed-array type
							*unspecified*
							'(5 6))))))
		types))))

;;;
;;; array-set!
;;;

(with-test-prefix "array-set!"

  (with-test-prefix "bitvector"

    ;; in Guile 1.8.0 a bug in bitvector_set() caused a segv in array-set!
    ;; on a bitvector like the following
    (let ((a (make-bitvector 1)))
      (pass-if "one elem set #t"
	(begin
	  (array-set! a #t 0)
	  (eq? #t (array-ref a 0))))
      (pass-if "one elem set #f"
	(begin
	  (array-set! a #f 0)
	  (eq? #f (array-ref a 0))))))

  (with-test-prefix "byte"

    (let ((a (make-s8vector 1)))

      (pass-if "-128"
	(begin (array-set! a -128 0) #t))
      (pass-if "0"
	(begin (array-set! a 0 0) #t))
      (pass-if "127"
	(begin (array-set! a 127 0) #t))
      (pass-if-exception "-129" exception:out-of-range
	(begin (array-set! a -129 0) #t))
      (pass-if-exception "128" exception:out-of-range
	(begin (array-set! a 128 0) #t))))

  (with-test-prefix "short"

    (let ((a (make-s16vector 1)))
      ;; true if n can be array-set! into a
      (define (fits? n)
	(false-if-exception (begin (array-set! a n 0) #t)))

      (with-test-prefix "store/fetch"
	;; Check array-ref gives back what was put with array-set!.
	;; In Guile 1.6.4 and earlier, array-set! only demanded an inum and
	;; would silently truncate to a short.

	(do ((n 1 (1+ (* 2 n))))  ;; n=2^k-1
	    ((not (fits? n)))
	  (array-set! a n 0)
	  (pass-if n
	    (= n (array-ref a 0))))

	(do ((n -1 (* 2 n)))      ;; -n=2^k
	    ((not (fits? n)))
	  (array-set! a n 0)
	  (pass-if n
	    (= n (array-ref a 0))))))))

;;;
;;; array-set!
;;;

(with-test-prefix "array-set!"

  (with-test-prefix "one dim"
    (let ((a (make-array #f '(3 5))))
      (pass-if "start"
	(array-set! a 'y 3)
	#t)
      (pass-if "end"
	(array-set! a 'y 5)
	#t)
      (pass-if-exception "start-1" exception:out-of-range
	(array-set! a 'y 2))
      (pass-if-exception "end+1" exception:out-of-range
	(array-set! a 'y 6))
      (pass-if-exception "two indexes" exception:out-of-range
	(array-set! a 'y 6 7))))

  (with-test-prefix "two dim"
    (let ((a (make-array #f '(3 5) '(7 9))))
      (pass-if "start"
	(array-set! a 'y 3 7)
	#t)
      (pass-if "end"
	(array-set! a 'y 5 9)
	#t)
      (pass-if-exception "start i-1" exception:out-of-range
	(array-set! a 'y 2 7))
      (pass-if-exception "end i+1" exception:out-of-range
	(array-set! a 'y 6 9))
      (pass-if-exception "one index" exception:wrong-num-indices
	(array-set! a 'y 4))
      (pass-if-exception "three indexes" exception:wrong-num-indices
	(array-set! a 'y 4 8 0)))))

;;;
;;; make-shared-array
;;;

(define exception:mapping-out-of-range
  (cons 'misc-error "^mapping out of range"))  ;; per scm_make_shared_array

(with-test-prefix "make-shared-array"

  ;; this failed in guile 1.8.0
  (pass-if "vector unchanged"
    (let* ((a (make-array #f '(0 7)))
	   (s (make-shared-array a list '(0 7))))
      (array-equal? a s)))

  (pass-if-exception "vector, high too big" exception:mapping-out-of-range
    (let* ((a (make-array #f '(0 7))))
      (make-shared-array a list '(0 8))))

  (pass-if-exception "vector, low too big" exception:out-of-range
    (let* ((a (make-array #f '(0 7))))
      (make-shared-array a list '(-1 7))))

  (pass-if "truncate columns"
    (array-equal? (make-shared-array #2((a b c) (d e f) (g h i)) list 3 2)
		  #2((a b) (d e) (g h))))

  (pass-if "pick one column"
    (array-equal? (make-shared-array #2((a b c) (d e f) (g h i))
				     (lambda (i) (list i 2))
				     '(0 2))
		  #(c f i)))

  (pass-if "diagonal"
    (array-equal? (make-shared-array #2((a b c) (d e f) (g h i))
				     (lambda (i) (list i i))
				     '(0 2))
		  #(a e i)))

  ;; this failed in guile 1.8.0
  (pass-if "2 dims from 1 dim"
    (array-equal? (make-shared-array #1(a b c d e f g h i j k l)
				     (lambda (i j) (list (+ (* i 3) j)))
				     4 3)
		  #2((a b c) (d e f) (g h i) (j k l))))

  (pass-if "reverse columns"
    (array-equal? (make-shared-array #2((a b c) (d e f) (g h i))
				     (lambda (i j) (list i (- 2 j)))
				     3 3)
		  #2((c b a) (f e d) (i h g))))

  (pass-if "fixed offset, 0 based becomes 1 based"
    (let* ((x #2((a b c) (d e f) (g h i)))
	   (y (make-shared-array x
				 (lambda (i j) (list (1- i) (1- j)))
				 '(1 3) '(1 3))))
      (and (eq? (array-ref x 0 0) 'a)
	   (eq? (array-ref y 1 1) 'a))))

  ;; this failed in guile 1.8.0
  (pass-if "stride every third element"
    (array-equal? (make-shared-array #1(a b c d e f g h i j k l)
				     (lambda (i) (list (* i 3)))
				     4)
		  #1(a d g j)))

  (pass-if "shared of shared"
    (let* ((a  #2((1 2 3) (4 5 6) (7 8 9)))
	   (s1 (make-shared-array a (lambda (i) (list i 1)) 3))
	   (s2 (make-shared-array s1 list '(1 2))))
      (and (eqv? 5 (array-ref s2 1))
	   (eqv? 8 (array-ref s2 2))))))

;;;
;;; uniform-vector-ref
;;;

(with-test-prefix "uniform-vector-ref"

  (with-test-prefix "byte"

    (let ((a (make-s8vector 1)))

      (pass-if "0"
	(begin
	  (array-set! a 0 0)
	  (= 0 (uniform-vector-ref a 0))))
      (pass-if "127"
	(begin
	  (array-set! a 127 0)
	  (= 127 (uniform-vector-ref a 0))))
      (pass-if "-128"
	(begin
	  (array-set! a -128 0)
	  (= -128 (uniform-vector-ref a 0)))))))

;;;
;;; syntax
;;;

(with-test-prefix "syntax"

  (pass-if "rank and lower bounds"
    ;; uniform u32 array of rank 2 with index ranges 2..3 and 7..8.
    (let ((a '#2u32@2@7((1 2) (3 4))))
      (and (array? a)
           (typed-array? a 'u32)
           (= (array-rank a) 2)
           (let loop ((bounds '((2 7) (2 8) (3 7) (3 8)))
                      (result #t))
             (if (null? bounds)
                 result
                 (and result
                      (loop (cdr bounds)
                            (apply array-in-bounds? a (car bounds)))))))))

  (pass-if "negative lower bound"
     (let ((a '#1@-3(a b)))
       (and (array? a)
            (= (array-rank a) 1)
            (array-in-bounds? a -3) (array-in-bounds? a -2)
            (eq? 'a (array-ref a -3))
            (eq? 'b (array-ref a -2)))))

  (pass-if-exception "negative length" exception:length-non-negative
     (with-input-from-string "'#1:-3(#t #t)" read)))

;;;
;;; equal? with vector and one-dimensional array
;;;

(pass-if "vector equal? one-dimensional array"
  (equal? (make-shared-array #2((a b c) (d e f) (g h i))
			     (lambda (i) (list i i))
			     '(0 2))
	  #(a e i)))


code:
;;;; vectors.test --- test suite for Guile's vector functions -*- scheme -*-
;;;;
;;;; Copyright (C) 2003, 2006, 2010 Free Software Foundation, Inc.
;;;;
;;;; This program is free software; you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
;;;; the Free Software Foundation; either version 2, or (at your option)
;;;; any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this software; see the file COPYING.  If not, write to
;;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;;;; Boston, MA 02110-1301 USA

(define-module (test-suite vectors)
  :use-module (test-suite lib))

;; FIXME:  As soon as guile supports immutable vectors, this has to be
;; replaced with the appropriate error type and message.
(define exception:immutable-vector
  (cons 'some-error-type "^trying to modify an immutable vector"))

(with-test-prefix "vector-set!"

  (expect-fail-exception "vector constant"
    exception:immutable-vector
    (vector-set! '#(1 2 3) 0 4)))

(with-test-prefix "vector->list"

  (pass-if "simple vector"
    (equal? '(1 2 3) (vector->list #(1 2 3))))

  (pass-if "shared array"
    (let ((b (make-shared-array #(1) (lambda (x) '(0)) 2)))
      (equal? b (list->vector (vector->list b))))))

(with-test-prefix "vector-move-left!"

  (pass-if-exception "before start" exception:out-of-range
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
      (vector-move-left! a 3 5 b -1)))

  (pass-if "beginning"
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
      (vector-move-left! a 3 5 b 0)
      (equal? b #(4 5 30 40 50 60 70 80 90))))

  (pass-if "middle"
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
      (vector-move-left! a 3 5 b 2)
      (equal? b #(10 20 4 5 50 60 70 80 90))))

  (pass-if "overlap -"
    (let ((a (vector 1 2 3 4 5 6 7 8 9)))
      (vector-move-left! a 3 5 a 2)
      (equal? a #(1 2 4 5 5 6 7 8 9))))

  (pass-if "overlap +"
    (let ((a (vector 1 2 3 4 5 6 7 8 9)))
      (vector-move-left! a 3 5 a 4)
      (equal? a #(1 2 3 4 4 4 7 8 9))))

  (pass-if "end"
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
       (vector-move-left! a 3 5 b 7)
       (equal? b #(10 20 30 40 50 60 70 4 5))))

  (pass-if-exception "past end" exception:out-of-range
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
      (vector-move-left! a 3 5 b 8))))

(with-test-prefix "vector-move-right!"

  (pass-if-exception "before start" exception:out-of-range
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
      (vector-move-right! a 3 5 b -1)))

  (pass-if "beginning"
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
      (vector-move-right! a 3 5 b 0)
      (equal? b #(4 5 30 40 50 60 70 80 90))))

  (pass-if "middle"
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
      (vector-move-right! a 3 5 b 2)
      (equal? b #(10 20 4 5 50 60 70 80 90))))

  (pass-if "overlap -"
    (let ((a (vector 1 2 3 4 5 6 7 8 9)))
      (vector-move-right! a 3 5 a 2)
      (equal? a #(1 2 5 5 5 6 7 8 9))))

  (pass-if "overlap +"
    (let ((a (vector 1 2 3 4 5 6 7 8 9)))
      (vector-move-right! a 3 5 a 4)
      (equal? a #(1 2 3 4 4 5 7 8 9))))

  (pass-if "end"
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
       (vector-move-right! a 3 5 b 7)
       (equal? b #(10 20 30 40 50 60 70 4 5))))

  (pass-if-exception "past end" exception:out-of-range
    (let ((a (vector 1 2 3 4 5 6 7 8 9))
          (b (vector 10 20 30 40 50 60 70 80 90)))
      (vector-move-right! a 3 5 b 8))))

license: unknown


code:
;;;; versions.test --- test suite for Guile's version functions  -*- scheme -*-
;;;; Greg J. Badros <gjb@cs.washington.edu>
;;;;
;;;; 	Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc.
;;;;
;;;; This program is free software; you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
;;;; the Free Software Foundation; either version 2, or (at your option)
;;;; any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this software; see the file COPYING.  If not, write to
;;;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;;;; Boston, MA 02110-1301 USA

(use-modules (test-suite lib))

(pass-if "version reporting works"
	 (and (string? (major-version))
	      (string? (minor-version))
	      (string? (micro-version))
	      (string=? (version)
			(string-append (major-version) "."
				       (minor-version) "."
				       (micro-version)))
	      (string=? (effective-version)
			(string-append (major-version) "."
				       (minor-version)))))


code:
;;;; weaks.test --- tests guile's weaks     -*- scheme -*-
;;;; Copyright (C) 1999, 2001, 2003, 2006 Free Software Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 2.1 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

;;; {Description}

;;; This is a semi test suite for weaks; I say semi, because weaks
;;; are pretty non-deterministic given the amount of information we
;;; can infer from scheme.
;;;
;;; In particular, we can't always reliably test the more important
;;; aspects of weaks (i.e., that an object is removed when it's dead)
;;; because we have no way of knowing for certain that the object is
;;; really dead. It tests it anyway, but the failures of any `death'
;;; tests really shouldn't be surprising.
;;;
;;; Interpret failures in the dying functions here as a hint that you
;;; should look at any changes you've made involving weaks
;;; (everything else should always pass), but there are a host of
;;; other reasons why they might not work as tested here, so if you
;;; haven't done anything to weaks, don't sweat it :)

(use-modules (test-suite lib)
	     (ice-9 weak-vector))

;;; Creation functions

(with-test-prefix
 "weak-creation"
 (with-test-prefix "make-weak-vector"
  (pass-if "normal"
    (make-weak-vector 10 #f)
    #t)
  (pass-if-exception "bad size"
    exception:wrong-type-arg
    (make-weak-vector 'foo)))

 (with-test-prefix "list->weak-vector"
		   (pass-if "create"
			    (let* ((lst '(a b c d e f g))
				   (wv (list->weak-vector lst)))
			      (and (eq? (vector-ref wv 0) 'a)
				   (eq? (vector-ref wv 1) 'b)
				   (eq? (vector-ref wv 2) 'c)
				   (eq? (vector-ref wv 3) 'd)
				   (eq? (vector-ref wv 4) 'e)
				   (eq? (vector-ref wv 5) 'f)
				   (eq? (vector-ref wv 6) 'g))))
		   (pass-if-exception "bad-args"
		     exception:wrong-type-arg
		     (list->weak-vector 32)))

 (with-test-prefix "make-weak-key-alist-vector"
		   (pass-if "create"
		     (make-weak-key-alist-vector 17)
		     #t)
		   (pass-if-exception "bad-args"
		     exception:wrong-type-arg
		     (make-weak-key-alist-vector '(bad arg))))
 (with-test-prefix "make-weak-value-alist-vector"
		   (pass-if "create"
		     (make-weak-value-alist-vector 17)
		     #t)
		   (pass-if-exception "bad-args"
		     exception:wrong-type-arg
		     (make-weak-value-alist-vector '(bad arg))))

 (with-test-prefix "make-doubly-weak-alist-vector"
		   (pass-if "create"
		     (make-doubly-weak-alist-vector 17)
		     #t)
		   (pass-if-exception "bad-args"
		     exception:wrong-type-arg
		     (make-doubly-weak-alist-vector '(bad arg)))))

;; This should remove most of the non-dying problems associated with
;; trying this inside a closure

(define global-weak (make-weak-vector 10 #f))
(begin
  (vector-set! global-weak 0 "string")
  (vector-set! global-weak 1 "beans")
  (vector-set! global-weak 2 "to")
  (vector-set! global-weak 3 "utah")
  (vector-set! global-weak 4 "yum yum")
  (gc))

;;; Normal weak vectors
(let ((x (make-weak-vector 10 #f))
      (bar "bar"))
  (with-test-prefix
   "weak-vector"
   (pass-if "lives"
	    (begin
	      (vector-set! x 0 bar)
	      (gc)
	      (and (vector-ref x 0) (eq? bar (vector-ref x 0)))))
   (pass-if "dies"
	    (begin
	      (gc)
	      (or (and (not (vector-ref global-weak 0))
		       (not (vector-ref global-weak 1))
		       (not (vector-ref global-weak 2))
		       (not (vector-ref global-weak 3))
		       (not (vector-ref global-weak 4)))
		  (throw 'unresolved))))))

 (let ((x (make-weak-key-alist-vector 17))
      (y (make-weak-value-alist-vector 17))
      (z (make-doubly-weak-alist-vector 17))
      (test-key "foo")
      (test-value "bar"))
  (with-test-prefix
   "weak-hash"
   (pass-if "lives"
	    (begin
	      (hashq-set! x test-key test-value)
	      (hashq-set! y test-key test-value)
	      (hashq-set! z test-key test-value)
	      (gc)
	      (gc)
	      (and (hashq-ref x test-key)
		   (hashq-ref y test-key)
		   (hashq-ref z test-key)
		   #t)))
   (pass-if "weak-key dies"
	    (begin
	      (hashq-set! x "this" "is")
	      (hashq-set! x "a" "test")
	      (hashq-set! x "of" "the")
	      (hashq-set! x "emergency" "weak")
	      (hashq-set! x "key" "hash system")
	      (gc)
	      (and
	       (or (not (hashq-ref x "this"))
		   (not (hashq-ref x "a"))
		   (not (hashq-ref x "of"))
		   (not (hashq-ref x "emergency"))
		   (not (hashq-ref x "key")))
	       (hashq-ref x test-key)
	       #t)))

   (pass-if "weak-value dies"
	    (begin
	      (hashq-set! y "this" "is")
	      (hashq-set! y "a" "test")
	      (hashq-set! y "of" "the")
	      (hashq-set! y "emergency" "weak")
	      (hashq-set! y "value" "hash system")
	      (gc)
	      (and (or (not (hashq-ref y "this"))
		       (not (hashq-ref y "a"))
		       (not (hashq-ref y "of"))
		       (not (hashq-ref y "emergency"))
		       (not (hashq-ref y "value")))
		   (hashq-ref y test-key)
		   #t)))
   (pass-if "doubly-weak dies"
	    (begin
	      (hashq-set! z "this" "is")
	      (hashq-set! z "a" "test")
	      (hashq-set! z "of" "the")
	      (hashq-set! z "emergency" "weak")
	      (hashq-set! z "all" "hash system")
	      (gc)
	      (and (or (not (hashq-ref z "this"))
		       (not (hashq-ref z "a"))
		       (not (hashq-ref z "of"))
		       (not (hashq-ref z "emergency"))
		       (not (hashq-ref z "all")))
		   (hashq-ref z test-key)
		   #t)))))


code:
# Object files
*.o
*.ko
*.obj
*.elf

# Libraries
*.lib
*.a

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex

# Linux kernel related
modules.order
modules.builtin
*.o.cmd

path: .gitignore

license: mit


code:
sm712fb
=======

Continued Maintained sm7xxfb of Linux kernel, but supports sm712 only.


code:
config FB_SM712
	tristate "Silicon Motion SM712 framebuffer support"
	depends on FB && PCI
	select FB_CFB_FILLRECT
	select FB_CFB_COPYAREA
	select FB_CFB_IMAGEBLIT
	help
	  Frame buffer driver for the Silicon Motion SM712 chip.

	  This driver is also available as a module. The module will be
	  called sm7xxfb. If you want to compile it as a module, say M
	  here and read <file:Documentation/kbuild/modules.txt>.


code: obj-$(CONFIG_FB_SM712) += sm712fb_drv.o sm712fb_accel.o


code:
TODO:
- Dual head support
- refine the code, convert more registers magic numbers to macros
- Does it really works on Big Endian machines?

Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and
Tom Li <biergaizi@member.fsf.org>.


code:
/*
 * Silicon Motion SM712 frame buffer device
 *
 * Copyright (C) 2006 Silicon Motion Technology Corp.
 * Authors:  Ge Wang, gewang@siliconmotion.com
 *	     Boyod boyod.yang@siliconmotion.com.cn
 *
 * Copyright (C) 2009 Lemote, Inc.
 * Author:   Wu Zhangjin, wuzhangjin@gmail.com
 *
 * Copyright (C) 2011 Igalia, S.L.
 * Author:   Javier M. Mellid <jmunhoz@igalia.com>
 *
 * Copyright (C) 2014 Tom Li.
 * Author:   Tom Li (Yifeng Li) <biergaizi@member.fsf.org>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file COPYING in the main directory of this archive for
 * more details.
 *
 * Framebuffer driver for Silicon Motion SM712 chip
 */

#include <linux/fb.h>
#include <linux/screen_info.h>
#include <linux/delay.h>

#include "sm712fb_drv.h"
#include "sm712fb_accel.h"

static inline u32 bytes_to_dword(const u8 *bytes, int length)
{
	u32 dword = 0;

	switch (length) {
#ifdef __BIG_ENDIAN
	case 3:
		dword |= bytes[2] << 8;
	case 2:
		dword |= bytes[1] << 16;
	case 1:
		dword |= bytes[0] << 24;
#else
	case 3:
		dword |= bytes[2] << 16;
	case 2:
		dword |= bytes[1] << 8;
	case 1:
		dword |= bytes[0];
#endif
	}
	return dword;
}

int sm712fb_init_accel(struct sm712fb_info *fb)
{
	u8 reg;

	/* reset the 2D engine */
	sm712_write_seq(fb, 0x21, sm712_read_seq(fb, 0x21) & 0xf8);
	reg = sm712_read_seq(fb, 0x15);
	sm712_write_seq(fb, 0x15, reg | 0x30);
	sm712_write_seq(fb, 0x15, reg);

	if (sm712fb_wait(fb) != 0)
		return -1;

	sm712_write_dpr(fb, DPR_CROP_TOPLEFT_COORDS, DPR_COORDS(0, 0));

	/* same width for DPR_PITCH and DPR_SRC_WINDOW */
	sm712_write_dpr(fb, DPR_PITCH,
			DPR_COORDS(fb->fb.var.xres, fb->fb.var.xres));
	sm712_write_dpr(fb, DPR_SRC_WINDOW,
			DPR_COORDS(fb->fb.var.xres, fb->fb.var.xres));

	if (fb->fb.var.bits_per_pixel == 24) {
		sm712_write_dpr(fb, DPR_PITCH,
				DPR_COORDS(fb->fb.var.xres * 3, fb->fb.var.xres * 3));
		sm712_write_dpr(fb, DPR_SRC_WINDOW,
				DPR_COORDS(fb->fb.var.xres, fb->fb.var.xres));
		sm712_writew_dpr(fb, DPR_DE_FORMAT_SELECT, DE_FORMAT_VAL);
	}

	sm712_write_dpr(fb, DPR_BYTE_BIT_MASK, 0xffffffff);
	sm712_write_dpr(fb, DPR_COLOR_COMPARE_MASK, 0);
	sm712_write_dpr(fb, DPR_COLOR_COMPARE, 0);
	sm712_write_dpr(fb, DPR_SRC_BASE, 0);
	sm712_write_dpr(fb, DPR_DST_BASE, 0);
	sm712_write_dpr(fb, DPR_MONO_PATTERN_LOW, 0xffffffff);
	sm712_write_dpr(fb, DPR_MONO_PATTERN_HIGH, 0xffffffff);
	sm712_read_dpr(fb, DPR_DST_BASE);

	return 0;
}

int sm712fb_wait(struct sm712fb_info *fb)
{
	int i;
	u8 reg;

	sm712_read_dpr(fb, DPR_DE_CTRL);
	for (i = 0; i < 10000; i++) {
		reg = sm712_read_seq(fb, SCR_DE_STATUS);
		if ((reg & SCR_DE_STATUS_MASK) == SCR_DE_ENGINE_IDLE)
			return 0;
		udelay(1);
	}
	printk("sm712fb: 2D engine hang detected!\n");
	return -EBUSY;
}

/*
 * VGA's CRT starting address is only effective for IBM VGA mode,
 * it doesn't work for a framebuffer. It should be removed.
 */
#if 0
int sm712fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
	struct sm712fb_info *sfb = info->par;
	u32 base;

	u8 low, high, extra;

	base = (var->yoffset * info->fix.line_length
	     + (var->xoffset & ~1) * ((info->var.bits_per_pixel + 7) / 8)) >> 2;

	/*
	 * On SM712, CRT starting address is a 19-bit value, 0x0d has the low
	 * 8-bit, 0x0c has the high 8-bit, while 0x30[6:4] stores the extra
	 * 3-bit high.
	 */
	low   = (base & 0x000000ff);
	high  = (base & 0x0000ff00) >> 8;
	extra = (base & 0x00070000) >> 16;

	sm712_write_crtc(sfb, 0x0d, low);
	sm712_write_crtc(sfb, 0x0c, high);
	sm712_write_crtc(sfb, 0x30,
			(sm712_read_crtc(sfb, 0x30) & 0x8f) | (extra << 4));

	return 0;
}
#endif

void sm712fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
	u32 width = rect->width, height = rect->height;
	u32 dx = rect->dx, dy = rect->dy;
	u32 color;

	struct sm712fb_info *sfb = info->par;

	if (unlikely(info->state != FBINFO_STATE_RUNNING))
		return;

	if (unlikely(rect->rop != ROP_COPY)) {
		/*
		 * It must be ROP_XOR. It's only used to combine a hardware
		 * cursor with the screen, and should never occur. Included
		 * for completeness. If one wants to implement hardware cursor
		 * (you don't, hardware only has RGB332 cursor), ROP2_XOR
		 * should be implemented here.
		 */
		cfb_fillrect(info, rect);
		return;
	}

	if ((rect->dx >= info->var.xres_virtual) ||
	    (rect->dy >= info->var.yres_virtual))
		return;

	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
	    info->fix.visual == FB_VISUAL_DIRECTCOLOR)
		color = ((u32 *) (info->pseudo_palette))[rect->color];
	else
		color = rect->color;

	if (sfb->fb.var.bits_per_pixel == 24) {
		dx *= 3;
		dy *= 3;
		width *= 3;

		/*
		 * In 24-bit color mode, SOLIDFILL will sometimes put random color stripes
		 * of garbage on the screen, it seems to be a hardware bug. Alternatively,
		 * we initialize DPR_MONO_PATTERN_LOW & HIGH with 0xffffffff (all ones,
		 * and we have already set that in sm712fb_init_accel). Since the color
		 * of this mono pattern is controlled by DPR_FG_COLOR, BITBLTing it with
		 * ROP_COPY is effectively a rectfill().
		 */
		sm712_write_dpr(sfb, DPR_FG_COLOR, color);
		sm712_write_dpr(sfb, DPR_DST_COORDS, DPR_COORDS(dx, dy));
		sm712_write_dpr(sfb, DPR_SPAN_COORDS, DPR_COORDS(width, height));
		sm712_write_dpr(sfb, DPR_DE_CTRL, DE_CTRL_START |
				DE_CTRL_ROP2_SELECT | DE_CTRL_ROP2_SRC_IS_PATTERN |
				(DE_CTRL_COMMAND_BITBLT << DE_CTRL_COMMAND_SHIFT) |
				(DE_CTRL_ROP2_COPY << DE_CTRL_ROP2_SHIFT));
	}
	else {
		sm712_write_dpr(sfb, DPR_FG_COLOR, color);
		sm712_write_dpr(sfb, DPR_DST_COORDS, DPR_COORDS(dx, dy));
		sm712_write_dpr(sfb, DPR_SPAN_COORDS, DPR_COORDS(width, height));
		sm712_write_dpr(sfb, DPR_DE_CTRL, DE_CTRL_START | DE_CTRL_ROP2_SELECT |
				(DE_CTRL_COMMAND_SOLIDFILL << DE_CTRL_COMMAND_SHIFT) |
				(DE_CTRL_ROP2_COPY << DE_CTRL_ROP2_SHIFT));
	}
	sm712fb_wait(sfb);
}

void sm712fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
{
	u32 sx = area->sx, sy = area->sy;
	u32 dx = area->dx, dy = area->dy;
	u32 height = area->height, width = area->width;
	u32 direction;

	struct sm712fb_info *sfb = info->par;

	if (unlikely(info->state != FBINFO_STATE_RUNNING))
		return;
	if ((sx >= info->var.xres_virtual) || (sy >= info->var.yres_virtual))
		return;

	if (sy < dy || (sy == dy && sx <= dx)) {
		sx += width - 1;
		dx += width - 1;
		sy += height - 1;
		dy += height - 1;
		direction = DE_CTRL_RTOL;
	} else {
		direction = 0;
	}

	if (sfb->fb.var.bits_per_pixel == 24) {
		sx *= 3;
		sy *= 3;
		dx *= 3;
		dy *= 3;
		width *= 3;
		if (direction == DE_CTRL_RTOL) {
			/*
			 * some hardware shenanigan from the original git
			 * commit, that is never clearly mentioned in the
			 * official datasheet. Not sure whether it even
			 * works correctly.
			 */
			sx += 2;
			dx += 2;
		}
	}

	sm712_write_dpr(sfb, DPR_SRC_COORDS, DPR_COORDS(sx, sy));
	sm712_write_dpr(sfb, DPR_DST_COORDS, DPR_COORDS(dx, dy));
	sm712_write_dpr(sfb, DPR_SPAN_COORDS, DPR_COORDS(width, height));
	sm712_write_dpr(sfb, DPR_DE_CTRL,
			DE_CTRL_START | DE_CTRL_ROP2_SELECT | direction |
			(DE_CTRL_COMMAND_BITBLT << DE_CTRL_COMMAND_SHIFT) |
			(DE_CTRL_ROP2_COPY << DE_CTRL_ROP2_SHIFT));
	sm712fb_wait(sfb);
}

void sm712fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
	u32 dx = image->dx, dy = image->dy;
	u32 width = image->width, height = image->height;
	u32 fg_color, bg_color;

	u32 total_bytes, total_dwords, leftovers;
	u32 i;
	u32 idx = 0;
	u32 scanline = image->width >> 3;

	struct sm712fb_info *sfb = info->par;

	if (unlikely(info->state != FBINFO_STATE_RUNNING))
		return;
	if ((image->dx >= info->var.xres_virtual) ||
	    (image->dy >= info->var.yres_virtual))
		return;

	if (unlikely(image->depth != 1)) {
		/* unsupported depth, fallback to draw Tux */
		cfb_imageblit(info, image);
		return;
	}

	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
		fg_color = ((u32 *) (info->pseudo_palette))[image->fg_color];
		bg_color = ((u32 *) (info->pseudo_palette))[image->bg_color];
	} else {
		fg_color = image->fg_color;
		bg_color = image->bg_color;
	}

	/* total bytes we need to write */
	total_bytes = (width + 7) / 8;
	total_dwords = (total_bytes & ~3) / 4;
	leftovers = total_bytes & 3;

	if (sfb->fb.var.bits_per_pixel == 24) {
		dx *= 3;
		dy *= 3;
		width *= 3;
	}
	sm712_write_dpr(sfb, DPR_SRC_COORDS, 0);
	sm712_write_dpr(sfb, DPR_DST_COORDS, DPR_COORDS(dx, dy));
	sm712_write_dpr(sfb, DPR_SPAN_COORDS, DPR_COORDS(width, height));
	sm712_write_dpr(sfb, DPR_FG_COLOR, fg_color);
	sm712_write_dpr(sfb, DPR_BG_COLOR, bg_color);
	sm712_write_dpr(sfb, DPR_DE_CTRL, DE_CTRL_START | DE_CTRL_ROP2_SELECT |
			(DE_CTRL_COMMAND_HOST_WRITE << DE_CTRL_COMMAND_SHIFT) |
			(DE_CTRL_HOST_MONO << DE_CTRL_HOST_SHIFT) |
			(DE_CTRL_ROP2_COPY << DE_CTRL_ROP2_SHIFT));

	for (i = 0; i < height; i++) {
		iowrite32_rep(sfb->dataport, &image->data[idx], total_dwords);
		if (leftovers) {
			writel_relaxed(
				bytes_to_dword(
					&image->data[idx + total_dwords * 4],
					leftovers),
				sfb->dataport);
		}
		idx += scanline;
	}
	mb();
	sm712fb_wait(sfb);
}


code:
/*
 * Silicon Motion SM712 frame buffer device
 *
 * Copyright (C) 2006 Silicon Motion Technology Corp.
 * Authors:  Ge Wang, gewang@siliconmotion.com
 *	     Boyod boyod.yang@siliconmotion.com.cn
 *
 * Copyright (C) 2009 Lemote, Inc.
 * Author:   Wu Zhangjin, wuzhangjin@gmail.com
 *
 * Copyright (C) 2011 Igalia, S.L.
 * Author:   Javier M. Mellid <jmunhoz@igalia.com>
 *
 * Copyright (C) 2014 Tom Li.
 * Author:   Tom Li (Yifeng Li) <biergaizi@member.fsf.org>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file COPYING in the main directory of this archive for
 * more details.
 *
 * Framebuffer driver for Silicon Motion SM712 chip
 */

#ifndef _SM712FB_ACCEL_H
#define _SM712FB_ACCEL_H

int sm712fb_init_accel(struct sm712fb_info *fb);
int sm712fb_wait(struct sm712fb_info *fb);
int sm712fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
void sm712fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
void sm712fb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
void sm712fb_imageblit(struct fb_info *info, const struct fb_image *image);

#endif


code:
/*
 * Silicon Motion SM712 frame buffer device
 *
 * Copyright (C) 2006 Silicon Motion Technology Corp.
 * Authors:  Ge Wang, gewang@siliconmotion.com
 *	     Boyod boyod.yang@siliconmotion.com.cn
 *
 * Copyright (C) 2009 Lemote, Inc.
 * Author:   Wu Zhangjin, wuzhangjin@gmail.com
 *
 * Copyright (C) 2011 Igalia, S.L.
 * Author:   Javier M. Mellid <jmunhoz@igalia.com>
 *
 * Copyright (C) 2014 Tom Li.
 * Author:   Tom Li (Yifeng Li) <biergaizi@member.fsf.org>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file COPYING in the main directory of this archive for
 * more details.
 *
 * Framebuffer driver for Silicon Motion SM712 chip
 */

#include <linux/io.h>
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/console.h>
#include <linux/screen_info.h>

#ifdef CONFIG_PM
#include <linux/pm.h>
#endif

#include "sm712fb_drv.h"
#include "sm712fb_accel.h"
#include "sm712fb_modedb.h"

static struct fb_var_screeninfo sm712fb_var = {
	.xres = 1024,
	.yres = 600,
	.xres_virtual = 1024,
	.yres_virtual = 600,
	.bits_per_pixel = 16,
	.red = {16, 8, 0},
	.green = {8, 8, 0},
	.blue = {0, 8, 0},
	.activate = FB_ACTIVATE_NOW,
	.height = -1,
	.width = -1,
	.vmode = FB_VMODE_NONINTERLACED,
	.nonstd = 0,
	.accel_flags = FB_ACCELF_TEXT,
};

static struct fb_fix_screeninfo sm712fb_fix = {
	.id = "smXXXfb",
	.type = FB_TYPE_PACKED_PIXELS,
	.visual = FB_VISUAL_TRUECOLOR,
	.line_length = 800 * 3,
	.accel = FB_ACCEL_SMI_LYNX,
	.type_aux = 0,
	.xpanstep = 0,
	.ypanstep = 0,
	.ywrapstep = 0,
};

struct vesa_mode {
	char index[6];
	u16 lfb_width;
	u16 lfb_height;
	u16 lfb_depth;
};

static bool accel = 1;

static struct vesa_mode vesa_mode_table[] = {
	{"0x301", 640, 480, 8},
	{"0x303", 800, 600, 8},
	{"0x305", 1024, 768, 8},
	{"0x307", 1280, 1024, 8},

	{"0x311", 640, 480, 16},
	{"0x314", 800, 600, 16},
	{"0x317", 1024, 768, 16},
	{"0x31A", 1280, 1024, 16},

	{"0x312", 640, 480, 24},
	{"0x315", 800, 600, 24},
	{"0x318", 1024, 768, 24},
	{"0x31B", 1280, 1024, 24},
};

struct screen_info sm712_scr_info;

static int sm712fb_setup(char *options)
{
	char *this_opt;

	if (!options || !*options)
		return 0;

	while ((this_opt = strsep(&options, ",")) != NULL) {
		if (!*this_opt)
			continue;

		if (!strcmp(this_opt, "accel:0"))
			accel = false;
		else if (!strcmp(this_opt, "accel:1"))
			accel = true;
	}
	return 0;
}

/* process command line options, get vga parameter */
static int __init sm712_vga_setup(char *options)
{
	int i;

	if (!options || !*options)
		return -EINVAL;

	sm712_scr_info.lfb_width = 0;
	sm712_scr_info.lfb_height = 0;
	sm712_scr_info.lfb_depth = 0;

	pr_debug("sm712_vga_setup = %s\n", options);

	for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) {
		if (strstr(options, vesa_mode_table[i].index)) {
			sm712_scr_info.lfb_width = vesa_mode_table[i].lfb_width;
			sm712_scr_info.lfb_height =
			    vesa_mode_table[i].lfb_height;
			sm712_scr_info.lfb_depth = vesa_mode_table[i].lfb_depth;
			return 0;
		}
	}

	return -1;
}

__setup("vga=", sm712_vga_setup);

static void sm712_setpalette(int regno, unsigned red, unsigned green,
			     unsigned blue, struct fb_info *info)
{
	struct sm712fb_info *sfb = info->par;

	/* set bit 5:4 = 01 (write LCD RAM only) */
	sm712_write_seq(sfb, 0x66, (sm712_read_seq(sfb, 0x66) & 0xC3) | 0x10);

	sm712_writeb(sfb->mmio, DAC_REG, regno);
	sm712_writeb(sfb->mmio, DAC_VAL, red >> 10);
	sm712_writeb(sfb->mmio, DAC_VAL, green >> 10);
	sm712_writeb(sfb->mmio, DAC_VAL, blue >> 10);
}

/* chan_to_field
 *
 * convert a colour value into a field position
 *
 * from pxafb.c
 */

static inline unsigned int chan_to_field(unsigned int chan,
					 struct fb_bitfield *bf)
{
	chan &= 0xffff;
	chan >>= 16 - bf->length;
	return chan << bf->offset;
}

static int sm712_blank(int blank_mode, struct fb_info *info)
{
	struct sm712fb_info *sfb = info->par;

	/* clear DPMS setting */
	switch (blank_mode) {
	case FB_BLANK_UNBLANK:
		/* Screen On: HSync: On, VSync : On */
		sm712_write_seq(sfb, 0x01,
				(sm712_read_seq(sfb, 0x01) & (~0x20)));
		sm712_write_seq(sfb, 0x6a, 0x16);
		sm712_write_seq(sfb, 0x6b, 0x02);
		sm712_write_seq(sfb, 0x21, (sm712_read_seq(sfb, 0x21) & 0x77));
		sm712_write_seq(sfb, 0x22,
				(sm712_read_seq(sfb, 0x22) & (~0x30)));
		sm712_write_seq(sfb, 0x23,
				(sm712_read_seq(sfb, 0x23) & (~0xc0)));
		sm712_write_seq(sfb, 0x24, (sm712_read_seq(sfb, 0x24) | 0x01));
		sm712_write_seq(sfb, 0x31, (sm712_read_seq(sfb, 0x31) | 0x03));
		break;
	case FB_BLANK_NORMAL:
		/* Screen Off: HSync: On, VSync : On   Soft blank */
		sm712_write_seq(sfb, 0x01,
				(sm712_read_seq(sfb, 0x01) & (~0x20)));
		sm712_write_seq(sfb, 0x6a, 0x16);
		sm712_write_seq(sfb, 0x6b, 0x02);
		sm712_write_seq(sfb, 0x22,
				(sm712_read_seq(sfb, 0x22) & (~0x30)));
		sm712_write_seq(sfb, 0x23,
				(sm712_read_seq(sfb, 0x23) & (~0xc0)));
		sm712_write_seq(sfb, 0x24, (sm712_read_seq(sfb, 0x24) | 0x01));
		sm712_write_seq(sfb, 0x31,
				((sm712_read_seq(sfb, 0x31) & (~0x07)) | 0x00));
		break;
	case FB_BLANK_VSYNC_SUSPEND:
		/* Screen On: HSync: On, VSync : Off */
		sm712_write_seq(sfb, 0x01, (sm712_read_seq(sfb, 0x01) | 0x20));
		sm712_write_seq(sfb, 0x20,
				(sm712_read_seq(sfb, 0x20) & (~0xB0)));
		sm712_write_seq(sfb, 0x6a, 0x0c);
		sm712_write_seq(sfb, 0x6b, 0x02);
		sm712_write_seq(sfb, 0x21, (sm712_read_seq(sfb, 0x21) | 0x88));
		sm712_write_seq(sfb, 0x22,
				((sm712_read_seq(sfb, 0x22) & (~0x30)) | 0x20));
		sm712_write_seq(sfb, 0x23,
				((sm712_read_seq(sfb, 0x23) & (~0xc0)) | 0x20));
		sm712_write_seq(sfb, 0x24,
				(sm712_read_seq(sfb, 0x24) & (~0x01)));
		sm712_write_seq(sfb, 0x31,
				((sm712_read_seq(sfb, 0x31) & (~0x07)) | 0x00));
		sm712_write_seq(sfb, 0x34, (sm712_read_seq(sfb, 0x34) | 0x80));
		break;
	case FB_BLANK_HSYNC_SUSPEND:
		/* Screen On: HSync: Off, VSync : On */
		sm712_write_seq(sfb, 0x01, (sm712_read_seq(sfb, 0x01) | 0x20));
		sm712_write_seq(sfb, 0x20,
				(sm712_read_seq(sfb, 0x20) & (~0xB0)));
		sm712_write_seq(sfb, 0x6a, 0x0c);
		sm712_write_seq(sfb, 0x6b, 0x02);
		sm712_write_seq(sfb, 0x21, (sm712_read_seq(sfb, 0x21) | 0x88));
		sm712_write_seq(sfb, 0x22,
				((sm712_read_seq(sfb, 0x22) & (~0x30)) | 0x10));
		sm712_write_seq(sfb, 0x23,
				((sm712_read_seq(sfb, 0x23) & (~0xc0)) | 0xD8));
		sm712_write_seq(sfb, 0x24,
				(sm712_read_seq(sfb, 0x24) & (~0x01)));
		sm712_write_seq(sfb, 0x31,
				((sm712_read_seq(sfb, 0x31) & (~0x07)) | 0x00));
		sm712_write_seq(sfb, 0x34, (sm712_read_seq(sfb, 0x34) | 0x80));
		break;
	case FB_BLANK_POWERDOWN:
		/* Screen On: HSync: Off, VSync : Off */
		sm712_write_seq(sfb, 0x01, (sm712_read_seq(sfb, 0x01) | 0x20));
		sm712_write_seq(sfb, 0x20,
				(sm712_read_seq(sfb, 0x20) & (~0xB0)));
		sm712_write_seq(sfb, 0x6a, 0x5a);
		sm712_write_seq(sfb, 0x6b, 0x20);
		sm712_write_seq(sfb, 0x21, (sm712_read_seq(sfb, 0x21) | 0x88));
		sm712_write_seq(sfb, 0x22,
				((sm712_read_seq(sfb, 0x22) & (~0x30)) | 0x30));
		sm712_write_seq(sfb, 0x23,
				((sm712_read_seq(sfb, 0x23) & (~0xc0)) | 0xD8));
		sm712_write_seq(sfb, 0x24,
				(sm712_read_seq(sfb, 0x24) & (~0x01)));
		sm712_write_seq(sfb, 0x31,
				((sm712_read_seq(sfb, 0x31) & (~0x07)) | 0x00));
		sm712_write_seq(sfb, 0x34, (sm712_read_seq(sfb, 0x34) | 0x80));
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int sm712_setcolreg(unsigned regno, unsigned red, unsigned green,
			   unsigned blue, unsigned trans, struct fb_info *info)
{
	struct sm712fb_info *sfb;
	u32 val;

	sfb = info->par;

	if (regno > 255)
		return 1;

	switch (sfb->fb.fix.visual) {
	case FB_VISUAL_DIRECTCOLOR:
	case FB_VISUAL_TRUECOLOR:
		/*
		 * 16/32 bit true-colour, use pseudo-palette for 16 base color
		 */
		if (regno < 16) {
			if (sfb->fb.var.bits_per_pixel == 16) {
				u32 *pal = sfb->fb.pseudo_palette;

				val = chan_to_field(red, &sfb->fb.var.red);
				val |= chan_to_field(green, &sfb->fb.var.green);
				val |= chan_to_field(blue, &sfb->fb.var.blue);
#ifdef __BIG_ENDIAN
				pal[regno] =
				    ((red & 0xf800) >> 8) |
				    ((green & 0xe000) >> 13) |
				    ((green & 0x1c00) << 3) |
				    ((blue & 0xf800) >> 3);
#else
				pal[regno] = val;
#endif
			} else {
				u32 *pal = sfb->fb.pseudo_palette;

				val = chan_to_field(red, &sfb->fb.var.red);
				val |= chan_to_field(green, &sfb->fb.var.green);
				val |= chan_to_field(blue, &sfb->fb.var.blue);
#ifdef __BIG_ENDIAN
				val =
				    (val & 0xff00ff00 >> 8) |
				    (val & 0x00ff00ff << 8);
#endif
				pal[regno] = val;
			}
		}
		break;

	case FB_VISUAL_PSEUDOCOLOR:
		/* color depth 8 bit */
		sm712_setpalette(regno, red, green, blue, info);
		break;

	default:
		return 1;	/* unknown type */
	}

	return 0;

}

#ifdef __BIG_ENDIAN
static ssize_t sm712fb_read(struct fb_info *info, char __user *buf,
			    size_t count, loff_t *ppos)
{
	unsigned long p = *ppos;

	u32 *buffer, *dst;
	u32 __iomem *src;
	int c, i, cnt = 0, err = 0;
	unsigned long total_size;

	if (!info || !info->screen_base)
		return -ENODEV;

	if (info->state != FBINFO_STATE_RUNNING)
		return -EPERM;

	total_size = info->screen_size;

	if (total_size == 0)
		total_size = info->fix.smem_len;

	if (p >= total_size)
		return 0;

	if (count >= total_size)
		count = total_size;

	if (count + p > total_size)
		count = total_size - p;

	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
	if (!buffer)
		return -ENOMEM;

	src = (u32 __iomem *) (info->screen_base + p);

	if (info->fbops->fb_sync)
		info->fbops->fb_sync(info);

	while (count) {
		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
		dst = buffer;
		for (i = c >> 2; i--;) {
			*dst = fb_readl(src++);
			*dst =
			    (*dst & 0xff00ff00 >> 8) | (*dst & 0x00ff00ff << 8);
			dst++;
		}
		if (c & 3) {
			u8 *dst8 = (u8 *) dst;
			u8 __iomem *src8 = (u8 __iomem *) src;

			for (i = c & 3; i--;) {
				if (i & 1) {
					*dst8++ = fb_readb(++src8);
				} else {
					*dst8++ = fb_readb(--src8);
					src8 += 2;
				}
			}
			src = (u32 __iomem *) src8;
		}

		if (copy_to_user(buf, buffer, c)) {
			err = -EFAULT;
			break;
		}
		*ppos += c;
		buf += c;
		cnt += c;
		count -= c;
	}

	kfree(buffer);

	return (err) ? err : cnt;
}

static ssize_t
sm712fb_write(struct fb_info *info, const char __user *buf, size_t count,
	      loff_t *ppos)
{
	unsigned long p = *ppos;

	u32 *buffer, *src;
	u32 __iomem *dst;
	int c, i, cnt = 0, err = 0;
	unsigned long total_size;

	if (!info || !info->screen_base)
		return -ENODEV;

	if (info->state != FBINFO_STATE_RUNNING)
		return -EPERM;

	total_size = info->screen_size;

	if (total_size == 0)
		total_size = info->fix.smem_len;

	if (p > total_size)
		return -EFBIG;

	if (count > total_size) {
		err = -EFBIG;
		count = total_size;
	}

	if (count + p > total_size) {
		if (!err)
			err = -ENOSPC;

		count = total_size - p;
	}

	buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);
	if (!buffer)
		return -ENOMEM;

	dst = (u32 __iomem *) (info->screen_base + p);

	if (info->fbops->fb_sync)
		info->fbops->fb_sync(info);

	while (count) {
		c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
		src = buffer;

		if (copy_from_user(src, buf, c)) {
			err = -EFAULT;
			break;
		}

		for (i = c >> 2; i--;) {
			fb_writel((*src & 0xff00ff00 >> 8) |
				  (*src & 0x00ff00ff << 8), dst++);
			src++;
		}
		if (c & 3) {
			u8 *src8 = (u8 *) src;
			u8 __iomem *dst8 = (u8 __iomem *) dst;

			for (i = c & 3; i--;) {
				if (i & 1) {
					fb_writeb(*src8++, ++dst8);
				} else {
					fb_writeb(*src8++, --dst8);
					dst8 += 2;
				}
			}
			dst = (u32 __iomem *) dst8;
		}

		*ppos += c;
		buf += c;
		cnt += c;
		count -= c;
	}

	kfree(buffer);

	return (cnt) ? cnt : err;
}
#endif /* ! __BIG_ENDIAN */

static void sm712_set_timing(struct sm712fb_info *sfb)
{
	int i = 0, j = 0;
	u32 m_nScreenStride;

	dev_dbg(&sfb->pdev->dev,
		"sfb->width=%d sfb->height=%d "
		"sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n",
		sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz);

	for (j = 0; j < numVGAModes; j++) {
		if (VGAMode[j].mmSizeX != sfb->width ||
		    VGAMode[j].mmSizeY != sfb->height ||
		    VGAMode[j].bpp != sfb->fb.var.bits_per_pixel ||
		    VGAMode[j].hz != sfb->hz) {
			continue;
		}

		dev_dbg(&sfb->pdev->dev,
			"VGAMode[j].mmSizeX=%d VGAMode[j].mmSizeY=%d "
			"VGAMode[j].bpp=%d VGAMode[j].hz=%d\n",
			VGAMode[j].mmSizeX, VGAMode[j].mmSizeY,
			VGAMode[j].bpp, VGAMode[j].hz);

		dev_dbg(&sfb->pdev->dev, "VGAMode index=%d\n", j);

		sm712_writeb(sfb->mmio, 0x3c6, 0x0);

		sm712_write_seq(sfb, 0, 0x1);

		sm712_writeb(sfb->mmio, 0x3c2, VGAMode[j].Init_MISC);

		/* init SEQ register SR00 - SR04 */
		for (i = 0; i < SR00_SR04_SIZE; i++)
			sm712_write_seq(sfb, i, VGAMode[j].Init_SR00_SR04[i]);

		/* init SEQ register SR10 - SR24 */
		for (i = 0; i < SR10_SR24_SIZE; i++)
			sm712_write_seq(sfb, i + 0x10,
					VGAMode[j].Init_SR10_SR24[i]);

		/* init SEQ register SR30 - SR75 */
		for (i = 0; i < SR30_SR75_SIZE; i++)
			if ((i + 0x30) != 0x62 &&
			    (i + 0x30) != 0x6a && (i + 0x30) != 0x6b)
				sm712_write_seq(sfb, i + 0x30,
						VGAMode[j].Init_SR30_SR75[i]);

		/* init SEQ register SR80 - SR93 */
		for (i = 0; i < SR80_SR93_SIZE; i++)
			sm712_write_seq(sfb, i + 0x80,
					VGAMode[j].Init_SR80_SR93[i]);

		/* init SEQ register SRA0 - SRAF */
		for (i = 0; i < SRA0_SRAF_SIZE; i++)
			sm712_write_seq(sfb, i + 0xa0,
					VGAMode[j].Init_SRA0_SRAF[i]);

		/* init Graphic register GR00 - GR08 */
		for (i = 0; i < GR00_GR08_SIZE; i++)
			sm712_write_grph(sfb, i, VGAMode[j].Init_GR00_GR08[i]);

		/* init Attribute register AR00 - AR14 */
		for (i = 0; i < AR00_AR14_SIZE; i++)
			sm712_write_attr(sfb, i, VGAMode[j].Init_AR00_AR14[i]);

		/* init CRTC register CR00 - CR18 */
		for (i = 0; i < CR00_CR18_SIZE; i++)
			sm712_write_crtc(sfb, i, VGAMode[j].Init_CR00_CR18[i]);

		/* init CRTC register CR30 - CR4D */
		for (i = 0; i < CR30_CR4D_SIZE; i++)
			sm712_write_crtc(sfb, i + 0x30,
					 VGAMode[j].Init_CR30_CR4D[i]);

		/* init CRTC register CR90 - CRA7 */
		for (i = 0; i < CR90_CRA7_SIZE; i++)
			sm712_write_crtc(sfb, i + 0x90,
					 VGAMode[j].Init_CR90_CRA7[i]);
	}
	sm712_writeb(sfb->mmio, 0x3c2, 0x67);

	/* set VPR registers */
	sm712_writel(sfb->vpr, 0x0C, 0x0);
	sm712_writel(sfb->vpr, 0x40, 0x0);

	/* set data width */
	m_nScreenStride = (sfb->width * sfb->fb.var.bits_per_pixel) / 64;
	switch (sfb->fb.var.bits_per_pixel) {
	case 8:
		sm712_writel(sfb->vpr, 0x0, 0x0);
		break;
	case 16:
		sm712_writel(sfb->vpr, 0x0, 0x00020000);
		break;
	case 24:
		sm712_writel(sfb->vpr, 0x0, 0x00040000);
		break;
	case 32:
		sm712_writel(sfb->vpr, 0x0, 0x00030000);
		break;
	}
	sm712_writel(sfb->vpr, 0x10,
		     (u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride));
}

static void sm712fb_setmode(struct sm712fb_info *sfb)
{
	switch (sfb->fb.var.bits_per_pixel) {
	case 32:
		sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
		sfb->fb.fix.line_length = sfb->fb.var.xres * 4;
		sfb->fb.var.red.length = 8;
		sfb->fb.var.green.length = 8;
		sfb->fb.var.blue.length = 8;
		sfb->fb.var.red.offset = 16;
		sfb->fb.var.green.offset = 8;
		sfb->fb.var.blue.offset = 0;
		break;
	case 24:
		sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
		sfb->fb.fix.line_length = sfb->fb.var.xres * 3;
		sfb->fb.var.red.length = 8;
		sfb->fb.var.green.length = 8;
		sfb->fb.var.blue.length = 8;
		sfb->fb.var.red.offset = 16;
		sfb->fb.var.green.offset = 8;
		sfb->fb.var.blue.offset = 0;
		break;
	case 8:
		sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
		sfb->fb.fix.line_length = sfb->fb.var.xres;
		sfb->fb.var.red.length = 3;
		sfb->fb.var.green.length = 3;
		sfb->fb.var.blue.length = 2;
		sfb->fb.var.red.offset = 5;
		sfb->fb.var.green.offset = 2;
		sfb->fb.var.blue.offset = 0;
		break;
	case 16:
	default:
		sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
		sfb->fb.fix.line_length = sfb->fb.var.xres * 2;
		sfb->fb.var.red.length = 5;
		sfb->fb.var.green.length = 6;
		sfb->fb.var.blue.length = 5;
		sfb->fb.var.red.offset = 11;
		sfb->fb.var.green.offset = 5;
		sfb->fb.var.blue.offset = 0;
		break;
	}

	sfb->width = sfb->fb.var.xres;
	sfb->height = sfb->fb.var.yres;
	sfb->hz = 60;
	sm712_set_timing(sfb);
}

static int sm712_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
	/* sanity checks */
	if (var->xres_virtual < var->xres)
		var->xres_virtual = var->xres;

	if (var->yres_virtual < var->yres)
		var->yres_virtual = var->yres;

	/* set valid default bpp */
	if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16) &&
	    (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32))
		var->bits_per_pixel = 16;

	return 0;
}

static int sm712_set_par(struct fb_info *info)
{
	sm712fb_setmode(info->par);

	return 0;
}

static struct fb_ops sm712fb_ops = {
	.owner = THIS_MODULE,
	.fb_check_var = sm712_check_var,
	.fb_set_par = sm712_set_par,
	.fb_setcolreg = sm712_setcolreg,
	.fb_blank = sm712_blank,
	.fb_fillrect = cfb_fillrect,
	.fb_imageblit = cfb_imageblit,
	.fb_copyarea = cfb_copyarea,
#ifdef __BIG_ENDIAN
	.fb_read = sm712fb_read,
	.fb_write = sm712fb_write,
#endif
};

/*
 * alloc struct sm712fb_info and assign default values
 */
static struct sm712fb_info *sm712_fb_info_new(struct pci_dev *pdev)
{
	struct sm712fb_info *sfb;

	sfb = kzalloc(sizeof(*sfb), GFP_KERNEL);

	if (!sfb)
		return NULL;

	sfb->pdev = pdev;

	sfb->fb.flags = FBINFO_FLAG_DEFAULT;
	sfb->fb.fbops = &sm712fb_ops;
	sfb->fb.fix = sm712fb_fix;
	sfb->fb.var = sm712fb_var;
	sfb->fb.pseudo_palette = sfb->colreg;
	sfb->fb.par = sfb;
	sfb->accel = accel;

	return sfb;
}

/*
 * free struct sm712fb_info
 */
static void sm712_fb_info_free(struct sm712fb_info *sfb)
{
	kfree(sfb);
}

/*
 * Map in the screen memory
 */

static int sm712_map_smem(struct sm712fb_info *sfb,
			  struct pci_dev *pdev, u_long smem_len)
{

	sfb->fb.fix.smem_start = pci_resource_start(pdev, 0);

#ifdef __BIG_ENDIAN
	if (sfb->fb.var.bits_per_pixel == 32)
		sfb->fb.fix.smem_start += 0x800000;
#endif

	sfb->fb.fix.smem_len = smem_len;

	sfb->fb.screen_base = sfb->lfb;

	if (!sfb->fb.screen_base) {
		dev_err(&pdev->dev,
			"%s: unable to map screen memory\n", sfb->fb.fix.id);
		return -ENOMEM;
	}

	return 0;
}

/*
 * Unmap in the screen memory
 *
 */
static void sm712_unmap_smem(struct sm712fb_info *sfb)
{
	if (sfb && sfb->fb.screen_base) {
		iounmap(sfb->fb.screen_base);
		sfb->fb.screen_base = NULL;
		sfb->lfb = NULL;
	}
}

static inline void sm712_init_hw(struct sm712fb_info *sfb)
{
	/* enable linear memory mode and packed pixel format */
	outb_p(0x18, 0x3c4);
	outb_p(0x11, 0x3c5);

	/* set MCLK = 14.31818 *  (0x16 / 0x2) */
	sm712_write_seq(sfb, 0x6a, 0x16);
	sm712_write_seq(sfb, 0x6b, 0x02);
	sm712_write_seq(sfb, 0x62, 0x3e);

	/* enable PCI burst */
	sm712_write_seq(sfb, 0x17, 0x20);

#ifdef __BIG_ENDIAN
	/* enable word swap */
	if (sfb->fb.var.bits_per_pixel == 32)
		sm712_write_seq(sfb, 0x17, 0x30);
#endif

	if (!sfb->accel) {
		dev_info(&sfb->pdev->dev, "2d acceleration was disabled by user.\n");
		sfb->fb.flags = FBINFO_FLAG_DEFAULT | FBINFO_HWACCEL_NONE;
		return;
	}

	if (sm712fb_init_accel(sfb) < 0) {
		dev_info(&sfb->pdev->dev, "failed to enable 2d accleration.\n");
		sfb->fb.flags = FBINFO_FLAG_DEFAULT | FBINFO_HWACCEL_NONE;
		sfb->accel = 0;
		return;
	} else {
		sm712fb_ops.fb_copyarea = sm712fb_copyarea;
		sm712fb_ops.fb_fillrect = sm712fb_fillrect;
		sm712fb_ops.fb_imageblit = sm712fb_imageblit;
		sfb->fb.flags |= FBINFO_HWACCEL_COPYAREA |
				 FBINFO_HWACCEL_FILLRECT | \
				 FBINFO_HWACCEL_IMAGEBLIT | \
		                 /* FBINFO_HWACCEL_YPAN | \ */ \
				 FBINFO_READS_FAST;
		dev_info(&sfb->pdev->dev, "sm712fb: enable 2d acceleration.\n");
	}
}

static int sm712fb_pci_probe(struct pci_dev *pdev,
			     const struct pci_device_id *ent)
{
	struct sm712fb_info *sfb;
	int err;
	unsigned long mmio_base;

#ifndef MODULE
	char *option = NULL;

	if (!fb_get_options("sm712fb", &option))
		sm712fb_setup(option);
#endif

	dev_info(&pdev->dev, "Silicon Motion display driver.");

	err = pci_enable_device(pdev);	/* enable SMTC chip */
	if (err)
		return err;

	sprintf(sm712fb_fix.id, "sm712fb");

	sfb = sm712_fb_info_new(pdev);

	if (!sfb) {
		err = -ENOMEM;
		goto free_fail;
	}

	sfb->chip_id = ent->device;

	pci_set_drvdata(pdev, sfb);

	/* get mode parameter from sm712_scr_info */
	if (sm712_scr_info.lfb_width != 0) {
		sfb->fb.var.xres = sm712_scr_info.lfb_width;
		sfb->fb.var.yres = sm712_scr_info.lfb_height;
		sfb->fb.var.bits_per_pixel = sm712_scr_info.lfb_depth;
	} else {
		/* default resolution 1024x600 16bit mode */
		sfb->fb.var.xres = SM712_DEFAULT_XRES;
		sfb->fb.var.yres = SM712_DEFAULT_YRES;
		sfb->fb.var.bits_per_pixel = SM712_DEFAULT_BPP;
	}

#ifdef __BIG_ENDIAN
	if (sfb->fb.var.bits_per_pixel == 24)
		sfb->fb.var.bits_per_pixel = (sm712_scr_info.lfb_depth = 32);
#endif

	/* Map address and memory detection */
	mmio_base = pci_resource_start(pdev, 0);
	pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);

	if (sfb->chip_id != 0x712) {
		dev_err(&pdev->dev,
			"No valid Silicon Motion display chip was detected!");

		goto fb_fail;
	}

	sfb->fb.fix.mmio_start = mmio_base + SM712_REG_BASE;
	sfb->fb.fix.mmio_len = SM712_REG_SIZE;
#ifdef __BIG_ENDIAN
	sfb->lfb = ioremap(mmio_base, 0x00c00000);
#else
	sfb->lfb = ioremap(mmio_base, 0x00800000);
#endif
	sfb->mmio = sfb->lfb + SM712_MMIO_BASE;
	sfb->dpr = sfb->lfb + SM712_DPR_BASE;
	sfb->vpr = sfb->lfb + SM712_VPR_BASE;
	sfb->dataport = sfb->lfb + SM712_DATAPORT_BASE;
#ifdef __BIG_ENDIAN
	if (sfb->fb.var.bits_per_pixel == 32) {
		sfb->lfb += 0x800000;
		dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb);
	}
#endif
	if (!sfb->mmio) {
		dev_err(&pdev->dev,
			"%s: unable to map memory mapped IO!", sfb->fb.fix.id);
		err = -ENOMEM;
		goto fb_fail;
	}

	sm712_init_hw(sfb);

	/* can support 32 bpp */
	if (15 == sfb->fb.var.bits_per_pixel)
		sfb->fb.var.bits_per_pixel = 16;

	sfb->fb.var.xres_virtual = sfb->fb.var.xres;
	sfb->fb.var.yres_virtual = sfb->fb.var.yres;
	err = sm712_map_smem(sfb, pdev, SM712_VRAM_SIZE);
	if (err)
		goto fail;

	sm712fb_setmode(sfb);

	err = register_framebuffer(&sfb->fb);
	if (err < 0)
		goto fail;

	dev_info(&pdev->dev,
		 "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.",
		 sfb->chip_id, sfb->chip_rev_id, sfb->fb.var.xres,
		 sfb->fb.var.yres, sfb->fb.var.bits_per_pixel);

	return 0;

fail:
	dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail.");

	sm712_unmap_smem(sfb);
fb_fail:
	sm712_fb_info_free(sfb);
free_fail:
	pci_disable_device(pdev);

	return err;
}

/*
 * 0x712 (LynxEM+)
 */
static const struct pci_device_id sm712fb_pci_table[] = {
	{PCI_DEVICE(0x126f, 0x712),},
	{0,}
};

static void sm712fb_pci_remove(struct pci_dev *pdev)
{
	struct sm712fb_info *sfb;

	sfb = pci_get_drvdata(pdev);
	sm712_unmap_smem(sfb);
	unregister_framebuffer(&sfb->fb);
	sm712_fb_info_free(sfb);
}

#ifdef CONFIG_PM
static int sm712fb_pci_suspend(struct device *device)
{
	struct pci_dev *pdev = to_pci_dev(device);
	struct sm712fb_info *sfb;

	sfb = pci_get_drvdata(pdev);

	/* set the hw in sleep mode use external clock and self memory refresh
	 * so that we can turn off internal PLLs later on
	 */
	sm712_write_seq(sfb, 0x20, (sm712_read_seq(sfb, 0x20) | 0xc0));
	sm712_write_seq(sfb, 0x69, (sm712_read_seq(sfb, 0x69) & 0xf7));

	console_lock();
	fb_set_suspend(&sfb->fb, 1);
	console_unlock();

	/* additionally turn off all function blocks including internal PLLs */
	sm712_write_seq(sfb, 0x21, 0xff);

	return 0;
}

static int sm712fb_pci_resume(struct device *device)
{
	struct pci_dev *pdev = to_pci_dev(device);
	struct sm712fb_info *sfb;

	sfb = pci_get_drvdata(pdev);

	/* reinit hardware */
	sm712_init_hw(sfb);

	sm712_write_seq(sfb, 0x34, (sm712_read_seq(sfb, 0x34) | 0xc0));
	sm712_write_seq(sfb, 0x33, ((sm712_read_seq(sfb, 0x33) | 0x08) & 0xfb));

	sm712fb_setmode(sfb);

	console_lock();
	fb_set_suspend(&sfb->fb, 0);
	console_unlock();

	return 0;
}

static SIMPLE_DEV_PM_OPS(sm712_pm_ops, sm712fb_pci_suspend, sm712fb_pci_resume);
#define SM712_PM_OPS (&sm712_pm_ops)

#else /* !CONFIG_PM */

#define SM712_PM_OPS NULL

#endif /* !CONFIG_PM */

static struct pci_driver sm712fb_driver = {
	.name = "sm712fb",
	.id_table = sm712fb_pci_table,
	.probe = sm712fb_pci_probe,
	.remove = sm712fb_pci_remove,
	.driver.pm = SM712_PM_OPS,
};

module_pci_driver(sm712fb_driver);

module_param(accel, bool, S_IRUGO);
MODULE_PARM_DESC(accel, "Enable or disable 2D Acceleration");

MODULE_AUTHOR("Siliconmotion ");
MODULE_DESCRIPTION("Framebuffer driver for Silicon Motion SM712 Graphic Cards");
MODULE_LICENSE("GPL");


code:
/*
 * Silicon Motion SM712 frame buffer device
 *
 * Copyright (C) 2006 Silicon Motion Technology Corp.
 * Authors:  Ge Wang, gewang@siliconmotion.com
 *	     Boyod boyod.yang@siliconmotion.com.cn
 *
 * Copyright (C) 2009 Lemote, Inc.
 * Author:   Wu Zhangjin, wuzhangjin@gmail.com
 *
 * Copyright (C) 2011 Igalia, S.L.
 * Author:   Javier M. Mellid <jmunhoz@igalia.com>
 *
 * Copyright (C) 2014 Tom Li.
 * Author:   Tom Li (Yifeng Li) <biergaizi@member.fsf.org>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file COPYING in the main directory of this archive for
 * more details.
 *
 * Framebuffer driver for Silicon Motion SM712 chip
 */

#ifndef _SM712FB_DRV_H
#define _SM712FB_DRV_H

/*
* Private structure
*/
struct sm712fb_info {
	struct pci_dev *pdev;
	struct fb_info fb;
	u16 chip_id;
	u8  chip_rev_id;

	void __iomem *lfb;	/* linear frame buffer, the base address */

	void __iomem *dpr;	/* drawing processor control regs */
	void __iomem *vpr;	/* video processor control regs */
	void __iomem *cpr;	/* capture processor control regs */
	void __iomem *mmio;	/* memory map IO port */
	void __iomem *dataport; /* 2d drawing engine data port */

	u_int width;
	u_int height;
	u_int hz;

	u32 colreg[17];

	bool accel;
};

/* constants for registers operations */

#include "sm712fb_io.h"

#define FB_ACCEL_SMI_LYNX		88

#define SM712_DEFAULT_XRES		1024
#define SM712_DEFAULT_YRES		600
#define SM712_DEFAULT_BPP		16

#define SM712_VRAM_SIZE			0x00400000

#define	SM712_REG_BASE			0x00400000
#define SM712_REG_SIZE                  0x00400000

#define	SM712_MMIO_BASE			0x00700000

#define	SM712_DPR_BASE			0x00408000
#define SM712_DPR_SIZE                  (0x6C + 1)

#define	DPR_COORDS(x, y)		(((x) << 16) | (y))

#define	DPR_SRC_COORDS			0x00
#define	DPR_DST_COORDS			0x04
#define	DPR_SPAN_COORDS			0x08
#define	DPR_DE_CTRL			0x0c
#define	DPR_PITCH			0x10
#define	DPR_FG_COLOR			0x14
#define	DPR_BG_COLOR			0x18
#define	DPR_STRETCH			0x1c
#define	DPR_DE_FORMAT_SELECT		0x1e    /* the only 16-bit write */
#define	DPR_COLOR_COMPARE		0x20
#define	DPR_COLOR_COMPARE_MASK		0x24
#define	DPR_BYTE_BIT_MASK		0x28
#define	DPR_CROP_TOPLEFT_COORDS		0x2c
#define	DPR_CROP_BOTRIGHT_COORDS	0x30
#define DPR_MONO_PATTERN_LOW		0x34
#define DPR_MONO_PATTERN_HIGH		0x38
#define	DPR_SRC_WINDOW			0x3c
#define	DPR_SRC_BASE			0x40
#define	DPR_DST_BASE			0x44

#define	DE_CTRL_START			0x80000000
#define	DE_CTRL_RTOL			0x08000000
#define	DE_CTRL_COMMAND_MASK		0x001f0000
#define	DE_CTRL_COMMAND_SHIFT			16
#define	DE_CTRL_COMMAND_BITBLT			0x00
#define	DE_CTRL_COMMAND_SOLIDFILL		0x01
#define DE_CTRL_COMMAND_HOST_WRITE              0x08
#define	DE_CTRL_ROP2_SELECT		0x00008000
#define DE_CTRL_ROP2_SRC_IS_PATTERN	0x00004000
#define	DE_CTRL_ROP2_COPY		0x0c
#define	DE_CTRL_ROP2_SHIFT		0
#define DE_CTRL_HOST_SHIFT              22
#define DE_CTRL_HOST_MONO               1

#define	DE_FORMAT_VAL			0b0000000000110000

#define SCR_DE_STATUS			0x16
#define SCR_DE_STATUS_MASK		0x18
#define SCR_DE_ENGINE_IDLE		0x10

#define	SM712_VPR_BASE			0x0040c000
#define SM712_VPR_SIZE                  (0x44 + 1)

#define SM712_DATAPORT_BASE             0x00400000

#define SR00_SR04_SIZE      (0x04 - 0x00 + 1)
#define SR10_SR24_SIZE      (0x24 - 0x10 + 1)
#define SR30_SR75_SIZE      (0x75 - 0x30 + 1)
#define SR80_SR93_SIZE      (0x93 - 0x80 + 1)
#define SRA0_SRAF_SIZE      (0xAF - 0xA0 + 1)
#define GR00_GR08_SIZE      (0x08 - 0x00 + 1)
#define AR00_AR14_SIZE      (0x14 - 0x00 + 1)
#define CR00_CR18_SIZE      (0x18 - 0x00 + 1)
#define CR30_CR4D_SIZE      (0x4D - 0x30 + 1)
#define CR90_CRA7_SIZE      (0xA7 - 0x90 + 1)

#define DAC_REG	(0x3c8)
#define DAC_VAL	(0x3c9)

#endif


code:
/*
 * Silicon Motion SM712 frame buffer device
 *
 * Copyright (C) 2006 Silicon Motion Technology Corp.
 * Authors:  Ge Wang, gewang@siliconmotion.com
 *	     Boyod boyod.yang@siliconmotion.com.cn
 *
 * Copyright (C) 2009 Lemote, Inc.
 * Author:   Wu Zhangjin, wuzhangjin@gmail.com
 *
 * Copyright (C) 2011 Igalia, S.L.
 * Author:   Javier M. Mellid <jmunhoz@igalia.com>
 *
 * Copyright (C) 2014 Tom Li.
 * Author:   Tom Li (Yifeng Li) <biergaizi@member.fsf.org>
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file COPYING in the main directory of this archive for
 * more details.
 *
 */

#define sm712_writeb(base, reg, dat)	writeb(dat, base + reg)
#define sm712_writew(base, reg, dat)	writew(dat, base + reg)
#define sm712_writel(base, reg, dat)	writel(dat, base + reg)

#define sm712_readb(base, reg)	readb(base + reg)
#define sm712_readw(base, reg)	readw(base + reg)
#define sm712_readl(base, reg)	readl(base + reg)

static inline void sm712_write_crtc(struct sm712fb_info *fb, u8 reg, u8 val)
{
	sm712_writeb(fb->mmio, 0x3d4, reg);
	sm712_writeb(fb->mmio, 0x3d5, val);
}

static inline u8 sm712_read_crtc(struct sm712fb_info *fb, u8 reg)
{
	sm712_writeb(fb->mmio, 0x3d4, reg);
	return sm712_readb(fb->mmio, 0x3d5);
}

static inline void sm712_write_grph(struct sm712fb_info *fb, u8 reg, u8 val)
{
	sm712_writeb(fb->mmio, 0x3ce, reg);
	sm712_writeb(fb->mmio, 0x3cf, val);
}

static inline u8 sm712_read_grph(struct sm712fb_info *fb, u8 reg)
{
	sm712_writeb(fb->mmio, 0x3ce, reg);
	return sm712_readb(fb->mmio, 0x3cf);
}

static inline void sm712_write_attr(struct sm712fb_info *fb, u8 reg, u8 val)
{
	sm712_readb(fb->mmio, 0x3da);
	sm712_writeb(fb->mmio, 0x3c0, reg);
	sm712_readb(fb->mmio, 0x3c1);
	sm712_writeb(fb->mmio, 0x3c0, val);
}

static inline void sm712_write_seq(struct sm712fb_info *fb, u8 reg, u8 val)
{
	sm712_writeb(fb->mmio, 0x3c4, reg);
	sm712_writeb(fb->mmio, 0x3c5, val);
}

static inline u8 sm712_read_seq(struct sm712fb_info *fb, u8 reg)
{
	sm712_writeb(fb->mmio, 0x3c4, reg);
	return sm712_readb(fb->mmio, 0x3c5);
}

static inline u32 sm712_read_dpr(struct sm712fb_info *fb, u8 reg)
{
	return sm712_readl(fb->dpr, reg);
}

static inline void sm712_write_dpr(struct sm712fb_info *fb, u8 reg, u32 val)
{
	sm712_writel(fb->dpr, reg, val);
}

static inline void sm712_writew_dpr(struct sm712fb_info *fb, u8 reg, u16 val)
{
	sm712_writew(fb->dpr, reg, val);
}


code:
/build/
/install/
/release/
/sources/
/libreboot.conf
.version
.revision
.tarfiles
.epoch
push
*.vim
/TODO/
/docs/version
/bucts/
/coreboot/
/crossgcc/
/flashrom/
/grub/
/memtest86plus/
/seabios/
/bin/
/resources/utilities/ich9deblob/*.rom
/resources/utilities/ich9deblob/*.bin
/resources/utilities/ich9deblob/ich9deblob
/resources/utilities/ich9deblob/ich9gen
/resources/utilities/ich9deblob/demefactory
/resources/utilities/ich9deblob/obj/*.o
/resources/utilities/ich9deblob/obj/*/*.o
/resources/utilities/ich9deblob/mkdescriptor*.[ch]
/resources/utilities/ich9deblob/mkgbe*.[ch]
/resources/utilities/grub-assemble/grub_*.elf
/mkgbe.[ch]
/*.bin
/resources/utilities/i945-pwm/i945-pwm
/push
/ChangeLog
/NEWS
/version
/versiondate
/gm45macaddress
tocheck*
*.html
!www/template.html
/www/temp.md
/www/news/index.md


code:
Paper Build System
==================

Entry Point
-----------

The entry point for using the paper build system is the main script in the root
directory, named after the build system (paper, libreboot, etc).
Running the main script with no argument will show its general usage.

Configuration
-------------

The paper build system can be configured with a script named after the build
system (paper, libreboot, etc) with a ".conf" suffix. It is automatically loaded
by the build system when running the main script.

It contains environment variables assigned to the desired values. The list of
environment variables is shown in the main script's general usage.

Project and Tool Targets
------------------------

The build system works around the concepts of projects and tools, that define
specific components that can be used to produce either:
* sources
* systems
* images
* tools

Various actions are available for each project and tool targets, many of which
are shown in the main script's general usage. Each project and tool may provide
a usage action that allows to see the specific usage for it. Actions are
executed recursively when no targets are specified.

Each project and tool target has its own directory (either in projects or tools)
that contain a script named after the target and possible a helper script, named
after the script with a "-helper" suffix. The helper script is automatically
included by the build system. Functions in helper scripts are usually prefixed
with the name of the target, where "-" symbols are replaced with "_" symbols.

Each project and tool target's actions are functions defined in the target's
specific script, with names matching the target's actions.

Meta-Targets
------------

Meta targets are project and tool targets that apply the requested action to
individual targets, allowing to execute an action to many targets at once.
For instance, a meta-target named after the build system with a "-all" suffix
would call other meta-targets, prefixed with "-images", "-tools", etc that would
then perform the requested action to all underlying targets.

Projects Actions
----------------

Various generic actions allow preparing projects through a series of steps:
* downloading, extracting or updating the project's sources
* building the project to a build directory
* installing the project to an install directory
* releasing the project to a release directory
* cleaning the build, install and release directories

Actions can be checked by a matching project-specific function, named after the
function to check with a "_check" suffix, to determine whether it is necessary
to run them again to follow the steps. An environment variable can force actions
to be executed, by specifying a space-separated list of projects:
PROJECTS_FORCE.

Projects Configuration and Patches
----------------------------------

Configuration for each project is stored in each project's own directory.
Targets for each project are defined with a "targets" file in each directory
of the "configs" directory. Targets are read recursively, following
sub-directory names for project targets.

Each project's configuration directory can be used to hold target-specific
information and configuration.

An "install" file in each sub-directory indicated which files to grab from the
build files and where to install them in the install directory.

Projects Sources
----------------

Each project can either download specific sources or use another project's
sources, possibly providing its own revision and patches.

Sources are downloaded with the "download" action or can be extracted from
released sources (after placing the sources in the sources directory) with the
"extract" action.

Projects may also keep their sources in a "sources" directory in their
project-specific directory.

Projects Build
--------------

Each project is built to a build directory, named after the project, with the
list of targets separated by a "-" symbol.

An environment variable allows controlling the number of tasks to run at the
same time: TASKS.

Projects Install
----------------

Projects are installed from "install" files in the project directory, that
copies the selected built files to the install directory, named after the
project, with the list of targets separated by a "-" symbol. These install files
are read recursively, following sub-directory names for project targets.

Additional files to install can be specified in the "install" directory and
described in an "install" file. These install files are read recursively,
following sub-directory names for project targets.

Projects Release
----------------

Projects are released to a release directory, named after the project, with the
list of targets separated by a "-" symbol. Each project's install files are
packed into a tarball to the corresponding release directory. A checksum and a
GPG detached signature (if the RELEASE_KEY environment variable is set) are also
generated.

Tarballs are generated reproducibly, from a list of files stored in the
".tarfiles" file. They may also contain the ".epoch", git ".revision" and
".version" files.

Tools Actions
-------------

Tools are used for maintaining the build system, for performing routine tasks
that can be automated. They may have specific actions and not implement any of
the generic actions.

Actions can be checked by a matching tool-specific function, named after the
function to check with a "_check" suffix, to determine whether it is necessary
to run them again to follow the steps. An environment variable can force actions
to be executed, by specifying a space-separated list of tasks: TASKS_FORCE.

Tools Sources
-------------

Tools may keep their sources in a "sources" directory in their tool-specific
directory. These sources may be updated with the "update" action.


code:
Libreboot project

Libreboot documentation is under docs/
The website is https://libreboot.org/
License can be found in COPYING and through parts of the source tree.

Libreboot is a free BIOS or UEFI replacement (free as in freedom); libre boot
firmware that initializes the hardware and starts a bootloader for your
operating system. It's also an open source BIOS, but open source fails to
promote freedom; please call libreboot free software.

Why use libreboot?

Many people use non-free boot firmware, even if they use GNU+Linux. Non-free
BIOS/UEFI firmware often contains backdoors, can be slow and have severe bugs,
where you are left helpless at the mercy of the developers; you have no freedom
over your computing. By contrast, libreboot is building a world where
everyone can use, study, adapt and share software, with true control and
ownership over their technology. In other words, you should use Libreboot for
your freedom's sake!

Libreboot is faster, more secure and more reliable than most non-free firmware,
and can provide many advanced features (such as encrypted /boot/, GPG signature
checking before booting your kernel, ability to load an OS from the flash chip,
and more).

Libreboot's main upstream providers are coreboot (which we deblob, for hardware
initialization), depthcharge (bootloader, and default libreboot payload on ARM),
and GRUB (bootloader, and default libreboot payload on x86). We also
integrate flashrom (for installing libreboot), and several of our own utilities,
scripts and configuration files. All of this is integrated into a single,
coherent package that is easy to use. We add our own patches to the various
upstreams used, and where feasible try to merge upstream as much as possible.

Libreboot provides a fully automated build system and installation process, with
documentation written for non-technical users, in an attempt to make the
software as easy to use as possible. ROM images are provided, along with
utilities, all built from the publicly distributed source code.

This README is licensed under Creative Commons Zero 1.0:
https://creativecommons.org/publicdomain/zero/1.0/

path: README


code:
Libreboot 20160907

For existing boards, there are no new board specific changes.

This release adds one new mainboard to libreboot:
* Intel D945GCLF desktop motherboard (thanks to Arthur Heymans)

Other bugfixes:
* Various improvements to the documentation
* re-added "unset superusers" to the grub.cfg, which was needed for some users
  depending on the distros that they used

Libreboot 20160902

This is a bugfix release, based on 20160818. It contains no new board changes.
The previous 20160818 release had build errors in the _src archive, and the
_util archive was only source code.

Changes compared to 20160818:
* Fixed bug where ./build module coreboot always returned non-zero status
* Fixed missing symlink of crossgcc when building from _src (thanks Arthur
Heymans)
* Fixed building with the depthcharge payload (ASUS C201)
* Proper ChangeLog now, instead of pasted git log
* Util archive is now binaries again (source code is in the _src archive)
* Documentation is now in HTML format

Libreboot 20160818

NEW BOARDS ADDED:
* ASUS Chromebook C201 (ARM laptop) (thanks to Paul Kocialkowski)
* Gigabyte GA-G41M-ES2L motherboard (desktop) (thanks to Damien Zammit)
* Intel D510MO motherboard (desktop) (thanks to Damien Zammit)
* ASUS KCMA-D8 motherboard (desktop) (thanks to Timothy Pearson)
* ASUS KFSN4-DRE motherboard (server) (thanks to Timothy Pearson)
* ASUS KGPE-D16 motherboard (server) (thanks to Timothy Pearson)

For boards previously supported, many fixes from upstream have been merged.

Other changes (compared to libreboot 20150518):
(this is a summary. For more detailed change list, refer to the git log)

256MiB VRAM allocated on GM45 (X200, T400, T500, R400) instead of 32MiB.
This is an improvement over both Lenovo BIOS and Libreboot 20150518, allowing
video decoding at 1080p to be smoother. (thanks Arthur Heymans)
To clarify, GM45 video performance in libreboot 20160818 is better than on
the original BIOS and the previous libreboot release.

64MiB VRAM on i945 (X60, T60, MacBook2,1) now supported in coreboot-libre, and
used by default (in the previous release, it was 8MiB allocated). Thanks to
Arthur Heymans.

Higher battery life on GM45 (X200, T400, T500, R400) due to higher cstates now
being supported (thanks Arthur Heymans). C4 power states also supported.

Text mode on GM45 (X200, T400, T500, R400) now works, making it possible to
use MemTest86+ comfortably. (thanks to Nick High from coreboot)

Dual channel LVDS displays on GM45 (T400, T500) are now automatically
detected in coreboot-libre. (thanks Vladimir Serbinenko from coreboot)

Partial fix in coreboot-libre for GRUB display on GM45, for dual channel
LVDS higher resolution LCD panels (T400, T500). (thanks Arthur Heymans)

Massively improved GRUB configuration, making it easier to boot more
encrypted systems automatically, and generally a more useful menu for booting
the system (thanks go to Klemens Nanni of the autoboot project).
Libreboot now uses the grub.cfg provided by the installed GNU+Linux distribution
automatically, if present, switching to that configuration. This is done across
many partitions, where libreboot actively searches for a configuration file
(also on LVM volumes and encrypted volumes). This should make libreboot more
easy to use for non-technical users, without having to modify the GRUB
configuration used in libreboot.

Utilities archives is now source only. You will need to compile the packages
in there (build scripts included, and a script for installing build
dependencies. (binary utility archives are planned again in the next
release, when the new build system is merged)

SeaGRUB is now the default payload on all x86 boards. (SeaBIOS configured to
load a compressed GRUB payload from CBFS immediately, without providing an
interface in SeaBIOS. This way, GRUB is still used but now BIOS services are
available, so you get the best of both worlds). Thanks go to Timothy Pearson
of coreboot for this idea.

crossgcc is now downloaded and built as a separate module to coreboot-libre,
with a universal revision used to build all boards.

Individual boards now have their own coreboot revision and patches, independently
of each other board. This makes maintenance easier.

Updated all utilities, and modules (coreboot, GRUB, etc) to newer versions,
with various bugfixes and improvements upstream.

RTC century byte issue now fixed on GM45 in coreboot-libre, so the date
should now be correctly displayed when running the latest linux kernel, instead
of seeing 1970-01-01 when you boot (thanks to Alexander Couzens from coreboot)

Build system now uses multiple CPU cores when building, speeding up building
for some people. Manually specifying how many cores are needed is also possible,
for those using the build system in a chroot environment. (thanks go to
Timothy Pearson from coreboot)

In the build system (git repository), https:// is now used when cloning coreboot.
http:// is used as a fallback for GRUB, if git:// fails.

New payload, the depthcharge bootloader (free bootloader maintained by Google)
for use on the ASUS Chromebook C201. (thanks go to Paul Kocialkowski)

Various fixes to the ich9gen utility (e.g. flash component density is now
set correctly in the descriptor, gbe-less descriptors now supported)

path: RELEASE


code:
---
title: How to install FreeBSD on a libreboot system
...

This section relates to preparing, booting and installing FreeBSD on
your libreboot system, using nothing more than a USB flash drive (and
*dd*). They've only been tested on a Lenovo ThinkPad x200.

It is expected that you use text mode in libreboot (txtmode images), for
the early boot process in FreeBSD. **Booting the installer results in a
red flickering text display, and doesn't boot.**

Thanks go to ioxcide in [this Reddit
post](https://www.reddit.com/r/BSD/comments/53jt70/libreboot_and_bsds/)
for the initial instructions.

TODO: test FreeBSD more extensively, and make sure it works (and fix it
if it does not). Instructions are provided here, to boot and install
FreeBSD but we're not sure whether it is currently fully compatible
with libreboot.

-   [Prepare the USB drive (in FreeBSD)](#prepare)
-   [Installing FreeBSD without full disk encryption](#noencryption)
-   [Installing FreeBSD with full disk encryption](#encryption)
-   [Booting](#booting)
-   [Configuring Grub](#configuring_grub)
-   [Troubleshooting](#troubleshooting)

**This section is only for the GRUB payload. For depthcharge (used on
CrOS devices in libreboot), instructions have yet to be written in the
libreboot documentation.**

freebsd.img is the installation image for FreeBSD. Adapt the filename
accordingly, for whatever FreeBSD version you use.

Prepare the USB drive (in FreeBSD)
----------------------------------

[This page](https://www.freebsd.org/doc/handbook/bsdinstall-pre.html) on
the FreeBSD website shows how to create a bootable USB drive for
installing FreeBSD. Use the *dd* on that page.

Prepare the USB drive (in NetBSD)
---------------------------------

[This
page](https://wiki.netbsd.org/tutorials/how_to_install_netbsd_from_an_usb_memory_stick/)
on the NetBSD website shows how to create a NetBSD bootable USB drive
from within NetBSD itself. You should use the *dd* method documented
there; you can use this with any ISO, including FreeBSD.

Prepare the USB drive (in LibertyBSD or OpenBSD)
------------------------------------------------

If you downloaded your ISO on a LibertyBSD or OpenBSD system, here is
how to create the bootable FreeBSD USB drive:

Connect the USB drive. Check dmesg:

    $ dmesg | tail

Check to confirm which drive it is, for example, if you think its sd3:

    $ disklabel sd3

Check that it wasn't automatically mounted. If it was, unmount it. For
example:

    $ doas umount /dev/sd3i

dmesg told you what device it is. Overwrite the drive, writing the
FreeBSD installer to it with dd. For example:

    $ doas dd if=freebsd.img of=/dev/rsdXc bs=1M; sync

You should now be able to boot the installer from your USB drive.
Continue reading, for information about how to do that.

Prepare the USB drive (in GNU+Linux)
------------------------------------

If you downloaded your ISO on a GNU+Linux system, here is how to create
the bootable FreeBSD USB drive:

Connect the USB drive. Check dmesg:

    $ dmesg
Check lsblk to confirm which drive it is:

    $ lsblk

Check that it wasn't automatically mounted. If it was, unmount it. For
example:

    $ sudo umount /dev/sdX\*
    # umount /dev/sdX\*

dmesg told you what device it is. Overwrite the drive, writing your
distro ISO to it with dd. For example:

    $ sudo dd if=freebsd.img of=/dev/sdX bs=8M; sync
    # dd if=freebsd.img of=/dev/sdX bs=8M; sync

You should now be able to boot the installer from your USB drive.
Continue reading, for information about how to do that.

Installing FreeBSD without full disk encryption
-----------------------------------------------

Press C in GRUB to access the command line:

    grub> kfreebsd (usb0,gpt3)/boot/kernel/kernel
    grub> set FreeBSD.vfs.mountfrom=ufs:/dev/da1p3\
    grub> boot

It will start booting into the FreeBSD installer. Follow the normal
process for installing FreeBSD.

Installing FreeBSD with full disk encryption
--------------------------------------------

TODO

Booting
-------

TODO

Configuring Grub
----------------

TODO

Troubleshooting
===============

Most of these issues occur when using libreboot with coreboot's 'text
mode' instead of the coreboot framebuffer. This mode is useful for
booting payloads like memtest86+ which expect text-mode, but for FreeBSD
it can be problematic when they are trying to switch to a framebuffer
because it doesn't exist.

In most cases, you should use the vesafb ROM images. Example filename:
libreboot\_ukdvorak\_vesafb.rom.

won't boot\...something about file not found
---------------------------------------------

Your device names (i.e. usb0, usb1, sd0, sd1, wd0, ahci0, hd0, etc) and
numbers may differ. Use TAB completion.

Copyright © 2016 Leah Rowe <info@minifree.org>\
Copyright © 2016 Scott Bonds <scott@ggr.com>\
This page is available under the [CC BY SA 4.0](../cc-by-sa-4.0.txt)


code:
---
title: BSD projects
...

This section relates to dealing with BSD projects: preparing bootable
USB drives, changing the default GRUB menu and so on.

**This section is only for the \*GRUB\* payload. For depthcharge,
instructions have yet to be written.**

-   [How to install NetBSD on a libreboot system](netbsd.md)
-   [How to install LibertyBSD or OpenBSD on a libreboot
    system](openbsd.md)

-   [How to install FreeBSD on a libreboot system](freebsd.md)

Copyright © 2016 Scott Bonds <scott@ggr.com>\
This page is available under the [CC BY SA 4.0](../cc-by-sa-4.0.txt)


code:
---
title: How to install NetBSD on a libreboot system
...

This section relates to preparing, booting and installing NetBSD on your
libreboot system, using nothing more than a USB flash drive (and *dd*).
They've only been tested on a librebooted ThinkPad X60.

It is expected that you use text mode in libreboot (txtmode images), for
the early boot process in NetBSD. **Suspend/hibernate is broken,
according to at least 1 user.**

Thanks go to ioxcide in [this Reddit
post](https://www.reddit.com/r/BSD/comments/53jt70/libreboot_and_bsds/)
for the initial instructions.

-   [Prepare the USB drive (in NetBSD)](#prepare)
-   [Installing NetBSD without full disk encryption](#noencryption)
-   [Installing NetBSD with full disk encryption](#encryption)
-   [Booting](#booting)
-   [Configuring Grub](#configuring_grub)
-   [Troubleshooting](#troubleshooting)

**This section is only for the GRUB payload. For depthcharge (used on
CrOS devices in libreboot), instructions have yet to be written in the
libreboot documentation.**

netbsd.iso is the installation image for NetBSD. Adapt the filename
accordingly, for your version of NetBSD.

Prepare the USB drive (in NetBSD)
---------------------------------

[This
page](https://wiki.netbsd.org/tutorials/how_to_install_netbsd_from_an_usb_memory_stick/)
on the NetBSD website shows how to create a NetBSD bootable USB drive
from within NetBSD itself. You should use the *dd* method documented
there.

Prepare the USB drive (in FreeBSD)
----------------------------------

[This page](https://www.freebsd.org/doc/handbook/bsdinstall-pre.html) on
the FreeBSD website shows how to create a bootable USB drive for
installing FreeBSD. Use the *dd* on that page. You can also use the same
instructions with a NetBSD ISO image.

Prepare the USB drive (in LibertyBSD or NetBSD)
-----------------------------------------------

If you downloaded your ISO on a LibertyBSD or NetBSD system, here is how
to create the bootable NetBSD USB drive:

Connect the USB drive. Check dmesg:

    $ dmesg | tail

Check to confirm which drive it is, for example, if you think its sd3:

    $ disklabel sd3

Check that it wasn't automatically mounted. If it was, unmount it. For
example:

    $ doas umount /dev/sd3i

dmesg told you what device it is. Overwrite the drive, writing the
NetBSD installer to it with dd. For example:

    $ doas netbsd.iso of=/dev/rsdXc bs=1M; sync

You should now be able to boot the installer from your USB drive.
Continue reading, for information about how to do that.

Prepare the USB drive (in GNU+Linux)
------------------------------------

If you downloaded your ISO on a GNU+Linux system, here is how to create
the bootable NetBSD USB drive:

Connect the USB drive. Check dmesg:

    $ dmesg
Check lsblk to confirm which drive it is:

    $ lsblk

Check that it wasn't automatically mounted. If it was, unmount it. For
example:

    $ sudo umount /dev/sdX\*
    # umount /dev/sdX\*

dmesg told you what device it is. Overwrite the drive, writing your
distro ISO to it with dd. For example:

    $ sudo dd if=install60.fs of=/dev/sdX bs=8M; sync
    # dd if=netbsd.iso of=/dev/sdX bs=8M; sync

You should now be able to boot the installer from your USB drive.
Continue reading, for information about how to do that.

Installing NetBSD without full disk encryption
----------------------------------------------

You might have to use an external USB keyboard during the installation.
Press C to access the GRUB terminal.

    grub> knetbsd -r sd0a (usb0,netbsd1)/netbsd
    grub> boot

It will start booting into the NetBSD installer. Follow the normal
process for installing NetBSD.

Installing NetBSD with full disk encryption
-------------------------------------------

TODO

Booting
-------

Press C in GRUB to access the command line:

    grub> knetbsd -r wd0a (ahci0,netbsd1)/netbsd
    grub> boot

NetBSD will start booting. Yay!

Configuring Grub
----------------

If you don't want to drop to the GRUB command line and type in a
command to boot NetBSD every time, you can create a GRUB configuration
that's aware of your NetBSD installation and that will automatically be
used by libreboot.

On your NetBSD root partition, create the **/grub** directory and add
the file **libreboot\_grub.cfg** to it. Inside the
**libreboot\_grub.cfg** add these lines:

**default=0 timeout=3 menuentry "NetBSD" {\
    knetbsd -r wd0a (ahci0,netbsd1)/netbsd\
}\
**

The next time you boot, you'll see the old Grub menu for a few seconds,
then you'll see the a new menu with only NetBSD on the list. After 3
seconds NetBSD will boot, or you can hit enter to boot.

Troubleshooting
===============

Most of these issues occur when using libreboot with coreboot's 'text
mode' instead of the coreboot framebuffer. This mode is useful for
booting payloads like memtest86+ which expect text-mode, but for NetBSD
it can be problematic when they are trying to switch to a framebuffer
because it doesn't exist.

In most cases, you should use the vesafb ROM images. Example filename:
libreboot\_ukdvorak\_vesafb.rom.

won't boot\...something about file not found
---------------------------------------------

Your device names (i.e. usb0, usb1, sd0, sd1, wd0, ahci0, hd0, etc) and
numbers may differ. Use TAB completion.

Copyright © 2016 Leah Rowe <info@minifree.org>\
Copyright © 2016 Scott Bonds <scott@ggr.com>\
This page is available under the [CC BY SA 4.0](../cc-by-sa-4.0.txt)