p@2636: /** p@2636: Network Driver for Beckhoff CCAT communication controller p@2636: Copyright (C) 2015 Beckhoff Automation GmbH & Co. KG p@2636: Author: Patrick Bruenn p@2636: p@2636: This program is free software; you can redistribute it and/or modify p@2636: it under the terms of the GNU General Public License as published by p@2636: the Free Software Foundation; either version 2 of the License, or p@2636: (at your option) any later version. p@2636: p@2636: This program is distributed in the hope that it will be useful, p@2636: but WITHOUT ANY WARRANTY; without even the implied warranty of p@2636: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the p@2636: GNU General Public License for more details. p@2636: p@2636: You should have received a copy of the GNU General Public License along p@2636: with this program; if not, write to the Free Software Foundation, Inc., p@2636: 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. p@2636: */ p@2636: p@2636: #include "module.h" p@2636: #include p@2636: #include p@2636: #include p@2636: #include p@2636: p@2636: #define CCAT_SRAM_DEVICES_MAX 4 p@2636: p@2636: static ssize_t __sram_read(struct cdev_buffer *buffer, char __user * buf, p@2636: size_t len, loff_t * off) p@2636: { p@2636: memcpy_fromio(buffer->data, buffer->ccdev->ioaddr + *off, len); p@2636: if (copy_to_user(buf, buffer->data, len)) p@2636: return -EFAULT; p@2636: p@2636: *off += len; p@2636: return len; p@2636: } p@2636: p@2636: static ssize_t ccat_sram_read(struct file *const f, char __user * buf, p@2636: size_t len, loff_t * off) p@2636: { p@2636: struct cdev_buffer *buffer = f->private_data; p@2636: const size_t iosize = buffer->ccdev->iosize; p@2636: p@2636: if (*off >= iosize) { p@2636: return 0; p@2636: } p@2636: p@2636: len = min(len, (size_t) (iosize - *off)); p@2636: p@2636: return __sram_read(buffer, buf, len, off); p@2636: } p@2636: p@2636: static ssize_t ccat_sram_write(struct file *const f, const char __user * buf, p@2636: size_t len, loff_t * off) p@2636: { p@2636: struct cdev_buffer *const buffer = f->private_data; p@2636: p@2636: if (*off + len > buffer->ccdev->iosize) { p@2636: return 0; p@2636: } p@2636: p@2636: if (copy_from_user(buffer->data, buf, len)) { p@2636: return -EFAULT; p@2636: } p@2636: p@2636: memcpy_toio(buffer->ccdev->ioaddr + *off, buffer->data, len); p@2636: p@2636: *off += len; p@2636: return len; p@2636: } p@2636: p@2636: static struct ccat_cdev dev_table[CCAT_SRAM_DEVICES_MAX]; p@2636: static struct ccat_class cdev_class = { p@2636: .instances = {0}, p@2636: .count = CCAT_SRAM_DEVICES_MAX, p@2636: .devices = dev_table, p@2636: .name = "ccat_sram", p@2636: .fops = { p@2636: .owner = THIS_MODULE, p@2636: .open = ccat_cdev_open, p@2636: .release = ccat_cdev_release, p@2636: .read = ccat_sram_read, p@2636: .write = ccat_sram_write, p@2636: }, p@2636: }; p@2636: p@2636: static int ccat_sram_probe(struct ccat_function *func) p@2636: { p@2636: static const u8 NO_SRAM_CONNECTED = 0; p@2636: const u8 type = func->info.sram_width & 0x3; p@2636: const size_t iosize = (1 << func->info.sram_size); p@2636: p@2636: pr_info("%s: 0x%04x rev: 0x%04x\n", __FUNCTION__, func->info.type, p@2636: func->info.rev); p@2636: if (type == NO_SRAM_CONNECTED) { p@2636: return -ENODEV; p@2636: } p@2636: return ccat_cdev_probe(func, &cdev_class, iosize); p@2636: } p@2636: p@2636: struct ccat_driver sram_driver = { p@2636: .type = CCATINFO_SRAM, p@2636: .probe = ccat_sram_probe, p@2636: .remove = ccat_cdev_remove, p@2636: .cdev_class = &cdev_class, p@2636: };