PCI driver

This commit is contained in:
Inex Code 2023-05-08 17:57:16 +03:00
parent bd519208fd
commit e703628187
8 changed files with 273 additions and 0 deletions

8
.idea/Linux.iml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="FacetManager">
<facet type="Python" name="Python facet">
<configuration sdkName="Python 3.10 (Linux)" />
</facet>
</component>
</module>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="general">
<commitTypes>
<entry providerId="37415b03-9388-4c55-b949-8c4526f6934d" order="2" />
<entry providerId="e9ce9acf-f4a6-4b36-b43c-531169556c29" order="2" />
<entry providerId="e9d4e8de-79a0-48b8-b1ba-b4161e2572c0" order="1" />
</commitTypes>
</component>
</project>

View file

@ -0,0 +1,16 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="1">
<item index="0" class="java.lang.String" itemvalue="psycopg2" />
</list>
</value>
</option>
</inspection_tool>
<inspection_tool class="TsLint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

View file

@ -0,0 +1,31 @@
[Unit]
# A short human readable title of the unit
Description=Counter reader in bash?
# A list of units whose activations will wait until after this unit has completed.
Before=
# A list of units whose activations will occur before this unit starts.
After=network.target
# A list of units to activate when this one is activated, if any unit listed here fails this unit will deactivate.
Requires=
# A list of units to activate when this one is activated, if a unit listed here fails this unit will continue to run.
Wants=
[Service]
# Configures the process start-up type for this service unit, one of:
# simple - The process defined in ExecStart= will stay in the foreground while the unit is activated.
# forking - The process defined in ExecStart= will fork a background process and exit right away.
# oneshot - The process will exit right away, use with RemainAfterExit= to ensure the serice is marked as active.
# Consult the documentantion for types (https://www.freedesktop.org/software/systemd/man/systemd.service.html#Type=) other options.
Type=simple
# Command with arguments to invoke when the unit is activated.
ExecStart=
# Command with arguments to invoke when the unit is deactivated.
ExecStop=
# Configures under what conditions the unit will be restarted.
Restart=on-failure
[Install]
# A list of units who when activated will try and activate this unit
WantedBy=multi-user.target
# A list of units to enable or disable when this unit is enabled or disabled (e.g., with systemctl enable)
Also=

7
pci/Makefile Normal file
View file

@ -0,0 +1,7 @@
obj-m += ethernet.o
# make -C $(nix-build -E '(import <nixpkgs> {}).linux.dev' --no-out-link)/lib/modules/*/build M=$(pwd)
all:
make -C /nix/store/f0b11y3qv1y0l3yvwkl88m181fnbmn80-linux-5.15.92-dev/lib/modules/*/build M=/home/inex/dev/Linux/pci modules
clean:
make -C /nix/store/f0b11y3qv1y0l3yvwkl88m181fnbmn80-linux-5.15.92-dev/lib/modules/*/build M=/home/inex/dev/Linux/pci clean

164
pci/ethernet.c Normal file
View file

@ -0,0 +1,164 @@
// A symbol PCI driver that outputs the MAC address of the network card:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Inex Code");
MODULE_DESCRIPTION("A PCI driver");
MODULE_VERSION("0.0.1");
#define VENDOR_ID 0x10ec
#define DEVICE_ID 0x8168
#define DRIVER_NAME "network_card_pci_driver_mac"
#define CTL_GET_MAC _IOR('mac', 1, char *)
static struct pci_device_id network_card_pci_driver_mac_id_table[] = {
{ PCI_DEVICE(VENDOR_ID, DEVICE_ID) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, network_card_pci_driver_mac_id_table);
static int network_card_pci_driver_mac_probe(struct pci_dev *dev, const struct pci_device_id *id);
static void network_card_pci_driver_mac_remove(struct pci_dev *dev);
static struct pci_driver network_card_pci_driver_mac = {
.name = DRIVER_NAME,
.id_table = network_card_pci_driver_mac_id_table,
.probe = network_card_pci_driver_mac_probe,
.remove = network_card_pci_driver_mac_remove
};
static int network_card_open(struct inode *inode, struct file *file);
static int network_card_release(struct inode *inode, struct file *file);
static ssize_t network_card_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static struct file_operations network_card_fops = {
.owner = THIS_MODULE,
.open = network_card_open,
.release = network_card_release,
.unlocked_ioctl = network_card_ioctl
};
static int Major;
static struct class *network_card_class;
unsigned char mac_addr[6];
static atomic_t already_open = ATOMIC_INIT(0);
static int __init network_card_pci_driver_mac_init(void) {
int register_result = pci_register_driver(&network_card_pci_driver_mac);
if (register_result < 0) {
printk(KERN_ERR
"pci_register_driver failed\n");
return register_result;
}
Major = register_chrdev(0, DRIVER_NAME, &network_card_fops);
if (Major < 0) {
printk(KERN_ERR
"register_chrdev failed\n");
return Major;
}
network_card_class = class_create(THIS_MODULE, DRIVER_NAME);
if (!network_card_class) {
printk(KERN_ERR
"class_create failed\n");
return -1;
}
device_create(network_card_class, NULL, MKDEV(Major, 0), NULL, DRIVER_NAME);
return 0;
}
static void __exit network_card_pci_driver_mac_exit(void) {
class_destroy(network_card_class);
unregister_chrdev(Major, DRIVER_NAME);
pci_unregister_driver(&network_card_pci_driver_mac);
printk(KERN_INFO
"Goodbye cruel world.\n");
return;
}
static int network_card_pci_driver_mac_probe(struct pci_dev *dev, const struct pci_device_id *id) {
u8 __iomem *mmio_base;
int bar = 2;
if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {
mmio_base = pci_iomap(dev, bar, pci_resource_len(dev, bar));
if (!mmio_base) {
printk(KERN_ERR
"pci_iomap failed\n");
return -1;
}
} else {
printk(KERN_ERR
"Not a memory-mapped resource\n");
return -1;
}
int i;
for (i = 0; i < 6; i++) {
mac_addr[i] = ioread8(mmio_base + i);
printk(KERN_INFO
"MAC address byte %d: %02x\n", i, mmio_base[i]);
}
iounmap(mmio_base);
return 0;
}
static void network_card_pci_driver_mac_remove(struct pci_dev *dev) {
dev_t devno = MKDEV(Major, 0);
device_destroy(network_card_class, devno)
}
static int network_card_open(struct inode *inode, struct file *file) {
if (atomic_cmpxchg(&already_open, 0, 1)) {
printk(KERN_ERR
"already_open is true\n");
return -EBUSY;
}
try_module_get(THIS_MODULE);
return 0;
}
static int network_card_release(struct inode *inode, struct file *file) {
atomic_set(&already_open, 0);
module_put(THIS_MODULE);
return 0;
}
static ssize_t network_card_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
switch (cmd) {
case CTL_GET_MAC:
if (copy_to_user((unsigned long __user *) arg, mac_addr, 6) != 0) {
printk(KERN_ERR
"copy_to_user failed\n");
return -EFAULT;
}
break;
default:
printk(KERN_ERR
"unknown ioctl\n");
return -EINVAL;
}
return 0;
}
module_init(network_card_pci_driver_mac_init);
module_exit(network_card_pci_driver_mac_exit);

16
pci/read.py Normal file
View file

@ -0,0 +1,16 @@
import fcntl
MAC_ADDRESS_SIZE = 6
DEVICE_PATH = "/dev/network_card_pci_driver_mac"
MY_IOCTL_GET_MAC_ADDRESS = 0xed696301
if __name__ == "__main__":
device_file = open(DEVICE_PATH, "rb")
mac_address_buffer = bytearray(MAC_ADDRESS_SIZE)
fcntl.ioctl(device_file, MY_IOCTL_GET_MAC_ADDRESS, mac_address_buffer)
print(mac_address_buffer.hex())
device_file.close()

21
shell.nix Normal file
View file

@ -0,0 +1,21 @@
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "env";
nativeBuildInputs = [ pkg-config ];
buildInputs = [
cryptsetup
dbus
systemd
libcap
libgcrypt
xz
zstd
lz4
libgpg-error
libnotify
gdk-pixbuf
glib
glibc
];
}