Skip to content

Commit

Permalink
nvhw: Add a new generic pmc_id parsing function.
Browse files Browse the repository at this point in the history
  • Loading branch information
mwkmwkmwk committed Jan 9, 2014
1 parent 6344b9b commit de57843
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 0 deletions.
10 changes: 10 additions & 0 deletions include/nvhw.h
Expand Up @@ -27,6 +27,15 @@

#include <stdint.h>

struct chipset_info {
uint32_t pmc_id;
int chipset;
int card_type;
int is_nv03t;
int endian;
const char *name;
};

enum pfb_type {
PFB_NONE,
PFB_NV01,
Expand Down Expand Up @@ -55,6 +64,7 @@ struct mc_config {
int partshift;
};

int parse_pmc_id(uint32_t pmc_id, struct chipset_info *info);
int pfb_type(int chipset);

int tile_pitch_valid(int chipset, uint32_t pitch, int *pshift, int *pfactor);
Expand Down
154 changes: 154 additions & 0 deletions nvhw/chipset.c
Expand Up @@ -24,6 +24,160 @@

#include "nvhw.h"
#include <stdlib.h>
#include <string.h>

int parse_pmc_id(uint32_t pmc_id, struct chipset_info *info) {
/* First, detect PMC_ID format and endian. There are four cases:
*
* - pre-NV10 card: always little endian, bits 7 and 31 are guaranteed
* to be 0 (they're high bits of fields that never got big values)
* - NV10+ little-endian card: bit 7 is guaranteed to be 1 (MSB of
* stepping, which is always 0xaX or 0xbX), bit 31 is guaranteed
* to be 0
* - NV10+ big-endian card: like above, but with byteswapping - bit 7
* is 0, bit 31 is 1
* - something is broken with BAR0 access and ID returns 0xffffffff
* - both bit 7 and bit 31 are set
*/
memset(info, 0, sizeof *info);
info->endian = 0;
if (pmc_id & 0x80000000) {
/* bit 31 set - set endian flag and byteswap */
info->endian = 1;
pmc_id = (pmc_id & 0x0000ffff) << 16 | (pmc_id & 0xffff0000) >> 16;
pmc_id = (pmc_id & 0x00ff00ff) << 8 | (pmc_id & 0xff00ff00) >> 8;
}
if (pmc_id & 0x80000000) {
/* bit 31 still set - ie. old bit 7 was set - BAR0 is broken */
info->chipset = -1;
info->name = "(disabled)";
return -1;
}
info->pmc_id = pmc_id;
if (pmc_id & 0x80) {
/* NV10+ */
info->chipset = pmc_id >> 20 & 0x1ff;
info->card_type = info->chipset & 0x1f0;
if (info->card_type == 0x60) {
info->card_type = 0x40;
} else if (info->card_type >= 0x80 && info->card_type <= 0xa0) {
info->card_type = 0x50;
} else if (info->card_type >= 0xc0 && info->card_type <= 0x100) {
info->card_type = 0xc0;
}
switch (info->chipset) {
/* celsius */
case 0x10: info->name = "NV10"; break;
case 0x15: info->name = "NV15"; break;
case 0x1a: info->name = "NV1A"; break;
case 0x11: info->name = "NV11"; break;
case 0x17: info->name = "NV17"; break;
case 0x18: info->name = "NV18"; break;
case 0x1f: info->name = "NV1F"; break;

/* kelvin */
case 0x20: info->name = "NV20"; break;
case 0x2a: info->name = "NV2A"; break;
case 0x25: info->name = "NV25"; break;
case 0x28: info->name = "NV28"; break;

/* rankine */
case 0x30: info->name = "NV30"; break;
case 0x35: info->name = "NV35"; break;
case 0x31: info->name = "NV31"; break;
case 0x36: info->name = "NV36"; break;
case 0x34: info->name = "NV34"; break;

/* curie */
case 0x40: info->name = "NV40"; break;
case 0x45: info->name = "NV45"; break;
case 0x41: info->name = "NV41"; break;
case 0x42: info->name = "NV42"; break;
case 0x43: info->name = "NV43"; break;
case 0x44: info->name = "NV44"; break;
case 0x4a: info->name = "NV44A"; break;
case 0x4e: info->name = "C51"; break;

/* curie2 */
case 0x47: info->name = "G70"; break;
case 0x49: info->name = "G71"; break;
case 0x4b: info->name = "G73"; break;
case 0x46: info->name = "G72"; break;
case 0x4c: info->name = "C61"; break;
case 0x67: info->name = "C67"; break;
case 0x68: info->name = "C68"; break;
case 0x63: info->name = "C73"; break;

/* tesla */
case 0x50: info->name = "G80"; break;
case 0x84: info->name = "G84"; break;
case 0x86: info->name = "G86"; break;
case 0x92: info->name = "G92"; break;
case 0x94: info->name = "G94"; break;
case 0x96: info->name = "G96"; break;
case 0x98: info->name = "G98"; break;
case 0xa0: info->name = "GT200"; break;
case 0xaa: info->name = "MCP77"; break;
case 0xac: info->name = "MCP79"; break;

/* tesla2 */
case 0xa3: info->name = "GT215"; break;
case 0xa5: info->name = "GT216"; break;
case 0xa8: info->name = "GT218"; break;
case 0xaf: info->name = "MCP89"; break;

/* fermi */
case 0xc0: info->name = "GF100"; break;
case 0xc4: info->name = "GF104"; break;
case 0xc3: info->name = "GF106"; break;
case 0xce: info->name = "GF114"; break;
case 0xcf: info->name = "GF116"; break;
case 0xc1: info->name = "GF108"; break;
case 0xc8: info->name = "GF110"; break;
case 0xd9: info->name = "GF119"; break;
case 0xd7: info->name = "GF117"; break;

/* kepler */
case 0xe4: info->name = "GK104"; break;
case 0xe6: info->name = "GK106"; break;
case 0xe7: info->name = "GK107"; break;
case 0xf0: info->name = "GK110"; break;
case 0xf1: info->name = "GK110B"; break;
case 0x108: info->name = "GK208"; break;

/* wtf */
default: info->name = "???";
}
} else {
/* pre-NV10 */
if (pmc_id & 0xf000) {
if (pmc_id & 0xf00000) {
info->chipset = 5;
info->name = "NV05";
} else {
info->chipset = 4;
info->name = "NV04";
}
info->card_type = 4;
} else {
info->chipset = pmc_id >> 16 & 0xf;
info->card_type = info->chipset;
if (info->chipset == 1) {
info->name = "NV01";
} else if (info->chipset == 3) {
if ((pmc_id & 0xff) >= 0x20) {
info->name = "NV03T";
info->is_nv03t = 1;
} else {
info->name = "NV03";
}
} else {
info->name = "???";
}
}
}
return 0;
}

int is_igp(int chipset) {
switch (chipset) {
Expand Down

0 comments on commit de57843

Please sign in to comment.