vga.c 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683
  1. /*
  2. * QEMU VGA Emulator.
  3. *
  4. * Copyright (c) 2003 Fabrice Bellard
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "hw.h"
  25. #include "console.h"
  26. #include "pc.h"
  27. #include "pci.h"
  28. #include "vga_int.h"
  29. #include "pixel_ops.h"
  30. #include "qemu-timer.h"
  31. #include "kvm.h"
  32. //#define DEBUG_VGA
  33. //#define DEBUG_VGA_MEM
  34. //#define DEBUG_VGA_REG
  35. //#define DEBUG_BOCHS_VBE
  36. /* force some bits to zero */
  37. const uint8_t sr_mask[8] = {
  38. (uint8_t)~0xfc,
  39. (uint8_t)~0xc2,
  40. (uint8_t)~0xf0,
  41. (uint8_t)~0xc0,
  42. (uint8_t)~0xf1,
  43. (uint8_t)~0xff,
  44. (uint8_t)~0xff,
  45. (uint8_t)~0x00,
  46. };
  47. const uint8_t gr_mask[16] = {
  48. (uint8_t)~0xf0, /* 0x00 */
  49. (uint8_t)~0xf0, /* 0x01 */
  50. (uint8_t)~0xf0, /* 0x02 */
  51. (uint8_t)~0xe0, /* 0x03 */
  52. (uint8_t)~0xfc, /* 0x04 */
  53. (uint8_t)~0x84, /* 0x05 */
  54. (uint8_t)~0xf0, /* 0x06 */
  55. (uint8_t)~0xf0, /* 0x07 */
  56. (uint8_t)~0x00, /* 0x08 */
  57. (uint8_t)~0xff, /* 0x09 */
  58. (uint8_t)~0xff, /* 0x0a */
  59. (uint8_t)~0xff, /* 0x0b */
  60. (uint8_t)~0xff, /* 0x0c */
  61. (uint8_t)~0xff, /* 0x0d */
  62. (uint8_t)~0xff, /* 0x0e */
  63. (uint8_t)~0xff, /* 0x0f */
  64. };
  65. #define cbswap_32(__x) \
  66. ((uint32_t)( \
  67. (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
  68. (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
  69. (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
  70. (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
  71. #ifdef WORDS_BIGENDIAN
  72. #define PAT(x) cbswap_32(x)
  73. #else
  74. #define PAT(x) (x)
  75. #endif
  76. #ifdef WORDS_BIGENDIAN
  77. #define BIG 1
  78. #else
  79. #define BIG 0
  80. #endif
  81. #ifdef WORDS_BIGENDIAN
  82. #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
  83. #else
  84. #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
  85. #endif
  86. static const uint32_t mask16[16] = {
  87. PAT(0x00000000),
  88. PAT(0x000000ff),
  89. PAT(0x0000ff00),
  90. PAT(0x0000ffff),
  91. PAT(0x00ff0000),
  92. PAT(0x00ff00ff),
  93. PAT(0x00ffff00),
  94. PAT(0x00ffffff),
  95. PAT(0xff000000),
  96. PAT(0xff0000ff),
  97. PAT(0xff00ff00),
  98. PAT(0xff00ffff),
  99. PAT(0xffff0000),
  100. PAT(0xffff00ff),
  101. PAT(0xffffff00),
  102. PAT(0xffffffff),
  103. };
  104. #undef PAT
  105. #ifdef WORDS_BIGENDIAN
  106. #define PAT(x) (x)
  107. #else
  108. #define PAT(x) cbswap_32(x)
  109. #endif
  110. static const uint32_t dmask16[16] = {
  111. PAT(0x00000000),
  112. PAT(0x000000ff),
  113. PAT(0x0000ff00),
  114. PAT(0x0000ffff),
  115. PAT(0x00ff0000),
  116. PAT(0x00ff00ff),
  117. PAT(0x00ffff00),
  118. PAT(0x00ffffff),
  119. PAT(0xff000000),
  120. PAT(0xff0000ff),
  121. PAT(0xff00ff00),
  122. PAT(0xff00ffff),
  123. PAT(0xffff0000),
  124. PAT(0xffff00ff),
  125. PAT(0xffffff00),
  126. PAT(0xffffffff),
  127. };
  128. static const uint32_t dmask4[4] = {
  129. PAT(0x00000000),
  130. PAT(0x0000ffff),
  131. PAT(0xffff0000),
  132. PAT(0xffffffff),
  133. };
  134. static uint32_t expand4[256];
  135. static uint16_t expand2[256];
  136. static uint8_t expand4to8[16];
  137. static void vga_screen_dump(void *opaque, const char *filename);
  138. static void vga_dumb_update_retrace_info(VGAState *s)
  139. {
  140. (void) s;
  141. }
  142. static void vga_precise_update_retrace_info(VGAState *s)
  143. {
  144. int htotal_chars;
  145. int hretr_start_char;
  146. int hretr_skew_chars;
  147. int hretr_end_char;
  148. int vtotal_lines;
  149. int vretr_start_line;
  150. int vretr_end_line;
  151. int div2, sldiv2, dots;
  152. int clocking_mode;
  153. int clock_sel;
  154. const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
  155. int64_t chars_per_sec;
  156. struct vga_precise_retrace *r = &s->retrace_info.precise;
  157. htotal_chars = s->cr[0x00] + 5;
  158. hretr_start_char = s->cr[0x04];
  159. hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
  160. hretr_end_char = s->cr[0x05] & 0x1f;
  161. vtotal_lines = (s->cr[0x06]
  162. | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
  163. ;
  164. vretr_start_line = s->cr[0x10]
  165. | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
  166. ;
  167. vretr_end_line = s->cr[0x11] & 0xf;
  168. div2 = (s->cr[0x17] >> 2) & 1;
  169. sldiv2 = (s->cr[0x17] >> 3) & 1;
  170. clocking_mode = (s->sr[0x01] >> 3) & 1;
  171. clock_sel = (s->msr >> 2) & 3;
  172. dots = (s->msr & 1) ? 8 : 9;
  173. chars_per_sec = clk_hz[clock_sel] / dots;
  174. htotal_chars <<= clocking_mode;
  175. r->total_chars = vtotal_lines * htotal_chars;
  176. if (r->freq) {
  177. r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
  178. } else {
  179. r->ticks_per_char = ticks_per_sec / chars_per_sec;
  180. }
  181. r->vstart = vretr_start_line;
  182. r->vend = r->vstart + vretr_end_line + 1;
  183. r->hstart = hretr_start_char + hretr_skew_chars;
  184. r->hend = r->hstart + hretr_end_char + 1;
  185. r->htotal = htotal_chars;
  186. #if 0
  187. printf (
  188. "hz=%f\n"
  189. "htotal = %d\n"
  190. "hretr_start = %d\n"
  191. "hretr_skew = %d\n"
  192. "hretr_end = %d\n"
  193. "vtotal = %d\n"
  194. "vretr_start = %d\n"
  195. "vretr_end = %d\n"
  196. "div2 = %d sldiv2 = %d\n"
  197. "clocking_mode = %d\n"
  198. "clock_sel = %d %d\n"
  199. "dots = %d\n"
  200. "ticks/char = %lld\n"
  201. "\n",
  202. (double) ticks_per_sec / (r->ticks_per_char * r->total_chars),
  203. htotal_chars,
  204. hretr_start_char,
  205. hretr_skew_chars,
  206. hretr_end_char,
  207. vtotal_lines,
  208. vretr_start_line,
  209. vretr_end_line,
  210. div2, sldiv2,
  211. clocking_mode,
  212. clock_sel,
  213. clk_hz[clock_sel],
  214. dots,
  215. r->ticks_per_char
  216. );
  217. #endif
  218. }
  219. static uint8_t vga_precise_retrace(VGAState *s)
  220. {
  221. struct vga_precise_retrace *r = &s->retrace_info.precise;
  222. uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
  223. if (r->total_chars) {
  224. int cur_line, cur_line_char, cur_char;
  225. int64_t cur_tick;
  226. cur_tick = qemu_get_clock(vm_clock);
  227. cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
  228. cur_line = cur_char / r->htotal;
  229. if (cur_line >= r->vstart && cur_line <= r->vend) {
  230. val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
  231. } else {
  232. cur_line_char = cur_char % r->htotal;
  233. if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
  234. val |= ST01_DISP_ENABLE;
  235. }
  236. }
  237. return val;
  238. } else {
  239. return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
  240. }
  241. }
  242. static uint8_t vga_dumb_retrace(VGAState *s)
  243. {
  244. return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
  245. }
  246. static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
  247. {
  248. VGAState *s = opaque;
  249. int val, index;
  250. /* check port range access depending on color/monochrome mode */
  251. if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
  252. (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
  253. val = 0xff;
  254. } else {
  255. switch(addr) {
  256. case 0x3c0:
  257. if (s->ar_flip_flop == 0) {
  258. val = s->ar_index;
  259. } else {
  260. val = 0;
  261. }
  262. break;
  263. case 0x3c1:
  264. index = s->ar_index & 0x1f;
  265. if (index < 21)
  266. val = s->ar[index];
  267. else
  268. val = 0;
  269. break;
  270. case 0x3c2:
  271. val = s->st00;
  272. break;
  273. case 0x3c4:
  274. val = s->sr_index;
  275. break;
  276. case 0x3c5:
  277. val = s->sr[s->sr_index];
  278. #ifdef DEBUG_VGA_REG
  279. printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
  280. #endif
  281. break;
  282. case 0x3c7:
  283. val = s->dac_state;
  284. break;
  285. case 0x3c8:
  286. val = s->dac_write_index;
  287. break;
  288. case 0x3c9:
  289. val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
  290. if (++s->dac_sub_index == 3) {
  291. s->dac_sub_index = 0;
  292. s->dac_read_index++;
  293. }
  294. break;
  295. case 0x3ca:
  296. val = s->fcr;
  297. break;
  298. case 0x3cc:
  299. val = s->msr;
  300. break;
  301. case 0x3ce:
  302. val = s->gr_index;
  303. break;
  304. case 0x3cf:
  305. val = s->gr[s->gr_index];
  306. #ifdef DEBUG_VGA_REG
  307. printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
  308. #endif
  309. break;
  310. case 0x3b4:
  311. case 0x3d4:
  312. val = s->cr_index;
  313. break;
  314. case 0x3b5:
  315. case 0x3d5:
  316. val = s->cr[s->cr_index];
  317. #ifdef DEBUG_VGA_REG
  318. printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
  319. #endif
  320. break;
  321. case 0x3ba:
  322. case 0x3da:
  323. /* just toggle to fool polling */
  324. val = s->st01 = s->retrace(s);
  325. s->ar_flip_flop = 0;
  326. break;
  327. default:
  328. val = 0x00;
  329. break;
  330. }
  331. }
  332. #if defined(DEBUG_VGA)
  333. printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
  334. #endif
  335. return val;
  336. }
  337. static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
  338. {
  339. VGAState *s = opaque;
  340. int index;
  341. /* check port range access depending on color/monochrome mode */
  342. if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
  343. (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
  344. return;
  345. #ifdef DEBUG_VGA
  346. printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
  347. #endif
  348. switch(addr) {
  349. case 0x3c0:
  350. if (s->ar_flip_flop == 0) {
  351. val &= 0x3f;
  352. s->ar_index = val;
  353. } else {
  354. index = s->ar_index & 0x1f;
  355. switch(index) {
  356. case 0x00 ... 0x0f:
  357. s->ar[index] = val & 0x3f;
  358. break;
  359. case 0x10:
  360. s->ar[index] = val & ~0x10;
  361. break;
  362. case 0x11:
  363. s->ar[index] = val;
  364. break;
  365. case 0x12:
  366. s->ar[index] = val & ~0xc0;
  367. break;
  368. case 0x13:
  369. s->ar[index] = val & ~0xf0;
  370. break;
  371. case 0x14:
  372. s->ar[index] = val & ~0xf0;
  373. break;
  374. default:
  375. break;
  376. }
  377. }
  378. s->ar_flip_flop ^= 1;
  379. break;
  380. case 0x3c2:
  381. s->msr = val & ~0x10;
  382. s->update_retrace_info(s);
  383. break;
  384. case 0x3c4:
  385. s->sr_index = val & 7;
  386. break;
  387. case 0x3c5:
  388. #ifdef DEBUG_VGA_REG
  389. printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
  390. #endif
  391. s->sr[s->sr_index] = val & sr_mask[s->sr_index];
  392. if (s->sr_index == 1) s->update_retrace_info(s);
  393. break;
  394. case 0x3c7:
  395. s->dac_read_index = val;
  396. s->dac_sub_index = 0;
  397. s->dac_state = 3;
  398. break;
  399. case 0x3c8:
  400. s->dac_write_index = val;
  401. s->dac_sub_index = 0;
  402. s->dac_state = 0;
  403. break;
  404. case 0x3c9:
  405. s->dac_cache[s->dac_sub_index] = val;
  406. if (++s->dac_sub_index == 3) {
  407. memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
  408. s->dac_sub_index = 0;
  409. s->dac_write_index++;
  410. }
  411. break;
  412. case 0x3ce:
  413. s->gr_index = val & 0x0f;
  414. break;
  415. case 0x3cf:
  416. #ifdef DEBUG_VGA_REG
  417. printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
  418. #endif
  419. s->gr[s->gr_index] = val & gr_mask[s->gr_index];
  420. break;
  421. case 0x3b4:
  422. case 0x3d4:
  423. s->cr_index = val;
  424. break;
  425. case 0x3b5:
  426. case 0x3d5:
  427. #ifdef DEBUG_VGA_REG
  428. printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
  429. #endif
  430. /* handle CR0-7 protection */
  431. if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
  432. /* can always write bit 4 of CR7 */
  433. if (s->cr_index == 7)
  434. s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
  435. return;
  436. }
  437. switch(s->cr_index) {
  438. case 0x01: /* horizontal display end */
  439. case 0x07:
  440. case 0x09:
  441. case 0x0c:
  442. case 0x0d:
  443. case 0x12: /* vertical display end */
  444. s->cr[s->cr_index] = val;
  445. break;
  446. default:
  447. s->cr[s->cr_index] = val;
  448. break;
  449. }
  450. switch(s->cr_index) {
  451. case 0x00:
  452. case 0x04:
  453. case 0x05:
  454. case 0x06:
  455. case 0x07:
  456. case 0x11:
  457. case 0x17:
  458. s->update_retrace_info(s);
  459. break;
  460. }
  461. break;
  462. case 0x3ba:
  463. case 0x3da:
  464. s->fcr = val & 0x10;
  465. break;
  466. }
  467. }
  468. #ifdef CONFIG_BOCHS_VBE
  469. static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
  470. {
  471. VGAState *s = opaque;
  472. uint32_t val;
  473. val = s->vbe_index;
  474. return val;
  475. }
  476. static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
  477. {
  478. VGAState *s = opaque;
  479. uint32_t val;
  480. if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
  481. if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
  482. switch(s->vbe_index) {
  483. /* XXX: do not hardcode ? */
  484. case VBE_DISPI_INDEX_XRES:
  485. val = VBE_DISPI_MAX_XRES;
  486. break;
  487. case VBE_DISPI_INDEX_YRES:
  488. val = VBE_DISPI_MAX_YRES;
  489. break;
  490. case VBE_DISPI_INDEX_BPP:
  491. val = VBE_DISPI_MAX_BPP;
  492. break;
  493. default:
  494. val = s->vbe_regs[s->vbe_index];
  495. break;
  496. }
  497. } else {
  498. val = s->vbe_regs[s->vbe_index];
  499. }
  500. } else {
  501. val = 0;
  502. }
  503. #ifdef DEBUG_BOCHS_VBE
  504. printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
  505. #endif
  506. return val;
  507. }
  508. static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
  509. {
  510. VGAState *s = opaque;
  511. s->vbe_index = val;
  512. }
  513. static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
  514. {
  515. VGAState *s = opaque;
  516. if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
  517. #ifdef DEBUG_BOCHS_VBE
  518. printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
  519. #endif
  520. switch(s->vbe_index) {
  521. case VBE_DISPI_INDEX_ID:
  522. if (val == VBE_DISPI_ID0 ||
  523. val == VBE_DISPI_ID1 ||
  524. val == VBE_DISPI_ID2 ||
  525. val == VBE_DISPI_ID3 ||
  526. val == VBE_DISPI_ID4) {
  527. s->vbe_regs[s->vbe_index] = val;
  528. }
  529. break;
  530. case VBE_DISPI_INDEX_XRES:
  531. if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
  532. s->vbe_regs[s->vbe_index] = val;
  533. }
  534. break;
  535. case VBE_DISPI_INDEX_YRES:
  536. if (val <= VBE_DISPI_MAX_YRES) {
  537. s->vbe_regs[s->vbe_index] = val;
  538. }
  539. break;
  540. case VBE_DISPI_INDEX_BPP:
  541. if (val == 0)
  542. val = 8;
  543. if (val == 4 || val == 8 || val == 15 ||
  544. val == 16 || val == 24 || val == 32) {
  545. s->vbe_regs[s->vbe_index] = val;
  546. }
  547. break;
  548. case VBE_DISPI_INDEX_BANK:
  549. if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
  550. val &= (s->vbe_bank_mask >> 2);
  551. } else {
  552. val &= s->vbe_bank_mask;
  553. }
  554. s->vbe_regs[s->vbe_index] = val;
  555. s->bank_offset = (val << 16);
  556. break;
  557. case VBE_DISPI_INDEX_ENABLE:
  558. if ((val & VBE_DISPI_ENABLED) &&
  559. !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
  560. int h, shift_control;
  561. s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
  562. s->vbe_regs[VBE_DISPI_INDEX_XRES];
  563. s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
  564. s->vbe_regs[VBE_DISPI_INDEX_YRES];
  565. s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
  566. s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
  567. if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
  568. s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
  569. else
  570. s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
  571. ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
  572. s->vbe_start_addr = 0;
  573. /* clear the screen (should be done in BIOS) */
  574. if (!(val & VBE_DISPI_NOCLEARMEM)) {
  575. memset(s->vram_ptr, 0,
  576. s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
  577. }
  578. /* we initialize the VGA graphic mode (should be done
  579. in BIOS) */
  580. s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
  581. s->cr[0x17] |= 3; /* no CGA modes */
  582. s->cr[0x13] = s->vbe_line_offset >> 3;
  583. /* width */
  584. s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
  585. /* height (only meaningful if < 1024) */
  586. h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
  587. s->cr[0x12] = h;
  588. s->cr[0x07] = (s->cr[0x07] & ~0x42) |
  589. ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
  590. /* line compare to 1023 */
  591. s->cr[0x18] = 0xff;
  592. s->cr[0x07] |= 0x10;
  593. s->cr[0x09] |= 0x40;
  594. if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
  595. shift_control = 0;
  596. s->sr[0x01] &= ~8; /* no double line */
  597. } else {
  598. shift_control = 2;
  599. s->sr[4] |= 0x08; /* set chain 4 mode */
  600. s->sr[2] |= 0x0f; /* activate all planes */
  601. }
  602. s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
  603. s->cr[0x09] &= ~0x9f; /* no double scan */
  604. } else {
  605. /* XXX: the bios should do that */
  606. s->bank_offset = 0;
  607. }
  608. s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
  609. s->vbe_regs[s->vbe_index] = val;
  610. break;
  611. case VBE_DISPI_INDEX_VIRT_WIDTH:
  612. {
  613. int w, h, line_offset;
  614. if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
  615. return;
  616. w = val;
  617. if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
  618. line_offset = w >> 1;
  619. else
  620. line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
  621. h = s->vram_size / line_offset;
  622. /* XXX: support weird bochs semantics ? */
  623. if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
  624. return;
  625. s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
  626. s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
  627. s->vbe_line_offset = line_offset;
  628. }
  629. break;
  630. case VBE_DISPI_INDEX_X_OFFSET:
  631. case VBE_DISPI_INDEX_Y_OFFSET:
  632. {
  633. int x;
  634. s->vbe_regs[s->vbe_index] = val;
  635. s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
  636. x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
  637. if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
  638. s->vbe_start_addr += x >> 1;
  639. else
  640. s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
  641. s->vbe_start_addr >>= 2;
  642. }
  643. break;
  644. default:
  645. break;
  646. }
  647. }
  648. }
  649. #endif
  650. /* called for accesses between 0xa0000 and 0xc0000 */
  651. uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
  652. {
  653. VGAState *s = opaque;
  654. int memory_map_mode, plane;
  655. uint32_t ret;
  656. /* convert to VGA memory offset */
  657. memory_map_mode = (s->gr[6] >> 2) & 3;
  658. addr &= 0x1ffff;
  659. switch(memory_map_mode) {
  660. case 0:
  661. break;
  662. case 1:
  663. if (addr >= 0x10000)
  664. return 0xff;
  665. addr += s->bank_offset;
  666. break;
  667. case 2:
  668. addr -= 0x10000;
  669. if (addr >= 0x8000)
  670. return 0xff;
  671. break;
  672. default:
  673. case 3:
  674. addr -= 0x18000;
  675. if (addr >= 0x8000)
  676. return 0xff;
  677. break;
  678. }
  679. if (s->sr[4] & 0x08) {
  680. /* chain 4 mode : simplest access */
  681. ret = s->vram_ptr[addr];
  682. } else if (s->gr[5] & 0x10) {
  683. /* odd/even mode (aka text mode mapping) */
  684. plane = (s->gr[4] & 2) | (addr & 1);
  685. ret = s->vram_ptr[((addr & ~1) << 1) | plane];
  686. } else {
  687. /* standard VGA latched access */
  688. s->latch = ((uint32_t *)s->vram_ptr)[addr];
  689. if (!(s->gr[5] & 0x08)) {
  690. /* read mode 0 */
  691. plane = s->gr[4];
  692. ret = GET_PLANE(s->latch, plane);
  693. } else {
  694. /* read mode 1 */
  695. ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
  696. ret |= ret >> 16;
  697. ret |= ret >> 8;
  698. ret = (~ret) & 0xff;
  699. }
  700. }
  701. return ret;
  702. }
  703. static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
  704. {
  705. uint32_t v;
  706. #ifdef TARGET_WORDS_BIGENDIAN
  707. v = vga_mem_readb(opaque, addr) << 8;
  708. v |= vga_mem_readb(opaque, addr + 1);
  709. #else
  710. v = vga_mem_readb(opaque, addr);
  711. v |= vga_mem_readb(opaque, addr + 1) << 8;
  712. #endif
  713. return v;
  714. }
  715. static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
  716. {
  717. uint32_t v;
  718. #ifdef TARGET_WORDS_BIGENDIAN
  719. v = vga_mem_readb(opaque, addr) << 24;
  720. v |= vga_mem_readb(opaque, addr + 1) << 16;
  721. v |= vga_mem_readb(opaque, addr + 2) << 8;
  722. v |= vga_mem_readb(opaque, addr + 3);
  723. #else
  724. v = vga_mem_readb(opaque, addr);
  725. v |= vga_mem_readb(opaque, addr + 1) << 8;
  726. v |= vga_mem_readb(opaque, addr + 2) << 16;
  727. v |= vga_mem_readb(opaque, addr + 3) << 24;
  728. #endif
  729. return v;
  730. }
  731. /* called for accesses between 0xa0000 and 0xc0000 */
  732. void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  733. {
  734. VGAState *s = opaque;
  735. int memory_map_mode, plane, write_mode, b, func_select, mask;
  736. uint32_t write_mask, bit_mask, set_mask;
  737. #ifdef DEBUG_VGA_MEM
  738. printf("vga: [0x%x] = 0x%02x\n", addr, val);
  739. #endif
  740. /* convert to VGA memory offset */
  741. memory_map_mode = (s->gr[6] >> 2) & 3;
  742. addr &= 0x1ffff;
  743. switch(memory_map_mode) {
  744. case 0:
  745. break;
  746. case 1:
  747. if (addr >= 0x10000)
  748. return;
  749. addr += s->bank_offset;
  750. break;
  751. case 2:
  752. addr -= 0x10000;
  753. if (addr >= 0x8000)
  754. return;
  755. break;
  756. default:
  757. case 3:
  758. addr -= 0x18000;
  759. if (addr >= 0x8000)
  760. return;
  761. break;
  762. }
  763. if (s->sr[4] & 0x08) {
  764. /* chain 4 mode : simplest access */
  765. plane = addr & 3;
  766. mask = (1 << plane);
  767. if (s->sr[2] & mask) {
  768. s->vram_ptr[addr] = val;
  769. #ifdef DEBUG_VGA_MEM
  770. printf("vga: chain4: [0x%x]\n", addr);
  771. #endif
  772. s->plane_updated |= mask; /* only used to detect font change */
  773. cpu_physical_memory_set_dirty(s->vram_offset + addr);
  774. }
  775. } else if (s->gr[5] & 0x10) {
  776. /* odd/even mode (aka text mode mapping) */
  777. plane = (s->gr[4] & 2) | (addr & 1);
  778. mask = (1 << plane);
  779. if (s->sr[2] & mask) {
  780. addr = ((addr & ~1) << 1) | plane;
  781. s->vram_ptr[addr] = val;
  782. #ifdef DEBUG_VGA_MEM
  783. printf("vga: odd/even: [0x%x]\n", addr);
  784. #endif
  785. s->plane_updated |= mask; /* only used to detect font change */
  786. cpu_physical_memory_set_dirty(s->vram_offset + addr);
  787. }
  788. } else {
  789. /* standard VGA latched access */
  790. write_mode = s->gr[5] & 3;
  791. switch(write_mode) {
  792. default:
  793. case 0:
  794. /* rotate */
  795. b = s->gr[3] & 7;
  796. val = ((val >> b) | (val << (8 - b))) & 0xff;
  797. val |= val << 8;
  798. val |= val << 16;
  799. /* apply set/reset mask */
  800. set_mask = mask16[s->gr[1]];
  801. val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
  802. bit_mask = s->gr[8];
  803. break;
  804. case 1:
  805. val = s->latch;
  806. goto do_write;
  807. case 2:
  808. val = mask16[val & 0x0f];
  809. bit_mask = s->gr[8];
  810. break;
  811. case 3:
  812. /* rotate */
  813. b = s->gr[3] & 7;
  814. val = (val >> b) | (val << (8 - b));
  815. bit_mask = s->gr[8] & val;
  816. val = mask16[s->gr[0]];
  817. break;
  818. }
  819. /* apply logical operation */
  820. func_select = s->gr[3] >> 3;
  821. switch(func_select) {
  822. case 0:
  823. default:
  824. /* nothing to do */
  825. break;
  826. case 1:
  827. /* and */
  828. val &= s->latch;
  829. break;
  830. case 2:
  831. /* or */
  832. val |= s->latch;
  833. break;
  834. case 3:
  835. /* xor */
  836. val ^= s->latch;
  837. break;
  838. }
  839. /* apply bit mask */
  840. bit_mask |= bit_mask << 8;
  841. bit_mask |= bit_mask << 16;
  842. val = (val & bit_mask) | (s->latch & ~bit_mask);
  843. do_write:
  844. /* mask data according to sr[2] */
  845. mask = s->sr[2];
  846. s->plane_updated |= mask; /* only used to detect font change */
  847. write_mask = mask16[mask];
  848. ((uint32_t *)s->vram_ptr)[addr] =
  849. (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
  850. (val & write_mask);
  851. #ifdef DEBUG_VGA_MEM
  852. printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
  853. addr * 4, write_mask, val);
  854. #endif
  855. cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
  856. }
  857. }
  858. static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  859. {
  860. #ifdef TARGET_WORDS_BIGENDIAN
  861. vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
  862. vga_mem_writeb(opaque, addr + 1, val & 0xff);
  863. #else
  864. vga_mem_writeb(opaque, addr, val & 0xff);
  865. vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  866. #endif
  867. }
  868. static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  869. {
  870. #ifdef TARGET_WORDS_BIGENDIAN
  871. vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
  872. vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
  873. vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
  874. vga_mem_writeb(opaque, addr + 3, val & 0xff);
  875. #else
  876. vga_mem_writeb(opaque, addr, val & 0xff);
  877. vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
  878. vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
  879. vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
  880. #endif
  881. }
  882. typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
  883. const uint8_t *font_ptr, int h,
  884. uint32_t fgcol, uint32_t bgcol);
  885. typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
  886. const uint8_t *font_ptr, int h,
  887. uint32_t fgcol, uint32_t bgcol, int dup9);
  888. typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
  889. const uint8_t *s, int width);
  890. #define DEPTH 8
  891. #include "vga_template.h"
  892. #define DEPTH 15
  893. #include "vga_template.h"
  894. #define BGR_FORMAT
  895. #define DEPTH 15
  896. #include "vga_template.h"
  897. #define DEPTH 16
  898. #include "vga_template.h"
  899. #define BGR_FORMAT
  900. #define DEPTH 16
  901. #include "vga_template.h"
  902. #define DEPTH 32
  903. #include "vga_template.h"
  904. #define BGR_FORMAT
  905. #define DEPTH 32
  906. #include "vga_template.h"
  907. static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
  908. {
  909. unsigned int col;
  910. col = rgb_to_pixel8(r, g, b);
  911. col |= col << 8;
  912. col |= col << 16;
  913. return col;
  914. }
  915. static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
  916. {
  917. unsigned int col;
  918. col = rgb_to_pixel15(r, g, b);
  919. col |= col << 16;
  920. return col;
  921. }
  922. static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
  923. unsigned int b)
  924. {
  925. unsigned int col;
  926. col = rgb_to_pixel15bgr(r, g, b);
  927. col |= col << 16;
  928. return col;
  929. }
  930. static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
  931. {
  932. unsigned int col;
  933. col = rgb_to_pixel16(r, g, b);
  934. col |= col << 16;
  935. return col;
  936. }
  937. static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
  938. unsigned int b)
  939. {
  940. unsigned int col;
  941. col = rgb_to_pixel16bgr(r, g, b);
  942. col |= col << 16;
  943. return col;
  944. }
  945. static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
  946. {
  947. unsigned int col;
  948. col = rgb_to_pixel32(r, g, b);
  949. return col;
  950. }
  951. static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
  952. {
  953. unsigned int col;
  954. col = rgb_to_pixel32bgr(r, g, b);
  955. return col;
  956. }
  957. /* return true if the palette was modified */
  958. static int update_palette16(VGAState *s)
  959. {
  960. int full_update, i;
  961. uint32_t v, col, *palette;
  962. full_update = 0;
  963. palette = s->last_palette;
  964. for(i = 0; i < 16; i++) {
  965. v = s->ar[i];
  966. if (s->ar[0x10] & 0x80)
  967. v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
  968. else
  969. v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
  970. v = v * 3;
  971. col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
  972. c6_to_8(s->palette[v + 1]),
  973. c6_to_8(s->palette[v + 2]));
  974. if (col != palette[i]) {
  975. full_update = 1;
  976. palette[i] = col;
  977. }
  978. }
  979. return full_update;
  980. }
  981. /* return true if the palette was modified */
  982. static int update_palette256(VGAState *s)
  983. {
  984. int full_update, i;
  985. uint32_t v, col, *palette;
  986. full_update = 0;
  987. palette = s->last_palette;
  988. v = 0;
  989. for(i = 0; i < 256; i++) {
  990. if (s->dac_8bit) {
  991. col = s->rgb_to_pixel(s->palette[v],
  992. s->palette[v + 1],
  993. s->palette[v + 2]);
  994. } else {
  995. col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
  996. c6_to_8(s->palette[v + 1]),
  997. c6_to_8(s->palette[v + 2]));
  998. }
  999. if (col != palette[i]) {
  1000. full_update = 1;
  1001. palette[i] = col;
  1002. }
  1003. v += 3;
  1004. }
  1005. return full_update;
  1006. }
  1007. static void vga_get_offsets(VGAState *s,
  1008. uint32_t *pline_offset,
  1009. uint32_t *pstart_addr,
  1010. uint32_t *pline_compare)
  1011. {
  1012. uint32_t start_addr, line_offset, line_compare;
  1013. #ifdef CONFIG_BOCHS_VBE
  1014. if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
  1015. line_offset = s->vbe_line_offset;
  1016. start_addr = s->vbe_start_addr;
  1017. line_compare = 65535;
  1018. } else
  1019. #endif
  1020. {
  1021. /* compute line_offset in bytes */
  1022. line_offset = s->cr[0x13];
  1023. line_offset <<= 3;
  1024. /* starting address */
  1025. start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
  1026. /* line compare */
  1027. line_compare = s->cr[0x18] |
  1028. ((s->cr[0x07] & 0x10) << 4) |
  1029. ((s->cr[0x09] & 0x40) << 3);
  1030. }
  1031. *pline_offset = line_offset;
  1032. *pstart_addr = start_addr;
  1033. *pline_compare = line_compare;
  1034. }
  1035. /* update start_addr and line_offset. Return TRUE if modified */
  1036. static int update_basic_params(VGAState *s)
  1037. {
  1038. int full_update;
  1039. uint32_t start_addr, line_offset, line_compare;
  1040. full_update = 0;
  1041. s->get_offsets(s, &line_offset, &start_addr, &line_compare);
  1042. if (line_offset != s->line_offset ||
  1043. start_addr != s->start_addr ||
  1044. line_compare != s->line_compare) {
  1045. s->line_offset = line_offset;
  1046. s->start_addr = start_addr;
  1047. s->line_compare = line_compare;
  1048. full_update = 1;
  1049. }
  1050. return full_update;
  1051. }
  1052. #define NB_DEPTHS 7
  1053. static inline int get_depth_index(DisplayState *s)
  1054. {
  1055. switch(ds_get_bits_per_pixel(s)) {
  1056. default:
  1057. case 8:
  1058. return 0;
  1059. case 15:
  1060. return 1;
  1061. case 16:
  1062. return 2;
  1063. case 32:
  1064. return 3;
  1065. }
  1066. }
  1067. static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
  1068. vga_draw_glyph8_8,
  1069. vga_draw_glyph8_16,
  1070. vga_draw_glyph8_16,
  1071. vga_draw_glyph8_32,
  1072. vga_draw_glyph8_32,
  1073. vga_draw_glyph8_16,
  1074. vga_draw_glyph8_16,
  1075. };
  1076. static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
  1077. vga_draw_glyph16_8,
  1078. vga_draw_glyph16_16,
  1079. vga_draw_glyph16_16,
  1080. vga_draw_glyph16_32,
  1081. vga_draw_glyph16_32,
  1082. vga_draw_glyph16_16,
  1083. vga_draw_glyph16_16,
  1084. };
  1085. static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
  1086. vga_draw_glyph9_8,
  1087. vga_draw_glyph9_16,
  1088. vga_draw_glyph9_16,
  1089. vga_draw_glyph9_32,
  1090. vga_draw_glyph9_32,
  1091. vga_draw_glyph9_16,
  1092. vga_draw_glyph9_16,
  1093. };
  1094. static const uint8_t cursor_glyph[32 * 4] = {
  1095. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1096. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1097. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1098. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1099. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1100. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1101. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1102. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1103. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1104. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1105. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1106. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1107. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1108. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1109. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1110. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  1111. };
  1112. static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
  1113. int *pcwidth, int *pcheight)
  1114. {
  1115. int width, cwidth, height, cheight;
  1116. /* total width & height */
  1117. cheight = (s->cr[9] & 0x1f) + 1;
  1118. cwidth = 8;
  1119. if (!(s->sr[1] & 0x01))
  1120. cwidth = 9;
  1121. if (s->sr[1] & 0x08)
  1122. cwidth = 16; /* NOTE: no 18 pixel wide */
  1123. width = (s->cr[0x01] + 1);
  1124. if (s->cr[0x06] == 100) {
  1125. /* ugly hack for CGA 160x100x16 - explain me the logic */
  1126. height = 100;
  1127. } else {
  1128. height = s->cr[0x12] |
  1129. ((s->cr[0x07] & 0x02) << 7) |
  1130. ((s->cr[0x07] & 0x40) << 3);
  1131. height = (height + 1) / cheight;
  1132. }
  1133. *pwidth = width;
  1134. *pheight = height;
  1135. *pcwidth = cwidth;
  1136. *pcheight = cheight;
  1137. }
  1138. typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
  1139. static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
  1140. rgb_to_pixel8_dup,
  1141. rgb_to_pixel15_dup,
  1142. rgb_to_pixel16_dup,
  1143. rgb_to_pixel32_dup,
  1144. rgb_to_pixel32bgr_dup,
  1145. rgb_to_pixel15bgr_dup,
  1146. rgb_to_pixel16bgr_dup,
  1147. };
  1148. /*
  1149. * Text mode update
  1150. * Missing:
  1151. * - double scan
  1152. * - double width
  1153. * - underline
  1154. * - flashing
  1155. */
  1156. static void vga_draw_text(VGAState *s, int full_update)
  1157. {
  1158. int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
  1159. int cx_min, cx_max, linesize, x_incr;
  1160. uint32_t offset, fgcol, bgcol, v, cursor_offset;
  1161. uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
  1162. const uint8_t *font_ptr, *font_base[2];
  1163. int dup9, line_offset, depth_index;
  1164. uint32_t *palette;
  1165. uint32_t *ch_attr_ptr;
  1166. vga_draw_glyph8_func *vga_draw_glyph8;
  1167. vga_draw_glyph9_func *vga_draw_glyph9;
  1168. vga_dirty_log_stop(s);
  1169. /* compute font data address (in plane 2) */
  1170. v = s->sr[3];
  1171. offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
  1172. if (offset != s->font_offsets[0]) {
  1173. s->font_offsets[0] = offset;
  1174. full_update = 1;
  1175. }
  1176. font_base[0] = s->vram_ptr + offset;
  1177. offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
  1178. font_base[1] = s->vram_ptr + offset;
  1179. if (offset != s->font_offsets[1]) {
  1180. s->font_offsets[1] = offset;
  1181. full_update = 1;
  1182. }
  1183. if (s->plane_updated & (1 << 2)) {
  1184. /* if the plane 2 was modified since the last display, it
  1185. indicates the font may have been modified */
  1186. s->plane_updated = 0;
  1187. full_update = 1;
  1188. }
  1189. full_update |= update_basic_params(s);
  1190. line_offset = s->line_offset;
  1191. s1 = s->vram_ptr + (s->start_addr * 4);
  1192. vga_get_text_resolution(s, &width, &height, &cw, &cheight);
  1193. x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
  1194. if ((height * width) > CH_ATTR_SIZE) {
  1195. /* better than nothing: exit if transient size is too big */
  1196. return;
  1197. }
  1198. if (width != s->last_width || height != s->last_height ||
  1199. cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
  1200. s->last_scr_width = width * cw;
  1201. s->last_scr_height = height * cheight;
  1202. qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
  1203. s->last_depth = 0;
  1204. s->last_width = width;
  1205. s->last_height = height;
  1206. s->last_ch = cheight;
  1207. s->last_cw = cw;
  1208. full_update = 1;
  1209. }
  1210. s->rgb_to_pixel =
  1211. rgb_to_pixel_dup_table[get_depth_index(s->ds)];
  1212. full_update |= update_palette16(s);
  1213. palette = s->last_palette;
  1214. x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
  1215. cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
  1216. if (cursor_offset != s->cursor_offset ||
  1217. s->cr[0xa] != s->cursor_start ||
  1218. s->cr[0xb] != s->cursor_end) {
  1219. /* if the cursor position changed, we update the old and new
  1220. chars */
  1221. if (s->cursor_offset < CH_ATTR_SIZE)
  1222. s->last_ch_attr[s->cursor_offset] = -1;
  1223. if (cursor_offset < CH_ATTR_SIZE)
  1224. s->last_ch_attr[cursor_offset] = -1;
  1225. s->cursor_offset = cursor_offset;
  1226. s->cursor_start = s->cr[0xa];
  1227. s->cursor_end = s->cr[0xb];
  1228. }
  1229. cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
  1230. depth_index = get_depth_index(s->ds);
  1231. if (cw == 16)
  1232. vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
  1233. else
  1234. vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
  1235. vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
  1236. dest = ds_get_data(s->ds);
  1237. linesize = ds_get_linesize(s->ds);
  1238. ch_attr_ptr = s->last_ch_attr;
  1239. for(cy = 0; cy < height; cy++) {
  1240. d1 = dest;
  1241. src = s1;
  1242. cx_min = width;
  1243. cx_max = -1;
  1244. for(cx = 0; cx < width; cx++) {
  1245. ch_attr = *(uint16_t *)src;
  1246. if (full_update || ch_attr != *ch_attr_ptr) {
  1247. if (cx < cx_min)
  1248. cx_min = cx;
  1249. if (cx > cx_max)
  1250. cx_max = cx;
  1251. *ch_attr_ptr = ch_attr;
  1252. #ifdef WORDS_BIGENDIAN
  1253. ch = ch_attr >> 8;
  1254. cattr = ch_attr & 0xff;
  1255. #else
  1256. ch = ch_attr & 0xff;
  1257. cattr = ch_attr >> 8;
  1258. #endif
  1259. font_ptr = font_base[(cattr >> 3) & 1];
  1260. font_ptr += 32 * 4 * ch;
  1261. bgcol = palette[cattr >> 4];
  1262. fgcol = palette[cattr & 0x0f];
  1263. if (cw != 9) {
  1264. vga_draw_glyph8(d1, linesize,
  1265. font_ptr, cheight, fgcol, bgcol);
  1266. } else {
  1267. dup9 = 0;
  1268. if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
  1269. dup9 = 1;
  1270. vga_draw_glyph9(d1, linesize,
  1271. font_ptr, cheight, fgcol, bgcol, dup9);
  1272. }
  1273. if (src == cursor_ptr &&
  1274. !(s->cr[0x0a] & 0x20)) {
  1275. int line_start, line_last, h;
  1276. /* draw the cursor */
  1277. line_start = s->cr[0x0a] & 0x1f;
  1278. line_last = s->cr[0x0b] & 0x1f;
  1279. /* XXX: check that */
  1280. if (line_last > cheight - 1)
  1281. line_last = cheight - 1;
  1282. if (line_last >= line_start && line_start < cheight) {
  1283. h = line_last - line_start + 1;
  1284. d = d1 + linesize * line_start;
  1285. if (cw != 9) {
  1286. vga_draw_glyph8(d, linesize,
  1287. cursor_glyph, h, fgcol, bgcol);
  1288. } else {
  1289. vga_draw_glyph9(d, linesize,
  1290. cursor_glyph, h, fgcol, bgcol, 1);
  1291. }
  1292. }
  1293. }
  1294. }
  1295. d1 += x_incr;
  1296. src += 4;
  1297. ch_attr_ptr++;
  1298. }
  1299. if (cx_max != -1) {
  1300. dpy_update(s->ds, cx_min * cw, cy * cheight,
  1301. (cx_max - cx_min + 1) * cw, cheight);
  1302. }
  1303. dest += linesize * cheight;
  1304. s1 += line_offset;
  1305. }
  1306. }
  1307. enum {
  1308. VGA_DRAW_LINE2,
  1309. VGA_DRAW_LINE2D2,
  1310. VGA_DRAW_LINE4,
  1311. VGA_DRAW_LINE4D2,
  1312. VGA_DRAW_LINE8D2,
  1313. VGA_DRAW_LINE8,
  1314. VGA_DRAW_LINE15,
  1315. VGA_DRAW_LINE16,
  1316. VGA_DRAW_LINE24,
  1317. VGA_DRAW_LINE32,
  1318. VGA_DRAW_LINE_NB,
  1319. };
  1320. static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
  1321. vga_draw_line2_8,
  1322. vga_draw_line2_16,
  1323. vga_draw_line2_16,
  1324. vga_draw_line2_32,
  1325. vga_draw_line2_32,
  1326. vga_draw_line2_16,
  1327. vga_draw_line2_16,
  1328. vga_draw_line2d2_8,
  1329. vga_draw_line2d2_16,
  1330. vga_draw_line2d2_16,
  1331. vga_draw_line2d2_32,
  1332. vga_draw_line2d2_32,
  1333. vga_draw_line2d2_16,
  1334. vga_draw_line2d2_16,
  1335. vga_draw_line4_8,
  1336. vga_draw_line4_16,
  1337. vga_draw_line4_16,
  1338. vga_draw_line4_32,
  1339. vga_draw_line4_32,
  1340. vga_draw_line4_16,
  1341. vga_draw_line4_16,
  1342. vga_draw_line4d2_8,
  1343. vga_draw_line4d2_16,
  1344. vga_draw_line4d2_16,
  1345. vga_draw_line4d2_32,
  1346. vga_draw_line4d2_32,
  1347. vga_draw_line4d2_16,
  1348. vga_draw_line4d2_16,
  1349. vga_draw_line8d2_8,
  1350. vga_draw_line8d2_16,
  1351. vga_draw_line8d2_16,
  1352. vga_draw_line8d2_32,
  1353. vga_draw_line8d2_32,
  1354. vga_draw_line8d2_16,
  1355. vga_draw_line8d2_16,
  1356. vga_draw_line8_8,
  1357. vga_draw_line8_16,
  1358. vga_draw_line8_16,
  1359. vga_draw_line8_32,
  1360. vga_draw_line8_32,
  1361. vga_draw_line8_16,
  1362. vga_draw_line8_16,
  1363. vga_draw_line15_8,
  1364. vga_draw_line15_15,
  1365. vga_draw_line15_16,
  1366. vga_draw_line15_32,
  1367. vga_draw_line15_32bgr,
  1368. vga_draw_line15_15bgr,
  1369. vga_draw_line15_16bgr,
  1370. vga_draw_line16_8,
  1371. vga_draw_line16_15,
  1372. vga_draw_line16_16,
  1373. vga_draw_line16_32,
  1374. vga_draw_line16_32bgr,
  1375. vga_draw_line16_15bgr,
  1376. vga_draw_line16_16bgr,
  1377. vga_draw_line24_8,
  1378. vga_draw_line24_15,
  1379. vga_draw_line24_16,
  1380. vga_draw_line24_32,
  1381. vga_draw_line24_32bgr,
  1382. vga_draw_line24_15bgr,
  1383. vga_draw_line24_16bgr,
  1384. vga_draw_line32_8,
  1385. vga_draw_line32_15,
  1386. vga_draw_line32_16,
  1387. vga_draw_line32_32,
  1388. vga_draw_line32_32bgr,
  1389. vga_draw_line32_15bgr,
  1390. vga_draw_line32_16bgr,
  1391. };
  1392. static int vga_get_bpp(VGAState *s)
  1393. {
  1394. int ret;
  1395. #ifdef CONFIG_BOCHS_VBE
  1396. if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
  1397. ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
  1398. } else
  1399. #endif
  1400. {
  1401. ret = 0;
  1402. }
  1403. return ret;
  1404. }
  1405. static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
  1406. {
  1407. int width, height;
  1408. #ifdef CONFIG_BOCHS_VBE
  1409. if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
  1410. width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
  1411. height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
  1412. } else
  1413. #endif
  1414. {
  1415. width = (s->cr[0x01] + 1) * 8;
  1416. height = s->cr[0x12] |
  1417. ((s->cr[0x07] & 0x02) << 7) |
  1418. ((s->cr[0x07] & 0x40) << 3);
  1419. height = (height + 1);
  1420. }
  1421. *pwidth = width;
  1422. *pheight = height;
  1423. }
  1424. void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
  1425. {
  1426. int y;
  1427. if (y1 >= VGA_MAX_HEIGHT)
  1428. return;
  1429. if (y2 >= VGA_MAX_HEIGHT)
  1430. y2 = VGA_MAX_HEIGHT;
  1431. for(y = y1; y < y2; y++) {
  1432. s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
  1433. }
  1434. }
  1435. static void vga_sync_dirty_bitmap(VGAState *s)
  1436. {
  1437. if (s->map_addr)
  1438. cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
  1439. if (s->lfb_vram_mapped) {
  1440. cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
  1441. cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
  1442. }
  1443. vga_dirty_log_start(s);
  1444. }
  1445. /*
  1446. * graphic modes
  1447. */
  1448. static void vga_draw_graphic(VGAState *s, int full_update)
  1449. {
  1450. int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask, depth;
  1451. int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
  1452. int disp_width, multi_scan, multi_run;
  1453. uint8_t *d;
  1454. uint32_t v, addr1, addr;
  1455. vga_draw_line_func *vga_draw_line;
  1456. full_update |= update_basic_params(s);
  1457. if (!full_update)
  1458. vga_sync_dirty_bitmap(s);
  1459. s->get_resolution(s, &width, &height);
  1460. disp_width = width;
  1461. shift_control = (s->gr[0x05] >> 5) & 3;
  1462. double_scan = (s->cr[0x09] >> 7);
  1463. if (shift_control != 1) {
  1464. multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
  1465. } else {
  1466. /* in CGA modes, multi_scan is ignored */
  1467. /* XXX: is it correct ? */
  1468. multi_scan = double_scan;
  1469. }
  1470. multi_run = multi_scan;
  1471. if (shift_control != s->shift_control ||
  1472. double_scan != s->double_scan) {
  1473. full_update = 1;
  1474. s->shift_control = shift_control;
  1475. s->double_scan = double_scan;
  1476. }
  1477. if (shift_control == 0) {
  1478. if (s->sr[0x01] & 8) {
  1479. disp_width <<= 1;
  1480. }
  1481. } else if (shift_control == 1) {
  1482. if (s->sr[0x01] & 8) {
  1483. disp_width <<= 1;
  1484. }
  1485. }
  1486. depth = s->get_bpp(s);
  1487. if (s->line_offset != s->last_line_offset ||
  1488. disp_width != s->last_width ||
  1489. height != s->last_height ||
  1490. s->last_depth != depth) {
  1491. #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
  1492. if (depth == 16 || depth == 32) {
  1493. #else
  1494. if (depth == 32) {
  1495. #endif
  1496. if (is_graphic_console()) {
  1497. qemu_free_displaysurface(s->ds->surface);
  1498. s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
  1499. s->line_offset,
  1500. s->vram_ptr + (s->start_addr * 4));
  1501. #if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
  1502. s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
  1503. #endif
  1504. dpy_resize(s->ds);
  1505. } else {
  1506. qemu_console_resize(s->ds, disp_width, height);
  1507. }
  1508. } else {
  1509. qemu_console_resize(s->ds, disp_width, height);
  1510. }
  1511. s->last_scr_width = disp_width;
  1512. s->last_scr_height = height;
  1513. s->last_width = disp_width;
  1514. s->last_height = height;
  1515. s->last_line_offset = s->line_offset;
  1516. s->last_depth = depth;
  1517. full_update = 1;
  1518. } else if (is_graphic_console() && is_buffer_shared(s->ds->surface) &&
  1519. (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
  1520. s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
  1521. dpy_setdata(s->ds);
  1522. }
  1523. s->rgb_to_pixel =
  1524. rgb_to_pixel_dup_table[get_depth_index(s->ds)];
  1525. if (shift_control == 0) {
  1526. full_update |= update_palette16(s);
  1527. if (s->sr[0x01] & 8) {
  1528. v = VGA_DRAW_LINE4D2;
  1529. } else {
  1530. v = VGA_DRAW_LINE4;
  1531. }
  1532. bits = 4;
  1533. } else if (shift_control == 1) {
  1534. full_update |= update_palette16(s);
  1535. if (s->sr[0x01] & 8) {
  1536. v = VGA_DRAW_LINE2D2;
  1537. } else {
  1538. v = VGA_DRAW_LINE2;
  1539. }
  1540. bits = 4;
  1541. } else {
  1542. switch(s->get_bpp(s)) {
  1543. default:
  1544. case 0:
  1545. full_update |= update_palette256(s);
  1546. v = VGA_DRAW_LINE8D2;
  1547. bits = 4;
  1548. break;
  1549. case 8:
  1550. full_update |= update_palette256(s);
  1551. v = VGA_DRAW_LINE8;
  1552. bits = 8;
  1553. break;
  1554. case 15:
  1555. v = VGA_DRAW_LINE15;
  1556. bits = 16;
  1557. break;
  1558. case 16:
  1559. v = VGA_DRAW_LINE16;
  1560. bits = 16;
  1561. break;
  1562. case 24:
  1563. v = VGA_DRAW_LINE24;
  1564. bits = 24;
  1565. break;
  1566. case 32:
  1567. v = VGA_DRAW_LINE32;
  1568. bits = 32;
  1569. break;
  1570. }
  1571. }
  1572. vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
  1573. if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
  1574. s->cursor_invalidate(s);
  1575. line_offset = s->line_offset;
  1576. #if 0
  1577. printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
  1578. width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
  1579. #endif
  1580. addr1 = (s->start_addr * 4);
  1581. bwidth = (width * bits + 7) / 8;
  1582. y_start = -1;
  1583. page_min = 0x7fffffff;
  1584. page_max = -1;
  1585. d = ds_get_data(s->ds);
  1586. linesize = ds_get_linesize(s->ds);
  1587. y1 = 0;
  1588. for(y = 0; y < height; y++) {
  1589. addr = addr1;
  1590. if (!(s->cr[0x17] & 1)) {
  1591. int shift;
  1592. /* CGA compatibility handling */
  1593. shift = 14 + ((s->cr[0x17] >> 6) & 1);
  1594. addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
  1595. }
  1596. if (!(s->cr[0x17] & 2)) {
  1597. addr = (addr & ~0x8000) | ((y1 & 2) << 14);
  1598. }
  1599. page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
  1600. page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
  1601. update = full_update |
  1602. cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
  1603. cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
  1604. if ((page1 - page0) > TARGET_PAGE_SIZE) {
  1605. /* if wide line, can use another page */
  1606. update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
  1607. VGA_DIRTY_FLAG);
  1608. }
  1609. /* explicit invalidation for the hardware cursor */
  1610. update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
  1611. if (update) {
  1612. if (y_start < 0)
  1613. y_start = y;
  1614. if (page0 < page_min)
  1615. page_min = page0;
  1616. if (page1 > page_max)
  1617. page_max = page1;
  1618. if (!(is_buffer_shared(s->ds->surface))) {
  1619. vga_draw_line(s, d, s->vram_ptr + addr, width);
  1620. if (s->cursor_draw_line)
  1621. s->cursor_draw_line(s, d, y);
  1622. }
  1623. } else {
  1624. if (y_start >= 0) {
  1625. /* flush to display */
  1626. dpy_update(s->ds, 0, y_start,
  1627. disp_width, y - y_start);
  1628. y_start = -1;
  1629. }
  1630. }
  1631. if (!multi_run) {
  1632. mask = (s->cr[0x17] & 3) ^ 3;
  1633. if ((y1 & mask) == mask)
  1634. addr1 += line_offset;
  1635. y1++;
  1636. multi_run = multi_scan;
  1637. } else {
  1638. multi_run--;
  1639. }
  1640. /* line compare acts on the displayed lines */
  1641. if (y == s->line_compare)
  1642. addr1 = 0;
  1643. d += linesize;
  1644. }
  1645. if (y_start >= 0) {
  1646. /* flush to display */
  1647. dpy_update(s->ds, 0, y_start,
  1648. disp_width, y - y_start);
  1649. }
  1650. /* reset modified pages */
  1651. if (page_max != -1) {
  1652. cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
  1653. VGA_DIRTY_FLAG);
  1654. }
  1655. memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
  1656. }
  1657. static void vga_draw_blank(VGAState *s, int full_update)
  1658. {
  1659. int i, w, val;
  1660. uint8_t *d;
  1661. if (!full_update)
  1662. return;
  1663. if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
  1664. return;
  1665. vga_dirty_log_stop(s);
  1666. s->rgb_to_pixel =
  1667. rgb_to_pixel_dup_table[get_depth_index(s->ds)];
  1668. if (ds_get_bits_per_pixel(s->ds) == 8)
  1669. val = s->rgb_to_pixel(0, 0, 0);
  1670. else
  1671. val = 0;
  1672. w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
  1673. d = ds_get_data(s->ds);
  1674. for(i = 0; i < s->last_scr_height; i++) {
  1675. memset(d, val, w);
  1676. d += ds_get_linesize(s->ds);
  1677. }
  1678. dpy_update(s->ds, 0, 0,
  1679. s->last_scr_width, s->last_scr_height);
  1680. }
  1681. #define GMODE_TEXT 0
  1682. #define GMODE_GRAPH 1
  1683. #define GMODE_BLANK 2
  1684. static void vga_update_display(void *opaque)
  1685. {
  1686. VGAState *s = (VGAState *)opaque;
  1687. int full_update, graphic_mode;
  1688. if (ds_get_bits_per_pixel(s->ds) == 0) {
  1689. /* nothing to do */
  1690. } else {
  1691. full_update = 0;
  1692. if (!(s->ar_index & 0x20)) {
  1693. graphic_mode = GMODE_BLANK;
  1694. } else {
  1695. graphic_mode = s->gr[6] & 1;
  1696. }
  1697. if (graphic_mode != s->graphic_mode) {
  1698. s->graphic_mode = graphic_mode;
  1699. full_update = 1;
  1700. }
  1701. switch(graphic_mode) {
  1702. case GMODE_TEXT:
  1703. vga_draw_text(s, full_update);
  1704. break;
  1705. case GMODE_GRAPH:
  1706. vga_draw_graphic(s, full_update);
  1707. break;
  1708. case GMODE_BLANK:
  1709. default:
  1710. vga_draw_blank(s, full_update);
  1711. break;
  1712. }
  1713. }
  1714. }
  1715. /* force a full display refresh */
  1716. static void vga_invalidate_display(void *opaque)
  1717. {
  1718. VGAState *s = (VGAState *)opaque;
  1719. s->last_width = -1;
  1720. s->last_height = -1;
  1721. }
  1722. void vga_reset(void *opaque)
  1723. {
  1724. VGAState *s = (VGAState *) opaque;
  1725. s->lfb_addr = 0;
  1726. s->lfb_end = 0;
  1727. s->map_addr = 0;
  1728. s->map_end = 0;
  1729. s->lfb_vram_mapped = 0;
  1730. s->bios_offset = 0;
  1731. s->bios_size = 0;
  1732. s->sr_index = 0;
  1733. memset(s->sr, '\0', sizeof(s->sr));
  1734. s->gr_index = 0;
  1735. memset(s->gr, '\0', sizeof(s->gr));
  1736. s->ar_index = 0;
  1737. memset(s->ar, '\0', sizeof(s->ar));
  1738. s->ar_flip_flop = 0;
  1739. s->cr_index = 0;
  1740. memset(s->cr, '\0', sizeof(s->cr));
  1741. s->msr = 0;
  1742. s->fcr = 0;
  1743. s->st00 = 0;
  1744. s->st01 = 0;
  1745. s->dac_state = 0;
  1746. s->dac_sub_index = 0;
  1747. s->dac_read_index = 0;
  1748. s->dac_write_index = 0;
  1749. memset(s->dac_cache, '\0', sizeof(s->dac_cache));
  1750. s->dac_8bit = 0;
  1751. memset(s->palette, '\0', sizeof(s->palette));
  1752. s->bank_offset = 0;
  1753. #ifdef CONFIG_BOCHS_VBE
  1754. s->vbe_index = 0;
  1755. memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
  1756. s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
  1757. s->vbe_start_addr = 0;
  1758. s->vbe_line_offset = 0;
  1759. s->vbe_bank_mask = (s->vram_size >> 16) - 1;
  1760. #endif
  1761. memset(s->font_offsets, '\0', sizeof(s->font_offsets));
  1762. s->graphic_mode = -1; /* force full update */
  1763. s->shift_control = 0;
  1764. s->double_scan = 0;
  1765. s->line_offset = 0;
  1766. s->line_compare = 0;
  1767. s->start_addr = 0;
  1768. s->plane_updated = 0;
  1769. s->last_cw = 0;
  1770. s->last_ch = 0;
  1771. s->last_width = 0;
  1772. s->last_height = 0;
  1773. s->last_scr_width = 0;
  1774. s->last_scr_height = 0;
  1775. s->cursor_start = 0;
  1776. s->cursor_end = 0;
  1777. s->cursor_offset = 0;
  1778. memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
  1779. memset(s->last_palette, '\0', sizeof(s->last_palette));
  1780. memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
  1781. switch (vga_retrace_method) {
  1782. case VGA_RETRACE_DUMB:
  1783. break;
  1784. case VGA_RETRACE_PRECISE:
  1785. memset(&s->retrace_info, 0, sizeof (s->retrace_info));
  1786. break;
  1787. }
  1788. }
  1789. #define TEXTMODE_X(x) ((x) % width)
  1790. #define TEXTMODE_Y(x) ((x) / width)
  1791. #define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
  1792. ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
  1793. /* relay text rendering to the display driver
  1794. * instead of doing a full vga_update_display() */
  1795. static void vga_update_text(void *opaque, console_ch_t *chardata)
  1796. {
  1797. VGAState *s = (VGAState *) opaque;
  1798. int graphic_mode, i, cursor_offset, cursor_visible;
  1799. int cw, cheight, width, height, size, c_min, c_max;
  1800. uint32_t *src;
  1801. console_ch_t *dst, val;
  1802. char msg_buffer[80];
  1803. int full_update = 0;
  1804. if (!(s->ar_index & 0x20)) {
  1805. graphic_mode = GMODE_BLANK;
  1806. } else {
  1807. graphic_mode = s->gr[6] & 1;
  1808. }
  1809. if (graphic_mode != s->graphic_mode) {
  1810. s->graphic_mode = graphic_mode;
  1811. full_update = 1;
  1812. }
  1813. if (s->last_width == -1) {
  1814. s->last_width = 0;
  1815. full_update = 1;
  1816. }
  1817. switch (graphic_mode) {
  1818. case GMODE_TEXT:
  1819. /* TODO: update palette */
  1820. full_update |= update_basic_params(s);
  1821. /* total width & height */
  1822. cheight = (s->cr[9] & 0x1f) + 1;
  1823. cw = 8;
  1824. if (!(s->sr[1] & 0x01))
  1825. cw = 9;
  1826. if (s->sr[1] & 0x08)
  1827. cw = 16; /* NOTE: no 18 pixel wide */
  1828. width = (s->cr[0x01] + 1);
  1829. if (s->cr[0x06] == 100) {
  1830. /* ugly hack for CGA 160x100x16 - explain me the logic */
  1831. height = 100;
  1832. } else {
  1833. height = s->cr[0x12] |
  1834. ((s->cr[0x07] & 0x02) << 7) |
  1835. ((s->cr[0x07] & 0x40) << 3);
  1836. height = (height + 1) / cheight;
  1837. }
  1838. size = (height * width);
  1839. if (size > CH_ATTR_SIZE) {
  1840. if (!full_update)
  1841. return;
  1842. snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
  1843. width, height);
  1844. break;
  1845. }
  1846. if (width != s->last_width || height != s->last_height ||
  1847. cw != s->last_cw || cheight != s->last_ch) {
  1848. s->last_scr_width = width * cw;
  1849. s->last_scr_height = height * cheight;
  1850. s->ds->surface->width = width;
  1851. s->ds->surface->height = height;
  1852. dpy_resize(s->ds);
  1853. s->last_width = width;
  1854. s->last_height = height;
  1855. s->last_ch = cheight;
  1856. s->last_cw = cw;
  1857. full_update = 1;
  1858. }
  1859. /* Update "hardware" cursor */
  1860. cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
  1861. if (cursor_offset != s->cursor_offset ||
  1862. s->cr[0xa] != s->cursor_start ||
  1863. s->cr[0xb] != s->cursor_end || full_update) {
  1864. cursor_visible = !(s->cr[0xa] & 0x20);
  1865. if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
  1866. dpy_cursor(s->ds,
  1867. TEXTMODE_X(cursor_offset),
  1868. TEXTMODE_Y(cursor_offset));
  1869. else
  1870. dpy_cursor(s->ds, -1, -1);
  1871. s->cursor_offset = cursor_offset;
  1872. s->cursor_start = s->cr[0xa];
  1873. s->cursor_end = s->cr[0xb];
  1874. }
  1875. src = (uint32_t *) s->vram_ptr + s->start_addr;
  1876. dst = chardata;
  1877. if (full_update) {
  1878. for (i = 0; i < size; src ++, dst ++, i ++)
  1879. console_write_ch(dst, VMEM2CHTYPE(*src));
  1880. dpy_update(s->ds, 0, 0, width, height);
  1881. } else {
  1882. c_max = 0;
  1883. for (i = 0; i < size; src ++, dst ++, i ++) {
  1884. console_write_ch(&val, VMEM2CHTYPE(*src));
  1885. if (*dst != val) {
  1886. *dst = val;
  1887. c_max = i;
  1888. break;
  1889. }
  1890. }
  1891. c_min = i;
  1892. for (; i < size; src ++, dst ++, i ++) {
  1893. console_write_ch(&val, VMEM2CHTYPE(*src));
  1894. if (*dst != val) {
  1895. *dst = val;
  1896. c_max = i;
  1897. }
  1898. }
  1899. if (c_min <= c_max) {
  1900. i = TEXTMODE_Y(c_min);
  1901. dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
  1902. }
  1903. }
  1904. return;
  1905. case GMODE_GRAPH:
  1906. if (!full_update)
  1907. return;
  1908. s->get_resolution(s, &width, &height);
  1909. snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
  1910. width, height);
  1911. break;
  1912. case GMODE_BLANK:
  1913. default:
  1914. if (!full_update)
  1915. return;
  1916. snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
  1917. break;
  1918. }
  1919. /* Display a message */
  1920. s->last_width = 60;
  1921. s->last_height = height = 3;
  1922. dpy_cursor(s->ds, -1, -1);
  1923. s->ds->surface->width = s->last_width;
  1924. s->ds->surface->height = height;
  1925. dpy_resize(s->ds);
  1926. for (dst = chardata, i = 0; i < s->last_width * height; i ++)
  1927. console_write_ch(dst ++, ' ');
  1928. size = strlen(msg_buffer);
  1929. width = (s->last_width - size) / 2;
  1930. dst = chardata + s->last_width + width;
  1931. for (i = 0; i < size; i ++)
  1932. console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
  1933. dpy_update(s->ds, 0, 0, s->last_width, height);
  1934. }
  1935. static CPUReadMemoryFunc *vga_mem_read[3] = {
  1936. vga_mem_readb,
  1937. vga_mem_readw,
  1938. vga_mem_readl,
  1939. };
  1940. static CPUWriteMemoryFunc *vga_mem_write[3] = {
  1941. vga_mem_writeb,
  1942. vga_mem_writew,
  1943. vga_mem_writel,
  1944. };
  1945. static void vga_save(QEMUFile *f, void *opaque)
  1946. {
  1947. VGAState *s = opaque;
  1948. int i;
  1949. if (s->pci_dev)
  1950. pci_device_save(s->pci_dev, f);
  1951. qemu_put_be32s(f, &s->latch);
  1952. qemu_put_8s(f, &s->sr_index);
  1953. qemu_put_buffer(f, s->sr, 8);
  1954. qemu_put_8s(f, &s->gr_index);
  1955. qemu_put_buffer(f, s->gr, 16);
  1956. qemu_put_8s(f, &s->ar_index);
  1957. qemu_put_buffer(f, s->ar, 21);
  1958. qemu_put_be32(f, s->ar_flip_flop);
  1959. qemu_put_8s(f, &s->cr_index);
  1960. qemu_put_buffer(f, s->cr, 256);
  1961. qemu_put_8s(f, &s->msr);
  1962. qemu_put_8s(f, &s->fcr);
  1963. qemu_put_byte(f, s->st00);
  1964. qemu_put_8s(f, &s->st01);
  1965. qemu_put_8s(f, &s->dac_state);
  1966. qemu_put_8s(f, &s->dac_sub_index);
  1967. qemu_put_8s(f, &s->dac_read_index);
  1968. qemu_put_8s(f, &s->dac_write_index);
  1969. qemu_put_buffer(f, s->dac_cache, 3);
  1970. qemu_put_buffer(f, s->palette, 768);
  1971. qemu_put_be32(f, s->bank_offset);
  1972. #ifdef CONFIG_BOCHS_VBE
  1973. qemu_put_byte(f, 1);
  1974. qemu_put_be16s(f, &s->vbe_index);
  1975. for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
  1976. qemu_put_be16s(f, &s->vbe_regs[i]);
  1977. qemu_put_be32s(f, &s->vbe_start_addr);
  1978. qemu_put_be32s(f, &s->vbe_line_offset);
  1979. qemu_put_be32s(f, &s->vbe_bank_mask);
  1980. #else
  1981. qemu_put_byte(f, 0);
  1982. #endif
  1983. }
  1984. static int vga_load(QEMUFile *f, void *opaque, int version_id)
  1985. {
  1986. VGAState *s = opaque;
  1987. int is_vbe, i, ret;
  1988. if (version_id > 2)
  1989. return -EINVAL;
  1990. if (s->pci_dev && version_id >= 2) {
  1991. ret = pci_device_load(s->pci_dev, f);
  1992. if (ret < 0)
  1993. return ret;
  1994. }
  1995. qemu_get_be32s(f, &s->latch);
  1996. qemu_get_8s(f, &s->sr_index);
  1997. qemu_get_buffer(f, s->sr, 8);
  1998. qemu_get_8s(f, &s->gr_index);
  1999. qemu_get_buffer(f, s->gr, 16);
  2000. qemu_get_8s(f, &s->ar_index);
  2001. qemu_get_buffer(f, s->ar, 21);
  2002. s->ar_flip_flop=qemu_get_be32(f);
  2003. qemu_get_8s(f, &s->cr_index);
  2004. qemu_get_buffer(f, s->cr, 256);
  2005. qemu_get_8s(f, &s->msr);
  2006. qemu_get_8s(f, &s->fcr);
  2007. qemu_get_8s(f, &s->st00);
  2008. qemu_get_8s(f, &s->st01);
  2009. qemu_get_8s(f, &s->dac_state);
  2010. qemu_get_8s(f, &s->dac_sub_index);
  2011. qemu_get_8s(f, &s->dac_read_index);
  2012. qemu_get_8s(f, &s->dac_write_index);
  2013. qemu_get_buffer(f, s->dac_cache, 3);
  2014. qemu_get_buffer(f, s->palette, 768);
  2015. s->bank_offset=qemu_get_be32(f);
  2016. is_vbe = qemu_get_byte(f);
  2017. #ifdef CONFIG_BOCHS_VBE
  2018. if (!is_vbe)
  2019. return -EINVAL;
  2020. qemu_get_be16s(f, &s->vbe_index);
  2021. for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
  2022. qemu_get_be16s(f, &s->vbe_regs[i]);
  2023. qemu_get_be32s(f, &s->vbe_start_addr);
  2024. qemu_get_be32s(f, &s->vbe_line_offset);
  2025. qemu_get_be32s(f, &s->vbe_bank_mask);
  2026. #else
  2027. if (is_vbe)
  2028. return -EINVAL;
  2029. #endif
  2030. /* force refresh */
  2031. s->graphic_mode = -1;
  2032. return 0;
  2033. }
  2034. typedef struct PCIVGAState {
  2035. PCIDevice dev;
  2036. VGAState vga_state;
  2037. } PCIVGAState;
  2038. void vga_dirty_log_start(VGAState *s)
  2039. {
  2040. if (kvm_enabled() && s->map_addr)
  2041. kvm_log_start(s->map_addr, s->map_end - s->map_addr);
  2042. if (kvm_enabled() && s->lfb_vram_mapped) {
  2043. kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
  2044. kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
  2045. }
  2046. }
  2047. void vga_dirty_log_stop(VGAState *s)
  2048. {
  2049. if (kvm_enabled() && s->map_addr)
  2050. kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
  2051. if (kvm_enabled() && s->lfb_vram_mapped) {
  2052. kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
  2053. kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
  2054. }
  2055. }
  2056. static void vga_map(PCIDevice *pci_dev, int region_num,
  2057. uint32_t addr, uint32_t size, int type)
  2058. {
  2059. PCIVGAState *d = (PCIVGAState *)pci_dev;
  2060. VGAState *s = &d->vga_state;
  2061. if (region_num == PCI_ROM_SLOT) {
  2062. cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
  2063. } else {
  2064. cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
  2065. }
  2066. s->map_addr = addr;
  2067. s->map_end = addr + VGA_RAM_SIZE;
  2068. vga_dirty_log_start(s);
  2069. }
  2070. void vga_common_init(VGAState *s, uint8_t *vga_ram_base,
  2071. ram_addr_t vga_ram_offset, int vga_ram_size)
  2072. {
  2073. int i, j, v, b;
  2074. for(i = 0;i < 256; i++) {
  2075. v = 0;
  2076. for(j = 0; j < 8; j++) {
  2077. v |= ((i >> j) & 1) << (j * 4);
  2078. }
  2079. expand4[i] = v;
  2080. v = 0;
  2081. for(j = 0; j < 4; j++) {
  2082. v |= ((i >> (2 * j)) & 3) << (j * 4);
  2083. }
  2084. expand2[i] = v;
  2085. }
  2086. for(i = 0; i < 16; i++) {
  2087. v = 0;
  2088. for(j = 0; j < 4; j++) {
  2089. b = ((i >> j) & 1);
  2090. v |= b << (2 * j);
  2091. v |= b << (2 * j + 1);
  2092. }
  2093. expand4to8[i] = v;
  2094. }
  2095. s->vram_ptr = vga_ram_base;
  2096. s->vram_offset = vga_ram_offset;
  2097. s->vram_size = vga_ram_size;
  2098. s->get_bpp = vga_get_bpp;
  2099. s->get_offsets = vga_get_offsets;
  2100. s->get_resolution = vga_get_resolution;
  2101. s->update = vga_update_display;
  2102. s->invalidate = vga_invalidate_display;
  2103. s->screen_dump = vga_screen_dump;
  2104. s->text_update = vga_update_text;
  2105. switch (vga_retrace_method) {
  2106. case VGA_RETRACE_DUMB:
  2107. s->retrace = vga_dumb_retrace;
  2108. s->update_retrace_info = vga_dumb_update_retrace_info;
  2109. break;
  2110. case VGA_RETRACE_PRECISE:
  2111. s->retrace = vga_precise_retrace;
  2112. s->update_retrace_info = vga_precise_update_retrace_info;
  2113. break;
  2114. }
  2115. vga_reset(s);
  2116. }
  2117. /* used by both ISA and PCI */
  2118. void vga_init(VGAState *s)
  2119. {
  2120. int vga_io_memory;
  2121. qemu_register_reset(vga_reset, s);
  2122. register_savevm("vga", 0, 2, vga_save, vga_load, s);
  2123. register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
  2124. register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
  2125. register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
  2126. register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
  2127. register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
  2128. register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
  2129. register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
  2130. register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
  2131. register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
  2132. register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
  2133. s->bank_offset = 0;
  2134. #ifdef CONFIG_BOCHS_VBE
  2135. #if defined (TARGET_I386)
  2136. register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
  2137. register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
  2138. register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
  2139. register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
  2140. /* old Bochs IO ports */
  2141. register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
  2142. register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
  2143. register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
  2144. register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
  2145. #else
  2146. register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
  2147. register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
  2148. register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
  2149. register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
  2150. #endif
  2151. #endif /* CONFIG_BOCHS_VBE */
  2152. vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
  2153. cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
  2154. vga_io_memory);
  2155. qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
  2156. }
  2157. /* Memory mapped interface */
  2158. static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
  2159. {
  2160. VGAState *s = opaque;
  2161. return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
  2162. }
  2163. static void vga_mm_writeb (void *opaque,
  2164. target_phys_addr_t addr, uint32_t value)
  2165. {
  2166. VGAState *s = opaque;
  2167. vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
  2168. }
  2169. static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
  2170. {
  2171. VGAState *s = opaque;
  2172. return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
  2173. }
  2174. static void vga_mm_writew (void *opaque,
  2175. target_phys_addr_t addr, uint32_t value)
  2176. {
  2177. VGAState *s = opaque;
  2178. vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
  2179. }
  2180. static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
  2181. {
  2182. VGAState *s = opaque;
  2183. return vga_ioport_read(s, addr >> s->it_shift);
  2184. }
  2185. static void vga_mm_writel (void *opaque,
  2186. target_phys_addr_t addr, uint32_t value)
  2187. {
  2188. VGAState *s = opaque;
  2189. vga_ioport_write(s, addr >> s->it_shift, value);
  2190. }
  2191. static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
  2192. &vga_mm_readb,
  2193. &vga_mm_readw,
  2194. &vga_mm_readl,
  2195. };
  2196. static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
  2197. &vga_mm_writeb,
  2198. &vga_mm_writew,
  2199. &vga_mm_writel,
  2200. };
  2201. static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
  2202. target_phys_addr_t ctrl_base, int it_shift)
  2203. {
  2204. int s_ioport_ctrl, vga_io_memory;
  2205. s->it_shift = it_shift;
  2206. s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
  2207. vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
  2208. register_savevm("vga", 0, 2, vga_save, vga_load, s);
  2209. cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
  2210. s->bank_offset = 0;
  2211. cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
  2212. qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
  2213. }
  2214. int isa_vga_init(uint8_t *vga_ram_base,
  2215. unsigned long vga_ram_offset, int vga_ram_size)
  2216. {
  2217. VGAState *s;
  2218. s = qemu_mallocz(sizeof(VGAState));
  2219. vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
  2220. vga_init(s);
  2221. s->ds = graphic_console_init(s->update, s->invalidate,
  2222. s->screen_dump, s->text_update, s);
  2223. #ifdef CONFIG_BOCHS_VBE
  2224. /* XXX: use optimized standard vga accesses */
  2225. cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
  2226. vga_ram_size, vga_ram_offset);
  2227. #endif
  2228. return 0;
  2229. }
  2230. int isa_vga_mm_init(uint8_t *vga_ram_base,
  2231. unsigned long vga_ram_offset, int vga_ram_size,
  2232. target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
  2233. int it_shift)
  2234. {
  2235. VGAState *s;
  2236. s = qemu_mallocz(sizeof(VGAState));
  2237. vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
  2238. vga_mm_init(s, vram_base, ctrl_base, it_shift);
  2239. s->ds = graphic_console_init(s->update, s->invalidate,
  2240. s->screen_dump, s->text_update, s);
  2241. #ifdef CONFIG_BOCHS_VBE
  2242. /* XXX: use optimized standard vga accesses */
  2243. cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
  2244. vga_ram_size, vga_ram_offset);
  2245. #endif
  2246. return 0;
  2247. }
  2248. static void pci_vga_write_config(PCIDevice *d,
  2249. uint32_t address, uint32_t val, int len)
  2250. {
  2251. PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
  2252. VGAState *s = &pvs->vga_state;
  2253. vga_dirty_log_stop(s);
  2254. pci_default_write_config(d, address, val, len);
  2255. vga_dirty_log_start(s);
  2256. }
  2257. int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base,
  2258. unsigned long vga_ram_offset, int vga_ram_size,
  2259. unsigned long vga_bios_offset, int vga_bios_size)
  2260. {
  2261. PCIVGAState *d;
  2262. VGAState *s;
  2263. uint8_t *pci_conf;
  2264. d = (PCIVGAState *)pci_register_device(bus, "VGA",
  2265. sizeof(PCIVGAState),
  2266. -1, NULL, pci_vga_write_config);
  2267. if (!d)
  2268. return -1;
  2269. s = &d->vga_state;
  2270. vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
  2271. vga_init(s);
  2272. s->ds = graphic_console_init(s->update, s->invalidate,
  2273. s->screen_dump, s->text_update, s);
  2274. s->pci_dev = &d->dev;
  2275. pci_conf = d->dev.config;
  2276. // dummy VGA (same as Bochs ID)
  2277. pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
  2278. pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
  2279. pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
  2280. pci_conf[0x0e] = 0x00; // header_type
  2281. /* XXX: vga_ram_size must be a power of two */
  2282. pci_register_io_region(&d->dev, 0, vga_ram_size,
  2283. PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
  2284. if (vga_bios_size != 0) {
  2285. unsigned int bios_total_size;
  2286. s->bios_offset = vga_bios_offset;
  2287. s->bios_size = vga_bios_size;
  2288. /* must be a power of two */
  2289. bios_total_size = 1;
  2290. while (bios_total_size < vga_bios_size)
  2291. bios_total_size <<= 1;
  2292. pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
  2293. PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
  2294. }
  2295. return 0;
  2296. }
  2297. /********************************************************/
  2298. /* vga screen dump */
  2299. static void vga_save_dpy_update(DisplayState *s,
  2300. int x, int y, int w, int h)
  2301. {
  2302. }
  2303. static void vga_save_dpy_resize(DisplayState *s)
  2304. {
  2305. }
  2306. static void vga_save_dpy_refresh(DisplayState *s)
  2307. {
  2308. }
  2309. int ppm_save(const char *filename, struct DisplaySurface *ds)
  2310. {
  2311. FILE *f;
  2312. uint8_t *d, *d1;
  2313. uint32_t v;
  2314. int y, x;
  2315. uint8_t r, g, b;
  2316. f = fopen(filename, "wb");
  2317. if (!f)
  2318. return -1;
  2319. fprintf(f, "P6\n%d %d\n%d\n",
  2320. ds->width, ds->height, 255);
  2321. d1 = ds->data;
  2322. for(y = 0; y < ds->height; y++) {
  2323. d = d1;
  2324. for(x = 0; x < ds->width; x++) {
  2325. if (ds->pf.bits_per_pixel == 32)
  2326. v = *(uint32_t *)d;
  2327. else
  2328. v = (uint32_t) (*(uint16_t *)d);
  2329. r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
  2330. (ds->pf.rmax + 1);
  2331. g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
  2332. (ds->pf.gmax + 1);
  2333. b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
  2334. (ds->pf.bmax + 1);
  2335. fputc(r, f);
  2336. fputc(g, f);
  2337. fputc(b, f);
  2338. d += ds->pf.bytes_per_pixel;
  2339. }
  2340. d1 += ds->linesize;
  2341. }
  2342. fclose(f);
  2343. return 0;
  2344. }
  2345. static void vga_screen_dump_blank(VGAState *s, const char *filename)
  2346. {
  2347. FILE *f;
  2348. unsigned int y, x, w, h;
  2349. unsigned char blank_sample[3] = { 0, 0, 0 };
  2350. w = s->last_scr_width;
  2351. h = s->last_scr_height;
  2352. f = fopen(filename, "wb");
  2353. if (!f)
  2354. return;
  2355. fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
  2356. for (y = 0; y < h; y++) {
  2357. for (x = 0; x < w; x++) {
  2358. fwrite(blank_sample, 3, 1, f);
  2359. }
  2360. }
  2361. fclose(f);
  2362. }
  2363. static void vga_screen_dump_common(VGAState *s, const char *filename,
  2364. int w, int h)
  2365. {
  2366. DisplayState *saved_ds, ds1, *ds = &ds1;
  2367. DisplayChangeListener dcl;
  2368. /* XXX: this is a little hackish */
  2369. vga_invalidate_display(s);
  2370. saved_ds = s->ds;
  2371. memset(ds, 0, sizeof(DisplayState));
  2372. memset(&dcl, 0, sizeof(DisplayChangeListener));
  2373. dcl.dpy_update = vga_save_dpy_update;
  2374. dcl.dpy_resize = vga_save_dpy_resize;
  2375. dcl.dpy_refresh = vga_save_dpy_refresh;
  2376. register_displaychangelistener(ds, &dcl);
  2377. ds->surface = qemu_create_displaysurface(w, h, 32, 4 * w);
  2378. s->ds = ds;
  2379. s->graphic_mode = -1;
  2380. vga_update_display(s);
  2381. ppm_save(filename, ds->surface);
  2382. qemu_free_displaysurface(ds->surface);
  2383. s->ds = saved_ds;
  2384. }
  2385. static void vga_screen_dump_graphic(VGAState *s, const char *filename)
  2386. {
  2387. int w, h;
  2388. s->get_resolution(s, &w, &h);
  2389. vga_screen_dump_common(s, filename, w, h);
  2390. }
  2391. static void vga_screen_dump_text(VGAState *s, const char *filename)
  2392. {
  2393. int w, h, cwidth, cheight;
  2394. vga_get_text_resolution(s, &w, &h, &cwidth, &cheight);
  2395. vga_screen_dump_common(s, filename, w * cwidth, h * cheight);
  2396. }
  2397. /* save the vga display in a PPM image even if no display is
  2398. available */
  2399. static void vga_screen_dump(void *opaque, const char *filename)
  2400. {
  2401. VGAState *s = (VGAState *)opaque;
  2402. if (!(s->ar_index & 0x20))
  2403. vga_screen_dump_blank(s, filename);
  2404. else if (s->gr[6] & 1)
  2405. vga_screen_dump_graphic(s, filename);
  2406. else
  2407. vga_screen_dump_text(s, filename);
  2408. vga_invalidate_display(s);
  2409. }