aux/vga: use devpnp for pci control register io
This commit is contained in:
parent
fb9c05bbef
commit
bbbfbe3dc4
2 changed files with 101 additions and 236 deletions
|
@ -1,267 +1,167 @@
|
||||||
#include <u.h>
|
#include <u.h>
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
#include <bio.h>
|
#include <bio.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
#include "vga.h"
|
#include "vga.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* PCI support code.
|
|
||||||
* There really should be a driver for this, it's not terribly safe
|
|
||||||
* without locks or restrictions on what can be poked (e.g. Axil NX801).
|
|
||||||
*/
|
|
||||||
enum { /* configuration mechanism #1 */
|
|
||||||
PciADDR = 0xCF8, /* CONFIG_ADDRESS */
|
|
||||||
PciDATA = 0xCFC, /* CONFIG_DATA */
|
|
||||||
|
|
||||||
/* configuration mechanism #2 */
|
|
||||||
PciCSE = 0xCF8, /* configuration space enable */
|
|
||||||
PciFORWARD = 0xCFA, /* which bus */
|
|
||||||
|
|
||||||
MaxFNO = 7,
|
|
||||||
MaxUBN = 255,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int pcicfgmode = -1;
|
|
||||||
static int pcimaxdno;
|
|
||||||
static Pcidev* pciroot;
|
|
||||||
static Pcidev* pcilist;
|
static Pcidev* pcilist;
|
||||||
static Pcidev* pcitail;
|
static Pcidev* pcitail;
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pcicfginit(void)
|
pcicfginit(void)
|
||||||
{
|
{
|
||||||
Dir *d;
|
|
||||||
int fd, i, j, n, bno, dno, fno;
|
int fd, i, j, n, bno, dno, fno;
|
||||||
char buf[1024], *s;
|
char buf[1024], *base, *s;
|
||||||
Pcidev *p;
|
Pcidev *p;
|
||||||
|
Dir *d;
|
||||||
|
|
||||||
pcicfgmode = 0x666;
|
|
||||||
trace("pcicfginit\n");
|
trace("pcicfginit\n");
|
||||||
fd = open("#$/pci", OREAD);
|
if((fd = open(base = "/dev/pci", OREAD)) < 0)
|
||||||
if(fd < 0)
|
if((fd = open(base = "#$/pci", OREAD)) < 0)
|
||||||
return;
|
|
||||||
if((n = dirreadall(fd, &d)) < 0)
|
|
||||||
return;
|
return;
|
||||||
|
n = dirreadall(fd, &d);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
if(n < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
for(i=0; i<n; i++) {
|
for(i=0; i<n; i++) {
|
||||||
int nl = strlen(d[i].name);
|
if(strstr(d[i].name, "ctl") == nil)
|
||||||
if(d[i].name[nl-3] == 'r' && d[i].name[nl-2] == 'a' && d[i].name[nl-1] == 'w' ) {
|
continue;
|
||||||
trace("pci device %s\n",d[i].name);
|
|
||||||
sprint(buf, "#$/pci/%s", d[i].name);
|
|
||||||
if((fd = open(buf, OREAD)) < 0)
|
|
||||||
return;
|
|
||||||
if((read(fd, buf, 0x30)) <= 0)
|
|
||||||
return;
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
bno = strtoul(d[i].name, &s, 10);
|
sprint(buf, "%s", d[i].name);
|
||||||
|
bno = strtoul(buf, &s, 10);
|
||||||
dno = strtoul(s+1, &s, 10);
|
dno = strtoul(s+1, &s, 10);
|
||||||
fno = strtoul(s+1, nil, 10);
|
fno = strtoul(s+1, nil, 10);
|
||||||
trace("\t-> %d %d %d\n",bno, dno, fno);
|
|
||||||
p = mallocz(sizeof(*p), 1);
|
p = mallocz(sizeof(*p), 1);
|
||||||
p->tbdf = MKBUS(BusPCI, bno, dno, fno);
|
p->tbdf = MKBUS(BusPCI, bno, dno, fno);
|
||||||
p->vid = *(ulong*)(buf);
|
sprint(buf, "%s/%d.%d.%draw", base, bno, dno, fno);
|
||||||
p->did = *(ushort*)(buf+2);
|
if((p->rawfd = open(buf, ORDWR)) < 0){
|
||||||
p->rid = *(uchar*)(buf+PciRID);
|
free(p);
|
||||||
p->intl = *(uchar*)(buf+PciINTL);
|
continue;
|
||||||
p->ccru = *(ushort*)(buf+PciCCRu);
|
}
|
||||||
|
sprint(buf, "%s/%d.%d.%dctl", base, bno, dno, fno);
|
||||||
|
if((fd = open(buf, OREAD)) < 0){
|
||||||
|
close(p->rawfd);
|
||||||
|
free(p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if((n = read(fd, buf, sizeof(buf)-1)) <= 0){
|
||||||
|
close(p->rawfd);
|
||||||
|
close(fd);
|
||||||
|
free(p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
buf[n] = 0;
|
||||||
|
close(fd);
|
||||||
|
|
||||||
int rno = PciBAR0 - 4;
|
p->ccru = strtol(buf + 3, nil, 16);
|
||||||
for(j = 0; j < nelem(p->mem); j++){
|
p->vid = strtol(buf + 9, &s, 16);
|
||||||
rno += 4;
|
p->did = strtol(s + 1, &s, 16);
|
||||||
p->mem[j].bar = pcicfgr32(p, rno);
|
p->intl = strtol(s + 1, &s, 10);
|
||||||
pcicfgw32(p, rno, -1);
|
|
||||||
ulong v = pcicfgr32(p, rno);
|
p->rid = pcicfgr8(p, PciRID);
|
||||||
pcicfgw32(p, rno, p->mem[i].bar);
|
|
||||||
p->mem[j].size = -(v & ~0xF);
|
trace("did=%X vid=%X rid=%X intl=%d ccru=%X\n", p->did, p->vid, p->rid, p->intl, p->ccru);
|
||||||
|
|
||||||
|
while(*s == ' '){
|
||||||
|
j = strtol(s+1, &s, 10);
|
||||||
|
if(j < 0 || j >= nelem(p->mem))
|
||||||
|
break;
|
||||||
|
p->mem[j].bar = strtol(s+1, &s, 16);
|
||||||
|
p->mem[j].size = strtol(s+1, &s, 10);
|
||||||
trace("\t->mem[%d] = %p %d\n", j, p->mem[j].bar, p->mem[j].size);
|
trace("\t->mem[%d] = %p %d\n", j, p->mem[j].bar, p->mem[j].size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(pcilist != nil)
|
if(pcilist != nil)
|
||||||
pcitail->list = p;
|
pcitail->list = p;
|
||||||
else
|
else
|
||||||
pcilist = p;
|
pcilist = p;
|
||||||
pcitail = p;
|
pcitail = p;
|
||||||
|
|
||||||
|
|
||||||
trace("\t-> did=%X vid=%X rid=%X intl=%d ccru=%X\n",p->did, p->vid, p->rid,p->intl, p->ccru);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pcicfgrw8(int tbdf, int rno, int data, int read)
|
pcicfgrw(Pcidev *pcidev, int rno, int data, int len, int read)
|
||||||
{
|
{
|
||||||
int o, type, x;
|
uchar buf[4];
|
||||||
|
|
||||||
if(pcicfgmode == -1)
|
|
||||||
pcicfginit();
|
|
||||||
|
|
||||||
if(BUSBNO(tbdf))
|
|
||||||
type = 0x01;
|
|
||||||
else
|
|
||||||
type = 0x00;
|
|
||||||
x = -1;
|
|
||||||
if(BUSDNO(tbdf) > pcimaxdno)
|
|
||||||
return x;
|
|
||||||
|
|
||||||
switch(pcicfgmode){
|
|
||||||
|
|
||||||
|
if(read){
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
if(pread(pcidev->rawfd, buf, len, rno) != len)
|
||||||
|
return -1;
|
||||||
|
switch(len){
|
||||||
case 1:
|
case 1:
|
||||||
o = rno & 0x03;
|
return GBIT8(buf);
|
||||||
rno &= ~0x03;
|
|
||||||
outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
|
|
||||||
if(read)
|
|
||||||
x = inportb(PciDATA+o);
|
|
||||||
else
|
|
||||||
outportb(PciDATA+o, data);
|
|
||||||
outportl(PciADDR, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
|
return GBIT16(buf);
|
||||||
outportb(PciFORWARD, BUSBNO(tbdf));
|
case 4:
|
||||||
if(read)
|
return GBIT32(buf);
|
||||||
x = inportb((0xC000|(BUSDNO(tbdf)<<8)) + rno);
|
default:
|
||||||
else
|
abort();
|
||||||
outportb((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
|
|
||||||
outportb(PciCSE, 0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
return x;
|
switch(len){
|
||||||
|
case 1:
|
||||||
|
PBIT8(buf, data);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
PBIT16(buf, data);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
PBIT32(buf, data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if(pwrite(pcidev->rawfd, buf, len, rno) != len)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pcicfgr8(Pcidev* pcidev, int rno)
|
pcicfgr8(Pcidev* pcidev, int rno)
|
||||||
{
|
{
|
||||||
return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
|
return pcicfgrw(pcidev, rno, 0, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pcicfgw8(Pcidev* pcidev, int rno, int data)
|
pcicfgw8(Pcidev* pcidev, int rno, int data)
|
||||||
{
|
{
|
||||||
pcicfgrw8(pcidev->tbdf, rno, data, 0);
|
pcicfgrw(pcidev, rno, data, 1, 0);
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
pcicfgrw16(int tbdf, int rno, int data, int read)
|
|
||||||
{
|
|
||||||
int o, type, x;
|
|
||||||
|
|
||||||
if(pcicfgmode == -1)
|
|
||||||
pcicfginit();
|
|
||||||
|
|
||||||
if(BUSBNO(tbdf))
|
|
||||||
type = 0x01;
|
|
||||||
else
|
|
||||||
type = 0x00;
|
|
||||||
x = -1;
|
|
||||||
if(BUSDNO(tbdf) > pcimaxdno)
|
|
||||||
return x;
|
|
||||||
|
|
||||||
switch(pcicfgmode){
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
o = rno & 0x02;
|
|
||||||
rno &= ~0x03;
|
|
||||||
outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
|
|
||||||
if(read)
|
|
||||||
x = inportw(PciDATA+o);
|
|
||||||
else
|
|
||||||
outportw(PciDATA+o, data);
|
|
||||||
outportl(PciADDR, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
|
|
||||||
outportb(PciFORWARD, BUSBNO(tbdf));
|
|
||||||
if(read)
|
|
||||||
x = inportw((0xC000|(BUSDNO(tbdf)<<8)) + rno);
|
|
||||||
else
|
|
||||||
outportw((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
|
|
||||||
outportb(PciCSE, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pcicfgr16(Pcidev* pcidev, int rno)
|
pcicfgr16(Pcidev* pcidev, int rno)
|
||||||
{
|
{
|
||||||
return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
|
return pcicfgrw(pcidev, rno, 0, 2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pcicfgw16(Pcidev* pcidev, int rno, int data)
|
pcicfgw16(Pcidev* pcidev, int rno, int data)
|
||||||
{
|
{
|
||||||
pcicfgrw16(pcidev->tbdf, rno, data, 0);
|
pcicfgrw(pcidev, rno, data, 2, 0);
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
pcicfgrw32(int tbdf, int rno, int data, int read)
|
|
||||||
{
|
|
||||||
int type, x;
|
|
||||||
|
|
||||||
if(pcicfgmode == -1)
|
|
||||||
pcicfginit();
|
|
||||||
|
|
||||||
if(BUSBNO(tbdf))
|
|
||||||
type = 0x01;
|
|
||||||
else
|
|
||||||
type = 0x00;
|
|
||||||
x = -1;
|
|
||||||
if(BUSDNO(tbdf) > pcimaxdno)
|
|
||||||
return x;
|
|
||||||
|
|
||||||
switch(pcicfgmode){
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
rno &= ~0x03;
|
|
||||||
outportl(PciADDR, 0x80000000|BUSBDF(tbdf)|rno|type);
|
|
||||||
if(read)
|
|
||||||
x = inportl(PciDATA);
|
|
||||||
else
|
|
||||||
outportl(PciDATA, data);
|
|
||||||
outportl(PciADDR, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
outportb(PciCSE, 0x80|(BUSFNO(tbdf)<<1));
|
|
||||||
outportb(PciFORWARD, BUSBNO(tbdf));
|
|
||||||
if(read)
|
|
||||||
x = inportl((0xC000|(BUSDNO(tbdf)<<8)) + rno);
|
|
||||||
else
|
|
||||||
outportl((0xC000|(BUSDNO(tbdf)<<8)) + rno, data);
|
|
||||||
outportb(PciCSE, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pcicfgr32(Pcidev* pcidev, int rno)
|
pcicfgr32(Pcidev* pcidev, int rno)
|
||||||
{
|
{
|
||||||
return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
|
return pcicfgrw(pcidev, rno, 0, 4, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pcicfgw32(Pcidev* pcidev, int rno, int data)
|
pcicfgw32(Pcidev* pcidev, int rno, int data)
|
||||||
{
|
{
|
||||||
pcicfgrw32(pcidev->tbdf, rno, data, 0);
|
pcicfgrw(pcidev, rno, data, 4, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Pcidev*
|
Pcidev*
|
||||||
pcimatch(Pcidev* prev, int vid, int did)
|
pcimatch(Pcidev* prev, int vid, int did)
|
||||||
{
|
{
|
||||||
if(pcicfgmode == -1)
|
if(pcilist == nil)
|
||||||
pcicfginit();
|
pcicfginit();
|
||||||
|
|
||||||
if(prev == nil)
|
if(prev == nil)
|
||||||
|
@ -277,36 +177,3 @@ pcimatch(Pcidev* prev, int vid, int did)
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
pcihinv(Pcidev* p)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
Pcidev *t;
|
|
||||||
|
|
||||||
if(pcicfgmode == -1)
|
|
||||||
pcicfginit();
|
|
||||||
|
|
||||||
|
|
||||||
if(p == nil) {
|
|
||||||
p = pciroot;
|
|
||||||
Bprint(&stdout, "bus dev type vid did intl memory\n");
|
|
||||||
}
|
|
||||||
for(t = p; t != nil; t = t->link) {
|
|
||||||
Bprint(&stdout, "%d %2d/%d %.4ux %.4ux %.4ux %2d ",
|
|
||||||
BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
|
|
||||||
t->ccru, t->vid, t->did, t->intl);
|
|
||||||
|
|
||||||
for(i = 0; i < nelem(p->mem); i++) {
|
|
||||||
if(t->mem[i].size == 0)
|
|
||||||
continue;
|
|
||||||
Bprint(&stdout, "%d:%.8lux %d ", i,
|
|
||||||
t->mem[i].bar, t->mem[i].size);
|
|
||||||
}
|
|
||||||
Bprint(&stdout, "\n");
|
|
||||||
}
|
|
||||||
while(p != nil) {
|
|
||||||
if(p->bridge != nil)
|
|
||||||
pcihinv(p->bridge);
|
|
||||||
p = p->link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -99,8 +99,6 @@ typedef struct Pcidev {
|
||||||
uchar intl; /* interrupt line */
|
uchar intl; /* interrupt line */
|
||||||
ushort ccru;
|
ushort ccru;
|
||||||
|
|
||||||
|
|
||||||
Pcidev* list;
|
Pcidev* list;
|
||||||
Pcidev* bridge; /* down a bus */
|
int rawfd;
|
||||||
Pcidev* link; /* next device on this bno */
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue