165 lines
3.5 KiB
C
165 lines
3.5 KiB
C
/**
|
|
* \file
|
|
* \brief VGA Framebuffer
|
|
*
|
|
* The VGA Framebuffer is a block device that exposes the memory region
|
|
* reserved to the framebuffer, so that other code can use VFS operations
|
|
* to get or change the contents of the screen.
|
|
*
|
|
* Applications will usually not use this file directly, but rather delegate
|
|
* changing the contents of the screen to the virtual console device, which
|
|
* also will make additional transformations, such as changing attributes.
|
|
*/
|
|
|
|
#include "vgafb.h"
|
|
#include <machine/cpu.h>
|
|
#include <sys/device.h>
|
|
#include <sys/stdkern.h>
|
|
#include <sys/vfs.h>
|
|
|
|
#define VGA_BASE 0xB8000
|
|
#define VGA_COLS 80
|
|
#define VGA_ROWS 25
|
|
#define VGA_CHARS (VGA_COLS * VGA_ROWS)
|
|
#define VGA_SIZE (VGA_CHARS * 2)
|
|
#define VGA_LIMIT (VGA_BASE + VGA_SIZE)
|
|
|
|
#define VGA_IOR_ADDR 0x3D4
|
|
#define VGA_IOR_DATA 0x3D5
|
|
|
|
static int vgafb_init(void);
|
|
static int vgafb_open(unsigned int flags);
|
|
static int vgafb_close(void);
|
|
static unsigned int
|
|
vgafb_read(unsigned char *buf, unsigned int off, unsigned int len);
|
|
static unsigned int
|
|
vgafb_write(unsigned char *buf, unsigned int off, unsigned int len);
|
|
static int vgafb_ioctl(int iorq, void *argp);
|
|
|
|
static driver_t vgafb_driver = {
|
|
.drv_name = "vgafb",
|
|
.drv_flags = DV_FBLCKDEV,
|
|
.drv_init = &vgafb_init,
|
|
};
|
|
|
|
static device_t vgafb_device = {
|
|
.dev_family = &vgafb_driver,
|
|
.dev_open = &vgafb_open,
|
|
.dev_close = &vgafb_close,
|
|
.dev_read_blk = &vgafb_read,
|
|
.dev_write_blk = &vgafb_write,
|
|
.dev_ioctl = &vgafb_ioctl,
|
|
};
|
|
|
|
static int
|
|
vgafb_init(void)
|
|
{
|
|
unsigned int i;
|
|
unsigned short *vga = (unsigned short *) VGA_BASE;
|
|
|
|
if (device_install(&vgafb_device, "fb") < 0) {
|
|
return -1;
|
|
}
|
|
for (i = 0; i < VGA_CHARS; i++)
|
|
vga[i] = 0x700;
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
vgafb_open(unsigned int flags)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
vgafb_close(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static unsigned int
|
|
vgafb_read(unsigned char *buf, unsigned int offt, unsigned int len)
|
|
{
|
|
unsigned char *start, *end, *ptr;
|
|
unsigned int read_bytes = 0;
|
|
|
|
if (offt < VGA_SIZE) {
|
|
start = (unsigned char *) VGA_BASE + offt;
|
|
end = start + len;
|
|
if (end >= (unsigned char *) VGA_LIMIT) {
|
|
end = (unsigned char *) VGA_LIMIT;
|
|
}
|
|
|
|
for (ptr = start; ptr < end; ptr++) {
|
|
*buf++ = *ptr;
|
|
read_bytes++;
|
|
}
|
|
}
|
|
|
|
return read_bytes;
|
|
}
|
|
|
|
static unsigned int
|
|
vgafb_write(unsigned char *buf, unsigned int offt, unsigned int len)
|
|
{
|
|
unsigned char *start, *end, *ptr;
|
|
unsigned int write_bytes = 0;
|
|
|
|
if (offt < VGA_SIZE) {
|
|
start = (unsigned char *) VGA_BASE + offt;
|
|
end = start + len;
|
|
if (end >= (unsigned char *) VGA_LIMIT) {
|
|
end = (unsigned char *) VGA_LIMIT;
|
|
}
|
|
|
|
for (ptr = start; ptr < end; ptr++) {
|
|
*ptr = *buf++;
|
|
write_bytes++;
|
|
}
|
|
}
|
|
|
|
return write_bytes;
|
|
}
|
|
|
|
static void
|
|
enablecursor(int enabled)
|
|
{
|
|
unsigned char in;
|
|
if (enabled) {
|
|
port_out_byte(VGA_IOR_ADDR, 0xA);
|
|
in = port_in_byte(VGA_IOR_DATA) & 0x1F;
|
|
port_out_byte(VGA_IOR_DATA, in | 0xD);
|
|
port_out_byte(VGA_IOR_ADDR, 0xB);
|
|
in = port_in_byte(VGA_IOR_DATA) & 0xC0;
|
|
port_out_byte(VGA_IOR_DATA, in | 0xF);
|
|
} else {
|
|
port_out_byte(VGA_IOR_ADDR, 0xA);
|
|
port_out_byte(VGA_IOR_DATA, 0x20);
|
|
}
|
|
}
|
|
|
|
static void
|
|
movecursor(unsigned short abspos)
|
|
{
|
|
port_out_byte(VGA_IOR_ADDR, 0xE);
|
|
port_out_byte(VGA_IOR_DATA, (abspos >> 8) & 0xFF);
|
|
port_out_byte(VGA_IOR_ADDR, 0xF);
|
|
port_out_byte(VGA_IOR_DATA, abspos & 0xFF);
|
|
}
|
|
|
|
static int
|
|
vgafb_ioctl(int iorq, void *arg)
|
|
{
|
|
switch (iorq) {
|
|
case VGAFB_IOCTL_SETCUR:
|
|
enablecursor(((int) arg) != 0);
|
|
return 0;
|
|
case VGAFB_IOCTL_MOVECUR:
|
|
movecursor(*(unsigned short *) arg);
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
DEVICE_DESCRIPTOR(vgafb, vgafb_driver); |