The CRTC Interface Essential aspects of display page 80-column by 25-row text

advertisement
The CRTC Interface
Essential aspects of display page
and cursor control for standard
80-column by 25-row text
Motivation
• When a UNIX application wishes to write a
text message to the display, and then wait
for a keyboard-response from the user, the
application will want a ‘cursor’ to be visible
at the position where the next keystroke is
going to be echoed
• EXAMPLE: Please type a number:
We expect a blinking cursor to appear here
But it’s tedious to program…
• To write code that draws a blinking cursor
on the screen would be a time-consuming
chore for both programmer and processor:
– You have to repeatedly ‘draw’ and then ‘hide’
– You have to setup careful timing controls
– Your program-loop will keep the CPU busy!
• Fortunately the video system’s hardware is
able to handle this tedious chore for you!
Info the CRTC engine needs
• The display hardware already knows how
to do the timing for normal cursor blinking
(i.e., usually about two blinks per second)
• Software only needs to tell the hardware a
few specific pieces of information:
– Where does the cursor appear (row, column)?
– How large is the cursor? Where does it start
and end within the 8x16 character-cell?
– Which region of display-memory is visible?
Hardware registers
• The CRT Controller is a peripheral chip
• It implements 25 standard CRTC registers
• Access to these registers is accomplished
via a multiplexing scheme which uses just
two I/O port-addresses for color text:
address-port: 0x03D4
data-port:
0x03D5
How it works
• The multiplexing scheme for access to the
CRTC registers was designed to function
as a two-step operation:
– First, specify which register is to be accessed
(by writing the register’s index to port 0x3D4)
– Then, read (or write) to the specified register
(by inputting, or outputting, at port 0x3D5)
• But a multi-step scheme is problematic for
preemptive multitasking (also it is slow!)
A useful optimization
• To improve the multiplexing scheme when
writing values to CRTC registers, the CPU
is able to perform the two steps in a single
‘atomic’ fetch-execute cycle:
mov
mov
outw
$0x03D4, %dx
$0xFF14, %ax
%ax, %dx
• Here the ‘outw’ instruction will write AL to
port $0x03D4 and AH to port $0x03D5
Cursor-related CRTC registers
• For text-mode cursor-control, we are concerned
with just 6 (of the 25) standard CRTC registers:
• Index 0x0A: CURSOR_START
• Index 0x0B: CURSOR_END
• Index 0x0C: START_ADDRESS_HI
• Index 0x0D: START_ADDRESS_LO
• Index 0x0E: CURSOR_LOCATION_HI
• Index 0x0F:
CURSOR_LOCATION_LO
8x16 character box
Cursor_start = 12
Cursor_end = 13
scanline 0
scanline 1
scanline 2
scanline 3
scanline 4
scanline 5
scanline 6
scanline 7
scanline 8
scanline 9
scanline 10
scanline 11
scanline 12
scanline 13
scanline 14
scanline 15
CURSOR START/END
7
6
Index 0x0A:
5
disable
4
3
2
1
0
starting_scanline
CURSOR_START REGISTER
7
Index 0x0B:
6
5
skew
4
3
2
1
0
ending_scanline
CURSOR_END REGISTER
NOTE: The ‘skew’ capability works by delaying the cursor’s appearance for
0, 1, 2, or 3 character-cells (i.e., shifting the cursor toward the right). When
Is this useful? We couldn’t find any examples. Recommend skew be zero.
Organization of the VRAM
4KB
Page 7
4KB
Page 6
4KB
Page 5
4KB
Page 4
4KB
Page 3
4KB
Page 2
4KB
Page 1
4KB
Page 0
Base_Address = 0xB8000
Changing the visual page
7
6
5
4
3
2
1
START_ADDRESS_HI
register-index 0x0C
Programming example:
0
7
6
5
4
3
2
1
START_ADDRESS_LO
register-index 0x0D
# switches display to vram page 5
# the word-offset for page 5 is 0x2800 (= 5 * 2048)
mov
$0x03D4, %dx
# port-address in register DX
mov
$0x280C, %ax
# value=0x28, register=0x0C
out
%ax, %dx
# write value to CRTC register
mov
$0x000D, %ax
# value=0x00, register=0x0D
out
%ax, %dx
# write value to CRTC register
0
Moving the CRT’s cursor
7
6
5
4
3
2
1
0
CURSOR_LOCATION_HI
register-index 0x0E
Programming example:
mov
mov
imul
add
mov
mov
out
mov
mov
out
7
6
5
4
3
2
1
0
CURSOR_LOCATION_LO
register-index 0x0F
// moves cursor to row 5, column 9, on page 0
$0x03D4, %dx
$5, %bx
$80, %bx
$9, %bx
%bh, %ah
$0x0E, %al
%ax, %dx
%bl, %ah
$0x0F, %al
%ax, %dx
// port-address in register DX
// row-number
// times cells-per-row
// plus column-number
// cursor offset’s MSB
// CURSOR_HI index
// write value to CRTC register
// cursor offset’s LSB
// CURSOR_LO index
// write value to CRTC register
Scrolling the screen
• Here’s a code-fragment that will scroll the
contents of vram page 0 up by one line:
mov
mov
mov
mov
mov
cld
mov
rep
mov
mov
rep
$0xB800, %ax
%ax, %ds
%ax, %es
$0, %di
$160, %si
$3840, %cx
movsb
$0x0720, %ax
$80, %cx
stosw
// address vram page 0
// with DS register
// also ES register
// destination is the top line
// source is one line lower
// do forward copying
// 24 times 160
// perform the copying
// blank character w/color
// characters on bottom line
// fill final line with blanks
Linux uses hardware scrolling
• The value of the CRT START_ADDRESS
is reprogrammed, to change the region of
visible vram by one line (i.e., add #80)
• So instead of subdividing vram into eight
4KB pages, the entire 32KB vram is one
continuous page, but only partially visible
• To scroll up by one line, Linux adds $80 to
the value of the CRT_START_ADDRESS
The ROM-BIOS variables
• Several variables in the ROM-BIOS DATA
AREA are used by the VIDEO ROM-BIOS
routines (i.e., int-0x10) to keep track of the
currently visible page and of the positions
of the cursors on each of the eight pages
• The locations of these variables are part of
the IBM-PC ROM-BIOS standard, and as
such they are widely documented
Standard data-addresses
0x449 (byte) current video mode-number
0x44A (word) number of columns on screen
0x44C (word) current page-size (in bytes)
0x44E (word) current page-address
0x450 (byte array) cursor-positions (col,row)
0x460 byte-pair) cursor type (END, START)
0x462 (byte) current display page-number
0x463 (word) CRTC base i/o port-address
Real-mode INT-0x10 services
• Function 0x00: set_display_mode
• Function 0x01: set_cursor_type
• Function 0x02: set_cursor_position
• Function 0x03: get_cursor_position_and_type
• Function 0x05: select_new_video_page
• Function 0x06: scroll_current_page_up
• Function 0x07: scroll_current_page_down
• Function 0x08: read_char_and_attrib_from_screen
• Function 0x09: write_char_and_attrib_to_screen
• Function 0x0A: write char_only_to_screen
• Function 0x0E: write_teletype_to_active_page
• Function 0x0F: return_video_status
• Function 0x13: write_string
NOTE: These ROM-BIOS services are not available in protected-mode
Cursor-movement demo
• To illustrate reprogramming of the six CRT
controller registers, we wrote ‘arrowpad.s’
• It lets the user control the cursor position
and visible page by using arrow-keys
• It also changes the height of the cursor
• An unusual feature (not recommended) is
its use of “polled mode” keyboard deviceprogramming (instead of “interrupt-driven”)
Polling the status-register
• The keyboard controller’s interrupt is masked
• The keyboard controller’s status-register is read
and reread in a tight loop until bit #0 gets set,
indicating that a key was pressed (or released)
and hence the output-buffer register is now “full”
• So then the output-buffer register is read by the
CPU to get the key’s “scancode”
• For the arrow-keys, the cursor will get moved
• Other keys are just ignored (except ESCAPE)
Disadvantage of polling
• Almost all of the CPU’s time is consumed
by continually reading the status-register
• So this would not be a good design to use
in writing a multitasking operating system!
• On the other hand, for single-tasking it has
the advantage of not requiring an Interrupt
Service Routine to be written, so the demo
code we write can be shorter and simpler
Another noteworthy feature
• The ‘arrowpad.s’ demo uses a ‘jump-table’
to dispatch control quickly to appropriate
subroutines, based on a variable’s value
• This is a similar programming situation to
using a ‘switch’ statement in C/C++
• The jump-table avoids the long chain of
‘compare-and-branch’ statements for all
the various possible cases that can occur
In-Class exercise
• To insure your mastery of the jump-table
concept, and cement your grasp of how
the CRTC START_ADDRESS registers
are programmed, try modifying the demo
to incorporate these additional actions:
when one of the function-keys F1-F7 is
pressed, the display is switched to the
correspondingly numbered display-page
Download