| /* Copyright (C) 2004-2005 SBE, Inc. |
| * |
| * 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. |
| */ |
| |
| #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| |
| #include <linux/types.h> |
| #include <linux/module.h> |
| #include <linux/errno.h> |
| #include <linux/kernel.h> |
| #include <linux/init.h> |
| #include <linux/proc_fs.h> |
| #include <linux/seq_file.h> |
| #include <linux/sched.h> |
| #include <asm/uaccess.h> |
| #include "pmcc4_sysdep.h" |
| #include "sbecom_inline_linux.h" |
| #include "pmcc4_private.h" |
| #include "sbeproc.h" |
| |
| extern void sbecom_get_brdinfo(ci_t *, struct sbe_brd_info *, u_int8_t *); |
| extern struct s_hdw_info hdw_info[MAX_BOARDS]; |
| |
| void sbecom_proc_brd_cleanup(ci_t *ci) |
| { |
| if (ci->dir_dev) { |
| char dir[7 + SBE_IFACETMPL_SIZE + 1]; |
| snprintf(dir, sizeof(dir), "driver/%s", ci->devname); |
| remove_proc_entry("info", ci->dir_dev); |
| remove_proc_entry(dir, NULL); |
| ci->dir_dev = NULL; |
| } |
| } |
| |
| static void sbecom_proc_get_brdinfo(ci_t *ci, struct sbe_brd_info *bip) |
| { |
| hdw_info_t *hi = &hdw_info[ci->brdno]; |
| u_int8_t *bsn = 0; |
| |
| switch (hi->promfmt) |
| { |
| case PROM_FORMAT_TYPE1: |
| bsn = (u_int8_t *) hi->mfg_info.pft1.Serial; |
| break; |
| case PROM_FORMAT_TYPE2: |
| bsn = (u_int8_t *) hi->mfg_info.pft2.Serial; |
| break; |
| } |
| |
| sbecom_get_brdinfo (ci, bip, bsn); |
| |
| pr_devel(">> sbecom_get_brdinfo: returned, first_if %p <%s> last_if %p <%s>\n", |
| bip->first_iname, bip->first_iname, |
| bip->last_iname, bip->last_iname); |
| } |
| |
| /* |
| * Describe the driver state through /proc |
| */ |
| static int sbecom_proc_get_sbe_info(struct seq_file *m, void *v) |
| { |
| ci_t *ci = m->private; |
| char *spd; |
| struct sbe_brd_info *bip; |
| |
| if (!(bip = OS_kmalloc(sizeof(struct sbe_brd_info)))) |
| return -ENOMEM; |
| |
| pr_devel(">> sbecom_proc_get_sbe_info: entered\n"); |
| |
| sbecom_proc_get_brdinfo(ci, bip); |
| |
| seq_puts(m, "Board Type: "); |
| switch (bip->brd_id) { |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T3): |
| seq_puts(m, "wanPMC-C1T3"); |
| break; |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_E1): |
| seq_puts(m, "wanPTMC-256T3 <E1>"); |
| break; |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_256T3_T1): |
| seq_puts(m, "wanPTMC-256T3 <T1>"); |
| break; |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPTMC_C24TE1): |
| seq_puts(m, "wanPTMC-C24TE1"); |
| break; |
| |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1): |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C4T1E1_L): |
| seq_puts(m, "wanPMC-C4T1E1"); |
| break; |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1): |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C2T1E1_L): |
| seq_puts(m, "wanPMC-C2T1E1"); |
| break; |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1): |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPMC_C1T1E1_L): |
| seq_puts(m, "wanPMC-C1T1E1"); |
| break; |
| |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C4T1E1): |
| seq_puts(m, "wanPCI-C4T1E1"); |
| break; |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C2T1E1): |
| seq_puts(m, "wanPCI-C2T1E1"); |
| break; |
| case SBE_BOARD_ID(PCI_VENDOR_ID_SBE, PCI_DEVICE_ID_WANPCI_C1T1E1): |
| seq_puts(m, "wanPCI-C1T1E1"); |
| break; |
| |
| default: |
| seq_puts(m, "unknown"); |
| break; |
| } |
| |
| seq_printf(m, " [%08X]\n", bip->brd_id); |
| |
| seq_printf(m, "Board Number: %d\n", bip->brdno); |
| seq_printf(m, "Hardware ID: 0x%02X\n", ci->hdw_bid); |
| seq_printf(m, "Board SN: %06X\n", bip->brd_sn); |
| seq_printf(m, "Board MAC: %pMF\n", bip->brd_mac_addr); |
| seq_printf(m, "Ports: %d\n", ci->max_port); |
| seq_printf(m, "Channels: %d\n", bip->brd_chan_cnt); |
| #if 1 |
| seq_printf(m, "Interface: %s -> %s\n", |
| bip->first_iname, bip->last_iname); |
| #else |
| seq_printf(m, "Interface: <not available> 1st %p lst %p\n", |
| bip->first_iname, bip->last_iname); |
| #endif |
| |
| switch (bip->brd_pci_speed) { |
| case BINFO_PCI_SPEED_33: |
| spd = "33Mhz"; |
| break; |
| case BINFO_PCI_SPEED_66: |
| spd = "66Mhz"; |
| break; |
| default: |
| spd = "<not available>"; |
| break; |
| } |
| seq_printf(m, "PCI Bus Speed: %s\n", spd); |
| seq_printf(m, "Release: %s\n", ci->release); |
| |
| #ifdef SBE_PMCC4_ENABLE |
| { |
| extern int cxt1e1_max_mru; |
| #if 0 |
| extern int max_chans_used; |
| extern int cxt1e1_max_mtu; |
| #endif |
| extern int max_rxdesc_used, max_txdesc_used; |
| |
| seq_printf(m, "\ncxt1e1_max_mru: %d\n", cxt1e1_max_mru); |
| #if 0 |
| seq_printf(m, "\nmax_chans_used: %d\n", max_chans_used); |
| seq_printf(m, "cxt1e1_max_mtu: %d\n", cxt1e1_max_mtu); |
| #endif |
| seq_printf(m, "max_rxdesc_used: %d\n", max_rxdesc_used); |
| seq_printf(m, "max_txdesc_used: %d\n", max_txdesc_used); |
| } |
| #endif |
| |
| kfree(bip); |
| |
| pr_devel(">> proc_fs: finished\n"); |
| return 0; |
| } |
| |
| /* |
| * seq_file wrappers for procfile show routines. |
| */ |
| static int sbecom_proc_open(struct inode *inode, struct file *file) |
| { |
| return single_open(file, sbecom_proc_get_sbe_info, PDE_DATA(inode)); |
| } |
| |
| static const struct file_operations sbecom_proc_fops = { |
| .open = sbecom_proc_open, |
| .read = seq_read, |
| .llseek = seq_lseek, |
| .release = single_release, |
| }; |
| |
| /* |
| * Initialize the /proc subsystem for the specific SBE driver |
| */ |
| int __init sbecom_proc_brd_init(ci_t *ci) |
| { |
| char dir[7 + SBE_IFACETMPL_SIZE + 1]; |
| |
| snprintf(dir, sizeof(dir), "driver/%s", ci->devname); |
| ci->dir_dev = proc_mkdir(dir, NULL); |
| if (!ci->dir_dev) { |
| pr_err("Unable to create directory /proc/driver/%s\n", ci->devname); |
| goto fail; |
| } |
| |
| if (!proc_create_data("info", S_IFREG | S_IRUGO, ci->dir_dev, |
| &sbecom_proc_fops, ci)) { |
| pr_err("Unable to create entry /proc/driver/%s/info\n", ci->devname); |
| goto fail; |
| } |
| return 0; |
| |
| fail: |
| sbecom_proc_brd_cleanup(ci); |
| return 1; |
| } |