blob: 9361dd8ce1255b6d7a4afa356bd477b219774296 [file] [log] [blame]
/* 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;
}