first commit
This commit is contained in:
2
include/nva/README.md
Normal file
2
include/nva/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
Copyright (C) envytools
|
||||
https://github.com/envytools/envytools
|
||||
17
include/nva/bus.h
Normal file
17
include/nva/bus.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* This file is auto-generated -- do not edit. */
|
||||
#ifndef CGEN_BUS_H
|
||||
#define CGEN_BUS_H
|
||||
|
||||
enum bus_interface_index {
|
||||
BUS_PCI,
|
||||
BUS_PCIE,
|
||||
BUS_IGP,
|
||||
BUS_FLEX_IO,
|
||||
BUS_TEGRA,
|
||||
NUM_BUS_INTERFACE,
|
||||
BUS_INTERFACE_UNKNOWN = NUM_BUS_INTERFACE,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
185
include/nva/chipset.c
Normal file
185
include/nva/chipset.c
Normal file
@@ -0,0 +1,185 @@
|
||||
#include "chipset.h"
|
||||
#include "gpu.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static bool pmc_id_flipped(uint32_t pmc_id) {
|
||||
/*
|
||||
* For determining endianness, 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. This can happen on later cards, so
|
||||
* in this case we can rely on bits 8-11 to be zero without
|
||||
* byteswapping
|
||||
*/
|
||||
if (pmc_id & 0x80000000) {
|
||||
if (!(pmc_id & 0x00000080)) /* bit 7 is 0, we're flipped */
|
||||
return true;
|
||||
else /* bits 31 and 7 are both 1, rely on 8-11 instead */
|
||||
return !!(pmc_id & 0x00000F00);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int parse_pmc_id(uint32_t pmc_id, struct chipset_info *info) {
|
||||
/* First, detect PMC_ID format and endianness */
|
||||
memset(info, 0, sizeof *info);
|
||||
info->endian = 0;
|
||||
info->gpu = GPU_UNKNOWN;
|
||||
info->gpu_desc = 0;
|
||||
if (pmc_id_flipped(pmc_id)) {
|
||||
/* 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;
|
||||
}
|
||||
info->pmc_id = pmc_id;
|
||||
if (pmc_id & 0x80000000 && pmc_id & 0x00000F00) {
|
||||
/* bit 31 still set - ie. old bit 7 was set, and bits 8-11 are
|
||||
* still nonzero - BAR0 is broken */
|
||||
return -1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
for (int i = 0; i < NUM_GPU; i++) {
|
||||
if (gpu_list[i].id_valid && gpu_list[i].id == info->chipset) {
|
||||
info->gpu = i;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* pre-NV10 */
|
||||
if (pmc_id & 0xf000) {
|
||||
if (pmc_id & 0xf00000) {
|
||||
info->chipset = 5;
|
||||
info->gpu = GPU_NV5;
|
||||
} else {
|
||||
info->chipset = 4;
|
||||
info->gpu = GPU_NV4;
|
||||
}
|
||||
info->card_type = 4;
|
||||
} else {
|
||||
info->chipset = pmc_id >> 16 & 0xf;
|
||||
info->card_type = info->chipset;
|
||||
if (info->chipset == 1) {
|
||||
info->gpu = GPU_NV1;
|
||||
} else if (info->chipset == 3) {
|
||||
if ((pmc_id & 0xff) >= 0x20) {
|
||||
info->gpu = GPU_NV3T;
|
||||
} else {
|
||||
info->gpu = GPU_NV3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (info->gpu != GPU_UNKNOWN) {
|
||||
info->gpu_desc = &gpu_list[info->gpu];
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int is_igp(int chipset) {
|
||||
switch (chipset) {
|
||||
case 0x0a:
|
||||
case 0x1a:
|
||||
case 0x1f:
|
||||
case 0x2a:
|
||||
case 0x4e:
|
||||
case 0x4c:
|
||||
case 0x67:
|
||||
case 0x68:
|
||||
case 0x63:
|
||||
case 0xaa:
|
||||
case 0xac:
|
||||
case 0xaf:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int is_g7x(int chipset) {
|
||||
if (chipset < 0x46 || chipset == 0x4a || chipset == 0x4e || chipset == 0x50 || chipset >= 0x70)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pfb_type(int chipset) {
|
||||
if (chipset <3)
|
||||
return PFB_NV01;
|
||||
if (chipset < 0x10)
|
||||
return PFB_NV03;
|
||||
if (chipset < 0x1a || chipset == 0x34)
|
||||
return PFB_NV10;
|
||||
if (chipset < 0x20)
|
||||
return PFB_NONE; /* IGP */
|
||||
if (chipset < 0x40)
|
||||
return PFB_NV20;
|
||||
if (chipset == 0x40 || chipset == 0x45)
|
||||
return PFB_NV40;
|
||||
if (chipset != 0x44 && chipset != 0x46 && chipset != 0x4a && chipset < 0x4c)
|
||||
return PFB_NV41;
|
||||
if (chipset != 0x50 && chipset < 0x80)
|
||||
return PFB_NV44;
|
||||
if (chipset < 0xc0)
|
||||
return PFB_NV50;
|
||||
return PFB_NVC0;
|
||||
}
|
||||
|
||||
int get_maxparts(int chipset) {
|
||||
switch (chipset) {
|
||||
case 0x1a:
|
||||
case 0x1f:
|
||||
case 0x2a:
|
||||
case 0x4e:
|
||||
case 0x4c:
|
||||
case 0x67:
|
||||
case 0x68:
|
||||
case 0x63:
|
||||
return 0;
|
||||
case 0x10:
|
||||
case 0x15:
|
||||
case 0x11:
|
||||
case 0x17:
|
||||
case 0x18:
|
||||
case 0x20:
|
||||
case 0x25:
|
||||
case 0x28:
|
||||
case 0x30:
|
||||
case 0x35:
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
case 0x42:
|
||||
case 0x47:
|
||||
case 0x49:
|
||||
return 4;
|
||||
case 0x31:
|
||||
case 0x36:
|
||||
case 0x43:
|
||||
case 0x4b:
|
||||
return 2;
|
||||
case 0x44:
|
||||
case 0x4a:
|
||||
case 0x46:
|
||||
return 1;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
70
include/nva/chipset.h
Normal file
70
include/nva/chipset.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2012 Marcelina Kościelnicka <mwk@0x04.net>
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef NVHW_H
|
||||
#define NVHW_H
|
||||
|
||||
#include "gpu.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum pfb_type {
|
||||
PFB_NONE,
|
||||
PFB_NV01,
|
||||
PFB_NV03,
|
||||
PFB_NV10,
|
||||
PFB_NV20,
|
||||
PFB_NV40,
|
||||
PFB_NV41,
|
||||
PFB_NV44,
|
||||
PFB_NV50,
|
||||
PFB_NVC0,
|
||||
};
|
||||
|
||||
struct chipset_info {
|
||||
uint32_t pmc_id;
|
||||
int chipset;
|
||||
int card_type;
|
||||
int endian;
|
||||
enum gpu_index gpu;
|
||||
const struct gpu *gpu_desc;
|
||||
};
|
||||
|
||||
int parse_pmc_id(uint32_t pmc_id, struct chipset_info *info);
|
||||
|
||||
int is_igp(int chipset);
|
||||
int is_g7x(int chipset);
|
||||
int pfb_type(int chipset);
|
||||
int get_maxparts(int chipset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
41
include/nva/fb.h
Normal file
41
include/nva/fb.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* This file is auto-generated -- do not edit. */
|
||||
#ifndef CGEN_FB_H
|
||||
#define CGEN_FB_H
|
||||
|
||||
enum fb_gen_index {
|
||||
FB_NV1,
|
||||
FB_NV3,
|
||||
FB_NV3T,
|
||||
FB_NV4,
|
||||
FB_NV5,
|
||||
FB_NVA,
|
||||
FB_NV10,
|
||||
FB_NV1A,
|
||||
FB_NV1F,
|
||||
FB_NV20,
|
||||
FB_NV2A,
|
||||
FB_NV25,
|
||||
FB_NV30,
|
||||
FB_NV31,
|
||||
FB_NV35,
|
||||
FB_NV36,
|
||||
FB_NV40,
|
||||
FB_NV41,
|
||||
FB_NV43,
|
||||
FB_G70,
|
||||
FB_G73,
|
||||
FB_NV44,
|
||||
FB_G72,
|
||||
FB_C51,
|
||||
FB_MCP61,
|
||||
FB_G80,
|
||||
FB_MCP77,
|
||||
FB_GF100,
|
||||
FB_GK20A,
|
||||
NUM_FB_GEN,
|
||||
FB_GEN_UNKNOWN = NUM_FB_GEN,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
143
include/nva/gen.h
Normal file
143
include/nva/gen.h
Normal file
@@ -0,0 +1,143 @@
|
||||
#ifndef CGEN_GPU_H
|
||||
#define CGEN_GPU_H
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "bus.h"
|
||||
#include "fb.h"
|
||||
|
||||
enum gpu_gen_index {
|
||||
GEN_NV1,
|
||||
GEN_NV3,
|
||||
GEN_NV4,
|
||||
GEN_CELSIUS,
|
||||
GEN_KELVIN,
|
||||
GEN_RANKINE,
|
||||
GEN_CURIE,
|
||||
GEN_TESLA,
|
||||
GEN_FERMI,
|
||||
GEN_KEPLER,
|
||||
GEN_MAXWELL,
|
||||
GEN_PASCAL,
|
||||
GEN_VOLTA,
|
||||
GEN_TURING,
|
||||
NUM_GPU_GEN,
|
||||
GPU_GEN_UNKNOWN = NUM_GPU_GEN,
|
||||
};
|
||||
|
||||
enum gpu_index {
|
||||
GPU_NV1,
|
||||
GPU_NV3,
|
||||
GPU_NV3T,
|
||||
GPU_NV4,
|
||||
GPU_NV5,
|
||||
GPU_NV6,
|
||||
GPU_NVA,
|
||||
GPU_NV10,
|
||||
GPU_NV15,
|
||||
GPU_NV1A,
|
||||
GPU_NV11,
|
||||
GPU_NV17,
|
||||
GPU_NV1F,
|
||||
GPU_NV18,
|
||||
GPU_NV20,
|
||||
GPU_NV2A,
|
||||
GPU_NV25,
|
||||
GPU_NV28,
|
||||
GPU_NV30,
|
||||
GPU_NV35,
|
||||
GPU_NV31,
|
||||
GPU_NV36,
|
||||
GPU_NV34,
|
||||
GPU_NV40,
|
||||
GPU_NV45,
|
||||
GPU_NV41,
|
||||
GPU_NV42,
|
||||
GPU_NV43,
|
||||
GPU_NV44,
|
||||
GPU_NV44A,
|
||||
GPU_G70,
|
||||
GPU_G72,
|
||||
GPU_G71,
|
||||
GPU_G73,
|
||||
GPU_C51,
|
||||
GPU_MCP61,
|
||||
GPU_MCP67,
|
||||
GPU_MCP68,
|
||||
GPU_MCP73,
|
||||
GPU_RSX,
|
||||
GPU_G80,
|
||||
GPU_G84,
|
||||
GPU_G86,
|
||||
GPU_G92,
|
||||
GPU_G94,
|
||||
GPU_G96,
|
||||
GPU_G98,
|
||||
GPU_G200,
|
||||
GPU_MCP77,
|
||||
GPU_MCP79,
|
||||
GPU_GT215,
|
||||
GPU_GT216,
|
||||
GPU_GT218,
|
||||
GPU_MCP89,
|
||||
GPU_GF100,
|
||||
GPU_GF104,
|
||||
GPU_GF114,
|
||||
GPU_GF106,
|
||||
GPU_GF116,
|
||||
GPU_GF108,
|
||||
GPU_GF110,
|
||||
GPU_GF119,
|
||||
GPU_GF117,
|
||||
GPU_GK104,
|
||||
GPU_GK107,
|
||||
GPU_GK106,
|
||||
GPU_GK110,
|
||||
GPU_GK110B,
|
||||
GPU_GK210,
|
||||
GPU_GK208,
|
||||
GPU_GK208B,
|
||||
GPU_GK20A,
|
||||
GPU_GM107,
|
||||
GPU_GM108,
|
||||
GPU_GM204,
|
||||
GPU_GM200,
|
||||
GPU_GM206,
|
||||
GPU_GM20B,
|
||||
GPU_GP100,
|
||||
GPU_GP102,
|
||||
GPU_GP104,
|
||||
GPU_GP106,
|
||||
GPU_GP107,
|
||||
GPU_GP108,
|
||||
GPU_GP10B,
|
||||
GPU_GV100,
|
||||
GPU_GV11B,
|
||||
GPU_TU102,
|
||||
GPU_TU104,
|
||||
GPU_TU106,
|
||||
GPU_TU116,
|
||||
GPU_TU117,
|
||||
NUM_GPU,
|
||||
GPU_UNKNOWN = NUM_GPU,
|
||||
};
|
||||
|
||||
extern const struct gpu {
|
||||
const char *name;
|
||||
uint32_t id;
|
||||
bool id_valid;
|
||||
uint32_t pciid;
|
||||
bool pciid_valid;
|
||||
int pciid_varbits;
|
||||
bool pciid_varbits_valid;
|
||||
uint32_t bios_major;
|
||||
bool bios_major_valid;
|
||||
uint32_t bios_chip;
|
||||
bool bios_chip_valid;
|
||||
enum bus_interface_index bus;
|
||||
enum fb_gen_index fb;
|
||||
enum gpu_gen_index gen;
|
||||
} gpu_list[];
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
97
include/nva/gpu.c
Normal file
97
include/nva/gpu.c
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "gpu.h"
|
||||
|
||||
const struct gpu gpu_list[] = {
|
||||
{ "NV1", 0, false, 0x8, true, 1, true, 0, false, 0, false, BUS_PCI, FB_NV1, GEN_NV1, },
|
||||
{ "NV3", 0, false, 0x18, true, 1, true, 0, false, 0, false, BUS_PCI, FB_NV3, GEN_NV3, },
|
||||
{ "NV3T", 0, false, 0x18, true, 1, true, 0, false, 0, false, BUS_PCI, FB_NV3T, GEN_NV3, },
|
||||
{ "NV4", 0, false, 0x20, true, 0, true, 0, false, 0, false, BUS_PCI, FB_NV4, GEN_NV4, },
|
||||
{ "NV5", 0, false, 0x28, true, 2, true, 0x2, true, 0x5, true, BUS_PCI, FB_NV5, GEN_NV4, },
|
||||
{ "NV6", 0, false, 0x2c, true, 2, true, 0x2, true, 0x5, true, BUS_PCI, FB_NV5, GEN_NV4, },
|
||||
{ "NVA", 0, false, 0xa0, true, 0, true, 0x2, true, -1, false, BUS_PCI, FB_NVA, GEN_NV4, },
|
||||
{ "NV10", 0x10, true, 0x100, true, 2, true, 0x2, true, 0x10, true, BUS_PCI, FB_NV10, GEN_CELSIUS, },
|
||||
{ "NV15", 0x15, true, 0x150, true, 2, true, 0x3, true, 0x15, true, BUS_PCI, FB_NV10, GEN_CELSIUS, },
|
||||
{ "NV1A", 0x1a, true, 0x1a0, true, 2, true, 0x3, true, 0x1a, true, BUS_PCI, FB_NV1A, GEN_CELSIUS, },
|
||||
{ "NV11", 0x11, true, 0x110, true, 2, true, 0x3, true, 0x11, true, BUS_PCI, FB_NV10, GEN_CELSIUS, },
|
||||
{ "NV17", 0x17, true, 0x170, true, 4, true, 0x4, true, 0x17, true, BUS_PCI, FB_NV10, GEN_CELSIUS, },
|
||||
{ "NV1F", 0x1f, true, 0x1f0, true, 4, true, 0x4, true, 0x1f, true, BUS_PCI, FB_NV1F, GEN_CELSIUS, },
|
||||
{ "NV18", 0x18, true, 0x180, true, 4, true, 0x4, true, 0x18, true, BUS_PCI, FB_NV10, GEN_CELSIUS, },
|
||||
{ "NV20", 0x20, true, 0x200, true, 2, true, 0x3, true, 0x20, true, BUS_PCI, FB_NV20, GEN_KELVIN, },
|
||||
{ "NV2A", 0x2a, true, 0x2a0, true, 2, true, 0, false, 0, false, BUS_PCI, FB_NV2A, GEN_KELVIN, },
|
||||
{ "NV25", 0x25, true, 0x250, true, 4, true, 0x4, true, 0x25, true, BUS_PCI, FB_NV25, GEN_KELVIN, },
|
||||
{ "NV28", 0x28, true, 0x280, true, 4, true, 0x4, true, 0x28, true, BUS_PCI, FB_NV25, GEN_KELVIN, },
|
||||
{ "NV30", 0x30, true, 0x300, true, 4, true, 0x4, true, 0x30, true, BUS_PCI, FB_NV30, GEN_RANKINE, },
|
||||
{ "NV35", 0x35, true, 0x330, true, 4, true, 0x4, true, 0x35, true, BUS_PCI, FB_NV35, GEN_RANKINE, },
|
||||
{ "NV31", 0x31, true, 0x310, true, 4, true, 0x4, true, 0x31, true, BUS_PCI, FB_NV31, GEN_RANKINE, },
|
||||
{ "NV36", 0x36, true, 0x340, true, 4, true, 0x4, true, 0x36, true, BUS_PCI, FB_NV36, GEN_RANKINE, },
|
||||
{ "NV34", 0x34, true, 0x320, true, 4, true, 0x4, true, 0x34, true, BUS_PCI, FB_NV10, GEN_RANKINE, },
|
||||
{ "NV40", 0x40, true, 0x40, true, 4, true, 0x5, true, 0x40, true, BUS_PCI, FB_NV40, GEN_CURIE, },
|
||||
{ "NV45", 0x45, true, 0x40, true, 4, true, 0x5, true, 0x40, true, BUS_PCI, FB_NV40, GEN_CURIE, },
|
||||
{ "NV41", 0x41, true, 0xc0, true, 4, true, 0x5, true, 0x41, true, BUS_PCIE, FB_NV41, GEN_CURIE, },
|
||||
{ "NV42", 0x42, true, 0xc0, true, 4, true, 0x5, true, 0x41, true, BUS_PCIE, FB_NV41, GEN_CURIE, },
|
||||
{ "NV43", 0x43, true, 0x140, true, 4, true, 0x5, true, 0x43, true, BUS_PCIE, FB_NV43, GEN_CURIE, },
|
||||
{ "NV44", 0x44, true, 0x160, true, 4, true, 0x5, true, 0x44, true, BUS_PCIE, FB_NV44, GEN_CURIE, },
|
||||
{ "NV44A", 0x4a, true, 0x220, true, 4, true, 0x5, true, 0x44, true, BUS_PCI, FB_NV44, GEN_CURIE, },
|
||||
{ "G70", 0x47, true, 0x90, true, 4, true, 0x5, true, 0x70, true, BUS_PCIE, FB_G70, GEN_CURIE, },
|
||||
{ "G72", 0x46, true, 0x1d0, true, 4, true, 0x5, true, 0x72, true, BUS_PCIE, FB_G72, GEN_CURIE, },
|
||||
{ "G71", 0x49, true, 0x290, true, 4, true, 0x5, true, 0x71, true, BUS_PCIE, FB_G70, GEN_CURIE, },
|
||||
{ "G73", 0x4b, true, 0x390, true, 4, true, 0x5, true, 0x73, true, BUS_PCIE, FB_G73, GEN_CURIE, },
|
||||
{ "C51", 0x4e, true, 0x240, true, 4, true, 0x5, true, 0x51, true, BUS_IGP, FB_C51, GEN_CURIE, },
|
||||
{ "MCP61", 0x4c, true, 0x3d0, true, 4, true, 0x5, true, 0x61, true, BUS_IGP, FB_MCP61, GEN_CURIE, },
|
||||
{ "MCP67", 0x67, true, 0x530, true, 4, true, 0x5, true, 0x67, true, BUS_IGP, FB_MCP61, GEN_CURIE, },
|
||||
{ "MCP68", 0x68, true, 0x530, true, 4, true, 0x5, true, 0x67, true, BUS_IGP, FB_MCP61, GEN_CURIE, },
|
||||
{ "MCP73", 0x63, true, 0x7e0, true, 4, true, 0x5, true, 0x73, true, BUS_IGP, FB_MCP61, GEN_CURIE, },
|
||||
{ "RSX", 0x4d, true, 0, false, 4, true, 0, false, 0, false, BUS_FLEX_IO, FB_G72, GEN_CURIE, },
|
||||
{ "G80", 0x50, true, 0x190, true, 4, true, 0x60, true, 0x80, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "G84", 0x84, true, 0x400, true, 4, true, 0x60, true, 0x84, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "G86", 0x86, true, 0x420, true, 4, true, 0x60, true, 0x86, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "G92", 0x92, true, 0x600, true, 5, true, 0x62, true, 0x92, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "G94", 0x94, true, 0x620, true, 5, true, 0x62, true, 0x94, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "G96", 0x96, true, 0x640, true, 5, true, 0x62, true, 0x94, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "G98", 0x98, true, 0x6e0, true, 5, true, 0x62, true, 0x98, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "G200", 0xa0, true, 0x5e0, true, 5, true, 0x62, true, 0x0, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "MCP77", 0xaa, true, 0x840, true, 5, true, 0x62, true, 0x77, true, BUS_IGP, FB_MCP77, GEN_TESLA, },
|
||||
{ "MCP79", 0xac, true, 0x860, true, 5, true, 0x62, true, 0x79, true, BUS_IGP, FB_MCP77, GEN_TESLA, },
|
||||
{ "GT215", 0xa3, true, 0xca0, true, 5, true, 0x70, true, 0x15, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "GT216", 0xa5, true, 0xa20, true, 5, true, 0x70, true, 0x16, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "GT218", 0xa8, true, 0xa60, true, 5, true, 0x70, true, 0x18, true, BUS_PCIE, FB_G80, GEN_TESLA, },
|
||||
{ "MCP89", 0xaf, true, 0x8a0, true, 5, true, 0x70, true, 0x89, true, BUS_IGP, FB_MCP77, GEN_TESLA, },
|
||||
{ "GF100", 0xc0, true, 0x6c0, true, 5, true, 0x70, true, 0x0, true, BUS_PCIE, FB_GF100, GEN_FERMI, },
|
||||
{ "GF104", 0xc4, true, 0xe20, true, 5, true, 0x70, true, 0x4, true, BUS_PCIE, FB_GF100, GEN_FERMI, },
|
||||
{ "GF114", 0xce, true, 0x1200, true, 5, true, 0x70, true, 0x24, true, BUS_PCIE, FB_GF100, GEN_FERMI, },
|
||||
{ "GF106", 0xc3, true, 0xdc0, true, 5, true, 0x70, true, 0x6, true, BUS_PCIE, FB_GF100, GEN_FERMI, },
|
||||
{ "GF116", 0xcf, true, 0x1240, true, 5, true, 0x70, true, 0x26, true, BUS_PCIE, FB_GF100, GEN_FERMI, },
|
||||
{ "GF108", 0xc1, true, 0xde0, true, 5, true, 0x70, true, 0x8, true, BUS_PCIE, FB_GF100, GEN_FERMI, },
|
||||
{ "GF110", 0xc8, true, 0x1080, true, 5, true, 0x70, true, 0x10, true, BUS_PCIE, FB_GF100, GEN_FERMI, },
|
||||
{ "GF119", 0xd9, true, 0x1040, true, 6, true, 0x75, true, 0x19, true, BUS_PCIE, FB_GF100, GEN_FERMI, },
|
||||
{ "GF117", 0xd7, true, 0x1140, true, 6, true, 0x75, true, -1, false, BUS_PCIE, FB_GF100, GEN_FERMI, },
|
||||
{ "GK104", 0xe4, true, 0x1180, true, 6, true, 0x80, true, 0x4, true, BUS_PCIE, FB_GF100, GEN_KEPLER, },
|
||||
{ "GK107", 0xe7, true, 0xfc0, true, 6, true, 0x80, true, 0x7, true, BUS_PCIE, FB_GF100, GEN_KEPLER, },
|
||||
{ "GK106", 0xe6, true, 0x11c0, true, 6, true, 0x80, true, 0x6, true, BUS_PCIE, FB_GF100, GEN_KEPLER, },
|
||||
{ "GK110", 0xf0, true, 0x1000, true, 6, true, 0x80, true, 0x10, true, BUS_PCIE, FB_GF100, GEN_KEPLER, },
|
||||
{ "GK110B", 0xf1, true, 0x1000, true, 6, true, 0x80, true, 0x80, true, BUS_PCIE, FB_GF100, GEN_KEPLER, },
|
||||
{ "GK210", -1, false, -1, false, 6, true, 0x80, true, -1, false, BUS_PCIE, FB_GF100, GEN_KEPLER, },
|
||||
{ "GK208", 0x108, true, 0x1280, true, 6, true, 0x80, true, 0x28, true, BUS_PCIE, FB_GF100, GEN_KEPLER, },
|
||||
{ "GK208B", 0x106, true, 0x1280, true, 6, true, 0x80, true, 0x28, true, BUS_PCIE, FB_GF100, GEN_KEPLER, },
|
||||
{ "GK20A", 0xea, true, 0, false, 6, true, 0, false, 0, false, BUS_TEGRA, FB_GK20A, GEN_KEPLER, },
|
||||
{ "GM107", 0x117, true, 0x1380, true, 6, true, 0x82, true, 0x7, true, BUS_PCIE, FB_GF100, GEN_MAXWELL, },
|
||||
{ "GM108", 0x118, true, 0x1340, true, 6, true, 0x82, true, 0x8, true, BUS_PCIE, FB_GF100, GEN_MAXWELL, },
|
||||
{ "GM204", 0x124, true, 0x13c0, true, 6, true, 0x84, true, 0x4, true, BUS_PCIE, FB_GF100, GEN_MAXWELL, },
|
||||
{ "GM200", 0x120, true, 0x17c0, true, 6, true, 0x84, true, 0x0, true, BUS_PCIE, FB_GF100, GEN_MAXWELL, },
|
||||
{ "GM206", 0x126, true, 0x1400, true, 6, true, 0x84, true, 0x6, true, BUS_PCIE, FB_GF100, GEN_MAXWELL, },
|
||||
{ "GM20B", 0x12b, true, 0, false, 6, true, 0, false, 0, false, BUS_TEGRA, FB_GK20A, GEN_MAXWELL, },
|
||||
{ "GP100", 0x130, true, 0x1580, true, 7, true, 0x86, true, 0x0, true, BUS_PCIE, FB_GF100, GEN_PASCAL, },
|
||||
{ "GP102", 0x132, true, 0x1b00, true, 7, true, 0x86, true, 0x2, true, BUS_PCIE, FB_GF100, GEN_PASCAL, },
|
||||
{ "GP104", 0x134, true, 0x1b80, true, 7, true, 0x86, true, 0x4, true, BUS_PCIE, FB_GF100, GEN_PASCAL, },
|
||||
{ "GP106", 0x136, true, 0x1c00, true, 7, true, 0x86, true, 0x6, true, BUS_PCIE, FB_GF100, GEN_PASCAL, },
|
||||
{ "GP107", 0x137, true, 0x1c80, true, 7, true, 0x86, true, 0x7, true, BUS_PCIE, FB_GF100, GEN_PASCAL, },
|
||||
{ "GP108", 0x138, true, 0x1d00, true, 7, true, 0x86, true, 0x8, true, BUS_PCIE, FB_GF100, GEN_PASCAL, },
|
||||
{ "GP10B", 0x13b, true, 0x10e5, true, 7, true, 0, false, 0, false, BUS_TEGRA, FB_GF100, GEN_PASCAL, },
|
||||
{ "GV100", 0x140, true, 0x1d80, true, 7, true, 0x88, true, 0x0, true, BUS_PCIE, FB_GF100, GEN_VOLTA, },
|
||||
{ "GV11B", 0x15b, true, 0, false, 7, true, 0, false, 0, false, BUS_TEGRA, FB_GF100, GEN_VOLTA, },
|
||||
{ "TU102", 0x162, true, 0x1e00, true, 7, true, 0x90, true, 0x2, true, BUS_PCIE, FB_GF100, GEN_TURING, },
|
||||
{ "TU104", 0x164, true, 0x1e80, true, 7, true, 0x90, true, 0x4, true, BUS_PCIE, FB_GF100, GEN_TURING, },
|
||||
{ "TU106", 0x166, true, 0x1f00, true, 7, true, 0x90, true, 0x6, true, BUS_PCIE, FB_GF100, GEN_TURING, },
|
||||
{ "TU116", 0x168, true, 0x2180, true, 7, true, 0x90, true, 0x16, true, BUS_PCIE, FB_GF100, GEN_TURING, },
|
||||
{ "TU117", 0x167, true, 0x1f80, true, 7, true, 0x90, true, 0x17, true, BUS_PCIE, FB_GF100, GEN_TURING, },
|
||||
};
|
||||
|
||||
143
include/nva/gpu.h
Normal file
143
include/nva/gpu.h
Normal file
@@ -0,0 +1,143 @@
|
||||
#ifndef CGEN_GPU_H
|
||||
#define CGEN_GPU_H
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "bus.h"
|
||||
#include "fb.h"
|
||||
|
||||
enum gpu_gen_index {
|
||||
GEN_NV1,
|
||||
GEN_NV3,
|
||||
GEN_NV4,
|
||||
GEN_CELSIUS,
|
||||
GEN_KELVIN,
|
||||
GEN_RANKINE,
|
||||
GEN_CURIE,
|
||||
GEN_TESLA,
|
||||
GEN_FERMI,
|
||||
GEN_KEPLER,
|
||||
GEN_MAXWELL,
|
||||
GEN_PASCAL,
|
||||
GEN_VOLTA,
|
||||
GEN_TURING,
|
||||
NUM_GPU_GEN,
|
||||
GPU_GEN_UNKNOWN = NUM_GPU_GEN,
|
||||
};
|
||||
|
||||
enum gpu_index {
|
||||
GPU_NV1,
|
||||
GPU_NV3,
|
||||
GPU_NV3T,
|
||||
GPU_NV4,
|
||||
GPU_NV5,
|
||||
GPU_NV6,
|
||||
GPU_NVA,
|
||||
GPU_NV10,
|
||||
GPU_NV15,
|
||||
GPU_NV1A,
|
||||
GPU_NV11,
|
||||
GPU_NV17,
|
||||
GPU_NV1F,
|
||||
GPU_NV18,
|
||||
GPU_NV20,
|
||||
GPU_NV2A,
|
||||
GPU_NV25,
|
||||
GPU_NV28,
|
||||
GPU_NV30,
|
||||
GPU_NV35,
|
||||
GPU_NV31,
|
||||
GPU_NV36,
|
||||
GPU_NV34,
|
||||
GPU_NV40,
|
||||
GPU_NV45,
|
||||
GPU_NV41,
|
||||
GPU_NV42,
|
||||
GPU_NV43,
|
||||
GPU_NV44,
|
||||
GPU_NV44A,
|
||||
GPU_G70,
|
||||
GPU_G72,
|
||||
GPU_G71,
|
||||
GPU_G73,
|
||||
GPU_C51,
|
||||
GPU_MCP61,
|
||||
GPU_MCP67,
|
||||
GPU_MCP68,
|
||||
GPU_MCP73,
|
||||
GPU_RSX,
|
||||
GPU_G80,
|
||||
GPU_G84,
|
||||
GPU_G86,
|
||||
GPU_G92,
|
||||
GPU_G94,
|
||||
GPU_G96,
|
||||
GPU_G98,
|
||||
GPU_G200,
|
||||
GPU_MCP77,
|
||||
GPU_MCP79,
|
||||
GPU_GT215,
|
||||
GPU_GT216,
|
||||
GPU_GT218,
|
||||
GPU_MCP89,
|
||||
GPU_GF100,
|
||||
GPU_GF104,
|
||||
GPU_GF114,
|
||||
GPU_GF106,
|
||||
GPU_GF116,
|
||||
GPU_GF108,
|
||||
GPU_GF110,
|
||||
GPU_GF119,
|
||||
GPU_GF117,
|
||||
GPU_GK104,
|
||||
GPU_GK107,
|
||||
GPU_GK106,
|
||||
GPU_GK110,
|
||||
GPU_GK110B,
|
||||
GPU_GK210,
|
||||
GPU_GK208,
|
||||
GPU_GK208B,
|
||||
GPU_GK20A,
|
||||
GPU_GM107,
|
||||
GPU_GM108,
|
||||
GPU_GM204,
|
||||
GPU_GM200,
|
||||
GPU_GM206,
|
||||
GPU_GM20B,
|
||||
GPU_GP100,
|
||||
GPU_GP102,
|
||||
GPU_GP104,
|
||||
GPU_GP106,
|
||||
GPU_GP107,
|
||||
GPU_GP108,
|
||||
GPU_GP10B,
|
||||
GPU_GV100,
|
||||
GPU_GV11B,
|
||||
GPU_TU102,
|
||||
GPU_TU104,
|
||||
GPU_TU106,
|
||||
GPU_TU116,
|
||||
GPU_TU117,
|
||||
NUM_GPU,
|
||||
GPU_UNKNOWN = NUM_GPU,
|
||||
};
|
||||
|
||||
extern const struct gpu {
|
||||
const char *name;
|
||||
uint32_t id;
|
||||
bool id_valid;
|
||||
uint32_t pciid;
|
||||
bool pciid_valid;
|
||||
int pciid_varbits;
|
||||
bool pciid_varbits_valid;
|
||||
uint32_t bios_major;
|
||||
bool bios_major_valid;
|
||||
uint32_t bios_chip;
|
||||
bool bios_chip_valid;
|
||||
enum bus_interface_index bus;
|
||||
enum fb_gen_index fb;
|
||||
enum gpu_gen_index gen;
|
||||
} gpu_list[];
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
351
include/nva/nva.c
Normal file
351
include/nva/nva.c
Normal file
@@ -0,0 +1,351 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <pciaccess.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "nva.h"
|
||||
#include "util.h"
|
||||
#include "chipset.h"
|
||||
|
||||
#define PLATFORM_DEVICES_DIR "/sys/bus/platform/devices"
|
||||
|
||||
struct nva_card **nva_cards = 0;
|
||||
int nva_cardsnum = 0;
|
||||
int nva_cardsmax = 0;
|
||||
int nva_vgaarberr = 0;
|
||||
|
||||
struct pci_id_match nv_gpu_match[] = {
|
||||
{0x104a, 0x0009, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0},
|
||||
{0x12d2, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0x30000, 0xffff0000},
|
||||
{0x10de, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0x30000, 0xffff0000},
|
||||
{0x10de, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0x48000, 0xffffff00},
|
||||
};
|
||||
|
||||
struct pci_id_match nv_apu_match[] = {
|
||||
{0x10de, 0x01b0, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0},
|
||||
{0x10de, 0x006b, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0},
|
||||
};
|
||||
|
||||
struct pci_id_match nv_smu_match[] = {
|
||||
{0x10de, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0xb4000, 0xffffff00},
|
||||
};
|
||||
|
||||
struct pci_id_match nv_eth_match[] = {
|
||||
{0x10de, 0x01c3, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP */
|
||||
{0x10de, 0x0066, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP2 */
|
||||
{0x10de, 0x0086, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP2A - network class */
|
||||
{0x10de, 0x008c, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP2A - bridge class */
|
||||
{0x10de, 0x00d6, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* CK8 */
|
||||
{0x10de, 0x00e6, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* CK8S - network class */
|
||||
{0x10de, 0x00df, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* CK8S - bridge class */
|
||||
{0x10de, 0x0056, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* CK804 - network class */
|
||||
{0x10de, 0x0057, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* CK804 - bridge class */
|
||||
{0x10de, 0x0037, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP04 - network class */
|
||||
{0x10de, 0x0038, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP04 - bridge class */
|
||||
{0x10de, 0x0268, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP51 - network class */
|
||||
{0x10de, 0x0269, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP51 - bridge class */
|
||||
{0x10de, 0x0372, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP55 - network class */
|
||||
{0x10de, 0x0373, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP55 - bridge class */
|
||||
{0x10de, 0x03e5, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP61 ? */
|
||||
{0x10de, 0x03e6, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP61 ? */
|
||||
{0x10de, 0x03ee, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP61 ? */
|
||||
{0x10de, 0x03ef, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP61 - bridge class */
|
||||
{0x10de, 0x0450, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP65 - network class */
|
||||
{0x10de, 0x0451, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP65 ? */
|
||||
{0x10de, 0x0452, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP65 - bridge class */
|
||||
{0x10de, 0x0453, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP65 ? */
|
||||
{0x10de, 0x054c, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP67 - network class */
|
||||
{0x10de, 0x054d, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP67 ? */
|
||||
{0x10de, 0x054e, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP67 ? */
|
||||
{0x10de, 0x054f, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP67 ? */
|
||||
{0x10de, 0x07dc, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP73 - network class */
|
||||
{0x10de, 0x07dd, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP73 ? */
|
||||
{0x10de, 0x07de, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP73 ? */
|
||||
{0x10de, 0x07df, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP73 ? */
|
||||
{0x10de, 0x0760, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77 - network class */
|
||||
{0x10de, 0x0761, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77 ? */
|
||||
{0x10de, 0x0762, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77 ? */
|
||||
{0x10de, 0x0763, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77 ? */
|
||||
{0x10de, 0x0764, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77 - bridge class */
|
||||
{0x10de, 0x0765, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77 ? */
|
||||
{0x10de, 0x0766, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77 ? */
|
||||
{0x10de, 0x0767, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77 ? */
|
||||
{0x10de, 0x0ab0, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP79 - network class */
|
||||
{0x10de, 0x0ab1, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP79 ? */
|
||||
{0x10de, 0x0ab2, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP79 ? */
|
||||
{0x10de, 0x0ab3, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP79 ? */
|
||||
{0x10de, 0x0570, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 0 */
|
||||
{0x10de, 0x0571, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 1 */
|
||||
{0x10de, 0x0572, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 2 */
|
||||
{0x10de, 0x0573, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 3 */
|
||||
{0x10de, 0x0574, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 4 */
|
||||
{0x10de, 0x0575, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 5 */
|
||||
{0x10de, 0x0576, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 6 */
|
||||
{0x10de, 0x0577, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 7 */
|
||||
{0x10de, 0x0578, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 8 */
|
||||
{0x10de, 0x0579, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 9 */
|
||||
{0x10de, 0x057a, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 10 */
|
||||
{0x10de, 0x057b, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 11 */
|
||||
{0x10de, 0x057c, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 12 */
|
||||
{0x10de, 0x057d, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 13 */
|
||||
{0x10de, 0x057e, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 14 */
|
||||
{0x10de, 0x057f, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP77/MCP79 alt 15 */
|
||||
{0x10de, 0x0d7d, PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0}, /* MCP89 */
|
||||
};
|
||||
|
||||
struct nva_card *nva_init_gpu(struct pci_device *dev) {
|
||||
struct nva_card *card = calloc(sizeof *card, 1);
|
||||
if (!card)
|
||||
return 0;
|
||||
card->type = NVA_DEVICE_GPU;
|
||||
card->bus_type = NVA_BUS_PCI;
|
||||
card->bus.pci = dev;
|
||||
int ret = pci_device_map_range(dev, dev->regions[0].base_addr, dev->regions[0].size, PCI_DEV_MAP_FLAG_WRITABLE, &card->bar0);
|
||||
if (ret) {
|
||||
fprintf (stderr, "WARN: Can't probe %04x:%02x:%02x.%x\n", dev->domain, dev->bus, dev->dev, dev->func);
|
||||
free(card);
|
||||
return 0;
|
||||
}
|
||||
card->bar0len = dev->regions[0].size;
|
||||
if (dev->regions[1].size) {
|
||||
card->hasbar1 = 1;
|
||||
card->bar1len = dev->regions[1].size;
|
||||
ret = pci_device_map_range(dev, dev->regions[1].base_addr, dev->regions[1].size, PCI_DEV_MAP_FLAG_WRITABLE, &card->bar1);
|
||||
if (ret) {
|
||||
card->bar1 = 0;
|
||||
}
|
||||
}
|
||||
if (dev->regions[2].size && !dev->regions[2].is_IO) {
|
||||
card->hasbar2 = 1;
|
||||
card->bar2len = dev->regions[2].size;
|
||||
ret = pci_device_map_range(dev, dev->regions[2].base_addr, dev->regions[2].size, PCI_DEV_MAP_FLAG_WRITABLE, &card->bar2);
|
||||
if (ret) {
|
||||
card->bar2 = 0;
|
||||
}
|
||||
} else if (dev->regions[3].size) {
|
||||
card->hasbar2 = 1;
|
||||
card->bar2len = dev->regions[3].size;
|
||||
ret = pci_device_map_range(dev, dev->regions[3].base_addr, dev->regions[3].size, PCI_DEV_MAP_FLAG_WRITABLE, &card->bar2);
|
||||
if (ret) {
|
||||
card->bar2 = 0;
|
||||
}
|
||||
}
|
||||
/* ignore errors */
|
||||
pci_device_map_legacy(dev, 0, 0x100000, PCI_DEV_MAP_FLAG_WRITABLE, &card->rawmem);
|
||||
card->rawio = pci_legacy_open_io(dev, 0, 0x10000);
|
||||
int iobar = -1;
|
||||
if (dev->regions[2].size && dev->regions[2].is_IO)
|
||||
iobar = 2;
|
||||
if (dev->regions[5].size && dev->regions[5].is_IO)
|
||||
iobar = 5;
|
||||
if (iobar != -1) {
|
||||
card->iobar = pci_device_open_io(dev, dev->regions[iobar].base_addr, dev->regions[iobar].size);
|
||||
card->iobarlen = dev->regions[iobar].size;
|
||||
}
|
||||
uint32_t pmc_id = nva_grd32(card->bar0, 0);
|
||||
parse_pmc_id(pmc_id, &card->chipset);
|
||||
return card;
|
||||
}
|
||||
|
||||
struct nva_card *nva_init_smu(struct pci_device *dev) {
|
||||
struct nva_card *card = calloc(sizeof *card, 1);
|
||||
if (!card)
|
||||
return 0;
|
||||
card->type = NVA_DEVICE_SMU;
|
||||
card->bus_type = NVA_BUS_PCI;
|
||||
card->bus.pci = dev;
|
||||
int ret = pci_device_map_range(dev, dev->regions[0].base_addr, dev->regions[0].size, PCI_DEV_MAP_FLAG_WRITABLE, &card->bar0);
|
||||
if (ret) {
|
||||
fprintf (stderr, "WARN: Can't probe %04x:%02x:%02x.%x\n", dev->domain, dev->bus, dev->dev, dev->func);
|
||||
free(card);
|
||||
return 0;
|
||||
}
|
||||
card->bar0len = dev->regions[0].size;
|
||||
return card;
|
||||
}
|
||||
|
||||
struct nva_card *nva_init_apu(struct pci_device *dev) {
|
||||
struct nva_card *card = calloc(sizeof *card, 1);
|
||||
if (!card)
|
||||
return 0;
|
||||
card->type = NVA_DEVICE_APU;
|
||||
card->bus_type = NVA_BUS_PCI;
|
||||
card->bus.pci = dev;
|
||||
int ret = pci_device_map_range(dev, dev->regions[0].base_addr, dev->regions[0].size, PCI_DEV_MAP_FLAG_WRITABLE, &card->bar0);
|
||||
if (ret) {
|
||||
fprintf (stderr, "WARN: Can't probe %04x:%02x:%02x.%x\n", dev->domain, dev->bus, dev->dev, dev->func);
|
||||
free(card);
|
||||
return 0;
|
||||
}
|
||||
card->bar0len = dev->regions[0].size;
|
||||
return card;
|
||||
}
|
||||
|
||||
struct nva_card *nva_init_eth(struct pci_device *dev) {
|
||||
struct nva_card *card = calloc(sizeof *card, 1);
|
||||
if (!card)
|
||||
return 0;
|
||||
card->type = NVA_DEVICE_ETH;
|
||||
card->bus_type = NVA_BUS_PCI;
|
||||
card->bus.pci = dev;
|
||||
int ret = pci_device_map_range(dev, dev->regions[0].base_addr, dev->regions[0].size, PCI_DEV_MAP_FLAG_WRITABLE, &card->bar0);
|
||||
if (ret) {
|
||||
fprintf (stderr, "WARN: Can't probe %04x:%02x:%02x.%x\n", dev->domain, dev->bus, dev->dev, dev->func);
|
||||
free(card);
|
||||
return 0;
|
||||
}
|
||||
card->bar0len = dev->regions[0].size;
|
||||
return card;
|
||||
}
|
||||
|
||||
static int check_modalias(const char *node_name) {
|
||||
char path[PATH_MAX];
|
||||
char buffer[255] = { 0 };
|
||||
FILE *file;
|
||||
|
||||
/* Check if the GPU is indeed made by NVIDIA by checking the compatibility
|
||||
* field of the device tree, exposed to the userspace via modalias. As
|
||||
* we are lazy, let's not parse the modalias string but just check if
|
||||
* it mentions nvidia at all. If it does, return 0.
|
||||
*/
|
||||
|
||||
snprintf(path, PATH_MAX, "%s/%s/modalias", PLATFORM_DEVICES_DIR, node_name);
|
||||
if (!(file = fopen(path, "r"))) {
|
||||
return 2;
|
||||
}
|
||||
fread(buffer, 1, sizeof(buffer), file);
|
||||
fclose(file);
|
||||
return strstr(buffer, "nvidia") == NULL;
|
||||
}
|
||||
|
||||
struct nva_card *nva_init_platform() {
|
||||
uint32_t tmp, bar0 = 0xffffffff;
|
||||
struct nva_card *card;
|
||||
struct dirent *dent;
|
||||
DIR *dir;
|
||||
int fd;
|
||||
|
||||
/* Look for a gpu on the "platform" bus by looking at the platform bus,
|
||||
* looking for an entry such as '/sys/bus/platform/devices/57000000.gpu'.
|
||||
* We only expect up to one entry. This will not pick up the GPUs older
|
||||
* than the tk1 because there was no "gpu" node before that, only gr2d
|
||||
* and gr3d.
|
||||
*/
|
||||
if (!(dir = opendir(PLATFORM_DEVICES_DIR)))
|
||||
return NULL;
|
||||
while ((dent = readdir(dir))) {
|
||||
/* FIXME: this may not work on downstream kernels */
|
||||
const char *last_four = dent->d_name + strlen(dent->d_name) - 4;
|
||||
if (strcmp(last_four, ".gpu") == 0) {
|
||||
if (sscanf(dent->d_name, "%x.gpu", &tmp) == 1) {
|
||||
/* Check if the modalias contains nvidia */
|
||||
if (check_modalias(dent->d_name))
|
||||
continue;
|
||||
|
||||
/* We have found the gpu, exit the loop */
|
||||
bar0 = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
if (bar0 == 0xffffffff)
|
||||
return NULL;
|
||||
|
||||
/* we have found a gpu */
|
||||
card = calloc(sizeof *card, 1);
|
||||
if (!card)
|
||||
return 0;
|
||||
card->type = NVA_DEVICE_GPU;
|
||||
card->bus_type = NVA_BUS_PLATFORM;
|
||||
card->bus.platform_address = bar0;
|
||||
|
||||
if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
|
||||
fprintf (stderr, "WARN: Can't open /dev/mem. Are you root?\n");
|
||||
free(card);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf (stdout, "bar0: 0x%x\n", bar0);
|
||||
|
||||
card->bar0 = mmap(0, 0x1000000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, bar0);
|
||||
if (!card->bar0) {
|
||||
fprintf (stderr, "WARN: Can't map the physical address 0x%x\n", bar0);
|
||||
free(card);
|
||||
return 0;
|
||||
}
|
||||
card->bar0len = 0x1000000;
|
||||
|
||||
uint32_t pmc_id = nva_grd32(card->bar0, 0);
|
||||
parse_pmc_id(pmc_id, &card->chipset);
|
||||
|
||||
/* Enable bar1 for the devices we know because I cannot figure out how
|
||||
* to read the relevant part of the DT via sysfs...
|
||||
*/
|
||||
if (card->chipset.chipset == 0xea) {
|
||||
card->hasbar1 = 1;
|
||||
card->bar1len = 0x1000000;
|
||||
card->bar1 = mmap(0, 0x1000000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x58000000);
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
struct {
|
||||
struct pci_id_match *match;
|
||||
size_t len;
|
||||
struct nva_card *(*func) (struct pci_device *dev);
|
||||
} nva_types[] = {
|
||||
{ nv_gpu_match, ARRAY_SIZE(nv_gpu_match), nva_init_gpu },
|
||||
{ nv_smu_match, ARRAY_SIZE(nv_smu_match), nva_init_smu },
|
||||
{ nv_apu_match, ARRAY_SIZE(nv_apu_match), nva_init_apu },
|
||||
{ nv_eth_match, ARRAY_SIZE(nv_eth_match), nva_init_eth },
|
||||
};
|
||||
|
||||
int nva_init() {
|
||||
int ret;
|
||||
ret = pci_system_init();
|
||||
if (ret)
|
||||
return -1;
|
||||
nva_vgaarberr = pci_device_vgaarb_init();
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(nva_types); i++) {
|
||||
for (j = 0; j < nva_types[i].len; j++) {
|
||||
struct pci_device_iterator* it = pci_id_match_iterator_create(&nva_types[i].match[j]);
|
||||
if (!it) {
|
||||
pci_system_cleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct pci_device *dev;
|
||||
while ((dev = pci_device_next(it))) {
|
||||
ret = pci_device_probe(dev);
|
||||
if (ret) {
|
||||
fprintf (stderr, "WARN: Can't probe %04x:%02x:%02x.%x\n", dev->domain, dev->bus, dev->dev, dev->func);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
struct nva_card *card = nva_types[i].func(dev);
|
||||
if (card)
|
||||
ADDARRAY(nva_cards, card);
|
||||
}
|
||||
pci_iterator_destroy(it);
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, try reading the platform */
|
||||
struct nva_card *card = nva_init_platform();
|
||||
if (card)
|
||||
ADDARRAY(nva_cards, card);
|
||||
|
||||
return (nva_cardsnum == 0);
|
||||
}
|
||||
168
include/nva/nva.h
Normal file
168
include/nva/nva.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2011 Marcelina Kościelnicka <mwk@0x04.net>
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef NVA_H
|
||||
#define NVA_H
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "chipset.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum nva_card_type {
|
||||
NVA_DEVICE_GPU,
|
||||
NVA_DEVICE_APU,
|
||||
NVA_DEVICE_SMU,
|
||||
NVA_DEVICE_ETH,
|
||||
};
|
||||
|
||||
enum nva_bus_type {
|
||||
NVA_BUS_PCI,
|
||||
NVA_BUS_PLATFORM,
|
||||
};
|
||||
|
||||
struct nva_card {
|
||||
enum nva_card_type type;
|
||||
enum nva_bus_type bus_type;
|
||||
union {
|
||||
struct pci_device *pci;
|
||||
uint32_t platform_address;
|
||||
} bus;
|
||||
struct chipset_info chipset;
|
||||
void *bar0;
|
||||
size_t bar0len;
|
||||
int hasbar1;
|
||||
void *bar1;
|
||||
size_t bar1len;
|
||||
int hasbar2;
|
||||
void *bar2;
|
||||
size_t bar2len;
|
||||
struct pci_io_handle *iobar;
|
||||
size_t iobarlen;
|
||||
void *rawmem;
|
||||
struct pci_io_handle *rawio;
|
||||
};
|
||||
|
||||
int nva_init();
|
||||
extern struct nva_card **nva_cards;
|
||||
extern int nva_cardsnum;
|
||||
|
||||
static inline uint32_t nva_grd32(void *base, uint32_t addr) {
|
||||
return *((volatile uint32_t*)(((volatile uint8_t *)base) + addr));
|
||||
}
|
||||
|
||||
static inline void nva_gwr32(void *base, uint32_t addr, uint32_t val) {
|
||||
*((volatile uint32_t*)(((volatile uint8_t *)base) + addr)) = val;
|
||||
}
|
||||
|
||||
static inline uint32_t nva_grd8(void *base, uint32_t addr) {
|
||||
return *(((volatile uint8_t *)base) + addr);
|
||||
}
|
||||
|
||||
static inline void nva_gwr8(void *base, uint32_t addr, uint32_t val) {
|
||||
*(((volatile uint8_t *)base) + addr) = val;
|
||||
}
|
||||
|
||||
static inline uint32_t nva_rd32(int card, uint32_t addr) {
|
||||
return nva_grd32(nva_cards[card]->bar0, addr);
|
||||
}
|
||||
|
||||
static inline void nva_wr32(int card, uint32_t addr, uint32_t val) {
|
||||
nva_gwr32(nva_cards[card]->bar0, addr, val);
|
||||
}
|
||||
|
||||
static inline uint32_t nva_rd8(int card, uint32_t addr) {
|
||||
return nva_grd8(nva_cards[card]->bar0, addr);
|
||||
}
|
||||
|
||||
static inline void nva_wr8(int card, uint32_t addr, uint32_t val) {
|
||||
nva_gwr8(nva_cards[card]->bar0, addr, val);
|
||||
}
|
||||
|
||||
static inline uint32_t nva_mask(int cnum, uint32_t reg, uint32_t mask, uint32_t val)
|
||||
{
|
||||
uint32_t tmp = nva_rd32(cnum, reg);
|
||||
nva_wr32(cnum, reg, (tmp & ~mask) | val);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
enum nva_regspace_type {
|
||||
NVA_REGSPACE_BAR0,
|
||||
NVA_REGSPACE_BAR1,
|
||||
NVA_REGSPACE_BAR2,
|
||||
NVA_REGSPACE_IOBAR,
|
||||
NVA_REGSPACE_RAWMEM,
|
||||
NVA_REGSPACE_RAWIO,
|
||||
NVA_REGSPACE_PDAC,
|
||||
NVA_REGSPACE_EEPROM,
|
||||
NVA_REGSPACE_VGA_CR,
|
||||
NVA_REGSPACE_VGA_SR,
|
||||
NVA_REGSPACE_VGA_AR,
|
||||
NVA_REGSPACE_VGA_GR,
|
||||
NVA_REGSPACE_VGA_ST,
|
||||
NVA_REGSPACE_DPRAM,
|
||||
NVA_REGSPACE_PIPE,
|
||||
NVA_REGSPACE_RDI,
|
||||
NVA_REGSPACE_RDIB,
|
||||
NVA_REGSPACE_VCOMP_CODE,
|
||||
NVA_REGSPACE_VCOMP_REG,
|
||||
NVA_REGSPACE_MACRO_CODE,
|
||||
NVA_REGSPACE_XT,
|
||||
NVA_REGSPACE_UNKNOWN,
|
||||
};
|
||||
|
||||
struct nva_regspace {
|
||||
struct nva_card *card;
|
||||
int cnum;
|
||||
enum nva_regspace_type type;
|
||||
int regsz;
|
||||
int idx;
|
||||
};
|
||||
|
||||
int nva_wr(struct nva_regspace *regspace, uint32_t addr, uint64_t val);
|
||||
int nva_rd(struct nva_regspace *regspace, uint32_t addr, uint64_t *val);
|
||||
|
||||
enum nva_err {
|
||||
NVA_ERR_SUCCESS,
|
||||
NVA_ERR_RANGE,
|
||||
NVA_ERR_REGSZ,
|
||||
NVA_ERR_NOSPC,
|
||||
NVA_ERR_MAP,
|
||||
};
|
||||
|
||||
int nva_rstype(const char *name);
|
||||
int nva_rsdefsz(struct nva_regspace *regspace);
|
||||
int nva_rsunitsz(struct nva_regspace *regspace);
|
||||
char nva_rserrc(enum nva_err err);
|
||||
void nva_rsprint(struct nva_regspace *regspace, enum nva_err err, uint64_t val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
698
include/nva/regspace.c
Normal file
698
include/nva/regspace.c
Normal file
@@ -0,0 +1,698 @@
|
||||
#include "nva.h"
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <pciaccess.h>
|
||||
|
||||
int nva_wr(struct nva_regspace *regspace, uint32_t addr, uint64_t val) {
|
||||
void *rawbase = 0;
|
||||
size_t rawlen;
|
||||
void *raw;
|
||||
int i;
|
||||
uint32_t vgaio;
|
||||
uint32_t vgabase;
|
||||
switch (regspace->type) {
|
||||
case NVA_REGSPACE_BAR0:
|
||||
rawbase = regspace->card->bar0;
|
||||
rawlen = regspace->card->bar0len;
|
||||
goto raw;
|
||||
case NVA_REGSPACE_BAR1:
|
||||
rawbase = regspace->card->bar1;
|
||||
rawlen = regspace->card->bar1len;
|
||||
if (!regspace->card->hasbar1)
|
||||
return NVA_ERR_NOSPC;
|
||||
goto raw;
|
||||
case NVA_REGSPACE_BAR2:
|
||||
rawbase = regspace->card->bar2;
|
||||
rawlen = regspace->card->bar2len;
|
||||
if (!regspace->card->hasbar2)
|
||||
return NVA_ERR_NOSPC;
|
||||
goto raw;
|
||||
case NVA_REGSPACE_RAWMEM:
|
||||
rawbase = regspace->card->rawmem;
|
||||
rawlen = 0x100000;
|
||||
raw:
|
||||
if (!rawbase)
|
||||
return NVA_ERR_MAP;
|
||||
if (addr > rawlen - regspace->regsz)
|
||||
return NVA_ERR_RANGE;
|
||||
raw = (uint8_t *)rawbase + addr;
|
||||
switch (regspace->regsz) {
|
||||
case 1:
|
||||
*(volatile uint8_t *)raw = val;
|
||||
return 0;
|
||||
case 2:
|
||||
*(volatile uint16_t *)raw = val;
|
||||
return 0;
|
||||
case 4:
|
||||
*(volatile uint32_t *)raw = val;
|
||||
return 0;
|
||||
case 8:
|
||||
*(volatile uint64_t *)raw = val;
|
||||
return 0;
|
||||
default:
|
||||
return NVA_ERR_REGSZ;
|
||||
}
|
||||
case NVA_REGSPACE_IOBAR:
|
||||
if (!regspace->card->iobar)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (addr > regspace->card->iobarlen - regspace->regsz)
|
||||
return NVA_ERR_RANGE;
|
||||
switch (regspace->regsz) {
|
||||
case 1:
|
||||
pci_io_write8(regspace->card->iobar, addr, val);
|
||||
return 0;
|
||||
case 2:
|
||||
pci_io_write16(regspace->card->iobar, addr, val);
|
||||
return 0;
|
||||
case 4:
|
||||
pci_io_write32(regspace->card->iobar, addr, val);
|
||||
return 0;
|
||||
default:
|
||||
return NVA_ERR_REGSZ;
|
||||
}
|
||||
case NVA_REGSPACE_RAWIO:
|
||||
if (!regspace->card->rawio)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (addr > 0x10000 - regspace->regsz)
|
||||
return NVA_ERR_RANGE;
|
||||
switch (regspace->regsz) {
|
||||
case 1:
|
||||
pci_io_write8(regspace->card->rawio, addr, val);
|
||||
return 0;
|
||||
case 2:
|
||||
pci_io_write16(regspace->card->rawio, addr, val);
|
||||
return 0;
|
||||
case 4:
|
||||
pci_io_write32(regspace->card->rawio, addr, val);
|
||||
return 0;
|
||||
default:
|
||||
return NVA_ERR_REGSZ;
|
||||
}
|
||||
case NVA_REGSPACE_PDAC:
|
||||
if (regspace->card->chipset.chipset != 0x01)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (addr > 0x10000 - regspace->regsz)
|
||||
return NVA_ERR_RANGE;
|
||||
if (regspace->regsz > 8)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x609010, addr & 0xff);
|
||||
nva_wr32(regspace->cnum, 0x609014, addr >> 8);
|
||||
for (i = 0; i < regspace->regsz; i++)
|
||||
nva_wr32(regspace->cnum, 0x609018, (val >> i * 8) & 0xff);
|
||||
return 0;
|
||||
case NVA_REGSPACE_EEPROM:
|
||||
if (regspace->card->chipset.chipset != 0x01)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 1)
|
||||
return NVA_ERR_REGSZ;
|
||||
if (addr >= 0x80)
|
||||
return NVA_ERR_RANGE;
|
||||
while (nva_rd32(regspace->cnum, 0x60a400) & 0x10000000);
|
||||
nva_wr32(regspace->cnum, 0x60a400, 0x1000000 | addr << 8 | (val & 0xff));
|
||||
while (nva_rd32(regspace->cnum, 0x60a400) & 0x10000000);
|
||||
return 0;
|
||||
case NVA_REGSPACE_VGA_CR:
|
||||
vgaio = 0x3d4;
|
||||
if (addr >= 0x100)
|
||||
return NVA_ERR_RANGE;
|
||||
goto vga;
|
||||
case NVA_REGSPACE_VGA_SR:
|
||||
vgaio = 0x3c4;
|
||||
if (addr >= 8)
|
||||
return NVA_ERR_RANGE;
|
||||
goto vga;
|
||||
case NVA_REGSPACE_VGA_GR:
|
||||
vgaio = 0x3ce;
|
||||
if (addr >= 0x10)
|
||||
return NVA_ERR_RANGE;
|
||||
goto vga;
|
||||
case NVA_REGSPACE_VGA_AR:
|
||||
vgaio = 0x3c0;
|
||||
if (addr >= 0x20)
|
||||
return NVA_ERR_RANGE;
|
||||
goto vga;
|
||||
vga:
|
||||
if (regspace->regsz != 1)
|
||||
return NVA_ERR_REGSZ;
|
||||
if (regspace->card->chipset.card_type == 0x01) {
|
||||
vgabase = 0x6d0000;
|
||||
if (regspace->idx != 0)
|
||||
return NVA_ERR_NOSPC;
|
||||
} else if (regspace->card->chipset.card_type < 0x50) {
|
||||
if (vgaio == 0x3c4 || vgaio == 0x3ce)
|
||||
vgabase = 0x0c0000;
|
||||
else
|
||||
vgabase = 0x601000;
|
||||
if (regspace->idx > 2)
|
||||
return NVA_ERR_NOSPC;
|
||||
if ((regspace->card->chipset.chipset < 0x17 || regspace->card->chipset.chipset == 0x1a || regspace->card->chipset.chipset == 0x20) && regspace->idx == 1)
|
||||
return NVA_ERR_NOSPC;
|
||||
vgabase += regspace->idx * 0x2000;
|
||||
} else {
|
||||
vgabase = 0x601000;
|
||||
if (regspace->idx != 0)
|
||||
return NVA_ERR_NOSPC;
|
||||
}
|
||||
if (vgaio == 0x3c0) {
|
||||
nva_rd8(regspace->cnum, vgabase + 0x3da);
|
||||
uint8_t idx = nva_rd8(regspace->cnum, vgabase + 0x3c0);
|
||||
nva_rd8(regspace->cnum, vgabase + 0x3da);
|
||||
nva_wr8(regspace->cnum, vgabase + 0x3c0, addr);
|
||||
nva_wr8(regspace->cnum, vgabase + 0x3c0, val);
|
||||
nva_wr8(regspace->cnum, vgabase + 0x3c0, idx);
|
||||
} else {
|
||||
uint8_t idx = nva_rd8(regspace->cnum, vgabase + vgaio);
|
||||
nva_wr8(regspace->cnum, vgabase + vgaio, addr);
|
||||
nva_wr8(regspace->cnum, vgabase + vgaio + 1, val);
|
||||
nva_wr8(regspace->cnum, vgabase + vgaio, idx);
|
||||
}
|
||||
return 0;
|
||||
case NVA_REGSPACE_VGA_ST:
|
||||
if (regspace->card->chipset.chipset < 0x41)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 1)
|
||||
return NVA_ERR_REGSZ;
|
||||
uint32_t vstbase = 0x1380;
|
||||
if (regspace->card->chipset.card_type >= 0x50)
|
||||
vstbase = 0x619e40;
|
||||
uint32_t savepos = nva_rd32(regspace->cnum, vstbase+0xc);
|
||||
uint32_t savecfg = nva_rd32(regspace->cnum, vstbase+0x8);
|
||||
nva_wr32(regspace->cnum, vstbase+0xc, addr);
|
||||
nva_wr32(regspace->cnum, vstbase+0x8, 7);
|
||||
nva_wr32(regspace->cnum, vstbase+0x0, val);
|
||||
nva_wr32(regspace->cnum, vstbase+0x8, savecfg);
|
||||
nva_wr32(regspace->cnum, vstbase+0xc, savepos);
|
||||
return 0;
|
||||
case NVA_REGSPACE_DPRAM:
|
||||
if (regspace->card->chipset.chipset == 0x34) {
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400bb0, addr);
|
||||
nva_wr32(regspace->cnum, 0x400bb4, val);
|
||||
return 0;
|
||||
}
|
||||
if (regspace->card->chipset.card_type < 4 || regspace->card->chipset.card_type >= 0x20)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400828, addr);
|
||||
nva_wr32(regspace->cnum, 0x40082c, val);
|
||||
return 0;
|
||||
case NVA_REGSPACE_PIPE:
|
||||
if (regspace->card->chipset.card_type < 0x10 || regspace->card->chipset.card_type >= 0x50)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400f50, addr);
|
||||
nva_wr32(regspace->cnum, 0x400f54, val);
|
||||
return 0;
|
||||
case NVA_REGSPACE_RDI:
|
||||
if (regspace->card->chipset.chipset == 0x17 || regspace->card->chipset.chipset == 0x18 || regspace->card->chipset.chipset == 0x1f) {
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400a08, addr);
|
||||
nva_wr32(regspace->cnum, 0x400a0c, val);
|
||||
return 0;
|
||||
}
|
||||
if (regspace->card->chipset.card_type < 0x20 || regspace->card->chipset.card_type >= 0x50)
|
||||
return NVA_ERR_NOSPC;
|
||||
nva_wr32(regspace->cnum, 0x400750, addr);
|
||||
nva_wr32(regspace->cnum, 0x400754, val);
|
||||
return 0;
|
||||
case NVA_REGSPACE_RDIB:
|
||||
if (regspace->card->chipset.card_type < 0x20 || regspace->card->chipset.card_type >= 0x50)
|
||||
return NVA_ERR_NOSPC;
|
||||
nva_wr32(regspace->cnum, 0x400750, addr);
|
||||
nva_wr32(regspace->cnum, 0x400758, val);
|
||||
return 0;
|
||||
case NVA_REGSPACE_VCOMP_CODE:
|
||||
if (regspace->card->chipset.chipset != 0xaf)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x1c17c8, addr);
|
||||
nva_wr32(regspace->cnum, 0x1c17cc, val);
|
||||
return 0;
|
||||
case NVA_REGSPACE_VCOMP_REG:
|
||||
if (regspace->card->chipset.chipset != 0xaf)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 8)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x1c17d0, addr/8);
|
||||
nva_wr32(regspace->cnum, 0x1c17d4, val);
|
||||
nva_wr32(regspace->cnum, 0x1c17d8, val >> 32);
|
||||
return 0;
|
||||
case NVA_REGSPACE_MACRO_CODE:
|
||||
if (regspace->card->chipset.chipset < 0xc0)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x40986c, 0x10);
|
||||
nva_wr32(regspace->cnum, 0x409ffc, 2);
|
||||
nva_wr32(regspace->cnum, 0x409928, 0xc);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
nva_wr32(regspace->cnum, 0x40993c, 0xf);
|
||||
nva_wr32(regspace->cnum, 0x409928, 0xa);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
nva_wr32(regspace->cnum, 0x40991c, 0x1);
|
||||
nva_wr32(regspace->cnum, 0x409928, 0x1);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
for (i = 0; i < addr; i+=4) {
|
||||
nva_wr32(regspace->cnum, 0x409928, 0x6);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
}
|
||||
nva_wr32(regspace->cnum, 0x409918, val);
|
||||
nva_wr32(regspace->cnum, 0x409928, 0x7);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
return 0;
|
||||
case NVA_REGSPACE_XT:
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x1700, 0x30);
|
||||
nva_wr32(regspace->cnum, 0x700004, addr);
|
||||
nva_wr32(regspace->cnum, 0x700008, val);
|
||||
nva_wr32(regspace->cnum, 0x70000, 1);
|
||||
while (nva_rd32(regspace->cnum, 0x70000));
|
||||
nva_wr32(regspace->cnum, 0x700000, 2);
|
||||
while (nva_rd32(regspace->cnum, 0x700000));
|
||||
return 0;
|
||||
default:
|
||||
return NVA_ERR_NOSPC;
|
||||
}
|
||||
}
|
||||
|
||||
int nva_rd(struct nva_regspace *regspace, uint32_t addr, uint64_t *val) {
|
||||
void *rawbase = 0;
|
||||
size_t rawlen;
|
||||
void *raw;
|
||||
int i;
|
||||
uint32_t vgaio;
|
||||
uint32_t vgabase;
|
||||
switch (regspace->type) {
|
||||
case NVA_REGSPACE_BAR0:
|
||||
rawbase = regspace->card->bar0;
|
||||
rawlen = regspace->card->bar0len;
|
||||
goto raw;
|
||||
case NVA_REGSPACE_BAR1:
|
||||
rawbase = regspace->card->bar1;
|
||||
rawlen = regspace->card->bar1len;
|
||||
goto raw;
|
||||
case NVA_REGSPACE_BAR2:
|
||||
rawbase = regspace->card->bar2;
|
||||
rawlen = regspace->card->bar2len;
|
||||
goto raw;
|
||||
case NVA_REGSPACE_RAWMEM:
|
||||
rawbase = regspace->card->rawmem;
|
||||
rawlen = 0x100000;
|
||||
raw:
|
||||
if (!rawbase)
|
||||
return NVA_ERR_MAP;
|
||||
if (addr > rawlen - regspace->regsz)
|
||||
return NVA_ERR_RANGE;
|
||||
raw = (uint8_t *)rawbase + addr;
|
||||
switch (regspace->regsz) {
|
||||
case 1:
|
||||
*val = *(volatile uint8_t *)raw;
|
||||
return 0;
|
||||
case 2:
|
||||
*val = *(volatile uint16_t *)raw;
|
||||
return 0;
|
||||
case 4:
|
||||
*val = *(volatile uint32_t *)raw;
|
||||
return 0;
|
||||
case 8:
|
||||
*val = *(volatile uint64_t *)raw;
|
||||
return 0;
|
||||
default:
|
||||
return NVA_ERR_REGSZ;
|
||||
}
|
||||
case NVA_REGSPACE_IOBAR:
|
||||
if (!regspace->card->iobar)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (addr > regspace->card->iobarlen - regspace->regsz)
|
||||
return NVA_ERR_RANGE;
|
||||
switch (regspace->regsz) {
|
||||
case 1:
|
||||
*val = pci_io_read8(regspace->card->iobar, addr);
|
||||
return 0;
|
||||
case 2:
|
||||
*val = pci_io_read16(regspace->card->iobar, addr);
|
||||
return 0;
|
||||
case 4:
|
||||
*val = pci_io_read32(regspace->card->iobar, addr);
|
||||
return 0;
|
||||
default:
|
||||
return NVA_ERR_REGSZ;
|
||||
}
|
||||
case NVA_REGSPACE_RAWIO:
|
||||
if (!regspace->card->rawio)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (addr > 0x10000 - regspace->regsz)
|
||||
return NVA_ERR_RANGE;
|
||||
switch (regspace->regsz) {
|
||||
case 1:
|
||||
*val = pci_io_read8(regspace->card->rawio, addr);
|
||||
return 0;
|
||||
case 2:
|
||||
*val = pci_io_read16(regspace->card->rawio, addr);
|
||||
return 0;
|
||||
case 4:
|
||||
*val = pci_io_read32(regspace->card->rawio, addr);
|
||||
return 0;
|
||||
default:
|
||||
return NVA_ERR_REGSZ;
|
||||
}
|
||||
case NVA_REGSPACE_PDAC:
|
||||
if (regspace->card->chipset.chipset != 0x01)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (addr > 0x10000 - regspace->regsz)
|
||||
return NVA_ERR_RANGE;
|
||||
if (regspace->regsz > 8)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x609010, addr & 0xff);
|
||||
nva_wr32(regspace->cnum, 0x609014, addr >> 8);
|
||||
*val = 0;
|
||||
for (i = 0; i < regspace->regsz; i++)
|
||||
*val |= (uint64_t)(nva_rd32(regspace->cnum, 0x609018) & 0xff) << i * 8;
|
||||
return 0;
|
||||
case NVA_REGSPACE_EEPROM:
|
||||
if (regspace->card->chipset.chipset != 0x01)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 1)
|
||||
return NVA_ERR_REGSZ;
|
||||
if (addr >= 0x80)
|
||||
return NVA_ERR_RANGE;
|
||||
while (nva_rd32(regspace->cnum, 0x60a400) & 0x10000000);
|
||||
nva_wr32(regspace->cnum, 0x60a400, 0x2000000 | addr << 8);
|
||||
while (nva_rd32(regspace->cnum, 0x60a400) & 0x10000000);
|
||||
*val = nva_rd32(regspace->cnum, 0x60a400) & 0xff;
|
||||
return 0;
|
||||
case NVA_REGSPACE_VGA_CR:
|
||||
vgaio = 0x3d4;
|
||||
if (addr >= 0x100)
|
||||
return NVA_ERR_RANGE;
|
||||
goto vga;
|
||||
case NVA_REGSPACE_VGA_SR:
|
||||
vgaio = 0x3c4;
|
||||
if (addr >= 8)
|
||||
return NVA_ERR_RANGE;
|
||||
goto vga;
|
||||
case NVA_REGSPACE_VGA_GR:
|
||||
vgaio = 0x3ce;
|
||||
if (addr >= 0x10)
|
||||
return NVA_ERR_RANGE;
|
||||
goto vga;
|
||||
case NVA_REGSPACE_VGA_AR:
|
||||
vgaio = 0x3c0;
|
||||
if (addr >= 0x20)
|
||||
return NVA_ERR_RANGE;
|
||||
goto vga;
|
||||
vga:
|
||||
if (regspace->regsz != 1)
|
||||
return NVA_ERR_REGSZ;
|
||||
if (regspace->card->chipset.card_type == 0x01) {
|
||||
vgabase = 0x6d0000;
|
||||
if (regspace->idx != 0)
|
||||
return NVA_ERR_NOSPC;
|
||||
} else if (regspace->card->chipset.card_type < 0x50) {
|
||||
if (vgaio == 0x3c4 || vgaio == 0x3ce)
|
||||
vgabase = 0x0c0000;
|
||||
else
|
||||
vgabase = 0x601000;
|
||||
if (regspace->idx > 2)
|
||||
return NVA_ERR_NOSPC;
|
||||
if ((regspace->card->chipset.chipset < 0x17 || regspace->card->chipset.chipset == 0x1a || regspace->card->chipset.chipset == 0x20) && regspace->idx == 1)
|
||||
return NVA_ERR_NOSPC;
|
||||
vgabase += regspace->idx * 0x2000;
|
||||
} else {
|
||||
vgabase = 0x601000;
|
||||
if (regspace->idx != 0)
|
||||
return NVA_ERR_NOSPC;
|
||||
}
|
||||
if (vgaio == 0x3c0) {
|
||||
nva_rd8(regspace->cnum, vgabase + 0x3da);
|
||||
uint8_t idx = nva_rd8(regspace->cnum, vgabase + 0x3c0);
|
||||
nva_rd8(regspace->cnum, vgabase + 0x3da);
|
||||
nva_wr8(regspace->cnum, vgabase + 0x3c0, addr);
|
||||
*val = nva_rd8(regspace->cnum, vgabase + 0x3c1);
|
||||
nva_rd8(regspace->cnum, vgabase + 0x3da);
|
||||
nva_wr8(regspace->cnum, vgabase + 0x3c0, idx);
|
||||
} else {
|
||||
uint8_t idx = nva_rd8(regspace->cnum, vgabase + vgaio);
|
||||
nva_wr8(regspace->cnum, vgabase + vgaio, addr);
|
||||
*val = nva_rd8(regspace->cnum, vgabase + vgaio + 1);
|
||||
nva_wr8(regspace->cnum, vgabase + vgaio, idx);
|
||||
}
|
||||
return 0;
|
||||
case NVA_REGSPACE_VGA_ST:
|
||||
if (regspace->card->chipset.chipset < 0x41)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 1)
|
||||
return NVA_ERR_REGSZ;
|
||||
uint32_t vstbase = 0x1380;
|
||||
if (regspace->card->chipset.card_type >= 0x50)
|
||||
vstbase = 0x619e40;
|
||||
uint32_t savepos = nva_rd32(regspace->cnum, vstbase+0xc);
|
||||
uint32_t savecfg = nva_rd32(regspace->cnum, vstbase+0x8);
|
||||
nva_wr32(regspace->cnum, vstbase+0xc, addr+1);
|
||||
nva_wr32(regspace->cnum, vstbase+0x8, 7);
|
||||
*val = nva_rd32(regspace->cnum, vstbase+0x0);
|
||||
nva_wr32(regspace->cnum, vstbase+0x8, savecfg);
|
||||
nva_wr32(regspace->cnum, vstbase+0xc, savepos);
|
||||
return 0;
|
||||
case NVA_REGSPACE_DPRAM:
|
||||
if (regspace->card->chipset.chipset == 0x34) {
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400bb0, addr);
|
||||
*val = nva_rd32(regspace->cnum, 0x400bb4);
|
||||
return 0;
|
||||
}
|
||||
if (regspace->card->chipset.card_type < 4 || regspace->card->chipset.card_type >= 0x20)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400828, addr);
|
||||
*val = nva_rd32(regspace->cnum, 0x40082c);
|
||||
return 0;
|
||||
case NVA_REGSPACE_PIPE:
|
||||
if (regspace->card->chipset.card_type < 0x10 || regspace->card->chipset.card_type >= 0x50)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400f50, addr);
|
||||
*val = nva_rd32(regspace->cnum, 0x400f54);
|
||||
return 0;
|
||||
case NVA_REGSPACE_RDI:
|
||||
if (regspace->card->chipset.chipset == 0x17 || regspace->card->chipset.chipset == 0x18 || regspace->card->chipset.chipset == 0x1f) {
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400a08, addr);
|
||||
*val = nva_rd32(regspace->cnum, 0x400a0c);
|
||||
return 0;
|
||||
}
|
||||
if (regspace->card->chipset.card_type < 0x20 || regspace->card->chipset.card_type >= 0x50)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400750, addr);
|
||||
*val = nva_rd32(regspace->cnum, 0x400754);
|
||||
return 0;
|
||||
case NVA_REGSPACE_RDIB:
|
||||
if (regspace->card->chipset.card_type < 0x20 || regspace->card->chipset.card_type >= 0x50)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x400750, addr);
|
||||
*val = nva_rd32(regspace->cnum, 0x400758);
|
||||
return 0;
|
||||
case NVA_REGSPACE_VCOMP_CODE:
|
||||
if (regspace->card->chipset.chipset != 0xaf)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x1c17c8, addr);
|
||||
*val = nva_rd32(regspace->cnum, 0x1c17cc);
|
||||
return 0;
|
||||
case NVA_REGSPACE_VCOMP_REG:
|
||||
if (regspace->card->chipset.chipset != 0xaf)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 8)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x1c17d0, addr/8);
|
||||
*val = nva_rd32(regspace->cnum, 0x1c17d4);
|
||||
*val |= (uint64_t)nva_rd32(regspace->cnum, 0x1c17d8) << 32;
|
||||
return 0;
|
||||
case NVA_REGSPACE_MACRO_CODE:
|
||||
if (regspace->card->chipset.chipset < 0xc0)
|
||||
return NVA_ERR_NOSPC;
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x40986c, 0x10);
|
||||
nva_wr32(regspace->cnum, 0x409ffc, 2);
|
||||
nva_wr32(regspace->cnum, 0x409928, 0xc);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
nva_wr32(regspace->cnum, 0x40993c, 0xf);
|
||||
nva_wr32(regspace->cnum, 0x409928, 0xa);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
nva_wr32(regspace->cnum, 0x40991c, 0x1);
|
||||
nva_wr32(regspace->cnum, 0x409928, 0x1);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
for (i = 0; i < addr; i+=4) {
|
||||
nva_wr32(regspace->cnum, 0x409928, 0x6);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
}
|
||||
nva_wr32(regspace->cnum, 0x409928, 0x6);
|
||||
while (nva_rd32(regspace->cnum, 0x409928));
|
||||
*val = nva_rd32(regspace->cnum, 0x409918);
|
||||
return 0;
|
||||
case NVA_REGSPACE_XT:
|
||||
if (regspace->regsz != 4)
|
||||
return NVA_ERR_REGSZ;
|
||||
nva_wr32(regspace->cnum, 0x1700, 0x30);
|
||||
nva_wr32(regspace->cnum, 0x700004, addr);
|
||||
nva_wr32(regspace->cnum, 0x70000, 1);
|
||||
while (nva_rd32(regspace->cnum, 0x70000));
|
||||
nva_wr32(regspace->cnum, 0x700000, 1);
|
||||
while (nva_rd32(regspace->cnum, 0x700000));
|
||||
*val = nva_rd32(regspace->cnum, 0x700004);
|
||||
return 0;
|
||||
default:
|
||||
return NVA_ERR_NOSPC;
|
||||
}
|
||||
}
|
||||
|
||||
int nva_rstype(const char *name) {
|
||||
if (!strcmp(name, "bar0"))
|
||||
return NVA_REGSPACE_BAR0;
|
||||
if (!strcmp(name, "mmio"))
|
||||
return NVA_REGSPACE_BAR0;
|
||||
if (!strcmp(name, "bar1"))
|
||||
return NVA_REGSPACE_BAR1;
|
||||
if (!strcmp(name, "fb"))
|
||||
return NVA_REGSPACE_BAR1;
|
||||
if (!strcmp(name, "bar2"))
|
||||
return NVA_REGSPACE_BAR2;
|
||||
if (!strcmp(name, "bar3"))
|
||||
return NVA_REGSPACE_BAR2;
|
||||
if (!strcmp(name, "ramin"))
|
||||
return NVA_REGSPACE_BAR2;
|
||||
if (!strcmp(name, "iobar"))
|
||||
return NVA_REGSPACE_IOBAR;
|
||||
if (!strcmp(name, "rawmem"))
|
||||
return NVA_REGSPACE_RAWMEM;
|
||||
if (!strcmp(name, "rawio"))
|
||||
return NVA_REGSPACE_RAWIO;
|
||||
if (!strcmp(name, "pdac"))
|
||||
return NVA_REGSPACE_PDAC;
|
||||
if (!strcmp(name, "eeprom"))
|
||||
return NVA_REGSPACE_EEPROM;
|
||||
if (!strcmp(name, "cr"))
|
||||
return NVA_REGSPACE_VGA_CR;
|
||||
if (!strcmp(name, "sr"))
|
||||
return NVA_REGSPACE_VGA_SR;
|
||||
if (!strcmp(name, "gr"))
|
||||
return NVA_REGSPACE_VGA_GR;
|
||||
if (!strcmp(name, "ar"))
|
||||
return NVA_REGSPACE_VGA_AR;
|
||||
if (!strcmp(name, "cr"))
|
||||
return NVA_REGSPACE_VGA_CR;
|
||||
if (!strcmp(name, "vst"))
|
||||
return NVA_REGSPACE_VGA_ST;
|
||||
if (!strcmp(name, "dpram"))
|
||||
return NVA_REGSPACE_DPRAM;
|
||||
if (!strcmp(name, "pipe"))
|
||||
return NVA_REGSPACE_PIPE;
|
||||
if (!strcmp(name, "rdi"))
|
||||
return NVA_REGSPACE_RDI;
|
||||
if (!strcmp(name, "rdib"))
|
||||
return NVA_REGSPACE_RDIB;
|
||||
if (!strcmp(name, "vcomp_code"))
|
||||
return NVA_REGSPACE_VCOMP_CODE;
|
||||
if (!strcmp(name, "vcomp_reg"))
|
||||
return NVA_REGSPACE_VCOMP_REG;
|
||||
if (!strcmp(name, "macro_code"))
|
||||
return NVA_REGSPACE_MACRO_CODE;
|
||||
if (!strcmp(name, "xt"))
|
||||
return NVA_REGSPACE_XT;
|
||||
return NVA_REGSPACE_UNKNOWN;
|
||||
}
|
||||
|
||||
int nva_rsdefsz(struct nva_regspace *regspace) {
|
||||
switch (regspace->type) {
|
||||
case NVA_REGSPACE_BAR0:
|
||||
case NVA_REGSPACE_BAR1:
|
||||
case NVA_REGSPACE_BAR2:
|
||||
case NVA_REGSPACE_IOBAR:
|
||||
case NVA_REGSPACE_DPRAM:
|
||||
case NVA_REGSPACE_PIPE:
|
||||
case NVA_REGSPACE_RDI:
|
||||
case NVA_REGSPACE_RDIB:
|
||||
case NVA_REGSPACE_VCOMP_CODE:
|
||||
case NVA_REGSPACE_MACRO_CODE:
|
||||
case NVA_REGSPACE_XT:
|
||||
return 4;
|
||||
case NVA_REGSPACE_VCOMP_REG:
|
||||
return 8;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int nva_rsunitsz(struct nva_regspace *regspace) {
|
||||
switch (regspace->type) {
|
||||
case NVA_REGSPACE_DPRAM:
|
||||
return 4;
|
||||
case NVA_REGSPACE_RDI:
|
||||
case NVA_REGSPACE_RDIB:
|
||||
if (regspace->card->chipset.chipset == 0x17 || regspace->card->chipset.chipset == 0x18 || regspace->card->chipset.chipset == 0x1f) {
|
||||
return 4;
|
||||
}
|
||||
return 1;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
char nva_rserrc(enum nva_err err) {
|
||||
switch (err) {
|
||||
case NVA_ERR_RANGE:
|
||||
return 'R';
|
||||
case NVA_ERR_REGSZ:
|
||||
return 'B';
|
||||
case NVA_ERR_NOSPC:
|
||||
return 'S';
|
||||
case NVA_ERR_MAP:
|
||||
return 'M';
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void nva_rsprint(struct nva_regspace *regspace, enum nva_err err, uint64_t val) {
|
||||
if (err) {
|
||||
int k;
|
||||
char ec = nva_rserrc(err);
|
||||
printf(" ");
|
||||
for (k = 0; k < regspace->regsz; k++)
|
||||
printf("%c%c", ec, ec);
|
||||
} else {
|
||||
switch (regspace->regsz) {
|
||||
case 1:
|
||||
printf (" %02"PRIx64, val);
|
||||
break;
|
||||
case 2:
|
||||
printf (" %04"PRIx64, val);
|
||||
break;
|
||||
case 4:
|
||||
printf (" %08"PRIx64, val);
|
||||
break;
|
||||
case 8:
|
||||
printf (" %016"PRIx64, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
include/nva/util.h
Normal file
19
include/nva/util.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof (a) / sizeof *(a))
|
||||
#define ADDARRAY(a, e) \
|
||||
do { \
|
||||
if ((a ## num) >= (a ## max)) { \
|
||||
if (!(a ## max)) \
|
||||
(a ## max) = 16; \
|
||||
else \
|
||||
(a ## max) *= 2; \
|
||||
(a) = realloc((a), (a ## max)*sizeof(*(a))); \
|
||||
} \
|
||||
(a)[(a ## num)++] = (e); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user