add pci
This commit is contained in:
parent
b6acb18500
commit
6c3b9d9f30
9
.gitignore
vendored
9
.gitignore
vendored
@ -1,2 +1,11 @@
|
||||
*.pyc
|
||||
*~
|
||||
|
||||
*.cmd
|
||||
*.symvers
|
||||
*.o
|
||||
*.kko
|
||||
*.order
|
||||
*.mod
|
||||
*.mod.*
|
||||
*.ko
|
||||
|
@ -123,8 +123,7 @@ _opcodes = """
|
||||
121 debug debug 0
|
||||
"""
|
||||
|
||||
def str_to_i(s):
|
||||
d = {
|
||||
_str_i_d = {
|
||||
"reg": 0,
|
||||
"ps": 1,
|
||||
"ws": 2,
|
||||
@ -134,11 +133,22 @@ def str_to_i(s):
|
||||
"pll": 6,
|
||||
"mc": 7,
|
||||
}
|
||||
if s in d:
|
||||
return d[s]
|
||||
_i_str_d = {
|
||||
v: k for k, v in _str_i_d.items()
|
||||
}
|
||||
|
||||
def str_to_i(s):
|
||||
if s in _str_i_d:
|
||||
return _str_i_d[s]
|
||||
else:
|
||||
return s
|
||||
|
||||
def i_to_str(i):
|
||||
if i in _i_str_d:
|
||||
return _i_str_d[i]
|
||||
else:
|
||||
return i
|
||||
|
||||
opcodes = {
|
||||
int(k): (a, b, str_to_i(c))
|
||||
for k, a, b, c in map(str.split, _opcodes.strip().split("\n"))
|
||||
|
@ -1,6 +1,6 @@
|
||||
import sys
|
||||
import struct
|
||||
from opcodes import opcodes
|
||||
from opcodes import opcodes, i_to_str
|
||||
import types
|
||||
|
||||
with open(sys.argv[1], 'rb') as f:
|
||||
@ -26,6 +26,15 @@ def rstr(offset, length):
|
||||
global rom
|
||||
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_ATI_MAGIC_OFFSET = 0x30
|
||||
ATOM_ATI_MAGIC = b" 761295520"
|
||||
@ -190,31 +199,64 @@ def dest_src_size(arg, src):
|
||||
case _:
|
||||
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):
|
||||
attr = u8(offset)
|
||||
arg = (attr >> 0) & 0b111
|
||||
src = (attr >> 3) & 0b111
|
||||
return (
|
||||
1
|
||||
+ dest_arg_size(dest_type)
|
||||
+ dest_src_size(arg, src)
|
||||
)
|
||||
|
||||
arg_size = dest_arg_size(dest_type)
|
||||
src_size = 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):
|
||||
arg = u16(offset)
|
||||
print_size(arg, 2)
|
||||
return 2
|
||||
|
||||
def opcode_type_setregblock(offset, dest_type):
|
||||
arg = u16(offset)
|
||||
print_size(arg, 2)
|
||||
return 2
|
||||
|
||||
def opcode_type_dest(offset, dest_type):
|
||||
attr = u8(offset)
|
||||
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):
|
||||
attr = u8(offset)
|
||||
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):
|
||||
return 0
|
||||
@ -237,10 +279,12 @@ def disassemble(start, length):
|
||||
opcode = u8(offset)
|
||||
arg_type, name, dest_type = opcodes[opcode]
|
||||
pc = (offset - start) + 6
|
||||
print(f"{pc:04x} opcode {opcode:02x} {name}:{dest_type}")
|
||||
offset += 1
|
||||
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):
|
||||
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