plan9fox/sys/src/9/pc/vgaclgd546x.c
cinap_lenrek 2a1b43ad98 vga: make kernel vga drivers more stupid
previously, we had to maintain 3 sets of pci vid/did's:

1) in /lib/vgadb for detection
2) in the userspace driver in aux/vga
3) in the kernel mode driver

this change makes the kernel mode driver more dumb in
the cases where possible. we let userspace do the pci
enumeration and if needed, it can set the pci address
of the vga card. kernel mode drivers can assume to get
the right pci device passed in scr->pci for enable()
and linear() functions and just do very basic sanity
checking before mapping framebuffer and mmio regions.

vgalinearpciid() was removed as userspace is responsible
to pick pci device.

theres a new vgactl message "pcidev" where userspace
can set the bus address. we initialize scr->pci in
vgareset() to the first pci graphics card found. this
should cover cases when an old aux/vga binary is used
that doesnt use the new pcidev message.

userspace drivers will now use the pci device that got
a match from /lib/vgadb and skip ther own enumeration.
this way, vga cards can be made to work by simply adding
an entry in vgadb with no need to modify userspace or
kernelspace drivers. this is not always possible if
the driver derives information from the specific card
model.
2013-01-02 01:19:51 +01:00

211 lines
3.5 KiB
C

#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#define Image IMAGE
#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"
typedef struct Cursor546x Cursor546x;
struct Cursor546x {
ushort x;
ushort y;
ushort preset;
ushort enable;
ushort addr;
};
enum {
PaletteState = 0xB0,
CursorMMIO = 0xE0,
};
static void
clgd546xlinear(VGAscr* scr, int, int)
{
vgalinearpci(scr);
}
static void
clgd546xenable(VGAscr* scr)
{
Pcidev *p;
if(scr->mmio)
return;
p = scr->pci;
if(p == nil)
return;
scr->mmio = vmap(p->mem[1].bar&~0x0F, p->mem[1].size);
if(scr->mmio == 0)
return;
addvgaseg("clgd546xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
}
static void
clgd546xcurdisable(VGAscr* scr)
{
Cursor546x *cursor546x;
if(scr->mmio == 0)
return;
cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
cursor546x->enable = 0;
}
static void
clgd546xcurload(VGAscr* scr, Cursor* curs)
{
int c, i, m, y;
uchar *p;
Cursor546x *cursor546x;
if(scr->mmio == 0)
return;
cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
/*
* Disable the cursor then change only the bits
* that need it.
*/
cursor546x->enable = 0;
p = (uchar*)scr->vaddr + scr->storage;
for(y = 0; y < 16; y++){
c = curs->set[2*y];
m = 0;
for(i = 0; i < 8; i++){
if(c & (1<<(7-i)))
m |= 1<<i;
}
*p++ = m;
c = curs->set[2*y + 1];
m = 0;
for(i = 0; i < 8; i++){
if(c & (1<<(7-i)))
m |= 1<<i;
}
*p++ = m;
p += 6;
c = curs->set[2*y]|curs->clr[2*y];
m = 0;
for(i = 0; i < 8; i++){
if(c & (1<<(7-i)))
m |= 1<<i;
}
*p++ = m;
c = curs->set[2*y + 1]|curs->clr[2*y + 1];
m = 0;
for(i = 0; i < 8; i++){
if(c & (1<<(7-i)))
m |= 1<<i;
}
*p++ = m;
p += 6;
}
/*
* Save the cursor hotpoint and enable the cursor.
*/
scr->offset = curs->offset;
cursor546x->enable = 1;
}
static int
clgd546xcurmove(VGAscr* scr, Point p)
{
int x, xo, y, yo;
Cursor546x *cursor546x;
if(scr->mmio == 0)
return 1;
cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
if((x = p.x+scr->offset.x) < 0){
xo = -x;
x = 0;
}
else
xo = 0;
if((y = p.y+scr->offset.y) < 0){
yo = -y;
y = 0;
}
else
yo = 0;
cursor546x->preset = (xo<<8)|yo;
cursor546x->x = x;
cursor546x->y = y;
return 0;
}
static void
clgd546xcurenable(VGAscr* scr)
{
uchar *p;
Cursor546x *cursor546x;
clgd546xenable(scr);
if(scr->mmio == 0)
return;
cursor546x = (Cursor546x*)((uchar*)scr->mmio+CursorMMIO);
/*
* Cursor colours.
* Can't call setcolor here as cursor is already locked.
*/
p = (uchar*)scr->mmio+PaletteState;
*p |= 0x08;
vgao(PaddrW, 0x00);
vgao(Pdata, Pwhite);
vgao(Pdata, Pwhite);
vgao(Pdata, Pwhite);
vgao(PaddrW, 0x0F);
vgao(Pdata, Pblack);
vgao(Pdata, Pblack);
vgao(Pdata, Pblack);
*p &= ~0x08;
/*
* Find a place for the cursor data in display memory.
* 2 cursor images might be needed, 1KB each so use the last
* 2KB of the framebuffer and initialise them to be
* transparent.
*/
scr->storage = ((vgaxi(Seqx, 0x14) & 0x07)+1)*1024*1022;
cursor546x->addr = (scr->storage>>10)<<2;
memset((uchar*)scr->vaddr + scr->storage, 0, 2*64*16);
/*
* Load, locate and enable the 64x64 cursor.
*/
clgd546xcurload(scr, &arrow);
clgd546xcurmove(scr, ZP);
cursor546x->enable = 1;
}
VGAdev vgaclgd546xdev = {
"clgd546x",
clgd546xenable,
nil,
nil,
clgd546xlinear,
};
VGAcur vgaclgd546xcur = {
"clgd546xhwgc",
clgd546xcurenable,
clgd546xcurdisable,
clgd546xcurload,
clgd546xcurmove,
};