Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
0007  * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
0008  * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
0009  */
0010 
0011 #define pr_fmt(fmt) "bcm63xx_nvram: " fmt
0012 
0013 #include <linux/bcm963xx_nvram.h>
0014 #include <linux/init.h>
0015 #include <linux/crc32.h>
0016 #include <linux/export.h>
0017 #include <linux/kernel.h>
0018 #include <linux/if_ether.h>
0019 
0020 #include <bcm63xx_nvram.h>
0021 
0022 #define BCM63XX_DEFAULT_PSI_SIZE    64
0023 
0024 static struct bcm963xx_nvram nvram;
0025 static int mac_addr_used;
0026 
0027 void __init bcm63xx_nvram_init(void *addr)
0028 {
0029     u32 crc, expected_crc;
0030     u8 hcs_mac_addr[ETH_ALEN] = { 0x00, 0x10, 0x18, 0xff, 0xff, 0xff };
0031 
0032     /* extract nvram data */
0033     memcpy(&nvram, addr, BCM963XX_NVRAM_V5_SIZE);
0034 
0035     /* check checksum before using data */
0036     if (bcm963xx_nvram_checksum(&nvram, &expected_crc, &crc))
0037         pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n",
0038             expected_crc, crc);
0039 
0040     /* Cable modems have a different NVRAM which is embedded in the eCos
0041      * firmware and not easily extractible, give at least a MAC address
0042      * pool.
0043      */
0044     if (BCMCPU_IS_3368()) {
0045         memcpy(nvram.mac_addr_base, hcs_mac_addr, ETH_ALEN);
0046         nvram.mac_addr_count = 2;
0047     }
0048 }
0049 
0050 u8 *bcm63xx_nvram_get_name(void)
0051 {
0052     return nvram.name;
0053 }
0054 EXPORT_SYMBOL(bcm63xx_nvram_get_name);
0055 
0056 int bcm63xx_nvram_get_mac_address(u8 *mac)
0057 {
0058     u8 *oui;
0059     int count;
0060 
0061     if (mac_addr_used >= nvram.mac_addr_count) {
0062         pr_err("not enough mac addresses\n");
0063         return -ENODEV;
0064     }
0065 
0066     memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
0067     oui = mac + ETH_ALEN/2 - 1;
0068     count = mac_addr_used;
0069 
0070     while (count--) {
0071         u8 *p = mac + ETH_ALEN - 1;
0072 
0073         do {
0074             (*p)++;
0075             if (*p != 0)
0076                 break;
0077             p--;
0078         } while (p != oui);
0079 
0080         if (p == oui) {
0081             pr_err("unable to fetch mac address\n");
0082             return -ENODEV;
0083         }
0084     }
0085 
0086     mac_addr_used++;
0087     return 0;
0088 }
0089 EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
0090 
0091 int bcm63xx_nvram_get_psi_size(void)
0092 {
0093     if (nvram.psi_size > 0)
0094         return nvram.psi_size;
0095 
0096     return BCM63XX_DEFAULT_PSI_SIZE;
0097 }
0098 EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);