|
|
1.1 ! root 1: // QEMU Cirrus CLGD 54xx VGABIOS Extension. ! 2: // ! 3: // Copyright (C) 2009 Kevin O'Connor <[email protected]> ! 4: // Copyright (c) 2004 Makoto Suzuki (suzu) ! 5: // ! 6: // This file may be distributed under the terms of the GNU LGPLv3 license. ! 7: ! 8: #include "vgatables.h" // cirrus_init ! 9: #include "biosvar.h" // GET_GLOBAL ! 10: #include "util.h" // dprintf ! 11: ! 12: struct cirrus_mode_s { ! 13: /* + 0 */ ! 14: u16 mode; ! 15: u16 width; ! 16: u16 height; ! 17: u16 depth; ! 18: /* + 8 */ ! 19: u16 hidden_dac; /* 0x3c6 */ ! 20: u16 *seq; /* 0x3c4 */ ! 21: u16 *graph; /* 0x3ce */ ! 22: u16 *crtc; /* 0x3d4 */ ! 23: /* +16 */ ! 24: u8 bitsperpixel; ! 25: u8 vesacolortype; ! 26: u8 vesaredmask; ! 27: u8 vesaredpos; ! 28: u8 vesagreenmask; ! 29: u8 vesagreenpos; ! 30: u8 vesabluemask; ! 31: u8 vesabluepos; ! 32: /* +24 */ ! 33: u8 vesareservedmask; ! 34: u8 vesareservedpos; ! 35: }; ! 36: ! 37: /* VGA */ ! 38: static u16 cseq_vga[] VAR16 = {0x0007,0xffff}; ! 39: static u16 cgraph_vga[] VAR16 = {0x0009,0x000a,0x000b,0xffff}; ! 40: static u16 ccrtc_vga[] VAR16 = {0x001a,0x001b,0x001d,0xffff}; ! 41: ! 42: /* extensions */ ! 43: static u16 cgraph_svgacolor[] VAR16 = { ! 44: 0x0000,0x0001,0x0002,0x0003,0x0004,0x4005,0x0506,0x0f07,0xff08, ! 45: 0x0009,0x000a,0x000b, ! 46: 0xffff ! 47: }; ! 48: /* 640x480x8 */ ! 49: static u16 cseq_640x480x8[] VAR16 = { ! 50: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, ! 51: 0x580b,0x580c,0x580d,0x580e, ! 52: 0x0412,0x0013,0x2017, ! 53: 0x331b,0x331c,0x331d,0x331e, ! 54: 0xffff ! 55: }; ! 56: static u16 ccrtc_640x480x8[] VAR16 = { ! 57: 0x2c11, ! 58: 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07, ! 59: 0x4009,0x000c,0x000d, ! 60: 0xea10,0xdf12,0x5013,0x4014,0xdf15,0x0b16,0xc317,0xff18, ! 61: 0x001a,0x221b,0x001d, ! 62: 0xffff ! 63: }; ! 64: /* 640x480x16 */ ! 65: static u16 cseq_640x480x16[] VAR16 = { ! 66: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707, ! 67: 0x580b,0x580c,0x580d,0x580e, ! 68: 0x0412,0x0013,0x2017, ! 69: 0x331b,0x331c,0x331d,0x331e, ! 70: 0xffff ! 71: }; ! 72: static u16 ccrtc_640x480x16[] VAR16 = { ! 73: 0x2c11, ! 74: 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07, ! 75: 0x4009,0x000c,0x000d, ! 76: 0xea10,0xdf12,0xa013,0x4014,0xdf15,0x0b16,0xc317,0xff18, ! 77: 0x001a,0x221b,0x001d, ! 78: 0xffff ! 79: }; ! 80: /* 640x480x24 */ ! 81: static u16 cseq_640x480x24[] VAR16 = { ! 82: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507, ! 83: 0x580b,0x580c,0x580d,0x580e, ! 84: 0x0412,0x0013,0x2017, ! 85: 0x331b,0x331c,0x331d,0x331e, ! 86: 0xffff ! 87: }; ! 88: static u16 ccrtc_640x480x24[] VAR16 = { ! 89: 0x2c11, ! 90: 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07, ! 91: 0x4009,0x000c,0x000d, ! 92: 0xea10,0xdf12,0x0013,0x4014,0xdf15,0x0b16,0xc317,0xff18, ! 93: 0x001a,0x321b,0x001d, ! 94: 0xffff ! 95: }; ! 96: /* 800x600x8 */ ! 97: static u16 cseq_800x600x8[] VAR16 = { ! 98: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, ! 99: 0x230b,0x230c,0x230d,0x230e, ! 100: 0x0412,0x0013,0x2017, ! 101: 0x141b,0x141c,0x141d,0x141e, ! 102: 0xffff ! 103: }; ! 104: static u16 ccrtc_800x600x8[] VAR16 = { ! 105: 0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007, ! 106: 0x6009,0x000c,0x000d, ! 107: 0x7d10,0x5712,0x6413,0x4014,0x5715,0x9816,0xc317,0xff18, ! 108: 0x001a,0x221b,0x001d, ! 109: 0xffff ! 110: }; ! 111: /* 800x600x16 */ ! 112: static u16 cseq_800x600x16[] VAR16 = { ! 113: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707, ! 114: 0x230b,0x230c,0x230d,0x230e, ! 115: 0x0412,0x0013,0x2017, ! 116: 0x141b,0x141c,0x141d,0x141e, ! 117: 0xffff ! 118: }; ! 119: static u16 ccrtc_800x600x16[] VAR16 = { ! 120: 0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007, ! 121: 0x6009,0x000c,0x000d, ! 122: 0x7d10,0x5712,0xc813,0x4014,0x5715,0x9816,0xc317,0xff18, ! 123: 0x001a,0x221b,0x001d, ! 124: 0xffff ! 125: }; ! 126: /* 800x600x24 */ ! 127: static u16 cseq_800x600x24[] VAR16 = { ! 128: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507, ! 129: 0x230b,0x230c,0x230d,0x230e, ! 130: 0x0412,0x0013,0x2017, ! 131: 0x141b,0x141c,0x141d,0x141e, ! 132: 0xffff ! 133: }; ! 134: static u16 ccrtc_800x600x24[] VAR16 = { ! 135: 0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007, ! 136: 0x6009,0x000c,0x000d, ! 137: 0x7d10,0x5712,0x2c13,0x4014,0x5715,0x9816,0xc317,0xff18, ! 138: 0x001a,0x321b,0x001d, ! 139: 0xffff ! 140: }; ! 141: /* 1024x768x8 */ ! 142: static u16 cseq_1024x768x8[] VAR16 = { ! 143: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, ! 144: 0x760b,0x760c,0x760d,0x760e, ! 145: 0x0412,0x0013,0x2017, ! 146: 0x341b,0x341c,0x341d,0x341e, ! 147: 0xffff ! 148: }; ! 149: static u16 ccrtc_1024x768x8[] VAR16 = { ! 150: 0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507, ! 151: 0x6009,0x000c,0x000d, ! 152: 0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18, ! 153: 0x001a,0x221b,0x001d, ! 154: 0xffff ! 155: }; ! 156: /* 1024x768x16 */ ! 157: static u16 cseq_1024x768x16[] VAR16 = { ! 158: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707, ! 159: 0x760b,0x760c,0x760d,0x760e, ! 160: 0x0412,0x0013,0x2017, ! 161: 0x341b,0x341c,0x341d,0x341e, ! 162: 0xffff ! 163: }; ! 164: static u16 ccrtc_1024x768x16[] VAR16 = { ! 165: 0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507, ! 166: 0x6009,0x000c,0x000d, ! 167: 0x0310,0xff12,0x0013,0x4014,0xff15,0x2416,0xc317,0xff18, ! 168: 0x001a,0x321b,0x001d, ! 169: 0xffff ! 170: }; ! 171: /* 1024x768x24 */ ! 172: static u16 cseq_1024x768x24[] VAR16 = { ! 173: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507, ! 174: 0x760b,0x760c,0x760d,0x760e, ! 175: 0x0412,0x0013,0x2017, ! 176: 0x341b,0x341c,0x341d,0x341e, ! 177: 0xffff ! 178: }; ! 179: static u16 ccrtc_1024x768x24[] VAR16 = { ! 180: 0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507, ! 181: 0x6009,0x000c,0x000d, ! 182: 0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18, ! 183: 0x001a,0x321b,0x001d, ! 184: 0xffff ! 185: }; ! 186: /* 1280x1024x8 */ ! 187: static u16 cseq_1280x1024x8[] VAR16 = { ! 188: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, ! 189: 0x760b,0x760c,0x760d,0x760e, ! 190: 0x0412,0x0013,0x2017, ! 191: 0x341b,0x341c,0x341d,0x341e, ! 192: 0xffff ! 193: }; ! 194: static u16 ccrtc_1280x1024x8[] VAR16 = { ! 195: 0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707, ! 196: 0x6009,0x000c,0x000d, ! 197: 0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18, ! 198: 0x001a,0x221b,0x001d, ! 199: 0xffff ! 200: }; ! 201: /* 1280x1024x16 */ ! 202: static u16 cseq_1280x1024x16[] VAR16 = { ! 203: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707, ! 204: 0x760b,0x760c,0x760d,0x760e, ! 205: 0x0412,0x0013,0x2017, ! 206: 0x341b,0x341c,0x341d,0x341e, ! 207: 0xffff ! 208: }; ! 209: static u16 ccrtc_1280x1024x16[] VAR16 = { ! 210: 0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707, ! 211: 0x6009,0x000c,0x000d, ! 212: 0x0310,0xff12,0x4013,0x4014,0xff15,0x2416,0xc317,0xff18, ! 213: 0x001a,0x321b,0x001d, ! 214: 0xffff ! 215: }; ! 216: ! 217: /* 1600x1200x8 */ ! 218: static u16 cseq_1600x1200x8[] VAR16 = { ! 219: 0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107, ! 220: 0x760b,0x760c,0x760d,0x760e, ! 221: 0x0412,0x0013,0x2017, ! 222: 0x341b,0x341c,0x341d,0x341e, ! 223: 0xffff ! 224: }; ! 225: static u16 ccrtc_1600x1200x8[] VAR16 = { ! 226: 0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707, ! 227: 0x6009,0x000c,0x000d, ! 228: 0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18, ! 229: 0x001a,0x221b,0x001d, ! 230: 0xffff ! 231: }; ! 232: ! 233: static struct cirrus_mode_s cirrus_modes[] VAR16 = { ! 234: {0x5f,640,480,8,0x00, ! 235: cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8,8, ! 236: 4,0,0,0,0,0,0,0,0}, ! 237: {0x64,640,480,16,0xe1, ! 238: cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16, ! 239: 6,5,11,6,5,5,0,0,0}, ! 240: {0x66,640,480,15,0xf0, ! 241: cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16, ! 242: 6,5,10,5,5,5,0,1,15}, ! 243: {0x71,640,480,24,0xe5, ! 244: cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24,24, ! 245: 6,8,16,8,8,8,0,0,0}, ! 246: ! 247: {0x5c,800,600,8,0x00, ! 248: cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8,8, ! 249: 4,0,0,0,0,0,0,0,0}, ! 250: {0x65,800,600,16,0xe1, ! 251: cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16, ! 252: 6,5,11,6,5,5,0,0,0}, ! 253: {0x67,800,600,15,0xf0, ! 254: cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16, ! 255: 6,5,10,5,5,5,0,1,15}, ! 256: ! 257: {0x60,1024,768,8,0x00, ! 258: cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8,8, ! 259: 4,0,0,0,0,0,0,0,0}, ! 260: {0x74,1024,768,16,0xe1, ! 261: cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16, ! 262: 6,5,11,6,5,5,0,0,0}, ! 263: {0x68,1024,768,15,0xf0, ! 264: cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16, ! 265: 6,5,10,5,5,5,0,1,15}, ! 266: ! 267: {0x78,800,600,24,0xe5, ! 268: cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24,24, ! 269: 6,8,16,8,8,8,0,0,0}, ! 270: {0x79,1024,768,24,0xe5, ! 271: cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24,24, ! 272: 6,8,16,8,8,8,0,0,0}, ! 273: ! 274: {0x6d,1280,1024,8,0x00, ! 275: cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8,8, ! 276: 4,0,0,0,0,0,0,0,0}, ! 277: {0x69,1280,1024,15,0xf0, ! 278: cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16, ! 279: 6,5,10,5,5,5,0,1,15}, ! 280: {0x75,1280,1024,16,0xe1, ! 281: cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16, ! 282: 6,5,11,6,5,5,0,0,0}, ! 283: ! 284: {0x7b,1600,1200,8,0x00, ! 285: cseq_1600x1200x8,cgraph_svgacolor,ccrtc_1600x1200x8,8, ! 286: 4,0,0,0,0,0,0,0,0}, ! 287: ! 288: {0xfe,0,0,0,0,cseq_vga,cgraph_vga,ccrtc_vga,0, ! 289: 0xff,0,0,0,0,0,0,0,0}, ! 290: }; ! 291: ! 292: static struct cirrus_mode_s * ! 293: cirrus_get_modeentry(u8 mode) ! 294: { ! 295: struct cirrus_mode_s *table_g = cirrus_modes; ! 296: while (table_g < &cirrus_modes[ARRAY_SIZE(cirrus_modes)]) { ! 297: u16 tmode = GET_GLOBAL(table_g->mode); ! 298: if (tmode == mode) ! 299: return table_g; ! 300: table_g++; ! 301: } ! 302: return NULL; ! 303: } ! 304: ! 305: static void ! 306: cirrus_switch_mode_setregs(u16 *data, u16 port) ! 307: { ! 308: for (;;) { ! 309: u16 val = GET_GLOBAL(*data); ! 310: if (val == 0xffff) ! 311: return; ! 312: outw(val, port); ! 313: data++; ! 314: } ! 315: } ! 316: ! 317: static u16 ! 318: cirrus_get_crtc() ! 319: { ! 320: if (inb(VGAREG_READ_MISC_OUTPUT) & 1) ! 321: return VGAREG_VGA_CRTC_ADDRESS; ! 322: return VGAREG_MDA_CRTC_ADDRESS; ! 323: } ! 324: ! 325: static void ! 326: cirrus_switch_mode(struct cirrus_mode_s *table) ! 327: { ! 328: // Unlock cirrus special ! 329: outw(0x1206, VGAREG_SEQU_ADDRESS); ! 330: cirrus_switch_mode_setregs(GET_GLOBAL(table->seq), VGAREG_SEQU_ADDRESS); ! 331: cirrus_switch_mode_setregs(GET_GLOBAL(table->graph), VGAREG_GRDC_ADDRESS); ! 332: cirrus_switch_mode_setregs(GET_GLOBAL(table->crtc), cirrus_get_crtc()); ! 333: ! 334: outb(0x00, VGAREG_PEL_MASK); ! 335: inb(VGAREG_PEL_MASK); ! 336: inb(VGAREG_PEL_MASK); ! 337: inb(VGAREG_PEL_MASK); ! 338: inb(VGAREG_PEL_MASK); ! 339: outb(GET_GLOBAL(table->hidden_dac), VGAREG_PEL_MASK); ! 340: outb(0xff, VGAREG_PEL_MASK); ! 341: ! 342: u8 vesacolortype = GET_GLOBAL(table->vesacolortype); ! 343: u8 v = vgahw_get_single_palette_reg(0x10) & 0xfe; ! 344: if (vesacolortype == 3) ! 345: v |= 0x41; ! 346: else if (vesacolortype) ! 347: v |= 0x01; ! 348: vgahw_set_single_palette_reg(0x10, v); ! 349: } ! 350: ! 351: void ! 352: cirrus_set_video_mode(u8 mode) ! 353: { ! 354: dprintf(1, "cirrus mode %d\n", mode); ! 355: SET_BDA(vbe_mode, 0); ! 356: struct cirrus_mode_s *table_g = cirrus_get_modeentry(mode & 0x7f); ! 357: if (table_g) { ! 358: //XXX - cirrus_set_video_mode_extended(table); ! 359: return; ! 360: } ! 361: table_g = cirrus_get_modeentry(0xfe); ! 362: cirrus_switch_mode(table_g); ! 363: dprintf(1, "cirrus mode switch regular\n"); ! 364: } ! 365: ! 366: static int ! 367: cirrus_check() ! 368: { ! 369: outw(0x9206, VGAREG_SEQU_ADDRESS); ! 370: return inb(VGAREG_SEQU_DATA) == 0x12; ! 371: } ! 372: ! 373: void ! 374: cirrus_init() ! 375: { ! 376: dprintf(1, "cirrus init\n"); ! 377: if (! cirrus_check()) ! 378: return; ! 379: dprintf(1, "cirrus init 2\n"); ! 380: ! 381: // memory setup ! 382: outb(0x0f, VGAREG_SEQU_ADDRESS); ! 383: u8 v = inb(VGAREG_SEQU_DATA); ! 384: outb(((v & 0x18) << 8) | 0x0a, VGAREG_SEQU_ADDRESS); ! 385: // set vga mode ! 386: outw(0x0007, VGAREG_SEQU_ADDRESS); ! 387: // reset bitblt ! 388: outw(0x0431, VGAREG_GRDC_ADDRESS); ! 389: outw(0x0031, VGAREG_GRDC_ADDRESS); ! 390: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.