video.S 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014
  1. /* video.S
  2. *
  3. * Display adapter & video mode setup, version 2.13 (14-May-99)
  4. *
  5. * Copyright (C) 1995 -- 1998 Martin Mares <mj@ucw.cz>
  6. * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
  7. *
  8. * Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> May 1999
  9. *
  10. * For further information, look at Documentation/svga.txt.
  11. *
  12. */
  13. #include <linux/config.h> /* for CONFIG_VIDEO_* */
  14. /* Enable autodetection of SVGA adapters and modes. */
  15. #undef CONFIG_VIDEO_SVGA
  16. /* Enable autodetection of VESA modes */
  17. #define CONFIG_VIDEO_VESA
  18. /* Enable compacting of mode table */
  19. #define CONFIG_VIDEO_COMPACT
  20. /* Retain screen contents when switching modes */
  21. #define CONFIG_VIDEO_RETAIN
  22. /* Enable local mode list */
  23. #undef CONFIG_VIDEO_LOCAL
  24. /* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
  25. #undef CONFIG_VIDEO_400_HACK
  26. /* Hack that lets you force specific BIOS mode ID and specific dimensions */
  27. #undef CONFIG_VIDEO_GFX_HACK
  28. #define VIDEO_GFX_BIOS_AX 0x4f02 /* 800x600 on ThinkPad */
  29. #define VIDEO_GFX_BIOS_BX 0x0102
  30. #define VIDEO_GFX_DUMMY_RESOLUTION 0x6425 /* 100x37 */
  31. /* This code uses an extended set of video mode numbers. These include:
  32. * Aliases for standard modes
  33. * NORMAL_VGA (-1)
  34. * EXTENDED_VGA (-2)
  35. * ASK_VGA (-3)
  36. * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
  37. * of compatibility when extending the table. These are between 0x00 and 0xff.
  38. */
  39. #define VIDEO_FIRST_MENU 0x0000
  40. /* Standard BIOS video modes (BIOS number + 0x0100) */
  41. #define VIDEO_FIRST_BIOS 0x0100
  42. /* VESA BIOS video modes (VESA number + 0x0200) */
  43. #define VIDEO_FIRST_VESA 0x0200
  44. /* Video7 special modes (BIOS number + 0x0900) */
  45. #define VIDEO_FIRST_V7 0x0900
  46. /* Special video modes */
  47. #define VIDEO_FIRST_SPECIAL 0x0f00
  48. #define VIDEO_80x25 0x0f00
  49. #define VIDEO_8POINT 0x0f01
  50. #define VIDEO_80x43 0x0f02
  51. #define VIDEO_80x28 0x0f03
  52. #define VIDEO_CURRENT_MODE 0x0f04
  53. #define VIDEO_80x30 0x0f05
  54. #define VIDEO_80x34 0x0f06
  55. #define VIDEO_80x60 0x0f07
  56. #define VIDEO_GFX_HACK 0x0f08
  57. #define VIDEO_LAST_SPECIAL 0x0f09
  58. /* Video modes given by resolution */
  59. #define VIDEO_FIRST_RESOLUTION 0x1000
  60. /* The "recalculate timings" flag */
  61. #define VIDEO_RECALC 0x8000
  62. /* Positions of various video parameters passed to the kernel */
  63. /* (see also include/linux/tty.h) */
  64. #define PARAM_CURSOR_POS 0x00
  65. #define PARAM_VIDEO_PAGE 0x04
  66. #define PARAM_VIDEO_MODE 0x06
  67. #define PARAM_VIDEO_COLS 0x07
  68. #define PARAM_VIDEO_EGA_BX 0x0a
  69. #define PARAM_VIDEO_LINES 0x0e
  70. #define PARAM_HAVE_VGA 0x0f
  71. #define PARAM_FONT_POINTS 0x10
  72. #define PARAM_LFB_WIDTH 0x12
  73. #define PARAM_LFB_HEIGHT 0x14
  74. #define PARAM_LFB_DEPTH 0x16
  75. #define PARAM_LFB_BASE 0x18
  76. #define PARAM_LFB_SIZE 0x1c
  77. #define PARAM_LFB_LINELENGTH 0x24
  78. #define PARAM_LFB_COLORS 0x26
  79. #define PARAM_VESAPM_SEG 0x2e
  80. #define PARAM_VESAPM_OFF 0x30
  81. #define PARAM_LFB_PAGES 0x32
  82. #define PARAM_VESA_ATTRIB 0x34
  83. #define PARAM_CAPABILITIES 0x36
  84. /* Define DO_STORE according to CONFIG_VIDEO_RETAIN */
  85. #ifdef CONFIG_VIDEO_RETAIN
  86. #define DO_STORE call store_screen
  87. #else
  88. #define DO_STORE
  89. #endif /* CONFIG_VIDEO_RETAIN */
  90. # This is the main entry point called by setup.S
  91. # %ds *must* be pointing to the bootsector
  92. video: pushw %ds # We use different segments
  93. pushw %ds # FS contains original DS
  94. popw %fs
  95. pushw %cs # DS is equal to CS
  96. popw %ds
  97. pushw %cs # ES is equal to CS
  98. popw %es
  99. xorw %ax, %ax
  100. movw %ax, %gs # GS is zero
  101. cld
  102. call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA)
  103. #ifdef CONFIG_VIDEO_SELECT
  104. movw %fs:(0x01fa), %ax # User selected video mode
  105. cmpw $ASK_VGA, %ax # Bring up the menu
  106. jz vid2
  107. call mode_set # Set the mode
  108. jc vid1
  109. leaw badmdt, %si # Invalid mode ID
  110. call prtstr
  111. vid2: call mode_menu
  112. vid1:
  113. #ifdef CONFIG_VIDEO_RETAIN
  114. call restore_screen # Restore screen contents
  115. #endif /* CONFIG_VIDEO_RETAIN */
  116. call store_edid
  117. #endif /* CONFIG_VIDEO_SELECT */
  118. call mode_params # Store mode parameters
  119. popw %ds # Restore original DS
  120. ret
  121. # Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
  122. basic_detect:
  123. movb $0, %fs:(PARAM_HAVE_VGA)
  124. movb $0x12, %ah # Check EGA/VGA
  125. movb $0x10, %bl
  126. int $0x10
  127. movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel
  128. cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card.
  129. je basret
  130. incb adapter
  131. movw $0x1a00, %ax # Check EGA or VGA?
  132. int $0x10
  133. cmpb $0x1a, %al # 1a means VGA...
  134. jne basret # anything else is EGA.
  135. incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA
  136. incb adapter
  137. basret: ret
  138. # Store the video mode parameters for later usage by the kernel.
  139. # This is done by asking the BIOS except for the rows/columns
  140. # parameters in the default 80x25 mode -- these are set directly,
  141. # because some very obscure BIOSes supply insane values.
  142. mode_params:
  143. #ifdef CONFIG_VIDEO_SELECT
  144. cmpb $0, graphic_mode
  145. jnz mopar_gr
  146. #endif
  147. movb $0x03, %ah # Read cursor position
  148. xorb %bh, %bh
  149. int $0x10
  150. movw %dx, %fs:(PARAM_CURSOR_POS)
  151. movb $0x0f, %ah # Read page/mode/width
  152. int $0x10
  153. movw %bx, %fs:(PARAM_VIDEO_PAGE)
  154. movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width
  155. cmpb $0x7, %al # MDA/HGA => segment differs
  156. jnz mopar0
  157. movw $0xb000, video_segment
  158. mopar0: movw %gs:(0x485), %ax # Font size
  159. movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA)
  160. movw force_size, %ax # Forced size?
  161. orw %ax, %ax
  162. jz mopar1
  163. movb %ah, %fs:(PARAM_VIDEO_COLS)
  164. movb %al, %fs:(PARAM_VIDEO_LINES)
  165. ret
  166. mopar1: movb $25, %al
  167. cmpb $0, adapter # If we are on CGA/MDA/HGA, the
  168. jz mopar2 # screen must have 25 lines.
  169. movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS
  170. incb %al # location of max lines.
  171. mopar2: movb %al, %fs:(PARAM_VIDEO_LINES)
  172. ret
  173. #ifdef CONFIG_VIDEO_SELECT
  174. # Fetching of VESA frame buffer parameters
  175. mopar_gr:
  176. leaw modelist+1024, %di
  177. movb $0x23, %fs:(PARAM_HAVE_VGA)
  178. movw 16(%di), %ax
  179. movw %ax, %fs:(PARAM_LFB_LINELENGTH)
  180. movw 18(%di), %ax
  181. movw %ax, %fs:(PARAM_LFB_WIDTH)
  182. movw 20(%di), %ax
  183. movw %ax, %fs:(PARAM_LFB_HEIGHT)
  184. movb 25(%di), %al
  185. movb $0, %ah
  186. movw %ax, %fs:(PARAM_LFB_DEPTH)
  187. movb 29(%di), %al
  188. movb $0, %ah
  189. movw %ax, %fs:(PARAM_LFB_PAGES)
  190. movl 40(%di), %eax
  191. movl %eax, %fs:(PARAM_LFB_BASE)
  192. movl 31(%di), %eax
  193. movl %eax, %fs:(PARAM_LFB_COLORS)
  194. movl 35(%di), %eax
  195. movl %eax, %fs:(PARAM_LFB_COLORS+4)
  196. movw 0(%di), %ax
  197. movw %ax, %fs:(PARAM_VESA_ATTRIB)
  198. # get video mem size
  199. leaw modelist+1024, %di
  200. movw $0x4f00, %ax
  201. int $0x10
  202. xorl %eax, %eax
  203. movw 18(%di), %ax
  204. movl %eax, %fs:(PARAM_LFB_SIZE)
  205. # store mode capabilities
  206. movl 10(%di), %eax
  207. movl %eax, %fs:(PARAM_CAPABILITIES)
  208. # switching the DAC to 8-bit is for <= 8 bpp only
  209. movw %fs:(PARAM_LFB_DEPTH), %ax
  210. cmpw $8, %ax
  211. jg dac_done
  212. # get DAC switching capability
  213. xorl %eax, %eax
  214. movb 10(%di), %al
  215. testb $1, %al
  216. jz dac_set
  217. # attempt to switch DAC to 8-bit
  218. movw $0x4f08, %ax
  219. movw $0x0800, %bx
  220. int $0x10
  221. cmpw $0x004f, %ax
  222. jne dac_set
  223. movb %bh, dac_size # store actual DAC size
  224. dac_set:
  225. # set color size to DAC size
  226. movb dac_size, %al
  227. movb %al, %fs:(PARAM_LFB_COLORS+0)
  228. movb %al, %fs:(PARAM_LFB_COLORS+2)
  229. movb %al, %fs:(PARAM_LFB_COLORS+4)
  230. movb %al, %fs:(PARAM_LFB_COLORS+6)
  231. # set color offsets to 0
  232. movb $0, %fs:(PARAM_LFB_COLORS+1)
  233. movb $0, %fs:(PARAM_LFB_COLORS+3)
  234. movb $0, %fs:(PARAM_LFB_COLORS+5)
  235. movb $0, %fs:(PARAM_LFB_COLORS+7)
  236. dac_done:
  237. # get protected mode interface informations
  238. movw $0x4f0a, %ax
  239. xorw %bx, %bx
  240. xorw %di, %di
  241. int $0x10
  242. cmp $0x004f, %ax
  243. jnz no_pm
  244. movw %es, %fs:(PARAM_VESAPM_SEG)
  245. movw %di, %fs:(PARAM_VESAPM_OFF)
  246. no_pm: ret
  247. # The video mode menu
  248. mode_menu:
  249. leaw keymsg, %si # "Return/Space/Timeout" message
  250. call prtstr
  251. call flush
  252. nokey: call getkt
  253. cmpb $0x0d, %al # ENTER ?
  254. je listm # yes - manual mode selection
  255. cmpb $0x20, %al # SPACE ?
  256. je defmd1 # no - repeat
  257. call beep
  258. jmp nokey
  259. defmd1: ret # No mode chosen? Default 80x25
  260. listm: call mode_table # List mode table
  261. listm0: leaw name_bann, %si # Print adapter name
  262. call prtstr
  263. movw card_name, %si
  264. orw %si, %si
  265. jnz an2
  266. movb adapter, %al
  267. leaw old_name, %si
  268. orb %al, %al
  269. jz an1
  270. leaw ega_name, %si
  271. decb %al
  272. jz an1
  273. leaw vga_name, %si
  274. jmp an1
  275. an2: call prtstr
  276. leaw svga_name, %si
  277. an1: call prtstr
  278. leaw listhdr, %si # Table header
  279. call prtstr
  280. movb $0x30, %dl # DL holds mode number
  281. leaw modelist, %si
  282. lm1: cmpw $ASK_VGA, (%si) # End?
  283. jz lm2
  284. movb %dl, %al # Menu selection number
  285. call prtchr
  286. call prtsp2
  287. lodsw
  288. call prthw # Mode ID
  289. call prtsp2
  290. movb 0x1(%si), %al
  291. call prtdec # Rows
  292. movb $0x78, %al # the letter 'x'
  293. call prtchr
  294. lodsw
  295. call prtdec # Columns
  296. movb $0x0d, %al # New line
  297. call prtchr
  298. movb $0x0a, %al
  299. call prtchr
  300. incb %dl # Next character
  301. cmpb $0x3a, %dl
  302. jnz lm1
  303. movb $0x61, %dl
  304. jmp lm1
  305. lm2: leaw prompt, %si # Mode prompt
  306. call prtstr
  307. leaw edit_buf, %di # Editor buffer
  308. lm3: call getkey
  309. cmpb $0x0d, %al # Enter?
  310. jz lment
  311. cmpb $0x08, %al # Backspace?
  312. jz lmbs
  313. cmpb $0x20, %al # Printable?
  314. jc lm3
  315. cmpw $edit_buf+4, %di # Enough space?
  316. jz lm3
  317. stosb
  318. call prtchr
  319. jmp lm3
  320. lmbs: cmpw $edit_buf, %di # Backspace
  321. jz lm3
  322. decw %di
  323. movb $0x08, %al
  324. call prtchr
  325. call prtspc
  326. movb $0x08, %al
  327. call prtchr
  328. jmp lm3
  329. lment: movb $0, (%di)
  330. leaw crlft, %si
  331. call prtstr
  332. leaw edit_buf, %si
  333. cmpb $0, (%si) # Empty string = default mode
  334. jz lmdef
  335. cmpb $0, 1(%si) # One character = menu selection
  336. jz mnusel
  337. cmpw $0x6373, (%si) # "scan" => mode scanning
  338. jnz lmhx
  339. cmpw $0x6e61, 2(%si)
  340. jz lmscan
  341. lmhx: xorw %bx, %bx # Else => mode ID in hex
  342. lmhex: lodsb
  343. orb %al, %al
  344. jz lmuse1
  345. subb $0x30, %al
  346. jc lmbad
  347. cmpb $10, %al
  348. jc lmhx1
  349. subb $7, %al
  350. andb $0xdf, %al
  351. cmpb $10, %al
  352. jc lmbad
  353. cmpb $16, %al
  354. jnc lmbad
  355. lmhx1: shlw $4, %bx
  356. orb %al, %bl
  357. jmp lmhex
  358. lmuse1: movw %bx, %ax
  359. jmp lmuse
  360. mnusel: lodsb # Menu selection
  361. xorb %ah, %ah
  362. subb $0x30, %al
  363. jc lmbad
  364. cmpb $10, %al
  365. jc lmuse
  366. cmpb $0x61-0x30, %al
  367. jc lmbad
  368. subb $0x61-0x30-10, %al
  369. cmpb $36, %al
  370. jnc lmbad
  371. lmuse: call mode_set
  372. jc lmdef
  373. lmbad: leaw unknt, %si
  374. call prtstr
  375. jmp lm2
  376. lmscan: cmpb $0, adapter # Scanning only on EGA/VGA
  377. jz lmbad
  378. movw $0, mt_end # Scanning of modes is
  379. movb $1, scanning # done as new autodetection.
  380. call mode_table
  381. jmp listm0
  382. lmdef: ret
  383. # Additional parts of mode_set... (relative jumps, you know)
  384. setv7: # Video7 extended modes
  385. DO_STORE
  386. subb $VIDEO_FIRST_V7>>8, %bh
  387. movw $0x6f05, %ax
  388. int $0x10
  389. stc
  390. ret
  391. _setrec: jmp setrec # Ugly...
  392. _set_80x25: jmp set_80x25
  393. # Aliases for backward compatibility.
  394. setalias:
  395. movw $VIDEO_80x25, %ax
  396. incw %bx
  397. jz mode_set
  398. movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al
  399. incw %bx
  400. jnz setbad # Fall-through!
  401. # Setting of user mode (AX=mode ID) => CF=success
  402. mode_set:
  403. movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S
  404. movw %ax, %bx
  405. cmpb $0xff, %ah
  406. jz setalias
  407. testb $VIDEO_RECALC>>8, %ah
  408. jnz _setrec
  409. cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah
  410. jnc setres
  411. cmpb $VIDEO_FIRST_SPECIAL>>8, %ah
  412. jz setspc
  413. cmpb $VIDEO_FIRST_V7>>8, %ah
  414. jz setv7
  415. cmpb $VIDEO_FIRST_VESA>>8, %ah
  416. jnc check_vesa
  417. orb %ah, %ah
  418. jz setmenu
  419. decb %ah
  420. jz setbios
  421. setbad: clc
  422. movb $0, do_restore # The screen needn't be restored
  423. ret
  424. setvesa:
  425. DO_STORE
  426. subb $VIDEO_FIRST_VESA>>8, %bh
  427. movw $0x4f02, %ax # VESA BIOS mode set call
  428. int $0x10
  429. cmpw $0x004f, %ax # AL=4f if implemented
  430. jnz setbad # AH=0 if OK
  431. stc
  432. ret
  433. setbios:
  434. DO_STORE
  435. int $0x10 # Standard BIOS mode set call
  436. pushw %bx
  437. movb $0x0f, %ah # Check if really set
  438. int $0x10
  439. popw %bx
  440. cmpb %bl, %al
  441. jnz setbad
  442. stc
  443. ret
  444. setspc: xorb %bh, %bh # Set special mode
  445. cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
  446. jnc setbad
  447. addw %bx, %bx
  448. jmp *spec_inits(%bx)
  449. setmenu:
  450. orb %al, %al # 80x25 is an exception
  451. jz _set_80x25
  452. pushw %bx # Set mode chosen from menu
  453. call mode_table # Build the mode table
  454. popw %ax
  455. shlw $2, %ax
  456. addw %ax, %si
  457. cmpw %di, %si
  458. jnc setbad
  459. movw (%si), %ax # Fetch mode ID
  460. _m_s: jmp mode_set
  461. setres: pushw %bx # Set mode chosen by resolution
  462. call mode_table
  463. popw %bx
  464. xchgb %bl, %bh
  465. setr1: lodsw
  466. cmpw $ASK_VGA, %ax # End of the list?
  467. jz setbad
  468. lodsw
  469. cmpw %bx, %ax
  470. jnz setr1
  471. movw -4(%si), %ax # Fetch mode ID
  472. jmp _m_s
  473. check_vesa:
  474. leaw modelist+1024, %di
  475. subb $VIDEO_FIRST_VESA>>8, %bh
  476. movw %bx, %cx # Get mode information structure
  477. movw $0x4f01, %ax
  478. int $0x10
  479. addb $VIDEO_FIRST_VESA>>8, %bh
  480. cmpw $0x004f, %ax
  481. jnz setbad
  482. movb (%di), %al # Check capabilities.
  483. andb $0x19, %al
  484. cmpb $0x09, %al
  485. jz setvesa # This is a text mode
  486. movb (%di), %al # Check capabilities.
  487. andb $0x99, %al
  488. cmpb $0x99, %al
  489. jnz _setbad # Doh! No linear frame buffer.
  490. subb $VIDEO_FIRST_VESA>>8, %bh
  491. orw $0x4000, %bx # Use linear frame buffer
  492. movw $0x4f02, %ax # VESA BIOS mode set call
  493. int $0x10
  494. cmpw $0x004f, %ax # AL=4f if implemented
  495. jnz _setbad # AH=0 if OK
  496. movb $1, graphic_mode # flag graphic mode
  497. movb $0, do_restore # no screen restore
  498. stc
  499. ret
  500. _setbad: jmp setbad # Ugly...
  501. # Recalculate vertical display end registers -- this fixes various
  502. # inconsistencies of extended modes on many adapters. Called when
  503. # the VIDEO_RECALC flag is set in the mode ID.
  504. setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
  505. call mode_set
  506. jnc rct3
  507. movw %gs:(0x485), %ax # Font size in pixels
  508. movb %gs:(0x484), %bl # Number of rows
  509. incb %bl
  510. mulb %bl # Number of visible
  511. decw %ax # scan lines - 1
  512. movw $0x3d4, %dx
  513. movw %ax, %bx
  514. movb $0x12, %al # Lower 8 bits
  515. movb %bl, %ah
  516. outw %ax, %dx
  517. movb $0x07, %al # Bits 8 and 9 in the overflow register
  518. call inidx
  519. xchgb %al, %ah
  520. andb $0xbd, %ah
  521. shrb %bh
  522. jnc rct1
  523. orb $0x02, %ah
  524. rct1: shrb %bh
  525. jnc rct2
  526. orb $0x40, %ah
  527. rct2: movb $0x07, %al
  528. outw %ax, %dx
  529. stc
  530. rct3: ret
  531. # Table of routines for setting of the special modes.
  532. spec_inits:
  533. .word set_80x25
  534. .word set_8pixel
  535. .word set_80x43
  536. .word set_80x28
  537. .word set_current
  538. .word set_80x30
  539. .word set_80x34
  540. .word set_80x60
  541. .word set_gfx
  542. # Set the 80x25 mode. If already set, do nothing.
  543. set_80x25:
  544. movw $0x5019, force_size # Override possibly broken BIOS
  545. use_80x25:
  546. #ifdef CONFIG_VIDEO_400_HACK
  547. movw $0x1202, %ax # Force 400 scan lines
  548. movb $0x30, %bl
  549. int $0x10
  550. #else
  551. movb $0x0f, %ah # Get current mode ID
  552. int $0x10
  553. cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available
  554. jz st80 # on CGA/MDA/HGA and is also available on EGAM
  555. cmpw $0x5003, %ax # Unknown mode, force 80x25 color
  556. jnz force3
  557. st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25
  558. jz set80
  559. movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc.
  560. orb %al, %al # Some buggy BIOS'es set 0 rows
  561. jz set80
  562. cmpb $24, %al # It's hopefully correct
  563. jz set80
  564. #endif /* CONFIG_VIDEO_400_HACK */
  565. force3: DO_STORE
  566. movw $0x0003, %ax # Forced set
  567. int $0x10
  568. set80: stc
  569. ret
  570. # Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
  571. set_8pixel:
  572. DO_STORE
  573. call use_80x25 # The base is 80x25
  574. set_8pt:
  575. movw $0x1112, %ax # Use 8x8 font
  576. xorb %bl, %bl
  577. int $0x10
  578. movw $0x1200, %ax # Use alternate print screen
  579. movb $0x20, %bl
  580. int $0x10
  581. movw $0x1201, %ax # Turn off cursor emulation
  582. movb $0x34, %bl
  583. int $0x10
  584. movb $0x01, %ah # Define cursor scan lines 6-7
  585. movw $0x0607, %cx
  586. int $0x10
  587. set_current:
  588. stc
  589. ret
  590. # Set the 80x28 mode. This mode works on all VGA's, because it's a standard
  591. # 80x25 mode with 14-point fonts instead of 16-point.
  592. set_80x28:
  593. DO_STORE
  594. call use_80x25 # The base is 80x25
  595. set14: movw $0x1111, %ax # Use 9x14 font
  596. xorb %bl, %bl
  597. int $0x10
  598. movb $0x01, %ah # Define cursor scan lines 11-12
  599. movw $0x0b0c, %cx
  600. int $0x10
  601. stc
  602. ret
  603. # Set the 80x43 mode. This mode is works on all VGA's.
  604. # It's a 350-scanline mode with 8-pixel font.
  605. set_80x43:
  606. DO_STORE
  607. movw $0x1201, %ax # Set 350 scans
  608. movb $0x30, %bl
  609. int $0x10
  610. movw $0x0003, %ax # Reset video mode
  611. int $0x10
  612. jmp set_8pt # Use 8-pixel font
  613. # Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
  614. set_80x30:
  615. call use_80x25 # Start with real 80x25
  616. DO_STORE
  617. movw $0x3cc, %dx # Get CRTC port
  618. inb %dx, %al
  619. movb $0xd4, %dl
  620. rorb %al # Mono or color?
  621. jc set48a
  622. movb $0xb4, %dl
  623. set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7)
  624. call outidx
  625. movw $0x0b06, %ax # Vertical total
  626. call outidx
  627. movw $0x3e07, %ax # (Vertical) overflow
  628. call outidx
  629. movw $0xea10, %ax # Vertical sync start
  630. call outidx
  631. movw $0xdf12, %ax # Vertical display end
  632. call outidx
  633. movw $0xe715, %ax # Vertical blank start
  634. call outidx
  635. movw $0x0416, %ax # Vertical blank end
  636. call outidx
  637. pushw %dx
  638. movb $0xcc, %dl # Misc output register (read)
  639. inb %dx, %al
  640. movb $0xc2, %dl # (write)
  641. andb $0x0d, %al # Preserve clock select bits and color bit
  642. orb $0xe2, %al # Set correct sync polarity
  643. outb %al, %dx
  644. popw %dx
  645. movw $0x501e, force_size
  646. stc # That's all.
  647. ret
  648. # Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
  649. set_80x34:
  650. call set_80x30 # Set 480 scans
  651. call set14 # And 14-pt font
  652. movw $0xdb12, %ax # VGA vertical display end
  653. movw $0x5022, force_size
  654. setvde: call outidx
  655. stc
  656. ret
  657. # Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
  658. set_80x60:
  659. call set_80x30 # Set 480 scans
  660. call set_8pt # And 8-pt font
  661. movw $0xdf12, %ax # VGA vertical display end
  662. movw $0x503c, force_size
  663. jmp setvde
  664. # Special hack for ThinkPad graphics
  665. set_gfx:
  666. #ifdef CONFIG_VIDEO_GFX_HACK
  667. movw $VIDEO_GFX_BIOS_AX, %ax
  668. movw $VIDEO_GFX_BIOS_BX, %bx
  669. int $0x10
  670. movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size
  671. stc
  672. #endif
  673. ret
  674. #ifdef CONFIG_VIDEO_RETAIN
  675. # Store screen contents to temporary buffer.
  676. store_screen:
  677. cmpb $0, do_restore # Already stored?
  678. jnz stsr
  679. testb $CAN_USE_HEAP, loadflags # Have we space for storing?
  680. jz stsr
  681. pushw %ax
  682. pushw %bx
  683. pushw force_size # Don't force specific size
  684. movw $0, force_size
  685. call mode_params # Obtain params of current mode
  686. popw force_size
  687. movb %fs:(PARAM_VIDEO_LINES), %ah
  688. movb %fs:(PARAM_VIDEO_COLS), %al
  689. movw %ax, %bx # BX=dimensions
  690. mulb %ah
  691. movw %ax, %cx # CX=number of characters
  692. addw %ax, %ax # Calculate image size
  693. addw $modelist+1024+4, %ax
  694. cmpw heap_end_ptr, %ax
  695. jnc sts1 # Unfortunately, out of memory
  696. movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params
  697. leaw modelist+1024, %di
  698. stosw
  699. movw %bx, %ax
  700. stosw
  701. pushw %ds # Store the screen
  702. movw video_segment, %ds
  703. xorw %si, %si
  704. rep
  705. movsw
  706. popw %ds
  707. incb do_restore # Screen will be restored later
  708. sts1: popw %bx
  709. popw %ax
  710. stsr: ret
  711. # Restore screen contents from temporary buffer.
  712. restore_screen:
  713. cmpb $0, do_restore # Has the screen been stored?
  714. jz res1
  715. call mode_params # Get parameters of current mode
  716. movb %fs:(PARAM_VIDEO_LINES), %cl
  717. movb %fs:(PARAM_VIDEO_COLS), %ch
  718. leaw modelist+1024, %si # Screen buffer
  719. lodsw # Set cursor position
  720. movw %ax, %dx
  721. cmpb %cl, %dh
  722. jc res2
  723. movb %cl, %dh
  724. decb %dh
  725. res2: cmpb %ch, %dl
  726. jc res3
  727. movb %ch, %dl
  728. decb %dl
  729. res3: movb $0x02, %ah
  730. movb $0x00, %bh
  731. int $0x10
  732. lodsw # Display size
  733. movb %ah, %dl # DL=number of lines
  734. movb $0, %ah # BX=phys. length of orig. line
  735. movw %ax, %bx
  736. cmpb %cl, %dl # Too many?
  737. jc res4
  738. pushw %ax
  739. movb %dl, %al
  740. subb %cl, %al
  741. mulb %bl
  742. addw %ax, %si
  743. addw %ax, %si
  744. popw %ax
  745. movb %cl, %dl
  746. res4: cmpb %ch, %al # Too wide?
  747. jc res5
  748. movb %ch, %al # AX=width of src. line
  749. res5: movb $0, %cl
  750. xchgb %ch, %cl
  751. movw %cx, %bp # BP=width of dest. line
  752. pushw %es
  753. movw video_segment, %es
  754. xorw %di, %di # Move the data
  755. addw %bx, %bx # Convert BX and BP to _bytes_
  756. addw %bp, %bp
  757. res6: pushw %si
  758. pushw %di
  759. movw %ax, %cx
  760. rep
  761. movsw
  762. popw %di
  763. popw %si
  764. addw %bp, %di
  765. addw %bx, %si
  766. decb %dl
  767. jnz res6
  768. popw %es # Done
  769. res1: ret
  770. #endif /* CONFIG_VIDEO_RETAIN */
  771. # Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
  772. outidx: outb %al, %dx
  773. pushw %ax
  774. movb %ah, %al
  775. incw %dx
  776. outb %al, %dx
  777. decw %dx
  778. popw %ax
  779. ret
  780. # Build the table of video modes (stored after the setup.S code at the
  781. # `modelist' label. Each video mode record looks like:
  782. # .word MODE-ID (our special mode ID (see above))
  783. # .byte rows (number of rows)
  784. # .byte columns (number of columns)
  785. # Returns address of the end of the table in DI, the end is marked
  786. # with a ASK_VGA ID.
  787. mode_table:
  788. movw mt_end, %di # Already filled?
  789. orw %di, %di
  790. jnz mtab1x
  791. leaw modelist, %di # Store standard modes:
  792. movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL)
  793. stosl
  794. movb adapter, %al # CGA/MDA/HGA -- no more modes
  795. orb %al, %al
  796. jz mtabe
  797. decb %al
  798. jnz mtabv
  799. movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode
  800. stosl
  801. jmp mtabe
  802. mtab1x: jmp mtab1
  803. mtabv: leaw vga_modes, %si # All modes for std VGA
  804. movw $vga_modes_end-vga_modes, %cx
  805. rep # I'm unable to use movsw as I don't know how to store a half
  806. movsb # of the expression above to cx without using explicit shr.
  807. cmpb $0, scanning # Mode scan requested?
  808. jz mscan1
  809. call mode_scan
  810. mscan1:
  811. #ifdef CONFIG_VIDEO_LOCAL
  812. call local_modes
  813. #endif /* CONFIG_VIDEO_LOCAL */
  814. #ifdef CONFIG_VIDEO_VESA
  815. call vesa_modes # Detect VESA VGA modes
  816. #endif /* CONFIG_VIDEO_VESA */
  817. #ifdef CONFIG_VIDEO_SVGA
  818. cmpb $0, scanning # Bypass when scanning
  819. jnz mscan2
  820. call svga_modes # Detect SVGA cards & modes
  821. mscan2:
  822. #endif /* CONFIG_VIDEO_SVGA */
  823. mtabe:
  824. #ifdef CONFIG_VIDEO_COMPACT
  825. leaw modelist, %si
  826. movw %di, %dx
  827. movw %si, %di
  828. cmt1: cmpw %dx, %si # Scan all modes
  829. jz cmt2
  830. leaw modelist, %bx # Find in previous entries
  831. movw 2(%si), %cx
  832. cmt3: cmpw %bx, %si
  833. jz cmt4
  834. cmpw 2(%bx), %cx # Found => don't copy this entry
  835. jz cmt5
  836. addw $4, %bx
  837. jmp cmt3
  838. cmt4: movsl # Copy entry
  839. jmp cmt1
  840. cmt5: addw $4, %si # Skip entry
  841. jmp cmt1
  842. cmt2:
  843. #endif /* CONFIG_VIDEO_COMPACT */
  844. movw $ASK_VGA, (%di) # End marker
  845. movw %di, mt_end
  846. mtab1: leaw modelist, %si # SI=mode list, DI=list end
  847. ret0: ret
  848. # Modes usable on all standard VGAs
  849. vga_modes:
  850. .word VIDEO_8POINT
  851. .word 0x5032 # 80x50
  852. .word VIDEO_80x43
  853. .word 0x502b # 80x43
  854. .word VIDEO_80x28
  855. .word 0x501c # 80x28
  856. .word VIDEO_80x30
  857. .word 0x501e # 80x30
  858. .word VIDEO_80x34
  859. .word 0x5022 # 80x34
  860. .word VIDEO_80x60
  861. .word 0x503c # 80x60
  862. #ifdef CONFIG_VIDEO_GFX_HACK
  863. .word VIDEO_GFX_HACK
  864. .word VIDEO_GFX_DUMMY_RESOLUTION
  865. #endif
  866. vga_modes_end:
  867. # Detect VESA modes.
  868. #ifdef CONFIG_VIDEO_VESA
  869. vesa_modes:
  870. cmpb $2, adapter # VGA only
  871. jnz ret0
  872. movw %di, %bp # BP=original mode table end
  873. addw $0x200, %di # Buffer space
  874. movw $0x4f00, %ax # VESA Get card info call
  875. int $0x10
  876. movw %bp, %di
  877. cmpw $0x004f, %ax # Successful?
  878. jnz ret0
  879. cmpw $0x4556, 0x200(%di)
  880. jnz ret0
  881. cmpw $0x4153, 0x202(%di)
  882. jnz ret0
  883. movw $vesa_name, card_name # Set name to "VESA VGA"
  884. pushw %gs
  885. lgsw 0x20e(%di), %si # GS:SI=mode list
  886. movw $128, %cx # Iteration limit
  887. vesa1:
  888. # gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.
  889. # XXX: lodsw %gs:(%si), %ax # Get next mode in the list
  890. gs; lodsw
  891. cmpw $0xffff, %ax # End of the table?
  892. jz vesar
  893. cmpw $0x0080, %ax # Check validity of mode ID
  894. jc vesa2
  895. orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
  896. jz vesan # Certain BIOSes report 0x80-0xff!
  897. cmpw $0x0800, %ax
  898. jnc vesae
  899. vesa2: pushw %cx
  900. movw %ax, %cx # Get mode information structure
  901. movw $0x4f01, %ax
  902. int $0x10
  903. movw %cx, %bx # BX=mode number
  904. addb $VIDEO_FIRST_VESA>>8, %bh
  905. popw %cx
  906. cmpw $0x004f, %ax
  907. jnz vesan # Don't report errors (buggy BIOSES)
  908. movb (%di), %al # Check capabilities. We require
  909. andb $0x19, %al # a color text mode.
  910. cmpb $0x09, %al
  911. jnz vesan
  912. cmpw $0xb800, 8(%di) # Standard video memory address required
  913. jnz vesan
  914. testb $2, (%di) # Mode characteristics supplied?
  915. movw %bx, (%di) # Store mode number
  916. jz vesa3
  917. xorw %dx, %dx
  918. movw 0x12(%di), %bx # Width
  919. orb %bh, %bh
  920. jnz vesan
  921. movb %bl, 0x3(%di)
  922. movw 0x14(%di), %ax # Height
  923. orb %ah, %ah
  924. jnz vesan
  925. movb %al, 2(%di)
  926. mulb %bl
  927. cmpw $8193, %ax # Small enough for Linux console driver?
  928. jnc vesan
  929. jmp vesaok
  930. vesa3: subw $0x8108, %bx # This mode has no detailed info specified,
  931. jc vesan # so it must be a standard VESA mode.
  932. cmpw $5, %bx
  933. jnc vesan
  934. movw vesa_text_mode_table(%bx), %ax
  935. movw %ax, 2(%di)
  936. vesaok: addw $4, %di # The mode is valid. Store it.
  937. vesan: loop vesa1 # Next mode. Limit exceeded => error
  938. vesae: leaw vesaer, %si
  939. call prtstr
  940. movw %bp, %di # Discard already found modes.
  941. vesar: popw %gs
  942. ret
  943. # Dimensions of standard VESA text modes
  944. vesa_text_mode_table:
  945. .byte 60, 80 # 0108
  946. .byte 25, 132 # 0109
  947. .byte 43, 132 # 010A
  948. .byte 50, 132 # 010B
  949. .byte 60, 132 # 010C
  950. #endif /* CONFIG_VIDEO_VESA */
  951. # Scan for video modes. A bit dirty, but should work.
  952. mode_scan:
  953. movw $0x0100, %cx # Start with mode 0
  954. scm1: movb $0, %ah # Test the mode
  955. movb %cl, %al
  956. int $0x10
  957. movb $0x0f, %ah
  958. int $0x10
  959. cmpb %cl, %al
  960. jnz scm2 # Mode not set
  961. movw $0x3c0, %dx # Test if it's a text mode
  962. movb $0x10, %al # Mode bits
  963. call inidx
  964. andb $0x03, %al
  965. jnz scm2
  966. movb $0xce, %dl # Another set of mode bits
  967. movb $0x06, %al
  968. call inidx
  969. shrb %al
  970. jc scm2
  971. movb $0xd4, %dl # Cursor location
  972. movb $0x0f, %al
  973. call inidx
  974. orb %al, %al
  975. jnz scm2
  976. movw %cx, %ax # Ok, store the mode
  977. stosw
  978. movb %gs:(0x484), %al # Number of rows
  979. incb %al
  980. stosb
  981. movw %gs:(0x44a), %ax # Number of columns
  982. stosb
  983. scm2: incb %cl
  984. jns scm1
  985. movw $0x0003, %ax # Return back to mode 3
  986. int $0x10
  987. ret
  988. tstidx: outw %ax, %dx # OUT DX,AX and inidx
  989. inidx: outb %al, %dx # Read from indexed VGA register
  990. incw %dx # AL=index, DX=index reg port -> AL=data
  991. inb %dx, %al
  992. decw %dx
  993. ret
  994. # Try to detect type of SVGA card and supply (usually approximate) video
  995. # mode table for it.
  996. #ifdef CONFIG_VIDEO_SVGA
  997. svga_modes:
  998. leaw svga_table, %si # Test all known SVGA adapters
  999. dosvga: lodsw
  1000. movw %ax, %bp # Default mode table
  1001. orw %ax, %ax
  1002. jz didsv1
  1003. lodsw # Pointer to test routine
  1004. pushw %si
  1005. pushw %di
  1006. pushw %es
  1007. movw $0xc000, %bx
  1008. movw %bx, %es
  1009. call *%ax # Call test routine
  1010. popw %es
  1011. popw %di
  1012. popw %si
  1013. orw %bp, %bp
  1014. jz dosvga
  1015. movw %bp, %si # Found, copy the modes
  1016. movb svga_prefix, %ah
  1017. cpsvga: lodsb
  1018. orb %al, %al
  1019. jz didsv
  1020. stosw
  1021. movsw
  1022. jmp cpsvga
  1023. didsv: movw %si, card_name # Store pointer to card name
  1024. didsv1: ret
  1025. # Table of all known SVGA cards. For each card, we store a pointer to
  1026. # a table of video modes supported by the card and a pointer to a routine
  1027. # used for testing of presence of the card. The video mode table is always
  1028. # followed by the name of the card or the chipset.
  1029. svga_table:
  1030. .word ati_md, ati_test
  1031. .word oak_md, oak_test
  1032. .word paradise_md, paradise_test
  1033. .word realtek_md, realtek_test
  1034. .word s3_md, s3_test
  1035. .word chips_md, chips_test
  1036. .word video7_md, video7_test
  1037. .word cirrus5_md, cirrus5_test
  1038. .word cirrus6_md, cirrus6_test
  1039. .word cirrus1_md, cirrus1_test
  1040. .word ahead_md, ahead_test
  1041. .word everex_md, everex_test
  1042. .word genoa_md, genoa_test
  1043. .word trident_md, trident_test
  1044. .word tseng_md, tseng_test
  1045. .word 0
  1046. # Test routines and mode tables:
  1047. # S3 - The test algorithm was taken from the SuperProbe package
  1048. # for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org
  1049. s3_test:
  1050. movw $0x0f35, %cx # we store some constants in cl/ch
  1051. movw $0x03d4, %dx
  1052. movb $0x38, %al
  1053. call inidx
  1054. movb %al, %bh # store current CRT-register 0x38
  1055. movw $0x0038, %ax
  1056. call outidx # disable writing to special regs
  1057. movb %cl, %al # check whether we can write special reg 0x35
  1058. call inidx
  1059. movb %al, %bl # save the current value of CRT reg 0x35
  1060. andb $0xf0, %al # clear bits 0-3
  1061. movb %al, %ah
  1062. movb %cl, %al # and write it to CRT reg 0x35
  1063. call outidx
  1064. call inidx # now read it back
  1065. andb %ch, %al # clear the upper 4 bits
  1066. jz s3_2 # the first test failed. But we have a
  1067. movb %bl, %ah # second chance
  1068. movb %cl, %al
  1069. call outidx
  1070. jmp s3_1 # do the other tests
  1071. s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35
  1072. orb %bl, %ah # set the upper 4 bits of ah with the orig value
  1073. call outidx # write ...
  1074. call inidx # ... and reread
  1075. andb %cl, %al # turn off the upper 4 bits
  1076. pushw %ax
  1077. movb %bl, %ah # restore old value in register 0x35
  1078. movb %cl, %al
  1079. call outidx
  1080. popw %ax
  1081. cmpb %ch, %al # setting lower 4 bits was successful => bad
  1082. je no_s3 # writing is allowed => this is not an S3
  1083. s3_1: movw $0x4838, %ax # allow writing to special regs by putting
  1084. call outidx # magic number into CRT-register 0x38
  1085. movb %cl, %al # check whether we can write special reg 0x35
  1086. call inidx
  1087. movb %al, %bl
  1088. andb $0xf0, %al
  1089. movb %al, %ah
  1090. movb %cl, %al
  1091. call outidx
  1092. call inidx
  1093. andb %ch, %al
  1094. jnz no_s3 # no, we can't write => no S3
  1095. movw %cx, %ax
  1096. orb %bl, %ah
  1097. call outidx
  1098. call inidx
  1099. andb %ch, %al
  1100. pushw %ax
  1101. movb %bl, %ah # restore old value in register 0x35
  1102. movb %cl, %al
  1103. call outidx
  1104. popw %ax
  1105. cmpb %ch, %al
  1106. jne no_s31 # writing not possible => no S3
  1107. movb $0x30, %al
  1108. call inidx # now get the S3 id ...
  1109. leaw idS3, %di
  1110. movw $0x10, %cx
  1111. repne
  1112. scasb
  1113. je no_s31
  1114. movb %bh, %ah
  1115. movb $0x38, %al
  1116. jmp s3rest
  1117. no_s3: movb $0x35, %al # restore CRT register 0x35
  1118. movb %bl, %ah
  1119. call outidx
  1120. no_s31: xorw %bp, %bp # Detection failed
  1121. s3rest: movb %bh, %ah
  1122. movb $0x38, %al # restore old value of CRT register 0x38
  1123. jmp outidx
  1124. idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95
  1125. .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0
  1126. s3_md: .byte 0x54, 0x2b, 0x84
  1127. .byte 0x55, 0x19, 0x84
  1128. .byte 0
  1129. .ascii "S3"
  1130. .byte 0
  1131. # ATI cards.
  1132. ati_test:
  1133. leaw idati, %si
  1134. movw $0x31, %di
  1135. movw $0x09, %cx
  1136. repe
  1137. cmpsb
  1138. je atiok
  1139. xorw %bp, %bp
  1140. atiok: ret
  1141. idati: .ascii "761295520"
  1142. ati_md: .byte 0x23, 0x19, 0x84
  1143. .byte 0x33, 0x2c, 0x84
  1144. .byte 0x22, 0x1e, 0x64
  1145. .byte 0x21, 0x19, 0x64
  1146. .byte 0x58, 0x21, 0x50
  1147. .byte 0x5b, 0x1e, 0x50
  1148. .byte 0
  1149. .ascii "ATI"
  1150. .byte 0
  1151. # AHEAD
  1152. ahead_test:
  1153. movw $0x200f, %ax
  1154. movw $0x3ce, %dx
  1155. outw %ax, %dx
  1156. incw %dx
  1157. inb %dx, %al
  1158. cmpb $0x20, %al
  1159. je isahed
  1160. cmpb $0x21, %al
  1161. je isahed
  1162. xorw %bp, %bp
  1163. isahed: ret
  1164. ahead_md:
  1165. .byte 0x22, 0x2c, 0x84
  1166. .byte 0x23, 0x19, 0x84
  1167. .byte 0x24, 0x1c, 0x84
  1168. .byte 0x2f, 0x32, 0xa0
  1169. .byte 0x32, 0x22, 0x50
  1170. .byte 0x34, 0x42, 0x50
  1171. .byte 0
  1172. .ascii "Ahead"
  1173. .byte 0
  1174. # Chips & Tech.
  1175. chips_test:
  1176. movw $0x3c3, %dx
  1177. inb %dx, %al
  1178. orb $0x10, %al
  1179. outb %al, %dx
  1180. movw $0x104, %dx
  1181. inb %dx, %al
  1182. movb %al, %bl
  1183. movw $0x3c3, %dx
  1184. inb %dx, %al
  1185. andb $0xef, %al
  1186. outb %al, %dx
  1187. cmpb $0xa5, %bl
  1188. je cantok
  1189. xorw %bp, %bp
  1190. cantok: ret
  1191. chips_md:
  1192. .byte 0x60, 0x19, 0x84
  1193. .byte 0x61, 0x32, 0x84
  1194. .byte 0
  1195. .ascii "Chips & Technologies"
  1196. .byte 0
  1197. # Cirrus Logic 5X0
  1198. cirrus1_test:
  1199. movw $0x3d4, %dx
  1200. movb $0x0c, %al
  1201. outb %al, %dx
  1202. incw %dx
  1203. inb %dx, %al
  1204. movb %al, %bl
  1205. xorb %al, %al
  1206. outb %al, %dx
  1207. decw %dx
  1208. movb $0x1f, %al
  1209. outb %al, %dx
  1210. incw %dx
  1211. inb %dx, %al
  1212. movb %al, %bh
  1213. xorb %ah, %ah
  1214. shlb $4, %al
  1215. movw %ax, %cx
  1216. movb %bh, %al
  1217. shrb $4, %al
  1218. addw %ax, %cx
  1219. shlw $8, %cx
  1220. addw $6, %cx
  1221. movw %cx, %ax
  1222. movw $0x3c4, %dx
  1223. outw %ax, %dx
  1224. incw %dx
  1225. inb %dx, %al
  1226. andb %al, %al
  1227. jnz nocirr
  1228. movb %bh, %al
  1229. outb %al, %dx
  1230. inb %dx, %al
  1231. cmpb $0x01, %al
  1232. je iscirr
  1233. nocirr: xorw %bp, %bp
  1234. iscirr: movw $0x3d4, %dx
  1235. movb %bl, %al
  1236. xorb %ah, %ah
  1237. shlw $8, %ax
  1238. addw $0x0c, %ax
  1239. outw %ax, %dx
  1240. ret
  1241. cirrus1_md:
  1242. .byte 0x1f, 0x19, 0x84
  1243. .byte 0x20, 0x2c, 0x84
  1244. .byte 0x22, 0x1e, 0x84
  1245. .byte 0x31, 0x25, 0x64
  1246. .byte 0
  1247. .ascii "Cirrus Logic 5X0"
  1248. .byte 0
  1249. # Cirrus Logic 54XX
  1250. cirrus5_test:
  1251. movw $0x3c4, %dx
  1252. movb $6, %al
  1253. call inidx
  1254. movb %al, %bl # BL=backup
  1255. movw $6, %ax
  1256. call tstidx
  1257. cmpb $0x0f, %al
  1258. jne c5fail
  1259. movw $0x1206, %ax
  1260. call tstidx
  1261. cmpb $0x12, %al
  1262. jne c5fail
  1263. movb $0x1e, %al
  1264. call inidx
  1265. movb %al, %bh
  1266. movb %bh, %ah
  1267. andb $0xc0, %ah
  1268. movb $0x1e, %al
  1269. call tstidx
  1270. andb $0x3f, %al
  1271. jne c5xx
  1272. movb $0x1e, %al
  1273. movb %bh, %ah
  1274. orb $0x3f, %ah
  1275. call tstidx
  1276. xorb $0x3f, %al
  1277. andb $0x3f, %al
  1278. c5xx: pushf
  1279. movb $0x1e, %al
  1280. movb %bh, %ah
  1281. outw %ax, %dx
  1282. popf
  1283. je c5done
  1284. c5fail: xorw %bp, %bp
  1285. c5done: movb $6, %al
  1286. movb %bl, %ah
  1287. outw %ax, %dx
  1288. ret
  1289. cirrus5_md:
  1290. .byte 0x14, 0x19, 0x84
  1291. .byte 0x54, 0x2b, 0x84
  1292. .byte 0
  1293. .ascii "Cirrus Logic 54XX"
  1294. .byte 0
  1295. # Cirrus Logic 64XX -- no known extra modes, but must be identified, because
  1296. # it's misidentified by the Ahead test.
  1297. cirrus6_test:
  1298. movw $0x3ce, %dx
  1299. movb $0x0a, %al
  1300. call inidx
  1301. movb %al, %bl # BL=backup
  1302. movw $0xce0a, %ax
  1303. call tstidx
  1304. orb %al, %al
  1305. jne c2fail
  1306. movw $0xec0a, %ax
  1307. call tstidx
  1308. cmpb $0x01, %al
  1309. jne c2fail
  1310. movb $0xaa, %al
  1311. call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's.
  1312. shrb $4, %al
  1313. subb $4, %al
  1314. jz c6done
  1315. decb %al
  1316. jz c6done
  1317. subb $2, %al
  1318. jz c6done
  1319. decb %al
  1320. jz c6done
  1321. c2fail: xorw %bp, %bp
  1322. c6done: movb $0x0a, %al
  1323. movb %bl, %ah
  1324. outw %ax, %dx
  1325. ret
  1326. cirrus6_md:
  1327. .byte 0
  1328. .ascii "Cirrus Logic 64XX"
  1329. .byte 0
  1330. # Everex / Trident
  1331. everex_test:
  1332. movw $0x7000, %ax
  1333. xorw %bx, %bx
  1334. int $0x10
  1335. cmpb $0x70, %al
  1336. jne noevrx
  1337. shrw $4, %dx
  1338. cmpw $0x678, %dx
  1339. je evtrid
  1340. cmpw $0x236, %dx
  1341. jne evrxok
  1342. evtrid: leaw trident_md, %bp
  1343. evrxok: ret
  1344. noevrx: xorw %bp, %bp
  1345. ret
  1346. everex_md:
  1347. .byte 0x03, 0x22, 0x50
  1348. .byte 0x04, 0x3c, 0x50
  1349. .byte 0x07, 0x2b, 0x64
  1350. .byte 0x08, 0x4b, 0x64
  1351. .byte 0x0a, 0x19, 0x84
  1352. .byte 0x0b, 0x2c, 0x84
  1353. .byte 0x16, 0x1e, 0x50
  1354. .byte 0x18, 0x1b, 0x64
  1355. .byte 0x21, 0x40, 0xa0
  1356. .byte 0x40, 0x1e, 0x84
  1357. .byte 0
  1358. .ascii "Everex/Trident"
  1359. .byte 0
  1360. # Genoa.
  1361. genoa_test:
  1362. leaw idgenoa, %si # Check Genoa 'clues'
  1363. xorw %ax, %ax
  1364. movb %es:(0x37), %al
  1365. movw %ax, %di
  1366. movw $0x04, %cx
  1367. decw %si
  1368. decw %di
  1369. l1: incw %si
  1370. incw %di
  1371. movb (%si), %al
  1372. testb %al, %al
  1373. jz l2
  1374. cmpb %es:(%di), %al
  1375. l2: loope l1
  1376. orw %cx, %cx
  1377. je isgen
  1378. xorw %bp, %bp
  1379. isgen: ret
  1380. idgenoa: .byte 0x77, 0x00, 0x99, 0x66
  1381. genoa_md:
  1382. .byte 0x58, 0x20, 0x50
  1383. .byte 0x5a, 0x2a, 0x64
  1384. .byte 0x60, 0x19, 0x84
  1385. .byte 0x61, 0x1d, 0x84
  1386. .byte 0x62, 0x20, 0x84
  1387. .byte 0x63, 0x2c, 0x84
  1388. .byte 0x64, 0x3c, 0x84
  1389. .byte 0x6b, 0x4f, 0x64
  1390. .byte 0x72, 0x3c, 0x50
  1391. .byte 0x74, 0x42, 0x50
  1392. .byte 0x78, 0x4b, 0x64
  1393. .byte 0
  1394. .ascii "Genoa"
  1395. .byte 0
  1396. # OAK
  1397. oak_test:
  1398. leaw idoakvga, %si
  1399. movw $0x08, %di
  1400. movw $0x08, %cx
  1401. repe
  1402. cmpsb
  1403. je isoak
  1404. xorw %bp, %bp
  1405. isoak: ret
  1406. idoakvga: .ascii "OAK VGA "
  1407. oak_md: .byte 0x4e, 0x3c, 0x50
  1408. .byte 0x4f, 0x3c, 0x84
  1409. .byte 0x50, 0x19, 0x84
  1410. .byte 0x51, 0x2b, 0x84
  1411. .byte 0
  1412. .ascii "OAK"
  1413. .byte 0
  1414. # WD Paradise.
  1415. paradise_test:
  1416. leaw idparadise, %si
  1417. movw $0x7d, %di
  1418. movw $0x04, %cx
  1419. repe
  1420. cmpsb
  1421. je ispara
  1422. xorw %bp, %bp
  1423. ispara: ret
  1424. idparadise: .ascii "VGA="
  1425. paradise_md:
  1426. .byte 0x41, 0x22, 0x50
  1427. .byte 0x47, 0x1c, 0x84
  1428. .byte 0x55, 0x19, 0x84
  1429. .byte 0x54, 0x2c, 0x84
  1430. .byte 0
  1431. .ascii "Paradise"
  1432. .byte 0
  1433. # Trident.
  1434. trident_test:
  1435. movw $0x3c4, %dx
  1436. movb $0x0e, %al
  1437. outb %al, %dx
  1438. incw %dx
  1439. inb %dx, %al
  1440. xchgb %al, %ah
  1441. xorb %al, %al
  1442. outb %al, %dx
  1443. inb %dx, %al
  1444. xchgb %ah, %al
  1445. movb %al, %bl # Strange thing ... in the book this wasn't
  1446. andb $0x02, %bl # necessary but it worked on my card which
  1447. jz setb2 # is a trident. Without it the screen goes
  1448. # blurred ...
  1449. andb $0xfd, %al
  1450. jmp clrb2
  1451. setb2: orb $0x02, %al
  1452. clrb2: outb %al, %dx
  1453. andb $0x0f, %ah
  1454. cmpb $0x02, %ah
  1455. je istrid
  1456. xorw %bp, %bp
  1457. istrid: ret
  1458. trident_md:
  1459. .byte 0x50, 0x1e, 0x50
  1460. .byte 0x51, 0x2b, 0x50
  1461. .byte 0x52, 0x3c, 0x50
  1462. .byte 0x57, 0x19, 0x84
  1463. .byte 0x58, 0x1e, 0x84
  1464. .byte 0x59, 0x2b, 0x84
  1465. .byte 0x5a, 0x3c, 0x84
  1466. .byte 0
  1467. .ascii "Trident"
  1468. .byte 0
  1469. # Tseng.
  1470. tseng_test:
  1471. movw $0x3cd, %dx
  1472. inb %dx, %al # Could things be this simple ! :-)
  1473. movb %al, %bl
  1474. movb $0x55, %al
  1475. outb %al, %dx
  1476. inb %dx, %al
  1477. movb %al, %ah
  1478. movb %bl, %al
  1479. outb %al, %dx
  1480. cmpb $0x55, %ah
  1481. je istsen
  1482. isnot: xorw %bp, %bp
  1483. istsen: ret
  1484. tseng_md:
  1485. .byte 0x26, 0x3c, 0x50
  1486. .byte 0x2a, 0x28, 0x64
  1487. .byte 0x23, 0x19, 0x84
  1488. .byte 0x24, 0x1c, 0x84
  1489. .byte 0x22, 0x2c, 0x84
  1490. .byte 0x21, 0x3c, 0x84
  1491. .byte 0
  1492. .ascii "Tseng"
  1493. .byte 0
  1494. # Video7.
  1495. video7_test:
  1496. movw $0x3cc, %dx
  1497. inb %dx, %al
  1498. movw $0x3b4, %dx
  1499. andb $0x01, %al
  1500. jz even7
  1501. movw $0x3d4, %dx
  1502. even7: movb $0x0c, %al
  1503. outb %al, %dx
  1504. incw %dx
  1505. inb %dx, %al
  1506. movb %al, %bl
  1507. movb $0x55, %al
  1508. outb %al, %dx
  1509. inb %dx, %al
  1510. decw %dx
  1511. movb $0x1f, %al
  1512. outb %al, %dx
  1513. incw %dx
  1514. inb %dx, %al
  1515. movb %al, %bh
  1516. decw %dx
  1517. movb $0x0c, %al
  1518. outb %al, %dx
  1519. incw %dx
  1520. movb %bl, %al
  1521. outb %al, %dx
  1522. movb $0x55, %al
  1523. xorb $0xea, %al
  1524. cmpb %bh, %al
  1525. jne isnot
  1526. movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching
  1527. ret
  1528. video7_md:
  1529. .byte 0x40, 0x2b, 0x50
  1530. .byte 0x43, 0x3c, 0x50
  1531. .byte 0x44, 0x3c, 0x64
  1532. .byte 0x41, 0x19, 0x84
  1533. .byte 0x42, 0x2c, 0x84
  1534. .byte 0x45, 0x1c, 0x84
  1535. .byte 0
  1536. .ascii "Video 7"
  1537. .byte 0
  1538. # Realtek VGA
  1539. realtek_test:
  1540. leaw idrtvga, %si
  1541. movw $0x45, %di
  1542. movw $0x0b, %cx
  1543. repe
  1544. cmpsb
  1545. je isrt
  1546. xorw %bp, %bp
  1547. isrt: ret
  1548. idrtvga: .ascii "REALTEK VGA"
  1549. realtek_md:
  1550. .byte 0x1a, 0x3c, 0x50
  1551. .byte 0x1b, 0x19, 0x84
  1552. .byte 0x1c, 0x1e, 0x84
  1553. .byte 0x1d, 0x2b, 0x84
  1554. .byte 0x1e, 0x3c, 0x84
  1555. .byte 0
  1556. .ascii "REALTEK"
  1557. .byte 0
  1558. #endif /* CONFIG_VIDEO_SVGA */
  1559. # User-defined local mode table (VGA only)
  1560. #ifdef CONFIG_VIDEO_LOCAL
  1561. local_modes:
  1562. leaw local_mode_table, %si
  1563. locm1: lodsw
  1564. orw %ax, %ax
  1565. jz locm2
  1566. stosw
  1567. movsw
  1568. jmp locm1
  1569. locm2: ret
  1570. # This is the table of local video modes which can be supplied manually
  1571. # by the user. Each entry consists of mode ID (word) and dimensions
  1572. # (byte for column count and another byte for row count). These modes
  1573. # are placed before all SVGA and VESA modes and override them if table
  1574. # compacting is enabled. The table must end with a zero word followed
  1575. # by NUL-terminated video adapter name.
  1576. local_mode_table:
  1577. .word 0x0100 # Example: 40x25
  1578. .byte 25,40
  1579. .word 0
  1580. .ascii "Local"
  1581. .byte 0
  1582. #endif /* CONFIG_VIDEO_LOCAL */
  1583. # Read a key and return the ASCII code in al, scan code in ah
  1584. getkey: xorb %ah, %ah
  1585. int $0x16
  1586. ret
  1587. # Read a key with a timeout of 30 seconds.
  1588. # The hardware clock is used to get the time.
  1589. getkt: call gettime
  1590. addb $30, %al # Wait 30 seconds
  1591. cmpb $60, %al
  1592. jl lminute
  1593. subb $60, %al
  1594. lminute:
  1595. movb %al, %cl
  1596. again: movb $0x01, %ah
  1597. int $0x16
  1598. jnz getkey # key pressed, so get it
  1599. call gettime
  1600. cmpb %cl, %al
  1601. jne again
  1602. movb $0x20, %al # timeout, return `space'
  1603. ret
  1604. # Flush the keyboard buffer
  1605. flush: movb $0x01, %ah
  1606. int $0x16
  1607. jz empty
  1608. xorb %ah, %ah
  1609. int $0x16
  1610. jmp flush
  1611. empty: ret
  1612. # Print hexadecimal number.
  1613. prthw: pushw %ax
  1614. movb %ah, %al
  1615. call prthb
  1616. popw %ax
  1617. prthb: pushw %ax
  1618. shrb $4, %al
  1619. call prthn
  1620. popw %ax
  1621. andb $0x0f, %al
  1622. prthn: cmpb $0x0a, %al
  1623. jc prth1
  1624. addb $0x07, %al
  1625. prth1: addb $0x30, %al
  1626. jmp prtchr
  1627. # Print decimal number in al
  1628. prtdec: pushw %ax
  1629. pushw %cx
  1630. xorb %ah, %ah
  1631. movb $0x0a, %cl
  1632. idivb %cl
  1633. cmpb $0x09, %al
  1634. jbe lt100
  1635. call prtdec
  1636. jmp skip10
  1637. lt100: addb $0x30, %al
  1638. call prtchr
  1639. skip10: movb %ah, %al
  1640. addb $0x30, %al
  1641. call prtchr
  1642. popw %cx
  1643. popw %ax
  1644. ret
  1645. store_edid:
  1646. #ifdef CONFIG_FB_FIRMWARE_EDID
  1647. pushw %es # just save all registers
  1648. pushw %ax
  1649. pushw %bx
  1650. pushw %cx
  1651. pushw %dx
  1652. pushw %di
  1653. pushw %fs
  1654. popw %es
  1655. movl $0x13131313, %eax # memset block with 0x13
  1656. movw $32, %cx
  1657. movw $0x140, %di
  1658. cld
  1659. rep
  1660. stosl
  1661. movw $0x4f15, %ax # do VBE/DDC
  1662. movw $0x01, %bx
  1663. movw $0x00, %cx
  1664. movw $0x00, %dx
  1665. movw $0x140, %di
  1666. int $0x10
  1667. popw %di # restore all registers
  1668. popw %dx
  1669. popw %cx
  1670. popw %bx
  1671. popw %ax
  1672. popw %es
  1673. #endif
  1674. ret
  1675. # VIDEO_SELECT-only variables
  1676. mt_end: .word 0 # End of video mode table if built
  1677. edit_buf: .space 6 # Line editor buffer
  1678. card_name: .word 0 # Pointer to adapter name
  1679. scanning: .byte 0 # Performing mode scan
  1680. do_restore: .byte 0 # Screen contents altered during mode change
  1681. svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes
  1682. graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
  1683. dac_size: .byte 6 # DAC bit depth
  1684. # Status messages
  1685. keymsg: .ascii "Press <RETURN> to see video modes available, "
  1686. .ascii "<SPACE> to continue or wait 30 secs"
  1687. .byte 0x0d, 0x0a, 0
  1688. listhdr: .byte 0x0d, 0x0a
  1689. .ascii "Mode: COLSxROWS:"
  1690. crlft: .byte 0x0d, 0x0a, 0
  1691. prompt: .byte 0x0d, 0x0a
  1692. .asciz "Enter mode number or `scan': "
  1693. unknt: .asciz "Unknown mode ID. Try again."
  1694. badmdt: .ascii "You passed an undefined mode number."
  1695. .byte 0x0d, 0x0a, 0
  1696. vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
  1697. .ascii "report to <mj@ucw.cz>."
  1698. .byte 0x0d, 0x0a, 0
  1699. old_name: .asciz "CGA/MDA/HGA"
  1700. ega_name: .asciz "EGA"
  1701. svga_name: .ascii " "
  1702. vga_name: .asciz "VGA"
  1703. vesa_name: .asciz "VESA"
  1704. name_bann: .asciz "Video adapter: "
  1705. #endif /* CONFIG_VIDEO_SELECT */
  1706. # Other variables:
  1707. adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA
  1708. video_segment: .word 0xb800 # Video memory segment
  1709. force_size: .word 0 # Use this size instead of the one in BIOS vars