patch-2.4.6 linux/drivers/isdn/tpam/tpam_memory.c
Next file: linux/drivers/isdn/tpam/tpam_nco.c
Previous file: linux/drivers/isdn/tpam/tpam_main.c
Back to the patch index
Back to the overall index
- Lines: 259
- Date:
Mon Jul 2 14:07:55 2001
- Orig file:
v2.4.5/linux/drivers/isdn/tpam/tpam_memory.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.4.5/linux/drivers/isdn/tpam/tpam_memory.c linux/drivers/isdn/tpam/tpam_memory.c
@@ -0,0 +1,258 @@
+/* $Id: tpam_memory.c,v 1.1.2.1 2001/06/05 19:45:37 kai Exp $
+ *
+ * Turbo PAM ISDN driver for Linux. (Kernel Driver - Board Memory Access)
+ *
+ * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
+ *
+ * For all support questions please contact: <support@auvertech.fr>
+ *
+ * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include "tpam.h"
+
+/*
+ * Write a DWORD into the board memory.
+ *
+ * card: the board
+ * addr: the address (in the board memory)
+ * val: the value to put into the memory.
+ */
+void copy_to_pam_dword(tpam_card *card, const void *addr, u32 val) {
+
+ /* set the page register */
+ writel(((unsigned long)addr) | TPAM_PAGE_SIZE,
+ card->bar0 + TPAM_PAGE_REGISTER);
+
+ /* write the value */
+ writel(val, card->bar0 + (((u32)addr) & TPAM_PAGE_SIZE));
+}
+
+/*
+ * Write n bytes into the board memory. The count of bytes will be rounded
+ * up to a multiple of 4.
+ *
+ * card: the board
+ * to: the destination address (in the board memory)
+ * from: the source address (in the kernel memory)
+ * n: number of bytes
+ */
+void copy_to_pam(tpam_card *card, void *to, const void *from, u32 n) {
+ u32 page, offset, count;
+
+ /* need to write in dword ! */
+ while (n & 3) n++;
+
+ while (n) {
+ page = ((u32)to) | TPAM_PAGE_SIZE;
+ offset = ((u32)to) & TPAM_PAGE_SIZE;
+ count = n < TPAM_PAGE_SIZE - offset
+ ? n
+ : TPAM_PAGE_SIZE - offset;
+
+ /* set the page register */
+ writel(page, card->bar0 + TPAM_PAGE_REGISTER);
+
+ /* copy the data */
+ memcpy_toio((void *)(card->bar0 + offset), from, count);
+
+ from += count;
+ to += count;
+ n -= count;
+ }
+}
+
+/*
+ * Read a DWORD from the board memory.
+ *
+ * card: the board
+ * addr: the address (in the board memory)
+ *
+ * Return: the value read into the memory.
+ */
+u32 copy_from_pam_dword(tpam_card *card, const void *addr) {
+
+ /* set the page register */
+ writel(((u32)addr) | TPAM_PAGE_SIZE,
+ card->bar0 + TPAM_PAGE_REGISTER);
+
+ /* read the data */
+ return readl(card->bar0 + (((u32)addr) & TPAM_PAGE_SIZE));
+}
+
+/*
+ * Read n bytes from the board memory.
+ *
+ * card: the board
+ * to: the destination address (in the kernel memory)
+ * from: the source address (in the board memory)
+ * n: number of bytes
+ */
+void copy_from_pam(tpam_card *card, void *to, const void *from, u32 n) {
+ u32 page, offset, count;
+
+ while (n) {
+ page = ((u32)from) | TPAM_PAGE_SIZE;
+ offset = ((u32)from) & TPAM_PAGE_SIZE;
+ count = n < TPAM_PAGE_SIZE - offset
+ ? n
+ : TPAM_PAGE_SIZE - offset;
+
+ /* set the page register */
+ writel(page, card->bar0 + TPAM_PAGE_REGISTER);
+
+ /* read the data */
+ memcpy_fromio(to, (void *)(card->bar0 + offset), count);
+
+ from += count;
+ to += count;
+ n -= count;
+ }
+}
+
+/*
+ * Read n bytes from the board memory and writes them into the user memory.
+ *
+ * card: the board
+ * to: the destination address (in the userspace memory)
+ * from: the source address (in the board memory)
+ * n: number of bytes
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int copy_from_pam_to_user(tpam_card *card, void *to, const void *from, u32 n) {
+ void *page;
+ u32 count;
+
+ /* allocate a free page for the data transfer */
+ if (!(page = (void *)__get_free_page(GFP_KERNEL))) {
+ printk(KERN_ERR "TurboPAM(copy_from_pam_to_user): "
+ "get_free_page failed\n");
+ return -ENOMEM;
+ }
+
+ while (n) {
+ count = n < PAGE_SIZE ? n : PAGE_SIZE;
+
+ /* copy data from the board into the kernel memory */
+ spin_lock_irq(&card->lock);
+ copy_from_pam(card, page, from, count);
+ spin_unlock_irq(&card->lock);
+
+ /* copy it from the kernel memory into the user memory */
+ if (copy_to_user(to, page, count)) {
+
+ /* this can fail... */
+ free_page((u32)page);
+ return -EFAULT;
+ }
+ from += count;
+ to += count;
+ n -= count;
+ }
+
+ /* release allocated memory */
+ free_page((u32)page);
+ return 0;
+}
+
+/*
+ * Read n bytes from the user memory and writes them into the board memory.
+ *
+ * card: the board
+ * to: the destination address (in the board memory)
+ * from: the source address (in the userspace memory)
+ * n: number of bytes
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int copy_from_user_to_pam(tpam_card *card, void *to, const void *from, u32 n) {
+ void *page;
+ u32 count;
+
+ /* allocate a free page for the data transfer */
+ if (!(page = (void *)__get_free_page(GFP_KERNEL))) {
+ printk(KERN_ERR "TurboPAM(copy_from_user_to_pam): "
+ "get_free_page failed\n");
+ return -ENOMEM;
+ }
+
+ while (n) {
+ count = n < PAGE_SIZE ? n : PAGE_SIZE;
+
+ /* copy data from the user memory into the kernel memory */
+ if (copy_from_user(page, from, count)) {
+ /* this can fail... */
+ free_page((u32)page);
+ return -EFAULT;
+ }
+
+ /* copy it from the kernel memory into the board memory */
+ spin_lock_irq(&card->lock);
+ copy_to_pam(card, to, page, count);
+ spin_unlock_irq(&card->lock);
+
+ from += count;
+ to += count;
+ n -= count;
+ }
+
+ /* release allocated memory */
+ free_page((u32)page);
+ return 0;
+}
+
+/*
+ * Verify if we have the permission to read or writes len bytes at the
+ * address address from/to the board memory.
+ *
+ * address: the start address (in the board memory)
+ * len: number of bytes
+ *
+ * Return: 0 if OK, <0 if error.
+ */
+int tpam_verify_area(u32 address, u32 len) {
+
+ if (address < TPAM_RESERVEDAREA1_START)
+ return (address + len <= TPAM_RESERVEDAREA1_START) ? 0 : -1;
+
+ if (address <= TPAM_RESERVEDAREA1_END)
+ return -1;
+
+ if (address < TPAM_RESERVEDAREA2_START)
+ return (address + len <= TPAM_RESERVEDAREA2_START) ? 0 : -1;
+
+ if (address <= TPAM_RESERVEDAREA2_END)
+ return -1;
+
+ if (address < TPAM_RESERVEDAREA3_START)
+ return (address + len <= TPAM_RESERVEDAREA3_START) ? 0 : -1;
+
+ if (address <= TPAM_RESERVEDAREA3_END)
+ return -1;
+
+ if (address < TPAM_RESERVEDAREA4_START)
+ return (address + len <= TPAM_RESERVEDAREA4_START) ? 0 : -1;
+
+ if (address <= TPAM_RESERVEDAREA4_END)
+ return -1;
+
+ return 0;
+}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)