add pci
This commit is contained in:
parent
b6acb18500
commit
6c3b9d9f30
9
.gitignore
vendored
9
.gitignore
vendored
@ -1,2 +1,11 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*~
|
*~
|
||||||
|
|
||||||
|
*.cmd
|
||||||
|
*.symvers
|
||||||
|
*.o
|
||||||
|
*.kko
|
||||||
|
*.order
|
||||||
|
*.mod
|
||||||
|
*.mod.*
|
||||||
|
*.ko
|
||||||
|
@ -123,22 +123,32 @@ _opcodes = """
|
|||||||
121 debug debug 0
|
121 debug debug 0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_str_i_d = {
|
||||||
|
"reg": 0,
|
||||||
|
"ps": 1,
|
||||||
|
"ws": 2,
|
||||||
|
"fb": 3,
|
||||||
|
"id": 4,
|
||||||
|
"imm": 5,
|
||||||
|
"pll": 6,
|
||||||
|
"mc": 7,
|
||||||
|
}
|
||||||
|
_i_str_d = {
|
||||||
|
v: k for k, v in _str_i_d.items()
|
||||||
|
}
|
||||||
|
|
||||||
def str_to_i(s):
|
def str_to_i(s):
|
||||||
d = {
|
if s in _str_i_d:
|
||||||
"reg": 0,
|
return _str_i_d[s]
|
||||||
"ps": 1,
|
|
||||||
"ws": 2,
|
|
||||||
"fb": 3,
|
|
||||||
"id": 4,
|
|
||||||
"imm": 5,
|
|
||||||
"pll": 6,
|
|
||||||
"mc": 7,
|
|
||||||
}
|
|
||||||
if s in d:
|
|
||||||
return d[s]
|
|
||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def i_to_str(i):
|
||||||
|
if i in _i_str_d:
|
||||||
|
return _i_str_d[i]
|
||||||
|
else:
|
||||||
|
return i
|
||||||
|
|
||||||
opcodes = {
|
opcodes = {
|
||||||
int(k): (a, b, str_to_i(c))
|
int(k): (a, b, str_to_i(c))
|
||||||
for k, a, b, c in map(str.split, _opcodes.strip().split("\n"))
|
for k, a, b, c in map(str.split, _opcodes.strip().split("\n"))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
import struct
|
import struct
|
||||||
from opcodes import opcodes
|
from opcodes import opcodes, i_to_str
|
||||||
import types
|
import types
|
||||||
|
|
||||||
with open(sys.argv[1], 'rb') as f:
|
with open(sys.argv[1], 'rb') as f:
|
||||||
@ -26,6 +26,15 @@ def rstr(offset, length):
|
|||||||
global rom
|
global rom
|
||||||
return bytes(rom[offset:offset + length])
|
return bytes(rom[offset:offset + length])
|
||||||
|
|
||||||
|
def uN(offset, N):
|
||||||
|
if N == 1:
|
||||||
|
return u8(offset)
|
||||||
|
if N == 2:
|
||||||
|
return u16(offset)
|
||||||
|
if N == 4:
|
||||||
|
return u32(offset)
|
||||||
|
assert False, N
|
||||||
|
|
||||||
ATOM_BIOS_MAGIC = 0xaa55
|
ATOM_BIOS_MAGIC = 0xaa55
|
||||||
ATOM_ATI_MAGIC_OFFSET = 0x30
|
ATOM_ATI_MAGIC_OFFSET = 0x30
|
||||||
ATOM_ATI_MAGIC = b" 761295520"
|
ATOM_ATI_MAGIC = b" 761295520"
|
||||||
@ -190,31 +199,64 @@ def dest_src_size(arg, src):
|
|||||||
case _:
|
case _:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
def print_size(n, size):
|
||||||
|
if size == 1:
|
||||||
|
print(f"{n:02x}", end='')
|
||||||
|
elif size == 2:
|
||||||
|
print(f"{n:04x}", end='')
|
||||||
|
else:
|
||||||
|
assert False, size
|
||||||
|
|
||||||
def opcode_type_dest_src(offset, dest_type):
|
def opcode_type_dest_src(offset, dest_type):
|
||||||
attr = u8(offset)
|
attr = u8(offset)
|
||||||
arg = (attr >> 0) & 0b111
|
arg = (attr >> 0) & 0b111
|
||||||
src = (attr >> 3) & 0b111
|
src = (attr >> 3) & 0b111
|
||||||
return (
|
|
||||||
1
|
arg_size = dest_arg_size(dest_type)
|
||||||
+ dest_arg_size(dest_type)
|
src_size = dest_src_size(arg, src)
|
||||||
+ dest_src_size(arg, src)
|
arg_value = uN(offset + 1, arg_size)
|
||||||
)
|
src_value = uN(offset + 1 + arg_size, src_size)
|
||||||
|
|
||||||
|
print_size(arg_value, arg_size)
|
||||||
|
print(" <- ", end='')
|
||||||
|
print_size(src_value, src_size)
|
||||||
|
|
||||||
|
return 1 + arg_size + src_size
|
||||||
|
|
||||||
def opcode_type_1x16(offset, dest_type):
|
def opcode_type_1x16(offset, dest_type):
|
||||||
|
arg = u16(offset)
|
||||||
|
print_size(arg, 2)
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
def opcode_type_setregblock(offset, dest_type):
|
def opcode_type_setregblock(offset, dest_type):
|
||||||
|
arg = u16(offset)
|
||||||
|
print_size(arg, 2)
|
||||||
return 2
|
return 2
|
||||||
|
|
||||||
def opcode_type_dest(offset, dest_type):
|
def opcode_type_dest(offset, dest_type):
|
||||||
attr = u8(offset)
|
attr = u8(offset)
|
||||||
src = (attr >> 3) & 0b111
|
src = (attr >> 3) & 0b111
|
||||||
return 1 + dest_src_size(dest_type, src)
|
src_size = dest_src_size(dest_type, src)
|
||||||
|
src_arg = uN(offset + 1, src_size)
|
||||||
|
|
||||||
|
print_size(src_arg, src_size)
|
||||||
|
|
||||||
|
return 1 + src_size
|
||||||
|
|
||||||
def opcode_type_shift(offset, dest_type):
|
def opcode_type_shift(offset, dest_type):
|
||||||
attr = u8(offset)
|
attr = u8(offset)
|
||||||
src = (attr >> 3) & 0b111
|
src = (attr >> 3) & 0b111
|
||||||
return 1 + dest_src_size(dest_type, src)
|
src_size = dest_src_size(dest_type, src)
|
||||||
|
src_arg = uN(offset + 1, src_size)
|
||||||
|
|
||||||
|
print_size(src_arg, src_size)
|
||||||
|
|
||||||
|
shift_arg = u8(offset + 1 + src_size)
|
||||||
|
|
||||||
|
print(" by ", end='')
|
||||||
|
print_size(shift_arg, 1)
|
||||||
|
|
||||||
|
return 1 + src_size + 1
|
||||||
|
|
||||||
def opcode_0(offset, dest_type):
|
def opcode_0(offset, dest_type):
|
||||||
return 0
|
return 0
|
||||||
@ -237,10 +279,12 @@ def disassemble(start, length):
|
|||||||
opcode = u8(offset)
|
opcode = u8(offset)
|
||||||
arg_type, name, dest_type = opcodes[opcode]
|
arg_type, name, dest_type = opcodes[opcode]
|
||||||
pc = (offset - start) + 6
|
pc = (offset - start) + 6
|
||||||
print(f"{pc:04x} opcode {opcode:02x} {name}:{dest_type}")
|
|
||||||
offset += 1
|
offset += 1
|
||||||
handler = argument_handlers[arg_type]
|
handler = argument_handlers[arg_type]
|
||||||
offset += handler(offset, dest_type)
|
print(f"{pc:04x} opcode {opcode:02x} {name.rjust(12)} {i_to_str(dest_type).ljust(8)} ", end='')
|
||||||
|
length = handler(offset, dest_type)
|
||||||
|
offset += length
|
||||||
|
print()
|
||||||
|
|
||||||
def parse_table(names, table):
|
def parse_table(names, table):
|
||||||
structure_size = u16(table + 0)
|
structure_size = u16(table + 0)
|
||||||
|
19
pci/Makefile
Normal file
19
pci/Makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
BINARY := test_pci_module
|
||||||
|
KERNEL := /lib/modules/$(shell uname -r)/build
|
||||||
|
ARCH := x86
|
||||||
|
C_FLAGS := -Wall
|
||||||
|
KMOD_DIR := $(shell pwd)
|
||||||
|
|
||||||
|
OBJECTS := main.o
|
||||||
|
|
||||||
|
ccflags-y += $(C_FLAGS)
|
||||||
|
|
||||||
|
obj-m += $(BINARY).o
|
||||||
|
|
||||||
|
$(BINARY)-y := $(OBJECTS)
|
||||||
|
|
||||||
|
$(BINARY).ko:
|
||||||
|
make -C $(KERNEL) M=$(KMOD_DIR) modules
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(BINARY).ko
|
131
pci/main.c
Normal file
131
pci/main.c
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
|
||||||
|
#define R500 "r500"
|
||||||
|
|
||||||
|
static struct pci_device_id r500_id_table[] = {
|
||||||
|
{ PCI_DEVICE(0x121a, 0x0002) },
|
||||||
|
{ 0,}
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(pci, r500_id_table);
|
||||||
|
|
||||||
|
static int r500_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
|
||||||
|
static void r500_remove(struct pci_dev *pdev);
|
||||||
|
|
||||||
|
static struct pci_driver r500 = {
|
||||||
|
.name = R500,
|
||||||
|
.id_table = r500_id_table,
|
||||||
|
.probe = r500_probe,
|
||||||
|
.remove = r500_remove
|
||||||
|
};
|
||||||
|
|
||||||
|
struct r500_priv {
|
||||||
|
volatile u32 __iomem *hwmem;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
static int __init r500_module_init(void)
|
||||||
|
{
|
||||||
|
return pci_register_driver(&r500);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit r500_module_exit(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&r500);
|
||||||
|
}
|
||||||
|
|
||||||
|
void release_device(struct pci_dev *pdev);
|
||||||
|
|
||||||
|
void release_device(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
/* Free memory region */
|
||||||
|
pci_release_region(pdev, pci_select_bars(pdev, IORESOURCE_MEM));
|
||||||
|
/* And disable device */
|
||||||
|
pci_disable_device(pdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is called by the kernel */
|
||||||
|
static int r500_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
int bar, err;
|
||||||
|
u16 vendor, device;
|
||||||
|
unsigned long mmio_start, mmio_len;
|
||||||
|
|
||||||
|
struct r500_priv *drv_priv;
|
||||||
|
|
||||||
|
pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor);
|
||||||
|
pci_read_config_word(pdev, PCI_DEVICE_ID, &device);
|
||||||
|
|
||||||
|
printk(KERN_INFO "vid: %04x pid: %04x\n", vendor, device);
|
||||||
|
|
||||||
|
/* Request IO BAR */
|
||||||
|
bar = pci_select_bars(pdev, IORESOURCE_MEM);
|
||||||
|
|
||||||
|
/* Enable device memory */
|
||||||
|
err = pci_enable_device_mem(pdev);
|
||||||
|
if (err) {
|
||||||
|
printk(KERN_INFO "pci_enable_device_mem error\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Request memory region for the BAR */
|
||||||
|
err = pci_request_region(pdev, bar, R500);
|
||||||
|
if (err) {
|
||||||
|
printk(KERN_INFO "pci_request_region error\n");
|
||||||
|
pci_disable_device(pdev);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get start and stop memory offsets */
|
||||||
|
mmio_start = pci_resource_start(pdev, 0);
|
||||||
|
mmio_len = pci_resource_len(pdev, 0);
|
||||||
|
printk(KERN_INFO "mmio_start %p mmio_len %p\n", (void*)mmio_start, (void*)mmio_len);
|
||||||
|
|
||||||
|
/* Allocate memory for the module private data */
|
||||||
|
drv_priv = kzalloc(sizeof(struct r500_priv), GFP_KERNEL);
|
||||||
|
if (!drv_priv) {
|
||||||
|
release_device(pdev);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remap BAR to the local pointer */
|
||||||
|
drv_priv->hwmem = ioremap(mmio_start, mmio_len);
|
||||||
|
if (!drv_priv->hwmem) {
|
||||||
|
release_device(pdev);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set module private data */
|
||||||
|
/* Now we can access mapped "hwmem" from the any module's function */
|
||||||
|
pci_set_drvdata(pdev, drv_priv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up */
|
||||||
|
static void r500_remove(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
struct r500_priv *drv_priv = pci_get_drvdata(pdev);
|
||||||
|
|
||||||
|
if (drv_priv) {
|
||||||
|
if (drv_priv->hwmem) {
|
||||||
|
iounmap(drv_priv->hwmem);
|
||||||
|
}
|
||||||
|
|
||||||
|
kfree(drv_priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
release_device(pdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_AUTHOR("Zachary Buhman <zack@buhman.org>");
|
||||||
|
MODULE_DESCRIPTION("R500 module");
|
||||||
|
MODULE_VERSION("0.1");
|
||||||
|
|
||||||
|
module_init(r500_module_init);
|
||||||
|
module_exit(r500_module_exit);
|
Loading…
x
Reference in New Issue
Block a user