jehanne/sys/src/kern/amd64/ht.c

208 lines
4.6 KiB
C

/* Copyright (C) Charles Forsyth
* See /doc/license/NOTICE.Plan9-9k.txt for details about the licensing.
*/
/* Portions of this file are Copyright (C) 9front's team.
* See /doc/license/9front-mit for details about the licensing.
* See http://git.9front.org/plan9front/plan9front/HEAD/info.html for a list of authors.
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
static void
htcapabilities(Pcidev* pci, int cp)
{
uint64_t idr;
uint32_t command, r;
/*
* Top 5 bits of command give type:
* 000xx slave or primary interface
* 001xx host or secondary interface
* 10000 interrupt discovery and configuration
* Other values don't concern this interface.
*/
r = pcicfgr32(pci, cp);
command = (r>>16) & 0xFFFF;
if((command & 0xE000) == 0x0000){
DBG("HT: slave or primary interface\n");
}
else if((command & 0xE000) == 0x2000){
DBG("HT: host or secondary interface\n");
}
else if((command & 0xF800) == 0x8000){
/*
* The Interrupt and Discovery block uses
* an index and data scheme to access the
* registers. Index is a byte at +2, data is
* 32 bits at +4.
* The only interesting information is the 64-bit
* Interrupt Definition Register at offset 0x10.
*/
pcicfgw8(pci, cp+0x02, 0x11);
idr = pcicfgr32(pci, cp+0x04);
idr <<= 32;
pcicfgw8(pci, cp+0x02, 0x10);
idr |= (uint32_t)pcicfgr32(pci, cp+0x04);
DBG("HT: Interrupt and discovery block: idr %#16.16llux\n", idr);
}
else{
DBG("HT: capability code %#ux\n", command>>11);
}
}
void
htlink(void)
{
int cp;
char *p;
Pcidev *pci;
uint32_t r, *rp;
pci = nil;
while(pci = pcimatch(pci, 0, 0)){
/*
* AMD-8111 Hypertransport I/O Hub
*/
if(pci->vid == 0x1022 && pci->did == 0x1100){
DBG("HT: AMD-8111: tc %#8.8ux ic %#8.8ux\n",
pcicfgr32(pci, 0x68), pcicfgr32(pci, 0x6C));
}
/*
* AMD-8111 PCI Bridge
*/
if(pci->vid == 0x1022 && pci->did == 0x7460){
pcicfgw32(pci, 0xF0, 1);
DBG("HT: AMD-8111: 0xF4: %#8.8ux\n",
pcicfgr32(pci, 0xF4));
pcicfgw32(pci, 0xF0, 0x10);
DBG("HT: AMD-8111: 0x10: %#8.8ux\n",
pcicfgr32(pci, 0xF4));
pcicfgw32(pci, 0xF0, 0x11);
DBG("HT: AMD-8111: 0x11: %#8.8ux\n",
pcicfgr32(pci, 0xF4));
}
/*
* AMD-8111 LPC Bridge
*/
if(pci->vid == 0x1022 && pci->did == 0x7468){
r = pcicfgr32(pci, 0xA0);
DBG("HT: HPET @ %#ux\n", r);
if((rp = vmap(r & ~0x0F, 0x200)) != nil){
DBG("HT: HPET00: %#8.8ux%8.8ux\n",
rp[4/4], rp[0/4]);
DBG("HT: HPET10: %#8.8ux%8.8ux\n",
rp[0x10/4], rp[0x10/4]);
DBG("HT: HPET20: %#8.8ux%8.8ux\n",
rp[0x24/4], rp[0x20/4]);
DBG("HT: HPETF0: %#8.8ux%8.8ux\n",
rp[0xF4/4], rp[0xF0/4]);
DBG("HT: HPET100: %#8.8ux%8.8ux\n",
rp[0x104/4], rp[0x100/4]);
DBG("HT: HPET120: %#8.8ux%8.8ux\n",
rp[0x124/4], rp[0x120/4]);
DBG("HT: HPET140: %#8.8ux%8.8ux\n",
rp[0x144/4], rp[0x140/4]);
vunmap(rp, 0x200);
}
}
/*
* Check if there are extended capabilities implemented,
* (bit 4 in the status register).
* Find the capabilities pointer based on PCI header type.
*
* Make this more general (e.g. pcigetcap(pcidev, id, cp))
* and merge back into PCI code.
*/
if(!(pcicfgr16(pci, PciPSR) & 0x0010))
continue;
switch(pcicfgr8(pci, PciHDT)){
default:
continue;
case 0: /* all other */
case 1: /* PCI to PCI bridge */
cp = PciCP;
break;
}
for(cp = pcicfgr8(pci, cp); cp != 0; cp = pcicfgr8(pci, cp+1)){
/*
* Check for validity.
* Can't be in standard header and must be double
* word aligned.
*/
if(cp < 0x40 || (cp & ~0xFC))
break;
r = pcicfgr32(pci, cp);
switch(r & 0xFF){
default:
DBG("HT: %#4.4ux/%#4.4ux: unknown ID %d\n",
pci->vid, pci->did, r & 0xFF);
continue;
case 0x01:
p = "PMI";
break;
case 0x02:
p = "AGP";
break;
case 0x03:
p = "VPD";
break;
case 0x04:
p = "Slot Identification";
break;
case 0x05:
p = "MSI";
break;
case 0x06:
p = "CPCI Hot Swap";
break;
case 0x07:
p = "PCI-X";
break;
case 0x08:
DBG("HT: %#4.4ux/%#4.4ux: HT\n",
pci->vid, pci->did);
htcapabilities(pci, cp);
continue;
case 0x09:
p = "Vendor Specific";
break;
case 0x0A:
p = "Debug Port";
break;
case 0x0B:
p = "CPCI Central Resource Control";
break;
case 0x0C:
p = "PCI Hot-Plug";
break;
case 0x0E:
p = "AGP 8x";
break;
case 0x0F:
p = "Secure Device";
break;
case 0x10:
p = "PCIe";
break;
case 0x11:
p = "MSI-X";
break;
case 0x12:
p = "SATA HBA";
break;
}
DBG("HT: %#4.4ux/%#4.4ux: %s\n", pci->vid, pci->did, p);
}
}
}