Rev 522 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
44 | pj | 1 | /* Project: OSLib |
2 | * Description: The OS Construction Kit |
||
3 | * Date: 1.6.2000 |
||
4 | * Idea by: Luca Abeni & Gerardo Lamastra |
||
5 | * |
||
6 | * OSLib is an SO project aimed at developing a common, easy-to-use |
||
7 | * low-level infrastructure for developing OS kernels and Embedded |
||
8 | * Applications; it partially derives from the HARTIK project but it |
||
9 | * currently is independently developed. |
||
10 | * |
||
11 | * OSLib is distributed under GPL License, and some of its code has |
||
12 | * been derived from the Linux kernel source; also some important |
||
13 | * ideas come from studying the DJGPP go32 extender. |
||
14 | * |
||
15 | * We acknowledge the Linux Community, Free Software Foundation, |
||
16 | * D.J. Delorie and all the other developers who believe in the |
||
17 | * freedom of software and ideas. |
||
18 | * |
||
19 | * For legalese, check out the included GPL license. |
||
20 | */ |
||
21 | |||
22 | /* Console output functions */ |
||
23 | |||
24 | #include <ll/i386/hw-data.h> |
||
25 | #include <ll/i386/hw-instr.h> |
||
26 | #include <ll/i386/cons.h> |
||
27 | /* #include <xsys.h>*/ |
||
1689 | fabio | 28 | #include <arch/i386/string.h> |
29 | #include <arch/i386/stdlib.h> |
||
30 | #include <arch/i386/stdio.h> |
||
31 | #include <arch/stdarg.h> |
||
44 | pj | 32 | |
33 | FILE(Cons1); |
||
34 | /* CGA compatible registers value */ |
||
35 | |||
36 | #define CURSOR_POS_MSB 0x0E |
||
37 | #define CURSOR_POS_LSB 0x0F |
||
38 | #define CURSOR_START 0x0A |
||
39 | #define CURSOR_END 0x0B |
||
40 | |||
41 | /* CGA compatible registers */ |
||
42 | |||
43 | #define CGA_INDEX_REG 0x3D4 |
||
44 | #define CGA_DATA_REG 0x3D5 |
||
45 | |||
46 | /* Standard tab size */ |
||
47 | |||
48 | #define TAB_SIZE 8 |
||
49 | |||
50 | /* Store bios settings */ |
||
51 | |||
52 | static unsigned char bios_start,bios_end; |
||
53 | BYTE bios_x, bios_y, bios_attr; |
||
54 | |||
55 | /* MG */ |
||
56 | extern int cons_columns; /* number of screen columns */ |
||
57 | extern int cons_rows; /* number of screen rows */ |
||
58 | |||
59 | /* Access directly to video & BIOS memory through linear addressing */ |
||
60 | |||
61 | /* Active video page-buffer */ |
||
62 | #define PAGE_SIZE 2048 |
||
63 | |||
64 | int active_page = 0; |
||
65 | int visual_page = 0; |
||
66 | |||
67 | void bios_save(void) |
||
68 | { |
||
69 | /* This function must be called to init CONSole output */ |
||
70 | #if 1 |
||
71 | /* MG */ |
||
72 | cons_columns=lmempeekw((LIN_ADDR)0x0044a); |
||
73 | cons_rows=lmempeekb((LIN_ADDR)0x00484)+1; |
||
74 | |||
75 | bios_attr = lmempeekb((LIN_ADDR)0xB8000 + cons_columns * 2 -1); |
||
76 | bios_x = lmempeekb((LIN_ADDR)0x00450); |
||
77 | bios_y = lmempeekb((LIN_ADDR)0x00451); |
||
78 | bios_end = lmempeekb((LIN_ADDR)0x00460); |
||
79 | bios_start = lmempeekb((LIN_ADDR)0x00461); |
||
80 | active_page = visual_page = 0; |
||
81 | #else |
||
82 | LIN_ADDR p; |
||
83 | |||
84 | p = (LIN_ADDR)(0xB8000 + 159); |
||
85 | bios_attr = *p; |
||
86 | p = (LIN_ADDR)0x00450; |
||
87 | bios_x = *p; |
||
88 | p = (LIN_ADDR)0x00451; |
||
89 | bios_y = *p; |
||
90 | p = (LIN_ADDR)0x00460; |
||
91 | bios_end = *p; |
||
92 | p = (LIN_ADDR)0x00461; |
||
93 | bios_start = *p; |
||
94 | active_page = visual_page = 0; |
||
95 | #endif |
||
96 | } |
||
97 | |||
98 | void cursor(int start,int end) |
||
99 | { |
||
100 | /* Same thing as above; Set cursor scan line */ |
||
101 | outp(CGA_INDEX_REG, CURSOR_START); |
||
102 | outp(CGA_DATA_REG, start); |
||
103 | outp(CGA_INDEX_REG, CURSOR_END); |
||
104 | outp(CGA_DATA_REG, end); |
||
105 | } |
||
106 | |||
107 | void bios_restore(void) |
||
108 | { |
||
109 | lmempokeb((LIN_ADDR)0x00450,bios_x); |
||
110 | lmempokeb((LIN_ADDR)0x00451,bios_y); |
||
111 | place(bios_x,bios_y); |
||
112 | cursor(bios_start, bios_end); |
||
113 | } |
||
114 | |||
115 | void place(int x,int y) |
||
116 | { |
||
117 | unsigned short cursor_word = x + y*cons_columns + active_page*PAGE_SIZE; |
||
118 | /* Set cursor position */ |
||
119 | /* CGA is programmed writing first the Index register */ |
||
120 | /* to specify what internal register we are accessing */ |
||
121 | /* Then we load the Data register with the wanted val */ |
||
122 | outp(CGA_INDEX_REG,CURSOR_POS_LSB); |
||
123 | outp(CGA_DATA_REG,cursor_word & 0xFF); |
||
124 | outp(CGA_INDEX_REG,CURSOR_POS_MSB); |
||
125 | outp(CGA_DATA_REG,(cursor_word >> 8) & 0xFF); |
||
126 | /* Adjust temporary cursor bios position */ |
||
127 | bios_x = x; |
||
128 | bios_y = y; |
||
129 | } |
||
130 | |||
131 | |||
132 | void _scroll(char attr,int x1,int y1,int x2,int y2) |
||
133 | { |
||
134 | register int x,y; |
||
135 | WORD xattr = attr << 8,w; |
||
136 | LIN_ADDR v = (LIN_ADDR)(0xB8000 + active_page*(2*PAGE_SIZE)); |
||
137 | |||
138 | for (y = y1+1; y <= y2; y++) |
||
139 | for (x = x1; x <= x2; x++) { |
||
140 | w = lmempeekw((LIN_ADDR)(v + 2*(y*cons_columns+x))); |
||
141 | lmempokew((LIN_ADDR)(v + 2*((y-1)*cons_columns+x)),w); |
||
142 | } |
||
143 | for (x = x1; x <= x2; x++) |
||
144 | lmempokew((LIN_ADDR)(v + 2*((y-1)*cons_columns+x)),xattr); |
||
145 | } |
||
146 | |||
230 | giacomo | 147 | #define OPTIMIZED |
148 | #ifdef OPTIMIZED |
||
149 | |||
44 | pj | 150 | void scroll(void) |
151 | { |
||
230 | giacomo | 152 | |
153 | int x; |
||
154 | WORD xattr = bios_attr << 8; |
||
155 | LIN_ADDR v = (LIN_ADDR)(0xB8000 + active_page*(2*PAGE_SIZE)); |
||
156 | |||
157 | memcpy((LIN_ADDR)(v), |
||
158 | (LIN_ADDR)(v + 2*cons_columns), |
||
159 | cons_columns*(cons_rows-1)*2); |
||
160 | |||
161 | for (x = 0; x <= cons_columns-1; x++) |
||
162 | lmempokew((LIN_ADDR)(v + 2*((cons_rows-1)*cons_columns+x)),xattr); |
||
163 | |||
164 | } |
||
165 | |||
166 | #else |
||
167 | |||
168 | void scroll(void) |
||
169 | { |
||
44 | pj | 170 | _scroll(bios_attr,0,0,(cons_columns-1),(cons_rows-1)); |
171 | } |
||
172 | |||
230 | giacomo | 173 | #endif |
174 | |||
44 | pj | 175 | void cputc(char c) |
176 | { |
||
177 | static unsigned short scan_x,x,y; |
||
178 | LIN_ADDR v = (LIN_ADDR)(0xB8000 + active_page*(2*PAGE_SIZE)); |
||
522 | mauro | 179 | |
44 | pj | 180 | x = bios_x; |
181 | y = bios_y; |
||
182 | switch (c) { |
||
183 | case '\t' : x += 8; |
||
522 | mauro | 184 | if (x == (cons_columns-1)) { |
44 | pj | 185 | x = 0; |
522 | mauro | 186 | if (y >= (cons_rows-1)) scroll(); |
44 | pj | 187 | else y++; |
188 | } else { |
||
189 | scan_x = 0; |
||
190 | while ((scan_x+8) < x) scan_x += 8; |
||
191 | x = scan_x; |
||
192 | } |
||
193 | break; |
||
194 | case '\n' : x = 0; |
||
522 | mauro | 195 | if (y >= (cons_rows-1)) scroll(); |
44 | pj | 196 | else y++; |
197 | break; |
||
198 | case '\b' : x--; |
||
199 | lmempokeb((LIN_ADDR)(v + 2*(x + y*cons_columns)),' '); |
||
200 | x++; |
||
201 | break; |
||
202 | default : lmempokeb((LIN_ADDR)(v + 2*(x + y*cons_columns)),c); |
||
203 | x++; |
||
522 | mauro | 204 | if (x == (cons_columns-1)) { |
44 | pj | 205 | x = 0; |
522 | mauro | 206 | if (y >= (cons_rows-1)) scroll(); |
44 | pj | 207 | else y++; |
208 | } |
||
209 | } |
||
210 | place(x,y); |
||
522 | mauro | 211 | |
44 | pj | 212 | } |
213 | |||
214 | void cputs(char *s) |
||
215 | { |
||
216 | char c; |
||
230 | giacomo | 217 | |
44 | pj | 218 | while (*s != '\0') { |
219 | c = *s++; |
||
220 | cputc(c); |
||
221 | } |
||
230 | giacomo | 222 | |
44 | pj | 223 | } |