/root/src/xen/xen/drivers/video/vga.c
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * vga.c |
3 | | * |
4 | | * VGA support routines. |
5 | | */ |
6 | | |
7 | | #include <xen/init.h> |
8 | | #include <xen/lib.h> |
9 | | #include <xen/mm.h> |
10 | | #include <xen/vga.h> |
11 | | #include <xen/pci.h> |
12 | | #include <asm/io.h> |
13 | | |
14 | | /* Filled in by arch boot code. */ |
15 | | struct xen_vga_console_info vga_console_info; |
16 | | |
17 | | static int vgacon_keep; |
18 | | static unsigned int xpos, ypos; |
19 | | static unsigned char *video; |
20 | | |
21 | | static void vga_text_puts(const char *s); |
22 | 118k | static void vga_noop_puts(const char *s) {} |
23 | | void (*video_puts)(const char *) = vga_noop_puts; |
24 | | |
25 | | /* |
26 | | * 'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of: |
27 | | * |
28 | | * 'vga=ask': |
29 | | * display a vga menu of available modes |
30 | | * |
31 | | * 'vga=current': |
32 | | * use the current vga mode without modification |
33 | | * |
34 | | * 'vga=text-80x<rows>': |
35 | | * text mode, where <rows> is one of {25,28,30,34,43,50,60} |
36 | | * |
37 | | * 'vga=gfx-<width>x<height>x<depth>': |
38 | | * graphics mode, e.g., vga=gfx-1024x768x16 |
39 | | * |
40 | | * 'vga=mode-<mode>: |
41 | | * specifies a mode as specified in 'vga=ask' menu |
42 | | * (NB. menu modes are displayed in hex, so mode numbers here must |
43 | | * be prefixed with '0x' (e.g., 'vga=mode-0x0318')) |
44 | | * |
45 | | * The option 'keep' causes Xen to continue to print to the VGA console even |
46 | | * after domain 0 starts to boot. The default behaviour is to relinquish |
47 | | * control of the console to domain 0. |
48 | | */ |
49 | | static char __initdata opt_vga[30] = ""; |
50 | | string_param("vga", opt_vga); |
51 | | |
52 | | /* VGA text-mode definitions. */ |
53 | | static unsigned int columns, lines; |
54 | 12.3k | #define ATTRIBUTE 7 |
55 | | |
56 | | #ifdef CONFIG_X86 |
57 | | void vesa_early_init(void); |
58 | | void vesa_endboot(bool_t keep); |
59 | | #else |
60 | | #define vesa_early_init() ((void)0) |
61 | | #define vesa_endboot(x) ((void)0) |
62 | | #endif |
63 | | |
64 | | void __init video_init(void) |
65 | 1 | { |
66 | 1 | char *p; |
67 | 1 | |
68 | 1 | /* Look for 'keep' in comma-separated options. */ |
69 | 2 | for ( p = opt_vga; p != NULL; p = strchr(p, ',') ) |
70 | 1 | { |
71 | 1 | if ( *p == ',' ) |
72 | 0 | p++; |
73 | 1 | if ( strncmp(p, "keep", 4) == 0 ) |
74 | 0 | vgacon_keep = 1; |
75 | 1 | } |
76 | 1 | |
77 | 1 | switch ( vga_console_info.video_type ) |
78 | 1 | { |
79 | 1 | case XEN_VGATYPE_TEXT_MODE_3: |
80 | 1 | if ( page_is_ram_type(paddr_to_pfn(0xB8000), RAM_TYPE_CONVENTIONAL) || |
81 | 1 | ((video = ioremap(0xB8000, 0x8000)) == NULL) ) |
82 | 0 | return; |
83 | 1 | outw(0x200a, 0x3d4); /* disable cursor */ |
84 | 1 | columns = vga_console_info.u.text_mode_3.columns; |
85 | 1 | lines = vga_console_info.u.text_mode_3.rows; |
86 | 1 | memset(video, 0, columns * lines * 2); |
87 | 1 | video_puts = vga_text_puts; |
88 | 1 | break; |
89 | 0 | case XEN_VGATYPE_VESA_LFB: |
90 | 0 | case XEN_VGATYPE_EFI_LFB: |
91 | 0 | vesa_early_init(); |
92 | 0 | break; |
93 | 0 | default: |
94 | 0 | memset(&vga_console_info, 0, sizeof(vga_console_info)); |
95 | 0 | break; |
96 | 1 | } |
97 | 1 | } |
98 | | |
99 | | void __init video_endboot(void) |
100 | 1 | { |
101 | 1 | if ( video_puts == vga_noop_puts ) |
102 | 0 | return; |
103 | 1 | |
104 | 1 | printk("Xen is %s VGA console.\n", |
105 | 1 | vgacon_keep ? "keeping" : "relinquishing"); |
106 | 1 | |
107 | 1 | if ( !vgacon_keep ) |
108 | 1 | video_puts = vga_noop_puts; |
109 | 1 | else |
110 | 0 | { |
111 | 0 | int bus, devfn; |
112 | 0 |
|
113 | 0 | for ( bus = 0; bus < 256; ++bus ) |
114 | 0 | for ( devfn = 0; devfn < 256; ++devfn ) |
115 | 0 | { |
116 | 0 | const struct pci_dev *pdev; |
117 | 0 | u8 b = bus, df = devfn, sb; |
118 | 0 |
|
119 | 0 | pcidevs_lock(); |
120 | 0 | pdev = pci_get_pdev(0, bus, devfn); |
121 | 0 | pcidevs_unlock(); |
122 | 0 |
|
123 | 0 | if ( !pdev || |
124 | 0 | pci_conf_read16(0, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), |
125 | 0 | PCI_CLASS_DEVICE) != 0x0300 || |
126 | 0 | !(pci_conf_read16(0, bus, PCI_SLOT(devfn), |
127 | 0 | PCI_FUNC(devfn), PCI_COMMAND) & |
128 | 0 | (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) ) |
129 | 0 | continue; |
130 | 0 |
|
131 | 0 | while ( b ) |
132 | 0 | { |
133 | 0 | switch ( find_upstream_bridge(0, &b, &df, &sb) ) |
134 | 0 | { |
135 | 0 | case 0: |
136 | 0 | b = 0; |
137 | 0 | break; |
138 | 0 | case 1: |
139 | 0 | switch ( pci_conf_read8(0, b, PCI_SLOT(df), |
140 | 0 | PCI_FUNC(df), |
141 | 0 | PCI_HEADER_TYPE) ) |
142 | 0 | { |
143 | 0 | case PCI_HEADER_TYPE_BRIDGE: |
144 | 0 | case PCI_HEADER_TYPE_CARDBUS: |
145 | 0 | if ( pci_conf_read16(0, b, PCI_SLOT(df), |
146 | 0 | PCI_FUNC(df), |
147 | 0 | PCI_BRIDGE_CONTROL) & |
148 | 0 | PCI_BRIDGE_CTL_VGA ) |
149 | 0 | continue; |
150 | 0 | break; |
151 | 0 | } |
152 | 0 | break; |
153 | 0 | } |
154 | 0 | break; |
155 | 0 | } |
156 | 0 | if ( !b ) |
157 | 0 | { |
158 | 0 | printk(XENLOG_INFO "Boot video device %02x:%02x.%u\n", |
159 | 0 | bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
160 | 0 | pci_hide_device(bus, devfn); |
161 | 0 | } |
162 | 0 | } |
163 | 0 | } |
164 | 1 | |
165 | 1 | switch ( vga_console_info.video_type ) |
166 | 1 | { |
167 | 1 | case XEN_VGATYPE_TEXT_MODE_3: |
168 | 1 | if ( !vgacon_keep ) |
169 | 1 | memset(video, 0, columns * lines * 2); |
170 | 1 | break; |
171 | 0 | case XEN_VGATYPE_VESA_LFB: |
172 | 0 | case XEN_VGATYPE_EFI_LFB: |
173 | 0 | vesa_endboot(vgacon_keep); |
174 | 0 | break; |
175 | 0 | default: |
176 | 0 | BUG(); |
177 | 1 | } |
178 | 1 | } |
179 | | |
180 | | static void vga_text_puts(const char *s) |
181 | 882 | { |
182 | 882 | char c; |
183 | 882 | |
184 | 13.4k | while ( (c = *s++) != '\0' ) |
185 | 12.6k | { |
186 | 12.6k | if ( (c == '\n') || (xpos >= columns) ) |
187 | 272 | { |
188 | 272 | if ( ++ypos >= lines ) |
189 | 248 | { |
190 | 248 | ypos = lines - 1; |
191 | 248 | memmove(video, video + 2 * columns, ypos * 2 * columns); |
192 | 248 | memset(video + ypos * 2 * columns, 0, 2 * xpos); |
193 | 248 | } |
194 | 272 | xpos = 0; |
195 | 272 | } |
196 | 12.6k | |
197 | 12.6k | if ( c != '\n' ) |
198 | 12.3k | { |
199 | 12.3k | video[(xpos + ypos * columns) * 2] = c; |
200 | 12.3k | video[(xpos + ypos * columns) * 2 + 1] = ATTRIBUTE; |
201 | 12.3k | xpos++; |
202 | 12.3k | } |
203 | 12.6k | } |
204 | 882 | } |
205 | | |
206 | | int __init fill_console_start_info(struct dom0_vga_console_info *ci) |
207 | 0 | { |
208 | 0 | memcpy(ci, &vga_console_info, sizeof(*ci)); |
209 | 0 | return 1; |
210 | 0 | } |