VGA: Extract code from vga.c into new files vgaio.c and vgafb.c.
[seabios.git] / vgasrc / vgaio.c
1 // VGA io port access
2 //
3 // Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
4 // Copyright (C) 2001-2008 the LGPL VGABios developers Team
5 //
6 // This file may be distributed under the terms of the GNU LGPLv3 license.
7
8 #include "ioport.h" // outb
9 #include "bregs.h" // struct bregs
10 #include "farptr.h" // SET_FARVAR
11 #include "vgatables.h" // VGAREG_*
12
13
14 /****************************************************************
15  * Attribute control
16  ****************************************************************/
17
18 void
19 biosfn_set_border_color(struct bregs *regs)
20 {
21     inb(VGAREG_ACTL_RESET);
22     outb(0x00, VGAREG_ACTL_ADDRESS);
23     u8 al = regs->bl & 0x0f;
24     if (al & 0x08)
25         al += 0x08;
26     outb(al, VGAREG_ACTL_WRITE_DATA);
27     u8 bl = regs->bl & 0x10;
28
29     int i;
30     for (i = 1; i < 4; i++) {
31         outb(i, VGAREG_ACTL_ADDRESS);
32
33         al = inb(VGAREG_ACTL_READ_DATA);
34         al &= 0xef;
35         al |= bl;
36         outb(al, VGAREG_ACTL_WRITE_DATA);
37     }
38     outb(0x20, VGAREG_ACTL_ADDRESS);
39 }
40
41 void
42 biosfn_set_overscan_border_color(struct bregs *regs)
43 {
44     inb(VGAREG_ACTL_RESET);
45     outb(0x11, VGAREG_ACTL_ADDRESS);
46     outb(regs->bh, VGAREG_ACTL_WRITE_DATA);
47     outb(0x20, VGAREG_ACTL_ADDRESS);
48 }
49
50 void
51 biosfn_read_overscan_border_color(struct bregs *regs)
52 {
53     inb(VGAREG_ACTL_RESET);
54     outb(0x11, VGAREG_ACTL_ADDRESS);
55     regs->bh = inb(VGAREG_ACTL_READ_DATA);
56     inb(VGAREG_ACTL_RESET);
57     outb(0x20, VGAREG_ACTL_ADDRESS);
58 }
59
60 void
61 biosfn_set_palette(struct bregs *regs)
62 {
63     inb(VGAREG_ACTL_RESET);
64     u8 bl = regs->bl & 0x01;
65     int i;
66     for (i = 1; i < 4; i++) {
67         outb(i, VGAREG_ACTL_ADDRESS);
68
69         u8 al = inb(VGAREG_ACTL_READ_DATA);
70         al &= 0xfe;
71         al |= bl;
72         outb(al, VGAREG_ACTL_WRITE_DATA);
73     }
74     outb(0x20, VGAREG_ACTL_ADDRESS);
75 }
76
77 void
78 biosfn_set_single_palette_reg(u8 reg, u8 val)
79 {
80     inb(VGAREG_ACTL_RESET);
81     outb(reg, VGAREG_ACTL_ADDRESS);
82     outb(val, VGAREG_ACTL_WRITE_DATA);
83     outb(0x20, VGAREG_ACTL_ADDRESS);
84 }
85
86 u8
87 biosfn_get_single_palette_reg(u8 reg)
88 {
89     inb(VGAREG_ACTL_RESET);
90     outb(reg, VGAREG_ACTL_ADDRESS);
91     u8 v = inb(VGAREG_ACTL_READ_DATA);
92     inb(VGAREG_ACTL_RESET);
93     outb(0x20, VGAREG_ACTL_ADDRESS);
94     return v;
95 }
96
97 void
98 biosfn_set_all_palette_reg(struct bregs *regs)
99 {
100     inb(VGAREG_ACTL_RESET);
101
102     u8 *data_far = (u8*)(regs->dx + 0);
103     int i;
104     for (i = 0; i < 0x10; i++) {
105         outb(i, VGAREG_ACTL_ADDRESS);
106         u8 val = GET_FARVAR(regs->es, *data_far);
107         outb(val, VGAREG_ACTL_WRITE_DATA);
108         data_far++;
109     }
110     outb(0x11, VGAREG_ACTL_ADDRESS);
111     outb(GET_FARVAR(regs->es, *data_far), VGAREG_ACTL_WRITE_DATA);
112     outb(0x20, VGAREG_ACTL_ADDRESS);
113 }
114
115 void
116 biosfn_get_all_palette_reg(struct bregs *regs)
117 {
118     u8 *data_far = (u8*)(regs->dx + 0);
119     int i;
120     for (i = 0; i < 0x10; i++) {
121         inb(VGAREG_ACTL_RESET);
122         outb(i, VGAREG_ACTL_ADDRESS);
123         SET_FARVAR(regs->es, *data_far, inb(VGAREG_ACTL_READ_DATA));
124         data_far++;
125     }
126     inb(VGAREG_ACTL_RESET);
127     outb(0x11, VGAREG_ACTL_ADDRESS);
128     SET_FARVAR(regs->es, *data_far, inb(VGAREG_ACTL_READ_DATA));
129     inb(VGAREG_ACTL_RESET);
130     outb(0x20, VGAREG_ACTL_ADDRESS);
131 }
132
133 void
134 biosfn_toggle_intensity(struct bregs *regs)
135 {
136     inb(VGAREG_ACTL_RESET);
137     outb(0x10, VGAREG_ACTL_ADDRESS);
138     u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0x7f) | ((regs->bl & 0x01) << 3);
139     outb(val, VGAREG_ACTL_WRITE_DATA);
140     outb(0x20, VGAREG_ACTL_ADDRESS);
141 }
142
143 void
144 biosfn_select_video_dac_color_page(struct bregs *regs)
145 {
146     inb(VGAREG_ACTL_RESET);
147     outb(0x10, VGAREG_ACTL_ADDRESS);
148     u8 val = inb(VGAREG_ACTL_READ_DATA);
149     if (!(regs->bl & 0x01)) {
150         val = (val & 0x7f) | (regs->bh << 7);
151         outb(val, VGAREG_ACTL_WRITE_DATA);
152         outb(0x20, VGAREG_ACTL_ADDRESS);
153         return;
154     }
155     inb(VGAREG_ACTL_RESET);
156     outb(0x14, VGAREG_ACTL_ADDRESS);
157     u8 bh = regs->bh;
158     if (!(val & 0x80))
159         bh <<= 2;
160     bh &= 0x0f;
161     outb(bh, VGAREG_ACTL_WRITE_DATA);
162     outb(0x20, VGAREG_ACTL_ADDRESS);
163 }
164
165 void
166 biosfn_read_video_dac_state(struct bregs *regs)
167 {
168     inb(VGAREG_ACTL_RESET);
169     outb(0x10, VGAREG_ACTL_ADDRESS);
170     u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7;
171
172     inb(VGAREG_ACTL_RESET);
173     outb(0x14, VGAREG_ACTL_ADDRESS);
174     u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f;
175     if (!(val1 & 0x01))
176         val2 >>= 2;
177
178     inb(VGAREG_ACTL_RESET);
179     outb(0x20, VGAREG_ACTL_ADDRESS);
180
181     regs->bl = val1;
182     regs->bh = val2;
183 }
184
185
186 /****************************************************************
187  * DAC control
188  ****************************************************************/
189
190 void
191 biosfn_set_single_dac_reg(struct bregs *regs)
192 {
193     outb(regs->bl, VGAREG_DAC_WRITE_ADDRESS);
194     outb(regs->dh, VGAREG_DAC_DATA);
195     outb(regs->ch, VGAREG_DAC_DATA);
196     outb(regs->cl, VGAREG_DAC_DATA);
197 }
198
199 void
200 biosfn_read_single_dac_reg(struct bregs *regs)
201 {
202     outb(regs->bl, VGAREG_DAC_READ_ADDRESS);
203     regs->dh = inb(VGAREG_DAC_DATA);
204     regs->ch = inb(VGAREG_DAC_DATA);
205     regs->cl = inb(VGAREG_DAC_DATA);
206 }
207
208 void
209 biosfn_set_all_dac_reg(struct bregs *regs)
210 {
211     outb(regs->bl, VGAREG_DAC_WRITE_ADDRESS);
212     u8 *data_far = (u8*)(regs->dx + 0);
213     int count = regs->cx;
214     while (count) {
215         outb(GET_FARVAR(regs->es, *data_far), VGAREG_DAC_DATA);
216         data_far++;
217         outb(GET_FARVAR(regs->es, *data_far), VGAREG_DAC_DATA);
218         data_far++;
219         outb(GET_FARVAR(regs->es, *data_far), VGAREG_DAC_DATA);
220         data_far++;
221         count--;
222     }
223 }
224
225 void
226 biosfn_read_all_dac_reg(struct bregs *regs)
227 {
228     outb(regs->bl, VGAREG_DAC_READ_ADDRESS);
229     u8 *data_far = (u8*)(regs->dx + 0);
230     int count = regs->cx;
231     while (count) {
232         SET_FARVAR(regs->es, *data_far, inb(VGAREG_DAC_DATA));
233         data_far++;
234         SET_FARVAR(regs->es, *data_far, inb(VGAREG_DAC_DATA));
235         data_far++;
236         SET_FARVAR(regs->es, *data_far, inb(VGAREG_DAC_DATA));
237         data_far++;
238         count--;
239     }
240 }
241
242 void
243 biosfn_set_pel_mask(struct bregs *regs)
244 {
245     outb(regs->bl, VGAREG_PEL_MASK);
246 }
247
248 void
249 biosfn_read_pel_mask(struct bregs *regs)
250 {
251     regs->bl = inb(VGAREG_PEL_MASK);
252 }
253
254
255 /****************************************************************
256  * Memory control
257  ****************************************************************/
258
259 void
260 biosfn_set_text_block_specifier(struct bregs *regs)
261 {
262     outw((regs->bl << 8) | 0x03, VGAREG_SEQU_ADDRESS);
263 }
264
265 void
266 get_font_access()
267 {
268     outw(0x0100, VGAREG_SEQU_ADDRESS);
269     outw(0x0402, VGAREG_SEQU_ADDRESS);
270     outw(0x0704, VGAREG_SEQU_ADDRESS);
271     outw(0x0300, VGAREG_SEQU_ADDRESS);
272     outw(0x0204, VGAREG_GRDC_ADDRESS);
273     outw(0x0005, VGAREG_GRDC_ADDRESS);
274     outw(0x0406, VGAREG_GRDC_ADDRESS);
275 }
276
277 void
278 release_font_access()
279 {
280     outw(0x0100, VGAREG_SEQU_ADDRESS);
281     outw(0x0302, VGAREG_SEQU_ADDRESS);
282     outw(0x0304, VGAREG_SEQU_ADDRESS);
283     outw(0x0300, VGAREG_SEQU_ADDRESS);
284     u16 v = (inw(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a;
285     outw((v << 8) | 0x06, VGAREG_GRDC_ADDRESS);
286     outw(0x0004, VGAREG_GRDC_ADDRESS);
287     outw(0x1005, VGAREG_GRDC_ADDRESS);
288 }
289
290
291 /****************************************************************
292  * Misc
293  ****************************************************************/
294
295 void
296 biosfn_enable_video_addressing(struct bregs *regs)
297 {
298     u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
299     u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02;
300     outb(v | v2, VGAREG_WRITE_MISC_OUTPUT);
301     regs->ax = 0x1212;
302 }
303
304 void
305 init_vga_card()
306 {
307     // switch to color mode and enable CPU access 480 lines
308     outb(0xc3, VGAREG_WRITE_MISC_OUTPUT);
309     // more than 64k 3C4/04
310     outb(0x04, VGAREG_SEQU_ADDRESS);
311     outb(0x02, VGAREG_SEQU_DATA);
312 }