![cinap_lenrek](/assets/img/avatar_default.png)
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.
225 lines
4 KiB
C
225 lines
4 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"
|
|
|
|
enum {
|
|
Xrx = 0x3D6, /* Configuration Extensions Index */
|
|
};
|
|
|
|
static uchar
|
|
hiqvideoxi(long port, uchar index)
|
|
{
|
|
uchar data;
|
|
|
|
outb(port, index);
|
|
data = inb(port+1);
|
|
|
|
return data;
|
|
}
|
|
|
|
static void
|
|
hiqvideoxo(long port, uchar index, uchar data)
|
|
{
|
|
outb(port, index);
|
|
outb(port+1, data);
|
|
}
|
|
|
|
static void
|
|
hiqvideolinear(VGAscr*, int, int)
|
|
{
|
|
}
|
|
|
|
static void
|
|
hiqvideoenable(VGAscr* scr)
|
|
{
|
|
Pcidev *p;
|
|
int vmsize;
|
|
|
|
/*
|
|
* Only once, can't be disabled for now.
|
|
*/
|
|
if(scr->mmio)
|
|
return;
|
|
p = scr->pci;
|
|
if(p == nil || p->vid != 0x102C)
|
|
return;
|
|
switch(p->did){
|
|
case 0x00C0: /* 69000 HiQVideo */
|
|
vmsize = 2*1024*1024;
|
|
break;
|
|
case 0x00E0: /* 65550 HiQV32 */
|
|
case 0x00E4: /* 65554 HiQV32 */
|
|
case 0x00E5: /* 65555 HiQV32 */
|
|
switch((hiqvideoxi(Xrx, 0x43)>>1) & 0x03){
|
|
default:
|
|
case 0:
|
|
vmsize = 1*1024*1024;
|
|
break;
|
|
case 1:
|
|
vmsize = 2*1024*1024;
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
vgalinearpci(scr);
|
|
|
|
if(scr->paddr)
|
|
addvgaseg("hiqvideoscreen", scr->paddr, scr->apsize);
|
|
|
|
/*
|
|
* Find a place for the cursor data in display memory.
|
|
* Must be on a 4096-byte boundary.
|
|
* scr->mmio holds the virtual address of the cursor
|
|
* storage area in the framebuffer region.
|
|
*/
|
|
scr->storage = vmsize-4096;
|
|
scr->mmio = (ulong*)((uchar*)scr->vaddr+scr->storage);
|
|
}
|
|
|
|
static void
|
|
hiqvideocurdisable(VGAscr*)
|
|
{
|
|
hiqvideoxo(Xrx, 0xA0, 0x10);
|
|
}
|
|
|
|
static void
|
|
hiqvideocurload(VGAscr* scr, Cursor* curs)
|
|
{
|
|
uchar *p;
|
|
int x, y;
|
|
|
|
/*
|
|
* Disable the cursor.
|
|
*/
|
|
hiqvideocurdisable(scr);
|
|
|
|
if(scr->mmio == 0)
|
|
return;
|
|
p = (uchar*)scr->mmio;
|
|
|
|
for(y = 0; y < 16; y += 2){
|
|
*p++ = ~(curs->clr[2*y]|curs->set[2*y]);
|
|
*p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
|
|
*p++ = 0xFF;
|
|
*p++ = 0xFF;
|
|
*p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
|
|
*p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
|
|
*p++ = 0xFF;
|
|
*p++ = 0xFF;
|
|
*p++ = curs->set[2*y];
|
|
*p++ = curs->set[2*y+1];
|
|
*p++ = 0x00;
|
|
*p++ = 0x00;
|
|
*p++ = curs->set[2*y+2];
|
|
*p++ = curs->set[2*y+3];
|
|
*p++ = 0x00;
|
|
*p++ = 0x00;
|
|
}
|
|
while(y < 32){
|
|
for(x = 0; x < 64; x += 8)
|
|
*p++ = 0xFF;
|
|
for(x = 0; x < 64; x += 8)
|
|
*p++ = 0x00;
|
|
y += 2;
|
|
}
|
|
|
|
/*
|
|
* Save the cursor hotpoint and enable the cursor.
|
|
*/
|
|
scr->offset = curs->offset;
|
|
hiqvideoxo(Xrx, 0xA0, 0x11);
|
|
}
|
|
|
|
static int
|
|
hiqvideocurmove(VGAscr* scr, Point p)
|
|
{
|
|
int x, y;
|
|
|
|
if(scr->mmio == 0)
|
|
return 1;
|
|
|
|
if((x = p.x+scr->offset.x) < 0)
|
|
x = 0x8000|(-x & 0x07FF);
|
|
if((y = p.y+scr->offset.y) < 0)
|
|
y = 0x8000|(-y & 0x07FF);
|
|
|
|
hiqvideoxo(Xrx, 0xA4, x & 0xFF);
|
|
hiqvideoxo(Xrx, 0xA5, (x>>8) & 0xFF);
|
|
hiqvideoxo(Xrx, 0xA6, y & 0xFF);
|
|
hiqvideoxo(Xrx, 0xA7, (y>>8) & 0xFF);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
hiqvideocurenable(VGAscr* scr)
|
|
{
|
|
uchar xr80;
|
|
|
|
hiqvideoenable(scr);
|
|
if(scr->mmio == 0)
|
|
return;
|
|
|
|
/*
|
|
* Disable the cursor.
|
|
*/
|
|
hiqvideocurdisable(scr);
|
|
|
|
/*
|
|
* Cursor colours.
|
|
* Can't call setcolor here as cursor is already locked.
|
|
* When done make sure the cursor enable in Xr80 is set.
|
|
*/
|
|
xr80 = hiqvideoxi(Xrx, 0x80);
|
|
hiqvideoxo(Xrx, 0x80, xr80|0x01);
|
|
vgao(PaddrW, 0x04);
|
|
vgao(Pdata, Pwhite);
|
|
vgao(Pdata, Pwhite);
|
|
vgao(Pdata, Pwhite);
|
|
vgao(Pdata, Pblack);
|
|
vgao(Pdata, Pblack);
|
|
vgao(Pdata, Pblack);
|
|
hiqvideoxo(Xrx, 0x80, xr80|0x10);
|
|
|
|
hiqvideoxo(Xrx, 0xA2, (scr->storage>>12)<<4);
|
|
hiqvideoxo(Xrx, 0xA3, (scr->storage>>16) & 0x3F);
|
|
|
|
/*
|
|
* Load, locate and enable the 32x32 cursor.
|
|
* Cursor enable in Xr80 better be set already.
|
|
*/
|
|
hiqvideocurload(scr, &arrow);
|
|
hiqvideocurmove(scr, ZP);
|
|
hiqvideoxo(Xrx, 0xA0, 0x11);
|
|
}
|
|
|
|
VGAdev vgahiqvideodev = {
|
|
"hiqvideo",
|
|
|
|
hiqvideoenable, /* enable */
|
|
nil, /* disable */
|
|
nil, /* page */
|
|
hiqvideolinear, /* linear */
|
|
};
|
|
|
|
VGAcur vgahiqvideocur = {
|
|
"hiqvideohwgc",
|
|
|
|
hiqvideocurenable, /* enable */
|
|
hiqvideocurdisable, /* disable */
|
|
hiqvideocurload, /* load */
|
|
hiqvideocurmove, /* move */
|
|
};
|