📄 adm_procfs.c
字号:
#include <linux/kernel.h>#include <linux/module.h>#include <linux/proc_fs.h>#include <linux/sysctl.h>#include <linux/init.h>#include "adm6996.h"#define BIT(x) (1<<(x))#ifdef CONFIG_PROC_FSstatic inline char* yesno (unsigned int v){ return (v ? "yes" : "no");}static int adm6996_procfs_read (char *page, char **start, off_t offset, int count, int *eof, void *data){ int len, i; adm_info_t* info = (adm_info_t*) data; struct adm_port_stat aps[6]; struct adm_gen_config conf; if (offset > 0) return 0; len = sprintf (page, "ADM6996L version %s\n", ADM6996_VERSION); /* EEPROM config */ len += sprintf (page+len, "--- Stats ---\n"); adm_get_ports_stats (6, aps); for (i=0; i<6; ++i) { len += sprintf (page+len, "Port %d: ", i); len += sprintf (page+len, " %s", aps[i].link? "UP":"DOWN"); len += sprintf (page+len, " %s", aps[i].speed? "100M": "10M"); len += sprintf (page+len, " %s",aps[i].duplex? "FD":"HD"); if (aps[i].flow) len += sprintf (page+len, aps[i].duplex ? " 802.3X" : " BP"); if (aps[i].cable_broken) len += sprintf (page+len, " NOCABLE"); len += sprintf (page+len, "\n"); len += sprintf (page+len, "RX packets:%u%s bytes:%u%s ", aps[i].rx_packets, aps[i].rxp_overflow ? " (overflow)":"", aps[i].rx_bytes, aps[i].rxb_overflow ? " (overflow)":""); len += sprintf (page+len, "TX packets:%u%s bytes:%u%s\n", aps[i].tx_packets, aps[i].txp_overflow ? " (overflow)":"", aps[i].tx_bytes, aps[i].txb_overflow ? " (overflow)":""); len += sprintf (page+len, "errors:%u%s collisions:%u%s " "cable length:%u\n", aps[i].errors, aps[i].err_overflow ? " (overflow)":"", aps[i].collisions, aps[i].col_overflow ? " (overflow)":"", aps[i].cable_len); len += sprintf (page+len, "\n"); } return len;}static int adm6996_procfs_write (struct file *file, const char *buffer, unsigned long count, void *data){ int retval = -EINVAL; return retval;}int __init adm6996_register_procfs (adm_info_t *info){ static struct proc_dir_entry *adm6996_file; char filename[9]; /* create using convenience function */ sprintf(filename, "adm6996_%d", 0/*info->nr*/); adm6996_file = create_proc_entry (filename, S_IFREG | S_IRUGO | S_IWUSR, proc_root_driver); if (adm6996_file == NULL) return -ENOMEM; adm6996_file->data = info; adm6996_file->read_proc = adm6996_procfs_read; adm6996_file->write_proc = adm6996_procfs_write; adm6996_file->size = 0; adm6996_file->owner = THIS_MODULE; /* single card backward compatibility */ if (0/*info->nr*/ == 0) proc_symlink ("adm6996", proc_root_driver, "adm6996_0"); // PRINTK_INFO ("procfs file registered for adm6996_%d\n", 0/*info->nr*/); return 0;}void __exit adm6996_unregister_procfs (adm_info_t* info){ char filename[9]; sprintf(filename, "adm6996_%d", 0/*info->nr*/); remove_proc_entry (filename, proc_root_driver); /* single card backward compatibility */ if (0/*info->nr*/ == 0) remove_proc_entry ("adm6996", proc_root_driver); // PRINTK_INFO ("procfs file unregistered for adm6996_%d\n", 0/*info->nr*/);}// static struct adm_gen_config cfg;static int drop_on_collisions, replace_vid_pvid, ipg_bits, trunk, far_end_fault, xcrc, aging, polarity_error, reg_10_bit_3, reg_2c_bit_11;static int storming[2];static int drop[4];static int mac_clone_11, vlan_mode;static int mac_clone_30, mii_speed, speed_led, port_led;static int tag_shift, fwd_management_mac1, fwd_management_mac2, fwd_management_mac3, fwd_management_mac4, smart_squelch;static int vlan_groups[16][6], vlan_prio[8], tos_prio[8];static struct _port_cfg { int flow, autoneg, speed, duplex, tagging, enabled, use_tos, port_prio, pvid, fx, crossover, mac_lock, bandwidth, count_recv, vlan, use_prio;} *port_cfg;static int adm_sysctl_handler (ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp){ int ret, i, port, ctl_name; uint16 val; uint32 val32; static const int port_map[] = {0x01, 0x03, 0x05, 0x07, 0x08, 0x09}; ret = proc_dointvec(table, write, filp, buffer, lenp); if (ret || ! write) return ret; port = table->ctl_name / 100 - 1; ctl_name = table->ctl_name; if (ctl_name >= 100) ctl_name = ctl_name%100+100; switch (ctl_name) { default: printk ("ADM6996: unknown sysctl request: %s [%d]\n", table->procname, table->ctl_name); return -1; case 1: /* Discard mode */ for (i=0; i<4; ++i) drop[i] &= 3; case 9: /* storming */ storming[1] &= 3; case 2: /* CRC */ case 3: /* Aging */ case 25: /* reg 10, bit 3 */ val = (storming[1] & 3) | ((storming[0] ? 1 : 0) << 2) | ((reg_10_bit_3 ? 1 : 0) << 3) | ((xcrc ? 0 : 1) << 4) | ((aging ? 0 : 1) << 7) | (drop[0] << 8) | (drop[1] << 10) | (drop[2] << 12) | (drop[3] << 14) ; adm_wreg (einfo, 0x10, val); break; case 7: /* Replaced packet VID 0,1 with PVID */ val = ((replace_vid_pvid ? 1 : 0) << 9); adm_wreg (einfo, 0x0a, val); break; case 5: /* Trunking */ case 6: /* IPG bits */ case 4: /* Far end fault detection */ val = ((ipg_bits==92 ? 1 : 0) << 6) | ((trunk ? 1 : 0) << 7) | ((far_end_fault ? 0 : 1) << 15); adm_wreg (einfo, 0x0b, val); break; case 10: /* vlan mode */ case 11: /* mac clone 11reg */ case 21: /* smart squelch */ val = ((mac_clone_11 ? 1 : 0) << 4) | ((vlan_mode ? 1 : 0) << 5) | ((smart_squelch ? 1 : 0) << 10); adm_wreg (einfo, 0x11, val); break; case 22: /* vlan priority map */ val = 0; for (i=0; i<8; ++i) val |= ((vlan_prio[i]&=3)<<(i*2)); adm_wreg (einfo, 0x0e, val); break; case 23: /* tos priority map */ val = 0; for (i=0; i<8; ++i) val |= ((tos_prio[i]&=3)<<(i*2)); adm_wreg (einfo, 0x0f, val); break; case 12: /* mac clone 30 reg */ case 13: /* mii speed double */ case 14: /* dual speed led */ case 15: /* port led mode */ /* this register has R/W reserved bits, so we had to preserve its values */ adm_rreg(einfo, 0, 0x30, &val32); val = val32 & (0xFFFF & ~(BIT(5)&BIT(6)&BIT(9)&BIT(12))); val |= ((mac_clone_30 ? 1 : 0) << 5) | ((mii_speed ? 1 : 0) << 6) | ((speed_led ? 1 : 0) << 9) | ((port_led ? 1 : 0) << 12); adm_wreg (einfo, 0x30, val); break; case 8: /* drop on collisions */ /* port settings */ case 112: /* mac lock */ val = ((port_cfg[0].mac_lock?1:0)<<0) | ((port_cfg[1].mac_lock?1:0)<<2) | ((port_cfg[2].mac_lock?1:0)<<4) | ((port_cfg[3].mac_lock?1:0)<<6) | ((port_cfg[4].mac_lock?1:0)<<7) | ((port_cfg[5].mac_lock?1:0)<<8) | ((drop_on_collisions?1:0)<<15); adm_wreg (einfo, 0x12, val); break; /* vlan-groups */ case 70: case 71: case 72: case 73: case 74: case 75: case 76: case 77: case 78: case 79: case 80: case 81: case 82: case 83: case 84: case 85: for (i=0; i<16; ++i) { static const int bit_map[] = { BIT(0), BIT(2), BIT(4), BIT(6), BIT(7), BIT(8) }; int j; for (val=0, j=0; j<6; ++j) if (vlan_groups[i][j]) val |= bit_map[j]; adm_wreg (einfo, 0x13+i, val); } break; case 101: /* speed */ if (port_cfg[port].speed != 100 && port_cfg[port].speed != 10) port_cfg[port].speed = 100; case 100: /* enable */ case 104: /* tagging */ case 105: /* autoneg */ case 106: /* duplex */ case 107: /* port prio */ case 108: /* vlan-mask */ case 109: /* crossover */ case 110: /* tos */ case 111: /* fx */ case 113: /* flow */ printk ("ADM6996: %d request; port %d; id %d\n", ctl_name, port, table->ctl_name); val = ((port_cfg[port].flow?1:0) << 0) | ((port_cfg[port].autoneg?1:0) << 1) | ((port_cfg[port].speed==100?1:0) << 2) | ((port_cfg[port].duplex?1:0) << 3) | ((port_cfg[port].tagging?1:0)<<4) | ((port_cfg[port].enabled?0:1)<<5) | ((port_cfg[port].use_tos?1:0)<<6) | ((port_cfg[port].use_prio?1:0)<<7) | ((port_cfg[port].port_prio&=3)<<8) | ((port_cfg[port].fx?1:0) << 14) | ((port_cfg[port].crossover?1:0)<<15); val |= ((port_cfg[port].pvid&0x0f)<<10); adm_wreg (einfo, port_map[port], val); if (ctl_name != 108) break; port_cfg[port].vlan = (port_cfg[port].pvid>>tag_shift) & 0xf; if (port <= 2) { val = ((port_cfg[port].pvid & 0xff0)>>4); adm_wreg (einfo, 0x28+port, val); break; } else if (port <= 4) { val = ((port_cfg[3].pvid & 0xff0)>>4) | ((port_cfg[4].pvid & 0xff0)<<4); adm_wreg (einfo, 0x2b, val); break; } /* fallback */ case 16: if (ctl_name == 16) { for (i=0; i<6; ++i) port_cfg[i].vlan = (port_cfg[i].pvid>>tag_shift) & 0xf; } case 17: case 18: case 19: case 20: case 26: val = ((port_cfg[3].pvid & 0xff0)>>4) | ((tag_shift&7)<<8) | ((reg_2c_bit_11?1:0)<<11) | ((fwd_management_mac1?1:0)<<12) | ((fwd_management_mac2?1:0)<<13) | ((fwd_management_mac3?1:0)<<14) | ((fwd_management_mac4?1:0)<<15); adm_wreg (einfo, 0x2c, val); break; } return 0;}static char* bandwidth_map[] = { "256k", "512k", "1m", "2m", "5m", "10m", "20m", "50m", "full" };static int adm_sysctl_bandwidth (ctl_table *table, int write, struct file *filp, void *buffer, size_t *lenp){ int ret, port, val, index; ctl_table fake_table; int ctl_name; unsigned char buf[5]; port = (table->ctl_name / 100) - 1; // printk ("ADM6996: port %d detected, ctlname %d\n", port, table->ctl_name); ctl_name = table->ctl_name % 100 + 100; index = port_cfg[port].bandwidth; if (index == -1) index = 8; strcpy (buf, bandwidth_map[index]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -