/* ***************************************************************** * (C) Copyright 2007 Benjamin Krill * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA * *****************************************************************/ #include #include #include #include #include #include #include "fpgafs.h" #define VENDOR_ID_ALTERA 0x1172 #define DEVICE_ID_ALTERA 0x0100 static void *vaddr = 0; static unsigned long memstart = 0, memlen = 0; static int fpgafs_send_data_rag(struct fpga_context *ctx, const char __user *buf, int len) { int i; u8 __user *usr; unsigned char dat[2]; if (len < 2) return -EINVAL; if (!access_ok(VERIFY_READ, buf, len)) return -EFAULT; for(i=0; i < len; i+=2) { usr = (u8*)&buf[i]; if (__get_user(dat[0], usr)) return -EFAULT; usr = (u8*)&buf[i+1]; if (__get_user(dat[1], usr)) return -EFAULT; writew((dat[1] << 8)|dat[0], vaddr); } return i; } static int fpgafs_recv_data_rag(struct fpga_context *ctx, unsigned char *buf, int len) { int i; unsigned short d; unsigned char b[2]; if ((len < 2) || ((len % 2) != 0)) return -EINVAL; for(i=0; i < len; i+=2) { d=readw((void *)((unsigned long)vaddr | 0x20)); b[i] = d & 0xff; b[i+1] = d >> 8; if (copy_to_user(b, ctx->load_buf, 2)) return -EFAULT; } return i; } int fpgafs_device_probe_rag(struct pci_dev *dev, const struct pci_device_id *id) { int ret; ret = pci_enable_device(dev); if (ret < 0) { printk(KERN_WARNING "FPGAFS_RAG: unable to initialize PCI device\n"); return ret; } ret = pci_request_regions(dev, "FPGAFS_RAG"); if (ret < 0) { printk(KERN_WARNING "FPGAFS_RAG: unable to reserve PCI resources\n"); pci_disable_device(dev); return ret; } memstart = pci_resource_start(dev, 0); /* 0 for BAR0 */ memlen = pci_resource_len(dev, 0); printk(KERN_WARNING "FPGAFS_RAG: memstart=0x%lx memlen=%li\n", memstart, memlen); vaddr = ioremap(memstart, memlen); printk(KERN_INFO "FPGAFS_RAG: device_probe successful\n"); return ret; } void fpgafs_device_remove_rag(struct pci_dev *dev) { iounmap(vaddr); pci_release_regions(dev); pci_disable_device(dev); printk(KERN_INFO "FPGAFS_RAG: device removed\n"); } static struct pci_device_id pci_device_id_fpgafs_rag[] = { {VENDOR_ID_ALTERA, DEVICE_ID_ALTERA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {} /* EOL */ }; struct pci_driver pci_driver_fpgafs_rag = { name: "FPGAFS_RAG", id_table: pci_device_id_fpgafs_rag, probe: fpgafs_device_probe_rag, remove: fpgafs_device_remove_rag }; static int fpgafs_init_rag(void) { printk(KERN_INFO "FPGFS_RAG: PCI init\n"); return pci_register_driver(&pci_driver_fpgafs_rag); } static int fpgafs_exit_rag(void) { printk(KERN_INFO "FPGFS_RAG: PCI fini\n"); pci_unregister_driver(&pci_driver_fpgafs_rag); return 0; } static struct fpgafs_lldrv fpgafs_lldrv_rag = { .name = "rag", .init = &fpgafs_init_rag, .exit = &fpgafs_exit_rag, .send = &fpgafs_send_data_rag, .recv = &fpgafs_recv_data_rag, .read_load = NULL, .write_load = NULL, }; /* init exit functions ... */ int __init fpgafs_lldrv_rag_init(void) { return fpgafs_register_lldrv(&fpgafs_lldrv_rag); } void __exit fpgafs_lldrv_rag_exit(void) { fpgafs_unregister_lldrv(&fpgafs_lldrv_rag); } module_init(fpgafs_lldrv_rag_init); module_exit(fpgafs_lldrv_rag_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Benjamin Krill ");