📄 video.s
字号:
jz set80 cmpb $24, %al # It's hopefully correct jz set80#endif /* CONFIG_VIDEO_400_HACK */force3: DO_STORE movw $0x0003, %ax # Forced set int $0x10set80: stc ret# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.set_8pixel: DO_STORE call use_80x25 # The base is 80x25set_8pt: movw $0x1112, %ax # Use 8x8 font xorb %bl, %bl int $0x10 movw $0x1200, %ax # Use alternate print screen movb $0x20, %bl int $0x10 movw $0x1201, %ax # Turn off cursor emulation movb $0x34, %bl int $0x10 movb $0x01, %ah # Define cursor scan lines 6-7 movw $0x0607, %cx int $0x10set_current: stc ret# Set the 80x28 mode. This mode works on all VGA's, because it's a standard# 80x25 mode with 14-point fonts instead of 16-point.set_80x28: DO_STORE call use_80x25 # The base is 80x25set14: movw $0x1111, %ax # Use 9x14 font xorb %bl, %bl int $0x10 movb $0x01, %ah # Define cursor scan lines 11-12 movw $0x0b0c, %cx int $0x10 stc ret# Set the 80x43 mode. This mode is works on all VGA's.# It's a 350-scanline mode with 8-pixel font.set_80x43: DO_STORE movw $0x1201, %ax # Set 350 scans movb $0x30, %bl int $0x10 movw $0x0003, %ax # Reset video mode int $0x10 jmp set_8pt # Use 8-pixel font# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.set_80x30: call use_80x25 # Start with real 80x25 DO_STORE movw $0x3cc, %dx # Get CRTC port inb %dx, %al movb $0xd4, %dl rorb %al # Mono or color? jc set48a movb $0xb4, %dlset48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7) call outidx movw $0x0b06, %ax # Vertical total call outidx movw $0x3e07, %ax # (Vertical) overflow call outidx movw $0xea10, %ax # Vertical sync start call outidx movw $0xdf12, %ax # Vertical display end call outidx movw $0xe715, %ax # Vertical blank start call outidx movw $0x0416, %ax # Vertical blank end call outidx pushw %dx movb $0xcc, %dl # Misc output register (read) inb %dx, %al movb $0xc2, %dl # (write) andb $0x0d, %al # Preserve clock select bits and color bit orb $0xe2, %al # Set correct sync polarity outb %al, %dx popw %dx movw $0x501e, force_size stc # That's all. ret# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.set_80x34: call set_80x30 # Set 480 scans call set14 # And 14-pt font movw $0xdb12, %ax # VGA vertical display end movw $0x5022, force_sizesetvde: call outidx stc ret# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.set_80x60: call set_80x30 # Set 480 scans call set_8pt # And 8-pt font movw $0xdf12, %ax # VGA vertical display end movw $0x503c, force_size jmp setvde# Special hack for ThinkPad graphicsset_gfx:#ifdef CONFIG_VIDEO_GFX_HACK movw $VIDEO_GFX_BIOS_AX, %ax movw $VIDEO_GFX_BIOS_BX, %bx int $0x10 movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size stc#endif ret#ifdef CONFIG_VIDEO_RETAIN# Store screen contents to temporary buffer.store_screen: cmpb $0, do_restore # Already stored? jnz stsr testb $CAN_USE_HEAP, loadflags # Have we space for storing? jz stsr pushw %ax pushw %bx pushw force_size # Don't force specific size movw $0, force_size call mode_params # Obtain params of current mode popw force_size movb %fs:(PARAM_VIDEO_LINES), %ah movb %fs:(PARAM_VIDEO_COLS), %al movw %ax, %bx # BX=dimensions mulb %ah movw %ax, %cx # CX=number of characters addw %ax, %ax # Calculate image size addw $modelist+1024+4, %ax cmpw heap_end_ptr, %ax jnc sts1 # Unfortunately, out of memory movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params leaw modelist+1024, %di stosw movw %bx, %ax stosw pushw %ds # Store the screen movw video_segment, %ds xorw %si, %si rep movsw popw %ds incb do_restore # Screen will be restored latersts1: popw %bx popw %axstsr: ret# Restore screen contents from temporary buffer.restore_screen: cmpb $0, do_restore # Has the screen been stored? jz res1 call mode_params # Get parameters of current mode movb %fs:(PARAM_VIDEO_LINES), %cl movb %fs:(PARAM_VIDEO_COLS), %ch leaw modelist+1024, %si # Screen buffer lodsw # Set cursor position movw %ax, %dx cmpb %cl, %dh jc res2 movb %cl, %dh decb %dhres2: cmpb %ch, %dl jc res3 movb %ch, %dl decb %dlres3: movb $0x02, %ah movb $0x00, %bh int $0x10 lodsw # Display size movb %ah, %dl # DL=number of lines movb $0, %ah # BX=phys. length of orig. line movw %ax, %bx cmpb %cl, %dl # Too many? jc res4 pushw %ax movb %dl, %al subb %cl, %al mulb %bl addw %ax, %si addw %ax, %si popw %ax movb %cl, %dlres4: cmpb %ch, %al # Too wide? jc res5 movb %ch, %al # AX=width of src. lineres5: movb $0, %cl xchgb %ch, %cl movw %cx, %bp # BP=width of dest. line pushw %es movw video_segment, %es xorw %di, %di # Move the data addw %bx, %bx # Convert BX and BP to _bytes_ addw %bp, %bpres6: pushw %si pushw %di movw %ax, %cx rep movsw popw %di popw %si addw %bp, %di addw %bx, %si decb %dl jnz res6 popw %es # Doneres1: ret#endif /* CONFIG_VIDEO_RETAIN */# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)outidx: outb %al, %dx pushw %ax movb %ah, %al incw %dx outb %al, %dx decw %dx popw %ax ret# Build the table of video modes (stored after the setup.S code at the# `modelist' label. Each video mode record looks like:# .word MODE-ID (our special mode ID (see above))# .byte rows (number of rows)# .byte columns (number of columns)# Returns address of the end of the table in DI, the end is marked# with a ASK_VGA ID.mode_table: movw mt_end, %di # Already filled? orw %di, %di jnz mtab1x leaw modelist, %di # Store standard modes: movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL) stosl movb adapter, %al # CGA/MDA/HGA -- no more modes orb %al, %al jz mtabe decb %al jnz mtabv movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode stosl jmp mtabemtab1x: jmp mtab1mtabv: leaw vga_modes, %si # All modes for std VGA movw $vga_modes_end-vga_modes, %cx rep # I'm unable to use movsw as I don't know how to store a half movsb # of the expression above to cx without using explicit shr. cmpb $0, scanning # Mode scan requested? jz mscan1 call mode_scanmscan1:#ifdef CONFIG_VIDEO_LOCAL call local_modes#endif /* CONFIG_VIDEO_LOCAL */#ifdef CONFIG_VIDEO_VESA call vesa_modes # Detect VESA VGA modes#endif /* CONFIG_VIDEO_VESA */#ifdef CONFIG_VIDEO_SVGA cmpb $0, scanning # Bypass when scanning jnz mscan2 call svga_modes # Detect SVGA cards & modesmscan2:#endif /* CONFIG_VIDEO_SVGA */mtabe:#ifdef CONFIG_VIDEO_COMPACT leaw modelist, %si movw %di, %dx movw %si, %dicmt1: cmpw %dx, %si # Scan all modes jz cmt2 leaw modelist, %bx # Find in previous entries movw 2(%si), %cxcmt3: cmpw %bx, %si jz cmt4 cmpw 2(%bx), %cx # Found => don't copy this entry jz cmt5 addw $4, %bx jmp cmt3cmt4: movsl # Copy entry jmp cmt1cmt5: addw $4, %si # Skip entry jmp cmt1cmt2:#endif /* CONFIG_VIDEO_COMPACT */ movw $ASK_VGA, (%di) # End marker movw %di, mt_endmtab1: leaw modelist, %si # SI=mode list, DI=list endret0: ret# Modes usable on all standard VGAsvga_modes: .word VIDEO_8POINT .word 0x5032 # 80x50 .word VIDEO_80x43 .word 0x502b # 80x43 .word VIDEO_80x28 .word 0x501c # 80x28 .word VIDEO_80x30 .word 0x501e # 80x30 .word VIDEO_80x34 .word 0x5022 # 80x34 .word VIDEO_80x60 .word 0x503c # 80x60#ifdef CONFIG_VIDEO_GFX_HACK .word VIDEO_GFX_HACK .word VIDEO_GFX_DUMMY_RESOLUTION#endifvga_modes_end:# Detect VESA modes.#ifdef CONFIG_VIDEO_VESAvesa_modes: cmpb $2, adapter # VGA only jnz ret0 movw %di, %bp # BP=original mode table end addw $0x200, %di # Buffer space movw $0x4f00, %ax # VESA Get card info call int $0x10 movw %bp, %di cmpw $0x004f, %ax # Successful? jnz ret0 cmpw $0x4556, 0x200(%di) jnz ret0 cmpw $0x4153, 0x202(%di) jnz ret0 movw $vesa_name, card_name # Set name to "VESA VGA" pushw %gs lgsw 0x20e(%di), %si # GS:SI=mode list movw $128, %cx # Iteration limitvesa1:# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst.# XXX: lodsw %gs:(%si), %ax # Get next mode in the list gs; lodsw cmpw $0xffff, %ax # End of the table? jz vesar cmpw $0x0080, %ax # Check validity of mode ID jc vesa2 orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff jz vesan # Certain BIOSes report 0x80-0xff! cmpw $0x0800, %ax jnc vesaevesa2: pushw %cx movw %ax, %cx # Get mode information structure movw $0x4f01, %ax int $0x10 movw %cx, %bx # BX=mode number addb $VIDEO_FIRST_VESA>>8, %bh popw %cx cmpw $0x004f, %ax jnz vesan # Don't report errors (buggy BIOSES) movb (%di), %al # Check capabilities. We require andb $0x19, %al # a color text mode. cmpb $0x09, %al jnz vesan cmpw $0xb800, 8(%di) # Standard video memory address required jnz vesan testb $2, (%di) # Mode characteristics supplied? movw %bx, (%di) # Store mode number jz vesa3 xorw %dx, %dx movw 0x12(%di), %bx # Width orb %bh, %bh jnz vesan movb %bl, 0x3(%di) movw 0x14(%di), %ax # Height orb %ah, %ah jnz vesan movb %al, 2(%di) mulb %bl cmpw $8193, %ax # Small enough for Linux console driver? jnc vesan jmp vesaokvesa3: subw $0x8108, %bx # This mode has no detailed info specified, jc vesan # so it must be a standard VESA mode. cmpw $5, %bx jnc vesan movw vesa_text_mode_table(%bx), %ax movw %ax, 2(%di)vesaok: addw $4, %di # The mode is valid. Store it.vesan: loop vesa1 # Next mode. Limit exceeded => errorvesae: leaw vesaer, %si call prtstr movw %bp, %di # Discard already found modes.vesar: popw %gs ret# Dimensions of standard VESA text modesvesa_text_mode_table: .byte 60, 80 # 0108 .byte 25, 132 # 0109 .byte 43, 132 # 010A .byte 50, 132 # 010B .byte 60, 132 # 010C#endif /* CONFIG_VIDEO_VESA */# Scan for video modes. A bit dirty, but should work.mode_scan: movw $0x0100, %cx # Start with mode 0scm1: movb $0, %ah # Test the mode movb %cl, %al int $0x10 movb $0x0f, %ah int $0x10 cmpb %cl, %al jnz scm2 # Mode not set movw $0x3c0, %dx # Test if it's a text mode movb $0x10, %al # Mode bits call inidx andb $0x03, %al jnz scm2 movb $0xce, %dl # Another set of mode bits movb $0x06, %al call inidx shrb %al jc scm2 movb $0xd4, %dl # Cursor location movb $0x0f, %al call inidx orb %al, %al jnz scm2 movw %cx, %ax # Ok, store the mode stosw movb %gs:(0x484), %al # Number of rows incb %al stosb movw %gs:(0x44a), %ax # Number of columns stosbscm2: incb %cl jns scm1 movw $0x0003, %ax # Return back to mode 3 int $0x10 rettstidx: outw %ax, %dx # OUT DX,AX and inidxinidx: outb %al, %dx # Read from indexed VGA register incw %dx # AL=index, DX=index reg port -> AL=data inb %dx, %al decw %dx ret# Try to detect type of SVGA card and supply (usually approximate) video# mode table for it.#ifdef CONFIG_VIDEO_SVGAsvga_modes: leaw svga_table, %si # Test all known SVGA adaptersdosvga: lodsw movw %ax, %bp # Default mode table orw %ax, %ax jz didsv1 lodsw # Pointer to test routine pushw %si pushw %di pushw %es movw $0xc000, %bx movw %bx, %es call *%ax # Call test routine popw %es popw %di popw %si orw %bp, %bp jz dosvga movw %bp, %si # Found, copy the modes movb svga_prefix, %ahcpsvga: lodsb orb %al, %al jz didsv stosw movsw jmp cpsvgadidsv: movw %si, card_name # Store pointer to card namedidsv1: ret# Table of all known SVGA cards. For each card, we store a pointer to# a table of video modes supported by the card and a pointer to a routine# used for testing of presence of the card. The video mode table is always# followed by the name of the card or the chipset.svga_table: .word ati_md, ati_test .word oak_md, oak_test .word paradise_md, paradise_test .word realtek_md, realtek_test .word s3_md, s3_test .word chips_md, chips_test .word video7_md, video7_test .word cirrus5_md, cirrus5_test .word cirrus6_md, cirrus6_test .word cirrus1_md, cirrus1_test .word ahead_md, ahead_test .word everex_md, everex_test .word genoa_md, genoa_test .word trident_md, trident_test .word tseng_md, tseng_test .word 0# Test routines and mode tables:# S3 - The test algorithm was taken from the SuperProbe package# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.orgs3_test: movw $0x0f35, %cx # we store some constants in cl/ch movw $0x03d4, %dx movb $0x38, %al call inidx movb %al, %bh # store current CRT-register 0x38 movw $0x0038, %ax call outidx # disable writing to special regs movb %cl, %al # check whether we can write special reg 0x35 call inidx movb %al, %bl # save the current value of CRT reg 0x35 andb $0xf0, %al # clear bits 0-3 movb %al, %ah movb %cl, %al # and write it to CRT reg 0x35 call outidx call inidx # now read it back andb %ch, %al # clear the upper 4 bits jz s3_2 # the first test failed. But we have a movb %bl, %ah # second chance movb %cl, %al call outidx jmp s3_1 # do the other testss3_2: movw %cx, %ax # load ah with 0xf and al with 0x35 orb %bl, %ah # set the upper 4 bits of ah with the orig value call outidx # write ... call inidx # ... and reread andb %cl, %al # turn off the upper 4 bits pushw %ax movb %bl, %ah # restore old value in register 0x35 movb %cl, %al call outidx popw %ax cmpb %ch, %al # setting lower 4 bits was successful => bad je no_s3 # writing is allowed => this is not an S3s3_1: movw $0x4838, %ax # allow writing to special regs by putting call outidx # magic number into CRT-register 0x38 movb %cl, %al # check whether we can write special reg 0x35 call inidx movb %al, %bl andb $0xf0, %al movb %al, %ah movb %cl, %al call outidx call inidx andb %ch, %al jnz no_s3 # no, we can't write => no S3 movw %cx, %ax orb %bl, %ah call outidx call inidx andb %ch, %al pushw %ax movb %bl, %ah # restore old value in register 0x35 movb %cl, %al call outidx popw %ax cmpb %ch, %al jne no_s31 # writing not possible => no S3 movb $0x30, %al call inidx # now get the S3 id ... leaw idS3, %di movw $0x10, %cx repne scasb je no_s31 movb %bh, %ah movb $0x38, %al jmp s3restno_s3: movb $0x35, %al # restore CRT register 0x35 movb %bl, %ah call outidxno_s31: xorw %bp, %bp # Detection faileds3rest: movb %bh, %ah movb $0x38, %al # restore old value of CRT register 0x38 jmp outidxidS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95 .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0s3_md: .byte 0x54, 0x2b, 0x84 .byte 0x55, 0x19, 0x84 .byte 0 .ascii "S3" .byte 0# ATI cards.ati_test: leaw idati, %si movw $0x31, %di movw $0x09, %cx repe cmpsb je atiok xorw %bp, %bp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -