diff --git a/Driver/pcie40/ecs.c b/Driver/pcie40/ecs.c deleted file mode 100644 index de97d98be92cdb51994b3c0c7768df63a612cf34..0000000000000000000000000000000000000000 --- a/Driver/pcie40/ecs.c +++ /dev/null @@ -1,94 +0,0 @@ -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <linux/ioctl.h> -#include <sys/ioctl.h> -#include <sys/mman.h> - -#include "ecs.h" -#include "pcie40.h" -#include "pcie40_ioctl.h" - -//`p40_ecs_open` -int p40_ecs_open(int dev, int bar, uint32_t **regs) -{ - int fd; - char devname[32]; - - char *suffix; - switch (bar) { - case 0: - suffix = "bar0"; - break; - case 2: - suffix = "bar2"; - break; - default: - return -EINVAL; - } - - if (p40_get_devname(dev, suffix, devname, sizeof(devname)) < 0) { - perror("p40_get_devname()"); - return -1; - } - - if ((fd = open(devname, O_RDWR)) == -1){ - perror("open()"); - return -1; - } - - int bar_size = p40_ecs_bar_size(fd); - if (bar_size < 0) { - close(fd); - return -1; - } - - *regs = mmap(NULL, bar_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (*regs == NULL) { - perror("mmap()"); - close(fd); - return -1; - } - - return fd; -} - -//`p40_ecs_close` -void p40_ecs_close(int fd, uint32_t *regs) -{ - int bar_size = p40_ecs_bar_size(fd); - munmap(regs, bar_size); - close(fd); -} - -//`p40_ecs_bar_size` -int p40_ecs_bar_size(int fd) -{ - int ret; - - //? See ioctl.pcie`P40_ECS_GET_BAR_SIZE` . - ret = ioctl(fd, P40_ECS_GET_BAR_SIZE); - if (ret < 0) { - perror("ioctl(P40_ECS_GET_BAR_SIZE)"); - return -1; - } - return ret; -} - -//`p40_ecs_w32` -void p40_ecs_w32(uint32_t volatile *regs, uint32_t addr, uint32_t val) -{ - regs[addr >> 2] = val; -} - -//`p40_ecs_r32` -uint32_t p40_ecs_r32(uint32_t volatile *regs, uint32_t addr) -{ - return regs[addr >> 2]; -} diff --git a/Driver/pcie40/ecs.h b/Driver/pcie40/ecs.h deleted file mode 100644 index 4227e6bd0ec92ba1f18fd724a6932fef8326d1ee..0000000000000000000000000000000000000000 --- a/Driver/pcie40/ecs.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __PCIE40_ECS_H -#define __PCIE40_ECS_H - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -//dg`wt.pcie40.c.ecs` In order to interact with the ECS interface of the PCIe40 driver, C libraries are provided (*libpcie40_ecs.so* and *libpcie40_ecs.a*). -// To use these libraries, add ``#include <lhcb/pcie40/ecs.h>`` to your source code and ``-lpcie40_ecs`` to your linker flags. -// This API is very simple, consisting only of a handful of functions to create I/O memory mappings and to access individual I/O registers, see <<PCIe40 driver ECS API>>. - -//`p40_ecs_open` Create file descriptor to access an ECS BAR. -int p40_ecs_open(int dev, int bar, uint32_t **regs);//?> -//>`dev` Device identifier corresponding to the given board. -//>`bar` PCI BAR to access, valid values are 0 (for the user registers) and 2 (for the low-level registers). -//<`regs` Address of a valid +uint32_t *+ pointer. It is set by the function upon return. - -//`p40_ecs_close` Destroy file descriptor to an open ECS BAR. -void p40_ecs_close(int fd, uint32_t *regs);//?> -//>`fd` File descriptor returned by `p40_ecs_open` . -//>`regs` Pointer populated by `p40_ecs_open` . - -//`p40_ecs_bar_size` Query driver for size of a given PCI BAR. -int p40_ecs_bar_size(int fd);//?> -//>`fd` File descriptor returned by `p40_ecs_open` . - -//`p40_ecs_w32` Write register at given address. -void p40_ecs_w32(uint32_t volatile *regs, uint32_t addr, uint32_t val);//?> -//>`regs` Pointer populated by `p40_ecs_open` . -//>`addr` Address of register. -//>`val` 32-bit value to write. - -//`p40_ecs_r32` Read register at given address. -uint32_t p40_ecs_r32(uint32_t volatile *regs, uint32_t addr);//?> -//>`regs` Pointer populated by `p40_ecs_open` . -//>`addr` Address of register. - -#ifdef __cplusplus -} //extern "C" -#endif - -#endif//__PCIE40_ECS_H diff --git a/Driver/pcie40_driver/.gitignore b/Driver/pcie40_driver/.gitignore deleted file mode 100644 index 0f4f2ca7c8c700bcc39281e1b8e65603878bb9d4..0000000000000000000000000000000000000000 --- a/Driver/pcie40_driver/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -*.o -.tmp_versions/ -.*.o.cmd -.*.ko.cmd -Module.symvers -module.target -modules.order -pcie40.ko -pcie40.mod.c -pcie40_emu.ko -pcie40_emu.mod.c diff --git a/Driver/pcie40_driver/Makefile b/Driver/pcie40_driver/Makefile deleted file mode 100644 index d4f66277515f3e5d5d93ba1ac9f5d534150c131c..0000000000000000000000000000000000000000 --- a/Driver/pcie40_driver/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# Makefile for 2.6+ kernels -# -# Will compile and install for other kernel than the currently running, -# given the TARGET parameter (should be the name of a directory in -# /lib/modules) e.g. -# make TARGET=2.6.32.10-90.fc12.x86_64 -# -DAQ40_VER_REL ?=local-wip -ifneq ($(KERNELRELEASE),) -obj-m :=pcie40.o pcie40_emu.o -pcie40-y :=common.o main.o ecs.o daq.o -pcie40_emu-y :=common.o main_emu.o ecs_emu.o daq_emu.o -ccflags-y :=-DDAQ40_VER_REL=\"$(DAQ40_VER_REL)\" -else -ifeq ($(TARGET),) -TARGET :=$(shell uname -r) -endif -PWD :=$(shell pwd) -KDIR :=/lib/modules/$(TARGET)/build - -default: - @echo $(TARGET) > module.target - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules - -default: pcie40_dma_regmap.h pcie40_ioctl.h common.h common.c ecs.h daq.h - -default: main.c ecs.c daq.c - -default: main_emu.c ecs_emu.c daq_emu.c - -clean: - @rm -f *.ko *.o .*.cmd modules.order Module.symvers *.mod.? .pcie40.* *~ *.unsigned - @rm -rf .tmp_versions module.target - -install: pcie40.ko - install --mode 0755 -d /lib/modules/$(shell cat module.target)/extra - install --mode 0644 pcie40.ko /lib/modules/$(shell cat module.target)/extra - install --mode 0644 pcie40_emu.ko /lib/modules/$(shell cat module.target)/extra - /sbin/depmod -a $(shell cat module.target) - -pcie40.ko pcie40_emu.ko: - $(MAKE) - -ifneq ("$(wildcard ../common/pcie40_dma_regmap.cfg)","") -pcie40_dma_regmap.h: ../common/pcie40_dma_regmap.cfg - ../common/regmap_cfg_to_h.tcl P40_ $< > $@ 2> /dev/null -endif -endif diff --git a/Driver/pcie40_driver/common.c b/Driver/pcie40_driver/common.c deleted file mode 100644 index 702b24beb9975f3e63c4b7af55b6930ca85d20b9..0000000000000000000000000000000000000000 --- a/Driver/pcie40_driver/common.c +++ /dev/null @@ -1,33 +0,0 @@ -#define P40_FMT "P40:%s(): " - -#include "common.h" - -int pcie40_setup_cdev(struct class *cls, struct cdev *cdev, dev_t dev_num, int minor, int bar, const char *dev_name, int dev_id, struct file_operations *fops) -{ - int rc = 0; - char dev_name_full[16] = {0}; - - snprintf(dev_name_full, sizeof(dev_name_full), "pcie40_%d_%s", dev_id, dev_name); - - printk(P40_DIAG "device_create /dev/%s BAR=%d MAJ=%d, MIN=%d\n", P40_PARM, dev_name_full, bar, MAJOR(dev_num), MINOR(dev_num)+minor); - - if (device_create(cls, NULL, MKDEV(MAJOR(dev_num), MINOR(dev_num)+minor), NULL, dev_name_full) == NULL){ - rc = -1; - printk(P40_DIAG "device_create()\n", P40_PARM); - goto err_device_create; - } - cdev_init(cdev, fops); - - rc = cdev_add(cdev, MKDEV(MAJOR(dev_num), MINOR(dev_num)+minor), 1); - if (rc < 0){ - printk(P40_DIAG "cdev_add()\n", P40_PARM); - goto err_cdev_add; - } - return 0; - -err_cdev_add: - device_destroy(cls, MKDEV(MAJOR(dev_num), MINOR(dev_num)+minor)); -err_device_create: -//err_no_bar: - return rc; -} diff --git a/Driver/pcie40_driver/common.h b/Driver/pcie40_driver/common.h deleted file mode 100644 index 976e2b059bbf85451b12764acb6f0d8810c2e14a..0000000000000000000000000000000000000000 --- a/Driver/pcie40_driver/common.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef __PCIE40_DRIVER_COMMON_H -#define __PCIE40_DRIVER_COMMON_H -//p40driver``+ - -#include <linux/cdev.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/version.h> - -#include "pcie40_dma_regmap.h" - -#ifndef P40_FMT -#error "#define P40_FMT before including this file" -#endif -#define P40_DRV_NAME "lhcb_pcie40" -#define P40_INFO KERN_INFO P40_FMT -#define P40_WARN KERN_WARNING P40_FMT -#define P40_DIAG KERN_DEBUG P40_FMT -#define P40_ERR KERN_ERR P40_FMT -#define P40_PARM __FUNCTION__ - -#define P40_MAX_BAR 3 - -#define P40_COMMON_BARS_MASK ((1<<1)) //BAR1 - -#define PCI_MAX_ALLOC (4*1024*1024) //0x20000 - -//+`pcie40_state` -struct pcie40_state { - struct list_head list; - struct pci_dev *pci_dev; - - unsigned long bar_start[P40_MAX_BAR]; - unsigned long bar_size[P40_MAX_BAR]; - - int link_id; //0 or 1 - int dev_id; //unique device identifier, even for all link 0s, odd for all link 1s - -#ifndef PCIE40_EMU - void __iomem *bar0_regs; - void __iomem *bar1_regs; -#else - void *bar0_regs; - void *bar1_regs; - void *bar2_regs; -#endif - - struct pcie40_ecs_state *ecs_state; - struct pcie40_daq_state *daq_state; - struct pcie40_cvp_state *cvp_state; -}; - -static inline uint32_t pcie40_read32_bar0(struct pcie40_state *common, unsigned long offset) -{ -#ifndef PCIE40_EMU - return ioread32(common->bar0_regs + offset); -#else - return *(uint32_t *)(common->bar0_regs + offset); -#endif -} - -static inline void pcie40_write32_bar0(struct pcie40_state *common, unsigned long offset, uint32_t value) -{ -#ifndef PCIE40_EMU - iowrite32(value, common->bar0_regs + offset); -#else - *(uint32_t *)(common->bar0_regs + offset) = value; -#endif -} - -static inline uint32_t pcie40_read32_ctrl(struct pcie40_state *common, unsigned long offset) -{ -#ifndef PCIE40_EMU - return ioread32(common->bar1_regs + P40_DMA_CTRL_QSYS_BASE + offset); -#else - return *(uint32_t *)(common->bar1_regs + P40_DMA_CTRL_QSYS_BASE + offset); -#endif -} - -static inline void pcie40_write32_ctrl(struct pcie40_state *common, unsigned long offset, uint32_t value) -{ -#ifndef PCIE40_EMU - iowrite32(value, common->bar1_regs + P40_DMA_CTRL_QSYS_BASE + offset); -#else - *(uint32_t *)(common->bar1_regs + P40_DMA_CTRL_QSYS_BASE + offset) = value; -#endif -} - -static inline int pcie40_device_accessible(struct pcie40_state *common) -{ - uint32_t version = pcie40_read32_ctrl(common, P40_DMA_CTRL_OFF_VERSION); - return version != 0xFFFFFFFF; -} - -/* -static int pcie40_dev_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - add_uevent_var(env, "DEVMODE=%#o", 0666); - return 0; -} -*/ -static inline char *pcie40_devnode(struct device *dev, umode_t *mode) -{ - if (mode) { - *mode = 0666; - } - return NULL; -} - -int pcie40_setup_cdev(struct class *cls, struct cdev *cdev, dev_t dev_num, int minor, int bar, const char *dev_name, int dev_id, struct file_operations *fops); - -#endif//__PCIE40_DRIVER_COMMON_H diff --git a/Driver/pcie40_driver/daq.c b/Driver/pcie40_driver/daq.c deleted file mode 100644 index 13e7ecd338dd2425c2322300b2e48b59101de712..0000000000000000000000000000000000000000 --- a/Driver/pcie40_driver/daq.c +++ /dev/null @@ -1,483 +0,0 @@ -//p40fpga``+ -#define P40_FMT "P40DAQ:%s(): " -#define PCIE40_DAQ_CLASS "lhcb_pcie40_daq" - -#include <linux/pci.h> -#include <linux/types.h> - -struct pcie40_dma_map; - -static int dma_map_alloc(struct pci_dev *pci_dev, struct pcie40_dma_map* map, void __iomem *base, size_t max_entries, size_t desired_size); -static int dma_map_free(struct pci_dev *pci_dev, struct pcie40_dma_map* map); - -#include "daq.h" - -#include <linux/interrupt.h> - -//+`EXPECTED_FPGA_VERSION` -#define EXPECTED_FPGA_VERSION (0x0400)//?> - -static void pcie40_daq_set_drvdata(struct pci_dev *pci_dev, struct pcie40_daq_state *state) -{ - struct pcie40_state *common = pci_get_drvdata(pci_dev); - common->daq_state = state; - common->daq_state->common = common; -} -static struct pcie40_daq_state *pcie40_daq_get_drvdata(struct pci_dev *pci_dev) -{ - struct pcie40_state *common = pci_get_drvdata(pci_dev); - return common->daq_state; -} - -//NOTE: select/epoll behaviour: -// - if MSI_MODE is DAQ: -// poll the _ctrl* file descriptor for CTRL_MSI_BLOCKS interrupts -// - if MSI_MODE is MAIN: -// poll the _main* file descriptor for MAIN_MSI_BYTES interrupts -// - if MSI_MODE is META: -// poll the _meta* file descriptor for META_MSI_BYTES interrupts - -//+`pcie_bus_detect_mps` -static void pcie_bus_detect_mps(struct pci_dev *pci_dev)//;?> -{ - struct pci_dev *bridge = pci_dev->bus->self; - int mps, p_mps; - if (!bridge) - return; - - mps = pcie_get_mps(pci_dev); - p_mps = pcie_get_mps(bridge); - if (mps != p_mps) - dev_warn(&pci_dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n", - mps, pci_name(bridge), p_mps); - else - dev_info(&pci_dev->dev, "Max Payload Size = %d\n", mps); -} - -//+`dma_map_write_entry` -static void dma_map_write_entry(struct pcie40_dma_map* map, int i)//;?> -{ - struct pcie40_dma_buffer* buffer = map->entries + i; - size_t pages = buffer->size >> PAGE_SHIFT; - iowrite32(buffer->start >> 32, map->base + i * 8 + 4); - iowrite32((buffer->start | pages) & 0xFFFFFFFF, map->base + i * 8); - wmb(); -} - -//+`dma_map_read_entry_base` -static inline dma_addr_t dma_map_read_entry_base(struct pcie40_dma_map* map, int i)//;?> -{ - uint64_t lo, hi; - dma_addr_t base; - struct pcie40_dma_buffer* buffer = map->entries + i; - - lo = ioread32(map->base + i * 8); - hi = ioread32(map->base + i * 8 + 4); - - base = (hi << 32) | (lo & PAGE_MASK); - WARN_ON(base != buffer->start); - return base; -} - -//+`dma_map_read_entry_size` -static inline size_t dma_map_read_entry_size(struct pcie40_dma_map* map, int i)//;?> -{ - uint32_t lo; - size_t size; - struct pcie40_dma_buffer* buffer = map->entries + i; - - lo = ioread32(map->base + i * 8); - - size = (lo & PAGE_MASK) << PAGE_SHIFT; - WARN_ON(size != buffer->size); - return size; -} - -//+`dma_map_alloc` -static int dma_map_alloc(struct pci_dev *pci_dev, struct pcie40_dma_map* map, void __iomem *base, size_t max_entries, size_t desired_size)//;?> -{ - int i; - - map->base = base; - map->max_entries = max_entries; - map->num_entries = 0; - map->size = 0; - map->entries = kzalloc(sizeof(struct pcie40_dma_buffer)*max_entries, GFP_KERNEL); - - printk(P40_DIAG "entries = 0x%p\n", P40_PARM, map->entries); - - for (i = 0; i < map->max_entries; ++i) { - size_t alloc_size = desired_size - map->size > PCI_MAX_ALLOC - ? PCI_MAX_ALLOC - : desired_size - map->size; - while (1) { - struct pcie40_dma_buffer* buffer = map->entries + i; - buffer->size = alloc_size; - buffer->ptr = pci_alloc_consistent(pci_dev, buffer->size, &buffer->start); - //printk("...%zu", buffer->size); - if (buffer->ptr == NULL) { - if (buffer->size < 1024*1024) { - printk("...NOT ENOUGH MEMORY!\n"); - map->num_entries = i; - dma_map_free(pci_dev, map); - return -1; - } - alloc_size /= 2; - } else { - map->size += buffer->size; - break; - } - } - - dma_map_write_entry(map, i); - - if (map->size >= desired_size) { - ++i; - break; - } - } - map->num_entries = i; - - return 0; -} - -//+`dma_map_free` -static int dma_map_free(struct pci_dev *pci_dev, struct pcie40_dma_map* map)//?> -{ - int i; - for (i = 0; i < map->num_entries; ++i) { - struct pcie40_dma_buffer* buffer = map->entries + i; - pci_free_consistent(pci_dev, buffer->size, buffer->ptr, buffer->start); - } - kfree(map->entries); - map->entries = NULL; - - return 0; -} - -//+`pcie40_isr` -static irqreturn_t pcie40_isr(int irq, void *arg)//;?> -{ - /* So, since the FPGA can't get more than one MSI from the kernel, - and since MSI-X is a bit overkill for now, we'll use the same isr - and the same wait queue, and the ONLY thing we do here is wake up the - wait queue, all timers and stuff could just go in the poll handler... - */ -// uint32_t write_off, read_off; - ktime_t now = ktime_get_real(); - - struct pcie40_daq_state *state = (struct pcie40_daq_state *)arg; - if (IS_ERR(state)) { - return IRQ_NONE; - } - - spin_lock_irqsave(&state->main_stream.off_lock, state->main_stream.off_flags); - dma_stream_get_write_off(&state->main_stream); - spin_unlock_irqrestore(&state->main_stream.off_lock, state->main_stream.off_flags); - - spin_lock_irqsave(&state->meta_stream.off_lock, state->meta_stream.off_flags); - dma_stream_get_write_off(&state->meta_stream); - spin_unlock_irqrestore(&state->meta_stream.off_lock, state->meta_stream.off_flags); - - wake_up_interruptible(&state->wait); - - //if (irq == state->irq_line) { - state->main_stream.msi_delay = ktime_sub(now, state->main_stream.msi_last); -/* - write_off = ioread32(state->common->bar1_regs - + state->main_stream.regs_base - + P40_DMA_DAQ_STREAM_OFF_HOST_BUF_WRITE_OFF); - - read_off = write_off < PAGE_SIZE - ? state->main_stream.map.size - PAGE_SIZE - : write_off - PAGE_SIZE; - - iowrite32(read_off, state->common->bar1_regs - + state->main_stream.regs_base - + P40_DMA_DAQ_STREAM_OFF_HOST_BUF_READ_OFF); -*/ - state->main_stream.msi_last = now; - state->main_stream.msi_count++;/* - } else if (irq == state->irq_line+1) { - state->meta_stream.msi_delay = ktime_sub(now, state->meta_stream.msi_last); - - write_off = ioread32(state->common->bar1_regs - + state->meta_stream.regs_base - + P40_DMA_DAQ_STREAM_OFF_HOST_BUF_WRITE_OFF); - - read_off = write_off < PAGE_SIZE - ? state->meta_stream.map.size - PAGE_SIZE - : write_off - PAGE_SIZE; - - iowrite32(read_off, state->common->bar1_regs - + state->meta_stream.regs_base - + P40_STREAM_GET_HOST_BUF_READ_OFF); - - state->meta_stream.msi_last = now; - state->meta_stream.msi_count++; - }*/ - return IRQ_HANDLED; - -#if 0 - - uint32_t write_off, read_off; - ktime_t now = ktime_get_real(); - //getnstimeofday(&now); - //diff_timeval(&(state->daq_delay), &now, &(state->daq_msi)); - state->daq_delay = ktime_sub(now, state->daq_last_msi); - - write_off = ioread32(state->common->bar1_regs + P40_OFF_MEM_WRITE_OFF); - read_off = write_off < PAGE_SIZE - ? state->memmap.size - PAGE_SIZE - : write_off - PAGE_SIZE; - rmb(); - if (read_off == 0xFFFFFFFF) { - printk(P40_ERR "Read unvalid value at P40_OFF_MEM_READ_OFF", P40_PARM); - return IRQ_HANDLED; - } - - //automatically advance read pointer (this is for testing only, in reality the event builder should advance the pointer) - - //read_off = read_off ? 0 : (state->daq_mem_size / 2); - /*read_off += 2*1024*2024; //TODO: this is actually a parameter - if (read_off >= state->daq_mem_size) { - read_off = 0; - }*/ - - iowrite32(read_off, state->common->bar1_regs + P40_OFF_MEM_READ_OFF); - wmb(); - - //memcpy(&(state->daq_msi), &now, sizeof(state->daq_msi)); - state->daq_last_msi = now; - - state->irq_count++; -#endif - return IRQ_HANDLED; -} - -//+`pcie40_daq_probe` -int pcie40_daq_probe(struct pci_dev *dev, const struct pci_device_id *id)//;?> -{ - int rc = 0; - - struct pcie40_state *common; - struct pcie40_daq_state *state = NULL; - uint32_t regmap_version, fpga_version; - - common = pci_get_drvdata(dev); - - state = kzalloc(sizeof(struct pcie40_daq_state), GFP_KERNEL); - if (IS_ERR(state)) { - printk(P40_ERR "kzalloc()\n", P40_PARM); - rc = PTR_ERR(state); - goto err_kzalloc; - } - state->common = common; - printk(P40_DIAG "state = 0x%p\n", P40_PARM, state); - - init_waitqueue_head(&state->wait); - - if (!pci_set_dma_mask(dev, DMA_BIT_MASK(64))) { - pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64)); - printk(P40_INFO "using 64-bit DMA mask\n", P40_PARM); - } else if (!pci_set_dma_mask(dev, DMA_BIT_MASK(32))) { - pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(32)); - printk(P40_INFO "using 32-bit DMA mask\n", P40_PARM); - } else { - printk(P40_WARN "unable to set 32-bit DMA mask\n", P40_PARM); - rc = -1; //TODO - goto err_pci_set_dma_mask; - } - pcie_bus_detect_mps(dev); - - rc = alloc_chrdev_region(&(state->dev_num), P40_DAQ_CDEV_BASEMINOR, P40_DAQ_CDEV_COUNT, P40_DRV_NAME); - if (rc < 0) { - printk(P40_ERR "alloc_chrdev_region()\n", P40_PARM); - goto err_alloc_chrdev_region; - } - - // Reset to default state - pcie40_write32_ctrl(state->common, P40_DMA_CTRL_OFF_RESET, (1 << P40_RST_BIT_DEFAULT)); - - regmap_version = pcie40_read32_ctrl(state->common, P40_DMA_CTRL_OFF_REGMAP); - printk(P40_INFO "Register map version: 0x%08X\n", P40_PARM, regmap_version); - if (regmap_version != P40_DMA_REGMAP_VERSION) { - printk(P40_ERR "Versions do not match (0x%08X expected)!\n", P40_PARM, - P40_DMA_REGMAP_VERSION); - rc = -1; - goto err_version; - } - - fpga_version = pcie40_read32_ctrl(state->common, P40_DMA_CTRL_OFF_VERSION); - printk(P40_INFO "FPGA core version: %X.%02X (%04X)\n", P40_PARM, - fpga_version >> 24, (fpga_version >> 16) & 0xFF, fpga_version & 0xFFFF); - if ((fpga_version >> 16) != EXPECTED_FPGA_VERSION) { - printk(P40_ERR "Version is not compatible with this driver!\n", P40_PARM); - rc = -1; - goto err_version; - } - - // CTRL endpoint - rc = pcie40_setup_cdev(pcie40_daq_class, &(state->ctrl_cdev), state->dev_num, CTRL_CDEV_MINOR, 1, CTRL_CDEV_NAME, state->common->dev_id, &ctrl_file_ops); - if (rc < 0) { - goto err_dev_ctrl; - } - - // TODO: the streams should be configured only when the corresponding device is opened (so, if we're not using metadata or odin, that memory will not be allocated at all) - - if (mainmibs < 0 || mainmibs > MAIN_BUF_MIBS_MAX) { - mainmibs = MAIN_BUF_MIBS_MAX; - } - - // MAIN stream - state->main_stream.cdev_name = MAIN_CDEV_NAME; - state->main_stream.cdev_minor = MAIN_CDEV_MINOR; - state->main_stream.regs_base = P40_DMA_DAQ_MAIN_STREAM_QSYS_BASE; - state->main_stream.state = state; - rc = dma_stream_configure(state->common->dev_id, &state->main_stream, - P40_DMA_DAQ_MAIN_MAP_QSYS_BASE, MAIN_MAP_MAX_ENTRIES, mainmibs * 1024LL*1024LL); - if (rc < 0) { - goto err_main_configure; - } - - if (metamibs < 0 || metamibs > META_BUF_MIBS_MAX) { - metamibs = META_BUF_MIBS_MAX; - } - - // META stream - state->meta_stream.cdev_name = META_CDEV_NAME; - state->meta_stream.cdev_minor = META_CDEV_MINOR; - state->meta_stream.regs_base = P40_DMA_DAQ_META_STREAM_QSYS_BASE; - state->meta_stream.state = state; - rc = dma_stream_configure(state->common->dev_id, &state->meta_stream, - P40_DMA_DAQ_META_MAP_QSYS_BASE, META_MAP_MAX_ENTRIES, metamibs * 1024LL*1024LL); - if (rc < 0) { - goto err_meta_configure; - } - - // Continue PCIe configuration - - rc = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &(state->irq_pin)); - if (rc) { - printk(P40_WARN "unable to read PCI_INTERRUPT_PIN\n", P40_PARM); - goto err_pci_interrupt_pin; - } - printk(P40_INFO "IRQ pin = %d\n", P40_PARM, state->irq_pin); - - rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &(state->irq_line)); - if (rc) { - printk(P40_WARN "unable to read PCI_INTERRUPT_LINE\n", P40_PARM); - goto err_pci_interrupt_line; - } - printk(P40_INFO "IRQ line = %d\n", P40_PARM, state->irq_line); - -//=Interrupt configuration - - rc = pci_enable_msi(dev); //< -// A successful call allocates 1 interrupts to the device, regardless -// of how many MSIs the device supports. The device is switched from -// pin-based interrupt mode to MSI mode. The dev->irq number is changed -// to a new number which represents the message signaled interrupt; -// consequently, this function should be called before the driver calls -// request_irq(), because an MSI is delivered via a vector that is -//.different from the vector of a pin-based interrupt. - if (rc) { - //NOTE: from experience, you can try to pci_enable_msi_range to have more than one, but on all cpus I looked, YOU WILL ONLY GET ONE, MSI-X is needed to have more! - printk(P40_WARN "could not enable MSI (errno %d)\n", P40_PARM, rc); - } else { - printk(P40_INFO "enabled MSI interrupting\n", P40_PARM); - } - printk(P40_INFO "dev->irq = %d\n", P40_PARM, dev->irq); - - rc = request_irq(dev->irq, pcie40_isr, 0, P40_DRV_NAME, state); - if (rc) { - printk(P40_WARN "could not request IRQ #%d, error %d\n", P40_PARM, dev->irq, rc); - state->irq_line = -1; - goto err_request_irq; - } - state->irq_line = (int)dev->irq; //TODO: is this value being overwritten somewhere? Sometimes it looks different in pcie40_remove! - -//.For more information, please refer to https://www.kernel.org/doc/Documentation/PCI/MSI-HOWTO.txt - - pcie40_daq_set_drvdata(dev, state); - - return rc; - -err_request_irq: - if (dev->irq >= 0) { - free_irq(dev->irq, state); - } - if (dev->msi_enabled) { - pci_disable_msi(dev); - } -err_pci_interrupt_line: -err_pci_interrupt_pin: - dma_stream_destroy(state->common->dev_id, &state->meta_stream); -err_meta_configure: - dma_stream_destroy(state->common->dev_id, &state->main_stream); -err_main_configure: - printk(P40_INFO "remove /dev/pcie40_%d_%s\n", P40_PARM, state->common->dev_id, CTRL_CDEV_NAME); - device_destroy(pcie40_daq_class, MKDEV(MAJOR(state->dev_num), MINOR(state->dev_num)+CTRL_CDEV_MINOR)); -err_dev_ctrl: -err_version: - unregister_chrdev_region(state->dev_num, P40_DAQ_CDEV_COUNT); -err_alloc_chrdev_region: -err_pci_set_dma_mask: - kfree(state); -err_kzalloc: - return rc; -} - -//+`pcie40_daq_remove` -void pcie40_daq_remove(struct pci_dev *dev)//;?> -{ - struct pcie40_daq_state *state; - - printk(P40_DIAG "pci_dev = 0x%p\n", P40_PARM, dev); - state = pcie40_daq_get_drvdata(dev); - - if (!dev || !state) { - printk(P40_DIAG "remove(dev = 0x%p) dev->driver_data = 0x%p\n", P40_PARM, dev, state); - return; - } - - printk(P40_DIAG "state = 0x%p\n", P40_PARM, state); - if (state->common->pci_dev != dev) { - printk(P40_DIAG "dev->dev.driver_data->pci_dev (0x%08lx) != dev (0x%08lx)\n", P40_PARM, - (unsigned long)state->common->pci_dev, (unsigned long)dev); - } - - printk(P40_DIAG "disabling main DMA stream\n", P40_PARM); - iowrite32(0, state->common->bar1_regs - + P40_DMA_DAQ_MAIN_STREAM_QSYS_BASE + P40_DMA_DAQ_STREAM_OFF_ENABLE); - - printk(P40_DIAG "disabling meta DMA stream\n", P40_PARM); - iowrite32(0, state->common->bar1_regs - + P40_DMA_DAQ_META_STREAM_QSYS_BASE + P40_DMA_DAQ_STREAM_OFF_ENABLE); - - if (dev->irq >= 0) { - printk(P40_INFO "freeing IRQ %d\n", P40_PARM, dev->irq); - free_irq(dev->irq, state); - } - - if (dev->msi_enabled) { - printk(P40_INFO "disabling MSIs\n", P40_PARM); - pci_disable_msi(dev); - } - - printk(P40_INFO "processed %d MSIs in main stream\n", - P40_PARM, state->main_stream.msi_count); - printk(P40_INFO "processed %d MSIs in meta stream\n", - P40_PARM, state->meta_stream.msi_count); - - dma_stream_destroy(state->common->dev_id, &state->meta_stream); - dma_stream_destroy(state->common->dev_id, &state->main_stream); - - printk(P40_INFO "remove /dev/pcie40_%d_%s\n", P40_PARM, state->common->dev_id, CTRL_CDEV_NAME); - device_destroy(pcie40_daq_class, MKDEV(MAJOR(state->dev_num), MINOR(state->dev_num)+CTRL_CDEV_MINOR)); - - unregister_chrdev_region(state->dev_num, P40_DAQ_CDEV_COUNT); - - kfree(state); -} -