paul@49 | 1 | = System Architecture = |
paul@49 | 2 | |
paul@49 | 3 | A significant motivation for providing server programs is to isolate |
paul@49 | 4 | device-specific operations within separate components, thus preventing each |
paul@49 | 5 | component from having too broad access to low-level system functionality. The |
paul@49 | 6 | combination of components is then encouraged to achieve configuration |
paul@49 | 7 | objectives. |
paul@49 | 8 | |
paul@49 | 9 | For example, two computing systems that employ the same LCD controller might |
paul@49 | 10 | each employ different screen types and have different ways of controlling |
paul@49 | 11 | display behaviour. By defining explicit mechanisms for combining access to |
paul@49 | 12 | these different aspects of the hardware, common elements (such as the LCD |
paul@49 | 13 | controller) may be encapsulated by a device server that can be reused, with |
paul@49 | 14 | differing elements (such as the screen type) being described by separate |
paul@49 | 15 | resources or components that can be introduced as required. |
paul@49 | 16 | |
paul@49 | 17 | Here is how the Ben NanoNote's framebuffer is supported by components: |
paul@49 | 18 | |
paul@49 | 19 | ######## A graph showing the relationship between components. |
paul@49 | 20 | |
paul@49 | 21 | {{{#!graphviz |
paul@49 | 22 | #format svg |
paul@49 | 23 | #transform notugly |
paul@49 | 24 | digraph nanonote_framebuffer { |
paul@89 | 25 | node [shape=rectangle,fontsize="13.0",fontname="sans-serif"]; |
paul@49 | 26 | |
paul@49 | 27 | fb_drv [label="fb-drv"]; |
paul@49 | 28 | dev_cpm_jz4740 [label="dev_cpm_jz4740\nClock configuration"]; |
paul@49 | 29 | dev_display_qi_lb60 [label="dev_display_qi_lb60\nDisplay control"]; |
paul@49 | 30 | dev_backlight_spi_ili8960 [label="dev_backlight_spi_ili8960\nBacklight control"]; |
paul@49 | 31 | dev_spi_jz4740 [label="dev_spi_jz4740\nBacklight communication"]; |
paul@49 | 32 | |
paul@49 | 33 | fb_drv -> dev_cpm_jz4740; |
paul@49 | 34 | fb_drv -> dev_display_qi_lb60 -> dev_backlight_spi_ili8960 -> dev_spi_jz4740; |
paul@49 | 35 | } |
paul@49 | 36 | }}} |
paul@49 | 37 | |
paul@49 | 38 | ######## |
paul@49 | 39 | |
paul@49 | 40 | And here is how the Letux 400's framebuffer is supported: |
paul@49 | 41 | |
paul@49 | 42 | ######## A graph showing the relationship between components. |
paul@49 | 43 | |
paul@49 | 44 | {{{#!graphviz |
paul@49 | 45 | #format svg |
paul@49 | 46 | #transform notugly |
paul@49 | 47 | digraph letux400_framebuffer { |
paul@89 | 48 | node [shape=rectangle,fontsize="13.0",fontname="sans-serif"]; |
paul@49 | 49 | |
paul@49 | 50 | fb_drv [label="fb-drv"]; |
paul@49 | 51 | dev_cpm_jz4730 [label="dev_cpm_jz4730\nClock configuration"]; |
paul@49 | 52 | dev_display_letux400 [label="dev_display_letux400\nDisplay control"]; |
paul@49 | 53 | dev_backlight_pwm [label="dev_backlight_pwm\nBacklight control"]; |
paul@49 | 54 | dev_pwm_jz4730 [label="dev_pwm_jz4730\nBacklight communication"]; |
paul@49 | 55 | |
paul@49 | 56 | fb_drv -> dev_cpm_jz4730; |
paul@49 | 57 | fb_drv -> dev_display_letux400 -> dev_backlight_pwm -> dev_pwm_jz4730; |
paul@49 | 58 | } |
paul@49 | 59 | }}} |
paul@49 | 60 | |
paul@49 | 61 | ######## |
paul@49 | 62 | |
paul@49 | 63 | Note that fb-drv links to the same generic JZ4740 LCD controller library in |
paul@49 | 64 | both cases |
paul@49 | 65 | |
paul@49 | 66 | Here, the CPM device provides access to the clock and power management |
paul@49 | 67 | functionality, the display device provides access to the backlight and is |
paul@49 | 68 | responsible for configuring pins for the display. Device servers are connected |
paul@49 | 69 | using capabilities (object references). |
paul@49 | 70 | |
paul@49 | 71 | Meanwhile, panel information is provided via a dynamically-loaded library: |
paul@49 | 72 | |
paul@49 | 73 | ######## A graph showing the acquisition of panel information. |
paul@49 | 74 | |
paul@49 | 75 | {{{#!graphviz |
paul@49 | 76 | #format svg |
paul@49 | 77 | #transform notugly |
paul@49 | 78 | digraph panel_information { |
paul@89 | 79 | node [shape=rectangle,fontsize="13.0",fontname="sans-serif"]; |
paul@49 | 80 | |
paul@49 | 81 | subgraph { |
paul@49 | 82 | rank=min; |
paul@49 | 83 | fb_drv [label="fb-drv"]; |
paul@49 | 84 | } |
paul@49 | 85 | |
paul@49 | 86 | paneldata [label="mips-jz4740-panel.txt\nLibrary details"]; |
paul@49 | 87 | library [label="...\nLibrary with panel data"]; |
paul@49 | 88 | |
paul@49 | 89 | paneldata -> fb_drv -> library; |
paul@49 | 90 | } |
paul@49 | 91 | }}} |
paul@49 | 92 | |
paul@49 | 93 | ######## |
paul@49 | 94 | |
paul@49 | 95 | This method of obtaining a configured library name in order to load it |
paul@49 | 96 | dynamically is effectively equivalent to having a symbolic link identifying |
paul@49 | 97 | the library referencing the desired, specific library to be used. Since the |
paul@49 | 98 | "rom" virtual filesystem does not appear to support symbolic links, this |
paul@49 | 99 | method is used instead. |
paul@49 | 100 | |
paul@49 | 101 | By providing well-defined interfacing mechanisms, the behaviour of driver code |
paul@49 | 102 | can be parameterised using external components, and a proliferation of |
paul@49 | 103 | specially-constructed device drivers is hopefully avoided. |