From 8340edb2d8a24ee88bad3e230b77cbfedf81cff8 Mon Sep 17 00:00:00 2001 From: bnewbold Date: Tue, 21 Aug 2012 21:36:42 -0400 Subject: commit all files and directions See README and LICENSE. --- libertas_uap/uap_proc.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 libertas_uap/uap_proc.c (limited to 'libertas_uap/uap_proc.c') diff --git a/libertas_uap/uap_proc.c b/libertas_uap/uap_proc.c new file mode 100644 index 0000000..a28a9a6 --- /dev/null +++ b/libertas_uap/uap_proc.c @@ -0,0 +1,296 @@ +/** @file uap_proc.c + * @brief This file contains functions for proc file. + * + * Copyright (C) 2008-2009, Marvell International Ltd. + * + * This software file (the "File") is distributed by Marvell International + * Ltd. under the terms of the GNU General Public License Version 2, June 1991 + * (the "License"). You may use, redistribute and/or modify this File in + * accordance with the terms and conditions of the License, a copy of which + * is available along with the File in the gpl.txt file or by writing to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. + * + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about + * this warranty disclaimer. + * + */ +#ifdef CONFIG_PROC_FS +#include "uap_headers.h" + +/** /proc directory root */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) +#define PROC_DIR NULL +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#define PROC_DIR &proc_root +#else +#define PROC_DIR proc_net +#endif + +/******************************************************** + Local Variables +********************************************************/ + +/******************************************************** + Global Variables +********************************************************/ + +/******************************************************** + Local Functions +********************************************************/ + +/** + * @brief proc read function + * + * @param page pointer to buffer + * @param start read data starting position + * @param offset offset + * @param count counter + * @param eof end of file flag + * @param data data to output + * @return number of output data + */ +static int +uap_proc_read(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + int i; + char *p = page; + struct net_device *netdev = data; + struct netdev_hw_addr *ha; + char fmt[64]; + uap_private *priv = (uap_private *) netdev_priv(netdev); + + if (offset != 0) { + *eof = 1; + goto exit; + } + + strcpy(fmt, DRIVER_VERSION); + + p += sprintf(p, "driver_name = " "\"uap\"\n"); + p += sprintf(p, "driver_version = %s-(FP%s)", fmt, FPNUM); + p += sprintf(p, "\nInterfaceName=\"%s\"\n", netdev->name); + p += sprintf(p, "State=\"%s\"\n", + ((priv->MediaConnected == + FALSE) ? "Disconnected" : "Connected")); + p += sprintf(p, "MACAddress=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", + netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], + netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); + i = 0; + netdev_for_each_mc_addr(ha, netdev) { + ++i; + } + p += sprintf(p, "MCCount=\"%d\"\n", i); + + /* + * Put out the multicast list + */ + i = 0; + netdev_for_each_mc_addr(ha, netdev) { + p += sprintf(p, + "MCAddr[%d]=\"%02x:%02x:%02x:%02x:%02x:%02x\"\n", + i++, + ha->addr[0], ha->addr[1], + ha->addr[2], ha->addr[3], + ha->addr[4], ha->addr[5]); + } + + p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); + p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); + p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); + p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); + p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); + p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); + p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); + p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); + p += sprintf(p, "num_tx_timeout = %u\n", priv->num_tx_timeout); + p += sprintf(p, "carrier %s\n", + ((netif_carrier_ok(priv->uap_dev.netdev)) ? "on" : "off")); + p += sprintf(p, "tx queue %s\n", + ((netif_queue_stopped(priv->uap_dev.netdev)) ? "stopped" : + "started")); + + exit: + return (p - page); +} + +/** + * @brief hwstatus proc write function + * + * @param f file pointer + * @param buf pointer to data buffer + * @param cnt data number to write + * @param data data to write + * @return number of data + */ +static int +uap_hwstatus_write(struct file *f, const char *buf, unsigned long cnt, + void *data) +{ + struct net_device *netdev = data; + uap_private *priv = (uap_private *) netdev_priv(netdev); + char databuf[10]; + int hwstatus; + MODULE_GET; + if (cnt > 10) { + MODULE_PUT; + return cnt; + } + if (copy_from_user(databuf, buf, cnt)) { + MODULE_PUT; + return 0; + } + hwstatus = string_to_number(databuf); + switch (hwstatus) { + case HWReset: + PRINTM(MSG, "reset hw\n"); + uap_soft_reset(priv); + priv->adapter->HardwareStatus = HWReset; + break; + default: + break; + } + MODULE_PUT; + return cnt; +} + +/** + * @brief hwstatus proc read function + * + * @param page pointer to buffer + * @param s read data starting position + * @param off offset + * @param cnt counter + * @param eof end of file flag + * @param data data to output + * @return number of output data + */ +static int +uap_hwstatus_read(char *page, char **s, off_t off, int cnt, int *eof, + void *data) +{ + char *p = page; + struct net_device *netdev = data; + uap_private *priv = (uap_private *) netdev_priv(netdev); + MODULE_GET; + p += sprintf(p, "%d\n", priv->adapter->HardwareStatus); + MODULE_PUT; + return p - page; +} + +/******************************************************** + Global Functions +********************************************************/ +/** + * @brief create uap proc file + * + * @param priv pointer uap_private + * @param dev pointer net_device + * @return N/A + */ +void +uap_proc_entry(uap_private * priv, struct net_device *dev) +{ + struct proc_dir_entry *r = PROC_DIR; + + PRINTM(INFO, "Creating Proc Interface\n"); + /* Check if uap directory already exists */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) + for (r = r->subdir; r; r = r->next) { + if (r->namelen && !strcmp("uap", r->name)) { + /* Directory exists */ + PRINTM(WARN, "proc directory already exists!\n"); + priv->proc_uap = r; + break; + } + } +#endif + if (!priv->proc_uap) { + priv->proc_uap = proc_mkdir("uap", PROC_DIR); + if (!priv->proc_uap) + return; + else + atomic_set(&priv->proc_uap->count, 1); + } else { + atomic_inc(&priv->proc_uap->count); + } + priv->proc_entry = proc_mkdir(dev->name, priv->proc_uap); + + if (priv->proc_entry) { + r = create_proc_read_entry("info", 0, priv->proc_entry, uap_proc_read, + dev); + r = create_proc_entry("hwstatus", 0644, priv->proc_entry); + if (r) { + r->data = dev; + r->read_proc = uap_hwstatus_read; + r->write_proc = uap_hwstatus_write; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) + r->owner = THIS_MODULE; +#endif + } else + PRINTM(MSG, "Fail to create proc hwstatus\n"); + } +} + +/** + * @brief remove proc file + * + * @param priv pointer uap_private + * @return N/A + */ +void +uap_proc_remove(uap_private * priv) +{ + if (priv->proc_uap) { + if (priv->proc_entry) { + remove_proc_entry("info", priv->proc_entry); + remove_proc_entry("hwstatus", priv->proc_entry); + } + remove_proc_entry(priv->uap_dev.netdev->name, priv->proc_uap); + atomic_dec(&priv->proc_uap->count); + if (atomic_read(&(priv->proc_uap->count)) == 0) + remove_proc_entry("uap", PROC_DIR); + } +} + +/** + * @brief convert string to number + * + * @param s pointer to numbered string + * @return converted number from string s + */ +int +string_to_number(char *s) +{ + int r = 0; + int base = 0; + int pn = 1; + + if (strncmp(s, "-", 1) == 0) { + pn = -1; + s++; + } + if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0)) { + base = 16; + s += 2; + } else + base = 10; + + for (s = s; *s != 0; s++) { + if ((*s >= '0') && (*s <= '9')) + r = (r * base) + (*s - '0'); + else if ((*s >= 'A') && (*s <= 'F')) + r = (r * base) + (*s - 'A' + 10); + else if ((*s >= 'a') && (*s <= 'f')) + r = (r * base) + (*s - 'a' + 10); + else + break; + } + + return (r * pn); +} + +#endif -- cgit v1.2.3