Rev 522 |
Go to most recent revision |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/* Project: OSLib
* Description: The OS Construction Kit
* Date: 1.6.2000
* Idea by: Luca Abeni & Gerardo Lamastra
*
* OSLib is an SO project aimed at developing a common, easy-to-use
* low-level infrastructure for developing OS kernels and Embedded
* Applications; it partially derives from the HARTIK project but it
* currently is independently developed.
*
* OSLib is distributed under GPL License, and some of its code has
* been derived from the Linux kernel source; also some important
* ideas come from studying the DJGPP go32 extender.
*
* We acknowledge the Linux Community, Free Software Foundation,
* D.J. Delorie and all the other developers who believe in the
* freedom of software and ideas.
*
* For legalese, check out the included GPL license.
*/
/* Console output functions */
#include <ll/i386/hw-data.h>
#include <ll/i386/hw-instr.h>
#include <ll/i386/cons.h>
/* #include <xsys.h>*/
#include <ll/i386/string.h>
#include <ll/i386/stdlib.h>
#include <ll/i386/stdio.h>
#include <ll/stdarg.h>
FILE
(Cons1
);
/* CGA compatible registers value */
#define CURSOR_POS_MSB 0x0E
#define CURSOR_POS_LSB 0x0F
#define CURSOR_START 0x0A
#define CURSOR_END 0x0B
/* CGA compatible registers */
#define CGA_INDEX_REG 0x3D4
#define CGA_DATA_REG 0x3D5
/* Standard tab size */
#define TAB_SIZE 8
/* Store bios settings */
static unsigned char bios_start
,bios_end
;
BYTE bios_x
, bios_y
, bios_attr
;
/* MG */
extern int cons_columns
; /* number of screen columns */
extern int cons_rows
; /* number of screen rows */
/* Access directly to video & BIOS memory through linear addressing */
/* Active video page-buffer */
#define PAGE_SIZE 2048
int active_page
= 0;
int visual_page
= 0;
void bios_save
(void)
{
/* This function must be called to init CONSole output */
#if 1
/* MG */
cons_columns
=lmempeekw
((LIN_ADDR
)0x0044a);
cons_rows
=lmempeekb
((LIN_ADDR
)0x00484)+1;
bios_attr
= lmempeekb
((LIN_ADDR
)0xB8000 + cons_columns
* 2 -1);
bios_x
= lmempeekb
((LIN_ADDR
)0x00450);
bios_y
= lmempeekb
((LIN_ADDR
)0x00451);
bios_end
= lmempeekb
((LIN_ADDR
)0x00460);
bios_start
= lmempeekb
((LIN_ADDR
)0x00461);
active_page
= visual_page
= 0;
#else
LIN_ADDR p
;
p
= (LIN_ADDR
)(0xB8000 + 159);
bios_attr
= *p
;
p
= (LIN_ADDR
)0x00450;
bios_x
= *p
;
p
= (LIN_ADDR
)0x00451;
bios_y
= *p
;
p
= (LIN_ADDR
)0x00460;
bios_end
= *p
;
p
= (LIN_ADDR
)0x00461;
bios_start
= *p
;
active_page
= visual_page
= 0;
#endif
}
void cursor
(int start
,int end
)
{
/* Same thing as above; Set cursor scan line */
outp
(CGA_INDEX_REG
, CURSOR_START
);
outp
(CGA_DATA_REG
, start
);
outp
(CGA_INDEX_REG
, CURSOR_END
);
outp
(CGA_DATA_REG
, end
);
}
void bios_restore
(void)
{
lmempokeb
((LIN_ADDR
)0x00450,bios_x
);
lmempokeb
((LIN_ADDR
)0x00451,bios_y
);
place
(bios_x
,bios_y
);
cursor
(bios_start
, bios_end
);
}
void place
(int x
,int y
)
{
unsigned short cursor_word
= x
+ y
*cons_columns
+ active_page
*PAGE_SIZE
;
/* Set cursor position */
/* CGA is programmed writing first the Index register */
/* to specify what internal register we are accessing */
/* Then we load the Data register with the wanted val */
outp
(CGA_INDEX_REG
,CURSOR_POS_LSB
);
outp
(CGA_DATA_REG
,cursor_word
& 0xFF);
outp
(CGA_INDEX_REG
,CURSOR_POS_MSB
);
outp
(CGA_DATA_REG
,(cursor_word
>> 8) & 0xFF);
/* Adjust temporary cursor bios position */
bios_x
= x
;
bios_y
= y
;
}
void _scroll
(char attr
,int x1
,int y1
,int x2
,int y2
)
{
register int x
,y
;
WORD xattr
= attr
<< 8,w
;
LIN_ADDR v
= (LIN_ADDR
)(0xB8000 + active_page
*(2*PAGE_SIZE
));
for (y
= y1
+1; y
<= y2
; y
++)
for (x
= x1
; x
<= x2
; x
++) {
w
= lmempeekw
((LIN_ADDR
)(v
+ 2*(y
*cons_columns
+x
)));
lmempokew
((LIN_ADDR
)(v
+ 2*((y
-1)*cons_columns
+x
)),w
);
}
for (x
= x1
; x
<= x2
; x
++)
lmempokew
((LIN_ADDR
)(v
+ 2*((y
-1)*cons_columns
+x
)),xattr
);
}
#define OPTIMIZED
#ifdef OPTIMIZED
void scroll
(void)
{
int x
;
WORD xattr
= bios_attr
<< 8;
LIN_ADDR v
= (LIN_ADDR
)(0xB8000 + active_page
*(2*PAGE_SIZE
));
memcpy((LIN_ADDR
)(v
),
(LIN_ADDR
)(v
+ 2*cons_columns
),
cons_columns
*(cons_rows
-1)*2);
for (x
= 0; x
<= cons_columns
-1; x
++)
lmempokew
((LIN_ADDR
)(v
+ 2*((cons_rows
-1)*cons_columns
+x
)),xattr
);
}
#else
void scroll
(void)
{
_scroll
(bios_attr
,0,0,(cons_columns
-1),(cons_rows
-1));
}
#endif
void cputc
(char c
)
{
static unsigned short scan_x
,x
,y
;
LIN_ADDR v
= (LIN_ADDR
)(0xB8000 + active_page
*(2*PAGE_SIZE
));
x
= bios_x
;
y
= bios_y
;
switch (c
) {
case '\t' : x
+= 8;
if (x
== (cons_columns
-1)) {
x
= 0;
if (y
>= (cons_rows
-1)) scroll
();
else y
++;
} else {
scan_x
= 0;
while ((scan_x
+8) < x
) scan_x
+= 8;
x
= scan_x
;
}
break;
case '\n' : x
= 0;
if (y
>= (cons_rows
-1)) scroll
();
else y
++;
break;
case '\b' : x
--;
lmempokeb
((LIN_ADDR
)(v
+ 2*(x
+ y
*cons_columns
)),' ');
x
++;
break;
default : lmempokeb
((LIN_ADDR
)(v
+ 2*(x
+ y
*cons_columns
)),c
);
x
++;
if (x
== (cons_columns
-1)) {
x
= 0;
if (y
>= (cons_rows
-1)) scroll
();
else y
++;
}
}
place
(x
,y
);
}
void cputs
(char *s
)
{
char c
;
while (*s
!= '\0') {
c
= *s
++;
cputc
(c
);
}
}