mirror of
https://github.com/54shady/kernel_drivers_examples.git
synced 2025-08-05 18:35:40 +00:00
Delete crypto driver
This commit is contained in:
@ -1,413 +0,0 @@
|
|||||||
#include <linux/module.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/err.h>
|
|
||||||
#include <linux/ioport.h>
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <asm/uaccess.h>
|
|
||||||
#include <linux/bitops.h>
|
|
||||||
#include <linux/pci.h>
|
|
||||||
|
|
||||||
#define DMA_TEST_DEMO
|
|
||||||
#ifdef DMA_TEST_DEMO
|
|
||||||
struct aaaa {
|
|
||||||
int a;
|
|
||||||
char name[10];
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* refcode: linux/drivers/net/ethernet/intel/e1000/e1000_main.c */
|
|
||||||
#define BAR_0 0
|
|
||||||
char e1000_driver_name[] = "mycrypto";
|
|
||||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
|
||||||
PCI_DEVICE(0x1111, device_id)}
|
|
||||||
static const struct pci_device_id e1000_pci_tbl[] = {
|
|
||||||
INTEL_E1000_ETHERNET_DEVICE(0x2222),
|
|
||||||
/* required last entry */
|
|
||||||
{0,}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum tagIOField {
|
|
||||||
ErrorCode = 0x00,
|
|
||||||
State = 0x01,
|
|
||||||
Command = 0x02,
|
|
||||||
InterruptFlag = 0x03,
|
|
||||||
DmaInAddress = 0x04,
|
|
||||||
DmaInPagesCount = 0x08,
|
|
||||||
DmaInSizeInBytes = 0x0c,
|
|
||||||
DmaOutAddress = 0x10,
|
|
||||||
DmaOutPagesCount = 0x14,
|
|
||||||
DmaOutSizeInBytes = 0x18,
|
|
||||||
MsiErrorFlag = 0x1c,
|
|
||||||
MsiReadyFlag = 0x1d,
|
|
||||||
MsiResetFlag = 0x1e,
|
|
||||||
Unused = 0x1f,
|
|
||||||
} IoField;
|
|
||||||
|
|
||||||
#define NO2STR(n) case n: return #n
|
|
||||||
static const char *iofield2str(IoField io)
|
|
||||||
{
|
|
||||||
switch (io)
|
|
||||||
{
|
|
||||||
NO2STR(ErrorCode);
|
|
||||||
NO2STR(State);
|
|
||||||
NO2STR(Command);
|
|
||||||
NO2STR(InterruptFlag);
|
|
||||||
NO2STR(DmaInAddress);
|
|
||||||
NO2STR(DmaInPagesCount);
|
|
||||||
NO2STR(DmaInSizeInBytes);
|
|
||||||
NO2STR(DmaOutAddress);
|
|
||||||
NO2STR(DmaOutPagesCount);
|
|
||||||
NO2STR(DmaOutSizeInBytes);
|
|
||||||
NO2STR(MsiErrorFlag);
|
|
||||||
NO2STR(MsiReadyFlag);
|
|
||||||
NO2STR(MsiResetFlag);
|
|
||||||
default:
|
|
||||||
return "UnknowIoFiled";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int bit = 0; /* 0: byte, 1: word, 2: long */
|
|
||||||
int regIdx = 0;
|
|
||||||
int val = 0;
|
|
||||||
int bars;
|
|
||||||
void __iomem *hw_addr;
|
|
||||||
void *cpu_in_addr, *cpu_out_addr;
|
|
||||||
dma_addr_t dma_in_addr, dma_out_addr;
|
|
||||||
|
|
||||||
/* cat /sys/devices/pci0000:00/0000:00:03.0/mycrypto_debug */
|
|
||||||
static ssize_t mycrypto_debug_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
switch (bit)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
printk("%s = 0x%x\n", iofield2str(regIdx), readb(hw_addr + regIdx));
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
printk("%s = 0x%x\n", iofield2str(regIdx), readw(hw_addr + regIdx));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
printk("%s = 0x%x\n", iofield2str(regIdx), readl(hw_addr + regIdx));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable interrupt flag to 2 using devmem
|
|
||||||
* devmem 0xfebf1003 b 2
|
|
||||||
*
|
|
||||||
* for MIS#0 (LineBase INTx or signle MSI mode)
|
|
||||||
* 1: Error INT
|
|
||||||
* Enable Error INT flag
|
|
||||||
* echo 0 3 1 > /sys/devices/pci0000\:00/0000\:00\:03.0/mycrypto_debug
|
|
||||||
*
|
|
||||||
* Trigger write ErrorCode
|
|
||||||
* echo 0 0 0 > /sys/devices/pci0000\:00/0000\:00\:03.0/mycrypto_debug
|
|
||||||
*
|
|
||||||
* 2: Ready INT
|
|
||||||
* Enable Ready INT
|
|
||||||
* echo 0 3 2 > /sys/devices/pci0000\:00/0000\:00\:03.0/mycrypto_debug
|
|
||||||
*
|
|
||||||
* Trigger Encrypt
|
|
||||||
* echo 0 2 2 > /sys/devices/pci0000\:00/0000\:00\:03.0/mycrypto_debug
|
|
||||||
*
|
|
||||||
* 3: Reset INT
|
|
||||||
* Enable Reset INT
|
|
||||||
* echo 0 3 3 > /sys/devices/pci0000\:00/0000\:00\:03.0/mycrypto_debug
|
|
||||||
*
|
|
||||||
* Trigger Encrypt
|
|
||||||
* echo 0 2 2 > /sys/devices/pci0000\:00/0000\:00\:03.0/mycrypto_debug
|
|
||||||
*/
|
|
||||||
static ssize_t mycrypto_debug_store(struct device *dev,
|
|
||||||
struct device_attribute *attr, const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
sscanf(buf, "%d %d %d", &bit, ®Idx, &val);
|
|
||||||
printk("Write [0x%x]%s = %d\n", hw_addr + regIdx, iofield2str(regIdx), val);
|
|
||||||
|
|
||||||
switch (bit)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
/* byte write */
|
|
||||||
writeb(val & 0xf, hw_addr + regIdx);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
/* word write */
|
|
||||||
writew(val & 0xff, hw_addr + regIdx);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
/* long write */
|
|
||||||
writel(val, hw_addr + regIdx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEVICE_ATTR(mycrypto_debug, S_IRUGO | S_IWUSR, mycrypto_debug_show, mycrypto_debug_store);
|
|
||||||
|
|
||||||
static struct attribute *mycrypto_attrs[] = {
|
|
||||||
&dev_attr_mycrypto_debug.attr,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attribute_group mycrypto_attr_group = {
|
|
||||||
.attrs = mycrypto_attrs,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum tagCryptoDeviceMSI
|
|
||||||
{
|
|
||||||
CryptoDevice_MsiZero = 0x00,
|
|
||||||
CryptoDevice_MsiError = 0x01,
|
|
||||||
CryptoDevice_MsiReady = 0x02,
|
|
||||||
CryptoDevice_MsiReset = 0x03,
|
|
||||||
CryptoDevice_MsiMax = 0x04,
|
|
||||||
} CryptoDeviceMSI;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CryptoDevice_NoError,
|
|
||||||
CryptoDevice_DmaError,
|
|
||||||
CryptoDevice_DeviceHasBennReseted,
|
|
||||||
CryptoDevice_WriteIoError,
|
|
||||||
CryptoDevice_InternalError
|
|
||||||
} CryptoDeviceErrorCode;
|
|
||||||
|
|
||||||
static const char *errno2errstr(CryptoDeviceErrorCode error)
|
|
||||||
{
|
|
||||||
switch (error)
|
|
||||||
{
|
|
||||||
NO2STR(CryptoDevice_NoError);
|
|
||||||
NO2STR(CryptoDevice_DmaError);
|
|
||||||
NO2STR(CryptoDevice_DeviceHasBennReseted);
|
|
||||||
NO2STR(CryptoDevice_WriteIoError);
|
|
||||||
NO2STR(CryptoDevice_InternalError);
|
|
||||||
default:
|
|
||||||
return "UnknowError";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static irqreturn_t crypto_irq_handler(int irq, void *data)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = readb(hw_addr + InterruptFlag);
|
|
||||||
/* read interrupt flag */
|
|
||||||
printk("Interrupt(%d) is %d -> %s\n", irq, ret, ret ? "Enable" : "Disable");
|
|
||||||
/* INTx */
|
|
||||||
if (ret == CryptoDevice_MsiError)
|
|
||||||
{
|
|
||||||
printk("ErrorINT handled\n");
|
|
||||||
printk("ErrorCode: %s\n", errno2errstr(readb(hw_addr + ErrorCode)));
|
|
||||||
}
|
|
||||||
if (ret == CryptoDevice_MsiReady)
|
|
||||||
{
|
|
||||||
printk("ReadyINT handled\n");
|
|
||||||
/* 从dma buffer中取出数据 */
|
|
||||||
struct aaaa *pa = cpu_out_addr;
|
|
||||||
printk("Read Dma data back: %d %s\n", pa->a, pa->name);
|
|
||||||
}
|
|
||||||
if (ret == CryptoDevice_MsiReset)
|
|
||||||
printk("ResetINT handled\n");
|
|
||||||
|
|
||||||
/* MSI#1,2,3 */
|
|
||||||
//if (readb(hw_addr + MsiErrorFlag))
|
|
||||||
// printk("MsiErrorFlag is set\n");
|
|
||||||
//if (readb(hw_addr + MsiReadyFlag))
|
|
||||||
// printk("MsiReadyFlag is set\n");
|
|
||||||
//if (readb(hw_addr + MsiResetFlag))
|
|
||||||
// printk("MsiResetFlag is set\n");
|
|
||||||
|
|
||||||
/* disable irq */
|
|
||||||
disable_irq_nosync(irq);
|
|
||||||
|
|
||||||
/* clear int */
|
|
||||||
writeb(0, hw_addr + InterruptFlag);
|
|
||||||
writeb(0, hw_addr + MsiErrorFlag);
|
|
||||||
writeb(0, hw_addr + MsiReadyFlag);
|
|
||||||
writeb(0, hw_addr + MsiResetFlag);
|
|
||||||
|
|
||||||
/* enable irq */
|
|
||||||
enable_irq(irq);
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
||||||
{
|
|
||||||
int err;
|
|
||||||
|
|
||||||
bars = pci_select_bars(pdev, IORESOURCE_MEM);
|
|
||||||
printk("bars = %d, %s, %d\n", bars, __FUNCTION__, __LINE__);
|
|
||||||
err = pci_enable_device_mem(pdev);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
printk("%s, %d\n", "Error*****", __LINE__);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = pci_request_selected_regions(pdev, bars, e1000_driver_name);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
printk("%s, %d\n", "error", __LINE__);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
pci_set_master(pdev);
|
|
||||||
err = pci_save_state(pdev);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
printk("%s, %d\n", "error", __LINE__);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
hw_addr = pci_ioremap_bar(pdev, BAR_0);
|
|
||||||
if (!hw_addr)
|
|
||||||
{
|
|
||||||
printk("%s, %d\n", "error", __LINE__);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
printk("hw_addr = 0x%x\n", hw_addr);
|
|
||||||
printk("ErrorCode = 0x%x\n", readb(hw_addr + ErrorCode));
|
|
||||||
printk("State = 0x%x\n", readb(hw_addr + State));
|
|
||||||
printk("Command = 0x%x\n", readb(hw_addr + Command));
|
|
||||||
printk("InterruptFlag = 0x%x\n", readb(hw_addr + InterruptFlag));
|
|
||||||
|
|
||||||
printk("irq = %d\n", pdev->irq);
|
|
||||||
err = request_irq(pdev->irq, crypto_irq_handler, IRQF_ONESHOT, "crypto-irq", NULL);
|
|
||||||
//err = request_irq(pdev->irq, crypto_irq_handler, IRQF_PROBE_SHARED, "crypto-irq", NULL);
|
|
||||||
if (err) {
|
|
||||||
printk("Unable to allocate interrupt Error: %d\n", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* sysfs for debug */
|
|
||||||
err = sysfs_create_group(&pdev->dev.kobj, &mycrypto_attr_group);
|
|
||||||
if (err) {
|
|
||||||
printk("failed to create sysfs device attributes\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST_VIRT_TO_PHY
|
|
||||||
struct aaaa {
|
|
||||||
int a;
|
|
||||||
char name[10];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct aaaa *virt4a;
|
|
||||||
unsigned long phy4a;
|
|
||||||
|
|
||||||
virt4a = kmalloc(sizeof(struct aaaa), GFP_ATOMIC);
|
|
||||||
if (!virt4a)
|
|
||||||
return -1;
|
|
||||||
virt4a->a = 911;
|
|
||||||
strcpy(virt4a->name, "virt4a");
|
|
||||||
phy4a = virt_to_phys(virt4a);
|
|
||||||
printk("phy4a = 0x%lx, virt4a = 0x%lx\n", phy4a, virt4a);
|
|
||||||
writel(phy4a, hw_addr + DmaInAddress);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
printk("%s, %d\n", "error", __LINE__);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* driver using cpu_in_addr, pass the dma_in_addr/dma_out_addr to device */
|
|
||||||
cpu_in_addr = dma_alloc_coherent(&pdev->dev, 4096, &dma_in_addr, GFP_KERNEL);
|
|
||||||
if (!cpu_in_addr)
|
|
||||||
{
|
|
||||||
printk("Failed allocation memory for DMA\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST_VIRT_TO_PHY
|
|
||||||
//memcpy(cpu_in_addr, virt4a, 4096);
|
|
||||||
|
|
||||||
struct aaaa a = {
|
|
||||||
.a = 912,
|
|
||||||
.name = "test-dma"
|
|
||||||
};
|
|
||||||
memcpy(cpu_in_addr, &a, sizeof(struct aaaa));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DMA_TEST_DEMO
|
|
||||||
/* setup data */
|
|
||||||
struct aaaa a = {
|
|
||||||
.a = 911,
|
|
||||||
.name = "DmaIn"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 将需要传输的数据放入dma buffer */
|
|
||||||
memcpy(cpu_in_addr, &a, sizeof(struct aaaa));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printk("DmaInAddress = 0x%llx, cpu_in = 0x%x\n", dma_in_addr, cpu_in_addr);
|
|
||||||
writel(dma_in_addr, hw_addr + DmaInAddress);
|
|
||||||
writel(4096, hw_addr + DmaInSizeInBytes);
|
|
||||||
writel(1, hw_addr + DmaInPagesCount);
|
|
||||||
|
|
||||||
cpu_out_addr = dma_alloc_coherent(&pdev->dev, 4096, &dma_out_addr, GFP_KERNEL);
|
|
||||||
if (!cpu_out_addr)
|
|
||||||
{
|
|
||||||
printk("Failed allocation memory for DMA\n");
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
printk("DmaOutAddress = 0x%llx, cpu_out = 0x%x\n", dma_out_addr, cpu_out_addr);
|
|
||||||
writel(dma_out_addr, hw_addr + DmaOutAddress);
|
|
||||||
writel(4096, hw_addr + DmaOutSizeInBytes);
|
|
||||||
writel(1, hw_addr + DmaOutPagesCount);
|
|
||||||
|
|
||||||
#ifdef DMA_TEST_DEMO
|
|
||||||
/* 从dma buffer中取出数据 */
|
|
||||||
struct aaaa *pa = cpu_out_addr;
|
|
||||||
printk("Dma data: %d %s\n", pa->a, pa->name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void e1000_remove(struct pci_dev *pdev)
|
|
||||||
{
|
|
||||||
printk("%s, %d\n", __FUNCTION__, __LINE__);
|
|
||||||
pci_release_selected_regions(pdev, bars);
|
|
||||||
iounmap(hw_addr);
|
|
||||||
|
|
||||||
sysfs_remove_group(&pdev->dev.kobj, &mycrypto_attr_group);
|
|
||||||
|
|
||||||
free_irq(pdev->irq, NULL);
|
|
||||||
|
|
||||||
dma_free_coherent(&pdev->dev, 4096, cpu_in_addr, dma_in_addr);
|
|
||||||
dma_free_coherent(&pdev->dev, 4096, cpu_out_addr, dma_out_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void e1000_shutdown(struct pci_dev *pdev)
|
|
||||||
{
|
|
||||||
printk("%s, %d\n", __FUNCTION__, __LINE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct pci_driver e1000_driver = {
|
|
||||||
.name = e1000_driver_name,
|
|
||||||
.id_table = e1000_pci_tbl,
|
|
||||||
.probe = e1000_probe,
|
|
||||||
.remove = e1000_remove,
|
|
||||||
.shutdown = e1000_shutdown,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init e1000_init_module(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = pci_register_driver(&e1000_driver);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
module_init(e1000_init_module);
|
|
||||||
|
|
||||||
static void __exit e1000_exit_module(void)
|
|
||||||
{
|
|
||||||
pci_unregister_driver(&e1000_driver);
|
|
||||||
}
|
|
||||||
module_exit(e1000_exit_module);
|
|
||||||
MODULE_LICENSE("GPL");
|
|
Reference in New Issue
Block a user