diff options
342 files changed, 63462 insertions, 316 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb35050..6860be0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,3 +35,11 @@ outlined on that page and do not file a public issue. ## Coding Style * 2 spaces for indentation rather than tabs * 80 character line length + +## License +OpenBMC is made up of different packages. Each package contains recipe files +that detail where to fetch source code from third party sources or local +directories. The recipe files themselves are provided under the GPLv2 +license, but your use of the code fetched by each recipe file is subject to +the licenses of each respective third party project or as defined in the local +directory. diff --git a/common/recipes-connectivity/lldp-util/lldp-util/src/LICENSE b/common/recipes-connectivity/lldp-util/lldp-util/src/LICENSE new file mode 100644 index 0000000..a1dd699 --- /dev/null +++ b/common/recipes-connectivity/lldp-util/lldp-util/src/LICENSE @@ -0,0 +1,30 @@ +BSD License + +For OpenBMC lldp-util software + +Copyright (c) 2015-present, Facebook, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name Facebook nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/common/recipes-connectivity/lldp-util/lldp-util/src/Makefile b/common/recipes-connectivity/lldp-util/lldp-util/src/Makefile new file mode 100644 index 0000000..8dfacfb --- /dev/null +++ b/common/recipes-connectivity/lldp-util/lldp-util/src/Makefile @@ -0,0 +1,19 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +all: lldp-util + +# Yocto overrides anything we do to CFLAGS using "make -e", +# so use our own EXTRA_CFLAGS variable instead of CFLAGS. +EXTRA_CFLAGS = -std=gnu99 -Wall -Wextra -Werror \ + -Wno-unused -Wno-unused-parameter + +lldp-util: lldp_util.o + $(CC) -o $@ $^ $(LDFLAGS) + +%.o: %.c + @echo $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< + +.PHONY: clean + +clean: + rm -rf *.o lldp-util diff --git a/common/recipes-connectivity/lldp-util/lldp-util/src/PATENTS b/common/recipes-connectivity/lldp-util/lldp-util/src/PATENTS new file mode 100644 index 0000000..97e8932 --- /dev/null +++ b/common/recipes-connectivity/lldp-util/lldp-util/src/PATENTS @@ -0,0 +1,23 @@ +Additional Grant of Patent Rights + +"Software" means the OpenBMC lldp-util software distributed by Facebook, Inc. + +Facebook hereby grants you a perpetual, worldwide, royalty-free, non-exclusive, +irrevocable (subject to the termination provision below) license under any +rights in any patent claims owned by Facebook, to make, have made, use, sell, +offer to sell, import, and otherwise transfer the Software. For avoidance of +doubt, no license is granted under Facebook’s rights in any patent claims that +are infringed by (i) modifications to the Software made by you or a third party, +or (ii) the Software in combination with any software or other technology +provided by you or a third party. + +The license granted hereunder will terminate, automatically and without notice, +for anyone that makes any claim (including by filing any lawsuit, assertion or +other action) alleging (a) direct, indirect, or contributory infringement or +inducement to infringe any patent: (i) by Facebook or any of its subsidiaries or +affiliates, whether or not such claim is related to the Software, (ii) by any +party if such claim arises in whole or in part from any software, product or +service of Facebook or any of its subsidiaries or affiliates, whether or not +such claim is related to the Software, or (iii) by any party relating to the +Software; or (b) that any right in any patent claim of Facebook is invalid or +unenforceable. diff --git a/common/recipes-connectivity/lldp-util/lldp-util/src/lldp_util.c b/common/recipes-connectivity/lldp-util/lldp-util/src/lldp_util.c new file mode 100644 index 0000000..a4ffc11 --- /dev/null +++ b/common/recipes-connectivity/lldp-util/lldp-util/src/lldp_util.c @@ -0,0 +1,703 @@ +/* + * Copyright 2004-present Facebook. All Rights Reserved. + * + * A simple utility for printing LLDP and CDP packets received on an interface. + * Eventually it might be worth replacing this with lldpd or lldpad, + * but for now this provides a simple standalone script that can be dropped + * onto a system and run on an as-needed basis. + */ +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <linux/filter.h> +#include <linux/if_ether.h> +#include <netpacket/packet.h> +#include <net/ethernet.h> +#include <net/if.h> +#include <assert.h> +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <inttypes.h> +#include <signal.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +// The minimum ethernet frame length, without the 4-byte frame check sequence +#define MIN_FRAME_LENGTH 60 +#define MAX_FRAME_LENGTH 9000 + +#define ETHERTYPE_VLAN 0x8100 +#define ETHERTYPE_LLDP 0x88CC + +#define LLDP_CHASSIS_CDP 0xff +#define LLDP_CHASSIS_MAC_ADDRESS 4 +#define LLDP_CHASSIS_NET_ADDRESS 5 + +#define LLDP_PORT_CDP 0xff +#define LLDP_PORT_MAC_ADDRESS 3 +#define LLDP_PORT_NET_ADDRESS 4 + +#define LLDP_TYPE_END 0 +#define LLDP_TYPE_CHASSIS_ID 1 +#define LLDP_TYPE_PORT_ID 2 +#define LLDP_TYPE_SYSTEM_NAME 5 + +#define CDP_TYPE_DEVICE_ID 1 +#define CDP_TYPE_PORT_ID 3 +#define CDP_TYPE_SYSTEM_NAME 20 + +static const unsigned char MAC_LLDP_NEAREST_BRIDGE[] = + { 0x01, 0x80, 0xc2, 0x00, 0x00,0x0e }; +static const unsigned char MAC_CDP[] = + { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc }; + +static bool verbose = false; + +void errmsg(const char* fmt, ...) __attribute__((format(printf, 1, 2))); +void debugmsg(const char* fmt, ...) __attribute__((format(printf, 1, 2))); + +void errmsg(const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +} + +void debugmsg(const char* fmt, ...) { + if (!verbose) { + return; + } + + va_list ap; + va_start(ap, fmt); + fputs("DEBUG: ", stderr); + vfprintf(stderr, fmt, ap); + fputc('\n', stderr); + va_end(ap); +} + +#define FAIL_ERRNO(msg, ...) \ + do { \ + returnCode = -errno; \ + errmsg((msg), ##__VA_ARGS__); \ + goto error; \ + } while (0) + +#define CHECK_ERROR(rc, msg, ...) \ + do { if ((rc) == -1) { FAIL_ERRNO((msg), ##__VA_ARGS__); } } while (0) + +typedef struct { + const char* protocol; + const char* local_interface; + const uint8_t* src_mac; + const uint8_t* chassis_id; + const uint8_t* port_id; + const uint8_t* system_name; + uint32_t chassis_id_length; + uint32_t port_id_length; + uint32_t system_name_length; + uint8_t chassis_id_type; + uint8_t port_id_type; +} lldp_neighbor_t; + + +#define DFLT_MAX_SAV_CDP 10 + +typedef struct { + uint8_t *cdp_buf; + size_t length; +} cdp_frame_t; + +typedef struct { + int max_sav_cdp; // max # cdp frames to save + int num_sav_cdp; // number currently saved + cdp_frame_t* frame; // saved CDP frames +} cdp_sav_data_t; + +cdp_sav_data_t cdp_sav_data; + +volatile sig_atomic_t g_interrupt; // set in exit handler + +void lldp_neighbor_init(lldp_neighbor_t* neighbor, + const char* protocol, + const char* interface, + const uint8_t* src_mac) { + memset(neighbor, 0, sizeof(*neighbor)); + neighbor->protocol = protocol; + neighbor->local_interface = interface; + neighbor->src_mac = src_mac; +} + +int lldp_open(const char* interface) { + int fd = -1; + int returnCode = -EINVAL; + + { + fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (fd < 0) { + FAIL_ERRNO("failed to create socket for local interface %s", interface); + } + + // Look up the interface index + struct ifreq ifr; + snprintf(ifr.ifr_name, IFNAMSIZ, interface); + int rc = ioctl(fd, SIOCGIFINDEX, &ifr); + CHECK_ERROR(rc, "failed to get interface index for %s", interface); + + // Bind the socket + struct sockaddr_ll addr; + addr.sll_family = AF_PACKET; + addr.sll_ifindex = ifr.ifr_ifindex; + addr.sll_protocol = htons(ETH_P_ALL); + rc = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); + CHECK_ERROR(rc, "failed to bind socket for %s", interface); + + // Ask linux to also send us packets sent to LLDP "nearest bridge" + // multicast MAC address + struct packet_mreq mr; + memset(&mr, 0, sizeof(mr)); + mr.mr_ifindex = ifr.ifr_ifindex; + mr.mr_alen = ETH_ALEN; + memcpy(mr.mr_address, MAC_LLDP_NEAREST_BRIDGE, ETH_ALEN); + mr.mr_type = PACKET_MR_MULTICAST; + rc = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)); + CHECK_ERROR(rc, "failed to add LLDP packet membership for %s", interface); + + // Ask linux to also send us packets sent to the CDP multicast MAC address + memcpy(mr.mr_address, MAC_CDP, ETH_ALEN); + rc = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)); + CHECK_ERROR(rc, "failed to add CDP packet membership for %s", interface); + + // Set a filter to ignore non-multicast packets, so we don't get a flood + // of meaningless packets that we don't care about. + // + // tcpdump -i eth0 -dd ether multicast + static struct sock_filter PACKET_FILTER[] = { + { 0x30, 0, 0, 0x00000000 }, + { 0x45, 0, 1, 0x00000001 }, + { 0x6, 0, 0, 0x0000ffff }, + { 0x6, 0, 0, 0x00000000 }, + }; + struct sock_fprog bpf; + bpf.len = sizeof(PACKET_FILTER) / sizeof(PACKET_FILTER[0]); + bpf.filter = PACKET_FILTER; + rc = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)); + CHECK_ERROR(rc, "failed to set socket packet filter for %s", interface); + + returnCode = fd; + goto cleanup; + } + +error: + assert(returnCode < 0); + if (fd != -1) { + close(fd); + } + +cleanup: + return returnCode; +} + +void lldp_print_value(const uint8_t* buf, uint32_t length) { + int n; + + bool add_quotes = false; + for (uint32_t n = 0; n < length; ++n) { + uint8_t value = buf[n]; + if (value < 0x20 || value >= 0x7f || isspace(value)) { + add_quotes = true; + break; + } + } + + if (add_quotes) { + putchar('"'); + } + for (uint32_t n = 0; n < length; ++n) { + uint8_t value = buf[n]; + + // Ignore trailing NUL characters + if (value == 0 && n + 1 == length) { + break; + } + + if (value == '"' || value == '\\') { + putchar('\\'); + putchar(value); + } else if (value >= 0x20 && value < 0x7f) { + putchar(value); + } else { + printf("\\x%02x", value); + } + } + if (add_quotes) { + putchar('"'); + } +} + +void lldp_print_mac(const uint8_t* buf, uint32_t length) { + if (length != 6) { + fputs("<bad_mac:", stdout); + lldp_print_value(buf, length); + putchar('>'); + return; + } + + printf("%02x:%02x:%02x:%02x:%02x:%02x", + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); +} + +void lldp_print_net_addr(const uint8_t* buf, uint32_t length) { + if (length < 1) { + return; + } + + if (buf[0] == 1 && length == 5) { + // IPv4 + struct in_addr addr; + memcpy(&addr.s_addr, buf + 1, length - 1); + + char str[INET_ADDRSTRLEN]; + if (inet_ntop(AF_INET, &addr, str, sizeof(str)) != NULL) { + fputs(str, stdout); + return; + } + } else if (buf[0] == 2 && length == 17) { + struct in6_addr addr; + memcpy(&addr.s6_addr, buf + 1, length - 1); + + char str[INET6_ADDRSTRLEN]; + if (inet_ntop(AF_INET6, &addr, str, sizeof(str)) != NULL) { + fputs(str, stdout); + return; + } + } + + // If we are still here, this wasn't IPv4 or IPv6, or we failed to parse it. + printf("<net_addr:%d:", buf[0]); + lldp_print_value(buf + 1, length - 1); + putchar('>'); +} + +void lldp_print_neighbor(lldp_neighbor_t* neighbor) { + fprintf(stdout, "%s: local_port=%s", + neighbor->protocol, neighbor->local_interface); + fputs(" remote_system=", stdout); + if (neighbor->system_name) { + lldp_print_value(neighbor->system_name, neighbor->system_name_length); + } else if (neighbor->chassis_id_type == LLDP_CHASSIS_MAC_ADDRESS) { + lldp_print_mac(neighbor->chassis_id, neighbor->chassis_id_length); + } else if (neighbor->chassis_id_type == LLDP_CHASSIS_NET_ADDRESS) { + lldp_print_net_addr(neighbor->chassis_id, neighbor->chassis_id_length); + } else { + lldp_print_value(neighbor->chassis_id, neighbor->chassis_id_length); + } + + fputs(" remote_port=", stdout); + if (neighbor->port_id_type == LLDP_PORT_MAC_ADDRESS) { + lldp_print_mac(neighbor->port_id, neighbor->port_id_length); + } else if (neighbor->port_id_type == LLDP_PORT_NET_ADDRESS) { + lldp_print_net_addr(neighbor->port_id, neighbor->port_id_length); + } else { + lldp_print_value(neighbor->port_id, neighbor->port_id_length); + } + putchar('\n'); +} + +uint16_t lldp_read_u16(const uint8_t** buf) { + // Use memcpy() to comply with strict-aliasing rules. + // The compiler will optimize this away anyway. + uint16_t result; + memcpy(&result, *buf, 2); + (*buf) += 2; + return htons(result); +} + +int lldp_parse_lldp(lldp_neighbor_t* neighbor, + const uint8_t* buf, + const uint8_t* end) { + while (buf < end) { + // Parse the type (7 bits) and length (9 bits) + if ((end - buf) < 2) { + errmsg("LLDPDU truncated in tag/length header"); + return -EINVAL; + } + uint16_t length = lldp_read_u16(&buf); + uint16_t type = (length >> 9); + length &= 0x01ff; + + if ((end - buf) < length) { + errmsg("LLDPDU truncated inside field of type %d: " + "field_length=%d, remaining=%d", type, length, end - buf); + return -EINVAL; + } + + if (type == LLDP_TYPE_CHASSIS_ID) { + if (length < 1) { + errmsg("LLDPDU with invalid chassis ID length %d", length); + return -EINVAL; + } + neighbor->chassis_id_type = buf[0]; + neighbor->chassis_id = buf + 1; + neighbor->chassis_id_length = length - 1; + } else if (type == LLDP_TYPE_PORT_ID) { + if (length < 1) { + errmsg("LLDPDU with invalid port ID length %d", length); + return -EINVAL; + } + neighbor->port_id_type = buf[0]; + neighbor->port_id = buf + 1; + neighbor->port_id_length = length - 1; + } else if (type == LLDP_TYPE_SYSTEM_NAME) { + neighbor->system_name = buf; + neighbor->system_name_length = length; + } + + buf += length; + + if (type == LLDP_TYPE_END) { + break; + } + } + + if (!neighbor->chassis_id) { + errmsg("received LLDPDU with missing chassis ID"); + return -EINVAL; + } + if (!neighbor->port_id) { + errmsg("received LLDPDU with missing port ID"); + return -EINVAL; + } + + return 0; +} + +int lldp_parse_cdp(lldp_neighbor_t* neighbor, + const uint8_t* buf, + const uint8_t* end) { + // Skip over some initial headers: + // 1 byte DSAP + // 1 byte SSAP + // 1 byte LLC control field + // 3 byte SNAP vendor code + // 2 byte SNAP local code + // 1 byte CDP version + // 1 byte TTL + // 2 byte checksum + if ((end - buf) < 12) { + errmsg("CDP PDU truncated in initial headers: length=%d", end - buf); + return -EINVAL; + } + buf += 8; + uint8_t cdp_version = *buf; + if (cdp_version != 2) { + // We only support CDP version 2 for now. + debugmsg("ignoring unsupported CDP PDU with version %d", cdp_version); + return -EPFNOSUPPORT; + } + buf += 4; + + while (buf < end) { + if ((end - buf) < 4) { + errmsg("CDP PDU truncated in tag/length header"); + return -EINVAL; + } + uint16_t type = lldp_read_u16(&buf); + uint16_t length = lldp_read_u16(&buf); + + if (length < 4) { + errmsg("CDP PDU with bad length=%d for field of type %d", + length, type); + return -EINVAL; + } + length -= 4; + if ((end - buf) < length) { + errmsg("CDP PDU truncated inside field of type %d: " + "field_length=%d, remaining=%d", type, length, end - buf); + return -EINVAL; + } + + if (type == CDP_TYPE_DEVICE_ID) { + neighbor->chassis_id_type = LLDP_CHASSIS_CDP; + neighbor->chassis_id = buf; + neighbor->chassis_id_length = length; + } else if (type == CDP_TYPE_PORT_ID) { + neighbor->port_id_type = LLDP_PORT_CDP; + neighbor->port_id = buf; + neighbor->port_id_length = length; + } else if (type == CDP_TYPE_SYSTEM_NAME) { + neighbor->system_name = buf; + neighbor->system_name_length = length; + } + buf += length; + } + + if (!neighbor->chassis_id) { + errmsg("received CDP PDU with missing device ID"); + return -EINVAL; + } + if (!neighbor->port_id) { + errmsg("received CDP PDU with missing port ID"); + return -EINVAL; + } + + return 0; +} + +int lldp_process_packet(const uint8_t* buf, + size_t length, + const char* interface, + bool process_cdp, + bool* processed) { + int returnCode = -EINVAL; + *processed = false; + + { + // Bail if the minimum ethernet frame size is not met + if (length < MIN_FRAME_LENGTH) { + errmsg("received too-short frame on interface %s: length=%d", + interface, length); + returnCode = -EINVAL; + goto error; + } + + const uint8_t* buf_start = buf; + const uint8_t* end = buf + length; + + const uint8_t* dest_mac = buf; + buf += 6; + const uint8_t* src_mac = buf; + buf += 6; + uint16_t ethertype = lldp_read_u16(&buf); + + if (ethertype == ETHERTYPE_VLAN) { + uint16_t vlan = lldp_read_u16(&buf); + ethertype = lldp_read_u16(&buf); + } + + if (ethertype == ETHERTYPE_LLDP) { + lldp_neighbor_t neighbor; + lldp_neighbor_init(&neighbor, "LLDP", interface, src_mac); + returnCode = lldp_parse_lldp(&neighbor, buf, end); + if (returnCode != 0) { + goto error; + } + lldp_print_neighbor(&neighbor); + fflush(stdout); + *processed = true; + } else if ((memcmp(dest_mac, MAC_CDP, 6) == 0) && (ethertype < 0x600)) { + if (process_cdp) { + lldp_neighbor_t neighbor; + lldp_neighbor_init(&neighbor, "CDP", interface, src_mac); + returnCode = lldp_parse_cdp(&neighbor, buf, end); + if (returnCode != 0) { + goto error; + } + lldp_print_neighbor(&neighbor); + fflush(stdout); + *processed = true; + } else if (cdp_sav_data.num_sav_cdp < cdp_sav_data.max_sav_cdp) { + cdp_sav_data.frame[cdp_sav_data.num_sav_cdp].cdp_buf = malloc(length); + assert(cdp_sav_data.frame[cdp_sav_data.num_sav_cdp].cdp_buf); + memcpy(cdp_sav_data.frame[cdp_sav_data.num_sav_cdp].cdp_buf, buf_start, + length); + cdp_sav_data.frame[cdp_sav_data.num_sav_cdp].length = length; + cdp_sav_data.num_sav_cdp++; + } + } else { + // Some other packet type that we don't care about. + debugmsg("Ignored packet on %s: ethertype=0x%04x", + interface, ethertype); + } + + returnCode = 0; + goto cleanup; + } + +error: + assert(returnCode < 0); +cleanup: + return returnCode; +} + +int lldp_receive(int fd, const char* interface, bool cdp, bool* processed) { + int returnCode = -EINVAL; + *processed = false; + { + uint8_t buf[MAX_FRAME_LENGTH]; + + struct sockaddr_ll src_addr; + socklen_t addr_len; + ssize_t len = recvfrom(fd, buf, MAX_FRAME_LENGTH, 0, + (struct sockaddr*)&src_addr, &addr_len); + if (len == -1) { + if (errno != EINTR) { + errmsg("error reading packet from %s", interface); + } + returnCode = -errno; + goto error; + } + + returnCode = lldp_process_packet(buf, len, interface, cdp, processed); + goto cleanup; + } + +error: + assert(returnCode < 0); +cleanup: + return returnCode; +} + +void exit_handler(int signum) { + g_interrupt = true; +} + +void usage_short(FILE* out) { + fprintf(out, "lldp-util [-h] [-c] [-i <interface>] " + "[-n <count>] [-t <timeout>]\n"); +} + +void usage_full(FILE* out) { + usage_short(out); + fprintf(out, + "\n" + " -c Report CDP packets as they arrive in addition " + "to LLDP\n" + " -h Show this help message and exit\n" + " -i <interface> Specify the interface to listen on\n" + " -n <count> Exit after receiving <count> LLDP packets\n" + " -t <timeout> Exit after <timeout> seconds\n" + " Negative or 0 means no timeout\n" + "\n" + "If neither -n nor -t are specified, lldp-util uses a 65 second\n" + "timeout by default\n" + ); +} + +int main(int argc, char* argv[]) { + const char* interface = "eth0"; + long timeout = 0; + bool has_timeout = false; + long max_count = 0; + bool has_max_count = false; + bool inline_cdp = false; + + while (true) { + int opt = getopt(argc, argv, "chi:n:t:"); + if (opt == -1) { + break; + } + switch (opt) { + case 'c': + inline_cdp = true; + break; + case 'h': + usage_full(stdout); + return 0; + case 'i': + interface = optarg; + break; + case 'n': { + char* end; + max_count = strtol(optarg, &end, 10); + if (end == optarg || *end != '\0') { + fprintf(stderr, "error: bad count value: must be an integer\n"); + return 1; + } + has_max_count = true; + break; + } + case 't': { + char* end; + timeout = strtol(optarg, &end, 10); + if (end == optarg || *end != '\0') { + fprintf(stderr, "error: bad timeout value: must be an integer\n"); + return 1; + } + has_timeout = true; + break; + } + default: + usage_short(stderr); + return 1; + } + } + + // Default to a 65 second timeout if no other limits were specified. + if (!has_max_count && !has_timeout) { + timeout = 65; + } + + int fd = lldp_open(interface); + if (fd < 0) { + return 1; + } + + struct sigaction sa; + + // Clear all fields in sa. In particular, SA_RESTART must not be set in + // sa_flags field because we want recvfrom to be interrupted. + memset(&sa, 0, sizeof(sa)); + + sa.sa_handler = exit_handler; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + // Automatically stop after 65 seconds + if (timeout > 0) { + sigaction(SIGALRM, &sa, NULL); + alarm(timeout); + } + + // In the case when we are asked not to report CDP packets as they arrive, + // we will save them in a global buffer. On exiting, if we have not seen + // any LLDP packets, we'll dump the CDP packets that arrived. + if (!inline_cdp) { + if (max_count > 0) { + cdp_sav_data.max_sav_cdp = max_count; + } else { + cdp_sav_data.max_sav_cdp = DFLT_MAX_SAV_CDP; + } + cdp_sav_data.frame = malloc(sizeof(cdp_frame_t) * + cdp_sav_data.max_sav_cdp); + if (cdp_sav_data.frame == NULL) { + printf("memory allocation failed for saved frames\n"); + exit(1); + } + } + + printf("Listening for LLDP packets...\n"); + fflush(stdout); + long count = 0; + bool processed; + while (true) { + lldp_receive(fd, interface, inline_cdp, &processed); + if (processed) { + ++count; + if (max_count > 0 && count >= max_count) { + break; + } + } + if (g_interrupt) { + break; + } + } + + // Print saved CDP packets if we haven't printed anything yet + if (count == 0) { + for (int i = 0; i < cdp_sav_data.num_sav_cdp; i++) { + lldp_process_packet(cdp_sav_data.frame[i].cdp_buf, + cdp_sav_data.frame[i].length, + interface, true, &processed); + } + } + + return 0; +} diff --git a/common/recipes-connectivity/lldp-util/lldp-util_0.1.bb b/common/recipes-connectivity/lldp-util/lldp-util_0.1.bb new file mode 100644 index 0000000..eb53e9a --- /dev/null +++ b/common/recipes-connectivity/lldp-util/lldp-util_0.1.bb @@ -0,0 +1,21 @@ +# Copyright 2014-present Facebook. All Rights Reserved. + +SUMMARY = "LLDP Utility" +DESCRIPTION = "A utility for reporting LLDP information" +SECTION = "base" +PR = "r1" +LICENSE = "BSD" +LIC_FILES_CHKSUM = "file://LICENSE;md5=cc7ed73f378cc0ea228aebab24237853 \ + file://PATENTS;md5=aed2575e5dba9ba3aea25cfeddb8f1d2 " + +SRC_URI = "file://src \ + " + +S = "${WORKDIR}/src" + +do_install() { + install -d ${D}${bindir} + install -m 755 lldp-util ${D}${bindir} +} + +FILES_${PN} = " ${bindir} " diff --git a/common/recipes-core/base-files/base-files_%.bbappend b/common/recipes-core/base-files/base-files_%.bbappend index 340ad2c..6a73f2b 100644 --- a/common/recipes-core/base-files/base-files_%.bbappend +++ b/common/recipes-core/base-files/base-files_%.bbappend @@ -15,8 +15,8 @@ do_install_bmc_issue () { dir=$(dirname $dir) done - if [ -d "$dir/meta-aspeed/.git" ]; then - srcdir="$dir/meta-aspeed" + if [ -d "$dir/meta-openbmc/.git" ]; then + srcdir="$dir/meta-openbmc" srcdir_git="${srcdir}/.git" version=$(git --git-dir=${srcdir_git} --work-tree=${srcdir} describe --dirty 2> /dev/null) else diff --git a/common/recipes-core/cfg-util/cfg-util_0.1.bb b/common/recipes-core/cfg-util/cfg-util_0.1.bb new file mode 100644 index 0000000..13b6568 --- /dev/null +++ b/common/recipes-core/cfg-util/cfg-util_0.1.bb @@ -0,0 +1,36 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Configuration Utility" +DESCRIPTION = "Utility for reading or writing configuration" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://cfg-util.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238" + +SRC_URI = "file://Makefile \ + file://cfg-util.c \ + " +S = "${WORKDIR}" + +LDFLAGS =+ " -lpal " + +DEPENDS =+ " libpal " + +binfiles = "cfg-util" + +pkgdir = "cfg-util" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + install -m 755 cfg-util ${dst}/cfg-util + ln -snf ../fbpackages/${pkgdir}/cfg-util ${bin}/cfg-util +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/cfg-util ${prefix}/local/bin" + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-core/cfg-util/files/Makefile b/common/recipes-core/cfg-util/files/Makefile new file mode 100644 index 0000000..05b9b16 --- /dev/null +++ b/common/recipes-core/cfg-util/files/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +all: cfg-util + + +cfg-util: cfg-util.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o cfg-util diff --git a/common/recipes-core/cfg-util/files/cfg-util.c b/common/recipes-core/cfg-util/files/cfg-util.c new file mode 100644 index 0000000..99618f7 --- /dev/null +++ b/common/recipes-core/cfg-util/files/cfg-util.c @@ -0,0 +1,78 @@ +/* + * cfg-util + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <string.h> +#include <openbmc/pal.h> + +static void +print_usage(void) { + printf("Usage: cfg-util <dump-all|key> <value>\n"); +} + +int +main(int argc, char **argv) { + + int ret; + uint8_t key[MAX_KEY_LEN] = {0}; + uint8_t val[MAX_VALUE_LEN] = {0}; + + // Handle boundary checks + if (argc < 2 || argc > 3) { + goto err_exit; + } + + // Handle dump of key value data base + if ((argc == 2) && (!strcmp(argv[1], "dump-all"))){ + pal_dump_key_value(); + return 0; + } + + // Handle Get the Configuration + if (argc == 2) { + snprintf(key, MAX_KEY_LEN, "%s", argv[1]); + + ret = pal_get_key_value(key, val); + if (ret) { + goto err_exit; + } + + printf("%s\n", val); + return 0; + } + + // Handle Set the configuration + snprintf(key, MAX_KEY_LEN, "%s", argv[1]); + snprintf(val, MAX_VALUE_LEN, "%s", argv[2]); + + ret = pal_set_key_value(key, val); + if (ret) { + goto err_exit; + } + + return 0; + +err_exit: + print_usage(); + exit(-1); +} diff --git a/common/recipes-core/consoled/consoled_0.1.bb b/common/recipes-core/consoled/consoled_0.1.bb new file mode 100644 index 0000000..5b6edd1 --- /dev/null +++ b/common/recipes-core/consoled/consoled_0.1.bb @@ -0,0 +1,36 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Serial Buffer" +DESCRIPTION = "Daemon for serial buffering" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://consoled.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238" + +SRC_URI = "file://Makefile \ + file://consoled.c \ + " +S = "${WORKDIR}" + +LDFLAGS =+ " -lpal " + +DEPENDS =+ " libpal " + +binfiles = "consoled" + +pkgdir = "consoled" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + install -m 755 consoled ${dst}/consoled + ln -snf ../fbpackages/${pkgdir}/consoled ${bin}/consoled +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/consoled ${prefix}/local/bin" + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-core/consoled/files/Makefile b/common/recipes-core/consoled/files/Makefile new file mode 100644 index 0000000..2b30ef2 --- /dev/null +++ b/common/recipes-core/consoled/files/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +all: consoled + + +consoled: consoled.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o consoled diff --git a/common/recipes-core/consoled/files/consoled.c b/common/recipes-core/consoled/files/consoled.c new file mode 100644 index 0000000..9f17e31 --- /dev/null +++ b/common/recipes-core/consoled/files/consoled.c @@ -0,0 +1,284 @@ +/* + * consoled + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <syslog.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <poll.h> +#include <termios.h> +#include <signal.h> +#include <openbmc/pal.h> + +#define BAUDRATE B57600 +#define CTRL_X 0x18 +#define ASCII_ENTER 0x0D + +static sig_atomic_t sigexit = 0; + +static void +write_data(int file, char *buf, int len, char *fname) { + int wlen = 0; + char *tbuf = buf; + while(len > 0) { + errno = 0; + wlen = write(file, tbuf, len); + // In case wlen < 0, retry write() + if (wlen >= 0) { + len -= wlen; + tbuf = tbuf + wlen; + } else { + syslog(LOG_ALERT, "write_data: write() failed to file %s | errno: %d", + fname, errno); + return; + } + } +} + +static void +exit_session(int sig) +{ + sigexit = sig; +} + +static void +print_usage() { + printf("Usage: consoled [ %s ]\n", pal_server_list); +} + +static void +run_console(char* fru_name, int term) { + + int i; + int tty; // serial port + int buf_fd; // Buffer File + int blen; // len for + int nfd = 0; // For number of fd + int nevents; // For number of events in fd + int nline = 0; + //int pid_fd; + int flags; + pid_t pid; // For pid of the daemon + uint8_t fru; + char in; // For stdin character + char data[32]; + char pid_file[64]; + char devtty[32]; // For tty dev path + char bfname[32]; // For buffer file path + char old_bfname[32]; // For old buffer file path + char buf[256]; // For buffer data + struct termios ottytio, nttytio; // For the tty dev + + int stdi; // STDIN_FILENO + int stdo; // STDOUT_FILENO + struct termios ostditio, nstditio; // For STDIN_FILENO + struct termios ostdotio, nstdotio; // For STDOUT_FILENO + + struct pollfd pfd[2]; + + /* Start Daemon for the console buffering */ + if (!term) { + daemon(0,1); + openlog("consoled", LOG_CONS, LOG_DAEMON); + syslog(LOG_INFO, "consoled: daemon started"); + } + + if (pal_get_fru_id(fru_name, &fru)) { + exit(-1); + } + + if (pal_get_fru_devtty(fru, devtty)) { + exit(-1); + } + + /* Handling the few Signals differently */ + signal(SIGHUP, exit_session); + signal(SIGINT, exit_session); + signal(SIGTERM, exit_session); + signal(SIGPIPE, exit_session); + signal(SIGQUIT, exit_session); + + /* Different flag value for tty dev */ + flags = term == 1 ? (O_RDWR | O_NOCTTY | O_NONBLOCK) : + (O_RDONLY | O_NOCTTY | O_NONBLOCK); + + if ((tty = open(devtty, flags)) < 0) { + syslog(LOG_ALERT, "Cannot open the file %s", devtty); + exit(-1); + } + fcntl(tty, F_SETFL, O_RDWR); + + /* Changing the attributes of the tty dev */ + tcgetattr(tty, &ottytio); + memcpy(&nttytio, &ottytio, sizeof(struct termios)); + cfmakeraw(&nttytio); + cfsetspeed(&nttytio, BAUDRATE); + tcflush(tty, TCIFLUSH); + tcsetattr(tty, TCSANOW, &nttytio); + pfd[0].fd = tty; + pfd[0].events = POLLIN; + nfd++; + + /* Buffering the console data into a file */ + sprintf(old_bfname, "/tmp/consoled_%s_log-old", fru_name); + sprintf(bfname, "/tmp/consoled_%s_log", fru_name); + if ((buf_fd = open(bfname, O_RDWR | O_APPEND | O_CREAT, 0666)) < 0) { + syslog(LOG_ALERT, "Cannot open the file %s", bfname); + exit(-1); + } + + if (term) { + /* Changing the attributes of STDIN_FILENO */ + stdi = STDIN_FILENO; + tcgetattr(stdi, &ostditio); + memcpy(&nstditio, &ostditio, sizeof(struct termios)); + cfmakeraw(&nstditio); + tcflush(stdi, TCIFLUSH); + tcsetattr(stdi, TCSANOW, &nstditio); + + /* Changing the attributes of STDOUT_FILENO */ + stdo = STDOUT_FILENO; + tcgetattr(stdo, &ostdotio); + memcpy(&nstdotio, &ostdotio, sizeof(struct termios)); + cfmakeraw(&nstdotio); + tcflush(stdo, TCIFLUSH); + tcsetattr(stdo, TCSANOW, &nstdotio); + + /* Adding STDIN_FILENO to the poll fd set */ + pfd[1].fd = stdi; + pfd[1].events = POLLIN; + nfd++; + } + + /* Handling the input event from the terminal and tty dev */ + while (!sigexit && (nevents = poll(pfd, nfd, -1 /* Timeout */))) { + + /* Input to the terminal from the user */ + if (term && nevents && nfd > 1 && pfd[1].revents > 0) { + blen = read(stdi, &in, sizeof(in)); + if (blen < 1) { + nfd--; + } + + if (in == CTRL_X) { + break; + } + + write_data(tty, &in, sizeof(in), "tty"); + + nevents--; + } + + /* Input from the tty dev */ + if (nevents && pfd[0].revents > 0) { + blen = read(tty, buf, sizeof(buf)); + if (blen > 0) { + for (i = 0; i < blen; i++) { + if (buf[i] == 0xD) + nline++; + } + write_data(buf_fd, buf, blen, bfname); + fsync(buf_fd); + if (term) { + write_data(stdo, buf, blen, "STDOUT_FILENO"); + } + } else if (blen < 0) { + raise(SIGHUP); + } + + /* Log Rotation */ + if (nline >= 300) { + close(buf_fd); + remove(old_bfname); + rename(bfname, old_bfname); + if ((buf_fd = open(bfname, O_RDWR | O_APPEND | O_CREAT, 0666)) < 0) { + syslog(LOG_ALERT, "Cannot open the file %s", bfname); + exit(-1); + } + nline = 0; + } + nevents--; + } + } + + /* Close the console buffer file */ + close(buf_fd); + + /* Revert the tty dev to old attributes */ + tcflush(tty, TCIFLUSH); + tcsetattr(tty, TCSANOW, &ottytio); + + /* Revert STDIN to old attributes */ + if (term) { + tcflush(stdo, TCIFLUSH); + tcsetattr(stdo, TCSANOW, &ostdotio); + tcflush(stdi, TCIFLUSH); + tcsetattr(stdi, TCSANOW, &ostditio); + } + + /* Delete the pid file */ + if (!term) + remove(pid_file); +} + +int +main(int argc, void **argv) { + int dev, rc, lock_file; + char file[64]; + int term; + char *fru_name; + + if (argc != 3) { + print_usage(); + exit(1); + } + + // A lock file for one instance of consoled for each fru + sprintf(file, "/var/lock/consoled_%s", argv[1]); + lock_file = open(file, O_CREAT | O_RDWR, 0666); + rc = flock(lock_file, LOCK_EX | LOCK_NB); + if(rc) { + if(errno == EWOULDBLOCK) { + printf("Another consoled %s instance is running...\n", argv[1]); + exit(-1); + } + } else { + + fru_name = argv[1]; + + if (!strcmp(argv[2], "--buffer")) { + term = 0; + } else if (!strcmp(argv[2], "--term")) { + term = 1; + } else { + print_usage(); + exit(-1); + } + + run_console(fru_name, term); + } + + return sigexit; +} + diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/Makefile b/common/recipes-core/fan-ctrl/fan-ctrl/Makefile new file mode 100644 index 0000000..da74a34 --- /dev/null +++ b/common/recipes-core/fan-ctrl/fan-ctrl/Makefile @@ -0,0 +1,26 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +all: fand + +fand: fand.cpp watchdog.cpp + $(CXX) $(CXXFLAGS) -pthread -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o fand diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/README b/common/recipes-core/fan-ctrl/fan-ctrl/README new file mode 100644 index 0000000..2a92b9d --- /dev/null +++ b/common/recipes-core/fan-ctrl/fan-ctrl/README @@ -0,0 +1,5 @@ +The AST PWM/Tach driver is in the kernel sources at drivers/hwmon/ast_pwm_fan.c + +There are 7 PWM output pins. Each PWM can be configured in one of 3 types (M, +N, or O). The clock settings for each type are configurable. See init_pwm.sh +for more comments about how we configure the settings. diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp b/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp new file mode 100644 index 0000000..49c6f6b --- /dev/null +++ b/common/recipes-core/fan-ctrl/fan-ctrl/fand.cpp @@ -0,0 +1,1030 @@ +/* + * fand + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Daemon to manage the fan speed to ensure that we stay within a reasonable + * temperature range. We're using a simplistic algorithm to get started: + * + * If the fan is already on high, we'll move it to medium if we fall below + * a top temperature. If we're on medium, we'll move it to high + * if the temperature goes over the top value, and to low if the + * temperature falls to a bottom level. If the fan is on low, + * we'll increase the speed if the temperature rises to the top level. + * + * To ensure that we're not just turning the fans up, then back down again, + * we'll require an extra few degrees of temperature drop before we lower + * the fan speed. + * + * We check the RPM of the fans against the requested RPMs to determine + * whether the fans are failing, in which case we'll turn up all of + * the other fans and report the problem.. + * + * TODO: Implement a PID algorithm to closely track the ideal temperature. + * TODO: Determine if the daemon is already started. + */ + +/* Yeah, the file ends in .cpp, but it's a C program. Deal. */ + +#if !defined(CONFIG_YOSEMITE) && !defined(CONFIG_WEDGE) +#error "No hardware platform defined!" +#endif +#if defined(CONFIG_YOSEMITE) && defined(CONFIG_WEDGE) +#error "Both hardware platform defined!" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <signal.h> +#include <syslog.h> +#ifdef CONFIG_YOSEMITE +#include <openbmc/ipmi.h> +#include <facebook/bic.h> +#include <facebook/yosemite_sensor.h> +#endif +#ifdef CONFIG_WEDGE +#include <facebook/wedge_eeprom.h> +#endif + +#include "watchdog.h" + +/* Sensor definitions */ + +#ifdef CONFIG_WEDGE +#define INTERNAL_TEMPS(x) ((x) * 1000) // stored a C * 1000 +#define EXTERNAL_TEMPS(x) ((x) / 1000) +#elif CONFIG_YOSEMITE +#define INTERNAL_TEMPS(x) (x) +#define EXTERNAL_TEMPS(x) (x) +#define TOTAL_1S_SERVERS 4 +#endif + +#define I2C_BUS_3_DIR "/sys/class/i2c-adapter/i2c-3/" +#define I2C_BUS_4_DIR "/sys/class/i2c-adapter/i2c-4/" + +#define INTAKE_TEMP_DEVICE I2C_BUS_3_DIR "3-0048" +#define T2_TEMP_DEVICE I2C_BUS_3_DIR "3-0049" +#define EXHAUST_TEMP_DEVICE I2C_BUS_3_DIR "3-004a" +#define USERVER_TEMP_DEVICE I2C_BUS_4_DIR "4-0040" + +/* + * The sensor for the uServer CPU is not on the CPU itself, so it reads + * a little low. We are special casing this, but we should obviously + * be thinking about a way to generalize these tweaks, and perhaps + * the entire configuration. JSON file? + */ + +#ifdef CONFIG_WEDGE +#define USERVER_TEMP_FUDGE INTERNAL_TEMPS(10) +#else +#define USERVER_TEMP_FUDGE INTERNAL_TEMPS(1) +#endif + +#define BAD_TEMP INTERNAL_TEMPS(-60) + +#define BAD_READ_THRESHOLD 4 /* How many times can reads fail */ +#define FAN_FAILURE_THRESHOLD 4 /* How many times can a fan fail */ +#define FAN_SHUTDOWN_THRESHOLD 20 /* How long fans can be failed before */ + /* we just shut down the whole thing. */ + + +#define PWM_DIR "/sys/devices/platform/ast_pwm_tacho.0" + +#define PWM_UNIT_MAX 96 + +#define LARGEST_DEVICE_NAME 120 + +#define GPIO_USERVER_POWER_DIRECTION "/sys/class/gpio/gpio25/direction" +#define GPIO_USERVER_POWER "/sys/class/gpio/gpio25/value" +#define GPIO_T2_POWER_DIRECTION "/tmp/gpionames/T2_POWER_UP/direction" +#define GPIO_T2_POWER "/tmp/gpionames/T2_POWER_UP/value" + +#define GPIO_FAN0_LED "/sys/class/gpio/gpio53/value" +#define GPIO_FAN1_LED "/sys/class/gpio/gpio54/value" +#define GPIO_FAN2_LED "/sys/class/gpio/gpio55/value" +#define GPIO_FAN3_LED "/sys/class/gpio/gpio72/value" + +const char *fan_led[] = {GPIO_FAN0_LED, GPIO_FAN1_LED, + GPIO_FAN2_LED, GPIO_FAN3_LED}; + +#define FAN_LED_RED "0" +#define FAN_LED_BLUE "1" + +#define GPIO_PIN_ID "/sys/class/gpio/gpio%d/value" +#define REV_IDS 3 +#define GPIO_REV_ID_START 192 + +#define BOARD_IDS 4 +#define GPIO_BOARD_ID_START 160 + +/* + * With hardware revisions after 3, we use a different set of pins for + * the BOARD_ID. + */ + +#define REV_ID_NEW_BOARD_ID 3 +#define GPIO_BOARD_ID_START_NEW 166 + +#define REPORT_TEMP 720 /* Report temp every so many cycles */ + +/* Sensor limits and tuning parameters */ + +#define INTAKE_LIMIT INTERNAL_TEMPS(60) +#define T2_LIMIT INTERNAL_TEMPS(80) +#define USERVER_LIMIT INTERNAL_TEMPS(90) + +#define TEMP_TOP INTERNAL_TEMPS(70) +#define TEMP_BOTTOM INTERNAL_TEMPS(40) + +/* + * Toggling the fan constantly will wear it out (and annoy anyone who + * can hear it), so we'll only turn down the fan after the temperature + * has dipped a bit below the point at which we'd otherwise switch + * things up. + */ + +#define COOLDOWN_SLOP INTERNAL_TEMPS(6) + +#define WEDGE_FAN_LOW 35 +#define WEDGE_FAN_MEDIUM 50 +#define WEDGE_FAN_HIGH 70 +#define WEDGE_FAN_MAX 99 + +#define SIXPACK_FAN_LOW 35 +#define SIXPACK_FAN_MEDIUM 55 +#define SIXPACK_FAN_HIGH 75 +#define SIXPACK_FAN_MAX 99 + +/* + * Mapping physical to hardware addresses for fans; it's different for + * RPM measuring and PWM setting, naturally. Doh. + */ + +#ifdef CONFIG_WEDGE +int fan_to_rpm_map[] = {3, 2, 0, 1}; +int fan_to_pwm_map[] = {7, 6, 0, 1}; +#define FANS 4 +// Tacho offset between front and rear fans: +#define REAR_FAN_OFFSET 4 +#define BACK_TO_BACK_FANS +#else +int fan_to_rpm_map[] = {0, 1}; +int fan_to_pwm_map[] = {0, 1}; +#define FANS 2 +// Tacho offset between front and rear fans: +#define REAR_FAN_OFFSET 1 +#endif + + +/* + * The measured RPM of the fans doesn't match linearly to the requested + * rate. In addition, there are coaxially mounted fans, so the rear fans + * feed into the front fans. The rear fans will run slower since they're + * grabbing still air, and the front fants are getting an extra boost. + * + * We'd like to measure the fan RPM and compare it to the expected RPM + * so that we can detect failed fans, so we have a table (derived from + * hardware testing): + */ + +struct rpm_to_pct_map { + ushort pct; + ushort rpm; +}; + +#ifdef CONFIG_WEDGE +struct rpm_to_pct_map rpm_front_map[] = {{30, 6150}, + {35, 7208}, + {40, 8195}, + {45, 9133}, + {50, 10017}, + {55, 10847}, + {60, 11612}, + {65, 12342}, + {70, 13057}, + {75, 13717}, + {80, 14305}, + {85, 14869}, + {90, 15384}, + {95, 15871}, + {100, 16095}}; +#define FRONT_MAP_SIZE (sizeof(rpm_front_map) / sizeof(struct rpm_to_pct_map)) + +struct rpm_to_pct_map rpm_rear_map[] = {{30, 3911}, + {35, 4760}, + {40, 5587}, + {45, 6434}, + {50, 7295}, + {55, 8187}, + {60, 9093}, + {65, 10008}, + {70, 10949}, + {75, 11883}, + {80, 12822}, + {85, 13726}, + {90, 14690}, + {95, 15516}, + {100, 15897}}; +#define REAR_MAP_SIZE (sizeof(rpm_rear_map) / sizeof(struct rpm_to_pct_map)) +#else +struct rpm_to_pct_map rpm_map[] = {{30, 3413}, + {35, 3859}, + {40, 4305}, + {45, 4686}, + {50, 5032}, + {55, 5432}, + {60, 5991}, + {65, 6460}, + {70, 6927}, + {75, 7379}, + {80, 7733}, + {85, 8156}, + {90, 8599}, + {95, 9049}, + {100, 9265}}; +struct rpm_to_pct_map *rpm_front_map = rpm_map; +struct rpm_to_pct_map *rpm_rear_map = rpm_map; +#define MAP_SIZE (sizeof(rpm_map) / sizeof(struct rpm_to_pct_map)) +#define FRONT_MAP_SIZE MAP_SIZE +#define REAR_MAP_SIZE MAP_SIZE + +#endif + +#define FAN_FAILURE_OFFSET 30 + +int fan_low = WEDGE_FAN_LOW; +int fan_medium = WEDGE_FAN_MEDIUM; +int fan_high = WEDGE_FAN_HIGH; +int fan_max = WEDGE_FAN_MAX; +int total_fans = FANS; +int fan_offset = 0; + +int temp_bottom = TEMP_BOTTOM; +int temp_top = TEMP_TOP; + +int report_temp = REPORT_TEMP; +bool verbose = false; + +void usage() { + fprintf(stderr, + "fand [-v] [-l <low-pct>] [-m <medium-pct>] " + "[-h <high-pct>]\n" + "\t[-b <temp-bottom>] [-t <temp-top>] [-r <report-temp>]\n\n" + "\tlow-pct defaults to %d%% fan\n" + "\tmedium-pct defaults to %d%% fan\n" + "\thigh-pct defaults to %d%% fan\n" + "\ttemp-bottom defaults to %dC\n" + "\ttemp-top defaults to %dC\n" + "\treport-temp defaults to every %d measurements\n\n" + "fand compensates for uServer temperature reading %d degrees low\n" + "kill with SIGUSR1 to stop watchdog\n", + fan_low, + fan_medium, + fan_high, + EXTERNAL_TEMPS(temp_bottom), + EXTERNAL_TEMPS(temp_top), + report_temp, + EXTERNAL_TEMPS(USERVER_TEMP_FUDGE)); + exit(1); +} + +/* We need to open the device each time to read a value */ + +int read_device(const char *device, int *value) { + FILE *fp; + int rc; + + fp = fopen(device, "r"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device %s", device); + return err; + } + + rc = fscanf(fp, "%d", value); + fclose(fp); + + if (rc != 1) { + syslog(LOG_INFO, "failed to read device %s", device); + return ENOENT; + } else { + return 0; + } +} + +/* We need to open the device again each time to write a value */ + +int write_device(const char *device, const char *value) { + FILE *fp; + int rc; + + fp = fopen(device, "w"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device for write %s", device); + return err; + } + + rc = fputs(value, fp); + fclose(fp); + + if (rc < 0) { + syslog(LOG_INFO, "failed to write device %s", device); + return ENOENT; + } else { + return 0; + } +} + +#ifdef CONFIG_WEDGE +int read_temp(const char *device, int *value) { + char full_name[LARGEST_DEVICE_NAME + 1]; + + /* We set an impossible value to check for errors */ + *value = BAD_TEMP; + snprintf( + full_name, LARGEST_DEVICE_NAME, "%s/temp1_input", device); + return read_device(full_name, value); +} + +int read_gpio_value(const int id, const char *device, int *value) { + char full_name[LARGEST_DEVICE_NAME]; + + snprintf(full_name, LARGEST_DEVICE_NAME, device, id); + return read_device(full_name, value); +} + +int read_gpio_values(const int start, const int count, + const char *device, int *result) { + int status = 0; + int value; + + *result = 0; + for (int i = 0; i < count; i++) { + status |= read_gpio_value(start + i, GPIO_PIN_ID, &value); + *result |= value << i; + } + return status; +} + +int read_ids(int *rev_id, int *board_id) { + int status = 0; + int value; + + status = read_gpio_values(GPIO_REV_ID_START, REV_IDS, GPIO_PIN_ID, rev_id); + if (status != 0) { + syslog(LOG_INFO, "failed to read rev_id"); + return status; + } + + int board_id_start; + if (*rev_id >= REV_ID_NEW_BOARD_ID) { + board_id_start = GPIO_BOARD_ID_START_NEW; + } else { + board_id_start = GPIO_BOARD_ID_START; + } + + status = read_gpio_values(board_id_start, BOARD_IDS, GPIO_PIN_ID, board_id); + if (status != 0) { + syslog(LOG_INFO, "failed to read board_id"); + } + return status; +} + +bool is_two_fan_board(bool verbose) { + struct wedge_eeprom_st eeprom; + /* Retrieve the board type from EEPROM */ + if (wedge_eeprom_parse(NULL, &eeprom) == 0) { + /* able to parse EEPROM */ + if (verbose) { + syslog(LOG_INFO, "board type is %s", eeprom.fbw_location); + } + /* only WEDGE is NOT two-fan board */ + return strncasecmp(eeprom.fbw_location, "wedge", + sizeof(eeprom.fbw_location)); + } else { + int status; + int board_id = 0; + int rev_id = 0; + /* + * Could not parse EEPROM. Most likely, it is an old HW without EEPROM. + * In this case, use board ID to distinguish if it is wedge or 6-pack. + */ + status = read_ids(&rev_id, &board_id); + if (verbose) { + syslog(LOG_INFO, "rev ID %d, board id %d", rev_id, board_id); + } + if (status == 0 && board_id != 0xf) { + return true; + } else { + return false; + } + } +} +#endif + +int read_fan_value(const int fan, const char *device, int *value) { + char device_name[LARGEST_DEVICE_NAME]; + char output_value[LARGEST_DEVICE_NAME]; + char full_name[LARGEST_DEVICE_NAME]; + + snprintf(device_name, LARGEST_DEVICE_NAME, device, fan); + snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", PWM_DIR, device_name); + return read_device(full_name, value); +} + +int write_fan_value(const int fan, const char *device, const int value) { + char full_name[LARGEST_DEVICE_NAME]; + char device_name[LARGEST_DEVICE_NAME]; + char output_value[LARGEST_DEVICE_NAME]; + + snprintf(device_name, LARGEST_DEVICE_NAME, device, fan); + snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", PWM_DIR, device_name); + snprintf(output_value, LARGEST_DEVICE_NAME, "%d", value); + return write_device(full_name, output_value); +} + +/* Return fan speed as a percentage of maximum -- not necessarily linear. */ + +int fan_rpm_to_pct(const struct rpm_to_pct_map *table, + const int table_len, + int rpm) { + int i; + + for (i = 0; i < table_len; i++) { + if (table[i].rpm > rpm) { + break; + } + } + + /* + * If the fan RPM is lower than the lowest value in the table, + * we may have a problem -- fans can only go so slow, and it might + * have stopped. In this case, we'll return an interpolated + * percentage, as just returning zero is even more problematic. + */ + + if (i == 0) { + return (rpm * table[i].pct) / table[i].rpm; + } else if (i == table_len) { // Fell off the top? + return table[i - 1].pct; + } + + // Interpolate the right percentage value: + + int percent_diff = table[i].pct - table[i - 1].pct; + int rpm_diff = table[i].rpm - table[i - 1].rpm; + int fan_diff = table[i].rpm - rpm; + + return table[i].pct - (fan_diff * percent_diff / rpm_diff); +} + +int fan_speed_okay(const int fan, const int speed, const int slop) { + int front_fan, rear_fan; + int front_pct, rear_pct; + int real_fan; + int okay; + + /* + * The hardware fan numbers are different from the physical order + * in the box, so we have to map them: + */ + + real_fan = fan_to_rpm_map[fan]; + + front_fan = 0; + read_fan_value(real_fan, "tacho%d_rpm", &front_fan); + front_pct = fan_rpm_to_pct(rpm_front_map, FRONT_MAP_SIZE, front_fan); +#ifdef BACK_TO_BACK_FANS + rear_fan = 0; + read_fan_value(real_fan + REAR_FAN_OFFSET, "tacho%d_rpm", &rear_fan); + rear_pct = fan_rpm_to_pct(rpm_rear_map, REAR_MAP_SIZE, rear_fan); +#endif + + + /* + * If the fans are broken, the measured rate will be rather + * different from the requested rate, and we can turn up the + * rest of the fans to compensate. The slop is the percentage + * of error that we'll tolerate. + * + * XXX: I suppose that we should only measure negative values; + * running too fast isn't really a problem. + */ + +#ifdef BACK_TO_BACK_FANS + okay = (abs(front_pct - speed) * 100 / speed < slop && + abs(rear_pct - speed) * 100 / speed < slop); +#else + okay = (abs(front_pct - speed) * 100 / speed < slop); +#endif + + if (!okay || verbose) { + syslog(!okay ? LOG_ALERT : LOG_INFO, +#ifdef BACK_TO_BACK_FANS + "fan %d rear %d (%d%%), front %d (%d%%), expected %d", +#else + "fan %d %d RPM (%d%%), expected %d", +#endif + fan, +#ifdef BACK_TO_BACK_FANS + rear_fan, + rear_pct, +#endif + front_fan, + front_pct, + speed); + } + + return okay; +} + +/* Set fan speed as a percentage */ + +int write_fan_speed(const int fan, const int value) { + /* + * The hardware fan numbers for pwm control are different from + * both the physical order in the box, and the mapping for reading + * the RPMs per fan, above. + */ + + int real_fan = fan_to_pwm_map[fan]; + + if (value == 0) { + return write_fan_value(real_fan, "pwm%d_en", 0); + } else { + int unit = value * PWM_UNIT_MAX / 100; + int status; + + if (unit == PWM_UNIT_MAX) + unit = 0; + + if ((status = write_fan_value(real_fan, "pwm%d_type", 0)) != 0 || + (status = write_fan_value(real_fan, "pwm%d_rising", 0)) != 0 || + (status = write_fan_value(real_fan, "pwm%d_falling", unit)) != 0 || + (status = write_fan_value(real_fan, "pwm%d_en", 1)) != 0) { + return status; + } + } +} + +/* Set up fan LEDs */ + +int write_fan_led(const int fan, const char *color) +{ +#ifdef CONFIG_WEDGE + return write_device(fan_led[fan], color); +#else + return 0; +#endif +} + +int server_shutdown(const char *why) { + int fan; + for (fan = 0; fan < total_fans; fan++) { + write_fan_speed(fan + fan_offset, fan_max); + } + + syslog(LOG_EMERG, "Shutting down: %s", why); + write_device(GPIO_USERVER_POWER_DIRECTION, "out"); + write_device(GPIO_USERVER_POWER, "0"); +#ifdef CONFIG_WEDGE + /* + * Putting T2 in reset generates a non-maskable interrupt to uS, + * the kernel running on uS might panic depending on its version. + * sleep 5s here to make sure uS is completely down. + */ + sleep(5); + + if (write_device(GPIO_T2_POWER_DIRECTION, "out") || + write_device(GPIO_T2_POWER, "1")) { + /* + * We're here because something has gone badly wrong. If we + * didn't manage to shut down the T2, cut power to the whole box, + * using the PMBus OPERATION register. This will require a power + * cycle (removal of both power inputs) to recover. + */ + syslog(LOG_EMERG, "T2 power off failed; turning off via ADM1278"); + system("rmmod adm1275"); + system("i2cset -y 12 0x10 0x01 00"); + } + +#else + // TODO(7088822): try throttling, then shutting down server. + syslog(LOG_EMERG, "Need to implement actual shutdown!\n"); +#endif + + /* + * We have to stop the watchdog, or the system will be automatically + * rebooted some seconds after fand exits (and stops kicking the + * watchdog). + */ + + stop_watchdog(); + + sleep(2); + exit(2); +} + +/* Gracefully shut down on receipt of a signal */ + +void fand_interrupt(int sig) +{ + int fan; + for (fan = 0; fan < total_fans; fan++) { + write_fan_speed(fan + fan_offset, fan_max); + } + + syslog(LOG_ALERT, "Shutting down fand on signal %s", strsignal(sig)); + if (sig == SIGUSR1) { + stop_watchdog(); + } + exit(3); +} + +int main(int argc, char **argv) { + /* Sensor values */ + +#ifdef CONFIG_WEDGE + int intake_temp; + int exhaust_temp; + int t2_temp; + int userver_temp; +#else + float intake_temp; + float exhaust_temp; + float userver_temp; +#endif + + int fan_speed = fan_high; + int bad_reads = 0; + int fan_failure = 0; + int fan_speed_changes = 0; + int old_speed; + + int fan_bad[FANS]; + int fan; + + unsigned log_count = 0; // How many times have we logged our temps? + int opt; + int prev_fans_bad = 0; + + struct sigaction sa; + + sa.sa_handler = fand_interrupt; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGUSR1, &sa, NULL); + + // Start writing to syslog as early as possible for diag purposes. + + openlog("fand", LOG_CONS, LOG_DAEMON); + +#ifdef CONFIG_WEDGE + if (is_two_fan_board(false)) { + /* Alternate, two fan configuration */ + total_fans = 2; + fan_offset = 2; /* fan 3 is the first */ + + fan_low = SIXPACK_FAN_LOW; + fan_medium = SIXPACK_FAN_MEDIUM; + fan_high = SIXPACK_FAN_HIGH; + fan_max = SIXPACK_FAN_MAX; + fan_speed = fan_high; + } +#endif + + while ((opt = getopt(argc, argv, "l:m:h:b:t:r:v")) != -1) { + switch (opt) { + case 'l': + fan_low = atoi(optarg); + break; + case 'm': + fan_medium = atoi(optarg); + break; + case 'h': + fan_high = atoi(optarg); + break; + case 'b': + temp_bottom = INTERNAL_TEMPS(atoi(optarg)); + break; + case 't': + temp_top = INTERNAL_TEMPS(atoi(optarg)); + break; + case 'r': + report_temp = atoi(optarg); + break; + case 'v': + verbose = true; + break; + default: + usage(); + break; + } + } + + if (optind > argc) { + usage(); + } + + if (temp_bottom > temp_top) { + fprintf(stderr, + "Should temp-bottom (%d) be higher than " + "temp-top (%d)? Starting anyway.\n", + EXTERNAL_TEMPS(temp_bottom), + EXTERNAL_TEMPS(temp_top)); + } + + if (fan_low > fan_medium || fan_low > fan_high || fan_medium > fan_high) { + fprintf(stderr, + "fan RPMs not strictly increasing " + "-- %d, %d, %d, starting anyway\n", + fan_low, + fan_medium, + fan_high); + } + + daemon(1, 0); + + if (verbose) { + syslog(LOG_DEBUG, "Starting up; system should have %d fans.", + total_fans); + } + + for (fan = 0; fan < total_fans; fan++) { + fan_bad[fan] = 0; + write_fan_speed(fan + fan_offset, fan_speed); + write_fan_led(fan + fan_offset, FAN_LED_BLUE); + } + +#ifdef CONFIG_YOSEMITE + /* Ensure that we can read from sensors before proceeding. */ + + while (yosemite_sensor_read(1, BIC_SENSOR_SOC_TEMP, &userver_temp)) + syslog(LOG_DEBUG, "Failed reading of SOC_TEMP."); +#endif + + /* Start watchdog in manual mode */ + start_watchdog(0); + + /* Set watchdog to persistent mode so timer expiry will happen independent + * of this process's liveliness. */ + set_persistent_watchdog(WATCHDOG_SET_PERSISTENT); + + sleep(5); /* Give the fans time to come up to speed */ + + while (1) { + int max_temp; + old_speed = fan_speed; + + /* Read sensors */ + +#ifdef CONFIG_WEDGE + read_temp(INTAKE_TEMP_DEVICE, &intake_temp); + read_temp(EXHAUST_TEMP_DEVICE, &exhaust_temp); + read_temp(T2_TEMP_DEVICE, &t2_temp); + read_temp(USERVER_TEMP_DEVICE, &userver_temp); + + /* + * uServer can be powered down, but all of the rest of the sensors + * should be readable at any time. + */ + + if ((intake_temp == BAD_TEMP || exhaust_temp == BAD_TEMP || + t2_temp == BAD_TEMP)) { + bad_reads++; + } +#else + userver_temp = BAD_TEMP; + if (yosemite_sensor_read(1, SP_SENSOR_INLET_TEMP, &intake_temp) || + yosemite_sensor_read(1, SP_SENSOR_OUTLET_TEMP, &exhaust_temp)) + bad_reads++; + + /* + * There are a number of 1S servers; any or all of them + * could be powered off and returning no values. Ignore these + * invalid values. + */ + for (int node = 1; node <= TOTAL_1S_SERVERS; node++) { + float new_temp; + if (!yosemite_sensor_read(node, BIC_SENSOR_SOC_TEMP, &new_temp)) { + if (userver_temp < new_temp) { + userver_temp = new_temp; + } + } + } +#endif + + if (bad_reads > BAD_READ_THRESHOLD) { + server_shutdown("Some sensors couldn't be read"); + } + + if (log_count++ % report_temp == 0) { + syslog(LOG_DEBUG, +#ifdef CONFIG_WEDGE + "Temp intake %d, t2 %d, " + " userver %d, exhaust %d, " + "fan speed %d, speed changes %d", +#else + "Temp intake %f, max server %f, exhaust %f, " + "fan speed %d, speed changes %d", +#endif + intake_temp, +#ifdef CONFIG_WEDGE + t2_temp, +#endif + userver_temp, + exhaust_temp, + fan_speed, + fan_speed_changes); + } + + /* Protection heuristics */ + + if (intake_temp > INTAKE_LIMIT) { + server_shutdown("Intake temp limit reached"); + } + +#ifdef CONFIG_WEDGE + if (t2_temp > T2_LIMIT) { + server_shutdown("T2 temp limit reached"); + } +#endif + + if (userver_temp + USERVER_TEMP_FUDGE > USERVER_LIMIT) { + server_shutdown("uServer temp limit reached"); + } + + /* + * Calculate change needed -- we should eventually + * do something more sophisticated, like PID. + * + * We should use the intake temperature to adjust this + * as well. + */ + +#ifdef CONFIG_WEDGE + if (t2_temp > userver_temp + USERVER_TEMP_FUDGE) { + max_temp = t2_temp; + } else { + max_temp = userver_temp + USERVER_TEMP_FUDGE; + } +#else + /* Yosemite could have no servers turned on, so ignore that case. */ + if (userver_temp + USERVER_TEMP_FUDGE > exhaust_temp) { + max_temp = userver_temp + USERVER_TEMP_FUDGE; + } else { + max_temp = exhaust_temp; + } +#endif + + /* + * If recovering from a fan problem, spin down fans gradually in case + * temperatures are still high. Gradual spin down also reduces wear on + * the fans. + */ + if (fan_speed == fan_max) { + if (fan_failure == 0) { + fan_speed = fan_high; + } + } else if (fan_speed == fan_high) { + if (max_temp + COOLDOWN_SLOP < temp_top) { + fan_speed = fan_medium; + } + } else if (fan_speed == fan_medium) { + if (max_temp > temp_top) { + fan_speed = fan_high; + } else if (max_temp + COOLDOWN_SLOP < temp_bottom) { + fan_speed = fan_low; + } + } else {/* low */ + if (max_temp > temp_bottom) { + fan_speed = fan_medium; + } + } + + /* + * Update fans only if there are no failed ones. If any fans failed + * earlier, all remaining fans should continue to run at max speed. + */ + + if (fan_failure == 0 && fan_speed != old_speed) { + syslog(LOG_NOTICE, + "Fan speed changing from %d to %d", + old_speed, + fan_speed); + fan_speed_changes++; + for (fan = 0; fan < total_fans; fan++) { + write_fan_speed(fan + fan_offset, fan_speed); + } + } + + /* + * Wait for some change. Typical I2C temperature sensors + * only provide a new value every second and a half, so + * checking again more quickly than that is a waste. + * + * We also have to wait for the fan changes to take effect + * before measuring them. + */ + + sleep(5); + + /* Check fan RPMs */ + + for (fan = 0; fan < total_fans; fan++) { + /* + * Make sure that we're within some percentage + * of the requested speed. + */ + if (fan_speed_okay(fan + fan_offset, fan_speed, FAN_FAILURE_OFFSET)) { + if (fan_bad[fan] > FAN_FAILURE_THRESHOLD) { + write_fan_led(fan + fan_offset, FAN_LED_BLUE); + syslog(LOG_NOTICE, + "Fan %d has recovered", + fan); + } + fan_bad[fan] = 0; + } else { + fan_bad[fan]++; + } + } + + fan_failure = 0; + for (fan = 0; fan < total_fans; fan++) { + if (fan_bad[fan] > FAN_FAILURE_THRESHOLD) { + fan_failure++; + write_fan_led(fan + fan_offset, FAN_LED_RED); + } + } + + if (fan_failure > 0) { + if (prev_fans_bad != fan_failure) { + syslog(LOG_ALERT, "%d fans failed", fan_failure); + } + + /* + * If fans are bad, we need to blast all of the + * fans at 100%; we don't bother to turn off + * the bad fans, in case they are all that is left. + * + * Note that we have a temporary bug with setting fans to + * 100% so we only do fan_max = 99%. + */ + + fan_speed = fan_max; + for (fan = 0; fan < total_fans; fan++) { + write_fan_speed(fan + fan_offset, fan_speed); + } + + if (fan_failure == total_fans) { + int count = 0; + for (fan = 0; fan < total_fans; fan++) { + if (fan_bad[fan] > FAN_SHUTDOWN_THRESHOLD) + count++; + } + if (count == total_fans) { + server_shutdown("all fans are bad for more than 12 cycles"); + } + } + + + /* + * Fans can be hot swapped and replaced; in which case the fan daemon + * will automatically detect the new fan and (assuming the new fan isn't + * itself faulty), automatically readjust the speeds for all fans down + * to a more suitable rpm. The fan daemon does not need to be restarted. + */ + } + + /* Suppress multiple warnings for similar number of fan failures. */ + prev_fans_bad = fan_failure; + + /* if everything is fine, restart the watchdog countdown. If this process + * is terminated, the persistent watchdog setting will cause the system + * to reboot after the watchdog timeout. */ + kick_watchdog(); + } +} diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp b/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp new file mode 100644 index 0000000..ebb390a --- /dev/null +++ b/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.cpp @@ -0,0 +1,201 @@ +/* + * watchdog + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "watchdog.h" + +#include <errno.h> +#include <fcntl.h> +#include <pthread.h> +#include <syslog.h> +#include <unistd.h> + +#define WATCHDOG_START_KEY "x" +#define WATCHDOG_STOP_KEY "X" +/* The "magic close" character (as defined in Linux watchdog specs). */ +#define WATCHDOG_PERSISTENT_KEY "V" +#define WATCHDOG_NON_PERSISTENT_KEY "a" + +static int watchdog_dev = -1; + +/* This is needed to prevent rapid consecutive stop/start watchdog calls from + * generating multiple threads. */ +static int watchdog_started = 0; + +static const char* watchdog_kick_key = WATCHDOG_PERSISTENT_KEY; +static pthread_t watchdog_tid; +static pthread_mutex_t watchdog_lock = PTHREAD_MUTEX_INITIALIZER; + +/* Forward declarations. */ +static void* watchdog_thread(void* args); +static int kick_watchdog_unsafe(); + +/* + * When started, this background thread will constantly reset the watchdog + * at every 5 second interval. + */ + +static void* watchdog_thread(void* args) { + + pthread_detach(pthread_self()); + + /* Make sure another instance of the thread hasn't already been started. */ + pthread_mutex_lock(&watchdog_lock); + if (watchdog_started) { + goto done; + } else { + watchdog_started = 1; + } + pthread_mutex_unlock(&watchdog_lock); + + /* Actual loop for refreshing the watchdog timer. */ + while (1) { + pthread_mutex_lock(&watchdog_lock); + if (watchdog_dev != -1) { + kick_watchdog_unsafe(); + } else { + break; + } + pthread_mutex_unlock(&watchdog_lock); + sleep(5); + } + + /* Broke out of loop because watchdog was stopped. */ + watchdog_started = 0; +done: + pthread_mutex_unlock(&watchdog_lock); + return NULL; +} + +/* + * Starts the watchdog timer. timer counts down and restarts the ARM chip + * upon timeout. use kick_watchdog() to restart the timer. + * + * Returns: 1 on success; 0 otherwise. + */ + +int start_watchdog(const int auto_mode) { + int status; + + pthread_mutex_lock(&watchdog_lock); + + /* Don't start the watchdog again if it has already been started. */ + if (watchdog_dev != -1) { + while ((status = write(watchdog_dev, WATCHDOG_START_KEY, 1)) == 0 + && errno == EINTR); + pthread_mutex_unlock(&watchdog_lock); + syslog(LOG_ALERT, "system watchdog already started.\n"); + return 0; + } + + while (((watchdog_dev = open("/dev/watchdog", O_WRONLY)) == -1) && + errno == EINTR); + + /* Fail if watchdog device is invalid or if the user asked for auto + * mode and the thread failed to spawn. */ + if ((watchdog_dev == -1) || + (auto_mode == 1 && watchdog_started == 0 && + pthread_create(&watchdog_tid, NULL, watchdog_thread, NULL) != 0)) { + goto fail; + } + + while ((status = write(watchdog_dev, WATCHDOG_START_KEY, 1)) == 0 + && errno == EINTR); + pthread_mutex_unlock(&watchdog_lock); + syslog(LOG_INFO, "system watchdog started.\n"); + return 1; + +fail: + if (watchdog_dev != -1) { + close(watchdog_dev); + watchdog_dev = -1; + } + + pthread_mutex_unlock(&watchdog_lock); + syslog(LOG_ALERT, "system watchdog failed to start!\n"); + return 0; +} + +/* + * Toggles between watchdog persistent modes. In persistent mode, the watchdog + * timer will continue to tick even after process shutdown. Under non- + * persistent mode, the watchdog timer will automatically be disabled when the + * process shuts down. + */ +void set_persistent_watchdog(enum watchdog_persistent_en persistent) { + switch (persistent) { + case WATCHDOG_SET_PERSISTENT: + watchdog_kick_key = WATCHDOG_PERSISTENT_KEY; + break; + default: + watchdog_kick_key = WATCHDOG_NON_PERSISTENT_KEY; + break; + } + kick_watchdog(); +} + +/* + * Restarts the countdown timer on the watchdog, delaying restart by another + * timeout period (default: 11 seconds as configured in the device driver). + * + * This function assumes the watchdog lock has already been acquired and is + * only used internally within the watchdog code. + * + * Returns 1 on success; 0 or -1 indicates failure (check errno). + */ + +static int kick_watchdog_unsafe() { + int status = 0; + if (watchdog_dev != -1) { + while ((status = write(watchdog_dev, watchdog_kick_key, 1)) == 0 + && errno == EINTR); + } + return status; +} + +/* + * Acquires the watchdog lock and resets the watchdog atomically. For use by + * library users. + */ + +int kick_watchdog() { + int result; + pthread_mutex_lock(&watchdog_lock); + result = kick_watchdog_unsafe(); + pthread_mutex_unlock(&watchdog_lock); + + return result; +} + +/* Shuts down the watchdog gracefully and disables the watchdog timer so that + * restarts no longer happen. + */ + +void stop_watchdog() { + int status; + pthread_mutex_lock(&watchdog_lock); + if (watchdog_dev != -1) { + while ((status = write(watchdog_dev, WATCHDOG_STOP_KEY, 1)) == 0 + && errno == EINTR); + close(watchdog_dev); + watchdog_dev = -1; + syslog(LOG_INFO, "system watchdog stopped.\n"); + } + pthread_mutex_unlock(&watchdog_lock); +} diff --git a/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.h b/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.h new file mode 100644 index 0000000..19b9944 --- /dev/null +++ b/common/recipes-core/fan-ctrl/fan-ctrl/watchdog.h @@ -0,0 +1,60 @@ +/* + * watchdog + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Utility library to handle the aspeed watchdog. Only one watchdog + * should be in use at any time throughout the entire system (multiple users + * will not cause adverse effects but the behavior of the watchdog becomes + * undefined). + * + * The watchdog can be started in either manual or automatic mode. In manual + * mode, the watchdog has to be constantly reset by the user via the + * kick_watchdog() function. Under automatic mode, the watchdog will + * run in a separate thread and reset the timer on its own so no intervention + * is required from the user. + * + * In both modes, the watchdog timer will not stop when the process is + * terminated, unless a call to stop_watchdog() has been made beforehand, or + * if the user runs in manual mode and uses a non persistent watchdog kick. + * + * The default timeout for the watchdog is 11 seconds. When this time period + * elapses, the ARM chip is restarted and the kernel is rebooted. Other + * hardware state is not reset, so this may introduce strange behavior on + * reboot (example: an I2C bus may be left in the open state, triggering + * constant interrupts). In rare cases, this could result in the kernel + * failing to fully restart itself and thus preclude the possibility of + * reinitializing the watchdog timer. Someone will then have to go over and + * physically restart the machine. + * + * The alternative to the soft reset is to request the watchdog device driver + * for a hard reset on timeout. However this will stop the fans. If the + * kernel fails to fully boot and restart the fan daemon, the system could + * overheat. For this reason, we've chosen to take the risk of a stuck soft + * reset instead. + * + */ + +/* Forward declarations. */ +int start_watchdog(const int auto_mode); +enum watchdog_persistent_en { + WATCHDOG_SET_PERSISTENT, + WATCHDOG_SET_NONPERSISTENT, +}; +void set_persistent_watchdog(enum watchdog_persistent_en persistent); +int kick_watchdog(); +void stop_watchdog(); diff --git a/common/recipes-core/fan-ctrl/fan-ctrl_0.1.bb b/common/recipes-core/fan-ctrl/fan-ctrl_0.1.bb new file mode 100644 index 0000000..1abfaaa --- /dev/null +++ b/common/recipes-core/fan-ctrl/fan-ctrl_0.1.bb @@ -0,0 +1,61 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "Fan controller" +DESCRIPTION = "The utilities to control fan." +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://fand.cpp;beginline=6;endline=18;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI = "file://README \ + file://Makefile \ + file://fand.cpp \ + file://watchdog.h \ + file://watchdog.cpp \ + " + +S = "${WORKDIR}" + +binfiles = "fand \ + " + +otherfiles = "README" + +pkgdir = "fan_ctrl" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${dst}/$f + ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f + done + for f in ${otherfiles}; do + install -m 644 $f ${dst}/$f + done +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/fan_ctrl ${prefix}/local/bin" + +# Inhibit complaints about .debug directories for the fand binary: + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-core/fruid/files/Makefile b/common/recipes-core/fruid/files/Makefile new file mode 100644 index 0000000..5c6aff4 --- /dev/null +++ b/common/recipes-core/fruid/files/Makefile @@ -0,0 +1,26 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +all: fruid-util + +fruid: fruid-util.c + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o fruid-util diff --git a/common/recipes-core/fruid/files/fruid-util.c b/common/recipes-core/fruid/files/fruid-util.c new file mode 100644 index 0000000..3c8d2e1 --- /dev/null +++ b/common/recipes-core/fruid/files/fruid-util.c @@ -0,0 +1,145 @@ +/* + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <openbmc/fruid.h> +#include <openbmc/pal.h> + +/* Print the FRUID in detail */ +void print_fruid_info(fruid_info_t *fruid, const char *name) +{ + /* Print format */ + printf("%-27s: %s", "\nFRU Information", + name /* Name of the FRU device */ ); + printf("%-27s: %s", "\n---------------", "------------------"); + + if (fruid->chassis.flag) { + printf("%-27s: %s", "\nChassis Type",fruid->chassis.type_str); + printf("%-27s: %s", "\nChassis Part",fruid->chassis.part); + printf("%-27s: %s", "\nChassis Serial Number",fruid->chassis.serial); + printf("%-27s: %s", "\nChassis Custom Data",fruid->chassis.custom); + } + + if (fruid->board.flag) { + printf("%-27s: %s", "\nBoard Mfg Time",fruid->board.mfg_time_str); + printf("%-27s: %s", "\nBoard Manufacturer",fruid->board.mfg); + printf("%-27s: %s", "\nBoard Name",fruid->board.name); + printf("%-27s: %s", "\nBoard Serial Number",fruid->board.serial); + printf("%-27s: %s", "\nBoard Part",fruid->board.part); + printf("%-27s: %s", "\nBoard FRU ID",fruid->board.fruid); + printf("%-27s: %s", "\nBoard Custom Data",fruid->board.custom); + } + + if (fruid->product.flag) { + printf("%-27s: %s", "\nProduct Manufacturer",fruid->product.mfg); + printf("%-27s: %s", "\nProduct Name",fruid->product.name); + printf("%-27s: %s", "\nProduct Part",fruid->product.part); + printf("%-27s: %s", "\nProduct Version",fruid->product.version); + printf("%-27s: %s", "\nProduct Serial Number",fruid->product.serial); + printf("%-27s: %s", "\nProduct Asset Tag",fruid->product.asset_tag); + printf("%-27s: %s", "\nProduct FRU ID",fruid->product.fruid); + printf("%-27s: %s", "\nProduct Custom Data",fruid->product.custom); + } + + printf("\n"); +} + +/* Populate and print fruid_info by parsing the fru's binary dump */ +void get_fruid_info(uint8_t fru, char *path, char* name) { + int ret; + fruid_info_t fruid; + + ret = fruid_parse(path, &fruid); + if (ret) { + fprintf(stderr, "Failed print FRUID for %s\nCheck syslog for errors!\n", + name); + } else { + print_fruid_info(&fruid, name); + free_fruid_info(&fruid); + } + +} + +static int +print_usage() { + printf("Usage: fruid-util [ %s ]\n", pal_fru_list); +} + +/* Utility to just print the FRUID */ +int main(int argc, char * argv[]) { + + int ret; + uint8_t fru; + char path[64] = {0}; + char name[64] = {0}; + + if (argc != 2) { + print_usage(); + exit(-1); + } + + ret = pal_get_fru_id(argv[1], &fru); + if (ret < 0) { + print_usage(); + return ret; + } + + if (fru == 0) { + fru = 1; + while (fru <= MAX_NUM_FRUS) { + ret = pal_get_fruid_path(fru, path); + if (ret < 0) { + return ret; + } + + ret = pal_get_fruid_name(fru, name); + if (ret < 0) { + return ret; + } + + if (fru == FRU_NIC) { + printf("fruid-util does not support nic\n"); + exit(-1); + } + + get_fruid_info(fru, path, name); + + fru++; + } + } else { + ret = pal_get_fruid_path(fru, path); + if (ret < 0) { + return ret; + } + + ret = pal_get_fruid_name(fru, name); + if (ret < 0) { + return ret; + } + + if (fru == FRU_NIC) { + printf("fruid-util does not support nic\n"); + exit(-1); + } + + get_fruid_info(fru, path, name); + } + + return 0; +} diff --git a/common/recipes-core/fruid/fruid_0.1.bb b/common/recipes-core/fruid/fruid_0.1.bb new file mode 100644 index 0000000..604845f --- /dev/null +++ b/common/recipes-core/fruid/fruid_0.1.bb @@ -0,0 +1,55 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "IPMI FRUID Utilities" +DESCRIPTION = "Util for ipmi fruid" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://fruid-util.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +LDFLAGS = " -lfruid -lpal " +DEPENDS = "libfruid libpal " + +SRC_URI = "file://Makefile \ + file://fruid-util.c \ + " + +S = "${WORKDIR}" + +binfiles = "fruid-util \ + " + +pkgdir = "fruid" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${dst}/$f + ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f + done +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/fruid ${prefix}/local/bin" + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-core/ipmbd/files/Makefile b/common/recipes-core/ipmbd/files/Makefile new file mode 100644 index 0000000..719ccc3 --- /dev/null +++ b/common/recipes-core/ipmbd/files/Makefile @@ -0,0 +1,10 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +all: ipmbd + +ipmbd: ipmbd.o + $(CC) $(CFLAGS) -pthread -lrt -lipmi -std=gnu99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o ipmbd diff --git a/common/recipes-core/ipmbd/files/ipmbd.c b/common/recipes-core/ipmbd/files/ipmbd.c new file mode 100644 index 0000000..5ea5af3 --- /dev/null +++ b/common/recipes-core/ipmbd/files/ipmbd.c @@ -0,0 +1,843 @@ +/* + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * This module handles all the IPMB communication protocol + * Refer http://www.intel.com/content/www/us/en/servers/ipmi/ipmp-spec-v1-0.html + * for more information. + * + * IPMB packet format is described here for quick reference + * Request: + * <Responder Slave Address(rsSA)> + * <NetFn/ResponderLUN(Netfn/rsLUN)> + * <Header Checksum(hdrCksum)> + * <Requester Slave Address(rqSA)> + * <Requester Sequence Number/RequesterLUN(rqSeq/rqLUN> + * <Command> + * <Data[0..n]> + * <Data Checksum(dataCksum)> + * Response: + * <Requester Slave Address(rqSA)> + * <NetFn/RequesterLUN(Netfn/rqLUN)> + * <Header Checksum(hdrCksum)> + * <Responder Slave Address(rsSA)> + * <Requester Sequence Number/ResponderLUN(rqSeq/rsLUN> + * <Command> + * <Completion Code(CC)> + * <Data[0..n]> + * <Data Checksum(dataCksum)> + */ +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <string.h> +#include <syslog.h> +#include <pthread.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <stdint.h> +#include <mqueue.h> +#include <semaphore.h> + +#include "facebook/i2c-dev.h" +#include "openbmc/ipmi.h" +#include "openbmc/ipmb.h" + +//#define DEBUG 0 + +#define MAX_BYTES 255 + +#define MQ_IPMB_REQ "/mq_ipmb_req" +#define MQ_IPMB_RES "/mq_ipmb_res" +#define MQ_MAX_MSG_SIZE MAX_BYTES +#define MQ_MAX_NUM_MSGS 10 + +#define SEQ_NUM_MAX 64 + +#define I2C_RETRIES_MAX 3 + +// Structure for i2c file descriptor and socket +typedef struct _ipmb_sfd_t { + int fd; + int sock; +} ipmb_sfd_t; + +// Structure for sequence number and buffer +typedef struct _seq_buf_t { + bool in_use; // seq# is being used + uint8_t len; // buffer size + uint8_t *p_buf; // pointer to buffer + sem_t s_seq; // semaphore for thread sync. +} seq_buf_t; + +// Structure for holding currently used sequence number and +// array of all possible sequence number +typedef struct _ipmb_sbuf_t { + uint8_t curr_seq; // currently used seq# + seq_buf_t seq[SEQ_NUM_MAX]; //array of all possible seq# struct. +} ipmb_sbuf_t; + +// Global storage for holding IPMB sequence number and buffer +ipmb_sbuf_t g_seq; + +// mutex to protect global data access +pthread_mutex_t m_seq; + +pthread_mutex_t m_i2c; + +#ifdef CONFIG_YOSEMITE +// Returns the payload ID from IPMB bus routing +// Slot#1: bus#3, Slot#2: bus#1, Slot#3: bus#7, Slot#4: bus#5 +static uint8_t +get_payload_id(uint8_t bus_id) { + uint8_t payload_id = 0xFF; // Invalid payload ID + + switch(bus_id) { + case 1: + payload_id = 2; + break; + case 3: + payload_id = 1; + break; + case 5: + payload_id = 4; + break; + case 7: + payload_id = 3; + break; + default: + syslog(LOG_ALERT, "get_payload_id: Wrong bus ID\n"); + break; + } + + return payload_id; +} +#endif + +// Returns an unused seq# from all possible seq# +static uint8_t +seq_get_new(void) { + uint8_t ret = -1; + uint8_t index; + + pthread_mutex_lock(&m_seq); + + // Search for unused sequence number + index = g_seq.curr_seq; + do { + if (g_seq.seq[index].in_use == false) { + // Found it! + ret = index; + g_seq.seq[index].in_use = true; + g_seq.seq[index].len = 0; + break; + } + + if (++index == SEQ_NUM_MAX) { + index = 0; + } + } while (index != g_seq.curr_seq); + + // Update the current seq num + if (ret >= 0) { + if (++index == SEQ_NUM_MAX) { + index = 0; + } + g_seq.curr_seq = index; + } + + pthread_mutex_unlock(&m_seq); + + return ret; +} + +static int +i2c_open(uint8_t bus_num) { + int fd; + char fn[32]; + int rc; + + snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus_num); + fd = open(fn, O_RDWR); + if (fd == -1) { + syslog(LOG_ALERT, "Failed to open i2c device %s", fn); + return -1; + } + + rc = ioctl(fd, I2C_SLAVE, BRIDGE_SLAVE_ADDR); + if (rc < 0) { + syslog(LOG_ALERT, "Failed to open slave @ address 0x%x", BRIDGE_SLAVE_ADDR); + close(fd); + return -1; + } + + return fd; +} + +static int +i2c_write(int fd, uint8_t *buf, uint8_t len) { + struct i2c_rdwr_ioctl_data data; + struct i2c_msg msg; + int rc; + int i; + + memset(&msg, 0, sizeof(msg)); + + msg.addr = BRIDGE_SLAVE_ADDR; + msg.flags = 0; + msg.len = len; + msg.buf = buf; + + data.msgs = &msg; + data.nmsgs = 1; + + pthread_mutex_lock(&m_i2c); + + for (i = 0; i < I2C_RETRIES_MAX; i++) { + rc = ioctl(fd, I2C_RDWR, &data); + if (rc < 0) { + sleep(1); + continue; + } else { + break; + } + } + + if (rc < 0) { + syslog(LOG_ALERT, "Failed to do raw io"); + pthread_mutex_unlock(&m_i2c); + return -1; + } + + pthread_mutex_unlock(&m_i2c); + + return 0; +} + +static int +i2c_slave_open(uint8_t bus_num) { + int fd; + char fn[32]; + int rc; + struct i2c_rdwr_ioctl_data data; + struct i2c_msg msg; + uint8_t read_bytes[MAX_BYTES] = { 0 }; + + snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus_num); + fd = open(fn, O_RDWR); + if (fd == -1) { + syslog(LOG_ALERT, "Failed to open i2c device %s", fn); + return -1; + } + + memset(&msg, 0, sizeof(msg)); + + msg.addr = BMC_SLAVE_ADDR; + msg.flags = I2C_S_EN; + msg.len = 1; + msg.buf = read_bytes; + msg.buf[0] = 1; + + data.msgs = &msg; + data.nmsgs = 1; + + rc = ioctl(fd, I2C_SLAVE_RDWR, &data); + if (rc < 0) { + syslog(LOG_ALERT, "Failed to open slave @ address 0x%x", BMC_SLAVE_ADDR); + close(fd); + } + + return fd; +} + +static int +i2c_slave_read(int fd, uint8_t *buf, uint8_t *len) { + struct i2c_rdwr_ioctl_data data; + struct i2c_msg msg; + int rc; + + memset(&msg, 0, sizeof(msg)); + + msg.addr = BMC_SLAVE_ADDR; + msg.flags = 0; + msg.len = MAX_BYTES; + msg.buf = buf; + + data.msgs = &msg; + data.nmsgs = 1; + + rc = ioctl(fd, I2C_SLAVE_RDWR, &data); + if (rc < 0) { + return -1; + } + + *len = msg.len; + + return 0; +} + +// Thread to handle new requests +static void* +ipmb_req_handler(void *bus_num) { + uint8_t *bnum = (uint8_t*) bus_num; + mqd_t mq; + int fd; + int i; + + //Buffers for IPMB transport + uint8_t rxbuf[MQ_MAX_MSG_SIZE] = {0}; + uint8_t txbuf[MQ_MAX_MSG_SIZE] = {0}; + ipmb_req_t *p_ipmb_req; + ipmb_res_t *p_ipmb_res; + + p_ipmb_req = (ipmb_req_t*) rxbuf; + p_ipmb_res = (ipmb_res_t*) txbuf; + + //Buffers for IPMI Stack + uint8_t rbuf[MQ_MAX_MSG_SIZE] = {0}; + uint8_t tbuf[MQ_MAX_MSG_SIZE] = {0}; + ipmi_mn_req_t *p_ipmi_mn_req; + ipmi_res_t *p_ipmi_res; + + p_ipmi_mn_req = (ipmi_mn_req_t*) rbuf; + p_ipmi_res = (ipmi_res_t*) tbuf; + + uint8_t rlen = 0; + uint8_t tlen = 0; + + char mq_ipmb_req[64] = {0}; + + sprintf(mq_ipmb_req, "%s_%d", MQ_IPMB_REQ, *bnum); + + // Open Queue to receive requests + mq = mq_open(mq_ipmb_req, O_RDONLY); + if (mq == (mqd_t) -1) { + return NULL; + } + + // Open the i2c bus for sending response + fd = i2c_open(*bnum); + if (fd < 0) { + syslog(LOG_ALERT, "i2c_open failure\n"); + close(mq); + return NULL; + } + + // Loop to process incoming requests + while (1) { + if ((rlen = mq_receive(mq, rxbuf, MQ_MAX_MSG_SIZE, NULL)) < 0) { + sleep(1); + continue; + } + +#ifdef DEBUG + syslog(LOG_ALERT, "Received Request of %d bytes\n", rlen); + for (i = 0; i < rlen; i++) { + syslog(LOG_ALERT, "0x%X", rxbuf[i]); + } +#endif + + // Create IPMI request from IPMB data +#ifdef CONFIG_YOSEMITE + p_ipmi_mn_req->payload_id = get_payload_id(*bnum); +#else + // For single node systems use payload ID as 1 + p_ipmi_mn_req->payload_id = 0x1; +#endif + p_ipmi_mn_req->netfn_lun = p_ipmb_req->netfn_lun; + p_ipmi_mn_req->cmd = p_ipmb_req->cmd; + + memcpy(p_ipmi_mn_req->data, p_ipmb_req->data, rlen - IPMB_HDR_SIZE - IPMI_REQ_HDR_SIZE); + + // Send to IPMI stack and get response + // Additional byte as we are adding and passing payload ID for MN support + lib_ipmi_handle(rbuf, rlen - IPMB_HDR_SIZE + 1, tbuf, &tlen); + + // Populate IPMB response data from IPMB request + p_ipmb_res->req_slave_addr = p_ipmb_req->req_slave_addr; + p_ipmb_res->res_slave_addr = p_ipmb_req->res_slave_addr; + p_ipmb_res->cmd = p_ipmb_req->cmd; + p_ipmb_res->seq_lun = p_ipmb_req->seq_lun; + + // Add IPMI response data + p_ipmb_res->netfn_lun = p_ipmi_res->netfn_lun; + p_ipmb_res->cc = p_ipmi_res->cc; + + memcpy(p_ipmb_res->data, p_ipmi_res->data, tlen - IPMI_RESP_HDR_SIZE); + + // Calculate Header Checksum + p_ipmb_res->hdr_cksum = p_ipmb_res->req_slave_addr + + p_ipmb_res->netfn_lun; + p_ipmb_res->hdr_cksum = ZERO_CKSUM_CONST - p_ipmb_res->hdr_cksum; + + // Calculate Data Checksum + p_ipmb_res->data[tlen-IPMI_RESP_HDR_SIZE] = p_ipmb_res->res_slave_addr + + p_ipmb_res->seq_lun + + p_ipmb_res->cmd + + p_ipmb_res->cc; + + for (i = 0; i < tlen-IPMI_RESP_HDR_SIZE; i++) { + p_ipmb_res->data[tlen-IPMI_RESP_HDR_SIZE] += p_ipmb_res->data[i]; + } + + p_ipmb_res->data[tlen-IPMI_RESP_HDR_SIZE] = ZERO_CKSUM_CONST - + p_ipmb_res->data[tlen-IPMI_RESP_HDR_SIZE]; + +#ifdef DEBUG + syslog(LOG_ALERT, "Sending Response of %d bytes\n", tlen+IPMB_HDR_SIZE-1); + for (i = 1; i < tlen+IPMB_HDR_SIZE; i++) { + syslog(LOG_ALERT, "0x%X:", txbuf[i]); + } +#endif + + // Send response back + i2c_write(fd, &txbuf[1], tlen+IPMB_HDR_SIZE-1); + } +} + +// Thread to handle the incoming responses +static void* +ipmb_res_handler(void *bus_num) { + uint8_t *bnum = (uint8_t*) bus_num; + uint8_t buf[MQ_MAX_MSG_SIZE] = { 0 }; + uint8_t len = 0; + mqd_t mq; + ipmb_res_t *p_res; + uint8_t index; + char mq_ipmb_res[64] = {0}; + + sprintf(mq_ipmb_res, "%s_%d", MQ_IPMB_RES, *bnum); + + // Open the message queue + mq = mq_open(mq_ipmb_res, O_RDONLY); + if (mq == (mqd_t) -1) { + syslog(LOG_ALERT, "mq_open fails\n"); + return NULL; + } + + // Loop to wait for incomng response messages + while (1) { + if ((len = mq_receive(mq, buf, MQ_MAX_MSG_SIZE, NULL)) < 0) { + sleep(1); + continue; + } + + p_res = (ipmb_res_t *) buf; + + // Check the seq# of response + index = p_res->seq_lun >> LUN_OFFSET; + + // Check if the response is being waited for + pthread_mutex_lock(&m_seq); + if (g_seq.seq[index].in_use) { + // Copy the response to the requester's buffer + memcpy(g_seq.seq[index].p_buf, buf, len); + g_seq.seq[index].len = len; + + // Wake up the worker thread to receive the response + sem_post(&g_seq.seq[index].s_seq); + } + pthread_mutex_unlock(&m_seq); + +#ifdef DEBUG + syslog(LOG_ALERT, "Received Response of %d bytes\n", len); + int i; + for (i = 0; i < len; i++) { + syslog(LOG_ALERT, "0x%X:", buf[i]); + } +#endif + } +} + +// Thread to receive the IPMB messages over i2c bus as a slave +static void* +ipmb_rx_handler(void *bus_num) { + uint8_t *bnum = (uint8_t*) bus_num; + int fd; + uint8_t len; + uint8_t tlun; + uint8_t buf[MAX_BYTES] = { 0 }; + mqd_t mq_req, mq_res, tmq; + ipmb_req_t *p_req; + struct timespec req; + struct timespec rem; + char mq_ipmb_req[64] = {0}; + char mq_ipmb_res[64] = {0}; + + // Setup wait time + req.tv_sec = 0; + req.tv_nsec = 10000000;//10mSec + + // Open the i2c bus as a slave + fd = i2c_slave_open(*bnum); + if (fd < 0) { + syslog(LOG_ALERT, "i2c_slave_open fails\n"); + goto cleanup; + } + + sprintf(mq_ipmb_req, "%s_%d", MQ_IPMB_REQ, *bnum); + sprintf(mq_ipmb_res, "%s_%d", MQ_IPMB_RES, *bnum); + + // Open the message queues for post processing + mq_req = mq_open(mq_ipmb_req, O_WRONLY); + if (mq_req == (mqd_t) -1) { + syslog(LOG_ALERT, "mq_open req fails\n"); + goto cleanup; + } + + mq_res = mq_open(mq_ipmb_res, O_WRONLY); + if (mq_res == (mqd_t) -1) { + syslog(LOG_ALERT, "mq_open res fails\n"); + goto cleanup; + } + + // Loop that retrieves messages + while (1) { + // Read messages from i2c driver + if (i2c_slave_read(fd, buf, &len) < 0) { + nanosleep(&req, &rem); + continue; + } + + // Check if the messages is request or response + // Even NetFn: Request, Odd NetFn: Response + p_req = (ipmb_req_t*) buf; + tlun = p_req->netfn_lun >> LUN_OFFSET; + if (tlun%2) { + tmq = mq_res; + } else { + tmq = mq_req; + } + // Post message to approriate Queue for further processing + if (mq_send(tmq, buf, len, 0)) { + syslog(LOG_ALERT, "mq_send failed\n"); + sleep(1); + continue; + } + } + +cleanup: + if (fd > 0) { + close (fd); + } + + if (mq_req > 0) { + close(mq_req); + } + + if (mq_res > 0) { + close(mq_req); + } +} + +/* + * Function to handle all IPMB requests + */ +static void +ipmb_handle (int fd, unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + ipmb_req_t *req = (ipmb_req_t *) request; + ipmb_res_t *res = (ipmb_res_t *) response; + + uint8_t index; + struct timespec ts; + + // Allocate right sequence Number + index = seq_get_new(); + if (index < 0) { + *res_len = 0; + return ; + } + + req->seq_lun = index << LUN_OFFSET; + + // Calculate/update dataCksum + // Note: dataCkSum byte is last byte + int i; + for (i = IPMB_DATA_OFFSET; i < req_len-1; i++) { + request[req_len-1] += request[i]; + } + + request[req_len-1] = ZERO_CKSUM_CONST - request[req_len-1]; + + // Setup response buffer + pthread_mutex_lock(&m_seq); + g_seq.seq[index].p_buf = response; + pthread_mutex_unlock(&m_seq); + + // Send request over i2c bus + // Note: Need not send first byte SlaveAddress automatically added by driver + if (i2c_write(fd, &request[1], req_len-1)) { + goto ipmb_handle_out; + } + + // Wait on semaphore for that sequence Number + clock_gettime(CLOCK_REALTIME, &ts); + + ts.tv_sec += TIMEOUT_IPMI; + + int ret; + ret = sem_timedwait(&g_seq.seq[index].s_seq, &ts); + if (ret == -1) { + syslog(LOG_ALERT, "No response for sequence number: %d\n", index); + *res_len = 0; + } + +ipmb_handle_out: + // Reply to user with data + pthread_mutex_lock(&m_seq); + *res_len = g_seq.seq[index].len; + + g_seq.seq[index].in_use = false; + pthread_mutex_unlock(&m_seq); + + return; +} + +void +*conn_handler(void *sfd) { + ipmb_sfd_t *p_sfd = (ipmb_sfd_t *) sfd; + + int sock = p_sfd->sock; + int fd = p_sfd->fd; + int n; + unsigned char req_buf[MAX_IPMI_MSG_SIZE]; + unsigned char res_buf[MAX_IPMI_MSG_SIZE]; + unsigned char res_len = 0; + + n = recv(sock, req_buf, sizeof(req_buf), 0); + if (n <= 0) { + syslog(LOG_ALERT, "ipmbd: recv() failed with %d\n", n); + goto conn_cleanup; + } + + ipmb_handle(fd, req_buf, n, res_buf, &res_len); + + if (send(sock, res_buf, res_len, MSG_NOSIGNAL) < 0) { + syslog(LOG_ALERT, "ipmbd: send() failed\n"); + } + +conn_cleanup: + close(sock); + free(p_sfd); + + pthread_exit(NULL); + return 0; +} + +// Thread to receive the IPMB lib messages from various apps +static void* +ipmb_lib_handler(void *bus_num) { + int s, s2, t, len; + struct sockaddr_un local, remote; + pthread_t tid; + ipmb_sfd_t *sfd; + int fd; + uint8_t *bnum = (uint8_t*) bus_num; + char sock_path[20] = {0}; + + // Open the i2c bus for sending request + fd = i2c_open(*bnum); + if (fd < 0) { + syslog(LOG_ALERT, "i2c_open failure\n"); + return NULL; + } + + // Initialize g_seq structure + int i; + for (i = 0; i < SEQ_NUM_MAX; i++) { + g_seq.seq[i].in_use = false; + sem_init(&g_seq.seq[i].s_seq, 0, 0); + g_seq.seq[i].len = 0; + } + + // Initialize mutex to access global structure + pthread_mutex_init(&m_seq, NULL); + + if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) + { + syslog(LOG_ALERT, "ipmbd: socket() failed\n"); + exit (1); + } + + sprintf(sock_path, "%s_%d", SOCK_PATH_IPMB, *bnum); + + local.sun_family = AF_UNIX; + strcpy (local.sun_path, sock_path); + unlink (local.sun_path); + len = strlen (local.sun_path) + sizeof (local.sun_family); + if (bind (s, (struct sockaddr *) &local, len) == -1) + { + syslog(LOG_ALERT, "ipmbd: bind() failed\n"); + exit (1); + } + + if (listen (s, 5) == -1) + { + syslog(LOG_ALERT, "ipmbd: listen() failed\n"); + exit (1); + } + + while(1) { + int n; + t = sizeof (remote); + if ((s2 = accept (s, (struct sockaddr *) &remote, &t)) < 0) { + syslog(LOG_ALERT, "ipmbd: accept() failed\n"); + break; + } + + // Creating a worker thread to handle the request + // TODO: Need to monitor the server performance with higher load and + // see if we need to create pre-defined number of workers and schedule + // the requests among them. + sfd = (ipmb_sfd_t *) malloc(sizeof(ipmb_sfd_t)); + sfd->fd = fd; + sfd->sock = s2; + if (pthread_create(&tid, NULL, conn_handler, (void*) sfd) < 0) { + syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + close(s2); + continue; + } + + pthread_detach(tid); + } + + close(s); + pthread_mutex_destroy(&m_seq); + + return 0; +} + +int +main(int argc, char * const argv[]) { + pthread_t tid_ipmb_rx; + pthread_t tid_req_handler; + pthread_t tid_res_handler; + pthread_t tid_lib_handler; + uint8_t ipmb_bus_num; + mqd_t mqd_req, mqd_res; + struct mq_attr attr; + char mq_ipmb_req[64] = {0}; + char mq_ipmb_res[64] = {0}; + + daemon(1, 0); + openlog("ipmbd", LOG_CONS, LOG_DAEMON); + + if (argc != 2) { + syslog(LOG_ALERT, "ipmbd: Usage: ipmbd <bus#>"); + exit(1); + } + + ipmb_bus_num = atoi(argv[1]); +syslog(LOG_ALERT, "ipmbd: bus#:%d\n", ipmb_bus_num); + + pthread_mutex_init(&m_i2c, NULL); + + // Create Message Queues for Request Messages and Response Messages + attr.mq_flags = 0; + attr.mq_maxmsg = MQ_MAX_NUM_MSGS; + attr.mq_msgsize = MQ_MAX_MSG_SIZE; + attr.mq_curmsgs = 0; + + sprintf(mq_ipmb_req, "%s_%d", MQ_IPMB_REQ, ipmb_bus_num); + sprintf(mq_ipmb_res, "%s_%d", MQ_IPMB_RES, ipmb_bus_num); + + // Remove the MQ if exists + mq_unlink(mq_ipmb_req); + + errno = 0; + mqd_req = mq_open(mq_ipmb_req, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &attr); + if (mqd_req == (mqd_t) -1) { + syslog(LOG_ALERT, "ipmbd: mq_open request failed errno:%d\n", errno); + goto cleanup; + } + + // Remove the MQ if exists + mq_unlink(mq_ipmb_res); + + errno = 0; + mqd_res = mq_open(mq_ipmb_res, O_RDONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, &attr); + if (mqd_res == (mqd_t) -1) { + syslog(LOG_ALERT, "ipmbd: mq_open response failed errno: %d\n", errno); + goto cleanup; + } + + // Create thread to handle IPMB Requests + if (pthread_create(&tid_req_handler, NULL, ipmb_req_handler, (void*) &ipmb_bus_num) < 0) { + syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + goto cleanup; + } + + // Create thread to handle IPMB Responses + if (pthread_create(&tid_res_handler, NULL, ipmb_res_handler, (void*) &ipmb_bus_num) < 0) { + syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + goto cleanup; + } + + // Create thread to retrieve ipmb traffic from i2c bus as slave + if (pthread_create(&tid_ipmb_rx, NULL, ipmb_rx_handler, (void*) &ipmb_bus_num) < 0) { + syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + goto cleanup; + } + + // Create thread to receive ipmb library requests from apps + if (pthread_create(&tid_lib_handler, NULL, ipmb_lib_handler, (void*) &ipmb_bus_num) < 0) { + syslog(LOG_ALERT, "ipmbd: pthread_create failed\n"); + goto cleanup; + } + +cleanup: + if (tid_ipmb_rx > 0) { + pthread_join(tid_ipmb_rx, NULL); + } + + if (tid_req_handler > 0) { + pthread_join(tid_req_handler, NULL); + } + + if (tid_res_handler > 0) { + pthread_join(tid_res_handler, NULL); + } + + if (tid_lib_handler > 0) { + pthread_join(tid_lib_handler, NULL); + } + + if (mqd_res > 0) { + mq_close(mqd_res); + mq_unlink(mq_ipmb_res); + } + + if (mqd_req > 0) { + mq_close(mqd_req); + mq_unlink(mq_ipmb_req); + } + + pthread_mutex_destroy(&m_i2c); + + return 0; +} diff --git a/common/recipes-core/ipmbd/ipmbd_0.1.bb b/common/recipes-core/ipmbd/ipmbd_0.1.bb new file mode 100644 index 0000000..f5724b0 --- /dev/null +++ b/common/recipes-core/ipmbd/ipmbd_0.1.bb @@ -0,0 +1,19 @@ +# Copyright 2015-present Facebook. All Rights Reserved. + +SUMMARY = "ipmbd tx/rx daemon" +DESCRIPTION = "The ipmb daemon to receive/transmit messages" +SECTION = "base" +PR = "r2" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://ipmbd.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI = "file://Makefile \ + file://ipmbd.c \ + " + +S = "${WORKDIR}" +DEPENDS += "libipmi libipmb" + +binfiles = "ipmbd" + +pkgdir = "ipmbd" diff --git a/common/recipes-core/ipmid/files/Makefile b/common/recipes-core/ipmid/files/Makefile new file mode 100644 index 0000000..4f0db3d --- /dev/null +++ b/common/recipes-core/ipmid/files/Makefile @@ -0,0 +1,29 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +C_SRCS := $(wildcard *.c) +C_OBJS := ${C_SRCS:.c=.o} + +all: ipmid + +ipmid: $(C_OBJS) + $(CC) -pthread -lpal -std=c99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o ipmid diff --git a/common/recipes-core/ipmid/files/fruid.h b/common/recipes-core/ipmid/files/fruid.h new file mode 100644 index 0000000..3580b08 --- /dev/null +++ b/common/recipes-core/ipmid/files/fruid.h @@ -0,0 +1,28 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __FRUID_H__ +#define __FRUID_H__ + +int plat_fruid_size(void); +int plat_fruid_data(int offset, int count, unsigned char *data); +int plat_fruid_init(void); + +#endif /* __FRUID_H__ */ diff --git a/common/recipes-core/ipmid/files/ipmid.c b/common/recipes-core/ipmid/files/ipmid.c new file mode 100644 index 0000000..c79d3e2 --- /dev/null +++ b/common/recipes-core/ipmid/files/ipmid.c @@ -0,0 +1,1412 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "sdr.h" +#include "sel.h" +#include "fruid.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +#include <pthread.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <openbmc/ipmi.h> + +// TODO: Once data storage is finalized, the following structure needs +// to be retrieved/updated from persistant backend storage +static lan_config_t g_lan_config = { 0 }; +static proc_info_t g_proc_info = { 0 }; +static dimm_info_t g_dimm_info[MAX_NUM_DIMMS] = { 0 }; + +// TODO: Need to store this info after identifying proper storage +static sys_info_param_t g_sys_info_params; + +// TODO: Based on performance testing results, might need fine grained locks +// Since the global data is specific to a NetFunction, adding locs at NetFn level +static pthread_mutex_t m_chassis; +static pthread_mutex_t m_app; +static pthread_mutex_t m_storage; +static pthread_mutex_t m_transport; +static pthread_mutex_t m_oem; +static pthread_mutex_t m_oem_1s; + +static void ipmi_handle(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len); + +/* + * Function(s) to handle IPMI messages with NetFn: Chassis + */ +// Get Chassis Status (IPMI/Section 28.2) +static void +chassis_get_status (unsigned char *response, unsigned char *res_len) +{ + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + res->cc = CC_SUCCESS; + + // TODO: Need to obtain current power state and last power event + // from platform and return + *data++ = 0x01; // Current Power State + *data++ = 0x00; // Last Power Event + *data++ = 0x40; // Misc. Chassis Status + *data++ = 0x00; // Front Panel Button Disable + + res_len = data - &res->data[0]; +} + +// Get System Boot Options (IPMI/Section 28.12) +static void +chassis_get_boot_options (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res= (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + unsigned char param = req->data[0]; + + // Fill response with default values + res->cc = CC_SUCCESS; + *data++ = 0x01; // Parameter Version + *data++ = req->data[0]; // Parameter + + // TODO: Need to store user settings and return + switch (param) + { + case PARAM_SET_IN_PROG: + *data++ = 0x00; // Set In Progress + break; + case PARAM_SVC_PART_SELECT: + *data++ = 0x00; // Service Partition Selector + break; + case PARAM_SVC_PART_SCAN: + *data++ = 0x00; // Service Partition Scan + break; + case PARAM_BOOT_FLAG_CLR: + *data++ = 0x00; // BMC Boot Flag Valid Bit Clear + break; + case PARAM_BOOT_INFO_ACK: + *data++ = 0x00; // Write Mask + *data++ = 0x00; // Boot Initiator Ack Data + break; + case PARAM_BOOT_FLAGS: + *data++ = 0x00; // Boot Flags + *data++ = 0x00; // Boot Device Selector + *data++ = 0x00; // Firmwaer Verbosity + *data++ = 0x00; // BIOS Override + *data++ = 0x00; // Device Instance Selector + break; + case PARAM_BOOT_INIT_INFO: + *data++ = 0x00; // Chanel Number + *data++ = 0x00; // Session ID (4 bytes) + *data++ = 0x00; + *data++ = 0x00; + *data++ = 0x00; + *data++ = 0x00; // Boot Info Timestamp (4 bytes) + *data++ = 0x00; + *data++ = 0x00; + *data++ = 0x00; + break; + deault: + res->cc = CC_PARAM_OUT_OF_RANGE; + break; + } + + if (res->cc == CC_SUCCESS) { + *res_len = data - &res->data[0]; + } +} + +// Handle Chassis Commands (IPMI/Section 28) +static void +ipmi_handle_chassis (unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char cmd = req->cmd; + + pthread_mutex_lock(&m_chassis); + switch (cmd) + { + case CMD_CHASSIS_GET_STATUS: + chassis_get_status (response, res_len); + break; + case CMD_CHASSIS_GET_BOOT_OPTIONS: + chassis_get_boot_options (request, response, res_len); + break; + default: + res->cc = CC_INVALID_CMD; + break; + } + pthread_mutex_unlock(&m_chassis); +} + +/* + * Function(s) to handle IPMI messages with NetFn: Application + */ +// Get Device ID (IPMI/Section 20.1) +static void +app_get_device_id (unsigned char *response, unsigned char *res_len) +{ + + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + res->cc = CC_SUCCESS; + + //TODO: Following data needs to be updated based on platform + *data++ = 0x20; // Device ID + *data++ = 0x81; // Device Revision + *data++ = 0x00; // Firmware Revision Major + *data++ = 0x09; // Firmware Revision Minor + *data++ = 0x02; // IPMI Version + *data++ = 0xBF; // Additional Device Support + *data++ = 0x15; // Manufacturer ID1 + *data++ = 0xA0; // Manufacturer ID2 + *data++ = 0x00; // Manufacturer ID3 + *data++ = 0x46; // Product ID1 + *data++ = 0x31; // Product ID2 + *data++ = 0x00; // Aux. Firmware Version1 + *data++ = 0x00; // Aux. Firmware Version2 + *data++ = 0x00; // Aux. Firmware Version3 + *data++ = 0x00; // Aux. Firmware Version4 + + *res_len = data - &res->data[0]; +} + +// Get Self Test Results (IPMI/Section 20.4) +static void +app_get_selftest_results (unsigned char *response, unsigned char *res_len) +{ + + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + res->cc = CC_SUCCESS; + + //TODO: Following data needs to be updated based on self-test results + *data++ = 0x55; // Self-Test result + *data++ = 0x00; // Extra error info in case of failure + + *res_len = data - &res->data[0]; +} + +// Get Device GUID (IPMI/Section 20.8) +static void +app_get_device_guid (unsigned char *response, unsigned char *res_len) +{ + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + res->cc = 0x00; + + // TODO: Following data is Globaly Unique ID i.e. MAC Address.. + *data++ = 0x0; + *data++ = 0x1; + *data++ = 0x2; + *data++ = 0x3; + *data++ = 0x4; + *data++ = 0x5; + *data++ = 0x6; + *data++ = 0x7; + *data++ = 0x8; + *data++ = 0x9; + *data++ = 0xa; + *data++ = 0xb; + *data++ = 0xc; + *data++ = 0xd; + *data++ = 0xe; + *data++ = 0xf; + + *res_len = data - &res->data[0]; +} + +// Get BMC Global Enables (IPMI/Section 22.2) +static void +app_get_global_enables (unsigned char *response, unsigned char *res_len) +{ + + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + res->cc = CC_SUCCESS; + + *data++ = 0x09; // Global Enable + + *res_len = data - &res->data[0]; +} + +// Set System Info Params (IPMI/Section 22.14a) +static void +app_set_sys_info_params (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char param = req->data[0]; + + res->cc = CC_SUCCESS; + + switch (param) + { + case SYS_INFO_PARAM_SET_IN_PROG: + g_sys_info_params.set_in_prog = req->data[1]; + break; + case SYS_INFO_PARAM_SYSFW_VER: + memcpy(g_sys_info_params.sysfw_ver, &req->data[1], SIZE_SYSFW_VER); + break; + case SYS_INFO_PARAM_SYS_NAME: + memcpy(g_sys_info_params.sys_name, &req->data[1], SIZE_SYS_NAME); + break; + case SYS_INFO_PARAM_PRI_OS_NAME: + memcpy(g_sys_info_params.pri_os_name, &req->data[1], SIZE_OS_NAME); + break; + case SYS_INFO_PARAM_PRESENT_OS_NAME: + memcpy(g_sys_info_params.present_os_name, &req->data[1], SIZE_OS_NAME); + break; + case SYS_INFO_PARAM_PRESENT_OS_VER: + memcpy(g_sys_info_params.present_os_ver, &req->data[1], SIZE_OS_VER); + break; + case SYS_INFO_PARAM_BMC_URL: + memcpy(g_sys_info_params.bmc_url, &req->data[1], SIZE_BMC_URL); + break; + case SYS_INFO_PARAM_OS_HV_URL: + memcpy(g_sys_info_params.os_hv_url, &req->data[1], SIZE_OS_HV_URL); + break; + default: + res->cc = CC_INVALID_PARAM; + break; + } + + return; +} + +// Get System Info Params (IPMI/Section 22.14b) +static void +app_get_sys_info_params (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + unsigned char param = req->data[1]; + + // Fill default return values + res->cc = CC_SUCCESS; + *data++ = 1; // Parameter revision + + switch (param) + { + case SYS_INFO_PARAM_SET_IN_PROG: + *data++ = g_sys_info_params.set_in_prog; + break; + case SYS_INFO_PARAM_SYSFW_VER: + memcpy(data, g_sys_info_params.sysfw_ver, SIZE_SYSFW_VER); + data += SIZE_SYSFW_VER; + break; + case SYS_INFO_PARAM_SYS_NAME: + memcpy(data, g_sys_info_params.sys_name, SIZE_SYS_NAME); + data += SIZE_SYS_NAME; + break; + case SYS_INFO_PARAM_PRI_OS_NAME: + memcpy(data, g_sys_info_params.pri_os_name, SIZE_OS_NAME); + data += SIZE_OS_NAME; + break; + case SYS_INFO_PARAM_PRESENT_OS_NAME: + memcpy(data, g_sys_info_params.present_os_name, SIZE_OS_NAME); + data += SIZE_OS_NAME; + break; + case SYS_INFO_PARAM_PRESENT_OS_VER: + memcpy(data, g_sys_info_params.present_os_ver, SIZE_OS_VER); + data += SIZE_OS_VER; + break; + case SYS_INFO_PARAM_BMC_URL: + memcpy(data, g_sys_info_params.bmc_url, SIZE_BMC_URL); + data += SIZE_BMC_URL; + break; + case SYS_INFO_PARAM_OS_HV_URL: + memcpy(data, g_sys_info_params.os_hv_url, SIZE_OS_HV_URL); + data += SIZE_OS_HV_URL; + break; + default: + res->cc = CC_INVALID_PARAM; + break; + } + + if (res->cc == CC_SUCCESS) { + *res_len = data - &res->data[0]; + } + + return; +} + +// Handle Appliction Commands (IPMI/Section 20) +static void +ipmi_handle_app (unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char cmd = req->cmd; + + pthread_mutex_lock(&m_app); + switch (cmd) + { + case CMD_APP_GET_DEVICE_ID: + app_get_device_id (response, res_len); + break; + case CMD_APP_GET_SELFTEST_RESULTS: + app_get_selftest_results (response, res_len); + break; + case CMD_APP_GET_DEVICE_GUID: + case CMD_APP_GET_SYSTEM_GUID: + // Get Device GUID and Get System GUID returns same data + // from IPMI stack. FYI, Get System GUID will have to be + // sent with in an IPMI session that includes session info + app_get_device_guid (response, res_len); + break; + case CMD_APP_GET_GLOBAL_ENABLES: + app_get_global_enables (response, res_len); + break; + case CMD_APP_SET_SYS_INFO_PARAMS: + app_set_sys_info_params (request, response, res_len); + break; + case CMD_APP_GET_SYS_INFO_PARAMS: + app_get_sys_info_params (request, response, res_len); + break; + default: + res->cc = CC_INVALID_CMD; + break; + } + pthread_mutex_unlock(&m_app); +} + +/* + * Function(s) to handle IPMI messages with NetFn: Storage + */ + +static void +storage_get_fruid_info(unsigned char *response, unsigned char *res_len) +{ + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + int size = plat_fruid_size(); + + res->cc = CC_SUCCESS; + + *data++ = size & 0xFF; // FRUID size LSB + *data++ = (size >> 8) & 0xFF; // FRUID size MSB + *data++ = 0x00; // Device accessed by bytes + + *res_len = data - &res->data[0]; + + return; +} + +static void +storage_get_fruid_data(unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + int offset = req->data[1] + (req->data[2] << 8); + int count = req->data[3]; + + int ret = plat_fruid_data(offset, count, &(res->data[1])); + if (ret) { + res->cc = CC_UNSPECIFIED_ERROR; + } else { + res->cc = CC_SUCCESS; + *data++ = count; + data += count; + } + + if (res->cc == CC_SUCCESS) { + *res_len = data - &res->data[0]; + } + return; +} + +static void +storage_get_sdr_info (unsigned char *response, unsigned char *res_len) +{ + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + int num_entries; // number of sdr records + int free_space; // free space in SDR device in bytes + time_stamp_t ts_recent_add; // Recent Addition Timestamp + time_stamp_t ts_recent_erase; // Recent Erasure Timestamp + + // Use platform APIs to get SDR information + num_entries = sdr_num_entries (); + free_space = sdr_free_space (); + sdr_ts_recent_add (&ts_recent_add); + sdr_ts_recent_erase (&ts_recent_erase); + + res->cc = CC_SUCCESS; + + *data++ = IPMI_SDR_VERSION; // SDR version + *data++ = num_entries & 0xFF; // number of sdr entries + *data++ = (num_entries >> 8) & 0xFF; + *data++ = free_space & 0xFF; // Free SDR Space + *data++ = (free_space >> 8) & 0xFF; + + memcpy(data, ts_recent_add.ts, SIZE_TIME_STAMP); + data += SIZE_TIME_STAMP; + + memcpy(data, ts_recent_erase.ts, SIZE_TIME_STAMP); + data += SIZE_TIME_STAMP; + + *data++ = 0x02; // Operations supported + + *res_len = data - &res->data[0]; + + return; +} + +static void +storage_rsv_sdr (unsigned char *response, unsigned char *res_len) +{ + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + int rsv_id; // SDR reservation ID + + // Use platform APIs to get a SDR reservation ID + rsv_id = sdr_rsv_id (); + if (rsv_id < 0) + { + res->cc = CC_UNSPECIFIED_ERROR; + return; + } + + res->cc = CC_SUCCESS; + *data++ = rsv_id & 0xFF; // Reservation ID + *data++ = (rsv_id >> 8) & 0XFF; + + *res_len = data - &res->data[0]; + + return; +} + +static void +storage_get_sdr (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + int read_rec_id; //record ID to be read + int next_rec_id; //record ID for the next entry + int rsv_id; // Reservation ID for the request + int rec_offset; // Read offset into the record + int rec_bytes; // Number of bytes to be read + sdr_rec_t entry; // SDR record entry + int ret; + + rsv_id = (req->data[1] >> 8) | req->data[0]; + read_rec_id = (req->data[3] >> 8) | req->data[2]; + rec_offset = req->data[4]; + rec_bytes = req->data[5]; + + // Use platform API to read the record Id and get next ID + ret = sdr_get_entry (rsv_id, read_rec_id, &entry, &next_rec_id); + if (ret) + { + res->cc = CC_UNSPECIFIED_ERROR; + return; + } + + res->cc = CC_SUCCESS; + *data++ = next_rec_id & 0xFF; // next record ID + *data++ = (next_rec_id >> 8) & 0xFF; + + memcpy (data, &entry.rec[rec_offset], rec_bytes); + data += rec_bytes; + + *res_len = data - &res->data[0]; + + return; +} + +static void +storage_get_sel_info (unsigned char *response, unsigned char *res_len) +{ + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + int num_entries; // number of log entries + int free_space; // free space in SEL device in bytes + time_stamp_t ts_recent_add; // Recent Addition Timestamp + time_stamp_t ts_recent_erase; // Recent Erasure Timestamp + + // Use platform APIs to get SEL information + num_entries = sel_num_entries (); + free_space = sel_free_space (); + sel_ts_recent_add (&ts_recent_add); + sel_ts_recent_erase (&ts_recent_erase); + + res->cc = CC_SUCCESS; + + *data++ = IPMI_SEL_VERSION; // SEL version + *data++ = num_entries & 0xFF; // number of log entries + *data++ = (num_entries >> 8) & 0xFF; + *data++ = free_space & 0xFF; // Free SEL Space + *data++ = (free_space >> 8) & 0xFF; + + memcpy(data, ts_recent_add.ts, SIZE_TIME_STAMP); + data += SIZE_TIME_STAMP; + + memcpy(data, ts_recent_erase.ts, SIZE_TIME_STAMP); + data += SIZE_TIME_STAMP; + + *data++ = 0x02; // Operations supported + + *res_len = data - &res->data[0]; + + return; +} + +static void +storage_rsv_sel (unsigned char *response, unsigned char *res_len) +{ + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + int rsv_id; // SEL reservation ID + + // Use platform APIs to get a SEL reservation ID + rsv_id = sel_rsv_id (); + if (rsv_id < 0) + { + res->cc = CC_SEL_ERASE_PROG; + return; + } + + res->cc = CC_SUCCESS; + *data++ = rsv_id & 0xFF; // Reservation ID + *data++ = (rsv_id >> 8) & 0XFF; + + *res_len = data - &res->data[0]; + + return; +} + +static void +storage_get_sel (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + int read_rec_id; //record ID to be read + int next_rec_id; //record ID for the next msg + sel_msg_t entry; // SEL log entry + int ret; + + read_rec_id = (req->data[3] >> 8) | req->data[2]; + + // Use platform API to read the record Id and get next ID + ret = sel_get_entry (read_rec_id, &entry, &next_rec_id); + if (ret) + { + res->cc = CC_UNSPECIFIED_ERROR; + return; + } + + res->cc = CC_SUCCESS; + *data++ = next_rec_id & 0xFF; // next record ID + *data++ = (next_rec_id >> 8) & 0xFF; + + memcpy(data, entry.msg, SIZE_SEL_REC); + data += SIZE_SEL_REC; + + *res_len = data - &res->data[0]; + + return; +} + +static void +storage_add_sel (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + + int record_id; // Record ID for added entry + int ret; + + sel_msg_t entry; + + memcpy(entry.msg, req->data, SIZE_SEL_REC); + + // Use platform APIs to add the new SEL entry + ret = sel_add_entry (&entry, &record_id); + if (ret) + { + res->cc = CC_UNSPECIFIED_ERROR; + return; + } + + res->cc = CC_SUCCESS; + *data++ = record_id & 0xFF; + *data++ = (record_id >> 8) & 0xFF; + + *res_len = data - &res->data[0]; + + return; +} + +static void +storage_clr_sel (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + + sel_erase_stat_t status; + int ret; + int rsv_id; + + // Verify the request to contain 'CLR' characters + if ((req->data[2] != 'C') || (req->data[3] != 'L') || (req->data[4] != 'R')) + { + res->cc = CC_INVALID_PARAM; + return; + } + + // Populate reservation ID given in request + rsv_id = (req->data[1] << 8) | req->data[0]; + + // Use platform APIs to clear or get status + if (req->data[5] == IPMI_SEL_INIT_ERASE) + { + ret = sel_erase (rsv_id); + } + else if (req->data[5] == IPMI_SEL_ERASE_STAT) + { + ret = sel_erase_status (rsv_id, &status); + } + else + { + res->cc = CC_INVALID_PARAM; + return; + } + + // Handle platform error and return + if (ret) + { + res->cc = CC_UNSPECIFIED_ERROR; + return; + } + + res->cc = CC_SUCCESS; + *data++ = status; + + *res_len = data - &res->data[0]; + + return; +} + +static void +ipmi_handle_storage (unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char cmd = req->cmd; + + res->cc = CC_SUCCESS; + *res_len = 0; + + pthread_mutex_lock(&m_storage); + switch (cmd) + { + case CMD_STORAGE_GET_FRUID_INFO: + storage_get_fruid_info (response, res_len); + break; + case CMD_STORAGE_READ_FRUID_DATA: + storage_get_fruid_data (request, response, res_len); + break; + case CMD_STORAGE_GET_SEL_INFO: + storage_get_sel_info (response, res_len); + break; + case CMD_STORAGE_RSV_SEL: + storage_rsv_sel (response, res_len); + break; + case CMD_STORAGE_ADD_SEL: + storage_add_sel (request, response, res_len); + break; + case CMD_STORAGE_GET_SEL: + storage_get_sel (request, response, res_len); + break; + case CMD_STORAGE_CLR_SEL: + storage_clr_sel (request, response, res_len); + break; + case CMD_STORAGE_GET_SDR_INFO: + storage_get_sdr_info (response, res_len); + break; + case CMD_STORAGE_RSV_SDR: + storage_rsv_sdr (response, res_len); + break; + case CMD_STORAGE_GET_SDR: + storage_get_sdr (request, response, res_len); + break; + default: + res->cc = CC_INVALID_CMD; + break; + } + + pthread_mutex_unlock(&m_storage); + return; +} + +/* + * Function(s) to handle IPMI messages with NetFn: Transport + */ + +// Set LAN Configuration (IPMI/Section 23.1) +static void +transport_set_lan_config (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char param = req->data[1]; + + // Fill the response with default values + res->cc = CC_SUCCESS; + + switch (param) + { + case LAN_PARAM_SET_IN_PROG: + g_lan_config.set_in_prog = req->data[2]; + break; + case LAN_PARAM_AUTH_SUPPORT: + g_lan_config.auth_support = req->data[2]; + break; + case LAN_PARAM_AUTH_ENABLES: + memcpy(g_lan_config.auth_enables, &req->data[2], SIZE_AUTH_ENABLES); + break; + case LAN_PARAM_IP_ADDR: + memcpy(g_lan_config.ip_addr, &req->data[2], SIZE_IP_ADDR); + break; + case LAN_PARAM_IP_SRC: + g_lan_config.ip_src = req->data[2]; + break; + case LAN_PARAM_MAC_ADDR: + memcpy(g_lan_config.mac_addr, &req->data[2], SIZE_MAC_ADDR); + break; + case LAN_PARAM_NET_MASK: + memcpy(g_lan_config.net_mask, &req->data[2], SIZE_NET_MASK); + break; + case LAN_PARAM_IP_HDR: + memcpy(g_lan_config.ip_hdr, &req->data[2], SIZE_IP_HDR); + break; + case LAN_PARAM_PRI_RMCP_PORT: + g_lan_config.pri_rmcp_port[0] = req->data[2]; + g_lan_config.pri_rmcp_port[1] = req->data[3]; + break; + case LAN_PARAM_SEC_RMCP_PORT: + g_lan_config.sec_rmcp_port[0] = req->data[2]; + g_lan_config.sec_rmcp_port[1] = req->data[3]; + break; + case LAN_PARAM_ARP_CTRL: + g_lan_config.arp_ctrl = req->data[2]; + break; + case LAN_PARAM_GARP_INTERVAL: + g_lan_config.garp_interval = req->data[2]; + break; + case LAN_PARAM_DF_GW_IP_ADDR: + memcpy(g_lan_config.df_gw_ip_addr, &req->data[2], SIZE_IP_ADDR); + break; + case LAN_PARAM_DF_GW_MAC_ADDR: + memcpy(g_lan_config.df_gw_mac_addr, &req->data[2], SIZE_MAC_ADDR); + break; + case LAN_PARAM_BACK_GW_IP_ADDR: + memcpy(g_lan_config.back_gw_ip_addr, &req->data[2], SIZE_IP_ADDR); + break; + case LAN_PARAM_BACK_GW_MAC_ADDR: + memcpy(g_lan_config.back_gw_mac_addr, &req->data[2], SIZE_MAC_ADDR); + break; + case LAN_PARAM_COMMUNITY_STR: + memcpy(g_lan_config.community_str, &req->data[2], SIZE_COMMUNITY_STR); + break; + case LAN_PARAM_NO_OF_DEST: + g_lan_config.no_of_dest = req->data[2]; + break; + case LAN_PARAM_DEST_TYPE: + memcpy(g_lan_config.dest_type, &req->data[2], SIZE_DEST_TYPE); + break; + case LAN_PARAM_DEST_ADDR: + memcpy(g_lan_config.dest_addr, &req->data[2], SIZE_DEST_ADDR); + break; + default: + res->cc = CC_INVALID_PARAM; + break; + } +} + +// Get LAN Configuration (IPMI/Section 23.2) +static void +transport_get_lan_config (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char *data = &res->data[0]; + unsigned char param = req->data[1]; + + // Fill the response with default values + res->cc = CC_SUCCESS; + *data++ = 0x01; // Parameter revision + + switch (param) + { + case LAN_PARAM_SET_IN_PROG: + *data++ = g_lan_config.set_in_prog; + break; + case LAN_PARAM_AUTH_SUPPORT: + *data++ = g_lan_config.auth_support; + break; + case LAN_PARAM_AUTH_ENABLES: + memcpy(data, g_lan_config.auth_enables, SIZE_AUTH_ENABLES); + data += SIZE_AUTH_ENABLES; + break; + case LAN_PARAM_IP_ADDR: + memcpy(data, g_lan_config.ip_addr, SIZE_IP_ADDR); + data += SIZE_IP_ADDR; + break; + case LAN_PARAM_IP_SRC: + *data++ = g_lan_config.ip_src; + break; + case LAN_PARAM_MAC_ADDR: + memcpy(data, g_lan_config.mac_addr, SIZE_MAC_ADDR); + data += SIZE_MAC_ADDR; + break; + case LAN_PARAM_NET_MASK: + memcpy(data, g_lan_config.net_mask, SIZE_NET_MASK); + data += SIZE_NET_MASK; + break; + case LAN_PARAM_IP_HDR: + memcpy(data, g_lan_config.ip_hdr, SIZE_IP_HDR); + data += SIZE_IP_HDR; + break; + case LAN_PARAM_PRI_RMCP_PORT: + *data++ = g_lan_config.pri_rmcp_port[0]; + *data++ = g_lan_config.pri_rmcp_port[1]; + break; + case LAN_PARAM_SEC_RMCP_PORT: + *data++ = g_lan_config.sec_rmcp_port[0]; + *data++ = g_lan_config.sec_rmcp_port[1]; + break; + case LAN_PARAM_ARP_CTRL: + *data++ = g_lan_config.arp_ctrl; + break; + case LAN_PARAM_GARP_INTERVAL: + *data++ = g_lan_config.garp_interval; + break; + case LAN_PARAM_DF_GW_IP_ADDR: + memcpy(data, g_lan_config.df_gw_ip_addr, SIZE_IP_ADDR); + data += SIZE_IP_ADDR; + break; + case LAN_PARAM_DF_GW_MAC_ADDR: + memcpy(data, g_lan_config.df_gw_mac_addr, SIZE_MAC_ADDR); + data += SIZE_MAC_ADDR; + break; + case LAN_PARAM_BACK_GW_IP_ADDR: + memcpy(data, g_lan_config.back_gw_ip_addr, SIZE_IP_ADDR); + data += SIZE_IP_ADDR; + break; + case LAN_PARAM_BACK_GW_MAC_ADDR: + memcpy(data, g_lan_config.back_gw_mac_addr, SIZE_MAC_ADDR); + data += SIZE_MAC_ADDR; + break; + case LAN_PARAM_COMMUNITY_STR: + memcpy(data, g_lan_config.community_str, SIZE_COMMUNITY_STR); + data += SIZE_COMMUNITY_STR; + break; + case LAN_PARAM_NO_OF_DEST: + *data++ = g_lan_config.no_of_dest; + break; + case LAN_PARAM_DEST_TYPE: + memcpy(data, g_lan_config.dest_type, SIZE_DEST_TYPE); + data += SIZE_DEST_TYPE; + break; + case LAN_PARAM_DEST_ADDR: + memcpy(data, g_lan_config.dest_addr, SIZE_DEST_ADDR); + data += SIZE_DEST_ADDR; + break; + default: + res->cc = CC_INVALID_PARAM; + break; + } + + if (res->cc == CC_SUCCESS) { + *res_len = data - &res->data[0]; + } +} + +// Handle Transport Commands (IPMI/Section 23) +static void +ipmi_handle_transport (unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char cmd = req->cmd; + + pthread_mutex_lock(&m_transport); + switch (cmd) + { + case CMD_TRANSPORT_SET_LAN_CONFIG: + transport_set_lan_config (request, response, res_len); + break; + case CMD_TRANSPORT_GET_LAN_CONFIG: + transport_get_lan_config (request, response, res_len); + break; + default: + res->cc = CC_INVALID_CMD; + break; + } + pthread_mutex_unlock(&m_transport); +} + +/* + * Function(s) to handle IPMI messages with NetFn: OEM + */ + +static void +oem_set_proc_info (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + + g_proc_info.type = req->data[1]; + g_proc_info.freq[0] = req->data[2]; + g_proc_info.freq[1] = req->data[3]; + + res->cc = CC_SUCCESS; + *res_len = 0; +} + +static void +oem_set_dimm_info (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + + unsigned char index = req->data[0]; + + g_dimm_info[index].type = req->data[1]; + g_dimm_info[index].speed[0] = req->data[2]; + g_dimm_info[index].speed[1] = req->data[3]; + g_dimm_info[index].size[0] = req->data[4]; + g_dimm_info[index].size[1] = req->data[5]; + + res->cc = CC_SUCCESS; + *res_len = 0; +} + +static void +oem_set_post_start (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + + // TODO: For now logging the event, need to find usage for this info + syslog (LOG_INFO, "POST Start Event for Payload#%d\n", req->payload_id); + + res->cc = CC_SUCCESS; + *res_len = 0; +} + +static void +oem_set_post_end (unsigned char *request, unsigned char *response, + unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + + // TODO: For now logging the event, need to find usage for this info + syslog (LOG_INFO, "POST End Event for Payload#%d\n", req->payload_id); + + res->cc = CC_SUCCESS; + *res_len = 0; +} + +static void +ipmi_handle_oem (unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + + unsigned char cmd = req->cmd; + + pthread_mutex_lock(&m_oem); + switch (cmd) + { + case CMD_OEM_SET_PROC_INFO: + oem_set_proc_info (request, response, res_len); + break; + case CMD_OEM_SET_DIMM_INFO: + oem_set_dimm_info (request, response, res_len); + break; + case CMD_OEM_SET_POST_START: + oem_set_post_start (request, response, res_len); + break; + case CMD_OEM_SET_POST_END: + oem_set_post_end (request, response, res_len); + break; + default: + res->cc = CC_INVALID_CMD; + break; + } + pthread_mutex_unlock(&m_oem); +} + +static void +oem_1s_handle_ipmb_kcs(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + + // Need to extract bridged IPMI command and handle + unsigned char req_buf[MAX_IPMI_MSG_SIZE] = {0}; + unsigned char res_buf[MAX_IPMI_MSG_SIZE] = {0}; + + // Add the payload id from the bridged command + req_buf[0] = req->payload_id; + + // Remove OEM IPMI Header + 1 byte for BIC interface + // The offset moves by one due to the payload ID + memcpy(&req_buf[1], &request[BIC_INTF_HDR_SIZE + 1], req_len - BIC_INTF_HDR_SIZE); + + // Send the bridged KCS command along with the payload ID + // The offset moves by one due to the payload ID + ipmi_handle(req_buf, req_len - BIC_INTF_HDR_SIZE + 1, res_buf, res_len); + + // Copy the response back + memcpy(&res->data[1], res_buf, *res_len); + + // Add the OEM command's response + res->cc = CC_SUCCESS; + res->data[0] = req->data[0]; // Bridge-IC interface + *res_len += 1; +} + +static void +oem_1s_handle_ipmb_req(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + + // handle based on Bridge-IC interface + switch(req->data[0]) { + case BIC_INTF_ME: + // TODO: Need to call ME command handler + syslog(LOG_INFO, "oem_1s_handle_ipmb_req: Command received from ME for " + "payload#%d\n", req->payload_id); + res->data[0] = BIC_INTF_ME; + res->cc = CC_SUCCESS; + *res_len = 1; + break; + case BIC_INTF_SOL: + // TODO: Need to call Optional SoL message handler + syslog(LOG_INFO, "oem_1s_handle_ipmb_req: Command received from SOL for " + "payload#%d\n", req->payload_id); + res->data[0] = BIC_INTF_SOL; + res->cc = CC_SUCCESS; + *res_len = 1; + break; + case BIC_INTF_KCS: + oem_1s_handle_ipmb_kcs(request, req_len, response, res_len); + break; + default: + // TODO: Need to add additonal interface handler, if supported + syslog(LOG_ALERT, "oem_1s_handle_ipmb_req: Command received on intf#%d " + "for payload#%d", req->data[0], req->payload_id); + res->cc = CC_INVALID_PARAM; + *res_len = 0; + break; + } +} + +static void +ipmi_handle_oem_1s(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + int i; + + unsigned char cmd = req->cmd; + + pthread_mutex_lock(&m_oem_1s); + switch (cmd) + { + case CMD_OEM_1S_MSG_IN: + oem_1s_handle_ipmb_req(request, req_len, response, res_len); + break; + case CMD_OEM_1S_INTR: + syslog(LOG_INFO, "ipmi_handle_oem_1s: 1S server interrupt#%d received " + "for payload#%d\n", req->data[0], req->payload_id); + + res->cc = CC_SUCCESS; + *res_len = 0; + break; + case CMD_OEM_1S_POST_BUF: + for (i = 1; i <= req->data[0]; i++) { + pal_post_handle(req->payload_id, req->data[i]); + } + + res->cc = CC_SUCCESS; + *res_len = 0; + break; + case CMD_OEM_1S_PLAT_DISC: + syslog(LOG_INFO, "ipmi_handle_oem_1s: Platform Discovery received for " + "payload#%d\n", req->payload_id); + res->cc = CC_SUCCESS; + *res_len = 0; + break; + case CMD_OEM_1S_BIC_RESET: + syslog(LOG_INFO, "ipmi_handle_oem_1s: BIC Reset received " + "for payload#%d\n", req->payload_id); + + if (req->data[0] == 0x0) { + syslog(LOG_ALERT, "Cold Reset by Firmware Update\n"); + res->cc = CC_SUCCESS; + } else if (req->data[1] == 0x01) { + syslog(LOG_ALERT, "WDT Reset\n"); + res->cc = CC_SUCCESS; + } else { + syslog(LOG_ALERT, "Error\n"); + res->cc = CC_INVALID_PARAM; + } + + *res_len = 0; + break; + case CMD_OEM_1S_BIC_UPDATE_MODE: + syslog(LOG_INFO, "ipmi_handle_oem_1s: BIC Update Mode received " + "for payload#%d\n", req->payload_id); + + if (req->data[0] == 0x0) { + syslog(LOG_INFO, "Normal Mode\n"); + res->cc = CC_SUCCESS; + } else if (req->data[1] == 0x0F) { + syslog(LOG_INFO, "Update Mode\n"); + res->cc = CC_SUCCESS; + } else { + syslog(LOG_ALERT, "Error\n"); + res->cc = CC_INVALID_PARAM; + } + + *res_len = 0; + break; + default: + res->cc = CC_INVALID_CMD; + *res_len = 0; + break; + } + pthread_mutex_unlock(&m_oem_1s); +} + +/* + * Function to handle all IPMI messages + */ +static void +ipmi_handle (unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) +{ + + ipmi_mn_req_t *req = (ipmi_mn_req_t *) request; + ipmi_res_t *res = (ipmi_res_t *) response; + unsigned char netfn; + + netfn = req->netfn_lun >> 2; + + // Provide default values in the response message + res->cmd = req->cmd; + res->cc = 0xFF; // Unspecified completion code + *res_len = 0; + + switch (netfn) + { + case NETFN_CHASSIS_REQ: + res->netfn_lun = NETFN_CHASSIS_RES << 2; + ipmi_handle_chassis (request, req_len, response, res_len); + break; + case NETFN_APP_REQ: + res->netfn_lun = NETFN_APP_RES << 2; + ipmi_handle_app (request, req_len, response, res_len); + break; + case NETFN_STORAGE_REQ: + res->netfn_lun = NETFN_STORAGE_RES << 2; + ipmi_handle_storage (request, req_len, response, res_len); + break; + case NETFN_TRANSPORT_REQ: + res->netfn_lun = NETFN_TRANSPORT_RES << 2; + ipmi_handle_transport (request, req_len, response, res_len); + break; + case NETFN_OEM_REQ: + res->netfn_lun = NETFN_OEM_RES << 2; + ipmi_handle_oem (request, req_len, response, res_len); + break; + case NETFN_OEM_1S_REQ: + res->netfn_lun = NETFN_OEM_1S_RES << 2; + ipmi_handle_oem_1s(request, req_len, response, res_len); + break; + default: + res->netfn_lun = (netfn + 1) << 2; + break; + } + + // This header includes NetFunction, Command, and Completion Code + *res_len += IPMI_RESP_HDR_SIZE; + + return; +} + +void +*conn_handler(void *socket_desc) { + int sock = *(int*)socket_desc; + int n; + unsigned char req_buf[MAX_IPMI_MSG_SIZE]; + unsigned char res_buf[MAX_IPMI_MSG_SIZE]; + unsigned char res_len = 0; + + n = recv (sock, req_buf, sizeof(req_buf), 0); + if (n <= 0) { + syslog(LOG_ALERT, "ipmid: recv() failed with %d\n", n); + goto conn_cleanup; + } + + ipmi_handle(req_buf, n, res_buf, &res_len); + + if (send (sock, res_buf, res_len, 0) < 0) { + syslog(LOG_ALERT, "ipmid: send() failed\n"); + } + +conn_cleanup: + close(sock); + + pthread_exit(NULL); + return 0; +} + + +int +main (void) +{ + int s, s2, t, len; + struct sockaddr_un local, remote; + pthread_t tid; + + daemon(1, 0); + openlog("ipmid", LOG_CONS, LOG_DAEMON); + + + plat_fruid_init(); + plat_sensor_init(); + + sdr_init(); + sel_init(); + + pthread_mutex_init(&m_chassis, NULL); + pthread_mutex_init(&m_app, NULL); + pthread_mutex_init(&m_storage, NULL); + pthread_mutex_init(&m_transport, NULL); + pthread_mutex_init(&m_oem, NULL); + pthread_mutex_init(&m_oem_1s, NULL); + + if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) + { + syslog(LOG_ALERT, "ipmid: socket() failed\n"); + exit (1); + } + + local.sun_family = AF_UNIX; + strcpy (local.sun_path, SOCK_PATH_IPMI); + unlink (local.sun_path); + len = strlen (local.sun_path) + sizeof (local.sun_family); + if (bind (s, (struct sockaddr *) &local, len) == -1) + { + syslog(LOG_ALERT, "ipmid: bind() failed\n"); + exit (1); + } + + if (listen (s, 5) == -1) + { + syslog(LOG_ALERT, "ipmid: listen() failed\n"); + exit (1); + } + + while(1) { + int n; + t = sizeof (remote); + if ((s2 = accept (s, (struct sockaddr *) &remote, &t)) < 0) { + syslog(LOG_ALERT, "ipmid: accept() failed\n"); + break; + } + + // Creating a worker thread to handle the request + // TODO: Need to monitor the server performance with higher load and + // see if we need to create pre-defined number of workers and schedule + // the requests among them. + if (pthread_create(&tid, NULL, conn_handler, (void*) &s2) < 0) { + syslog(LOG_ALERT, "ipmid: pthread_create failed\n"); + close(s2); + continue; + } + + pthread_detach(tid); + } + + close(s); + + pthread_mutex_destroy(&m_chassis); + pthread_mutex_destroy(&m_app); + pthread_mutex_destroy(&m_storage); + pthread_mutex_destroy(&m_transport); + pthread_mutex_destroy(&m_oem); + pthread_mutex_destroy(&m_oem_1s); + + return 0; +} diff --git a/common/recipes-core/ipmid/files/sdr.c b/common/recipes-core/ipmid/files/sdr.c new file mode 100644 index 0000000..91a4df5 --- /dev/null +++ b/common/recipes-core/ipmid/files/sdr.c @@ -0,0 +1,414 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file represents platform specific implementation for storing + * SDR record entries and acts as back-end for IPMI stack + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "sdr.h" +#include "sensor.h" +#include "timestamp.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +#include <openbmc/ipmi.h> + +// SDR Header magic number +#define SDR_HDR_MAGIC 0xFBFBFBFB + +// SDR Header version number +#define SDR_HDR_VERSION 0x01 + +// SDR reservation IDs can not be 0x00 or 0xFFFF +#define SDR_RSVID_MIN 0x01 +#define SDR_RSVID_MAX 0xFFFE + +#define SDR_RECORDS_MAX 64 // to support around 64 sensors + +// SDR index to keep track +#define SDR_INDEX_MIN 0 +#define SDR_INDEX_MAX (SDR_RECORDS_MAX - 1) + +// Record ID can not be 0x0 (IPMI/Section 31) +#define SDR_RECID_MIN 1 +#define SDR_RECID_MAX SDR_RECORDS_MAX + +// Special RecID value for first and last (IPMI/Section 31) +#define SDR_RECID_FIRST 0x0000 +#define SDR_RECID_LAST 0xFFFF + +#define SDR_VERSION 0x51 +#define SDR_LEN_MAX 64 + +#define SDR_FULL_TYPE 0x01 +#define SDR_MGMT_TYPE 0x12 +#define SDR_OEM_TYPE 0xC0 + +#define SDR_FULL_LEN 64 +#define SDR_MGMT_LEN 32 +#define SDR_OEM_LEN 64 + +// SDR header struct to keep track of SEL Log entries +typedef struct { + int magic; // Magic number to check validity + int version; // version number of this header + int begin; // index to the first SDR entry + int end; // index to the last SDR entry + time_stamp_t ts_add; // last addition time stamp + time_stamp_t ts_erase; // last erase time stamp +} sdr_hdr_t; + +// Keep track of last Reservation ID +static int g_rsv_id = 0x01; + +// SDR Header and data global structures +static sdr_hdr_t g_sdr_hdr; +static sdr_rec_t g_sdr_data[SDR_RECORDS_MAX]; + +// Add a new SDR entry +static int +sdr_add_entry(sdr_rec_t *rec, int *rec_id) { + // If SDR is full, return error + if (sdr_num_entries() == SDR_RECORDS_MAX) { + syslog(LOG_ALERT, "sdr_add_entry: SDR full\n"); + return -1; + } + + // Add Record ID which is array index + 1 + rec->rec[0] = g_sdr_hdr.end+1; + + // Add the enry at end + memcpy(g_sdr_data[g_sdr_hdr.end].rec, rec->rec, sizeof(sdr_rec_t)); + + // Return the newly added record ID + *rec_id = g_sdr_hdr.end+1; + + // Increment the end pointer + ++g_sdr_hdr.end; + + // Update timestamp for add in header + time_stamp_fill(g_sdr_hdr.ts_add.ts); + + return 0; +} + +static int +sdr_add_mgmt_rec(sensor_mgmt_t *p_rec) { + int rec_id = 0; + sdr_rec_t sdr = { 0 }; + sdr_mgmt_t rec = { 0 }; + + // Populate SDR MGMT record + rec.ver = SDR_VERSION; + rec.type = SDR_MGMT_TYPE; + rec.len = SDR_MGMT_LEN; + + rec.slave_addr = p_rec->slave_addr; + rec.chan_no = p_rec->chan_no; + + rec.pwr_state_init = p_rec->pwr_state_init; + rec.dev_caps = p_rec->dev_caps; + rec.ent_id = p_rec->ent_id; + rec.ent_inst = p_rec->ent_inst; + rec.oem = p_rec->oem; + rec.str_type_len = p_rec->str_type_len; + memcpy(rec.str, p_rec->str, SENSOR_STR_SIZE); + + // Copy this record to generic SDR record + memcpy(sdr.rec, &rec, SDR_LEN_MAX); + + // Add this record to SDR repo + if (sdr_add_entry(&sdr, &rec_id)) { + syslog(LOG_ALERT, "sdr_add_mgmt_rec: sdr_add_entry failed\n"); + return -1; + } + + return 0; +} + +static int +sdr_add_disc_rec(sensor_disc_t *p_rec) { + int rec_id = 0; + sdr_rec_t sdr = { 0 }; + sdr_full_t rec = { 0 }; + + // Populate SDR FULL record + rec.ver = SDR_VERSION; + rec.type = SDR_FULL_TYPE; + rec.len = SDR_FULL_LEN; + + rec.owner = p_rec->owner; + rec.lun = p_rec->lun; + + rec.ent_id = p_rec->ent_id; + rec.ent_inst = p_rec->ent_inst; + rec.sensor_init = p_rec->sensor_init; + rec.sensor_caps = p_rec->sensor_caps; + rec.sensor_type = p_rec->sensor_type; + rec.evt_read_type = p_rec->evt_read_type; + memcpy(rec.assert_evt_mask, p_rec->assert_evt_mask, 2); + memcpy(rec.deassert_evt_mask, p_rec->deassert_evt_mask, 2); + memcpy(rec.read_evt_mask, p_rec->read_evt_mask, 2); + rec.oem = p_rec->oem; + rec.str_type_len = p_rec->str_type_len; + memcpy(rec.str, p_rec->str, SENSOR_STR_SIZE); + + // Copy this record to generic SDR record + memcpy(sdr.rec, &rec, SDR_LEN_MAX); + + // Add this record to SDR repo + if (sdr_add_entry(&sdr, &rec_id)) { + syslog(LOG_ALERT, "sdr_add_disc_rec: sdr_add_entry failed\n"); + return -1; + } + + return 0; +} + +static int +sdr_add_thresh_rec(sensor_thresh_t *p_rec) { + int rec_id = 0; + sdr_rec_t sdr = { 0 }; + sdr_full_t rec = { 0 }; + + // Populate SDR FULL record + rec.ver = SDR_VERSION; + rec.type = SDR_FULL_TYPE; + rec.len = SDR_FULL_LEN; + + rec.owner = p_rec->owner; + rec.lun = p_rec->lun; + + rec.ent_id = p_rec->ent_id; + rec.ent_inst = p_rec->ent_inst; + rec.sensor_init = p_rec->sensor_init; + rec.sensor_caps = p_rec->sensor_caps; + rec.sensor_type = p_rec->sensor_type; + rec.evt_read_type = p_rec->evt_read_type; + memcpy(rec.lt_read_mask, p_rec->lt_read_mask, 2); + memcpy(rec.ut_read_mask, p_rec->ut_read_mask, 2); + memcpy(rec.set_thresh_mask, p_rec->set_thresh_mask, 2); + rec.sensor_units1 = p_rec->sensor_units1; + rec.sensor_units2 = p_rec->sensor_units2; + rec.sensor_units3 = p_rec->sensor_units3; + rec.linear = p_rec->linear; + rec.m_val = p_rec->m_val; + rec.m_tolerance = p_rec->m_tolerance; + rec.b_val = p_rec->b_val; + rec.b_accuracy = p_rec->b_accuracy; + rec.analog_flags = p_rec->analog_flags; + rec.nominal = p_rec->nominal; + rec.normal_max = p_rec->normal_max; + rec.normal_min = p_rec->normal_min; + rec.max_reading = p_rec->max_reading; + rec.min_reading = p_rec->min_reading; + rec.unr_thresh = p_rec->unr_thresh; + rec.uc_thresh = p_rec->uc_thresh; + rec.unc_thresh = p_rec->unc_thresh; + rec.lnr_thresh = p_rec->lnr_thresh; + rec.lc_thresh = p_rec->lc_thresh; + rec.lnc_thresh = p_rec->lnc_thresh; + rec.pos_hyst = p_rec->pos_hyst; + rec.neg_hyst = p_rec->neg_hyst; + rec.oem = p_rec->oem; + rec.str_type_len = p_rec->str_type_len; + memcpy(rec.str, p_rec->str, SENSOR_STR_SIZE); + + // Copy this record to generic SDR record + memcpy(sdr.rec, &rec, SDR_LEN_MAX); + + // Add this record to SDR repo + if (sdr_add_entry(&sdr, &rec_id)) { + syslog(LOG_ALERT, "sdr_add_thresh_rec: sdr_add_entry failed\n"); + return -1; + } + + return 0; +} + +static int +sdr_add_oem_rec(sensor_oem_t *p_rec) { + int rec_id = 0; + sdr_rec_t sdr = { 0 }; + sdr_oem_t rec = { 0 }; + + // Populate SDR OEM record + rec.ver = SDR_VERSION; + rec.type = SDR_OEM_TYPE; + rec.len = SDR_OEM_LEN; + + memcpy(rec.mfr_id, p_rec->mfr_id, 3); + memcpy(rec.oem_data, p_rec->oem_data, SENSOR_OEM_DATA_SIZE); + + // Copy this record to generic SDR record + memcpy(sdr.rec, &rec, SDR_LEN_MAX); + + // Add this record to SDR repo + if (sdr_add_entry(&sdr, &rec_id)) { + syslog(LOG_ALERT, "sdr_add_oem_rec: sdr_add_entry failed\n"); + return -1; + } + + return 0; +} + +// Platform specific SEL API entry points +// Retrieve time stamp for recent add operation +void +sdr_ts_recent_add(time_stamp_t *ts) { + memcpy(ts->ts, g_sdr_hdr.ts_add.ts, 0x04); +} + +// Retrieve time stamp for recent erase operation +void +sdr_ts_recent_erase(time_stamp_t *ts) { + memcpy(ts->ts, g_sdr_hdr.ts_erase.ts, 0x04); +} + +// Retrieve total number of entries in SDR repo +int +sdr_num_entries(void) { + return (g_sdr_hdr.end - g_sdr_hdr.begin); +} + +// Retrieve total free space available in SDR repo +int +sdr_free_space(void) { + int total_space; + int used_space; + + total_space = SDR_RECORDS_MAX * sizeof(sdr_rec_t); + used_space = sdr_num_entries() * sizeof(sdr_rec_t); + + return (total_space - used_space); +} + +// Reserve an ID that will be used in later operations +// IPMI/Section 33.11 +int +sdr_rsv_id() { + // Increment the current reservation ID and return + if (g_rsv_id++ == SDR_RSVID_MAX) { + g_rsv_id = SDR_RSVID_MIN; + } + + return g_rsv_id; +} + +// Get the SDR entry for a given record ID +// IPMI/Section 33.12 +int +sdr_get_entry(int rsv_id, int read_rec_id, sdr_rec_t *rec, + int *next_rec_id) { + + int index; + + // Make sure the rsv_id matches + if (rsv_id != g_rsv_id) { + syslog(LOG_ALERT, "sdr_get_entry: Reservation ID mismatch\n"); + return -1; + } + + // Find the index in to array based on given index + if (read_rec_id == SDR_RECID_FIRST) { + index = g_sdr_hdr.begin; + } else if (read_rec_id == SDR_RECID_LAST) { + index = g_sdr_hdr.end - 1; + } else { + index = read_rec_id - 1; + } + + // If the SDR repo is empty return error + if (sdr_num_entries() == 0) { + syslog(LOG_ALERT, "sdr_get_entry: No entries\n"); + return -1; + } + + // Check for boundary conditions + if ((index < SDR_INDEX_MIN) || (index > SDR_INDEX_MAX)) { + syslog(LOG_ALERT, "sdr_get_entry: Invalid Record ID %d\n", read_rec_id); + return -1; + } + + // Check to make sure the given id is valid + if (index < g_sdr_hdr.begin || index >= g_sdr_hdr.end) { + syslog(LOG_ALERT, "sdr_get_entry: Wrong Record ID %d\n", read_rec_id); + return -1; + } + + memcpy(rec->rec, g_sdr_data[index].rec, sizeof(sdr_rec_t)); + + // Return the next record ID in the log + *next_rec_id = ++read_rec_id; + + // If this is the last entry in the log, return 0xFFFF + if (*next_rec_id == g_sdr_hdr.end) { + *next_rec_id = SDR_RECID_LAST; + } + + return 0; +} + + +// Initialize SDR Repo structure +int +sdr_init(void) { + int num; + int i; + sensor_mgmt_t *p_mgmt; + sensor_thresh_t *p_thresh; + sensor_disc_t *p_disc; + sensor_oem_t *p_oem; + + // Populate SDR Header + g_sdr_hdr.magic = SDR_HDR_MAGIC; + g_sdr_hdr.version = SDR_HDR_VERSION; + g_sdr_hdr.begin = SDR_INDEX_MIN; + g_sdr_hdr.end = SDR_INDEX_MIN; + memset(g_sdr_hdr.ts_add.ts, 0x0, 4); + memset(g_sdr_hdr.ts_erase.ts, 0x0, 4); + + // Populate all mgmt control sensors + plat_sensor_mgmt_info(&num, &p_mgmt); + for (i = 0; i < num; i++) { + sdr_add_mgmt_rec(&p_mgmt[i]); + } + + // Populate all discrete sensors + plat_sensor_disc_info(&num, &p_disc); + for (i = 0; i < num; i++) { + sdr_add_disc_rec(&p_disc[i]); + } + + // Populate all threshold sensors + plat_sensor_thresh_info(&num, &p_thresh); + for (i = 0; i < num; i++) { + sdr_add_thresh_rec(&p_thresh[i]); + } + + // Populate all OEM sensors + plat_sensor_oem_info(&num, &p_oem); + for (i = 0; i < num; i++) { + sdr_add_oem_rec(&p_oem[i]); + } + + return 0; +} diff --git a/common/recipes-core/ipmid/files/sdr.h b/common/recipes-core/ipmid/files/sdr.h new file mode 100644 index 0000000..5c11c31 --- /dev/null +++ b/common/recipes-core/ipmid/files/sdr.h @@ -0,0 +1,72 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SDR_H__ +#define __SDR_H__ + +#include "timestamp.h" + +typedef struct { + unsigned char rec[64]; +} sdr_rec_t; + +// Mgmt. Controller SDR record; IPMI/ Section 43.9 +typedef struct { + // Sensor Record Header + unsigned char rec_id[2]; + unsigned char ver; + unsigned char type; + unsigned char len; + // Record Key Bytes + unsigned char slave_addr; + unsigned char chan_no; + // Record Body Bytes + unsigned char pwr_state_init; + unsigned char dev_caps; + unsigned char rsvd[3]; + unsigned char ent_id; + unsigned char ent_inst; + unsigned char oem; + unsigned char str_type_len; + char str[16]; +} sdr_mgmt_t; + +// OEM type SDR record; IPMI/Section 43.12 +typedef struct { + // Sensor Record Header + unsigned char rec_id[2]; + unsigned char ver; + unsigned char type; + unsigned char len; + // Record Body Bytes + unsigned char mfr_id[3]; + unsigned char oem_data[56]; +} sdr_oem_t; + +void sdr_ts_recent_add(time_stamp_t *ts); +void sdr_ts_recent_erase(time_stamp_t *ts); +int sdr_num_entries(void); +int sdr_free_space(void); +int sdr_rsv_id(); +int sdr_get_entry(int rsv_id, int read_rec_id, sdr_rec_t *rec, + int *next_rec_id); +int sdr_init(void); + +#endif /* __SDR_H__ */ diff --git a/common/recipes-core/ipmid/files/sel.c b/common/recipes-core/ipmid/files/sel.c new file mode 100644 index 0000000..d598bb1 --- /dev/null +++ b/common/recipes-core/ipmid/files/sel.c @@ -0,0 +1,440 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file represents platform specific implementation for storing + * SEL logs and acts as back-end for IPMI stack + * + * TODO: Optimize the file handling to keep file open always instead of + * current open/seek/close + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "sel.h" +#include "timestamp.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> + +// SEL File. +#define SEL_LOG_FILE "/mnt/data/sel.bin" + +// SEL Header magic number +#define SEL_HDR_MAGIC 0xFBFBFBFB + +// SEL Header version number +#define SEL_HDR_VERSION 0x01 + +// SEL Data offset from file beginning +#define SEL_DATA_OFFSET 0x100 + +// SEL reservation IDs can not be 0x00 or 0xFFFF +#define SEL_RSVID_MIN 0x01 +#define SEL_RSVID_MAX 0xFFFE + +// Number of SEL records before wrap +#define SEL_RECORDS_MAX 128 // TODO: Based on need we can make it bigger +#define SEL_ELEMS_MAX (SEL_RECORDS_MAX+1) + +// Index for circular array +#define SEL_INDEX_MIN 0x00 +#define SEL_INDEX_MAX SEL_RECORDS_MAX + +// Record ID can not be 0x0 (IPMI/Section 31) +#define SEL_RECID_MIN (SEL_INDEX_MIN+1) +#define SEL_RECID_MAX (SEL_INDEX_MAX+1) + +// Special RecID value for first and last (IPMI/Section 31) +#define SEL_RECID_FIRST 0x0000 +#define SEL_RECID_LAST 0xFFFF + +// SEL header struct to keep track of SEL Log entries +typedef struct { + int magic; // Magic number to check validity + int version; // version number of this header + int begin; // index to the begining of the log + int end; // index to end of the log + time_stamp_t ts_add; // last addition time stamp + time_stamp_t ts_erase; // last erase time stamp +} sel_hdr_t; + +// Keep track of last Reservation ID +static int g_rsv_id = 0x01; + +// Cached version of SEL Header and data +static sel_hdr_t g_sel_hdr; +static sel_msg_t g_sel_data[SEL_ELEMS_MAX]; + +// Local helper functions to interact with file system +static int +file_get_sel_hdr(void) { + FILE *fp; + + fp = fopen(SEL_LOG_FILE, "r"); + if (fp == NULL) { + return -1; + } + + if (fread(&g_sel_hdr, sizeof(sel_hdr_t), 1, fp) <= 0) { + syslog(LOG_ALERT, "file_get_sel_hdr: fread\n"); + fclose (fp); + return -1; + } + + fclose(fp); + return 0; +} + +static int +file_get_sel_data(void) { + FILE *fp; + int i, j; + + fp = fopen(SEL_LOG_FILE, "r"); + if (fp == NULL) { + syslog(LOG_ALERT, "file_get_sel_data: fopen\n"); + return -1; + } + + if (fseek(fp, SEL_DATA_OFFSET, SEEK_SET)) { + syslog(LOG_ALERT, "file_get_sel_data: fseek\n"); + fclose(fp); + return -1; + } + + unsigned char buf[SEL_ELEMS_MAX * 16]; + if (fread(buf, 1, SEL_ELEMS_MAX * sizeof(sel_msg_t), fp) <= 0) { + syslog(LOG_ALERT, "file_get_sel_data: fread\n"); + fclose(fp); + return -1; + } + + fclose(fp); + + for (i = 0; i < SEL_ELEMS_MAX; i++) { + for (j = 0; j < sizeof(sel_msg_t);j++) { + g_sel_data[i].msg[j] = buf[i*16 + j]; + } + } + + return 0; +} + +static int +file_store_sel_hdr(void) { + FILE *fp; + + fp = fopen(SEL_LOG_FILE, "r+"); + if (fp == NULL) { + syslog(LOG_ALERT, "file_store_sel_hdr: fopen\n"); + return -1; + } + + if (fwrite(&g_sel_hdr, sizeof(sel_hdr_t), 1, fp) <= 0) { + syslog(LOG_ALERT, "file_store_sel_hdr: fwrite\n"); + fclose(fp); + return -1; + } + + fclose(fp); + + return 0; +} + +static int +file_store_sel_data(int recId, sel_msg_t *data) { + FILE *fp; + int index; + + fp = fopen(SEL_LOG_FILE, "r+"); + if (fp == NULL) { + syslog(LOG_ALERT, "file_store_sel_data: fopen\n"); + return -1; + } + + // Records are stored using zero-based index + index = (recId-1) * sizeof(sel_msg_t); + + if (fseek(fp, SEL_DATA_OFFSET+index, SEEK_SET)) { + syslog(LOG_ALERT, "file_store_sel_data: fseek\n"); + fclose(fp); + return -1; + } + + if (fwrite(data->msg, sizeof(sel_msg_t), 1, fp) <= 0) { + syslog(LOG_ALERT, "file_store_sel_data: fwrite\n"); + fclose(fp); + return -1; + } + + fclose(fp); + + return 0; +} + +// Platform specific SEL API entry points +// Retrieve time stamp for recent add operation +void +sel_ts_recent_add(time_stamp_t *ts) { + memcpy(ts->ts, g_sel_hdr.ts_add.ts, 0x04); +} + +// Retrieve time stamp for recent erase operation +void +sel_ts_recent_erase(time_stamp_t *ts) { + memcpy(ts->ts, g_sel_hdr.ts_erase.ts, 0x04); +} + +// Retrieve total number of entries in SEL log +int +sel_num_entries(void) { + if (g_sel_hdr.begin <= g_sel_hdr.end) { + return (g_sel_hdr.end - g_sel_hdr.begin); + } else { + return (g_sel_hdr.end + (SEL_INDEX_MAX - g_sel_hdr.begin + 1)); + } +} + +// Retrieve total free space available in SEL log +int +sel_free_space(void) { + int total_space; + int used_space; + + total_space = SEL_RECORDS_MAX * sizeof(sel_msg_t); + used_space = sel_num_entries() * sizeof(sel_msg_t); + + return (total_space - used_space); +} + +// Reserve an ID that will be used in later operations +// IPMI/Section 31.4 +int +sel_rsv_id() { + // Increment the current reservation ID and return + if (g_rsv_id++ == SEL_RSVID_MAX) { + g_rsv_id = SEL_RSVID_MIN; + } + + return g_rsv_id; +} + +// Get the SEL entry for a given record ID +// IPMI/Section 31.5 +int +sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id) { + + int index; + + // Find the index in to array based on given index + if (read_rec_id == SEL_RECID_FIRST) { + index = g_sel_hdr.begin; + } else if (read_rec_id == SEL_RECID_LAST) { + if (g_sel_hdr.end) { + index = g_sel_hdr.end - 1; + } else { + index = SEL_INDEX_MAX; + } + } else { + index = read_rec_id - 1; + } + + // If the log is empty return error + if (sel_num_entries() == 0) { + syslog(LOG_ALERT, "sel_get_entry: No entries\n"); + return -1; + } + + // Check for boundary conditions + if ((index < SEL_INDEX_MIN) || (index > SEL_INDEX_MAX)) { + syslog(LOG_ALERT, "sel_get_entry: Invalid Record ID %d\n", read_rec_id); + return -1; + } + + // If begin < end, check to make sure the given id falls between + if (g_sel_hdr.begin < g_sel_hdr.end) { + if (index < g_sel_hdr.begin || index >= g_sel_hdr.end) { + syslog(LOG_ALERT, "sel_get_entry: Wrong Record ID %d\n", read_rec_id); + return -1; + } + } + + // If end < begin, check to make sure the given id is valid + if (g_sel_hdr.begin > g_sel_hdr.end) { + if (index >= g_sel_hdr.end && index < g_sel_hdr.begin) { + syslog(LOG_ALERT, "sel_get_entry: Wrong Record ID2 %d\n", read_rec_id); + return -1; + } + } + + memcpy(msg->msg, g_sel_data[index].msg, sizeof(sel_msg_t)); + + // Return the next record ID in the log + *next_rec_id = read_rec_id++; + if (*next_rec_id > SEL_INDEX_MAX) { + *next_rec_id = SEL_INDEX_MIN; + } + + // If this is the last entry in the log, return 0xFFFF + if (*next_rec_id == g_sel_hdr.end) { + *next_rec_id = SEL_RECID_LAST; + } + + return 0; +} + +// Add a new entry in to SEL log +// IPMI/Section 31.6 +int +sel_add_entry(sel_msg_t *msg, int *rec_id) { + // If the SEL if full, roll over. To keep track of empty condition, use + // one empty location less than the max records. + if (sel_num_entries() == SEL_RECORDS_MAX) { + syslog(LOG_ALERT, "sel_add_entry: SEL rollover\n"); + if (++g_sel_hdr.begin > SEL_INDEX_MAX) { + g_sel_hdr.begin = SEL_INDEX_MIN; + } + } + + // Update message's time stamp starting at byte 4 + time_stamp_fill(&msg->msg[3]); + + // Add the enry at end + memcpy(g_sel_data[g_sel_hdr.end].msg, msg->msg, sizeof(sel_msg_t)); + + // Return the newly added record ID + *rec_id = g_sel_hdr.end+1; + + if (file_store_sel_data(*rec_id, msg)) { + syslog(LOG_ALERT, "sel_add_entry: file_store_sel_data\n"); + return -1; + } + + // Increment the end pointer + if (++g_sel_hdr.end > SEL_INDEX_MAX) { + g_sel_hdr.end = SEL_INDEX_MIN; + } + + // Update timestamp for add in header + time_stamp_fill(g_sel_hdr.ts_add.ts); + + // Store the structure persistently + if (file_store_sel_hdr()) { + syslog(LOG_ALERT, "sel_add_entry: file_store_sel_hdr\n"); + return -1; + } + + return 0; +} + +// Erase the SEL completely +// IPMI/Section 31.9 +// Note: To reduce wear/tear, instead of erasing, manipulating the metadata +int +sel_erase(int rsv_id) { + if (rsv_id != g_rsv_id) { + return -1; + } + + // Erase SEL Logs + g_sel_hdr.begin = SEL_INDEX_MIN; + g_sel_hdr.end = SEL_INDEX_MIN; + + // Update timestamp for erase in header + time_stamp_fill(g_sel_hdr.ts_erase.ts); + + // Store the structure persistently + if (file_store_sel_hdr()) { + syslog(LOG_ALERT, "sel_erase: file_store_sel_hdr\n"); + return -1; + } + + return 0; +} + +// To get the erase status while erase happens +// IPMI/Section 31.2 +// Note: Since we are not doing offline erasing, need not return in-progress state +int +sel_erase_status(int rsv_id, sel_erase_stat_t *status) { + if (rsv_id != g_rsv_id) { + return -1; + } + + // Since we do not do any offline erasing, always return erase done + *status = SEL_ERASE_DONE; + + return 0; +} + +// Initialize SEL log file +int +sel_init(void) { + FILE *fp; + int i; + + // Check if the file exists or not + if (access(SEL_LOG_FILE, F_OK) == 0) { + // Since file is present, fetch all the contents to cache + if (file_get_sel_hdr()) { + syslog(LOG_ALERT, "init_sel: file_get_sel_hdr\n"); + return -1; + } + + if (file_get_sel_data()) { + syslog(LOG_ALERT, "init_sel: file_get_sel_data\n"); + return -1; + } + + return 0; + } + + // File not present, so create the file + fp = fopen(SEL_LOG_FILE, "w+"); + if (fp == NULL) { + syslog(LOG_ALERT, "init_sel: fopen\n"); + return -1; + } + + fclose (fp); + + // Populate SEL Header in to the file + g_sel_hdr.magic = SEL_HDR_MAGIC; + g_sel_hdr.version = SEL_HDR_VERSION; + g_sel_hdr.begin = SEL_INDEX_MIN; + g_sel_hdr.end = SEL_INDEX_MIN; + memset(g_sel_hdr.ts_add.ts, 0x0, 4); + memset(g_sel_hdr.ts_erase.ts, 0x0, 4); + + if (file_store_sel_hdr()) { + syslog(LOG_ALERT, "init_sel: file_store_sel_hdr\n"); + return -1; + } + + // Populate SEL Data in to the file + for (i = 1; i <= SEL_RECORDS_MAX; i++) { + sel_msg_t msg = {0}; + if (file_store_sel_data(i, &msg)) { + syslog(LOG_ALERT, "init_sel: file_store_sel_data\n"); + return -1; + } + } + + return 0; +} diff --git a/common/recipes-core/ipmid/files/sel.h b/common/recipes-core/ipmid/files/sel.h new file mode 100644 index 0000000..3bb9a2f --- /dev/null +++ b/common/recipes-core/ipmid/files/sel.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SEL_H__ +#define __SEL_H__ + +#include "timestamp.h" + +enum { + IPMI_SEL_INIT_ERASE = 0xAA, + IPMI_SEL_ERASE_STAT = 0x00, +}; + +typedef enum { + SEL_ERASE_IN_PROG = 0x00, + SEL_ERASE_DONE = 0x01, +} sel_erase_stat_t; + +typedef struct { + unsigned char msg[16]; +} sel_msg_t; + +void sel_ts_recent_add(time_stamp_t *ts); +void sel_ts_recent_erase(time_stamp_t *ts); +int sel_num_entries(void); +int sel_free_space(void); +int sel_rsv_id(); +int sel_get_entry(int read_rec_id, sel_msg_t *msg, int *next_rec_id); +int sel_add_entry(sel_msg_t *msg, int *rec_id); +int sel_erase(int rsv_id); +int sel_erase_status(int rsv_id, sel_erase_stat_t *status); +int sel_init(void); + +#endif /* __SEL_H__ */ diff --git a/common/recipes-core/ipmid/files/sensor.h b/common/recipes-core/ipmid/files/sensor.h new file mode 100644 index 0000000..5d8c11a --- /dev/null +++ b/common/recipes-core/ipmid/files/sensor.h @@ -0,0 +1,117 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SENSOR_H__ +#define __SENSOR_H__ + +#include "timestamp.h" + +#define IANA_ID_SIZE 3 +#define SENSOR_STR_SIZE 16 +#define SENSOR_OEM_DATA_SIZE 56 + +// Threshold Sensor Descriptor +typedef struct { + unsigned char owner; + unsigned char lun; + unsigned char sensor_num; + unsigned char ent_id; + unsigned char ent_inst; + unsigned char sensor_init; + unsigned char sensor_caps; + unsigned char sensor_type; + unsigned char evt_read_type; + unsigned char lt_read_mask[2]; + unsigned char ut_read_mask[2]; + unsigned char set_thresh_mask[2]; + unsigned char sensor_units1; + unsigned char sensor_units2; + unsigned char sensor_units3; + unsigned char linear; + unsigned char m_val; + unsigned char m_tolerance; + unsigned char b_val; + unsigned char b_accuracy; + unsigned char accuracy_dir; + unsigned char rb_exp; + unsigned char analog_flags; + unsigned char nominal; + unsigned char normal_max; + unsigned char normal_min; + unsigned char max_reading; + unsigned char min_reading; + unsigned char unr_thresh; + unsigned char uc_thresh; + unsigned char unc_thresh; + unsigned char lnr_thresh; + unsigned char lc_thresh; + unsigned char lnc_thresh; + unsigned char pos_hyst; + unsigned char neg_hyst; + unsigned char oem; + unsigned char str_type_len; + char str[SENSOR_STR_SIZE]; +} sensor_thresh_t; + +// Discrete Sensor Descriptor +typedef struct { + unsigned char owner; + unsigned char lun; + unsigned char sensor_num; + unsigned char ent_id; + unsigned char ent_inst; + unsigned char sensor_init; + unsigned char sensor_caps; + unsigned char sensor_type; + unsigned char evt_read_type; + unsigned char assert_evt_mask[2]; + unsigned char deassert_evt_mask[2]; + unsigned char read_evt_mask[2]; + unsigned char oem; + unsigned char str_type_len; + char str[SENSOR_STR_SIZE]; +} sensor_disc_t; + +// Mgmt. Controller Sensor Descriptor +typedef struct { + unsigned char slave_addr; + unsigned char chan_no; + unsigned char pwr_state_init; + unsigned char dev_caps; + unsigned char ent_id; + unsigned char ent_inst; + unsigned char oem; + unsigned char str_type_len; + char str[SENSOR_STR_SIZE]; +} sensor_mgmt_t; + +// OEM type Sensor Descriptor +typedef struct { + unsigned char mfr_id[IANA_ID_SIZE]; + unsigned char oem_data[SENSOR_OEM_DATA_SIZE]; +} sensor_oem_t; + +void plat_sensor_mgmt_info(int *num, sensor_mgmt_t **p_sensor); +void plat_sensor_disc_info(int *num, sensor_disc_t **p_sensor); +void plat_sensor_thresh_info(int *num, sensor_thresh_t **p_sensor); +void plat_sensor_oem_info(int *num, sensor_oem_t **p_sensor); +int plat_sensor_init(void); + +#endif /* __SENSOR_H__ */ diff --git a/common/recipes-core/ipmid/files/timestamp.c b/common/recipes-core/ipmid/files/timestamp.c new file mode 100644 index 0000000..11ac03e --- /dev/null +++ b/common/recipes-core/ipmid/files/timestamp.c @@ -0,0 +1,46 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file is a helper file to fill timestamps from platform + * used by SEL Logs, SDR records etc. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +#include <sys/time.h> +#include <time.h> + +// Local helper function to fill time stamp +void +time_stamp_fill(unsigned char *ts) { + unsigned int time; + struct timeval tv; + + gettimeofday(&tv, NULL); + + time = tv.tv_sec; + ts[0] = time & 0xFF; + ts[1] = (time >> 8) & 0xFF; + ts[2] = (time >> 16) & 0xFF; + ts[3] = (time >> 24) & 0xFF; + + return; +} diff --git a/common/recipes-core/ipmid/files/timestamp.h b/common/recipes-core/ipmid/files/timestamp.h new file mode 100644 index 0000000..430dd23 --- /dev/null +++ b/common/recipes-core/ipmid/files/timestamp.h @@ -0,0 +1,30 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __TIMESTAMP_H__ +#define __TIMESTAMP_H__ + +typedef struct { + unsigned char ts[4]; +} time_stamp_t; + +void time_stamp_fill(unsigned char *ts); + +#endif /* __TIMESTAMP_H__ */ diff --git a/common/recipes-core/ipmid/ipmid_0.2.bb b/common/recipes-core/ipmid/ipmid_0.2.bb new file mode 100644 index 0000000..14c8c7f --- /dev/null +++ b/common/recipes-core/ipmid/ipmid_0.2.bb @@ -0,0 +1,42 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "IPMI Daemon" +DESCRIPTION = "Daemon to handle IPMI Messages." +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://ipmid.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://Makefile \ + file://ipmid.c \ + file://timestamp.c \ + file://timestamp.h \ + file://sel.c \ + file://sel.h \ + file://sdr.c \ + file://sdr.h \ + file://sensor.h \ + file://fruid.h \ + " + +DEPENDS += " libpal " + +binfiles = "ipmid" + +pkgdir = "ipmid" diff --git a/common/recipes-core/power-util/files/Makefile b/common/recipes-core/power-util/files/Makefile new file mode 100644 index 0000000..97ee9d5 --- /dev/null +++ b/common/recipes-core/power-util/files/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +all: power-util + + +power-util: power-util.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o power-util diff --git a/common/recipes-core/power-util/files/power-util.c b/common/recipes-core/power-util/files/power-util.c new file mode 100644 index 0000000..0fda9d6 --- /dev/null +++ b/common/recipes-core/power-util/files/power-util.c @@ -0,0 +1,295 @@ +/* + * power-util + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <syslog.h> +#include <stdint.h> +#include <string.h> +#include <getopt.h> +#include <stdbool.h> +#include <fcntl.h> +#include <openbmc/pal.h> + +#define POWER_ON_STR "on" +#define POWER_OFF_STR "off" + +const char *pwr_option_list = "status, graceful-shutdown, off, on, cycle, 12V-off," + "12V-on, 12V-cycle"; + +enum { + PWR_STATUS = 1, + PWR_GRACEFUL_SHUTDOWN, + PWR_OFF, + PWR_ON, + PWR_CYCLE, + PWR_12V_OFF, + PWR_12V_ON, + PWR_12V_CYCLE, + PWR_SLED_CYCLE +}; + +static int +set_last_pwr_state(uint8_t fru, char * state) { + + int ret; + char key[MAX_KEY_LEN] = {0}; + + sprintf(key, "pwr_server%d_last_state", (int) fru); + + ret = pal_set_key_value(key, state); + if (ret < 0) { + syslog(LOG_ALERT, "set_last_pwr_state: pal_set_key_value failed for " + "fru %u", fru); + } + return ret; +} + +static void +print_usage() { + printf("Usage: power-util [ %s ] [ %s ]\nUsage: power-util sled-cycle\n", + pal_server_list, pwr_option_list); +} + +static int +get_power_opt(char *option, uint8_t *opt) { + + if (!strcmp(option, "status")) { + *opt = PWR_STATUS; + } else if (!strcmp(option, "graceful-shutdown")) { + *opt = PWR_GRACEFUL_SHUTDOWN; + } else if (!strcmp(option, "off")) { + *opt = PWR_OFF; + } else if (!strcmp(option, "on")) { + *opt = PWR_ON; + } else if (!strcmp(option, "cycle")) { + *opt = PWR_CYCLE; + } else if (!strcmp(option, "12V-off")) { + *opt = PWR_12V_OFF; + } else if (!strcmp(option, "12V-on")) { + *opt = PWR_12V_ON; + } else if (!strcmp(option, "12V-cycle")) { + *opt = PWR_12V_CYCLE; + } else if (!strcmp(option, "sled-cycle")) { + *opt = PWR_SLED_CYCLE; + } else { + return -1; + } + + return 0; +} + +static int +power_util(uint8_t fru, uint8_t opt) { + + int ret; + uint8_t status; + + switch(opt) { + case PWR_STATUS: + ret = pal_get_server_power(fru, &status); + if (ret < 0) { + syslog(LOG_ALERT, "power_util: pal_get_server_power failed for fru %u\n", fru); + return ret; + } + printf("Power status for fru %u : %s\n", fru, status?"ON":"OFF"); + break; + + case PWR_GRACEFUL_SHUTDOWN: + + printf("Shutting down fru %u gracefully...\n", fru); + + ret = pal_set_server_power(fru, SERVER_GRACEFUL_SHUTDOWN); + if (ret < 0) { + syslog(LOG_ALERT, "power_util: pal_set_server_power failed for" + " fru %u", fru); + return ret; + } else if (ret == 1) { + printf("fru %u is already powered OFF...\n", fru); + return 0; + } + + ret = set_last_pwr_state(fru, POWER_OFF_STR); + if (ret < 0) { + return ret; + } + + ret = pal_set_led(fru, LED_STATE_OFF); + if (ret < 0) { + syslog(LOG_ALERT, "power_util: pal_set_led failed for fru %u", fru); + return ret; + } + break; + + case PWR_OFF: + + printf("Powering fru %u to OFF state...\n", fru); + + ret = pal_set_server_power(fru, SERVER_POWER_OFF); + if (ret < 0) { + syslog(LOG_ALERT, "power_util: pal_set_server_power failed for" + " fru %u", fru); + return ret; + } else if (ret == 1) { + printf("fru %u is already powered OFF...\n", fru); + return 0; + } + + ret = set_last_pwr_state(fru, POWER_OFF_STR); + if (ret < 0) { + return ret; + } + + ret = pal_set_led(fru, LED_STATE_OFF); + if (ret < 0) { + syslog(LOG_ALERT, "power_util: pal_set_led failed for fru %u", fru); + return ret; + } + break; + + case PWR_ON: + + printf("Powering fru %u to ON state...\n", fru); + + ret = pal_set_server_power(fru, SERVER_POWER_ON); + if (ret < 0) { + syslog(LOG_ALERT, "power_util: pal_set_server_power failed for" + " fru %u", fru); + return ret; + } else if (ret == 1) { + printf("fru %u is already powered ON...\n", fru); + return 0; + } + + ret = set_last_pwr_state(fru, POWER_ON_STR); + if (ret < 0) { + return ret; + } + + ret = pal_set_led(fru, LED_STATE_ON); + if (ret < 0) { + syslog(LOG_ALERT, "power_util: pal_set_led failed for fru %u", fru); + return ret; + } + break; + + case PWR_CYCLE: + + printf("Power cycling fru %u...\n", fru); + + ret = pal_set_server_power(fru, SERVER_POWER_CYCLE); + if (ret < 0) { + syslog(LOG_ALERT, "power_util: pal_set_server_power failed for" + " fru %u", fru); + return ret; + } + + ret = set_last_pwr_state(fru, POWER_ON_STR); + if (ret < 0) { + return ret; + } + + ret = pal_set_led(fru, LED_STATE_ON); + if (ret < 0) { + syslog(LOG_ALERT, "power_util: pal_set_led failed for fru %u", fru); + return ret; + } + break; + + case PWR_12V_OFF: + ret = 0; // TODO: Need to add the API to support this power state setting + break; + + case PWR_12V_ON: + ret = 0; // TODO: Need to add the API to support this power state setting + break; + + case PWR_12V_CYCLE: + ret = 0; // TODO: Need to add the API to support this power state setting + break; + + case PWR_SLED_CYCLE: + pal_sled_cycle(); + break; + + default: + syslog(LOG_ALERT, "power_util: wrong option"); + + } + + return ret; +} + +int +main(int argc, char **argv) { + + int ret; + + uint8_t fru, status, opt; + char *option; + + /* Check for sled-cycle */ + if (argc < 2 || argc > 3) { + print_usage(); + exit (-1); + } + + option = argc == 2 ? argv[1] : argv [2]; + + ret = get_power_opt(option, &opt); + /* If argc is 2, the option is sled-cycle */ + if ((ret < 0) || (argc == 2 && opt != PWR_SLED_CYCLE)) { + printf("Wrong option: %s\n", option); + print_usage(); + exit(-1); + } + + if (argc > 2) { + ret = pal_get_fru_id(argv[1], &fru); + if (ret < 0) { + printf("Wrong fru: %s\n", argv[1]); + print_usage(); + exit(-1); + } + } else { + fru = -1; + } + + if (argc > 2) { + ret = pal_is_server_prsnt(fru, &status); + if (ret < 0) { + printf("pal_is_server_prsnt failed for fru: %d\n", fru); + print_usage(); + exit(-1); + } + if (status == 0) { + printf("%s is empty!\n", argv[1]); + print_usage(); + exit(-1); + } + } + + ret = power_util(fru, opt); + if (ret < 0) { + print_usage(); + return ret; + } +} diff --git a/common/recipes-core/power-util/power-util_0.1.bb b/common/recipes-core/power-util/power-util_0.1.bb new file mode 100644 index 0000000..69ef2ad --- /dev/null +++ b/common/recipes-core/power-util/power-util_0.1.bb @@ -0,0 +1,36 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Power Utility" +DESCRIPTION = "Utility for Power Policy and Management" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://power-util.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238" + +SRC_URI = "file://Makefile \ + file://power-util.c \ + " +S = "${WORKDIR}" + +LDFLAGS =+ " -lpal " + +DEPENDS =+ " libpal " + +binfiles = "power-util" + +pkgdir = "power-util" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + install -m 755 power-util ${dst}/power-util + ln -snf ../fbpackages/${pkgdir}/power-util ${bin}/power-util +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/power-util ${prefix}/local/bin" + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-core/sensor-mon/files/Makefile b/common/recipes-core/sensor-mon/files/Makefile new file mode 100644 index 0000000..68a9fe7 --- /dev/null +++ b/common/recipes-core/sensor-mon/files/Makefile @@ -0,0 +1,26 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +all: sensord + +sensord: sensord.c + $(CC) $(CFLAGS) -D _XOPEN_SOURCE -pthread -lm -std=c99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o sensord diff --git a/common/recipes-core/sensor-mon/files/sensord.c b/common/recipes-core/sensor-mon/files/sensord.c new file mode 100644 index 0000000..1852af3 --- /dev/null +++ b/common/recipes-core/sensor-mon/files/sensord.c @@ -0,0 +1,1031 @@ +/* + * sensord + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <stdint.h> +#include <math.h> +#include <string.h> +#include <pthread.h> +#include <sys/file.h> +#include <facebook/bic.h> +#include <openbmc/ipmi.h> +#include <openbmc/sdr.h> +#ifdef CONFIG_YOSEMITE +#include <facebook/yosemite_sensor.h> +#endif /* CONFIG_YOSEMITE */ + +#define MAX_SENSOR_NUM 0xFF +#define NORMAL_STATE 0x00 + +#define SETBIT(x, y) (x | (1 << y)) +#define GETBIT(x, y) ((x & (1 << y)) > y) +#define CLEARBIT(x, y) (x & (~(1 << y))) +#define GETMASK(y) (1 << y) + + + +/* Enum for type of Upper and Lower threshold values */ +enum { + UCR_THRESH = 0x01, + UNC_THRESH, + UNR_THRESH, + LCR_THRESH, + LNC_THRESH, + LNR_THRESH, + POS_HYST, + NEG_HYST, +}; + +/* To hold the sensor info and calculated threshold values from the SDR */ +typedef struct { + uint8_t flag; + float ucr_thresh; + float unc_thresh; + float unr_thresh; + float lcr_thresh; + float lnc_thresh; + float lnr_thresh; + float pos_hyst; + float neg_hyst; + int curr_state; + char name[23]; + char units[64]; + +} thresh_sensor_t; + +/* Function pointer to read sensor current value */ +static int (*read_snr_val)(uint8_t, uint8_t, void *); + +#ifdef CONFIG_YOSEMITE + +// TODO: Change to 6 after adding SPB and NIC +#define MAX_NUM_FRUS 4 +#define YOSEMITE_SDR_PATH "/tmp/sdr_%s.bin" + +static thresh_sensor_t snr_slot1[MAX_SENSOR_NUM] = {0}; +static thresh_sensor_t snr_slot2[MAX_SENSOR_NUM] = {0}; +static thresh_sensor_t snr_slot3[MAX_SENSOR_NUM] = {0}; +static thresh_sensor_t snr_slot4[MAX_SENSOR_NUM] = {0}; +static thresh_sensor_t snr_spb[MAX_SENSOR_NUM] = {0}; +static thresh_sensor_t snr_nic[MAX_SENSOR_NUM] = {0}; + +static sensor_info_t sinfo_slot1[MAX_SENSOR_NUM] = {0}; +static sensor_info_t sinfo_slot2[MAX_SENSOR_NUM] = {0}; +static sensor_info_t sinfo_slot3[MAX_SENSOR_NUM] = {0}; +static sensor_info_t sinfo_slot4[MAX_SENSOR_NUM] = {0}; +static sensor_info_t sinfo_spb[MAX_SENSOR_NUM] = {0}; +static sensor_info_t sinfo_nic[MAX_SENSOR_NUM] = {0}; +#endif /* CONFIG_YOSEMITE */ + + +/* + * Returns the pointer to the struct holding all sensor info and + * calculated threshold values for the fru# + */ +static thresh_sensor_t * +get_struct_thresh_sensor(uint8_t fru) { + + thresh_sensor_t *snr; + +#ifdef CONFIG_YOSEMITE + switch (fru) { + case FRU_SLOT1: + snr = snr_slot1; + break; + case FRU_SLOT2: + snr = snr_slot2; + break; + case FRU_SLOT3: + snr = snr_slot3; + break; + case FRU_SLOT4: + snr = snr_slot4; + break; + case FRU_SPB: + snr = snr_spb; + break; + case FRU_NIC: + snr = snr_nic; + break; + default: + syslog(LOG_ALERT, "get_struct_thresh_sensor: Wrong FRU ID %d\n", fru); + return NULL; + } +#endif /* CONFIG_YOSEMITE */ + + return snr; +} + + +/* Returns the all the SDRs for the particular fru# */ +static sensor_info_t * +get_struct_sensor_info(uint8_t fru) { + + sensor_info_t *sinfo; + +#ifdef CONFIG_YOSEMITE + switch (fru) { + case FRU_SLOT1: + sinfo = sinfo_slot1; + break; + case FRU_SLOT2: + sinfo = sinfo_slot2; + break; + case FRU_SLOT3: + sinfo = sinfo_slot3; + break; + case FRU_SLOT4: + sinfo = sinfo_slot4; + break; + case FRU_SPB: + sinfo = sinfo_spb; + break; + case FRU_NIC: + sinfo = sinfo_nic; + break; + default: + syslog(LOG_ALERT, "get_struct_sensor_info: Wrong FRU ID %d\n", fru); + return NULL; + } +#endif /* CONFIG_YOSEMITE */ + + return sinfo; +} + + +/* Returns the SDR for a particular sensor of particular fru# */ +static sdr_full_t * +get_struct_sdr(uint8_t fru, uint8_t snr_num) { + + sdr_full_t *sdr; + sensor_info_t *sinfo; + sinfo = get_struct_sensor_info(fru); + if (sinfo == NULL) { + syslog(LOG_ALERT, "get_struct_sdr: get_struct_sensor_info failed\n"); + return NULL; + } + sdr = &sinfo[snr_num].sdr; + return sdr; +} + +/* Get the threshold values from the SDRs */ +static int +get_sdr_thresh_val(uint8_t fru, uint8_t snr_num, uint8_t thresh, void *value) { + + int ret; + uint8_t x; + uint8_t m_lsb, m_msb, m; + uint8_t b_lsb, b_msb, b; + int8_t b_exp, r_exp; + uint8_t thresh_val; + sdr_full_t *sdr; + + sdr = get_struct_sdr(fru, snr_num); + if (sdr == NULL) { + syslog(LOG_ALERT, "get_sdr_thresh_val: get_struct_sdr failed\n"); + return -1; + } + + switch (thresh) { + case UCR_THRESH: + thresh_val = sdr->uc_thresh; + break; + case UNC_THRESH: + thresh_val = sdr->unc_thresh; + break; + case UNR_THRESH: + thresh_val = sdr->unr_thresh; + break; + case LCR_THRESH: + thresh_val = sdr->lc_thresh; + break; + case LNC_THRESH: + thresh_val = sdr->lnc_thresh; + break; + case LNR_THRESH: + thresh_val = sdr->lnr_thresh; + break; + case POS_HYST: + thresh_val = sdr->pos_hyst; + break; + case NEG_HYST: + thresh_val = sdr->neg_hyst; + break; + default: + syslog(LOG_ERR, "get_sdr_thresh_val: reading unknown threshold val"); + return -1; + } + + // y = (mx + b * 10^b_exp) * 10^r_exp + x = thresh_val; + + m_lsb = sdr->m_val; + m_msb = sdr->m_tolerance >> 6; + m = (m_msb << 8) | m_lsb; + + b_lsb = sdr->b_val; + b_msb = sdr->b_accuracy >> 6; + b = (b_msb << 8) | b_lsb; + + // exponents are 2's complement 4-bit number + b_exp = sdr->rb_exp & 0xF; + if (b_exp > 7) { + b_exp = (~b_exp + 1) & 0xF; + b_exp = -b_exp; + } + r_exp = (sdr->rb_exp >> 4) & 0xF; + if (r_exp > 7) { + r_exp = (~r_exp + 1) & 0xF; + r_exp = -r_exp; + } + + * (float *) value = ((m * x) + (b * pow(10, b_exp))) * (pow(10, r_exp)); + + return 0; +} + +/* + * Populate all fields of thresh_sensor_t struct for a particular sensor. + * Incase the threshold value is 0 mask the check for that threshvold + * value in flag field. + */ +int +init_snr_thresh(uint8_t fru, uint8_t snr_num, uint8_t flag) { + + int value; + float fvalue; + uint8_t op, modifier; + thresh_sensor_t *snr; + + sdr_full_t *sdr; + + sdr = get_struct_sdr(fru, snr_num); + if (sdr == NULL) { + syslog(LOG_ALERT, "init_snr_name: get_struct_sdr failed\n"); + return -1; + } + + snr = get_struct_thresh_sensor(fru); + if (snr == NULL) { + syslog(LOG_ALERT, "init_snr_thresh: get_struct_thresh_sensor failed"); + return -1; + } + + snr[snr_num].flag = flag; + snr[snr_num].curr_state = NORMAL_STATE; + + if (sdr_get_sensor_name(sdr, snr[snr_num].name)) { + syslog(LOG_ALERT, "sdr_get_sensor_name: FRU %d: num: 0x%X: reading name" + " from SDR failed.", fru, snr_num); + return -1; + } + + // TODO: Add support for modifier (Mostly modifier is zero) + if (sdr_get_sensor_units(sdr, &op, &modifier, snr[snr_num].units)) { + syslog(LOG_ALERT, "sdr_get_sensor_units: FRU %d: num 0x%X: reading units" + " from SDR failed.", fru, snr_num); + return -1; + } + + if (get_sdr_thresh_val(fru, snr_num, UCR_THRESH, &fvalue)) { + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, UCR_THRESH", + fru, snr_num, snr[snr_num].name); + } else { + snr[snr_num].ucr_thresh = fvalue; + if (!(fvalue)) { + snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, UCR_THRESH); + syslog(LOG_ALERT, + "FRU: %d, num: 0x%X, %-16s, UCR_THRESH check disabled val->%.2f", + fru, snr_num, snr[snr_num].name, fvalue); + } + } + + if (get_sdr_thresh_val(fru, snr_num, UNC_THRESH, &fvalue)) { + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, UNC_THRESH", + fru, snr_num, snr[snr_num].name); + } else { + snr[snr_num].unc_thresh = fvalue; + if (!(fvalue)) { + snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, UNC_THRESH); + syslog(LOG_ALERT, + "FRU: %d, num: 0x%X, %-16s, UNC_THRESH check disabled val->%.2f", + fru, snr_num, snr[snr_num].name, fvalue); + } + } + + if (get_sdr_thresh_val(fru, snr_num, UNR_THRESH, &fvalue)) { + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, UNR_THRESH", + fru, snr_num, snr[snr_num].name); + } else { + snr[snr_num].unr_thresh = fvalue; + if (!(fvalue)) { + snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, UNR_THRESH); + syslog(LOG_ALERT, + "FRU: %d, num: 0x%X, %-16s, UNR_THRESH check disabled val->%.2f", + fru, snr_num, snr[snr_num].name, fvalue); + } + } + + if (get_sdr_thresh_val(fru, snr_num, LCR_THRESH, &fvalue)) { + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, LCR_THRESH", + fru, snr_num, snr[snr_num].name); + } else { + snr[snr_num].lcr_thresh = fvalue; + if (!(fvalue)) { + snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, LCR_THRESH); + syslog(LOG_ALERT, + "FRU: %d, num: 0x%X, %-16s, LCR_THRESH check disabled val->%.2f", + fru, snr_num, snr[snr_num].name, fvalue); + } + } + + if (get_sdr_thresh_val(fru, snr_num, LNC_THRESH, &fvalue)) { + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, LNC_THRESH", + fru, snr_num, snr[snr_num].name); + } else { + snr[snr_num].lnc_thresh = fvalue; + if (!(fvalue)) { + snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, LNC_THRESH); + syslog(LOG_ALERT, + "FRU: %d, num: 0x%X, %-16s, LNC_THRESH check disabled val->%.2f", + fru, snr_num, snr[snr_num].name, fvalue); + } + } + + if (get_sdr_thresh_val(fru, snr_num, LNR_THRESH, &fvalue)) { + syslog(LOG_ERR, + "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, LNR_THRESH", + fru, snr_num, snr[snr_num].name); + } else { + snr[snr_num].lnr_thresh = fvalue; + if (!(fvalue)) { + snr[snr_num].flag = CLEARBIT(snr[snr_num].flag, LNR_THRESH); + syslog(LOG_ALERT, + "FRU: %d, num: 0x%X, %-16s, LNR_THRESH check disabled val->%.2f", + fru, snr_num, snr[snr_num].name, fvalue); + } + } + + if (get_sdr_thresh_val(fru, snr_num, POS_HYST, &fvalue)) { + syslog(LOG_ERR, "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, POS_HYST", + fru, snr_num, snr[snr_num].name); + } else + snr[snr_num].pos_hyst = fvalue; + + if (get_sdr_thresh_val(fru, snr_num, NEG_HYST, &fvalue)) { + syslog(LOG_ERR, "get_sdr_thresh_val: failed for FRU: %d, num: 0x%X, %-16s, NEG_HYST", + fru, snr_num, snr[snr_num].name); + } else + snr[snr_num].neg_hyst = fvalue; + + return 0; +} + +#ifdef CONFIG_YOSEMITE +/* Initialize all thresh_sensor_t structs for all the Yosemite sensors */ +static void +init_yosemite_snr_thresh(uint8_t fru) { + + int i; + + switch (fru) { + case FRU_SLOT1: + case FRU_SLOT2: + case FRU_SLOT3: + case FRU_SLOT4: + + for (i < 0; i < bic_sensor_cnt; i++) { + init_snr_thresh(fru, bic_sensor_list[i], GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + } + /* + init_snr_thresh(fru, BIC_SENSOR_MB_OUTLET_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCCIN_VR_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCC_GBE_VR_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_1V05PCH_VR_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_SOC_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_MB_INLET_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_PCH_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_SOC_THERM_MARGIN, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VDDR_VR_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCC_GBE_VR_CURR, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_1V05_PCH_VR_CURR, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCCIN_VR_POUT, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCCIN_VR_CURR, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCCIN_VR_VOL, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_INA230_POWER, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_SOC_PACKAGE_PWR, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_SOC_TJMAX, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VDDR_VR_POUT, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VDDR_VR_CURR, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VDDR_VR_VOL, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCC_SCSUS_VR_CURR, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCC_SCSUS_VR_VOL, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCC_SCSUS_VR_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCC_SCSUS_VR_POUT, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCC_GBE_VR_POUT, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_VCC_GBE_VR_VOL, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_1V05_PCH_VR_VOL, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_SOC_DIMMA0_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_SOC_DIMMA1_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_SOC_DIMMB0_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_SOC_DIMMB1_TEMP, GETMASK(UCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_P3V3_MB, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_P12V_MB, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_P1V05_PCH, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_P3V3_STBY_MB, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_P5V_STBY_MB, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_PV_BAT, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_PVDDR, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + + init_snr_thresh(fru, BIC_SENSOR_PVCC_GBE, + GETMASK(UCR_THRESH) | GETMASK(LCR_THRESH)); + // TODO: Add Support for Discrete sensors + // init_snr_thresh(fru, BIC_SENSOR_POST_ERR, //Event-only + // init_snr_thresh(fru, BIC_SENSOR_SYSTEM_STATUS, //Discrete + // init_snr_thresh(fru, BIC_SENSOR_SPS_FW_HLTH); //Event-only + // init_snr_thresh(fru, BIC_SENSOR_POWER_THRESH_EVENT, //Event-only + // init_snr_thresh(fru, BIC_SENSOR_MACHINE_CHK_ERR, //Event-only + // init_snr_thresh(fru, BIC_SENSOR_PCIE_ERR); //Event-only + // init_snr_thresh(fru, BIC_SENSOR_OTHER_IIO_ERR); //Event-only + // init_snr_thresh(fru, BIC_SENSOR_PROC_HOT_EXT); //Event-only + // init_snr_thresh(fru, BIC_SENSOR_POWER_ERR); //Event-only + // init_snr_thresh(fru, , ); //Event-only + // init_snr_thresh(fru, BIC_SENSOR_PROC_FAIL); //Discrete + // init_snr_thresh(fru, BIC_SENSOR_SYS_BOOT_STAT ); //Discrete + // init_snr_thresh(fru, BIC_SENSOR_VR_HOT); //Discrete + // init_snr_thresh(fru, BIC_SENSOR_CPU_DIMM_HOT ); //Discrete + // init_snr_thresh(fru, BIC_SENSOR_CAT_ERR, //Event-only + + */ + + break; + + case FRU_SPB: + // TODO: Add support for threshold calculation for SP sensors + /* + init_snr_thresh(fru, SP_SENSOR_INLET_TEMP, "SP_SENSOR_INLET_TEMP"); + init_snr_thresh(fru, SP_SENSOR_OUTLET_TEMP, "SP_SENSOR_OUTLET_TEMP"); + init_snr_thresh(fru, SP_SENSOR_MEZZ_TEMP, "SP_SENSOR_MEZZ_TEMP"); + init_snr_thresh(fru, SP_SENSOR_FAN0_TACH, "SP_SENSOR_FAN0_TACH"); + init_snr_thresh(fru, SP_SENSOR_FAN1_TACH, "SP_SENSOR_FAN1_TACH"); + init_snr_thresh(fru, SP_SENSOR_AIR_FLOW, "SP_SENSOR_AIR_FLOW"); + init_snr_thresh(fru, SP_SENSOR_P5V, "SP_SENSOR_P5V"); + init_snr_thresh(fru, SP_SENSOR_P12V, "SP_SENSOR_P12V"); + init_snr_thresh(fru, SP_SENSOR_P3V3_STBY, "SP_SENSOR_P3V3_STBY"); + init_snr_thresh(fru, SP_SENSOR_P12V_SLOT0, "SP_SENSOR_P12V_SLOT0"); + init_snr_thresh(fru, SP_SENSOR_P12V_SLOT1, "SP_SENSOR_P12V_SLOT1"); + init_snr_thresh(fru, SP_SENSOR_P12V_SLOT2, "SP_SENSOR_P12V_SLOT2"); + init_snr_thresh(fru, SP_SENSOR_P12V_SLOT3, "SP_SENSOR_P12V_SLOT3"); + init_snr_thresh(fru, SP_SENSOR_P3V3, "SP_SENSOR_P3V3"); + init_snr_thresh(fru, SP_SENSOR_HSC_IN_VOLT, "SP_SENSOR_HSC_IN_VOLT"); + init_snr_thresh(fru, SP_SENSOR_HSC_OUT_CURR, "SP_SENSOR_HSC_OUT_CURR"); + init_snr_thresh(fru, SP_SENSOR_HSC_TEMP, "SP_SENSOR_HSC_TEMP"); + init_snr_thresh(fru, SP_SENSOR_HSC_IN_POWER, "SP_SENSOR_HSC_IN_POWER"); + */ + break; + + case FRU_NIC: + // TODO: Add support for NIC sensor threshold, if any. + break; + + default: + syslog(LOG_ALERT, "init_yosemite_snr_thresh: wrong FRU ID"); + exit(-1); + } +} +#endif /* CONFIG_YOSEMITE */ + +/* Wrapper function to initialize all the platform sensors */ +static void +init_all_snr_thresh() { + int fru; + + char path[64] = {0}; + sensor_info_t *sinfo; + + +#ifdef CONFIG_YOSEMITE + for (fru = FRU_SLOT1; fru < (FRU_SLOT1 + MAX_NUM_FRUS); fru++) { + + if (get_fru_sdr_path(fru, path) < 0) { + syslog(LOG_ALERT, "yosemite_sdr_init: get_fru_sdr_path failed\n"); + continue; + } +#endif /* CONFIG_YOSEMITE */ + + sinfo = get_struct_sensor_info(fru); + + if (sdr_init(path, sinfo) < 0) + syslog(LOG_ERR, "init_all_snr_thresh: sdr_init failed for FRU %d", fru); + } + +#ifdef CONFIG_YOSEMITE + for (fru = FRU_SLOT1; fru < (FRU_SLOT1 + MAX_NUM_FRUS); fru++) { + init_yosemite_snr_thresh(fru); + } +#endif /* CONFIG_YOSEMITE */ +} + + + + +static float +get_snr_thresh_val(uint8_t fru, uint8_t snr_num, uint8_t thresh) { + + float val; + thresh_sensor_t *snr; + + snr = get_struct_thresh_sensor(fru); + + switch (thresh) { + case UCR_THRESH: + val = snr[snr_num].ucr_thresh; + break; + case UNC_THRESH: + val = snr[snr_num].unc_thresh; + break; + case UNR_THRESH: + val = snr[snr_num].unr_thresh; + break; + case LCR_THRESH: + val = snr[snr_num].lcr_thresh; + break; + case LNC_THRESH: + val = snr[snr_num].lnc_thresh; + break; + case LNR_THRESH: + val = snr[snr_num].lnr_thresh; + break; + default: + syslog(LOG_ALERT, "get_snr_thresh_val: wrong thresh enum value"); + exit(-1); + } + + return val; +} + +/* + * Check the curr sensor values against the threshold and + * if the curr val has deasserted, log it. + */ +static void +check_thresh_deassert(uint8_t fru, uint8_t snr_num, uint8_t thresh, + float curr_val) { + uint8_t curr_state = 0; + float thresh_val; + char thresh_name[100]; + thresh_sensor_t *snr; + + snr = get_struct_thresh_sensor(fru); + + if (!GETBIT(snr[snr_num].flag, thresh) || + !GETBIT(snr[snr_num].curr_state, thresh)) + return; + + thresh_val = get_snr_thresh_val(fru, snr_num, thresh); + + switch (thresh) { + case UNC_THRESH: + if (curr_val <= thresh_val) { + curr_state = ~(SETBIT(curr_state, UNR_THRESH) | + SETBIT(curr_state, UCR_THRESH) | + SETBIT(curr_state, UNC_THRESH)); + sprintf(thresh_name, "Upper Non Critical"); + } + break; + + case UCR_THRESH: + if (curr_val <= thresh_val) { + curr_state = ~(SETBIT(curr_state, UCR_THRESH) | + SETBIT(curr_state, UNR_THRESH)); + sprintf(thresh_name, "Upper Critical"); + } + break; + + case UNR_THRESH: + if (curr_val <= thresh_val) { + curr_state = ~(SETBIT(curr_state, UNR_THRESH)); + sprintf(thresh_name, "Upper Non Recoverable"); + } + break; + + case LNC_THRESH: + if (curr_val >= thresh_val) { + curr_state = ~(SETBIT(curr_state, LNR_THRESH) | + SETBIT(curr_state, LCR_THRESH) | + SETBIT(curr_state, LNC_THRESH)); + sprintf(thresh_name, "Lower Non Critical"); + } + break; + + case LCR_THRESH: + if (curr_val >= thresh_val) { + curr_state = ~(SETBIT(curr_state, LCR_THRESH) | + SETBIT(curr_state, LNR_THRESH)); + sprintf(thresh_name, "Lower Critical"); + } + break; + + case LNR_THRESH: + if (curr_val >= thresh_val) { + curr_state = ~(SETBIT(curr_state, LNR_THRESH)); + sprintf(thresh_name, "Lower Non Recoverable"); + } + break; + + default: + syslog(LOG_ALERT, "get_snr_thresh_val: wrong thresh enum value"); + exit(-1); + } + + if (curr_state) { + snr[snr_num].curr_state &= curr_state; + syslog(LOG_CRIT, "DEASSERT: %s threshold raised - FRU: %d, num: 0x%X," + " snr: %-16s,",thresh_name, fru, snr_num, snr[snr_num].name); + syslog(LOG_CRIT, "curr_val: %.2f %s, thresh_val: %.2f %s cf: %u", + curr_val, snr[snr_num].units, thresh_val, snr[snr_num].units, snr[snr_num].curr_state); + } +} + + +/* + * Check the curr sensor values against the threshold and + * if the curr val has asserted, log it. + */ +static void +check_thresh_assert(uint8_t fru, uint8_t snr_num, uint8_t thresh, + float curr_val) { + uint8_t curr_state = 0; + float thresh_val; + char thresh_name[100]; + thresh_sensor_t *snr; + + snr = get_struct_thresh_sensor(fru); + + if (!GETBIT(snr[snr_num].flag, thresh) || + GETBIT(snr[snr_num].curr_state, thresh)) + return; + + thresh_val = get_snr_thresh_val(fru, snr_num, thresh); + + switch (thresh) { + case UNR_THRESH: + if (curr_val >= thresh_val) { + curr_state = (SETBIT(curr_state, UNR_THRESH) | + SETBIT(curr_state, UCR_THRESH) | + SETBIT(curr_state, UNC_THRESH)); + sprintf(thresh_name, "Upper Non Recoverable"); + } + break; + + case UCR_THRESH: + if (curr_val >= thresh_val) { + curr_state = (SETBIT(curr_state, UCR_THRESH) | + SETBIT(curr_state, UNC_THRESH)); + sprintf(thresh_name, "Upper Critical"); + } + break; + + case UNC_THRESH: + if (curr_val >= thresh_val) { + curr_state = (SETBIT(curr_state, UNC_THRESH)); + sprintf(thresh_name, "Upper Non Critical"); + } + break; + + case LNR_THRESH: + if (curr_val <= thresh_val) { + curr_state = (SETBIT(curr_state, LNR_THRESH) | + SETBIT(curr_state, LCR_THRESH) | + SETBIT(curr_state, LNC_THRESH)); + sprintf(thresh_name, "Lower Non Recoverable"); + } + break; + + case LCR_THRESH: + if (curr_val <= thresh_val) { + curr_state = (SETBIT(curr_state, LCR_THRESH) | + SETBIT(curr_state, LNC_THRESH)); + sprintf(thresh_name, "Lower Critical"); + } + break; + + case LNC_THRESH: + if (curr_val <= thresh_val) { + curr_state = (SETBIT(curr_state, LNC_THRESH)); + sprintf(thresh_name, "Lower Non Critical"); + } + break; + + default: + syslog(LOG_ALERT, "get_snr_thresh_val: wrong thresh enum value"); + exit(-1); + } + + if (curr_state) { + curr_state &= snr[snr_num].flag; + snr[snr_num].curr_state |= curr_state; + syslog(LOG_CRIT, "ASSERT: %s threshold raised - FRU: %d, num: 0x%X," + " snr: %-16s,",thresh_name, fru, snr_num, snr[snr_num].name); + syslog(LOG_CRIT, "curr_val: %.2f %s, thresh_val: %.2f %s cf: %u", + curr_val, snr[snr_num].units, thresh_val, snr[snr_num].units, snr[snr_num].curr_state); + } +} + +/* + * Starts monitoring all the sensors on a fru for all the threshold values. + * Each pthread runs this monitoring for a different fru. + */ +static void * +snr_monitor(void *arg) { + + uint8_t fru = *(uint8_t *) arg; + int f, ret, snr_num; + float normal_val, curr_val; + thresh_sensor_t *snr; + +#ifdef TESTING + float temp_thresh; + int cnt = 0; +#endif /* TESTING */ + + snr = get_struct_thresh_sensor(fru); + if (snr == NULL) { + syslog(LOG_ALERT, "snr_monitor: get_struct_thresh_sensor failed"); + exit(-1); + } + + while(1) { + +#ifdef TESTING + cnt++; +#endif /* TESTING */ + + for (snr_num = 0; snr_num < MAX_SENSOR_NUM; snr_num++) { + curr_val = 0; + if (snr[snr_num].flag) { + if (!(ret = read_snr_val(fru, snr_num, &curr_val))) { + + +#ifdef TESTING + /* + * The curr_val crosses UCR and then return to a state + * where UNC < curr_val < UCR and then eventually back to normal. + */ + if (cnt == 5 && snr_num == BIC_SENSOR_MB_INLET_TEMP) { + snr[snr_num].flag |= SETBIT(snr[snr_num].flag, UNC_THRESH); + temp_thresh = snr[snr_num].ucr_thresh; + snr[snr_num].ucr_thresh = 20.0; + snr[snr_num].unc_thresh = 10.0; + } else if (cnt == 8 && snr_num == BIC_SENSOR_MB_INLET_TEMP) { + snr[snr_num].ucr_thresh = temp_thresh; + } else if (cnt == 10 && snr_num == BIC_SENSOR_MB_INLET_TEMP) { + snr[snr_num].unc_thresh = 50.0; + } else if (cnt == 11 && snr_num == BIC_SENSOR_MB_INLET_TEMP) { + snr[snr_num].unc_thresh = 0.0; + snr[snr_num].flag &= CLEARBIT(snr[snr_num].flag, UNC_THRESH); + + } +#endif /* TESTING */ + +#ifdef DEBUG + if (cnt == 2) { + syslog(LOG_INFO, "pthread %d, cnt: %d, num: 0x%X name: %-16s" + " units:%s", fru, cnt, snr_num, snr[snr_num].name, + snr[snr_num].units); + } +#endif /* DEBUG */ + + check_thresh_assert(fru, snr_num, UNR_THRESH, curr_val); + check_thresh_assert(fru, snr_num, UCR_THRESH, curr_val); + check_thresh_assert(fru, snr_num, UNC_THRESH, curr_val); + check_thresh_assert(fru, snr_num, LNR_THRESH, curr_val); + check_thresh_assert(fru, snr_num, LCR_THRESH, curr_val); + check_thresh_assert(fru, snr_num, LNC_THRESH, curr_val); + + check_thresh_deassert(fru, snr_num, UNC_THRESH, curr_val); + check_thresh_deassert(fru, snr_num, UCR_THRESH, curr_val); + check_thresh_deassert(fru, snr_num, UNR_THRESH, curr_val); + check_thresh_deassert(fru, snr_num, LNC_THRESH, curr_val); + check_thresh_deassert(fru, snr_num, LCR_THRESH, curr_val); + check_thresh_deassert(fru, snr_num, LNR_THRESH, curr_val); + + } else { + /* + * Incase the read_snr_val failed for a sensor, + * disable all the threshold checks for that sensor + * after logging an approciate syslog message. + */ + if (ret) { + syslog(LOG_ERR, "FRU: %d, num: 0x%X, snr:%-16s, read failed", + fru, snr_num, snr[snr_num].name); + syslog(LOG_ERR, "FRU: %d, num: 0x%X, snr:%-16s, check disabled", + fru, snr_num, snr[snr_num].name); + snr[snr_num].flag = 0; + //} + } + } /* read_snr_val return check */ + } /* flag check */ + } /* loop for all sensors */ + sleep(5); + } /* while loop*/ +} /* function definition */ + + +/* Spawns a pthread for each fru to monitor all the sensors on it */ +static void +run_sensord(int argc, char **argv) { + int i, arg; + + pthread_t thread_snr[MAX_NUM_FRUS]; + int fru[MAX_NUM_FRUS] = {0}; + + for (arg = 1; arg < argc; arg ++) { +#ifdef CONFIG_YOSEMITE + if (!(strcmp(argv[arg], "slot1"))) + fru[FRU_SLOT1 - 1] = FRU_SLOT1; + else if (!(strcmp(argv[arg], "slot2"))) + fru[FRU_SLOT2 - 1] = FRU_SLOT2; + else if (!(strcmp(argv[arg], "slot3"))) + fru[FRU_SLOT3 - 1] = FRU_SLOT3; + else if (!(strcmp(argv[arg], "slot4"))) + fru[FRU_SLOT4 - 1] = FRU_SLOT4; + else if (!(strcmp(argv[arg], "spb"))) + fru[FRU_SPB - 1] = FRU_SPB; + else if (!(strcmp(argv[arg], "nic"))) + fru[FRU_NIC - 1] = FRU_NIC; + else { + syslog(LOG_ALERT, "Wrong argument: %s", argv[arg]); + exit(1); + } +#endif /* CONFIG_YOSEMITE */ + + } + + for (i = 0; i < MAX_NUM_FRUS; i++) { + if (fru[i]) { + if (pthread_create(&thread_snr[i], NULL, snr_monitor, + (void*) &fru[i]) < 0) { + syslog(LOG_ALERT, "pthread_create for FRU %d failed\n", fru[i]); + } +#ifdef DEBUG + else { + syslog(LOG_ALERT, "pthread_create for FRU %d succeed\n", fru[i]); + } +#endif /* DEBUG */ + } + sleep(1); + } + + for (i = 0; i < MAX_NUM_FRUS; i++) { + if (fru[i]) + pthread_join(thread_snr[i], NULL); + } +} + + +#ifdef DEBUG +void print_snr_thread(uint8_t fru, thresh_sensor_t *snr) +{ + int i; + float curr_val; + + for (i = 1; i <= MAX_SENSOR_NUM; i++) { + if (snr[i].flag) { + curr_val = 0; + if(!(read_snr_val(fru, i, &curr_val))) { + printf("%-30s:\t%.2f %s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n", + snr[i].name, curr_val,snr[i].units, + snr[i].ucr_thresh, + snr[i].unc_thresh, + snr[i].lcr_thresh, + snr[i].lnr_thresh, + snr[i].pos_hyst, + snr[i].neg_hyst); + } else + printf("Reading failed: %-16s\n", snr[i].name); + } + } +} +#endif /* DEBUG */ + +int +main(int argc, void **argv) { + int dev, rc, pid_file; + + if (argc < 2) { + syslog(LOG_ALERT, "Usage: sensord <options>"); + printf("Usage: sensord <options>\n"); +#ifdef CONFIG_YOSEMITE + syslog(LOG_ALERT, "Options: [slot1 | slot2 | slot3 | slot4 | spb | nic]"); + printf("Options: [slot1 | slot2 | slot3 | slot4 | spb | nic]\n"); +#endif /* CONFIG_YOSEMITE */ + exit(1); + } + + pid_file = open("/var/run/sensord.pid", O_CREAT | O_RDWR, 0666); + rc = flock(pid_file, LOCK_EX | LOCK_NB); + if(rc) { + if(EWOULDBLOCK == errno) { + printf("Another sensord instance is running...\n"); + exit(-1); + } + } else { + +#ifdef CONFIG_YOSEMITE + read_snr_val = &yosemite_sensor_read; +#endif /* CONFIG_YOSEMITE */ + + init_all_snr_thresh(); + +#ifdef DEBUG + print_snr_thread(1, snr_slot1); + print_snr_thread(2, snr_slot2); + print_snr_thread(3, snr_slot3); + print_snr_thread(4, snr_slot4); +#endif /* DEBUG */ + + daemon(0,1); + openlog("sensord", LOG_CONS, LOG_DAEMON); + syslog(LOG_INFO, "sensord: daemon started"); + run_sensord(argc, (char **) argv); + } + + return 0; +} diff --git a/common/recipes-core/sensor-mon/sensor-mon_0.1.bb b/common/recipes-core/sensor-mon/sensor-mon_0.1.bb new file mode 100644 index 0000000..adbd4cb --- /dev/null +++ b/common/recipes-core/sensor-mon/sensor-mon_0.1.bb @@ -0,0 +1,58 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "Sensor Monitoring Daemon" +DESCRIPTION = "Daemon for monitoring the sensors" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://sensord.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238" + +SRC_URI = "file://Makefile \ + file://sensord.c \ + " + +S = "${WORKDIR}" + +binfiles = "sensord \ + " + +CFLAGS += " -lsdr " + +DEPENDS += " libsdr " + +pkgdir = "sensor-mon" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${dst}/$f + ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f + done +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/sensor-mon ${prefix}/local/bin" + +# Inhibit complaints about .debug directories for the sensord binary: + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-core/sensor-util/files/Makefile b/common/recipes-core/sensor-util/files/Makefile new file mode 100644 index 0000000..2d39a04 --- /dev/null +++ b/common/recipes-core/sensor-util/files/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +all: sensor-util + + +sensor-util: sensor-util.o + $(CC) $(CFLAGS) -lpal -lrt -lm -std=gnu99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o sensor-util diff --git a/common/recipes-core/sensor-util/files/sensor-util.c b/common/recipes-core/sensor-util/files/sensor-util.c new file mode 100644 index 0000000..eb38d65 --- /dev/null +++ b/common/recipes-core/sensor-util/files/sensor-util.c @@ -0,0 +1,173 @@ +/* + * yosemite-sensors + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <syslog.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <openbmc/pal.h> + +static int +print_usage() { + printf("Usage: sensor-util [ %s ] <sensor num>\n" + "sensor num is optional.", pal_fru_list); +} + +static void +print_single_sensor_reading(uint8_t fru, uint8_t *sensor_list, int sensor_cnt, uint8_t num) { + + int i; + float fvalue; + char name[24]; + char units[64]; + int ret = 0; + + for (i = 0; i < sensor_cnt; i++) { + + if (sensor_list[i] == num) { + ret = 1; + pal_get_sensor_name(fru, sensor_list[i], name); + pal_get_sensor_units(fru, sensor_list[i], units); + + if (pal_sensor_read(fru, sensor_list[i], &fvalue) < 0) { + + printf("pal_sensor_read failed: fru: %d num: 0x%X name: %-23s\n", + fru, sensor_list[i], name); + } else { + printf("%-23s: %.2f %s\n", name, fvalue, units); + } + + break; + } + } + + if (!ret) { + printf("Wrong sensor number!\n"); + print_usage(); + exit(-1); + } +} + +static void +print_sensor_reading(uint8_t fru, uint8_t *sensor_list, int sensor_cnt) { + + int i; + float fvalue; + char name[24]; + char units[64]; + + for (i = 0; i < sensor_cnt; i++) { + + /* Clear the variable */ + sprintf(name, ""); + sprintf(units, ""); + + pal_get_sensor_name(fru, sensor_list[i], name); + pal_get_sensor_units(fru, sensor_list[i], units); + + if (pal_sensor_read(fru, sensor_list[i], &fvalue) < 0) { + + printf("pal_sensor_read failed: fru: %d num: 0x%X name: %-23s\n", + fru, sensor_list[i], name); + } else { + printf("%-23s: %.2f %s\n", name, fvalue, units); + } + } +} + +int +main(int argc, char **argv) { + + int ret; + int sensor_cnt; + uint8_t *sensor_list; + uint8_t fru; + uint8_t num; + + if (argc < 2 || argc > 3) { + print_usage(); + exit(-1); + } + + if (argc == 3) { + errno = 0; + num = (uint8_t) strtol(argv[2], NULL, 0); + if (errno) { + printf("Sensor number format incorrect.\n"); + print_usage(); + exit(-1); + } + } + + + ret = pal_get_fru_id(argv[1], &fru); + if (ret < 0) { + print_usage(); + return ret; + } + + if (fru == 0) { + fru = 1; + while (fru <= MAX_NUM_FRUS) { + + if (fru == FRU_NIC) { + printf("\nsensor-util does not support nic\n"); + exit(-1); + } + + ret = pal_get_fru_sensor_list(fru, &sensor_list, &sensor_cnt); + if (ret < 0) { + return ret; + } + + if (num) { + print_single_sensor_reading(fru, sensor_list, sensor_cnt, num); + } else { + print_sensor_reading(fru, sensor_list, sensor_cnt); + } + + fru++; + printf("\n"); + } + } else { + + if (fru == FRU_NIC) { + printf("\nsensor-util does not support nic\n"); + //exit(-1); + } + + ret = pal_get_fru_sensor_list(fru, &sensor_list, &sensor_cnt); + if (ret < 0) { + return ret; + } + + if (num) { + print_single_sensor_reading(fru, sensor_list, sensor_cnt, num); + } else { + print_sensor_reading(fru, sensor_list, sensor_cnt); + } + } + + return 0; +} diff --git a/common/recipes-core/sensor-util/sensor-util_0.1.bb b/common/recipes-core/sensor-util/sensor-util_0.1.bb new file mode 100644 index 0000000..227ec53 --- /dev/null +++ b/common/recipes-core/sensor-util/sensor-util_0.1.bb @@ -0,0 +1,34 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Sensor Utility" +DESCRIPTION = "Util for reading various sensors" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://sensor-util.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238" + +SRC_URI = "file://Makefile \ + file://sensor-util.c \ + " +S = "${WORKDIR}" + +binfiles = "sensor-util" + +DEPENDS =+ " libpal " + +pkgdir = "sensor-util" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + install -m 755 sensor-util ${dst}/sensor-util + ln -snf ../fbpackages/${pkgdir}/sensor-util ${bin}/sensor-util +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/sensor-util ${prefix}/local/bin" + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-core/watchdog-ctrl/watchdog-ctrl_0.1.bb b/common/recipes-core/watchdog-ctrl/watchdog-ctrl_0.1.bb index 00cf0f9..14c0fee 100644 --- a/common/recipes-core/watchdog-ctrl/watchdog-ctrl_0.1.bb +++ b/common/recipes-core/watchdog-ctrl/watchdog-ctrl_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "Watchdog control utilities." DESCRIPTION = "The utilities to control system watchdog." SECTION = "base" diff --git a/common/recipes-lib/fruid/files/Makefile b/common/recipes-lib/fruid/files/Makefile new file mode 100644 index 0000000..225d5f7 --- /dev/null +++ b/common/recipes-lib/fruid/files/Makefile @@ -0,0 +1,27 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +lib: libfruid.so + +libfruid.so: fruid.c + $(CC) $(CFLAGS) -fPIC -c -o fruid.o fruid.c + $(CC) -shared -o libfruid.so fruid.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libfruid.so diff --git a/common/recipes-lib/fruid/files/fruid.c b/common/recipes-lib/fruid/files/fruid.c new file mode 100644 index 0000000..dc71ac8 --- /dev/null +++ b/common/recipes-lib/fruid/files/fruid.c @@ -0,0 +1,682 @@ +/* + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include "fruid.h" + +#define FIELD_TYPE(x) ((x & (0x03 << 6)) >> 6) +#define FIELD_LEN(x) (x & ~(0x03 << 6)) +#define FIELD_EMPTY "N/A" + +/* Unix time difference between 1970 and 1996. */ +#define UNIX_TIMESTAMP_1996 820454400 + +/* Array for BCD Plus definition. */ +const char bcd_plus_array[] = "0123456789 -.XXX"; + +/* Array for 6-Bit ASCII definition. */ +const char * ascii_6bit[4] = { + " !\"#$%&'()*+,-./", + "0123456789:;<=>?", + "@ABCDEFGHIJKLMNO", + "PQRSTUVWXYZ[\\]^_" +}; + +/* + * calculate_time - calculate time from the unix time stamp stored + * + * @mfg_time : Unix timestamp since 1996 + * + * returns char * for mfg_time_str + * returns NULL for memory allocation failure + */ +static char * calculate_time(uint8_t * mfg_time) +{ + int len; + struct tm * local; + time_t unix_time = 0; + unix_time = ((mfg_time[2] << 16) + (mfg_time[1] << 8) + mfg_time[0]) * 60; + unix_time += UNIX_TIMESTAMP_1996; + + local = localtime(&unix_time); + char * str = asctime(local); + + len = strlen(str); + + char * mfg_time_str = (char *) malloc(len); + if (!mfg_time_str) { + syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); + return NULL; + } + + memset(mfg_time_str, 0, len); + + memcpy(mfg_time_str, str, len); + + mfg_time_str[len - 1] = '\0'; + + return mfg_time_str; +} + +/* + * verify_chksum - verify the zero checksum of the data + * + * @area : offset of the area + * @len : len of the area in bytes + * @chksum_read : stored checksum in the data. + * + * returns 0 if chksum is verified + * returns -1 if there exist a mismatch + */ +static int verify_chksum(uint8_t * area, uint8_t len, uint8_t chksum_read) +{ + int i; + uint8_t chksum = 0; + + for (i = 0; i < len - 1; i++) + chksum += area[i]; + + /* Zero checksum calculation */ + chksum = ~(chksum) + 1; + + return (chksum == chksum_read) ? 0 : -1; +} + +/* + * get_chassis_type - get the Chassis type + * + * @type_hex : type stored in the data + * + * returns char ptr for chassis type string + * returns NULL if type not in the list + */ +static char * get_chassis_type(uint8_t type_hex) +{ + int type, ret; + char type_int[4]; + + ret = sprintf(type_int, "%u", type_hex); + type = atoi(type_int) - 1; + + /* If the type is not in the list defined.*/ + if (type > FRUID_CHASSIS_TYPECODE_MAX || type < FRUID_CHASSIS_TYPECODE_MIN) { + syslog(LOG_INFO, "fruid: chassis area: invalid chassis type\n"); + return NULL; + } + + char * type_str = (char *) malloc(strlen(fruid_chassis_type[type])); + if (!type_str) { + syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); + return NULL; + } + + memcpy(type_str, fruid_chassis_type[type], strlen(fruid_chassis_type[type])); + + return type_str; +} + +/* + * _fruid_area_field_read - read the field data + * + * @offset : offset of the field + * + * returns char ptr for the field data string + */ +static char * _fruid_area_field_read(uint8_t *offset) +{ + int field_type, field_len, field_len_eff; + int idx, idx_eff, val; + char * field; + + /* Bits 7:6 */ + field_type = FIELD_TYPE(offset[0]); + /* Bits 5:0 */ + field_len = FIELD_LEN(offset[0]); + + /* Calculate the effective length of the field data based on type stored. */ + switch (field_type) { + + case TYPE_BINARY: + /* TODO: Need to add support to read data stored in binary type. */ + field_len_eff = 1; + break; + + case TYPE_ASCII_6BIT: + /* + * Every 3 bytes have four 6-bit packed values + * + 6-bit values from the remaining field bytes. + */ + field_len_eff = (field_len / 3) * 4 + (field_len % 3); + break; + + case TYPE_BCD_PLUS: + case TYPE_ASCII_8BIT: + field_len_eff = field_len; + break; + } + + /* If field data is zero, store 'N/A' for that field. */ + field_len_eff > 0 ? (field = (char *) malloc(field_len_eff + 1)) : + (field = (char *) malloc(strlen(FIELD_EMPTY))); + if (!field) { + syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); + return NULL; + } + + memset(field, 0, field_len + 1); + + if (field_len_eff < 1) { + strcpy(field, FIELD_EMPTY); + return field; + } + + /* Retrieve field data depending on the type it was stored. */ + switch (field_type) { + case TYPE_BINARY: + /* TODO: Need to add support to read data stored in binary type. */ + break; + + case TYPE_BCD_PLUS: + + idx = 0; + while (idx != field_len) { + field[idx] = bcd_plus_array[offset[idx + 1] & 0x0F]; + idx++; + } + field[idx] = '\0'; + break; + + case TYPE_ASCII_6BIT: + + idx_eff = 0, idx = 1; + + while (field_len > 0) { + + /* 6-Bits => Bits 5:0 of the first byte */ + val = offset[idx] & 0x3F; + field[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + field_len--; + + if (field_len > 0) { + /* 6-Bits => Bits 3:0 of second byte + Bits 7:6 of first byte. */ + val = ((offset[idx] & 0xC0) >> 6) | + ((offset[idx + 1] & 0x0F) << 2); + field[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + field_len--; + } + + if (field_len > 0) { + /* 6-Bits => Bits 1:0 of third byte + Bits 7:4 of second byte. */ + val = ((offset[idx + 1] & 0xF0) >> 4) | + ((offset[idx + 2] & 0x03) << 4); + field[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + + /* 6-Bits => Bits 7:2 of third byte. */ + val = ((offset[idx + 2] & 0xFC) >> 2); + field[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + + field_len--; + idx += 3; + } + } + /* Add Null terminator */ + field[idx_eff] = '\0'; + break; + + case TYPE_ASCII_8BIT: + + memcpy(field, offset + 1, field_len); + /* Add Null terminator */ + field[field_len] = '\0'; + break; + } + + return field; +} + +/* Free all the memory allocated for fruid information */ +void free_fruid_info(fruid_info_t * fruid) +{ + if (fruid->chassis.flag) { + free(fruid->chassis.type_str); + free(fruid->chassis.part); + free(fruid->chassis.serial); + free(fruid->chassis.custom); + } + + if (fruid->board.flag) { + free(fruid->board.mfg_time_str); + free(fruid->board.mfg); + free(fruid->board.name); + free(fruid->board.serial); + free(fruid->board.part); + free(fruid->board.fruid); + } + + if (fruid->product.flag) { + free(fruid->board.custom); + free(fruid->product.mfg); + free(fruid->product.name); + free(fruid->product.part); + free(fruid->product.version); + free(fruid->product.serial); + free(fruid->product.asset_tag); + free(fruid->product.fruid); + free(fruid->product.custom); + } +} + +/* Initialize the fruid information struct */ +static void init_fruid_info(fruid_info_t * fruid) +{ + fruid->chassis.flag = 0; + fruid->board.flag = 0; + fruid->product.flag = 0; + fruid->chassis.type_str = NULL; + fruid->chassis.part = NULL; + fruid->chassis.serial = NULL; + fruid->chassis.custom = NULL; + fruid->board.mfg_time_str = NULL; + fruid->board.mfg = NULL; + fruid->board.name = NULL; + fruid->board.serial = NULL; + fruid->board.part = NULL; + fruid->board.fruid = NULL; + fruid->board.custom = NULL; + fruid->product.mfg = NULL; + fruid->product.name = NULL; + fruid->product.part = NULL; + fruid->product.version = NULL; + fruid->product.serial = NULL; + fruid->product.asset_tag = NULL; + fruid->product.fruid = NULL; + fruid->product.custom = NULL; +} + +/* Parse the Product area data */ +int parse_fruid_area_product(uint8_t * product, + fruid_area_product_t * fruid_product) +{ + int ret, index; + + index = 0; + + /* Reset the struct to zero */ + memset(fruid_product, 0, sizeof(fruid_area_product_t)); + + /* Check if the format version is as per IPMI FRUID v1.0 format spec */ + fruid_product->format_ver = product[index++]; + if (fruid_product->format_ver != FRUID_FORMAT_VER) { + syslog(LOG_ERR, "fruid: product_area: format version not supported"); + return EPROTONOSUPPORT; + } + + fruid_product->area_len = product[index++] * FRUID_AREA_LEN_MULTIPLIER; + fruid_product->lang_code = product[index++]; + + fruid_product->chksum = product[fruid_product->area_len - 1]; + ret = verify_chksum((uint8_t *) product, + fruid_product->area_len, fruid_product->chksum); + + if (ret) { + syslog(LOG_ERR, "fruid: product_area: chksum not verified."); + return EBADF; + } + + fruid_product->mfg = _fruid_area_field_read(&product[index]); + if (fruid_product->mfg == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->name = _fruid_area_field_read(&product[index]); + if (fruid_product->name == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->part = _fruid_area_field_read(&product[index]); + if (fruid_product->part == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->version = _fruid_area_field_read(&product[index]); + if (fruid_product->version == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->serial = _fruid_area_field_read(&product[index]); + if (fruid_product->serial == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->asset_tag = _fruid_area_field_read(&product[index]); + if (fruid_product->asset_tag == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->fruid = _fruid_area_field_read(&product[index]); + if (fruid_product->fruid == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + fruid_product->custom = _fruid_area_field_read(&product[index]); + if (fruid_product->custom == NULL) + return ENOMEM; + index += FIELD_LEN(product[index]) + 1; + + return 0; +} + +/* Parse the Board area data */ +int parse_fruid_area_board(uint8_t * board, + fruid_area_board_t * fruid_board) +{ + int ret, index, i; + time_t unix_time; + + index = 0; + + /* Reset the struct to zero */ + memset(fruid_board, 0, sizeof(fruid_area_board_t)); + + /* Check if the format version is as per IPMI FRUID v1.0 format spec */ + fruid_board->format_ver = board[index++]; + if (fruid_board->format_ver != FRUID_FORMAT_VER) { + syslog(LOG_ERR, "fruid: board_area: format version not supported"); + return EPROTONOSUPPORT; + } + fruid_board->area_len = board[index++] * FRUID_AREA_LEN_MULTIPLIER; + fruid_board->lang_code = board[index++]; + + fruid_board->chksum = board[fruid_board->area_len - 1]; + ret = verify_chksum((uint8_t *) board, + fruid_board->area_len, fruid_board->chksum); + + if (ret) { + syslog(LOG_ERR, "fruid: board_area: chksum not verified."); + return EBADF; + } + + for (i = 0; i < 3; i++) { + fruid_board->mfg_time[i] = board[index++]; + } + + fruid_board->mfg_time_str = calculate_time(fruid_board->mfg_time); + if (fruid_board->mfg_time_str == NULL) + return ENOMEM; + + fruid_board->mfg = _fruid_area_field_read(&board[index]); + if (fruid_board->mfg == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->name = _fruid_area_field_read(&board[index]); + if (fruid_board->name == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->serial = _fruid_area_field_read(&board[index]); + if (fruid_board->serial == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->part = _fruid_area_field_read(&board[index]); + if (fruid_board->part == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->fruid = _fruid_area_field_read(&board[index]); + if (fruid_board->fruid == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + fruid_board->custom = _fruid_area_field_read(&board[index]); + if (fruid_board->custom == NULL) + return ENOMEM; + index += FIELD_LEN(board[index]) + 1; + + return 0; +} + +/* Parse the Chassis area data */ +int parse_fruid_area_chassis(uint8_t * chassis, + fruid_area_chassis_t * fruid_chassis) +{ + int ret, index; + + index = 0; + + /* Reset the struct to zero */ + memset(fruid_chassis, 0, sizeof(fruid_area_chassis_t)); + + /* Check if the format version is as per IPMI FRUID v1.0 format spec */ + fruid_chassis->format_ver = chassis[index++]; + if (fruid_chassis->format_ver != FRUID_FORMAT_VER) { + syslog(LOG_ERR, "fruid: chassis_area: format version not supported"); + return EPROTONOSUPPORT; + } + + fruid_chassis->area_len = chassis[index++] * FRUID_AREA_LEN_MULTIPLIER; + fruid_chassis->type = chassis[index++]; + + fruid_chassis->chksum = chassis[fruid_chassis->area_len - 1]; + ret = verify_chksum((uint8_t *) chassis, + fruid_chassis->area_len, fruid_chassis->chksum); + if (ret) { + syslog(LOG_ERR, "fruid: chassis_area: chksum not verified."); + return EBADF; + } + + fruid_chassis->type_str = get_chassis_type(fruid_chassis->type); + if (fruid_chassis->type_str == NULL) + return ENOMSG; + + fruid_chassis->part = _fruid_area_field_read(&chassis[index]); + if (fruid_chassis->part == NULL) + return ENOMEM; + index += FIELD_LEN(chassis[index]) + 1; + + fruid_chassis->serial = _fruid_area_field_read(&chassis[index]); + if (fruid_chassis->serial == NULL) + return ENOMEM; + index += FIELD_LEN(chassis[index]) + 1; + + fruid_chassis->custom = _fruid_area_field_read(&chassis[index]); + if (fruid_chassis->custom == NULL) + return ENOMEM; + index += FIELD_LEN(chassis[index]) + 1; + + return 0; +} + +/* Calculate the area offsets and populate the fruid_eeprom_t struct */ +void set_fruid_eeprom_offsets(uint8_t * eeprom, fruid_header_t * header, + fruid_eeprom_t * fruid_eeprom) +{ + fruid_eeprom->header = eeprom + 0x00; + + header->offset_area.chassis ? (fruid_eeprom->chassis = eeprom + \ + (header->offset_area.chassis * FRUID_OFFSET_MULTIPLIER)) : \ + (fruid_eeprom->chassis = NULL); + + header->offset_area.board ? (fruid_eeprom->board = eeprom + \ + (header->offset_area.board * FRUID_OFFSET_MULTIPLIER)) : \ + (fruid_eeprom->board = NULL); + + header->offset_area.product ? (fruid_eeprom->product = eeprom + \ + (header->offset_area.product * FRUID_OFFSET_MULTIPLIER)) : \ + (fruid_eeprom->product = NULL); + + header->offset_area.multirecord ? (fruid_eeprom->multirecord = eeprom + \ + (header->offset_area.multirecord * FRUID_OFFSET_MULTIPLIER)) : \ + (fruid_eeprom->multirecord = NULL); +} + +/* Populate the common header struct */ +int parse_fruid_header(uint8_t * eeprom, fruid_header_t * header) +{ + int ret; + + memcpy((uint8_t *)header, (uint8_t *)eeprom, sizeof(fruid_header_t)); + ret = verify_chksum((uint8_t *) header, + sizeof(fruid_header_t), header->chksum); + if (ret) { + syslog(LOG_ERR, "fruid: common_header: chksum not verified."); + return EBADF; + } + + return ret; +} + +/* Parse the eeprom dump and populate the fruid info in struct */ +int populate_fruid_info(fruid_eeprom_t * fruid_eeprom, fruid_info_t * fruid) +{ + int ret; + + /* Initial all the required fruid structures */ + fruid_area_chassis_t fruid_chassis; + fruid_area_board_t fruid_board; + fruid_area_product_t fruid_product; + + /* If Chassis area is present, parse and print it */ + if (fruid_eeprom->chassis) { + ret = parse_fruid_area_chassis(fruid_eeprom->chassis, &fruid_chassis); + if (!ret) { + fruid->chassis.flag = 1; + fruid->chassis.type_str = fruid_chassis.type_str; + fruid->chassis.part = fruid_chassis.part; + fruid->chassis.serial = fruid_chassis.serial; + fruid->chassis.custom = fruid_chassis.custom; + } else + return ret; + } + + /* If Board area is present, parse and print it */ + if (fruid_eeprom->board) { + ret = parse_fruid_area_board(fruid_eeprom->board, &fruid_board); + if (!ret) { + fruid->board.flag = 1; + fruid->board.mfg_time_str = fruid_board.mfg_time_str; + fruid->board.mfg = fruid_board.mfg; + fruid->board.name = fruid_board.name; + fruid->board.serial = fruid_board.serial; + fruid->board.part = fruid_board.part; + fruid->board.fruid = fruid_board.fruid; + fruid->board.custom = fruid_board.custom; + } else + return ret; + } + + /* If Product area is present, parse and print it */ + if (fruid_eeprom->product) { + ret = parse_fruid_area_product(fruid_eeprom->product, &fruid_product); + if (!ret) { + fruid->product.flag = 1; + fruid->product.mfg = fruid_product.mfg; + fruid->product.name = fruid_product.name; + fruid->product.part = fruid_product.part; + fruid->product.version = fruid_product.version; + fruid->product.serial = fruid_product.serial; + fruid->product.asset_tag = fruid_product.asset_tag; + fruid->product.fruid = fruid_product.fruid; + fruid->product.custom = fruid_product.custom; + } else + return ret; + } + + return 0; +} + +/* + * fruid_parse - To parse the bin file (eeprom) and populate + * the fruid information in the struct + * @bin : Eeprom binary file + * @fruid : ptr to the struct that holds the fruid information + * + * returns 0 on success + * returns non-zero errno value on error + */ +int fruid_parse(const char * bin, fruid_info_t * fruid) +{ + int fruid_len, ret; + FILE *fruid_fd; + uint8_t * eeprom; + + /* Initial all the required fruid structures */ + fruid_header_t fruid_header; + fruid_eeprom_t fruid_eeprom; + + memset(&fruid_header, 0, sizeof(fruid_header_t)); + memset(&fruid_eeprom, 0, sizeof(fruid_eeprom_t)); + + /* Reset parser return value */ + ret = 0; + + /* Open the FRUID binary file */ + fruid_fd = fopen(bin, "rb"); + if (!fruid_fd) { + syslog(LOG_ERR, "fruid: unable to open the file"); + return ENOENT; + } + + /* Get the size of the binary file */ + fseek(fruid_fd, 0, SEEK_END); + fruid_len = (uint32_t) ftell(fruid_fd); + + fseek(fruid_fd, 0, SEEK_SET); + + eeprom = (uint8_t *) malloc(fruid_len); + if (!eeprom) { + syslog(LOG_ALERT, "fruid: malloc: memory allocation failed\n"); + return ENOMEM; + } + + /* Read the binary file */ + fread(eeprom, sizeof(uint8_t), fruid_len, fruid_fd); + + /* Close the FRUID binary file */ + fclose(fruid_fd); + + /* Parse the common header data */ + ret = parse_fruid_header(eeprom, &fruid_header); + if (ret) { + /* Free the eeprom malloc'ed memory */ + free(eeprom); + return ret; + } + + /* Calculate all the area offsets */ + set_fruid_eeprom_offsets(eeprom, &fruid_header, &fruid_eeprom); + + init_fruid_info(fruid); + /* Parse the eeprom and populate the fruid information */ + ret = populate_fruid_info(&fruid_eeprom, fruid); + if (ret) { + /* Free the malloced memory for the fruid information */ + free_fruid_info(fruid); + } + + /* Free the eeprom malloced memory */ + free(eeprom); + + return ret; +} diff --git a/common/recipes-lib/fruid/files/fruid.h b/common/recipes-lib/fruid/files/fruid.h new file mode 100644 index 0000000..713658d --- /dev/null +++ b/common/recipes-lib/fruid/files/fruid.h @@ -0,0 +1,192 @@ +/* + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __FRUID_H__ +#define __FRUID_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> +#include <stdint.h> +#include <openbmc/ipmi.h> + +#define FRUID_FORMAT_VER 0x01 +#define FRUID_OFFSET_MULTIPLIER 8 +#define FRUID_AREA_LEN_MULTIPLIER 8 + +#define FRUID_OFFSET_AREA_INTERNAL 0 +#define FRUID_OFFSET_AREA_CHASSIS 1 +#define FRUID_OFFSET_AREA_BOARD 2 +#define FRUID_OFFSET_AREA_PRODUCT 3 +#define FRUID_OFFSET_AREA_MULTIRECORD 4 + +#define FRUID_CHASSIS_TYPECODE_MIN 1 +#define FRUID_CHASSIS_TYPECODE_MAX 32 + +/* To hold the common header information. */ +typedef struct fruid_header_t { + uint8_t format_ver : 4; + struct { + uint8_t internal; + uint8_t chassis; + uint8_t board; + uint8_t product; + uint8_t multirecord; + } offset_area; + uint8_t pad; + uint8_t chksum; +} fruid_header_t; + +/* To hold the Chassis area information. */ +typedef struct fruid_area_chassis_t { + uint8_t format_ver : 4; + uint8_t area_len; + uint8_t type; + char * type_str; + char * part; + char * serial; + char * custom; + uint8_t chksum; +} fruid_area_chassis_t; + +/* To hold the Board area information. */ +typedef struct fruid_area_board_t { + uint8_t format_ver : 4; + uint8_t area_len; + uint8_t lang_code; + uint8_t mfg_time[3]; + char * mfg_time_str; + char * mfg; + char * name; + char * serial; + char * part; + char * fruid; + char * custom; + uint8_t chksum; +} fruid_area_board_t; + +/* To hold the Product area information. */ +typedef struct fruid_area_product_t { + uint8_t format_ver : 4; + uint8_t area_len; + uint8_t lang_code; + char * mfg; + char * name; + char * part; + char * version; + char * serial; + char * asset_tag; + char * fruid; + char * custom; + uint8_t chksum; +} fruid_area_product_t; + +/* To hold the Multirecord area information. */ +typedef struct fruid_area_multirecord_t { + uint8_t format_ver : 4; + uint8_t area_len; + /* TODO: Add more fields to support Multirecord area. */ +} fruid_area_multirecord_t; + +/* To hold all the fruid information */ +typedef struct fruid_info_t { + struct { + uint8_t flag; + char * type_str; + char * part; + char * serial; + char * custom; + } chassis; + struct { + uint8_t flag; + char * mfg_time_str; + char * mfg; + char * name; + char * serial; + char * part; + char * fruid; + char * custom; + } board; + struct { + uint8_t flag; + char * mfg; + char * name; + char * part; + char * version; + char * serial; + char * asset_tag; + char * fruid; + char * custom; + } product; +} fruid_info_t; + +/* To hold the different area offsets. */ +typedef struct fruid_eeprom_t { + uint8_t * header; + uint8_t * chassis; + uint8_t * board; + uint8_t * product; + uint8_t * multirecord; +} fruid_eeprom_t; + +/* List of all the Chassis types. */ +const char * fruid_chassis_type [] = { + "Other", /* 0x01 */ + "Unknown", /* 0x02 */ + "Desktop", /* 0x03 */ + "Low Profile Desktop", /* 0x04 */ + "Pizza Box", /* 0x05 */ + "Mini Tower", /* 0x06 */ + "Tower", /* 0x07 */ + "Portable", /* 0x08 */ + "Laptop", /* 0x09 */ + "Notebook", /* 0x0A */ + "Hand Held", /* 0x0B */ + "Docking Station", /* 0x0C */ + "All in One", /* 0x0D */ + "Sub Notebook", /* 0x0E */ + "Space-saving", /* 0x0F */ + "Lunch Box", /* 0x10 */ + "Main Server Chassis", /* 0x11 */ + "Expansion Chassis", /* 0x12 */ + "SubChassis", /* 0x13 */ + "Bus Expansion Chassis", /* 0x14 */ + "Peripheral Chassis", /* 0x15 */ + "RAID Chassis", /* 0x16 */ + "Rack Mount Chassis", /* 0x17 */ + "Sealed-case PC", /* 0x18 */ + "Multi-system Chassis", /* 0x19 */ + "Compact PCI", /* 0x1A */ + "Advanced TCA", /* 0x1B */ + "Blade", /* 0x1C */ + "Blade Enclosure", /* 0x1D */ + "Tablet", /* 0x1E */ + "Convertible", /* 0x1F */ + "Detachable" /* 0x20 */ +}; + +int fruid_parse(const char * bin, fruid_info_t * fruid); +void free_fruid_info(fruid_info_t * fruid); + +#ifdef __cplusplus +} +#endif + +#endif /* __FRUID_H__ */ diff --git a/common/recipes-lib/fruid/libfruid_0.1.bb b/common/recipes-lib/fruid/libfruid_0.1.bb new file mode 100644 index 0000000..7984d3b --- /dev/null +++ b/common/recipes-lib/fruid/libfruid_0.1.bb @@ -0,0 +1,43 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "IPMI FRUID Library" +DESCRIPTION = "library for ipmi fruid" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://fruid.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI = "file://Makefile \ + file://fruid.c \ + file://fruid.h \ + " + +S = "${WORKDIR}" + +DEPENDS += " libipmi " + +do_install() { + install -d ${D}${libdir} + install -m 0644 libfruid.so ${D}${libdir}/libfruid.so + + install -d ${D}${includedir}/openbmc + install -m 0644 fruid.h ${D}${includedir}/openbmc/fruid.h +} + +FILES_${PN} = "${libdir}/libfruid.so" +FILES_${PN}-dev = "${includedir}/openbmc/fruid.h" diff --git a/common/recipes-lib/gpio/files/src/Makefile b/common/recipes-lib/gpio/files/src/Makefile new file mode 100644 index 0000000..0b605fc --- /dev/null +++ b/common/recipes-lib/gpio/files/src/Makefile @@ -0,0 +1,27 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +lib: libgpio.so + +libgpio.so: gpio.c + $(CC) $(CFLAGS) -fPIC -c -o gpio.o gpio.c + $(CC) -shared -o libgpio.so gpio.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libgpio.so diff --git a/common/recipes-lib/gpio/files/src/gpio.c b/common/recipes-lib/gpio/files/src/gpio.c new file mode 100644 index 0000000..9c1f7a2 --- /dev/null +++ b/common/recipes-lib/gpio/files/src/gpio.c @@ -0,0 +1,107 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +//#define DEBUG +//#define VERBOSE + +#include "gpio.h" + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/errno.h> + +#include <openbmc/log.h> + +void gpio_init_default(gpio_st *g) { + g->gs_gpio = -1; + g->gs_fd = -1; +} + +int gpio_open(gpio_st *g, int gpio) +{ + char buf[128]; + int rc; + + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/value", gpio); + rc = open(buf, O_RDWR); + if (rc == -1) { + rc = errno; + LOG_ERR(rc, "Failed to open %s", buf); + return -rc; + } + g->gs_fd = rc; + g->gs_gpio = gpio; + return 0; +} + +void gpio_close(gpio_st *g) +{ + if (g && g->gs_fd != -1) { + close(g->gs_fd); + } + gpio_init_default(g); +} + +gpio_value_en gpio_read(gpio_st *g) +{ + char buf[32] = {0}; + gpio_value_en v; + lseek(g->gs_fd, 0, SEEK_SET); + read(g->gs_fd, buf, sizeof(buf)); + v = atoi(buf) ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW; + LOG_VER("read gpio=%d value=%d %d", g->gs_gpio, atoi(buf), v); + return v; +} + +void gpio_write(gpio_st *g, gpio_value_en v) +{ + lseek(g->gs_fd, 0, SEEK_SET); + write(g->gs_fd, (v == GPIO_VALUE_HIGH) ? "1" : "0", 1); + LOG_VER("write gpio=%d value=%d", g->gs_gpio, v); +} + +int gpio_change_direction(gpio_st *g, gpio_direction_en dir) +{ + char buf[128]; + char *val; + int fd = -1; + int rc = 0; + + snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/direction", g->gs_gpio); + fd = open(buf, O_WRONLY); + if (fd == -1) { + rc = errno; + LOG_ERR(rc, "Failed to open %s", buf); + return -rc; + } + + val = (dir == GPIO_DIRECTION_IN) ? "in" : "out"; + write(fd, val, strlen(val)); + + LOG_VER("change gpio=%d direction=%s", g->gs_gpio, val); + + out: + if (fd != -1) { + close(fd); + } + return -rc; +} diff --git a/common/recipes-lib/gpio/files/src/gpio.h b/common/recipes-lib/gpio/files/src/gpio.h new file mode 100644 index 0000000..3303986 --- /dev/null +++ b/common/recipes-lib/gpio/files/src/gpio.h @@ -0,0 +1,42 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef GPIO_H +#define GPIO_H + +typedef struct { + int gs_gpio; + int gs_fd; +} gpio_st; + +typedef enum { + GPIO_DIRECTION_IN, + GPIO_DIRECTION_OUT, +} gpio_direction_en; + +typedef enum { + GPIO_VALUE_LOW = 0, + GPIO_VALUE_HIGH = 1, +} gpio_value_en; + +int gpio_open(gpio_st* g, int gpio); +void gpio_close(gpio_st *g); +gpio_value_en gpio_read(gpio_st *g); +void gpio_write(gpio_st *g, gpio_value_en v); +int gpio_change_direction(gpio_st *g, gpio_direction_en dir); + +#endif diff --git a/common/recipes-lib/gpio/libgpio_0.1.bb b/common/recipes-lib/gpio/libgpio_0.1.bb new file mode 100644 index 0000000..cd32ac0 --- /dev/null +++ b/common/recipes-lib/gpio/libgpio_0.1.bb @@ -0,0 +1,40 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "GPIO access library" +DESCRIPTION = "library to access GPIO" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://gpio.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI = "file://src \ + " + +DEPENDS += "liblog" + +S = "${WORKDIR}/src" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libgpio.so ${D}${libdir}/libgpio.so + + install -d ${D}${includedir}/openbmc + install -m 0644 gpio.h ${D}${includedir}/openbmc/gpio.h +} + +FILES_${PN} = "${libdir}/libgpio.so" +FILES_${PN}-dev = "${includedir}/openbmc/gpio.h" diff --git a/common/recipes-lib/ipmb/files/Makefile b/common/recipes-lib/ipmb/files/Makefile new file mode 100644 index 0000000..c09b325 --- /dev/null +++ b/common/recipes-lib/ipmb/files/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libipmb.so + +libipmb.so: ipmb.c + $(CC) $(CFLAGS) -fPIC -c -o ipmb.o ipmb.c + $(CC) -shared -o libipmb.so ipmb.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libipmb.so diff --git a/common/recipes-lib/ipmb/files/ipmb.c b/common/recipes-lib/ipmb/files/ipmb.c new file mode 100644 index 0000000..731eeba --- /dev/null +++ b/common/recipes-lib/ipmb/files/ipmb.c @@ -0,0 +1,82 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <errno.h> +#include <string.h> +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include "ipmb.h" + +/* + * Function to handle IPMB messages + */ +void +lib_ipmb_handle(unsigned char bus_id, + unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) { + + int s, t, len; + struct sockaddr_un remote; + char sock_path[64] = {0}; + + sprintf(sock_path, "%s_%d", SOCK_PATH_IPMB, bus_id); + + // TODO: Need to update to reuse the socket instead of creating new + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + syslog(LOG_ALERT, "lib_ipmb_handle: socket() failed\n"); + return; + } + + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, sock_path); + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + + if (connect(s, (struct sockaddr *)&remote, len) == -1) { + syslog(LOG_ALERT, "ipmb_handle: connect() failed\n"); + goto clean_exit; + } + + if (send(s, request, req_len, 0) == -1) { + syslog(LOG_ALERT, "ipmb_handle: send() failed\n"); + goto clean_exit; + } + + if ((t=recv(s, response, MAX_IPMB_RES_LEN, 0)) > 0) { + *res_len = t; + } else { + if (t < 0) { + syslog(LOG_ALERT, "lib_ipmb_handle: recv() failed\n"); + } else { + printf("Server closed connection\n"); + } + } + +clean_exit: + close(s); + + return; +} diff --git a/common/recipes-lib/ipmb/files/ipmb.h b/common/recipes-lib/ipmb/files/ipmb.h new file mode 100644 index 0000000..d9bc16b --- /dev/null +++ b/common/recipes-lib/ipmb/files/ipmb.h @@ -0,0 +1,75 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __IPMB_H__ +#define __IPMB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SOCK_PATH_IPMB "/tmp/ipmb_socket" + +#define BMC_SLAVE_ADDR 0x10 +#define BRIDGE_SLAVE_ADDR 0x20 +#define ZERO_CKSUM_CONST 0x100 + +// rqSA, rsSA, rqSeq, hdrCksum, dataCksum +#define IPMB_HDR_SIZE 5 + +// rqSA, NetFn, hdrCksum +#define IPMB_DATA_OFFSET 3 + +// Slot#0 is on I2C Bus1 +#define IPMB_BUS_SLOT0 1 + +#define TIMEOUT_IPMI 4 +#define MAX_IPMB_RES_LEN 255 + +typedef struct _ipmb_req_t { + uint8_t res_slave_addr; + uint8_t netfn_lun; + uint8_t hdr_cksum; + uint8_t req_slave_addr; + uint8_t seq_lun; + uint8_t cmd; + uint8_t data[]; +} ipmb_req_t; + +typedef struct _ipmb_res_t { + uint8_t req_slave_addr; + uint8_t netfn_lun; + uint8_t hdr_cksum; + uint8_t res_slave_addr; + uint8_t seq_lun; + uint8_t cmd; + uint8_t cc; + uint8_t data[]; +} ipmb_res_t; + +void lib_ipmb_handle(unsigned char bus_id, + unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __IPMB_H__ */ diff --git a/common/recipes-lib/ipmb/libipmb_0.1.bb b/common/recipes-lib/ipmb/libipmb_0.1.bb new file mode 100644 index 0000000..81eed9c --- /dev/null +++ b/common/recipes-lib/ipmb/libipmb_0.1.bb @@ -0,0 +1,26 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "IPMB Client Library" +DESCRIPTION = "library for IPMB Client" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://ipmb.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://Makefile \ + file://ipmb.c \ + file://ipmb.h \ + " + +S = "${WORKDIR}" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libipmb.so ${D}${libdir}/libipmb.so + + install -d ${D}${includedir}/openbmc + install -m 0644 ipmb.h ${D}${includedir}/openbmc/ipmb.h +} + +FILES_${PN} = "${libdir}/libipmb.so" +FILES_${PN}-dev = "${includedir}/openbmc/ipmb.h" diff --git a/common/recipes-lib/ipmi/files/Makefile b/common/recipes-lib/ipmi/files/Makefile new file mode 100644 index 0000000..369819c --- /dev/null +++ b/common/recipes-lib/ipmi/files/Makefile @@ -0,0 +1,27 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +lib: libipmi.so + +libipmi.so: ipmi.c + $(CC) $(CFLAGS) -fPIC -c -o ipmi.o ipmi.c + $(CC) -shared -o libipmi.so ipmi.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libipmi.so diff --git a/common/recipes-lib/ipmi/files/ipmi.c b/common/recipes-lib/ipmi/files/ipmi.c new file mode 100644 index 0000000..3579eca --- /dev/null +++ b/common/recipes-lib/ipmi/files/ipmi.c @@ -0,0 +1,80 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "ipmi.h" +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> + +#define MAX_IPMI_RES_LEN 100 + +/* + * Function to handle IPMI messages + */ +void +lib_ipmi_handle(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) { + + int s, t, len; + struct sockaddr_un remote; + + // TODO: Need to update to reuse the socket instead of creating new + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + syslog(LOG_ALERT, "lib_ipmi_handle: socket() failed\n"); + return; + } + + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, SOCK_PATH_IPMI); + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + + if (connect(s, (struct sockaddr *)&remote, len) == -1) { + syslog(LOG_ALERT, "lib_ipmi_handle: connect() failed\n"); + return; + } + + if (send(s, request, req_len, 0) == -1) { + syslog(LOG_ALERT, "lib_ipmi_handle: send() failed\n"); + return; + } + + if ((t=recv(s, response, MAX_IPMI_RES_LEN, 0)) > 0) { + *res_len = t; + } else { + if (t < 0) { + syslog(LOG_ALERT, "lib_ipmi_handle: recv() failed\n"); + } else { + printf("Server closed connection"); + } + + return; + } + + close(s); + + return; +} diff --git a/common/recipes-lib/ipmi/files/ipmi.h b/common/recipes-lib/ipmi/files/ipmi.h new file mode 100644 index 0000000..2ae7f1c --- /dev/null +++ b/common/recipes-lib/ipmi/files/ipmi.h @@ -0,0 +1,453 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __IPMI_H__ +#define __IPMI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#define SOCK_PATH_IPMI "/tmp/ipmi_socket" + +#define IPMI_SEL_VERSION 0x51 +#define IPMI_SDR_VERSION 0x51 + +#define MAX_NUM_DIMMS 4 + +#define SIZE_AUTH_ENABLES 5 +#define SIZE_IP_ADDR 4 +#define SIZE_MAC_ADDR 6 +#define SIZE_NET_MASK 4 +#define SIZE_IP_HDR 3 +#define SIZE_RMCP_PORT 2 +#define SIZE_COMMUNITY_STR 18 +#define SIZE_DEST_TYPE 4 +#define SIZE_DEST_ADDR 18 +#define SIZE_TIME_STAMP 4 + +#define SIZE_PROC_FREQ 2 +#define SIZE_DIMM_SPEED 2 +#define SIZE_DIMM_SIZE 2 + +#define SIZE_SYSFW_VER 17 +#define SIZE_SYS_NAME 17 +#define SIZE_OS_NAME 17 +#define SIZE_OS_VER 17 +#define SIZE_BMC_URL 17 +#define SIZE_OS_HV_URL 17 + +#define SIZE_SEL_REC 16 + +#define BIC_INTF_HDR_SIZE 3 + +#define LUN_OFFSET 2 + +//NetFn, Cmd +#define IPMI_REQ_HDR_SIZE 2 + +// NetFn, Cmd, CC +#define IPMI_RESP_HDR_SIZE 3 + +#define MAX_IPMI_MSG_SIZE 100 + +// Type Definition +#define TYPE_BINARY 0 +#define TYPE_BCD_PLUS 1 +#define TYPE_ASCII_6BIT 2 +#define TYPE_ASCII_8BIT 3 + +// IPMI request Structure (IPMI/Section 9.2) +typedef struct +{ + unsigned char netfn_lun; + unsigned char cmd; + unsigned char data[]; +} ipmi_req_t; + +// IPMI Multi Node request Structure +// Supports additional member to identify the node# +typedef struct +{ + unsigned char payload_id; + unsigned char netfn_lun; + unsigned char cmd; + unsigned char data[]; +} ipmi_mn_req_t; + +// IPMI response Structure (IPMI/Section 9.3) +typedef struct +{ + unsigned char netfn_lun; + unsigned char cmd; + unsigned char cc; + unsigned char data[]; +} ipmi_res_t; + +// IPMI/Spec Table 20-2 +typedef struct _ipmi_dev_id_t { + uint8_t dev_id; + uint8_t dev_rev; + uint8_t fw_rev1; + uint8_t fw_rev2; + uint8_t ipmi_ver; + uint8_t dev_support; + uint8_t mfg_id[3]; + uint8_t prod_id[2]; + uint8_t aux_fw_rev[4]; +} ipmi_dev_id_t; + + +typedef struct _ipmi_fruid_info_t { + uint8_t size_lsb; + uint8_t size_msb; + uint8_t bytes_words; +} ipmi_fruid_info_t; + +#pragma pack(push, 1) + +// Full Sensor SDR record; IPMI/Section 43.1 +typedef struct { + // Sensor Record Header + unsigned char rec_id[2]; + unsigned char ver; + unsigned char type; + unsigned char len; + // Record Key Bytes + unsigned char owner; + unsigned char lun; + unsigned char sensor_num; + // Record Body Bytes + unsigned char ent_id; + unsigned char ent_inst; + unsigned char sensor_init; + unsigned char sensor_caps; + unsigned char sensor_type; + unsigned char evt_read_type; + union { + unsigned char assert_evt_mask[2]; + unsigned char lt_read_mask[2]; + }; + union { + unsigned char deassert_evt_mask[2]; + unsigned char ut_read_mask[2]; + }; + union { + unsigned char read_evt_mask[2]; + unsigned char set_thresh_mask[2]; + }; + unsigned char sensor_units1; + unsigned char sensor_units2; + unsigned char sensor_units3; + unsigned char linear; + unsigned char m_val; + unsigned char m_tolerance; + unsigned char b_val; + unsigned char b_accuracy; + unsigned char accuracy_dir; + unsigned char rb_exp; + unsigned char analog_flags; + unsigned char nominal; + unsigned char normal_max; + unsigned char normal_min; + unsigned char max_reading; + unsigned char min_reading; + unsigned char unr_thresh; + unsigned char uc_thresh; + unsigned char unc_thresh; + unsigned char lnr_thresh; + unsigned char lc_thresh; + unsigned char lnc_thresh; + unsigned char pos_hyst; + unsigned char neg_hyst; + unsigned char rsvd[2]; + unsigned char oem; + unsigned char str_type_len; + char str[16]; +} sdr_full_t; + +typedef struct _ipmi_sel_sdr_info_t { + uint8_t ver; + uint16_t rec_count; + uint16_t free_space; + uint8_t add_ts[4]; + uint8_t erase_ts[4]; + uint8_t oper; +} ipmi_sel_sdr_info_t; + +typedef struct _ipmi_sel_sdr_req_t { + uint16_t rsv_id; + uint16_t rec_id; + uint8_t offset; + uint8_t nbytes; +} ipmi_sel_sdr_req_t; + +typedef struct _ipmi_sel_sdr_res_t { + uint16_t next_rec_id; + uint8_t data[]; +} ipmi_sel_sdr_res_t; + +#pragma pack(pop) + +// LAN Configuration Structure (IPMI/Table 23.4) +typedef struct +{ + unsigned char set_in_prog; + unsigned char auth_support; + unsigned char auth_enables[SIZE_AUTH_ENABLES]; + unsigned char ip_addr[SIZE_IP_ADDR]; + unsigned char ip_src; + unsigned char mac_addr[SIZE_MAC_ADDR]; + unsigned char net_mask[SIZE_NET_MASK]; + unsigned char ip_hdr[SIZE_IP_HDR]; + unsigned char pri_rmcp_port[SIZE_RMCP_PORT]; + unsigned char sec_rmcp_port[SIZE_RMCP_PORT]; + unsigned char arp_ctrl; + unsigned char garp_interval; + unsigned char df_gw_ip_addr[SIZE_IP_ADDR]; + unsigned char df_gw_mac_addr[SIZE_MAC_ADDR]; + unsigned char back_gw_ip_addr[SIZE_IP_ADDR]; + unsigned char back_gw_mac_addr[SIZE_MAC_ADDR]; + unsigned char community_str[SIZE_COMMUNITY_STR]; + unsigned char no_of_dest; + unsigned char dest_type[SIZE_DEST_TYPE]; + unsigned char dest_addr[SIZE_DEST_ADDR]; +} lan_config_t; + +// Structure to store Processor Information +typedef struct +{ + unsigned char type; + unsigned char freq[SIZE_PROC_FREQ]; +} proc_info_t; + +// Structure to store DIMM Information +typedef struct +{ + unsigned char type; + unsigned char speed[SIZE_DIMM_SPEED]; + unsigned char size[SIZE_DIMM_SIZE]; +} dimm_info_t; + + +// Structure for System Info Params (IPMI/Section 22.14a) +typedef struct +{ + unsigned char set_in_prog; + unsigned char sysfw_ver[SIZE_SYSFW_VER]; + unsigned char sys_name[SIZE_SYS_NAME]; + unsigned char pri_os_name[SIZE_OS_NAME]; + unsigned char present_os_name[SIZE_OS_NAME]; + unsigned char present_os_ver[SIZE_OS_VER]; + unsigned char bmc_url[SIZE_BMC_URL]; + unsigned char os_hv_url[SIZE_OS_HV_URL]; +} sys_info_param_t; + +// Structure for Sensor Reading (IPMI/Section 35.14) +typedef struct +{ + uint8_t value; + uint8_t flags; + uint8_t status; + uint8_t ext_status; +} ipmi_sensor_reading_t; + +// Network Function Codes (IPMI/Section 5.1) +enum +{ + NETFN_CHASSIS_REQ = 0x00, + NETFN_CHASSIS_RES, + NETFN_BRIDGE_REQ, + NETFN_BRIDGE_RES, + NETFN_SENSOR_REQ, + NETFN_SENSOR_RES, + NETFN_APP_REQ, + NETFN_APP_RES, + NETFN_FIRMWARE_REQ, + NETFN_FIRMWARE_RES, + NETFN_STORAGE_REQ, + NETFN_STORAGE_RES, + NETFN_TRANSPORT_REQ, + NETFN_TRANSPORT_RES, + NETFN_OEM_REQ = 0x30, + NETFN_OEM_RES = 0x31, + NETFN_OEM_1S_REQ = 0x38, + NETFN_OEM_1S_RES = 0x39, +}; + +// Chassis Command Codes (IPMI/Table H-1) +enum +{ + CMD_CHASSIS_GET_STATUS = 0x01, + CMD_CHASSIS_GET_BOOT_OPTIONS = 0x09, +}; + + +// Application Command Codes (IPMI/Table H-1) +enum +{ + CMD_APP_GET_DEVICE_ID = 0x01, + CMD_APP_GET_SELFTEST_RESULTS = 0x04, + CMD_APP_GET_DEVICE_GUID = 0x08, + CMD_APP_RESET_WDT = 0x22, + CMD_APP_SET_WDT = 0x24, + CMD_APP_GET_WDT = 0x25, + CMD_APP_GET_GLOBAL_ENABLES = 0x2F, + CMD_APP_GET_SYSTEM_GUID = 0x37, + CMD_APP_SET_SYS_INFO_PARAMS = 0x58, + CMD_APP_GET_SYS_INFO_PARAMS = 0x59, +}; + +// Storage Command Codes (IPMI/Table H-1) +enum +{ + CMD_STORAGE_GET_FRUID_INFO = 0x10, + CMD_STORAGE_READ_FRUID_DATA = 0x11, + CMD_STORAGE_GET_SDR_INFO = 0x20, + CMD_STORAGE_RSV_SDR = 0x22, + CMD_STORAGE_GET_SDR = 0x23, + CMD_STORAGE_GET_SEL_INFO = 0x40, + CMD_STORAGE_RSV_SEL = 0x42, + CMD_STORAGE_GET_SEL = 0x43, + CMD_STORAGE_ADD_SEL = 0x44, + CMD_STORAGE_CLR_SEL = 0x47, + CMD_STORAGE_GET_SEL_TIME = 0x48, + CMD_STORAGE_GET_SEL_UTC = 0x5C, +}; + +// Sensor Command Codes (IPMI/Table H-1) +enum +{ + CMD_SENSOR_GET_SENSOR_READING = 0x2D, +}; + +// Transport Command Codes (IPMI/Table H-1) +enum +{ + CMD_TRANSPORT_SET_LAN_CONFIG = 0x01, + CMD_TRANSPORT_GET_LAN_CONFIG = 0x02, +}; + +// OEM Command Codes (Quanta/FB defined commands) +enum +{ + CMD_OEM_SET_PROC_INFO = 0x1A, + CMD_OEM_SET_DIMM_INFO = 0x1C, + CMD_OEM_SET_POST_START = 0x73, + CMD_OEM_SET_POST_END = 0x74, +}; + +// OEM 1S Command Codes (Quanta/FB defined commands) +enum +{ + CMD_OEM_1S_MSG_IN = 0x1, + CMD_OEM_1S_GET_GPIO = 0x3, + CMD_OEM_1S_GET_GPIO_CONFIG = 0x5, + CMD_OEM_1S_SET_GPIO_CONFIG = 0x6, + CMD_OEM_1S_INTR = 0x7, + CMD_OEM_1S_POST_BUF = 0x8, + CMD_OEM_1S_GET_CONFIG = 0xE, + CMD_OEM_1S_PLAT_DISC = 0xF, + CMD_OEM_1S_SET_CONFIG = 0x10, + CMD_OEM_1S_BIC_RESET = 0x11, + CMD_OEM_1S_GET_POST_BUF = 0x12, + CMD_OEM_1S_BIC_UPDATE_MODE = 0x13, +}; + + +// IPMI command Completion Codes (IPMI/Section 5.2) +enum +{ + CC_SUCCESS = 0x00, + CC_INVALID_PARAM = 0x80, + CC_SEL_ERASE_PROG = 0x81, + CC_INVALID_CMD = 0xC1, + CC_PARAM_OUT_OF_RANGE = 0xC9, + CC_UNSPECIFIED_ERROR = 0xFF, +}; + +// LAN Configuration parameters (IPMI/Table 23-4) +enum +{ + LAN_PARAM_SET_IN_PROG, + LAN_PARAM_AUTH_SUPPORT, + LAN_PARAM_AUTH_ENABLES, + LAN_PARAM_IP_ADDR, + LAN_PARAM_IP_SRC, + LAN_PARAM_MAC_ADDR, + LAN_PARAM_NET_MASK, + LAN_PARAM_IP_HDR, + LAN_PARAM_PRI_RMCP_PORT, + LAN_PARAM_SEC_RMCP_PORT, + LAN_PARAM_ARP_CTRL, + LAN_PARAM_GARP_INTERVAL, + LAN_PARAM_DF_GW_IP_ADDR, + LAN_PARAM_DF_GW_MAC_ADDR, + LAN_PARAM_BACK_GW_IP_ADDR, + LAN_PARAM_BACK_GW_MAC_ADDR, + LAN_PARAM_COMMUNITY_STR, + LAN_PARAM_NO_OF_DEST, + LAN_PARAM_DEST_TYPE, + LAN_PARAM_DEST_ADDR, +}; + +// Boot Option Parameters (IPMI/Table 28-14) +enum +{ + PARAM_SET_IN_PROG = 0x00, + PARAM_SVC_PART_SELECT, + PARAM_SVC_PART_SCAN, + PARAM_BOOT_FLAG_CLR, + PARAM_BOOT_INFO_ACK, + PARAM_BOOT_FLAGS, + PARAM_BOOT_INIT_INFO, +}; + +//System Info Parameters (IPMI/Table 22-16c) +enum +{ + SYS_INFO_PARAM_SET_IN_PROG, + SYS_INFO_PARAM_SYSFW_VER, + SYS_INFO_PARAM_SYS_NAME, + SYS_INFO_PARAM_PRI_OS_NAME, + SYS_INFO_PARAM_PRESENT_OS_NAME, + SYS_INFO_PARAM_PRESENT_OS_VER, + SYS_INFO_PARAM_BMC_URL, + SYS_INFO_PARAM_OS_HV_URL, +}; + +// Bridge-IC interface on which this command initiated +enum +{ + BIC_INTF_ME = 0x01, + BIC_INTF_SOL = 0x02, + BIC_INTF_KCS = 0x03, +}; + +void lib_ipmi_handle(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __IPMI_H__ */ diff --git a/common/recipes-lib/ipmi/libipmi_0.2.bb b/common/recipes-lib/ipmi/libipmi_0.2.bb new file mode 100644 index 0000000..c5bca76 --- /dev/null +++ b/common/recipes-lib/ipmi/libipmi_0.2.bb @@ -0,0 +1,41 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "IPMI Client Library" +DESCRIPTION = "library for IPMI Client" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://ipmi.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://Makefile \ + file://ipmi.c \ + file://ipmi.h \ + " + +S = "${WORKDIR}" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libipmi.so ${D}${libdir}/libipmi.so + + install -d ${D}${includedir}/openbmc + install -m 0644 ipmi.h ${D}${includedir}/openbmc/ipmi.h +} + +FILES_${PN} = "${libdir}/libipmi.so" +FILES_${PN}-dev = "${includedir}/openbmc/ipmi.h" diff --git a/common/recipes-lib/log/files/src/log.h b/common/recipes-lib/log/files/src/log.h new file mode 100644 index 0000000..a69d69e --- /dev/null +++ b/common/recipes-lib/log/files/src/log.h @@ -0,0 +1,59 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef LOG_H +#define LOG_H + +#include <stdio.h> +#include <string.h> + +//#define DEBUG +//#define VERBOSE + +#define _LOG(dst, fmt, ...) do { \ + fprintf(dst, "%s:%d " fmt "\n", \ + __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + fflush(dst); \ +} while(0) + +#define LOG_ERR(err, fmt, ...) do { \ + char buf[128]; \ + strerror_r(err, buf, sizeof(buf)); \ + _LOG(stderr, "ERROR " fmt ": %s", ##__VA_ARGS__, buf); \ +} while(0) + +#define LOG_INFO(fmt, ...) do { \ + _LOG(stdout, fmt, ##__VA_ARGS__); \ +} while(0) + +#ifdef DEBUG +#define LOG_DBG(fmt, ...) do { \ + _LOG(stdout, fmt, ##__VA_ARGS__); \ +} while(0) +#else +#define LOG_DBG(fmt, ...) +#endif + +#ifdef VERBOSE +#define LOG_VER(fmt, ...) do { \ + _LOG(stdout, fmt, ##__VA_ARGS__); \ +} while(0) +#else +#define LOG_VER(fmt, ...) +#endif + +#endif diff --git a/common/recipes-lib/log/liblog_0.1.bb b/common/recipes-lib/log/liblog_0.1.bb new file mode 100644 index 0000000..8034c0d --- /dev/null +++ b/common/recipes-lib/log/liblog_0.1.bb @@ -0,0 +1,36 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "Log util functions" +DESCRIPTION = "some macros to log" +SECTION = "dev" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://log.h;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI += "file://src \ + " + +S = "${WORKDIR}/src" + +do_install() { + # common lib and include files + install -d ${D}${includedir}/openbmc + install -m 0644 log.h ${D}${includedir}/openbmc/log.h +} + +FILES_${PN}-dev = "${includedir}/openbmc/log.h" diff --git a/common/recipes-lib/sdr/files/Makefile b/common/recipes-lib/sdr/files/Makefile new file mode 100644 index 0000000..11fe3ee --- /dev/null +++ b/common/recipes-lib/sdr/files/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libsdr.so + +libsdr.so: sdr.c + $(CC) $(CFLAGS) -fPIC -c -o sdr.o sdr.c + $(CC) -lm -shared -o libsdr.so sdr.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libsdr.so diff --git a/common/recipes-lib/sdr/files/sdr.c b/common/recipes-lib/sdr/files/sdr.c new file mode 100644 index 0000000..208b10f --- /dev/null +++ b/common/recipes-lib/sdr/files/sdr.c @@ -0,0 +1,210 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <math.h> +#include <fcntl.h> +#include <errno.h> +#include <syslog.h> +#include "sdr.h" + +#define FIELD_RATE_UNIT(x) ((x & (0x07 << 3)) >> 3) +#define FIELD_OP(x) ((x & (0x03 << 1)) >> 1) +#define FIELD_PERCENTAGE(x) (x & 0x01) + +#define FIELD_TYPE(x) ((x & (0x03 << 6)) >> 6) +#define FIELD_LEN(x) (x & 0xF) + +/* Array for BCD Plus definition. */ +const char bcd_plus_array[] = "0123456789 -.XXX"; + +/* Array for 6-Bit ASCII definition. */ +const char * ascii_6bit[4] = { + " !\"#$%&'()*+,-./", + "0123456789:;<=>?", + "@ABCDEFGHIJKLMNO", + "PQRSTUVWXYZ[\\]^_" +}; + +/* Get the units of the sensor from the SDR */ +int +sdr_get_sensor_units(sdr_full_t *sdr, uint8_t *op, uint8_t *modifier, + char *units) { + + uint8_t percent; + uint8_t rate_idx; + uint8_t base_idx; + + /* Bits 5:3 */ + rate_idx = FIELD_RATE_UNIT(sdr->sensor_units1); + + /* Bits 2:1 */ + *op = FIELD_OP(sdr->sensor_units1); + + /* Bit 0 */ + percent = FIELD_PERCENTAGE(sdr->sensor_units1); + + base_idx = sdr->sensor_units2; + + if (*op == 0x0 || *op == 0x3) + *modifier = 0; + else + *modifier = sdr->sensor_units3; + + if (percent) { + sprintf(units, "%"); + } else { + if (base_idx > 0 && base_idx <= MAX_SENSOR_BASE_UNIT) { + if (rate_idx > 0 && rate_idx < MAX_SENSOR_RATE_UNIT) { + sprintf(units, "%s %s", sensor_base_units[base_idx], + sensor_rate_units[rate_idx]); + } else { + sprintf(units, "%s", sensor_base_units[base_idx]); + } + } + } + + return 0; +} + + +/* Get the name of the sensor from the SDR */ +int +sdr_get_sensor_name(sdr_full_t *sdr, char *name) { + int field_type, field_len; + int idx, idx_eff, val; + char *str; + + /* Bits 7:6 */ + field_type = FIELD_TYPE(sdr->str_type_len); + /* Bits 4:0 */ + field_len = FIELD_LEN(sdr->str_type_len) + 1; + + str = sdr->str; + + /* Case: length is zero */ + if (field_len == 1) { + syslog(LOG_ALERT, "get_sensor_name: str length is 0\n"); + // TODO: Fix this hack later + sprintf(name, "%s", str); + return -1; + } + + /* Retrieve field data depending on the type it was stored. */ + switch (field_type) { + case TYPE_BINARY: + /* TODO: Need to add support to read data stored in binary type. */ + break; + + case TYPE_BCD_PLUS: + + idx = 0; + while (idx != field_len) { + name[idx] = bcd_plus_array[str[idx] & 0x0F]; + idx++; + } + name[idx] = '\0'; + break; + + case TYPE_ASCII_6BIT: + + idx_eff = idx = 0; + + while (field_len > 0) { + + /* 6-Bits => Bits 5:0 of the first byte */ + val = str[idx] & 0x3F; + name[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + field_len--; + + if (field_len > 0) { + /* 6-Bits => Bits 3:0 of second byte + Bits 7:6 of first byte. */ + val = ((str[idx] & 0xC0) >> 6) | + ((str[idx + 1] & 0x0F) << 2); + name[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + field_len--; + } + + if (field_len > 0) { + /* 6-Bits => Bits 1:0 of third byte + Bits 7:4 of second byte. */ + val = ((str[idx + 1] & 0xF0) >> 4) | + ((str[idx + 2] & 0x03) << 4); + name[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + + /* 6-Bits => Bits 7:2 of third byte. */ + val = ((str[idx + 2] & 0xFC) >> 2); + name[idx_eff++] = ascii_6bit[(val & 0xF0) >> 4][val & 0x0F]; + + field_len--; + idx += 3; + } + } + /* Add Null terminator */ + name[idx_eff] = '\0'; + break; + + case TYPE_ASCII_8BIT: + snprintf(name, field_len, str); + /* Add Null terminator */ + name[field_len] = '\0'; + break; + } + + return 0; +} + +/* Populates all sensor_info_t struct using the path to SDR dump */ +int +sdr_init(char *path, sensor_info_t *sinfo) { + int fd; + uint8_t buf[MAX_SDR_LEN] = {0}; + uint8_t bytes_rd = 0; + uint8_t snr_num = 0; + sdr_full_t *sdr; + + while (access(path, F_OK) == -1) { + sleep(5); + } + + fd = open(path, O_RDONLY); + if (fd < 0) { + syslog(LOG_ERR, "sdr_init: open failed for %s\n", path); + return -1; + } + + while ((bytes_rd = read(fd, buf, sizeof(sdr_full_t))) > 0) { + if (bytes_rd != sizeof(sdr_full_t)) { + syslog(LOG_ERR, "sdr_init: read returns %d bytes\n", bytes_rd); + return -1; + } + + sdr = (sdr_full_t *) buf; + snr_num = sdr->sensor_num; + sinfo[snr_num].valid = true; + memcpy(&sinfo[snr_num].sdr, sdr, sizeof(sdr_full_t)); + } + + return 0; +} + diff --git a/common/recipes-lib/sdr/files/sdr.h b/common/recipes-lib/sdr/files/sdr.h new file mode 100644 index 0000000..c474fb1 --- /dev/null +++ b/common/recipes-lib/sdr/files/sdr.h @@ -0,0 +1,163 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SDR_H__ +#define __SDR_H__ + +#include <stdbool.h> +#include <openbmc/ipmi.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_SDR_LEN 64 + + +#define MAX_SENSOR_RATE_UNIT 7 +#define MAX_SENSOR_BASE_UNIT 92 + +typedef struct _sensor_info_t { + bool valid; + sdr_full_t sdr; +} sensor_info_t; + +/* List of all the Sensor Rate Units types. */ +const char * sensor_rate_units[] = { + "", /* 0x00 */ + "per \xC2\xB5s", /* 0x01 */ + "per ms", /* 0x02 */ + "per s", /* 0x03 */ + "per min", /* 0x04 */ + "per hour", /* 0x05 */ + "per day", /* 0x06 */ + "reserved", /* 0x07 */ +}; + + +/* List of all the Sensor Base Units types. */ +const char * sensor_base_units[] = { + "", /* 000 */ + "C", /* 001 */ + "F", /* 002 */ + "K", /* 003 */ + "Volts", /* 004 */ + "Amps", /* 005 */ + "Watts", /* 006 */ + "Joules", /* 007 */ + "Coulombs", /* 008 */ + "VA", /* 009 */ + "Nits", /* 010 */ + "lumen", /* 011 */ + "lux", /* 012 */ + "Candela", /* 013 */ + "kPa", /* 014 */ + "PSI", /* 015 */ + "Newton", /* 016 */ + "CFM", /* 017 */ + "RPM", /* 018 */ + "Hz", /* 019 */ + "\xC2\xB5s", /* 020 */ + "ms", /* 021 */ + "sec", /* 022 */ + "min", /* 023 */ + "hour", /* 024 */ + "day", /* 025 */ + "week", /* 026 */ + "mil", /* 027 */ + "inches", /* 028 */ + "feet", /* 029 */ + "cu in", /* 030 */ + "cu feet", /* 031 */ + "mm", /* 032 */ + "cm", /* 033 */ + "m", /* 034 */ + "cu cm", /* 035 */ + "cu m", /* 036 */ + "liters", /* 037 */ + "fluid ounce", /* 038 */ + "radians", /* 039 */ + "steradians", /* 040 */ + "revolutions", /* 041 */ + "cycles", /* 042 */ + "gravities", /* 043 */ + "ounce", /* 044 */ + "pound", /* 045 */ + "ft-lb", /* 046 */ + "oz-in", /* 047 */ + "gauss", /* 048 */ + "gilberts", /* 049 */ + "henry", /* 050 */ + "millihenry", /* 051 */ + "farad", /* 052 */ + "microfarad", /* 053 */ + "ohms", /* 054 */ + "siemens", /* 055 */ + "mole", /* 056 */ + "becquerel", /* 057 */ + "PPM", /* 058 */ + "reserved", /* 059 */ + "Db", /* 060 */ + "DbA", /* 061 */ + "DbC", /* 062 */ + "gray", /* 063 */ + "sievert", /* 064 */ + "color temp deg K", /* 065 */ + "bit", /* 066 */ + "kilobit", /* 067 */ + "megabit", /* 068 */ + "gigabit", /* 069 */ + "B", /* 070 */ + "KB", /* 071 */ + "MB", /* 072 */ + "GB", /* 073 */ + "word", /* 074 */ + "dword", /* 075 */ + "qword", /* 076 */ + "line", /* 077 */ + "hit", /* 078 */ + "miss", /* 079 */ + "retry", /* 080 */ + "reset", /* 081 */ + "overflow", /* 082 */ + "underrun", /* 083 */ + "collision", /* 084 */ + "packets", /* 085 */ + "messages", /* 086 */ + "characters", /* 087 */ + "error", /* 088 */ + "correctable error", /* 089 */ + "uncorrectable error", /* 090 */ + "fatal error", /* 091 */ + "grams", /* 092 */ + "", /* 093 */ +}; + +int sdr_init(char *path, sensor_info_t *sinfo); + +int sdr_get_sensor_units(sdr_full_t *sdr, uint8_t *op, uint8_t *modifier, + char *units); +int sdr_get_sensor_name(sdr_full_t *sdr, char *name); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __SDR_H__ */ diff --git a/common/recipes-lib/sdr/libsdr_0.1.bb b/common/recipes-lib/sdr/libsdr_0.1.bb new file mode 100644 index 0000000..958e0c6 --- /dev/null +++ b/common/recipes-lib/sdr/libsdr_0.1.bb @@ -0,0 +1,30 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "SDR Library" +DESCRIPTION = "library for extracting information from SDR" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" + + +LIC_FILES_CHKSUM = "file://sdr.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://Makefile \ + file://sdr.c \ + file://sdr.h \ + " + +S = "${WORKDIR}" + +DEPENDS += " libipmi " + +do_install() { + install -d ${D}${libdir} + install -m 0644 libsdr.so ${D}${libdir}/libsdr.so + + install -d ${D}${includedir}/openbmc + install -m 0644 sdr.h ${D}${includedir}/openbmc/sdr.h +} + +FILES_${PN} = "${libdir}/libsdr.so" +FILES_${PN}-dev = "${includedir}/openbmc/sdr.h" diff --git a/common/recipes-rest/rest-api/files/node.py b/common/recipes-rest/rest-api/files/node.py new file mode 100644 index 0000000..41e0a3e --- /dev/null +++ b/common/recipes-rest/rest-api/files/node.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +# Class Definition for Resource + +class node: + def __init__(self, info = None, actions = None): + if info == None: + self.info = {} + else: + self.info = info + + if actions == None: + self.actions = [] + else: + self.actions = actions + + def getInformation(self): + return self.info + + def getActions(self): + return self.actions + + def doAction(self, action): + result = { "result": 'failure', "reason": 'not supported'} diff --git a/common/recipes-rest/rest-api/files/node_api.py b/common/recipes-rest/rest-api/files/node_api.py new file mode 100644 index 0000000..ca5cc5c --- /dev/null +++ b/common/recipes-rest/rest-api/files/node_api.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +from node import node +from pal import * + +def get_node_api(): + + name = pal_get_platform_name() + info = { + "Description": name + " RESTful API Entry", + } + + return node(info) diff --git a/common/recipes-rest/rest-api/files/node_bmc.py b/common/recipes-rest/rest-api/files/node_bmc.py new file mode 100644 index 0000000..14b51e7 --- /dev/null +++ b/common/recipes-rest/rest-api/files/node_bmc.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + + +from subprocess import * +import re +from node import node +from pal import * + +class bmcNode(node): + def __init__(self, info = None, actions = None): + if info == None: + self.info = {} + else: + self.info = info + if actions == None: + self.actions = [] + else: + self.actions = actions + + def getInformation(self): + # Get Platform Name + name = pal_get_platform_name() + + # Get BMC Reset Reason + wdt_counter = Popen('devmem 0x1e785010', \ + shell=True, stdout=PIPE).stdout.read() + wdt_counter = int(wdt_counter, 0) + + wdt_counter &= 0xff00 + + if wdt_counter: + por_flag = 0 + else: + por_flag = 1 + + if por_flag: + reset_reason = "Power ON Reset" + else: + reset_reason = "User Initiated Reset or WDT Reset" + + # Get BMC's Up Time + uptime = Popen('uptime', \ + shell=True, stdout=PIPE).stdout.read() + + # Get Usage information + data = Popen('top -b n1', \ + shell=True, stdout=PIPE).stdout.read() + adata = data.split('\n') + mem_usage = adata[0] + cpu_usage = adata[1] + + # Get OpenBMC version + version = "" + data = Popen('cat /etc/issue', \ + shell=True, stdout=PIPE).stdout.read() + #Version might start with 'v'(wedge) or 'V'(Yosemite) + if name == 'Yosemite': + ver = re.search(r'V([\w\d._-]*)\s', data) + else: + ver = re.search(r'v([\w\d._-]*)\s', data) + if ver: + version = ver.group(1) + + + info = { + "Description": name + " BMC", + "Reset Reason": reset_reason, + "Uptime": uptime, + "Memory Usage": mem_usage, + "CPU Usage": cpu_usage, + "OpenBMC Version": version, + } + + return info; + +def get_node_bmc(): + return bmcNode() diff --git a/common/recipes-rest/rest-api/files/node_config.py b/common/recipes-rest/rest-api/files/node_config.py new file mode 100644 index 0000000..d37cc25 --- /dev/null +++ b/common/recipes-rest/rest-api/files/node_config.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + + +import os +from subprocess import * +from node import node +from pal import * + +class configNode(node): + def __init__(self, name = None, actions = None): + self.name = name + + if actions == None: + self.actions = [] + else: + self.actions = actions + + def getInformation(self): + result = {} + cmd = '/usr/local/bin/cfg-util dump-all' + data = Popen(cmd, shell=True, stdout=PIPE).stdout.read() + sdata = data.split('\n'); + for line in sdata: + # skip lines that does not start with name + if line.startswith(self.name): + kv = line.split(':') + result[kv[0].strip()] = kv[1].strip() + return result + + def doAction(self, data): + res = "success" + # Get the list of parameters to be updated + params = data["update"] + for key in params.keys(): + # update only if the key starts with the name + if key.startswith(self.name): + ret = pal_set_key_value(key, params[key]) + if ret: + res = "failure" + + result = {"result": res} + + return result + +def get_node_config(name): + actions = ["update"] + return configNode(name = name, actions = actions) diff --git a/common/recipes-rest/rest-api/files/node_fruid.py b/common/recipes-rest/rest-api/files/node_fruid.py new file mode 100644 index 0000000..d7a1dc3 --- /dev/null +++ b/common/recipes-rest/rest-api/files/node_fruid.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +from subprocess import * +from node import node + +class fruidNode(node): + def __init__(self, name, info = None, actions = None): + self.name = name + + if info == None: + self.info = {} + else: + self.info = info + if actions == None: + self.actions = [] + else: + self.actions = actions + + def getInformation(self): + result = {} + cmd = '/usr/local/bin/fruid-util ' + self.name + data = Popen(cmd, shell=True, stdout=PIPE).stdout.read() + sdata = data.split('\n') + for line in sdata: + # skip lines with --- or startin with FRU + if line.find("FRU") != -1: + continue + if line.find("-----") != -1: + continue + + kv = line.split(':') + if (len(kv) < 2): + continue + + result[kv[0].strip()] = kv[1].strip() + + return result + +def get_node_fruid(name): + return fruidNode(name) diff --git a/common/recipes-rest/rest-api/files/node_sensors.py b/common/recipes-rest/rest-api/files/node_sensors.py new file mode 100644 index 0000000..0e7ffc1 --- /dev/null +++ b/common/recipes-rest/rest-api/files/node_sensors.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +from subprocess import * +import json +import os +import re +from node import node + +class sensorsNode(node): + def __init__(self, name, info = None, actions = None): + self.name = name + if info == None: + self.info = {} + else: + self.info = info + if actions == None: + self.actions = [] + else: + self.actions = actions + + def getInformation(self): + result = {} + cmd = '/usr/local/bin/sensor-util ' + self.name + data = Popen(cmd, shell=True, stdout=PIPE).stdout.read() + sdata = data.split('\n') + for line in sdata: + # skip lines with " or startin with FRU + if line.find("bic_read_sensor_wrapper") != -1: + continue + if line.find("failed") != -1: + continue + + kv = line.split(':') + if (len(kv) < 2): + continue + + result[kv[0].strip()] = kv[1].strip() + + return result + +def get_node_sensors(name): + return sensorsNode(name) diff --git a/common/recipes-rest/rest-api/files/node_server.py b/common/recipes-rest/rest-api/files/node_server.py new file mode 100644 index 0000000..57a5c42 --- /dev/null +++ b/common/recipes-rest/rest-api/files/node_server.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + + +import os +from subprocess import * +from node import node +from pal import * + +class serverNode(node): + def __init__(self, num = None, info = None, actions = None): + self.num = num + + if info == None: + self.info = {} + else: + self.info = info + if actions == None: + self.actions = [] + else: + self.actions = actions + + def getInformation(self): + ret = pal_get_server_power(self.num) + if ret == 0: + status = 'power-off' + elif ret == 1: + status = 'power-on' + else: + status = 'error' + + info = { "status": status } + + return info + + def doAction(self, data): + if pal_set_server_power(self.num, data["action"]) == -1: + res = 'failure' + else: + res = 'success' + + result = { "result": res } + + return result + +def get_node_server(num): + actions = ["power-on", + "power-off", + "power-cycle", + "graceful-shutdown" + ] + return serverNode(num = num, actions = actions) diff --git a/common/recipes-rest/rest-api/files/node_spb.py b/common/recipes-rest/rest-api/files/node_spb.py new file mode 100644 index 0000000..a9fe4e6 --- /dev/null +++ b/common/recipes-rest/rest-api/files/node_spb.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# +from node import node +from pal import * + +class spbNode(node): + def __init__(self, info = None, actions = None): + if info == None: + self.info = {} + else: + self.info = info + + if actions == None: + self.actions = [] + else: + self.actions = actions + + def doAction(self, data): + if pal_sled_cycle(data["action"]) == -1: + res = 'failure' + else: + res = 'success' + + result = { "result": res } + + return result + +def get_node_spb(): + name = pal_get_platform_name() + info = { + "Description": name + " Side Plane", + } + + actions = [ "sled-cycle" ] + return spbNode(info, actions) diff --git a/common/recipes-rest/rest-api/files/pal.py b/common/recipes-rest/rest-api/files/pal.py new file mode 100644 index 0000000..8faef30 --- /dev/null +++ b/common/recipes-rest/rest-api/files/pal.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +from ctypes import * + +lpal_hndl = CDLL("libpal.so") + +def pal_get_platform_name(): + name = create_string_buffer(16) + ret = lpal_hndl.pal_get_platform_name(name) + if ret: + return None + else: + return name.value + +def pal_get_num_slots(): + num = c_ubyte() + p_num = pointer(num) + ret = lpal_hndl.pal_get_num_slots(p_num) + if ret: + return None + else: + return num.value + +def pal_is_server_prsnt(slot_id): + status = c_ubyte() + p_status = pointer(status) + ret = lpal_hndl.pal_is_server_prsnt(slot_id, p_status) + if ret: + return None + else: + return status.value + +def pal_get_server_power(slot_id): + status = c_ubyte() + p_status = pointer(status) + ret = lpal_hndl.pal_get_server_power(slot_id, p_status) + if ret: + return None + else: + return status.value + +def pal_set_server_power(slot_id, command): + cmd = c_ubyte() + if command == 'power-off': + cmd.value = 0 + elif command == 'power-on': + cmd.value = 1 + elif command == 'power-cycle': + cmd.value = 2 + elif command == 'graceful-shutdown': + cmd.value = 3 + ret = lpal_hndl.pal_set_server_power(slot_id, cmd) + if ret: + return -1 + else: + return 0 + +def pal_sled_cycle(command): + if command != 'sled-cycle': + return -1 + + ret = lpal_hndl.pal_sled_cycle() + if ret: + return -1 + else: + return 0 + +def pal_set_key_value(key, value): + pkey = create_string_buffer(key) + pvalue = create_string_buffer(value) + + ret = lpal_hndl.pal_set_key_value(pkey, pvalue) + if ret: + return -1; + else: + return 0; diff --git a/common/recipes-rest/rest-api/files/rest.py b/common/recipes-rest/rest-api/files/rest.py new file mode 100644 index 0000000..0a90d54 --- /dev/null +++ b/common/recipes-rest/rest-api/files/rest.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +from ctypes import * +from bottle import route, run, template, request, response, ServerAdapter +from bottle import abort +from wsgiref.simple_server import make_server, WSGIRequestHandler, WSGIServer +import json +import ssl +import socket +import os +from tree import tree +from node import node +from plat_tree import init_plat_tree + +CONSTANTS = { + 'certificate': '/usr/lib/ssl/certs/rest_server.pem', +} + +root = init_plat_tree() + +# Generic router for incoming requests +@route('/<path:path>', method='ANY') +def url_router(path): + token = path.split('/') + # Find the Node + r = root + for t in token: + r = r.getChildByName(t) + if r == None: + return r + c = r.data + + # Handle GET request + if request.method == 'GET': + # Gather info/actions directly from respective node + info = c.getInformation() + actions = c.getActions() + + # Create list of resources from tree structure + resources = [] + ca = r.getChildren() + for t in ca: + resources.append(t.name) + result = {'Information': info, + 'Actions': actions, + 'Resources': resources } + + return result + + # Handle POST request + if request.method == 'POST': + return c.doAction(json.load(request.body)) + + return None + +run(host = "::", port = 8080) + +# TODO: Test the https connection with proper certificates +# SSL Wrapper for Rest API +class SSLWSGIRefServer(ServerAdapter): + def run(self, handler): + if self.quiet: + class QuietHandler(WSGIRequestHandler): + def log_request(*args, **kw): pass + self.options['handler_class'] = QuietHandler + + # IPv6 Support + server_cls = self.options.get('server_class', WSGIServer) + + if ':' in self.host: + if getattr(server_cls, 'address_family') == socket.AF_INET: + class server_cls(server_cls): + address_family = socket.AF_INET6 + + srv = make_server(self.host, self.port, handler, + server_class=server_cls, **self.options) + srv.socket = ssl.wrap_socket ( + srv.socket, + certfile=CONSTANTS['certificate'], + server_side=True) + srv.serve_forever() + +# Use SSL if the certificate exists. Otherwise, run without SSL. +if os.access(CONSTANTS['certificate'], os.R_OK): + run(server=SSLWSGIRefServer(host="::", port=8443)) +else: + run(host = "::", port = 8080) diff --git a/common/recipes-rest/rest-api/files/tree.py b/common/recipes-rest/rest-api/files/tree.py new file mode 100644 index 0000000..ca81510 --- /dev/null +++ b/common/recipes-rest/rest-api/files/tree.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +# Class Definition for Tree + +class tree: + def __init__(self, name, data = None): + self.name = name + self.data = data + self.children = [] + + def addChild(self, child): + self.children.append(child) + + def addChildren(self, children): + for child in children: + self.children.append(child) + + def getChildren(self): + return self.children + + def getChildByName(self, name): + if self.name == name: + return self + + for child in self.children: + if child.name == name: + return child + return None diff --git a/common/recipes-rest/rest-api/rest-api_0.2.bb b/common/recipes-rest/rest-api/rest-api_0.2.bb new file mode 100644 index 0000000..1956cb2 --- /dev/null +++ b/common/recipes-rest/rest-api/rest-api_0.2.bb @@ -0,0 +1,36 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "Rest API Daemon" +DESCRIPTION = "Daemon to handle RESTful interface." +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://rest.py;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0" + + +SRC_URI = "file://rest.py \ + file://node.py \ + file://tree.py \ + file://pal.py \ + " +DEPENDS += "libpal" + + +binfiles = "rest.py node.py tree.py pal.py" + +pkgdir = "rest-api" +RDEPENDS_${PN} += "libpal" diff --git a/common/recipes-utils/bitbang/bitbang_0.1.bb b/common/recipes-utils/bitbang/bitbang_0.1.bb new file mode 100644 index 0000000..16fdbd3 --- /dev/null +++ b/common/recipes-utils/bitbang/bitbang_0.1.bb @@ -0,0 +1,37 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "Device driver using GPIO bitbang" +DESCRIPTION = "Various device driver using GPIO bitbang" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://bitbang.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI = "file://src \ + " + +DEPENDS += "openbmc-utils libgpio" + +S = "${WORKDIR}/src" + +do_install() { + install -d ${D}${bindir} + install -m 755 spi-bb ${D}${bindir}/spi-bb + install -m 755 mdio-bb ${D}${bindir}/mdio-bb +} + +FILES_${PN} = "${bindir}" diff --git a/common/recipes-utils/bitbang/files/src/Makefile b/common/recipes-utils/bitbang/files/src/Makefile new file mode 100644 index 0000000..24e4220 --- /dev/null +++ b/common/recipes-utils/bitbang/files/src/Makefile @@ -0,0 +1,29 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +all: spi-bb mdio-bb + +spi-bb: spi_bb.o bitbang.o + $(CC) -o $@ $^ $(LDFLAGS) -lgpio + +mdio-bb: mdio_bb.o bitbang.o + $(CC) -o $@ $^ $(LDFLAGS) -lgpio + +.PHONY: clean + +clean: + rm -rf *.o spi-bb mdio-bb diff --git a/common/recipes-utils/bitbang/files/src/bitbang.c b/common/recipes-utils/bitbang/files/src/bitbang.c new file mode 100644 index 0000000..1318f42 --- /dev/null +++ b/common/recipes-utils/bitbang/files/src/bitbang.c @@ -0,0 +1,236 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +//#define DEBUG +//#define VERBOSE + +#include "bitbang.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <openbmc/log.h> + +#define NANOSEC_IN_SEC (1000 * 1000 * 1000) + +#define BITBANG_FREQ_MAX (500 * 1000 * 1000) /* 500M Hz */ +#define BITBANG_FREQ_DEFAULT (1 * 1000 * 1000) /* 1M Hz */ + +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +struct bitbang_handle { + bitbang_init_st bbh_init; + uint32_t bbh_half_clk; /* ns per clock cycle */ +}; + +void bitbang_init_default(bitbang_init_st *init) +{ + memset(init, sizeof(*init), 0); + init->bbi_clk_start = BITBANG_PIN_HIGH; + init->bbi_data_out = BITBANG_CLK_EDGE_FALLING; + init->bbi_data_in = BITBANG_CLK_EDGE_RISING; + init->bbi_freq = BITBANG_FREQ_DEFAULT; +} + +bitbang_handle_st* bitbang_open(const bitbang_init_st *init) +{ + bitbang_handle_st *hdl; + + if (!init || !init->bbi_pin_f + || !init->bbi_freq || init->bbi_freq > BITBANG_FREQ_MAX) { + LOG_ERR(EINVAL, "Invalid init structure"); + return NULL; + } + + hdl = calloc(1, sizeof(*hdl)); + if (!hdl) { + return NULL; + } + + hdl->bbh_init = *init; + hdl->bbh_half_clk = NANOSEC_IN_SEC / init->bbi_freq / 2; + + LOG_DBG("Bitbang open with initial %s, data out at %s, data in at %s, " + "freq at %uHz, half clk %uns", + (init->bbi_clk_start == BITBANG_PIN_LOW) ? "LOW" : "HIGH", + (init->bbi_data_out == BITBANG_CLK_EDGE_RISING) + ? "RISING" : "FALLING", + (init->bbi_data_in == BITBANG_CLK_EDGE_RISING) + ? "RISING" : "FALLING", + init->bbi_freq, hdl->bbh_half_clk); + + return hdl; +} + +void bitbang_close(bitbang_handle_st *hdl) +{ + free(hdl); +} + +/* + * The threshold (ns) to use spin instead of nanosleep(). + * Before adding the high resolution timer support, either spin or nanosleep() + * will not bring the process wakeup within 10ms. It turns out the system time + * update is also controlled by HZ (100). + * After I added the high resolution timer support, the spin works as the + * system time is updated more frequently. However, nanosleep() solution is + * still noticable slower comparing with spin. There could be some kernel + * scheduling tweak missing. Did not get time on that yet. + * For now, use 10ms as the threshold to determine if spin or nanosleep() + * is used. + */ +#define BITBANG_SPIN_THRESHOLD (10 * 1000 * 1000) + +static int sleep_ns(uint32_t clk) +{ + struct timespec req, rem; + int rc = 0; + if (clk <= BITBANG_SPIN_THRESHOLD) { + struct timespec orig; + rc = clock_gettime(CLOCK_MONOTONIC, &req); + orig = req; + while (!rc && clk) { + uint32_t tmp; + rc = clock_gettime(CLOCK_MONOTONIC, &rem); + tmp = (rem.tv_sec - req.tv_sec) * NANOSEC_IN_SEC; + if (rem.tv_nsec >= req.tv_nsec) { + tmp += rem.tv_nsec - req.tv_nsec; + } else { + tmp -= req.tv_nsec - rem.tv_nsec; + } + if (tmp >= clk) { + break; + } + clk -= tmp; + req = rem; + } + } else { + req.tv_sec = 0; + req.tv_nsec = clk; + while ((rc = nanosleep(&req, &rem)) == -1 && errno == EINTR) { + req = rem; + } + } + if (rc == -1) { + rc = errno; + LOG_ERR(rc, "Failed to sleep %u nanoseconds", clk); + } + return rc; +} + +int bitbang_io(const bitbang_handle_st *hdl, bitbang_io_st *io) +{ + int rc = 0; + uint32_t clk = hdl->bbh_half_clk; + const struct { + bitbang_pin_value_en value; + bitbang_clk_edge_en edge; + } clks[] = { + {BITBANG_PIN_HIGH, BITBANG_CLK_EDGE_FALLING}, + {BITBANG_PIN_LOW, BITBANG_CLK_EDGE_RISING}, + }; + int clk_idx; + int n_clk = 0; + int n_bits = 0; + const uint8_t *dout = io->bbio_dout; + uint8_t *din = io->bbio_din; + int bit_pos = 7; + bitbang_pin_func pin_f = hdl->bbh_init.bbi_pin_f; + void *context = hdl->bbh_init.bbi_context; + + if ((io->bbio_in_bits == 0 && io->bbio_din) + || (io->bbio_in_bits > 0 && !io->bbio_din)) { + rc = EINVAL; + LOG_ERR(rc, "Incorrect in bits and in buffer"); + goto out; + } + + if ((io->bbio_out_bits == 0 && io->bbio_dout) + || (io->bbio_out_bits > 0 && !io->bbio_dout)) { + rc = EINVAL; + LOG_ERR(rc, "Incorrect out bits and out buffer"); + goto out; + } + + if (io->bbio_in_bits == 0 && io->bbio_out_bits == 0) { + rc = EINVAL; + LOG_ERR(rc, "Both in and out bits are 0"); + goto out; + } + + if (hdl->bbh_init.bbi_clk_start == BITBANG_PIN_HIGH) { + clk_idx = 0; + } else { + clk_idx = 1; + } + + /* set the CLK pin start position */ + pin_f(BITBANG_CLK_PIN, clks[clk_idx].value, context); + + /* clear the first byte of din */ + if (din && io->bbio_in_bits) { + memset(din, 0, (io->bbio_in_bits + 7) / 8); + } + + do { + if ((rc = sleep_ns(clk))) { + goto out; + } + + /* output first */ + if (hdl->bbh_init.bbi_data_out == clks[clk_idx].edge) { + if (dout && n_bits < io->bbio_out_bits) { + pin_f(BITBANG_DATA_OUT, (*dout >> bit_pos) & 0x1, context); + } + } + + /* then, input */ + if (hdl->bbh_init.bbi_data_in == clks[clk_idx].edge) { + if (din && n_bits < io->bbio_in_bits) { + *din |= (pin_f(BITBANG_DATA_IN, 0, context) & 0x1) << bit_pos; + } + } + + if (++n_clk % 2 == 0) { + /* one bit for every 2 half clks */ + n_bits ++; + if (bit_pos == 0) { + if (dout) { + dout++; + } + if (din) { + din++; + } + bit_pos = 7; + } else { + bit_pos --; + } + } + clk_idx = 1 - clk_idx; + pin_f(BITBANG_CLK_PIN, clks[clk_idx].value, context); + } while (n_bits < MAX(io->bbio_in_bits, io->bbio_out_bits)); + + out: + + return -rc; +} diff --git a/common/recipes-utils/bitbang/files/src/bitbang.h b/common/recipes-utils/bitbang/files/src/bitbang.h new file mode 100644 index 0000000..0f21a49 --- /dev/null +++ b/common/recipes-utils/bitbang/files/src/bitbang.h @@ -0,0 +1,66 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef BITBANG_H +#define BITBANG_H + +#include <stdint.h> + +typedef enum { + BITBANG_CLK_PIN, + BITBANG_DATA_IN, + BITBANG_DATA_OUT, +} bitbang_pin_type_en; + +typedef enum { + BITBANG_PIN_LOW = 0, + BITBANG_PIN_HIGH = 1, +} bitbang_pin_value_en; + +typedef enum { + BITBANG_CLK_EDGE_RISING, + BITBANG_CLK_EDGE_FALLING, +} bitbang_clk_edge_en; + +typedef bitbang_pin_value_en (* bitbang_pin_func)( + bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context); + +typedef struct { + bitbang_pin_value_en bbi_clk_start; + bitbang_clk_edge_en bbi_data_out; + bitbang_clk_edge_en bbi_data_in; + uint32_t bbi_freq; + bitbang_pin_func bbi_pin_f; + void *bbi_context; +} bitbang_init_st; + +typedef struct bitbang_handle bitbang_handle_st; + +void bitbang_init_default(bitbang_init_st *init); +bitbang_handle_st* bitbang_open(const bitbang_init_st *init); +void bitbang_close(bitbang_handle_st *hdl); + +typedef struct { + uint32_t bbio_in_bits; + uint32_t bbio_out_bits; + uint8_t *bbio_dout; + uint8_t *bbio_din; +} bitbang_io_st; + +int bitbang_io(const bitbang_handle_st *hdl, bitbang_io_st *io); + +#endif diff --git a/common/recipes-utils/bitbang/files/src/mdio_bb.c b/common/recipes-utils/bitbang/files/src/mdio_bb.c new file mode 100644 index 0000000..9137e17 --- /dev/null +++ b/common/recipes-utils/bitbang/files/src/mdio_bb.c @@ -0,0 +1,335 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +//#define DEBUG +//#define VERBOSE + +#include <stdlib.h> +#include <unistd.h> + +#include <openbmc/log.h> +#include <openbmc/gpio.h> + +#include "bitbang.h" + +typedef struct { + gpio_st m_mdc; + gpio_st m_mdio; +} mdio_context_st; + +/* + * 32b preamble, 2b start of frame, 2b operation code, + * 5b phy addr, 5b register addr, 2b turnaround, 16b data + */ +#define N_BITS (32 + 2 + 2 + 5 + 5 + 2 + 16) +#define N_BYTES (N_BITS + 7 / 8) + +#define START_OF_FRAME 0x1 +#define OP_READ 0x2 +#define OP_WRITE 0x1 +#define TURNAROUND 0x2 /* TA for write, for read, phy sends out TA */ + +void usage() +{ + fprintf(stderr, + "Usage:\n" + "mdio-bb: -c <GPIO for MDC> [-C <HIGH|low>]\n" + " -d <GPIO for MDIO> [-O <rising|FALLING>]\n" + " [-I <RISING|falling>] [-p] [-b]\n" + " <read|write> <phy address> <register address>\n" + " [value to write]\n"); +} + +bitbang_pin_value_en mdio_pin_f( + bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context) +{ + mdio_context_st *ctx = (mdio_context_st *)context; + gpio_st *gpio; + bitbang_pin_value_en res; + + switch (pin) { + case BITBANG_CLK_PIN: + gpio = &ctx->m_mdc; + break; + case BITBANG_DATA_IN: + case BITBANG_DATA_OUT: + gpio = &ctx->m_mdio; + break; + } + if (pin == BITBANG_DATA_IN) { + res = gpio_read(gpio) ? BITBANG_PIN_HIGH : BITBANG_PIN_LOW; + } else { + res = value; + gpio_write(gpio, ((res == BITBANG_PIN_HIGH) + ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW)); + } + return res; +} + +int main(int argc, char* const argv[]) +{ + int opt; + int mdc = -1, mdio = -1; + bitbang_pin_value_en mdc_start = BITBANG_PIN_HIGH; + bitbang_clk_edge_en out_edge = BITBANG_CLK_EDGE_FALLING; + bitbang_clk_edge_en in_edge = BITBANG_CLK_EDGE_RISING; + int is_write; + uint32_t phy_addr; + uint32_t reg_addr; + uint32_t data; /* data to write/read*/ + uint8_t buf[N_BYTES]; + uint8_t *buf_p; + mdio_context_st ctx; + bitbang_init_st init; + bitbang_handle_st *hdl = NULL; + bitbang_io_st io; + int n_bits; + int i; + int rc = 0; + int preamble = 0; + int binary = 0; + + while ((opt = getopt(argc, argv, "bc:C:d:D:p")) != -1) { + switch (opt) { + case 'b': + binary = 1; + break; + case 'c': + mdc = atoi(optarg); + break; + case 'C': + if (!strcasecmp(optarg, "high")) { + mdc_start = BITBANG_PIN_HIGH; + } else if (!strcasecmp(optarg, "low")) { + mdc_start = BITBANG_PIN_LOW; + } else { + usage(); + exit(-1); + } + break; + case 'd': + mdio = atoi(optarg); + break; + case 'I': + if (!strcasecmp(optarg, "rising")) { + in_edge = BITBANG_CLK_EDGE_RISING; + } if (!strcasecmp(optarg, "falling")) { + in_edge = BITBANG_CLK_EDGE_FALLING; + } else { + usage(); + exit(-1); + } + break; + case 'O': + if (!strcasecmp(optarg, "rising")) { + out_edge = BITBANG_CLK_EDGE_RISING; + } if (!strcasecmp(optarg, "falling")) { + out_edge = BITBANG_CLK_EDGE_FALLING; + } else { + usage(); + exit(-1); + } + break; + case 'p': + preamble = 1; + break; + default: + usage(); + exit(-1); + } + } + + if (mdc < 0 || mdio < 0) { + usage(); + exit(-1); + } + + if (optind + 2 >= argc) { + usage(); + exit(-1); + } + + /* read or write */ + if (!strcasecmp(argv[optind], "read")) { + is_write = 0; + } else if (!strcasecmp(argv[optind], "write")) { + is_write = 1; + } else { + usage(); + exit(-1); + } + + /* phy address, 5 bits only, so must be <= 0x1f */ + phy_addr = strtoul(argv[optind + 1], NULL, 0); + if (phy_addr > 0x1f) { + usage(); + exit(-1); + } + + /* register address, 5 bits only, so must be <= 0x1f */ + reg_addr = strtoul(argv[optind + 2], NULL, 0); + if (reg_addr > 0x1f) { + usage(); + exit(-1); + } + + /* data */ + if (is_write) { + if ((!binary && (optind + 4 != argc)) || + (binary && (optind + 3 != argc))) { + usage(); + exit(-1); + } + if (binary) { + uint16_t temp = 0; + if (fread(&temp, sizeof(temp), 1, stdin) != 1) { + usage(); + exit(-1); + } + data = htons(temp); + } else { + data = strtoul(argv[optind + 3], NULL, 0); + } + if (data > 0xFFFF) { + usage(); + exit(-1); + } + } else { + if ((!binary && (optind + 3 != argc)) || + (binary && (optind + 2 != argc))) { + usage(); + exit(-1); + } + } + + /* open all gpio */ + memset(&ctx, sizeof(ctx), 0); + gpio_init_default(&ctx.m_mdc); + gpio_init_default(&ctx.m_mdio); + if (gpio_open(&ctx.m_mdc, mdc) || gpio_open(&ctx.m_mdio, mdio)) { + goto out; + } + + if (gpio_change_direction(&ctx.m_mdc, GPIO_DIRECTION_OUT) + || gpio_change_direction(&ctx.m_mdio, GPIO_DIRECTION_OUT)) { + goto out; + } + + bitbang_init_default(&init); + init.bbi_clk_start = mdc_start; + init.bbi_data_out = out_edge; + init.bbi_data_in = in_edge; + init.bbi_freq = 1000 * 1000; /* 1M Hz */ + init.bbi_pin_f = mdio_pin_f; + init.bbi_context = &ctx; + hdl = bitbang_open(&init); + if (!hdl) { + goto out; + } + + if (is_write) { + buf[0] = (data >> 8) & 0xFF; + buf[1] = data & 0xFF; + io.bbio_out_bits = 16; + io.bbio_dout = buf; + io.bbio_in_bits = 0; + io.bbio_din = NULL; + } else { + io.bbio_in_bits = 16; + io.bbio_din = buf; + io.bbio_out_bits = 0; + io.bbio_dout = NULL; + } + + /* preamble, 32b */ + buf_p = buf; + n_bits = 0; + if (preamble) { + /* 32 bit of 1 for preamble */ + for (i = 0; i < 4; i++) { + *buf_p++ = 0xFF; + } + n_bits += 32; + } + + /* + * MDIO transaction header is: + * 2b START, 2b OPER CODE, 5b PHY ADDR, 5b register addr, 2b TURNROUND + */ + *buf_p++ = (START_OF_FRAME << 6) | (((is_write) ? OP_WRITE : OP_READ) << 4) + | ((phy_addr >> 1) & 0xF); + *buf_p++ = ((phy_addr & 0x1) << 7) | ((reg_addr & 0x1F) << 2) | TURNAROUND; + if (is_write) { + *buf_p++ = (data >> 8) & 0xFF; + *buf_p++ = data & 0xFF; + /* total # of bits is transaction header + 2 bytes to write */ + n_bits += 2 + 2 + 5 + 5 + 2 + 16; + } else { + /* for read, master does not send TR, so, n_bits should not include TR */ + n_bits += 2 + 2 + 5 + 5; + } + + memset(&io, sizeof(io), 0); + io.bbio_out_bits = n_bits; + io.bbio_dout = buf; + io.bbio_in_bits = 0; + io.bbio_din = NULL; + + rc = bitbang_io(hdl, &io); + if (rc != 0) { + goto out; + } + + /* for read, need to do another io for (2b TR + 16b data) reading */ + if (!is_write) { + /* first, change the MDIO to input */ + gpio_change_direction(&ctx.m_mdio, GPIO_DIRECTION_IN); + /* then, run the clock for read */ + memset(&io, sizeof(io), 0); + io.bbio_out_bits = 0; + io.bbio_dout = NULL;; + io.bbio_in_bits = 18; + io.bbio_din = buf; + + rc = bitbang_io(hdl, &io); + if (rc != 0) { + goto out; + } + + data = ((buf[0] << 2) | (buf[1] >> 6)) & 0xFF; + data <<= 8; + data |= ((buf[1] << 2) | (buf[2] >> 6)) & 0xFF; + } + + if (binary) { + if (!is_write) { + uint16_t temp = ntohs(data); + fwrite(&temp, sizeof(temp), 1, stdout); + } + } else { + printf("%s: 0x%02x\n", (is_write) ? "Wrote" : "Read", data); + } + + out: + if (hdl) { + bitbang_close(hdl); + } + gpio_close(&ctx.m_mdc); + gpio_close(&ctx.m_mdio); + + return 0; +} diff --git a/common/recipes-utils/bitbang/files/src/spi_bb.c b/common/recipes-utils/bitbang/files/src/spi_bb.c new file mode 100644 index 0000000..2125877 --- /dev/null +++ b/common/recipes-utils/bitbang/files/src/spi_bb.c @@ -0,0 +1,317 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +//#define DEBUG +//#define VERBOSE + +#include <stdlib.h> +#include <unistd.h> + +#include <openbmc/gpio.h> +#include <openbmc/log.h> + +#include "bitbang.h" + +void usage() +{ + fprintf(stderr, + "Usage:\n" + "spi-bb: -s <GPIO for CS> [-S <HIGH|low>]\n" + " -c <GPIO for CLK> [-C <HIGH|low>]\n" + " -o <GPIO for MOSI> [-O <rising|FALLING>]\n" + " -i <GPIO for MISO> [-I <RISING|falling>]\n" + " [-b]\n" + " < [-r <number of bits to read>]\n" + " [-w <number of bits to write> <byte 1> [... byte N]>\n\n" + "Note: If both '-r' and '-w' are provided, 'write' will be performed\n" + " before 'read'.\n"); +} + +typedef struct { + gpio_st sc_clk; + gpio_st sc_mosi; + gpio_st sc_miso; +} spi_context_st; + +bitbang_pin_value_en spi_pin_f( + bitbang_pin_type_en pin, bitbang_pin_value_en value, void *context) +{ + spi_context_st *ctx = (spi_context_st *)context; + gpio_st *gpio; + bitbang_pin_value_en res; + + switch (pin) { + case BITBANG_CLK_PIN: + gpio = &ctx->sc_clk; + break; + case BITBANG_DATA_IN: + gpio = &ctx->sc_miso; + break; + case BITBANG_DATA_OUT: + gpio = &ctx->sc_mosi; + break; + } + if (pin == BITBANG_DATA_IN) { + res = gpio_read(gpio) ? BITBANG_PIN_HIGH : BITBANG_PIN_LOW; + } else { + res = value; + gpio_write(gpio, ((res == BITBANG_PIN_HIGH) + ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW)); + } + return res; +} + +int main(int argc, char * const argv[]) +{ + bitbang_init_st init; + bitbang_handle_st *hdl = NULL; + int cs = -1, clk = -1, in = -1, out = -1; + gpio_st cs_gpio; + int opt; + int is_write = 0; + int is_read = 0; + int read_bits = 0; + int write_bits = 0; + int read_bytes = 0; + int write_bytes = 0; + int i; + uint8_t *read_buf = NULL;; + uint8_t *write_buf = NULL;; + bitbang_clk_edge_en dout_edge = BITBANG_CLK_EDGE_FALLING; + bitbang_clk_edge_en din_edge = BITBANG_CLK_EDGE_RISING; + bitbang_pin_value_en clk_start = BITBANG_PIN_HIGH; + bitbang_pin_value_en cs_value = BITBANG_PIN_HIGH; + spi_context_st ctx; + bitbang_io_st io; + int rc = 0; + int binary = 0; + + memset(&ctx, sizeof(ctx), 0); + gpio_init_default(&ctx.sc_clk); + gpio_init_default(&ctx.sc_mosi); + gpio_init_default(&ctx.sc_miso); + gpio_init_default(&cs_gpio); + + while ((opt = getopt(argc, argv, "bs:S:c:C:o:O:i:I:w:r:")) != -1) { + switch (opt) { + case 'b': + binary = 1; + break; + case 's': + cs = atoi(optarg); + break; + case 'S': + if (!strcmp(optarg, "high")) { + cs_value = BITBANG_PIN_HIGH; + } else if (!strcmp(optarg, "low")) { + cs_value = BITBANG_PIN_LOW; + } else { + usage(); + exit(-1); + } + break; + case 'c': + clk = atoi(optarg); + break; + case 'C': + if (!strcasecmp(optarg, "high")) { + clk_start = BITBANG_PIN_HIGH; + } else if (!strcasecmp(optarg, "low")) { + clk_start = BITBANG_PIN_LOW; + } else { + usage(); + exit(-1); + } + break; + case 'o': + out = atoi(optarg); + break; + case 'O': + if (!strcasecmp(optarg, "rising")) { + dout_edge = BITBANG_CLK_EDGE_RISING; + } else if (!strcasecmp(optarg, "falling")) { + dout_edge = BITBANG_CLK_EDGE_FALLING; + } else { + usage(); + exit(-1); + } + break; + case 'i': + in = atoi(optarg); + break; + case 'I': + if (!strcasecmp(optarg, "rising")) { + din_edge = BITBANG_CLK_EDGE_RISING; + } else if (!strcasecmp(optarg, "falling")) { + din_edge = BITBANG_CLK_EDGE_FALLING; + } else { + usage(); + exit(-1); + } + break; + case 'w': + is_write = 1; + write_bits = atoi(optarg); + if (write_bits <= 0) { + usage(); + exit(-1); + } + break; + case 'r': + is_read = 1; + read_bits = atoi(optarg); + if (read_bits <= 0) { + usage(); + exit(-1); + } + break; + default: + usage(); + exit(-1); + } + } + + if (clk < 0 || in < 0 || out < 0) { + usage(); + exit(-1); + } + + if ((!is_read && !is_write)) { + usage(); + exit(-1); + } + + write_bytes = ((write_bits + 7) / 8); + if (write_bytes) { + write_buf = calloc(write_bytes, sizeof(uint8_t)); + if (!write_buf) { + goto out; + } + if (binary) { + size_t written_bytes; + written_bytes = fread(write_buf, sizeof(*write_buf), write_bytes, stdin); + if( written_bytes != write_bytes ) { + goto out; + } + } else { + for (i = 0; i < write_bytes && i + optind < argc; i++) { + write_buf[i] = strtoul(argv[i + optind], NULL, 0); + } + } + } + + read_bytes = ((read_bits + 7) / 8); + if (read_bytes) { + read_buf = calloc(read_bytes, sizeof(uint8_t)); + if (!read_buf) { + goto out; + } + } + + if (gpio_open(&ctx.sc_clk, clk) || gpio_open(&ctx.sc_miso, in) + || gpio_open(&ctx.sc_mosi, out)) { + goto out; + } + + /* change GPIO directions, only MISO is input, all others are output */ + if (gpio_change_direction(&ctx.sc_clk, GPIO_DIRECTION_OUT) + || gpio_change_direction(&ctx.sc_miso, GPIO_DIRECTION_IN) + || gpio_change_direction(&ctx.sc_mosi, GPIO_DIRECTION_OUT)) { + goto out; + } + + if (cs != -1) { + if (gpio_open(&cs_gpio, cs)) { + goto out; + } + if (gpio_change_direction(&cs_gpio, GPIO_DIRECTION_OUT)) { + goto out; + } + } + + bitbang_init_default(&init); + init.bbi_clk_start = clk_start; + init.bbi_data_out = dout_edge; + init.bbi_data_in = din_edge; + init.bbi_freq = 1000 * 1000; /* 1M Hz */ + init.bbi_pin_f = spi_pin_f; + init.bbi_context = &ctx; + + hdl = bitbang_open(&init); + if (!hdl) { + goto out; + } + + if (cs != -1) { + /* have chip select */ + gpio_write(&cs_gpio, ((cs_value == BITBANG_PIN_HIGH) + ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW)); + } + + memset(&io, sizeof(io), 0); + io.bbio_in_bits = read_bits; + io.bbio_din = read_buf; + io.bbio_out_bits = write_bits; + io.bbio_dout = write_buf; + + rc = bitbang_io(hdl, &io); + if (rc != 0) { + goto out; + } + + if (binary) { + fwrite(read_buf, sizeof(*read_buf), read_bytes, stdout); + } else { + if (write_bits) { + printf("Wrote %u bits:", write_bits); + for (i = 0; i < write_bytes; i++) { + printf(" %02x", write_buf[i]); + } + printf("\n"); + } + + if (read_bits) { + printf("Read %u bits:", read_bits); + for (i = 0; i < read_bytes; i++) { + printf(" %02x", read_buf[i]); + } + printf("\n"); + } + } + + out: + if (hdl) { + bitbang_close(hdl); + } + gpio_close(&ctx.sc_clk); + gpio_close(&ctx.sc_miso); + gpio_close(&ctx.sc_mosi); + if (cs != -1) { + /* reset have chip select */ + gpio_write(&cs_gpio, ((cs_value == BITBANG_PIN_HIGH) + ? GPIO_VALUE_LOW : GPIO_VALUE_HIGH)); + gpio_close(&cs_gpio); + } + + if (read_buf) { + free(read_buf); + } + if (write_buf) { + free(write_buf); + } + return rc; +} diff --git a/common/recipes-utils/flashrom/files/01-include-make-local.patch b/common/recipes-utils/flashrom/files/01-include-make-local.patch new file mode 100644 index 0000000..660c4d6 --- /dev/null +++ b/common/recipes-utils/flashrom/files/01-include-make-local.patch @@ -0,0 +1,11 @@ +--- a/Makefile.orig 2015-08-05 17:10:45.945870520 -0700 ++++ b/Makefile 2015-08-05 17:11:01.212895144 -0700 +@@ -20,6 +20,8 @@ + + PROGRAM = flashrom + ++include make.local ++ + ############################################################################### + # Defaults for the toolchain. + diff --git a/common/recipes-utils/flashrom/files/flashrom-0.9.8/make.local b/common/recipes-utils/flashrom/files/flashrom-0.9.8/make.local new file mode 100644 index 0000000..54f4213 --- /dev/null +++ b/common/recipes-utils/flashrom/files/flashrom-0.9.8/make.local @@ -0,0 +1,9 @@ +CONFIG_BUSPIRATE_SPI = no +CONFIG_SERPROG = no +CONFIG_PONY_SPI = no +CONFIG_DEDIPROG = no +CONFIG_FT2232_SPI = no +CONFIG_USBBLASTER_SPI = no +CONFIG_PICKIT2_SPI = no +CONFIG_LINUX_SPI = yes +CONFIG_MSTARDDC_SPI = no diff --git a/common/recipes-utils/flashrom/flashrom_0.9.8.bb b/common/recipes-utils/flashrom/flashrom_0.9.8.bb new file mode 100644 index 0000000..a65a7c0 --- /dev/null +++ b/common/recipes-utils/flashrom/flashrom_0.9.8.bb @@ -0,0 +1,18 @@ +DESCRIPTION = "flashrom is a utility for identifying, reading, writing, verifying and erasing flash chips" +LICENSE = "GPLv2" +HOMEPAGE = "http://flashrom.org" + +LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe" +DEPENDS = "pciutils" + +SRC_URI = "http://download.flashrom.org/releases/flashrom-${PV}.tar.bz2 \ + file://flashrom-${PV}/make.local \ + file://01-include-make-local.patch \ + " + +Src_URI[md5sum] = "ac513076b63ab7eb411a7694bb8f6fda" +SRC_URI[sha256sum] = "13dc7c895e583111ecca370363a3527d237d178a134a94b20db7df177c05f934" + +do_install() { + oe_runmake PREFIX=${prefix} DESTDIR=${D} install +} diff --git a/common/recipes-utils/jbi/files/code/COPYING b/common/recipes-utils/jbi/files/code/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/common/recipes-utils/jbi/files/code/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/common/recipes-utils/jbi/files/code/Makefile b/common/recipes-utils/jbi/files/code/Makefile new file mode 100644 index 0000000..ca84b02 --- /dev/null +++ b/common/recipes-utils/jbi/files/code/Makefile @@ -0,0 +1,26 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +all: jbi + +jbi: jbicomp.o jbijtag.o jbimain.o jbistub.o + $(CC) -g -o $@ $^ $(LDFLAGS) -lgpio + +.PHONY: clean + +clean: + rm -rf *.o jbi diff --git a/common/recipes-utils/jbi/files/code/jbicomp.c b/common/recipes-utils/jbi/files/code/jbicomp.c new file mode 100644 index 0000000..99ba515 --- /dev/null +++ b/common/recipes-utils/jbi/files/code/jbicomp.c @@ -0,0 +1,416 @@ +/****************************************************************************/ +/* */ +/* Module: jbicomp.c */ +/* */ +/* Copyright (C) Altera Corporation 1997-2001 */ +/* */ +/* Description: Contains the code for compressing and uncompressing */ +/* Boolean array data. */ +/* */ +/* This algorithm works by searching previous bytes in the */ +/* data that match the current data. If a match is found, */ +/* then the offset and length of the matching data can */ +/* replace the actual data in the output. */ +/* */ +/* Revisions: 2.2 fixed /W4 warnings */ +/* */ +/****************************************************************************/ + +#include "jbiport.h" +#include "jbiexprt.h" +#include "jbicomp.h" + +#define SHORT_BITS 16 +#define CHAR_BITS 8 +#define DATA_BLOB_LENGTH 3 +#define MATCH_DATA_LENGTH 8192 +#define JBI_ACA_REQUEST_SIZE 1024 +#define JBI_ACA_BUFFER_SIZE (MATCH_DATA_LENGTH + JBI_ACA_REQUEST_SIZE) + +unsigned long jbi_in_length = 0L; +unsigned long jbi_in_index = 0L; /* byte index into compressed array */ +unsigned int jbi_bits_avail = CHAR_BITS; + +#if PORT == DOS +int jbi_current_variable_id = -1; +int jbi_current_page = -1; +int jbi_version = 0; +unsigned long jbi_out_length = 0L; +unsigned int jbi_out_index = 0; /* byte index into jbi_aca_out_buffer[] */ +unsigned long jbi_aca_in_offset = 0L; +unsigned char jbi_aca_out_buffer[JBI_ACA_BUFFER_SIZE]; +#endif + +/****************************************************************************/ +/* */ +/* The following functions implement incremental decompression of Boolean */ +/* array data, using a small memory window. */ +/* */ +/* This algorithm works by searching previous bytes in the data that match */ +/* the current data. If a match is found, then the offset and length of */ +/* the matching data can replace the actual data in the output. */ +/* */ +/* Memory usage is reduced by maintaining a "window" buffer which contains */ +/* the uncompressed data for one 8K page, plus some extra amount specified */ +/* by JBI_ACA_REQUEST_SIZE. The function jbi_uncompress_page() is used to */ +/* request a subrange of the uncompressed data, starting at a particular */ +/* bit position and extending a maximum of JBI_ACA_REQUEST_SIZE bytes. */ +/* */ +/****************************************************************************/ + +/****************************************************************************/ +/* */ + +unsigned int jbi_bits_required(unsigned int n) + +/* */ +/* Description: Calculate the minimum number of bits required to */ +/* represent n. */ +/* */ +/* Returns: Number of bits. */ +/* */ +/****************************************************************************/ +{ + unsigned int result = SHORT_BITS; + + if (n == 0) + { + result = 1; + } + else + { + /* Look for the highest non-zero bit position */ + while ((n & (1 << (SHORT_BITS - 1))) == 0) + { + n <<= 1; + --result; + } + } + + return (result); +} + +/****************************************************************************/ +/* */ + +unsigned int jbi_read_packed +( +#if PORT!=DOS + unsigned char *buffer, +#endif + unsigned int bits +) + +/* */ +/* Description: Read the next value from the input array "buffer". */ +/* Read only "bits" bits from the array. The amount of */ +/* bits that have already been read from "buffer" is */ +/* stored internally to this function. */ +/* */ +/* Returns: Up to 16 bit value. -1 if buffer overrun. */ +/* */ +/****************************************************************************/ +{ + unsigned int result = 0; + unsigned int shift = 0; + unsigned int databyte = 0; + + while (bits > 0) + { +#if PORT==DOS + databyte = GET_BYTE(jbi_aca_in_offset + jbi_in_index); +#else + databyte = buffer[jbi_in_index]; +#endif + result |= (((databyte >> (CHAR_BITS - jbi_bits_avail)) + & (0xFF >> (CHAR_BITS - jbi_bits_avail))) << shift); + + if (bits <= jbi_bits_avail) + { + result &= (0xFFFF >> (SHORT_BITS - (bits + shift))); + jbi_bits_avail -= bits; + bits = 0; + } + else + { + ++jbi_in_index; + shift += jbi_bits_avail; + bits -= jbi_bits_avail; + jbi_bits_avail = CHAR_BITS; + } + } + + return (result); +} + +#if PORT==DOS + +/****************************************************************************/ +/* */ + +void jbi_uncompress_next_page(int version) + +/* */ +/* Description: Uncompresses one page of compressed data, using */ +/* data page as reference for repeated sections. */ +/* Overwrites previous page of data in buffer. */ +/* */ +/* Returns: TRUE for success, FALSE if error encountered */ +/* */ +/****************************************************************************/ +{ + unsigned int i, j, offset, length; + unsigned int end_index; + unsigned long tmp_in_index = jbi_in_index; + unsigned int tmp_out_index = jbi_out_index; + unsigned int tmp_bits_avail = jbi_bits_avail; + unsigned int prev[3]; + unsigned long long_end; + unsigned int match_data_length = MATCH_DATA_LENGTH; + + if (version > 0) --match_data_length; + + if (jbi_current_page < 0) + { + /* this is the first page of the array */ + jbi_current_page = 0; + jbi_in_index = 4; /* skip over length field */ + jbi_out_index = 0; + end_index = (jbi_out_length < JBI_ACA_BUFFER_SIZE) ? + (unsigned int) jbi_out_length : JBI_ACA_BUFFER_SIZE; + } + else + { + /* this is not the first page */ + ++jbi_current_page; + jbi_out_index -= MATCH_DATA_LENGTH; + long_end = jbi_out_length - + ((long) jbi_current_page * (long) MATCH_DATA_LENGTH); + end_index = (long_end < JBI_ACA_BUFFER_SIZE) ? + (unsigned int) long_end : JBI_ACA_BUFFER_SIZE; + + /* copy extra data from end of circular buffer to beginning */ + for (i = 0; i < jbi_out_index; ++i) + { + jbi_aca_out_buffer[i] = jbi_aca_out_buffer[i + MATCH_DATA_LENGTH]; + } + } + + while (jbi_out_index < end_index) + { + /* save state so we can undo the last packet when we reach the end */ + tmp_in_index = jbi_in_index; + tmp_out_index = jbi_out_index; + tmp_bits_avail = jbi_bits_avail; + + /* A 0 bit indicates literal data. */ + if (jbi_read_packed(1) == 0) + { + for (i = 0; i < DATA_BLOB_LENGTH; ++i) + { + if (jbi_out_index < end_index) + { + if (version == 0) + { + prev[i] = jbi_aca_out_buffer[jbi_out_index] & 0xff; + } + jbi_aca_out_buffer[jbi_out_index++] = + (unsigned char) jbi_read_packed(CHAR_BITS); + } + } + } + else + { + /* A 1 bit indicates offset/length to follow. */ + offset = jbi_read_packed(jbi_bits_required( + (jbi_current_page > 0) ? match_data_length : + (jbi_out_index > match_data_length ? match_data_length : + jbi_out_index))); + length = jbi_read_packed(CHAR_BITS); + + if ((version == 0) && (offset == match_data_length + 3)) + { + jbi_aca_out_buffer[jbi_out_index++] = (unsigned char) prev[0]; + jbi_aca_out_buffer[jbi_out_index++] = (unsigned char) prev[1]; + jbi_aca_out_buffer[jbi_out_index++] = (unsigned char) prev[2]; + length -= 3; + } + + for (i = 0; i < length; ++i) + { + if (jbi_out_index < end_index) + { + if (offset > jbi_out_index) + { + j = jbi_out_index + MATCH_DATA_LENGTH - offset; + } + else j = jbi_out_index - offset; + jbi_aca_out_buffer[jbi_out_index] = jbi_aca_out_buffer[j]; + ++jbi_out_index; + } + } + + if (version == 0) + { + prev[0] = jbi_aca_out_buffer[jbi_out_index - 3] & 0xff; + prev[1] = jbi_aca_out_buffer[jbi_out_index - 2] & 0xff; + prev[2] = jbi_aca_out_buffer[jbi_out_index - 1] & 0xff; + } + } + } + + /* restore the state before the previous packet */ + jbi_in_index = tmp_in_index; + jbi_out_index = tmp_out_index; + jbi_bits_avail = tmp_bits_avail; +} + +/****************************************************************************/ +/* */ + +void jbi_uncompress_page +( + int variable_id, + int page, + int version +) + +/* */ +/* Description: Uncompress requested page of variable data. Stores */ +/* uncompressed data in jbi_aca_out_buffer[]. */ +/* */ +/* Returns: TRUE if successful, otherwise FALSE if: */ +/* 1) variable is not a compressed array */ +/* 2) compressed data is illegal or corrupted */ +/* 3) requested page is beyond the end of the array */ +/* 4) internal error in the code */ +/* */ +/****************************************************************************/ +{ + unsigned long symbol_table; + unsigned long data_section; + unsigned long offset; + unsigned long value; + int delta = version * 2; + + if (variable_id != jbi_current_variable_id) + { + /* initialize to uncompress the desired variable */ + symbol_table = GET_DWORD(16 + (version * 8)); + data_section = GET_DWORD(20 + (version * 8)); + offset = symbol_table + ((11 + delta) * variable_id); + value = GET_DWORD(offset + 3 + delta); + jbi_current_variable_id = variable_id; + jbi_current_page = -1; + jbi_bits_avail = CHAR_BITS; + jbi_in_length = GET_DWORD(offset + 7 + delta); + jbi_out_length = + (((unsigned long) GET_BYTE(data_section + value)) | + (((unsigned long) GET_BYTE(data_section + value + 1)) << 8) | + (((unsigned long) GET_BYTE(data_section + value + 2)) << 16) | + (((unsigned long) GET_BYTE(data_section + value + 3)) << 24)); + jbi_in_index = 4; /* skip over length field */ + jbi_out_index = 0; + jbi_aca_in_offset = data_section + value; + } + + /* to look back at an earlier page, start over at the beginning */ + if (page < jbi_current_page) + { + jbi_current_page = -1; + jbi_in_index = 4; /* skip over length field */ + jbi_bits_avail = CHAR_BITS; + } + + /* uncompress sequentially up to the desired page */ + while (page > jbi_current_page) + { + jbi_uncompress_next_page(version); + } +} + +#else + +/****************************************************************************/ +/* */ + +unsigned long jbi_uncompress +( + unsigned char *in, + unsigned long in_length, + unsigned char *out, + unsigned long out_length, + int version +) + +/* */ +/* Description: Uncompress data in "in" and write result to "out". */ +/* */ +/* Returns: Length of uncompressed data. -1 if: */ +/* 1) out_length is too small */ +/* 2) Internal error in the code */ +/* 3) in doesn't contain ACA compressed data. */ +/* */ +/****************************************************************************/ +{ + unsigned long i, j, data_length = 0L; + unsigned int offset, length; + unsigned int match_data_length = MATCH_DATA_LENGTH; + + if (version > 0) --match_data_length; + + jbi_in_length = in_length; + jbi_bits_avail = CHAR_BITS; + jbi_in_index = 0L; + for (i = 0; i < out_length; ++i) out[i] = 0; + + /* Read number of bytes in data. */ + for (i = 0; i < sizeof (in_length); ++i) + { + data_length = data_length | ((unsigned long) + jbi_read_packed(in, CHAR_BITS) << (i * CHAR_BITS)); + } + + if (data_length > out_length) + { + data_length = 0L; + } + else + { + i = 0; + while (i < data_length) + { + /* A 0 bit indicates literal data. */ + if (jbi_read_packed(in, 1) == 0) + { + for (j = 0; j < DATA_BLOB_LENGTH; ++j) + { + if (i < data_length) + { + out[i] = (unsigned char) jbi_read_packed(in, CHAR_BITS); + i++; + } + } + } + else + { + /* A 1 bit indicates offset/length to follow. */ + offset = jbi_read_packed(in, jbi_bits_required((short) (i > match_data_length ? match_data_length : i))); + length = jbi_read_packed(in, CHAR_BITS); + + for (j = 0; j < length; ++j) + { + if (i < data_length) + { + out[i] = out[i - offset]; + i++; + } + } + } + } + } + + return (data_length); +} + +#endif diff --git a/common/recipes-utils/jbi/files/code/jbicomp.h b/common/recipes-utils/jbi/files/code/jbicomp.h new file mode 100644 index 0000000..382995d --- /dev/null +++ b/common/recipes-utils/jbi/files/code/jbicomp.h @@ -0,0 +1,37 @@ +/****************************************************************************/ +/* */ +/* Module: jbicomp.h */ +/* */ +/* Copyright (C) Altera Corporation 1997-2001 */ +/* */ +/* Description: Contains the function prototypes for compressing */ +/* and uncompressing Boolean array data. */ +/* */ +/****************************************************************************/ + +#ifndef INC_JBICOMP_H +#define INC_JBICOMP_H + +#if PORT==DOS + +void jbi_uncompress_page +( + int variable_id, + int page, + int version +); + +#else + +unsigned long jbi_uncompress +( + unsigned char *in, + unsigned long in_length, + unsigned char *out, + unsigned long out_length, + int version +); + +#endif /* PORT==DOS */ + +#endif /* INC_JBICOMP_H */ diff --git a/common/recipes-utils/jbi/files/code/jbiexprt.h b/common/recipes-utils/jbi/files/code/jbiexprt.h new file mode 100644 index 0000000..6d6a401 --- /dev/null +++ b/common/recipes-utils/jbi/files/code/jbiexprt.h @@ -0,0 +1,224 @@ +/****************************************************************************/ +/* */ +/* Module: jbiexprt.h */ +/* */ +/* Copyright (C) Altera Corporation 1998-2001 */ +/* */ +/* Description: Jam STAPL ByteCode Player Export Header File */ +/* */ +/* Revisions: */ +/* */ +/****************************************************************************/ + +#ifndef INC_JBIEXPRT_H +#define INC_JBIEXPRT_H + +/****************************************************************************/ +/* */ +/* Return codes from most JBI functions */ +/* */ +/****************************************************************************/ + +#define JBI_RETURN_TYPE int + +#define JBIC_SUCCESS 0 +#define JBIC_OUT_OF_MEMORY 1 +#define JBIC_IO_ERROR 2 +/* #define JAMC_SYNTAX_ERROR 3 */ +#define JBIC_UNEXPECTED_END 4 +#define JBIC_UNDEFINED_SYMBOL 5 +/* #define JAMC_REDEFINED_SYMBOL 6 */ +#define JBIC_INTEGER_OVERFLOW 7 +#define JBIC_DIVIDE_BY_ZERO 8 +#define JBIC_CRC_ERROR 9 +#define JBIC_INTERNAL_ERROR 10 +#define JBIC_BOUNDS_ERROR 11 +/* #define JAMC_TYPE_MISMATCH 12 */ +/* #define JAMC_ASSIGN_TO_CONST 13 */ +/* #define JAMC_NEXT_UNEXPECTED 14 */ +/* #define JAMC_POP_UNEXPECTED 15 */ +/* #define JAMC_RETURN_UNEXPECTED 16 */ +/* #define JAMC_ILLEGAL_SYMBOL 17 */ +#define JBIC_VECTOR_MAP_FAILED 18 +#define JBIC_USER_ABORT 19 +#define JBIC_STACK_OVERFLOW 20 +#define JBIC_ILLEGAL_OPCODE 21 +/* #define JAMC_PHASE_ERROR 22 */ +/* #define JAMC_SCOPE_ERROR 23 */ +#define JBIC_ACTION_NOT_FOUND 24 + +/****************************************************************************/ +/* */ +/* Macro Definitions */ +/* */ +/****************************************************************************/ + +/* +* For DOS port, program data is stored in a set of 16K pages, accessed +* through a pointer table. For 32-bit version, the buffer is continuous. +* The macro GET_BYTE gets a single byte for either case. +*/ +#if PORT==DOS +#define PROGRAM_PTR unsigned char ** +#else +#define PROGRAM_PTR unsigned char * +#endif + +#if PORT==DOS +#define GET_BYTE(x) (jbi_program[(x) >> 14L][(x) & 0x3fffL]) +#else +#define GET_BYTE(x) (program[x]) +#endif + +#define GET_WORD(x) \ + (((((unsigned short) GET_BYTE(x)) << 8) & 0xFF00) | \ + (((unsigned short) GET_BYTE((x)+1)) & 0x00FF)) + +#define GET_DWORD(x) \ + (((((unsigned long) GET_BYTE(x)) << 24L) & 0xFF000000L) | \ + ((((unsigned long) GET_BYTE((x)+1)) << 16L) & 0x00FF0000L) | \ + ((((unsigned long) GET_BYTE((x)+2)) << 8L) & 0x0000FF00L) | \ + (((unsigned long) GET_BYTE((x)+3)) & 0x000000FFL)) + +/****************************************************************************/ +/* */ +/* Structured Types */ +/* */ +/****************************************************************************/ + +typedef struct JBI_PROCINFO_STRUCT +{ + char *name; + unsigned char attributes; + struct JBI_PROCINFO_STRUCT *next; +} +JBI_PROCINFO; + +/****************************************************************************/ +/* */ +/* Global Data Prototypes */ +/* */ +/****************************************************************************/ + +#if PORT==DOS +extern unsigned char jbi_aca_out_buffer[8192 + 1024]; +#endif + +extern PROGRAM_PTR jbi_program; + +extern char *jbi_workspace; + +extern long jbi_workspace_size; + +/****************************************************************************/ +/* */ +/* Function Prototypes */ +/* */ +/****************************************************************************/ + +JBI_RETURN_TYPE jbi_execute +( + PROGRAM_PTR program, + long program_size, + char *workspace, + long workspace_size, + char *action, + char **init_list, + int reset_jtag, + long *error_address, + int *exit_code, + int *format_version +); + +JBI_RETURN_TYPE jbi_get_note +( + PROGRAM_PTR program, + long program_size, + long *offset, + char *key, + char *value, + int length +); + +JBI_RETURN_TYPE jbi_check_crc +( + PROGRAM_PTR program, + long program_size, + unsigned short *expected_crc, + unsigned short *actual_crc +); + +JBI_RETURN_TYPE jbi_get_file_info +( + PROGRAM_PTR program, + long program_size, + int *format_version, + int *action_count, + int *procedure_count +); + +JBI_RETURN_TYPE jbi_get_action_info +( + PROGRAM_PTR program, + long program_size, + int index, + char **name, + char **description, + JBI_PROCINFO **procedure_list +); + +int jbi_jtag_io +( + int tms, + int tdi, + int read_tdo +); + +void jbi_message +( + char *message_text +); + +void jbi_export_integer +( + char *key, + long value +); + +void jbi_export_boolean_array +( + char *key, + unsigned char *data, + long count +); + +void jbi_delay +( + long microseconds +); + +int jbi_vector_map +( + int signal_count, + char **signals +); + +int jbi_vector_io +( + int signal_count, + long *dir_vect, + long *data_vect, + long *capture_vect +); + +void *jbi_malloc +( + unsigned int size +); + +void jbi_free +( + void *ptr +); + +#endif /* INC_JBIEXPRT_H */ diff --git a/common/recipes-utils/jbi/files/code/jbijtag.c b/common/recipes-utils/jbi/files/code/jbijtag.c new file mode 100644 index 0000000..728ab6a --- /dev/null +++ b/common/recipes-utils/jbi/files/code/jbijtag.c @@ -0,0 +1,1675 @@ +/****************************************************************************/ +/* */ +/* Module: jbijtag.c */ +/* */ +/* Copyright (C) Altera Corporation 1998-2001 */ +/* */ +/* Description: Contains JTAG interface functions */ +/* */ +/* Revisions: 2.2 updated state transition paths */ +/* 2.0 added multi-page scan code for 16-bit PORT */ +/* */ +/****************************************************************************/ + +#include "jbiport.h" +#include "jbiexprt.h" +#include "jbicomp.h" +#include "jbijtag.h" + +#define NULL 0 + +char *jbi_workspace = NULL; +long jbi_workspace_size = 0L; + +/****************************************************************************/ +/* */ +/* Enumerated Types */ +/* */ +/****************************************************************************/ + +/* maximum JTAG IR and DR lengths (in bits) */ +#define JBIC_MAX_JTAG_IR_PREAMBLE 256 +#define JBIC_MAX_JTAG_IR_POSTAMBLE 256 +#define JBIC_MAX_JTAG_IR_LENGTH 512 +#define JBIC_MAX_JTAG_DR_PREAMBLE 1024 +#define JBIC_MAX_JTAG_DR_POSTAMBLE 1024 +#define JBIC_MAX_JTAG_DR_LENGTH 2048 + +/* +* Global variable to store the current JTAG state +*/ +JBIE_JTAG_STATE jbi_jtag_state = JBI_ILLEGAL_JTAG_STATE; + +/* +* Store current stop-state for DR and IR scan commands +*/ +JBIE_JTAG_STATE jbi_drstop_state = IDLE; +JBIE_JTAG_STATE jbi_irstop_state = IDLE; + +/* +* Store current padding values +*/ +unsigned int jbi_dr_preamble = 0; +unsigned int jbi_dr_postamble = 0; +unsigned int jbi_ir_preamble = 0; +unsigned int jbi_ir_postamble = 0; +unsigned int jbi_dr_length = 0; +unsigned int jbi_ir_length = 0; +unsigned char *jbi_dr_preamble_data = NULL; +unsigned char *jbi_dr_postamble_data = NULL; +unsigned char *jbi_ir_preamble_data = NULL; +unsigned char *jbi_ir_postamble_data = NULL; +unsigned char *jbi_dr_buffer = NULL; +unsigned char *jbi_ir_buffer = NULL; + +/* +* This structure shows, for each JTAG state, which state is reached after +* a single TCK clock cycle with TMS high or TMS low, respectively. This +* describes all possible state transitions in the JTAG state machine. +*/ +struct JBIS_JTAG_MACHINE +{ + JBIE_JTAG_STATE tms_high; + JBIE_JTAG_STATE tms_low; +} jbi_jtag_state_transitions[] = +{ +/* RESET */ { RESET, IDLE }, +/* IDLE */ { DRSELECT, IDLE }, +/* DRSELECT */ { IRSELECT, DRCAPTURE }, +/* DRCAPTURE */ { DREXIT1, DRSHIFT }, +/* DRSHIFT */ { DREXIT1, DRSHIFT }, +/* DREXIT1 */ { DRUPDATE, DRPAUSE }, +/* DRPAUSE */ { DREXIT2, DRPAUSE }, +/* DREXIT2 */ { DRUPDATE, DRSHIFT }, +/* DRUPDATE */ { DRSELECT, IDLE }, +/* IRSELECT */ { RESET, IRCAPTURE }, +/* IRCAPTURE */ { IREXIT1, IRSHIFT }, +/* IRSHIFT */ { IREXIT1, IRSHIFT }, +/* IREXIT1 */ { IRUPDATE, IRPAUSE }, +/* IRPAUSE */ { IREXIT2, IRPAUSE }, +/* IREXIT2 */ { IRUPDATE, IRSHIFT }, +/* IRUPDATE */ { DRSELECT, IDLE } +}; + +/* +* This table contains the TMS value to be used to take the NEXT STEP on +* the path to the desired state. The array index is the current state, +* and the bit position is the desired endstate. To find out which state +* is used as the intermediate state, look up the TMS value in the +* jbi_jtag_state_transitions[] table. +*/ +unsigned short jbi_jtag_path_map[16] = +{ +/* RST RTI SDRS CDR SDR E1DR PDR E2DR */ + 0x0001, 0xFFFD, 0xFE01, 0xFFE7, 0xFFEF, 0xFF0F, 0xFFBF, 0xFFFF, +/* UDR SIRS CIR SIR E1IR PIR E2IR UIR */ + 0xFEFD, 0x0001, 0xF3FF, 0xF7FF, 0x87FF, 0xDFFF, 0xFFFF, 0x7FFD +}; + +/* +* Flag bits for jbi_jtag_io() function +*/ +#define TMS_HIGH 1 +#define TMS_LOW 0 +#define TDI_HIGH 1 +#define TDI_LOW 0 +#define READ_TDO 1 +#define IGNORE_TDO 0 + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_init_jtag() + +/* */ +/****************************************************************************/ +{ + /* initial JTAG state is unknown */ + jbi_jtag_state = JBI_ILLEGAL_JTAG_STATE; + + /* initialize global variables to default state */ + jbi_drstop_state = IDLE; + jbi_irstop_state = IDLE; + jbi_dr_preamble = 0; + jbi_dr_postamble = 0; + jbi_ir_preamble = 0; + jbi_ir_postamble = 0; + jbi_dr_length = 0; + jbi_ir_length = 0; + + if (jbi_workspace != NULL) + { + jbi_dr_preamble_data = (unsigned char *) jbi_workspace; + jbi_dr_postamble_data = &jbi_dr_preamble_data[JBIC_MAX_JTAG_DR_PREAMBLE / 8]; + jbi_ir_preamble_data = &jbi_dr_postamble_data[JBIC_MAX_JTAG_DR_POSTAMBLE / 8]; + jbi_ir_postamble_data = &jbi_ir_preamble_data[JBIC_MAX_JTAG_IR_PREAMBLE / 8]; + jbi_dr_buffer = &jbi_ir_postamble_data[JBIC_MAX_JTAG_IR_POSTAMBLE / 8]; + jbi_ir_buffer = &jbi_dr_buffer[JBIC_MAX_JTAG_DR_LENGTH / 8]; + } + else + { + jbi_dr_preamble_data = NULL; + jbi_dr_postamble_data = NULL; + jbi_ir_preamble_data = NULL; + jbi_ir_postamble_data = NULL; + jbi_dr_buffer = NULL; + jbi_ir_buffer = NULL; + } + + return (JBIC_SUCCESS); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_set_drstop_state +( + JBIE_JTAG_STATE state +) + +/* */ +/****************************************************************************/ +{ + jbi_drstop_state = state; + + return (JBIC_SUCCESS); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_set_irstop_state +( + JBIE_JTAG_STATE state +) + +/* */ +/****************************************************************************/ +{ + jbi_irstop_state = state; + + return (JBIC_SUCCESS); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_set_dr_preamble +( + unsigned int count, + unsigned int start_index, + unsigned char *preamble_data +) + +/* */ +/****************************************************************************/ +{ + JBI_RETURN_TYPE status = JBIC_SUCCESS; + unsigned int i; + unsigned int j; + + if (jbi_workspace != NULL) + { + if (count > JBIC_MAX_JTAG_DR_PREAMBLE) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_dr_preamble = count; + } + } + else + { + if (count > jbi_dr_preamble) + { + jbi_free(jbi_dr_preamble_data); + jbi_dr_preamble_data = (unsigned char *) jbi_malloc((count + 7) >> 3); + + if (jbi_dr_preamble_data == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_dr_preamble = count; + } + } + else + { + jbi_dr_preamble = count; + } + } + + if (status == JBIC_SUCCESS) + { + for (i = 0; i < count; ++i) + { + j = i + start_index; + + if (preamble_data == NULL) + { + jbi_dr_preamble_data[i >> 3] |= (1 << (i & 7)); + } + else + { + if (preamble_data[j >> 3] & (1 << (j & 7))) + { + jbi_dr_preamble_data[i >> 3] |= (1 << (i & 7)); + } + else + { + jbi_dr_preamble_data[i >> 3] &= + ~(unsigned int) (1 << (i & 7)); + } + } + } + } + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_set_ir_preamble +( + unsigned int count, + unsigned int start_index, + unsigned char *preamble_data +) + +/* */ +/****************************************************************************/ +{ + JBI_RETURN_TYPE status = JBIC_SUCCESS; + unsigned int i; + unsigned int j; + + if (jbi_workspace != NULL) + { + if (count > JBIC_MAX_JTAG_IR_PREAMBLE) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_ir_preamble = count; + } + } + else + { + if (count > jbi_ir_preamble) + { + jbi_free(jbi_ir_preamble_data); + jbi_ir_preamble_data = (unsigned char *) jbi_malloc((count + 7) >> 3); + + if (jbi_ir_preamble_data == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_ir_preamble = count; + } + } + else + { + jbi_ir_preamble = count; + } + } + + if (status == JBIC_SUCCESS) + { + for (i = 0; i < count; ++i) + { + j = i + start_index; + + if (preamble_data == NULL) + { + jbi_ir_preamble_data[i >> 3] |= (1 << (i & 7)); + } + else + { + if (preamble_data[j >> 3] & (1 << (j & 7))) + { + jbi_ir_preamble_data[i >> 3] |= (1 << (i & 7)); + } + else + { + jbi_ir_preamble_data[i >> 3] &= + ~(unsigned int) (1 << (i & 7)); + } + } + } + } + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_set_dr_postamble +( + unsigned int count, + unsigned int start_index, + unsigned char *postamble_data +) + +/* */ +/****************************************************************************/ +{ + JBI_RETURN_TYPE status = JBIC_SUCCESS; + unsigned int i; + unsigned int j; + + if (jbi_workspace != NULL) + { + if (count > JBIC_MAX_JTAG_DR_POSTAMBLE) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_dr_postamble = count; + } + } + else + { + if (count > jbi_dr_postamble) + { + jbi_free(jbi_dr_postamble_data); + jbi_dr_postamble_data = (unsigned char *) jbi_malloc((count + 7) >> 3); + + if (jbi_dr_postamble_data == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_dr_postamble = count; + } + } + else + { + jbi_dr_postamble = count; + } + } + + if (status == JBIC_SUCCESS) + { + for (i = 0; i < count; ++i) + { + j = i + start_index; + + if (postamble_data == NULL) + { + jbi_dr_postamble_data[i >> 3] |= (1 << (i & 7)); + } + else + { + if (postamble_data[j >> 3] & (1 << (j & 7))) + { + jbi_dr_postamble_data[i >> 3] |= (1 << (i & 7)); + } + else + { + jbi_dr_postamble_data[i >> 3] &= + ~(unsigned int) (1 << (i & 7)); + } + } + } + } + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_set_ir_postamble +( + unsigned int count, + unsigned int start_index, + unsigned char *postamble_data +) + +/* */ +/****************************************************************************/ +{ + JBI_RETURN_TYPE status = JBIC_SUCCESS; + unsigned int i; + unsigned int j; + + if (jbi_workspace != NULL) + { + if (count > JBIC_MAX_JTAG_IR_POSTAMBLE) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_ir_postamble = count; + } + } + else + { + if (count > jbi_ir_postamble) + { + jbi_free(jbi_ir_postamble_data); + jbi_ir_postamble_data = (unsigned char *) jbi_malloc((count + 7) >> 3); + + if (jbi_ir_postamble_data == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_ir_postamble = count; + } + } + else + { + jbi_ir_postamble = count; + } + } + + if (status == JBIC_SUCCESS) + { + for (i = 0; i < count; ++i) + { + j = i + start_index; + + if (postamble_data == NULL) + { + jbi_ir_postamble_data[i >> 3] |= (1 << (i & 7)); + } + else + { + if (postamble_data[j >> 3] & (1 << (j & 7))) + { + jbi_ir_postamble_data[i >> 3] |= (1 << (i & 7)); + } + else + { + jbi_ir_postamble_data[i >> 3] &= + ~(unsigned int) (1 << (i & 7)); + } + } + } + } + + return (status); +} + +/****************************************************************************/ +/* */ + +void jbi_jtag_reset_idle(void) + +/* */ +/****************************************************************************/ +{ + int i; + + /* + * Go to Test Logic Reset (no matter what the starting state may be) + */ + for (i = 0; i < 5; ++i) + { + jbi_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO); + } + + /* + * Now step to Run Test / Idle + */ + jbi_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO); + + jbi_jtag_state = IDLE; +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_goto_jtag_state +( + JBIE_JTAG_STATE state +) + +/* */ +/****************************************************************************/ +{ + int tms; + int count = 0; + JBI_RETURN_TYPE status = JBIC_SUCCESS; + + if (jbi_jtag_state == JBI_ILLEGAL_JTAG_STATE) + { + /* initialize JTAG chain to known state */ + jbi_jtag_reset_idle(); + } + + if (jbi_jtag_state == state) + { + /* + * We are already in the desired state. If it is a stable state, + * loop here. Otherwise do nothing (no clock cycles). + */ + if ((state == IDLE) || + (state == DRSHIFT) || + (state == DRPAUSE) || + (state == IRSHIFT) || + (state == IRPAUSE)) + { + jbi_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO); + } + else if (state == RESET) + { + jbi_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO); + } + } + else + { + while ((jbi_jtag_state != state) && (count < 9)) + { + /* + * Get TMS value to take a step toward desired state + */ + tms = (jbi_jtag_path_map[jbi_jtag_state] & (1 << state)) ? + TMS_HIGH : TMS_LOW; + + /* + * Take a step + */ + jbi_jtag_io(tms, TDI_LOW, IGNORE_TDO); + + if (tms) + { + jbi_jtag_state = + jbi_jtag_state_transitions[jbi_jtag_state].tms_high; + } + else + { + jbi_jtag_state = + jbi_jtag_state_transitions[jbi_jtag_state].tms_low; + } + + ++count; + } + } + + if (jbi_jtag_state != state) + { + status = JBIC_INTERNAL_ERROR; + } + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_do_wait_cycles +( + long cycles, + JBIE_JTAG_STATE wait_state +) + +/* */ +/* Description: Causes JTAG hardware to loop in the specified stable */ +/* state for the specified number of TCK clock cycles. */ +/* */ +/* Returns: JBIC_SUCCESS for success, else appropriate error code */ +/* */ +/****************************************************************************/ +{ + int tms; + long count; + JBI_RETURN_TYPE status = JBIC_SUCCESS; + + if (jbi_jtag_state != wait_state) + { + status = jbi_goto_jtag_state(wait_state); + } + + if (status == JBIC_SUCCESS) + { + /* + * Set TMS high to loop in RESET state + * Set TMS low to loop in any other stable state + */ + tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW; + + for (count = 0L; count < cycles; count++) + { + jbi_jtag_io(tms, TDI_LOW, IGNORE_TDO); + } + } + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_do_wait_microseconds +( + long microseconds, + JBIE_JTAG_STATE wait_state +) + +/* */ +/* Description: Causes JTAG hardware to sit in the specified stable */ +/* state for the specified duration of real time. If */ +/* no JTAG operations have been performed yet, then only */ +/* a delay is performed. This permits the WAIT USECS */ +/* statement to be used in VECTOR programs without causing */ +/* any JTAG operations. */ +/* */ +/* Returns: JBIC_SUCCESS for success, else appropriate error code */ +/* */ +/****************************************************************************/ +{ + JBI_RETURN_TYPE status = JBIC_SUCCESS; + + if ((jbi_jtag_state != JBI_ILLEGAL_JTAG_STATE) && + (jbi_jtag_state != wait_state)) + { + status = jbi_goto_jtag_state(wait_state); + } + + if (status == JBIC_SUCCESS) + { + /* + * Wait for specified time interval + */ + jbi_delay(microseconds); + } + + return (status); +} + +/****************************************************************************/ +/* */ + +void jbi_jtag_concatenate_data +( + unsigned char *buffer, + unsigned char *preamble_data, + unsigned int preamble_count, + unsigned char *target_data, + unsigned long start_index, + unsigned int target_count, + unsigned char *postamble_data, + unsigned int postamble_count +) + +/* */ +/* Description: Copies preamble data, target data, and postamble data */ +/* into one buffer for IR or DR scans. */ +/* */ +/* Returns: nothing */ +/* */ +/****************************************************************************/ +{ + unsigned long i; + unsigned long j; + unsigned long k; + + for (i = 0L; i < preamble_count; ++i) + { + if (preamble_data[i >> 3L] & (1L << (i & 7L))) + { + buffer[i >> 3L] |= (1L << (i & 7L)); + } + else + { + buffer[i >> 3L] &= ~(unsigned int) (1L << (i & 7L)); + } + } + + j = start_index; + k = preamble_count + target_count; + for (; i < k; ++i, ++j) + { + if (target_data[j >> 3L] & (1L << (j & 7L))) + { + buffer[i >> 3L] |= (1L << (i & 7L)); + } + else + { + buffer[i >> 3L] &= ~(unsigned int) (1L << (i & 7L)); + } + } + + j = 0L; + k = preamble_count + target_count + postamble_count; + for (; i < k; ++i, ++j) + { + if (postamble_data[j >> 3L] & (1L << (j & 7L))) + { + buffer[i >> 3L] |= (1L << (i & 7L)); + } + else + { + buffer[i >> 3L] &= ~(unsigned int) (1L << (i & 7L)); + } + } +} + +int jbi_jtag_drscan +( + int start_state, + int count, + unsigned char *tdi, + unsigned char *tdo +) +{ + int i = 0; + int tdo_bit = 0; + int status = 1; + + /* + * First go to DRSHIFT state + */ + switch (start_state) + { + case 0: /* IDLE */ + jbi_jtag_io(1, 0, 0); /* DRSELECT */ + jbi_jtag_io(0, 0, 0); /* DRCAPTURE */ + jbi_jtag_io(0, 0, 0); /* DRSHIFT */ + break; + + case 1: /* DRPAUSE */ + jbi_jtag_io(1, 0, 0); /* DREXIT2 */ + jbi_jtag_io(1, 0, 0); /* DRUPDATE */ + jbi_jtag_io(1, 0, 0); /* DRSELECT */ + jbi_jtag_io(0, 0, 0); /* DRCAPTURE */ + jbi_jtag_io(0, 0, 0); /* DRSHIFT */ + break; + + case 2: /* IRPAUSE */ + jbi_jtag_io(1, 0, 0); /* IREXIT2 */ + jbi_jtag_io(1, 0, 0); /* IRUPDATE */ + jbi_jtag_io(1, 0, 0); /* DRSELECT */ + jbi_jtag_io(0, 0, 0); /* DRCAPTURE */ + jbi_jtag_io(0, 0, 0); /* DRSHIFT */ + break; + + default: + status = 0; + } + + if (status) + { + /* loop in the SHIFT-DR state */ + for (i = 0; i < count; i++) + { + tdo_bit = jbi_jtag_io( + (i == count - 1), + tdi[i >> 3] & (1 << (i & 7)), + (tdo != NULL)); + + if (tdo != NULL) + { + if (tdo_bit) + { + tdo[i >> 3] |= (1 << (i & 7)); + } + else + { + tdo[i >> 3] &= ~(unsigned int) (1 << (i & 7)); + } + } + } + + jbi_jtag_io(0, 0, 0); /* DRPAUSE */ + } + + return (status); +} + +int jbi_jtag_irscan +( + int start_state, + int count, + unsigned char *tdi, + unsigned char *tdo +) +{ + int i = 0; + int tdo_bit = 0; + int status = 1; + + /* + * First go to IRSHIFT state + */ + switch (start_state) + { + case 0: /* IDLE */ + jbi_jtag_io(1, 0, 0); /* DRSELECT */ + jbi_jtag_io(1, 0, 0); /* IRSELECT */ + jbi_jtag_io(0, 0, 0); /* IRCAPTURE */ + jbi_jtag_io(0, 0, 0); /* IRSHIFT */ + break; + + case 1: /* DRPAUSE */ + jbi_jtag_io(1, 0, 0); /* DREXIT2 */ + jbi_jtag_io(1, 0, 0); /* DRUPDATE */ + jbi_jtag_io(1, 0, 0); /* DRSELECT */ + jbi_jtag_io(1, 0, 0); /* IRSELECT */ + jbi_jtag_io(0, 0, 0); /* IRCAPTURE */ + jbi_jtag_io(0, 0, 0); /* IRSHIFT */ + break; + + case 2: /* IRPAUSE */ + jbi_jtag_io(1, 0, 0); /* IREXIT2 */ + jbi_jtag_io(1, 0, 0); /* IRUPDATE */ + jbi_jtag_io(1, 0, 0); /* DRSELECT */ + jbi_jtag_io(1, 0, 0); /* IRSELECT */ + jbi_jtag_io(0, 0, 0); /* IRCAPTURE */ + jbi_jtag_io(0, 0, 0); /* IRSHIFT */ + break; + + default: + status = 0; + } + + if (status) + { + /* loop in the SHIFT-IR state */ + for (i = 0; i < count; i++) + { + tdo_bit = jbi_jtag_io( + (i == count - 1), + tdi[i >> 3] & (1 << (i & 7)), + (tdo != NULL)); + + if (tdo != NULL) + { + if (tdo_bit) + { + tdo[i >> 3] |= (1 << (i & 7)); + } + else + { + tdo[i >> 3] &= ~(unsigned int) (1 << (i & 7)); + } + } + } + + jbi_jtag_io(0, 0, 0); /* IRPAUSE */ + } + + return (status); +} + +/****************************************************************************/ +/* */ + +void jbi_jtag_extract_target_data +( + unsigned char *buffer, + unsigned char *target_data, + unsigned int start_index, + unsigned int preamble_count, + unsigned int target_count +) + +/* */ +/* Description: Copies target data from scan buffer, filtering out */ +/* preamble and postamble data. */ +/* */ +/* Returns: nothing */ +/* */ +/****************************************************************************/ +{ + unsigned int i; + unsigned int j; + unsigned int k; + + j = preamble_count; + k = start_index + target_count; + for (i = start_index; i < k; ++i, ++j) + { + if (buffer[j >> 3] & (1 << (j & 7))) + { + target_data[i >> 3] |= (1 << (i & 7)); + } + else + { + target_data[i >> 3] &= ~(unsigned int) (1 << (i & 7)); + } + } +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_do_irscan +( + unsigned int count, + unsigned char *tdi_data, + unsigned int start_index +) + +/* */ +/* Description: Shifts data into instruction register */ +/* */ +/* Returns: JBIC_SUCCESS for success, else appropriate error code */ +/* */ +/****************************************************************************/ +{ + int start_code = 0; + unsigned int alloc_chars = 0; + unsigned int shift_count = jbi_ir_preamble + count + jbi_ir_postamble; + JBI_RETURN_TYPE status = JBIC_SUCCESS; + JBIE_JTAG_STATE start_state = JBI_ILLEGAL_JTAG_STATE; + + switch (jbi_jtag_state) + { + case JBI_ILLEGAL_JTAG_STATE: + case RESET: + case IDLE: + start_code = 0; + start_state = IDLE; + break; + + case DRSELECT: + case DRCAPTURE: + case DRSHIFT: + case DREXIT1: + case DRPAUSE: + case DREXIT2: + case DRUPDATE: + start_code = 1; + start_state = DRPAUSE; + break; + + case IRSELECT: + case IRCAPTURE: + case IRSHIFT: + case IREXIT1: + case IRPAUSE: + case IREXIT2: + case IRUPDATE: + start_code = 2; + start_state = IRPAUSE; + break; + + default: + status = JBIC_INTERNAL_ERROR; + break; + } + + if (status == JBIC_SUCCESS) + { + if (jbi_jtag_state != start_state) + { + status = jbi_goto_jtag_state(start_state); + } + } + + if (status == JBIC_SUCCESS) + { + if (jbi_workspace != NULL) + { + if (shift_count > JBIC_MAX_JTAG_IR_LENGTH) + { + status = JBIC_OUT_OF_MEMORY; + } + } + else if (shift_count > jbi_ir_length) + { + alloc_chars = (shift_count + 7) >> 3; + jbi_free(jbi_ir_buffer); + jbi_ir_buffer = (unsigned char *) jbi_malloc(alloc_chars); + + if (jbi_ir_buffer == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_ir_length = alloc_chars * 8; + } + } + } + + if (status == JBIC_SUCCESS) + { + /* + * Copy preamble data, IR data, and postamble data into a buffer + */ + jbi_jtag_concatenate_data + ( + jbi_ir_buffer, + jbi_ir_preamble_data, + jbi_ir_preamble, + tdi_data, + start_index, + count, + jbi_ir_postamble_data, + jbi_ir_postamble + ); + + /* + * Do the IRSCAN + */ + jbi_jtag_irscan + ( + start_code, + shift_count, + jbi_ir_buffer, + NULL + ); + + /* jbi_jtag_irscan() always ends in IRPAUSE state */ + jbi_jtag_state = IRPAUSE; + } + + if (status == JBIC_SUCCESS) + { + if (jbi_irstop_state != IRPAUSE) + { + status = jbi_goto_jtag_state(jbi_irstop_state); + } + } + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_swap_ir +( + unsigned int count, + unsigned char *in_data, + unsigned int in_index, + unsigned char *out_data, + unsigned int out_index +) + +/* */ +/* Description: Shifts data into instruction register, capturing output */ +/* data */ +/* */ +/* Returns: JBIC_SUCCESS for success, else appropriate error code */ +/* */ +/****************************************************************************/ +{ + int start_code = 0; + unsigned int alloc_chars = 0; + unsigned int shift_count = jbi_ir_preamble + count + jbi_ir_postamble; + JBI_RETURN_TYPE status = JBIC_SUCCESS; + JBIE_JTAG_STATE start_state = JBI_ILLEGAL_JTAG_STATE; + + switch (jbi_jtag_state) + { + case JBI_ILLEGAL_JTAG_STATE: + case RESET: + case IDLE: + start_code = 0; + start_state = IDLE; + break; + + case DRSELECT: + case DRCAPTURE: + case DRSHIFT: + case DREXIT1: + case DRPAUSE: + case DREXIT2: + case DRUPDATE: + start_code = 1; + start_state = DRPAUSE; + break; + + case IRSELECT: + case IRCAPTURE: + case IRSHIFT: + case IREXIT1: + case IRPAUSE: + case IREXIT2: + case IRUPDATE: + start_code = 2; + start_state = IRPAUSE; + break; + + default: + status = JBIC_INTERNAL_ERROR; + break; + } + + if (status == JBIC_SUCCESS) + { + if (jbi_jtag_state != start_state) + { + status = jbi_goto_jtag_state(start_state); + } + } + + if (status == JBIC_SUCCESS) + { + if (jbi_workspace != NULL) + { + if (shift_count > JBIC_MAX_JTAG_IR_LENGTH) + { + status = JBIC_OUT_OF_MEMORY; + } + } + else if (shift_count > jbi_ir_length) + { + alloc_chars = (shift_count + 7) >> 3; + jbi_free(jbi_ir_buffer); + jbi_ir_buffer = (unsigned char *) jbi_malloc(alloc_chars); + + if (jbi_ir_buffer == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_ir_length = alloc_chars * 8; + } + } + } + + if (status == JBIC_SUCCESS) + { + /* + * Copy preamble data, IR data, and postamble data into a buffer + */ + jbi_jtag_concatenate_data + ( + jbi_ir_buffer, + jbi_ir_preamble_data, + jbi_ir_preamble, + in_data, + in_index, + count, + jbi_ir_postamble_data, + jbi_ir_postamble + ); + + /* + * Do the IRSCAN + */ + jbi_jtag_irscan + ( + start_code, + shift_count, + jbi_ir_buffer, + jbi_ir_buffer + ); + + /* jbi_jtag_irscan() always ends in IRPAUSE state */ + jbi_jtag_state = IRPAUSE; + } + + if (status == JBIC_SUCCESS) + { + if (jbi_irstop_state != IRPAUSE) + { + status = jbi_goto_jtag_state(jbi_irstop_state); + } + } + + if (status == JBIC_SUCCESS) + { + /* + * Now extract the returned data from the buffer + */ + jbi_jtag_extract_target_data + ( + jbi_ir_buffer, + out_data, + out_index, + jbi_ir_preamble, + count + ); + } + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_do_drscan +( + unsigned int count, + unsigned char *tdi_data, + unsigned long start_index +) + +/* */ +/* Description: Shifts data into data register (ignoring output data) */ +/* */ +/* Returns: JBIC_SUCCESS for success, else appropriate error code */ +/* */ +/****************************************************************************/ +{ + int start_code = 0; + unsigned int alloc_chars = 0; + unsigned int shift_count = jbi_dr_preamble + count + jbi_dr_postamble; + JBI_RETURN_TYPE status = JBIC_SUCCESS; + JBIE_JTAG_STATE start_state = JBI_ILLEGAL_JTAG_STATE; + + switch (jbi_jtag_state) + { + case JBI_ILLEGAL_JTAG_STATE: + case RESET: + case IDLE: + start_code = 0; + start_state = IDLE; + break; + + case DRSELECT: + case DRCAPTURE: + case DRSHIFT: + case DREXIT1: + case DRPAUSE: + case DREXIT2: + case DRUPDATE: + start_code = 1; + start_state = DRPAUSE; + break; + + case IRSELECT: + case IRCAPTURE: + case IRSHIFT: + case IREXIT1: + case IRPAUSE: + case IREXIT2: + case IRUPDATE: + start_code = 2; + start_state = IRPAUSE; + break; + + default: + status = JBIC_INTERNAL_ERROR; + break; + } + + if (status == JBIC_SUCCESS) + { + if (jbi_jtag_state != start_state) + { + status = jbi_goto_jtag_state(start_state); + } + } + + if (status == JBIC_SUCCESS) + { + if (jbi_workspace != NULL) + { + if (shift_count > JBIC_MAX_JTAG_DR_LENGTH) + { + status = JBIC_OUT_OF_MEMORY; + } + } + else if (shift_count > jbi_dr_length) + { + alloc_chars = (shift_count + 7) >> 3; + jbi_free(jbi_dr_buffer); + jbi_dr_buffer = (unsigned char *) jbi_malloc(alloc_chars); + + if (jbi_dr_buffer == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_dr_length = alloc_chars * 8; + } + } + } + + if (status == JBIC_SUCCESS) + { + /* + * Copy preamble data, DR data, and postamble data into a buffer + */ + jbi_jtag_concatenate_data + ( + jbi_dr_buffer, + jbi_dr_preamble_data, + jbi_dr_preamble, + tdi_data, + start_index, + count, + jbi_dr_postamble_data, + jbi_dr_postamble + ); + + /* + * Do the DRSCAN + */ + jbi_jtag_drscan + ( + start_code, + shift_count, + jbi_dr_buffer, + NULL + ); + + /* jbi_jtag_drscan() always ends in DRPAUSE state */ + jbi_jtag_state = DRPAUSE; + } + + if (status == JBIC_SUCCESS) + { + if (jbi_drstop_state != DRPAUSE) + { + status = jbi_goto_jtag_state(jbi_drstop_state); + } + } + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_swap_dr +( + unsigned int count, + unsigned char *in_data, + unsigned long in_index, + unsigned char *out_data, + unsigned int out_index +) + +/* */ +/* Description: Shifts data into data register, capturing output data */ +/* */ +/* Returns: JBIC_SUCCESS for success, else appropriate error code */ +/* */ +/****************************************************************************/ +{ + int start_code = 0; + unsigned int alloc_chars = 0; + unsigned int shift_count = jbi_dr_preamble + count + jbi_dr_postamble; + JBI_RETURN_TYPE status = JBIC_SUCCESS; + JBIE_JTAG_STATE start_state = JBI_ILLEGAL_JTAG_STATE; + + switch (jbi_jtag_state) + { + case JBI_ILLEGAL_JTAG_STATE: + case RESET: + case IDLE: + start_code = 0; + start_state = IDLE; + break; + + case DRSELECT: + case DRCAPTURE: + case DRSHIFT: + case DREXIT1: + case DRPAUSE: + case DREXIT2: + case DRUPDATE: + start_code = 1; + start_state = DRPAUSE; + break; + + case IRSELECT: + case IRCAPTURE: + case IRSHIFT: + case IREXIT1: + case IRPAUSE: + case IREXIT2: + case IRUPDATE: + start_code = 2; + start_state = IRPAUSE; + break; + + default: + status = JBIC_INTERNAL_ERROR; + break; + } + + if (status == JBIC_SUCCESS) + { + if (jbi_jtag_state != start_state) + { + status = jbi_goto_jtag_state(start_state); + } + } + + if (status == JBIC_SUCCESS) + { + if (jbi_workspace != NULL) + { + if (shift_count > JBIC_MAX_JTAG_DR_LENGTH) + { + status = JBIC_OUT_OF_MEMORY; + } + } + else if (shift_count > jbi_dr_length) + { + alloc_chars = (shift_count + 7) >> 3; + jbi_free(jbi_dr_buffer); + jbi_dr_buffer = (unsigned char *) jbi_malloc(alloc_chars); + + if (jbi_dr_buffer == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + jbi_dr_length = alloc_chars * 8; + } + } + } + + if (status == JBIC_SUCCESS) + { + /* + * Copy preamble data, DR data, and postamble data into a buffer + */ + jbi_jtag_concatenate_data + ( + jbi_dr_buffer, + jbi_dr_preamble_data, + jbi_dr_preamble, + in_data, + in_index, + count, + jbi_dr_postamble_data, + jbi_dr_postamble + ); + + /* + * Do the DRSCAN + */ + jbi_jtag_drscan + ( + start_code, + shift_count, + jbi_dr_buffer, + jbi_dr_buffer + ); + + /* jbi_jtag_drscan() always ends in DRPAUSE state */ + jbi_jtag_state = DRPAUSE; + } + + if (status == JBIC_SUCCESS) + { + if (jbi_drstop_state != DRPAUSE) + { + status = jbi_goto_jtag_state(jbi_drstop_state); + } + } + + if (status == JBIC_SUCCESS) + { + /* + * Now extract the returned data from the buffer + */ + jbi_jtag_extract_target_data + ( + jbi_dr_buffer, + out_data, + out_index, + jbi_dr_preamble, + count + ); + } + + return (status); +} + +/****************************************************************************/ +/* */ + +void jbi_free_jtag_padding_buffers(int reset_jtag) + +/* */ +/* Description: Frees memory allocated for JTAG IR and DR buffers */ +/* */ +/* Returns: nothing */ +/* */ +/****************************************************************************/ +{ + /* + * If the JTAG interface was used, reset it to TLR + */ + if (reset_jtag && (jbi_jtag_state != JBI_ILLEGAL_JTAG_STATE)) + { + jbi_jtag_reset_idle(); + } + + if (jbi_workspace == NULL) + { + if (jbi_dr_preamble_data != NULL) + { + jbi_free(jbi_dr_preamble_data); + jbi_dr_preamble_data = NULL; + } + + if (jbi_dr_postamble_data != NULL) + { + jbi_free(jbi_dr_postamble_data); + jbi_dr_postamble_data = NULL; + } + + if (jbi_dr_buffer != NULL) + { + jbi_free(jbi_dr_buffer); + jbi_dr_buffer = NULL; + } + + if (jbi_ir_preamble_data != NULL) + { + jbi_free(jbi_ir_preamble_data); + jbi_ir_preamble_data = NULL; + } + + if (jbi_ir_postamble_data != NULL) + { + jbi_free(jbi_ir_postamble_data); + jbi_ir_postamble_data = NULL; + } + + if (jbi_ir_buffer != NULL) + { + jbi_free(jbi_ir_buffer); + jbi_ir_buffer = NULL; + } + } +} + +#if PORT==DOS + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_do_drscan_multi_page +( + unsigned int variable_id, + unsigned long count, + unsigned long start_index, + int version +) + +/* */ +/* Description: Shifts data into data register (ignoring output data) */ +/* Scan data comes from compressed Boolean array. */ +/* */ +/* Returns: JBIC_SUCCESS for success, else appropriate error code */ +/* */ +/****************************************************************************/ +{ + JBI_RETURN_TYPE status = JBIC_SUCCESS; + unsigned long shift_count = jbi_dr_preamble + count + jbi_dr_postamble; + unsigned long i; + unsigned long j; + unsigned long k; + unsigned int bi; + + + if (status == JBIC_SUCCESS) + { + status = jbi_goto_jtag_state(DRSHIFT); + } + + if (status == JBIC_SUCCESS) + { + /* + * Get preamble data, DR data, and postamble data one bit at a time + * and immediately scan it into the JTAG chain + */ + + for (i = 0L; i < jbi_dr_preamble; ++i) + { + jbi_jtag_io((i == shift_count - 1), + (int) (jbi_dr_preamble_data[i >> 3L] & (1L << (i & 7L))), 0); + } + + j = start_index; + k = jbi_dr_preamble + count; + + jbi_uncompress_page(variable_id, (unsigned int) (j >> 16L), version); + + for (; i < k; ++i, ++j) + { + bi = (unsigned int) (j & 0x0000ffffL); + + /* check for page boundary - load next page if necessary */ + if (bi == 0) + { + jbi_uncompress_page(variable_id, (unsigned int) (j >> 16L), version); + } + + jbi_jtag_io((i == shift_count - 1), + (int) (jbi_aca_out_buffer[bi >> 3] & (1 << (bi & 7))), 0); + } + + j = 0L; + k = jbi_dr_preamble + count + jbi_dr_postamble; + for (; i < k; ++i, ++j) + { + jbi_jtag_io((i == shift_count - 1), + (int) (jbi_dr_postamble_data[j >> 3L] & (1L << (j & 7L))), 0); + } + + jbi_jtag_io(0, 0, 0); /* DRPAUSE */ + + + /* jbi_jtag_drscan() always ends in DRPAUSE state */ + jbi_jtag_state = DRPAUSE; + + if (jbi_drstop_state != DRPAUSE) + { + status = jbi_goto_jtag_state(jbi_drstop_state); + } + } + + return (status); +} + +#endif diff --git a/common/recipes-utils/jbi/files/code/jbijtag.h b/common/recipes-utils/jbi/files/code/jbijtag.h new file mode 100644 index 0000000..27299f0 --- /dev/null +++ b/common/recipes-utils/jbi/files/code/jbijtag.h @@ -0,0 +1,147 @@ +/****************************************************************************/ +/* */ +/* Module: jbijtag.h */ +/* */ +/* Copyright (C) Altera Corporation 1998-2001 */ +/* */ +/* Description: Definitions of JTAG constants, types, and functions */ +/* */ +/****************************************************************************/ + +#ifndef INC_JBIJTAG_H +#define INC_JBIJTAG_H + +/****************************************************************************/ +/* */ +/* Function Prototypes */ +/* */ +/****************************************************************************/ +typedef enum +{ + JBI_ILLEGAL_JTAG_STATE = -1, + RESET = 0, + IDLE = 1, + DRSELECT = 2, + DRCAPTURE = 3, + DRSHIFT = 4, + DREXIT1 = 5, + DRPAUSE = 6, + DREXIT2 = 7, + DRUPDATE = 8, + IRSELECT = 9, + IRCAPTURE = 10, + IRSHIFT = 11, + IREXIT1 = 12, + IRPAUSE = 13, + IREXIT2 = 14, + IRUPDATE = 15 + +} JBIE_JTAG_STATE; + + +JBI_RETURN_TYPE jbi_init_jtag +( + void +); + +JBI_RETURN_TYPE jbi_set_drstop_state +( + JBIE_JTAG_STATE state +); + +JBI_RETURN_TYPE jbi_set_irstop_state +( + JBIE_JTAG_STATE state +); + +JBI_RETURN_TYPE jbi_set_dr_preamble +( + unsigned int count, + unsigned int start_index, + unsigned char *preamble_data +); + +JBI_RETURN_TYPE jbi_set_ir_preamble +( + unsigned int count, + unsigned int start_index, + unsigned char *preamble_data +); + +JBI_RETURN_TYPE jbi_set_dr_postamble +( + unsigned int count, + unsigned int start_index, + unsigned char *postamble_data +); + +JBI_RETURN_TYPE jbi_set_ir_postamble +( + unsigned int count, + unsigned int start_index, + unsigned char *postamble_data +); + +JBI_RETURN_TYPE jbi_goto_jtag_state +( + JBIE_JTAG_STATE state +); + +JBI_RETURN_TYPE jbi_do_wait_cycles +( + long cycles, + JBIE_JTAG_STATE wait_state +); + +JBI_RETURN_TYPE jbi_do_wait_microseconds +( + long microseconds, + JBIE_JTAG_STATE wait_state +); + +JBI_RETURN_TYPE jbi_do_irscan +( + unsigned int count, + unsigned char *tdi_data, + unsigned int start_index +); + +JBI_RETURN_TYPE jbi_swap_ir +( + unsigned int count, + unsigned char *in_data, + unsigned int in_index, + unsigned char *out_data, + unsigned int out_index +); + +JBI_RETURN_TYPE jbi_do_drscan +( + unsigned int count, + unsigned char *tdi_data, + unsigned long start_index +); + +JBI_RETURN_TYPE jbi_swap_dr +( + unsigned int count, + unsigned char *in_data, + unsigned long in_index, + unsigned char *out_data, + unsigned int out_index +); + +void jbi_free_jtag_padding_buffers +( + int reset_jtag +); + +JBI_RETURN_TYPE jbi_do_drscan_multi_page +( + unsigned int variable_id, + unsigned long long_count, + unsigned long long_index, + int version +); + +#endif /* INC_JBIJTAG_H */ diff --git a/common/recipes-utils/jbi/files/code/jbimain.c b/common/recipes-utils/jbi/files/code/jbimain.c new file mode 100644 index 0000000..79bdf69 --- /dev/null +++ b/common/recipes-utils/jbi/files/code/jbimain.c @@ -0,0 +1,3290 @@ +/****************************************************************************/ +/* */ +/* Module: jbimain.c */ +/* */ +/* Copyright (C) Altera Corporation 1998-2001 */ +/* */ +/* Description: Jam STAPL ByteCode Player (Interpreter) */ +/* */ +/* Revisions: 2.2 fixed /W4 warnings */ +/* 2.0 added support for STAPL ByteCode format */ +/* */ +/****************************************************************************/ + +#include "jbiport.h" +#include "jbiexprt.h" +#include "jbijtag.h" +#include "jbicomp.h" + +/****************************************************************************/ +/* */ +/* MACROS */ +/* */ +/****************************************************************************/ + +#define NULL 0 + +#define JBI_STACK_SIZE 128 + +#define JBIC_MESSAGE_LENGTH 1024 + +/* +* This macro checks if enough parameters are available on the stack. The +* argument is the number of parameters needed. +*/ +#define IF_CHECK_STACK(x) \ + if (stack_ptr < (int) (x)) \ + { \ + status = JBIC_STACK_OVERFLOW; \ + } \ + else + +/* +* This macro checks if a code address is inside the code section +*/ +#define CHECK_PC \ + if ((pc < code_section) || (pc >= debug_section)) \ + { \ + status = JBIC_BOUNDS_ERROR; \ + } + +/****************************************************************************/ +/* */ +/* GLOBAL VARIABLES */ +/* */ +/****************************************************************************/ + +#if PORT==DOS +/* +* jbi_program is a global pointer used by macros GET_BYTE, GET_WORD, and +* GET_DWORD to read data from the JBC file +*/ +PROGRAM_PTR jbi_program; +#endif + +/****************************************************************************/ +/* */ +/* UTILITY FUNCTIONS */ +/* */ +/****************************************************************************/ + +int jbi_strlen(char *string) +{ + int len = 0; + + while (string[len] != '\0') ++len; + + return (len); +} + +long jbi_atol(char *buffer) +{ + long result = 0L; + int index = 0; + + while ((buffer[index] >= '0') && (buffer[index] <= '9')) + { + result = (result * 10) + (buffer[index] - '0'); + ++index; + } + + return (result); +} + +void jbi_ltoa(char *buffer, long number) +{ + int index = 0; + int rev_index = 0; + char reverse[32]; + + if (number < 0L) + { + buffer[index++] = '-'; + number = 0 - number; + } + else if (number == 0) + { + buffer[index++] = '0'; + } + + while (number != 0) + { + reverse[rev_index++] = (char) ((number % 10) + '0'); + number /= 10; + } + + while (rev_index > 0) + { + buffer[index++] = reverse[--rev_index]; + } + + buffer[index] = '\0'; +} + +char jbi_toupper(char ch) +{ + return ((char) (((ch >= 'a') && (ch <= 'z')) ? (ch + 'A' - 'a') : ch)); +} + +int jbi_stricmp(char *left, char *right) +{ + int result = 0; + char l, r; + + do + { + l = jbi_toupper(*left); + r = jbi_toupper(*right); + result = l - r; + ++left; + ++right; + } + while ((result == 0) && (l != '\0') && (r != '\0')); + + return (result); +} + +void jbi_strncpy(char *left, char *right, int count) +{ + char ch; + + do + { + *left = *right; + ch = *right; + ++left; + ++right; + --count; + } + while ((ch != '\0') && (count != 0)); +} + +void jbi_make_dword(unsigned char *buf, unsigned long num) +{ + buf[0] = (unsigned char) num; + buf[1] = (unsigned char) (num >> 8L); + buf[2] = (unsigned char) (num >> 16L); + buf[3] = (unsigned char) (num >> 24L); +} + +unsigned long jbi_get_dword(unsigned char *buf) +{ + return + (((unsigned long) buf[0]) | + (((unsigned long) buf[1]) << 8L) | + (((unsigned long) buf[2]) << 16L) | + (((unsigned long) buf[3]) << 24L)); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_execute +( + PROGRAM_PTR program, + long program_size, + char *workspace, + long workspace_size, + char *action, + char **init_list, + int reset_jtag, + long *error_address, + int *exit_code, + int *format_version +) + +/* */ +/* Description: */ +/* */ +/* Returns: */ +/* */ +/****************************************************************************/ +{ + JBI_RETURN_TYPE status = JBIC_SUCCESS; + unsigned long first_word = 0L; + unsigned long action_table = 0L; + unsigned long proc_table = 0L; + unsigned long string_table = 0L; + unsigned long symbol_table = 0L; + unsigned long data_section = 0L; + unsigned long code_section = 0L; + unsigned long debug_section = 0L; + unsigned long action_count = 0L; + unsigned long proc_count = 0L; + unsigned long symbol_count = 0L; + char message_buffer[JBIC_MESSAGE_LENGTH + 1]; + long *variables = NULL; + long *variable_size = NULL; + char *attributes = NULL; + unsigned char *proc_attributes = NULL; + unsigned long pc; + unsigned long opcode_address; + unsigned long args[3]; + unsigned int opcode; + unsigned long name_id; + long stack[JBI_STACK_SIZE] = {0}; + unsigned char charbuf[4]; + long long_temp; + unsigned int variable_id; + unsigned char *charptr_temp; + unsigned char *charptr_temp2; + long *longptr_temp; + int version = 0; + int delta = 0; + int stack_ptr = 0; + unsigned int arg_count; + int done = 0; + int bad_opcode = 0; + unsigned int count; + unsigned int index; + unsigned int index2; + long long_count; + long long_index; + long long_index2; + unsigned int i; + unsigned int j; + unsigned long uncompressed_size; + unsigned int offset; + unsigned long value; + int current_proc = 0; + char *equal_ptr; + int length; + int reverse; + +#if PORT==DOS + char name[33]; +#else + char *name; +#endif + + jbi_workspace = workspace; + jbi_workspace_size = workspace_size; + +#if PORT==DOS + jbi_program = program; +#endif + + /* + * Read header information + */ + if (program_size > 52L) + { + first_word = GET_DWORD(0); + version = (int) (first_word & 1L); + *format_version = version + 1; + delta = version * 8; + + action_table = GET_DWORD(4); + proc_table = GET_DWORD(8); + string_table = GET_DWORD(4 + delta); + symbol_table = GET_DWORD(16 + delta); + data_section = GET_DWORD(20 + delta); + code_section = GET_DWORD(24 + delta); + debug_section = GET_DWORD(28 + delta); + action_count = GET_DWORD(40 + delta); + proc_count = GET_DWORD(44 + delta); + symbol_count = GET_DWORD(48 + (2 * delta)); + } + + if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) + { + done = 1; + status = JBIC_IO_ERROR; + } + + if ((status == JBIC_SUCCESS) && (symbol_count > 0)) + { + variables = (long *) jbi_malloc( + (unsigned int) symbol_count * sizeof(long)); + + if (variables == NULL) status = JBIC_OUT_OF_MEMORY; + + if (status == JBIC_SUCCESS) + { + variable_size = (long *) jbi_malloc( + (unsigned int) symbol_count * sizeof(long)); + + if (variable_size == NULL) status = JBIC_OUT_OF_MEMORY; + } + + if (status == JBIC_SUCCESS) + { + attributes = (char *) jbi_malloc((unsigned int) symbol_count); + + if (attributes == NULL) status = JBIC_OUT_OF_MEMORY; + } + + if ((status == JBIC_SUCCESS) && (version > 0)) + { + proc_attributes = (unsigned char *) jbi_malloc((unsigned int) proc_count); + + if (proc_attributes == NULL) status = JBIC_OUT_OF_MEMORY; + } + + if (status == JBIC_SUCCESS) + { + delta = version * 2; + + for (i = 0; i < (unsigned int) symbol_count; ++i) + { + offset = (unsigned int) (symbol_table + ((11 + delta) * i)); + + value = GET_DWORD(offset + 3 + delta); + + attributes[i] = GET_BYTE(offset); + + /* use bit 7 of attribute byte to indicate that this buffer */ + /* was dynamically allocated and should be freed later */ + attributes[i] &= 0x7f; + + variable_size[i] = GET_DWORD(offset + 7 + delta); + + /* + * Attribute bits: + * bit 0: 0 = read-only, 1 = read-write + * bit 1: 0 = not compressed, 1 = compressed + * bit 2: 0 = not initialized, 1 = initialized + * bit 3: 0 = scalar, 1 = array + * bit 4: 0 = Boolean, 1 = integer + * bit 5: 0 = declared variable, + * 1 = compiler created temporary variable + */ + + if ((attributes[i] & 0x0c) == 0x04) + { + /* initialized scalar variable */ + variables[i] = value; + } + else if ((attributes[i] & 0x1e) == 0x0e) + { + /* initialized compressed Boolean array */ +#if PORT==DOS + /* for DOS port, get the size but do not uncompress */ + long_index = data_section + value; + uncompressed_size = + (((unsigned long) GET_BYTE(long_index)) | + (((unsigned long) GET_BYTE(long_index + 1L)) << 8L) | + (((unsigned long) GET_BYTE(long_index + 2L)) << 16L) | + (((unsigned long) GET_BYTE(long_index + 3L)) << 24L)); + variable_size[i] = uncompressed_size; +#else + uncompressed_size = jbi_get_dword( + &program[data_section + value]); + + /* allocate a buffer for the uncompressed data */ + variables[i] = (long) jbi_malloc(uncompressed_size); + + if (variables[i] == 0L) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + /* set flag so buffer will be freed later */ + attributes[i] |= 0x80; + + /* uncompress the data */ + if (jbi_uncompress( + &program[data_section + value], + variable_size[i], + (unsigned char *) variables[i], + uncompressed_size, + version) + != uncompressed_size) + { + /* decompression failed */ + status = JBIC_IO_ERROR; + } + else + { + variable_size[i] = uncompressed_size * 8L; + } + } +#endif + } + else if ((attributes[i] & 0x1e) == 0x0c) + { + /* initialized Boolean array */ +#if PORT==DOS + /* flag attributes so that memory is freed */ + attributes[i] |= 0x80; + + if (variable_size[i] > 0) + { + unsigned int size = (unsigned int) + ((variable_size[i] + 7L) / 8L); + + variables[i] = (long) jbi_malloc(size); + + if (variables[i] == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + unsigned char *p = (unsigned char *) variables[i]; + /* copy array values into buffer */ + for (j = 0; j < size; ++j) + { + p[j] = GET_BYTE(data_section + value + j); + } + } + } + else + { + variables[i] = 0; + } +#else + variables[i] = value + data_section + (long) program; +#endif + } + else if ((attributes[i] & 0x1c) == 0x1c) + { + /* initialized integer array */ + variables[i] = value + data_section; + } + else if ((attributes[i] & 0x0c) == 0x08) + { + /* uninitialized array */ + + /* flag attributes so that memory is freed */ + attributes[i] |= 0x80; + + if (variable_size[i] > 0) + { + unsigned int size; + + if (attributes[i] & 0x10) + { + /* integer array */ + size = (unsigned int) + (variable_size[i] * sizeof(long)); + } + else + { + /* Boolean array */ + size = (unsigned int) + ((variable_size[i] + 7L) / 8L); + } + + variables[i] = (long) jbi_malloc(size); + + if (variables[i] == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + /* zero out memory */ + for (j = 0; j < size; ++j) + { + ((unsigned char *)(variables[i]))[j] = 0; + } + } + } + else + { + variables[i] = 0; + } + } + else + { + variables[i] = 0; + } + } + } + } + + /* + * Initialize variables listed in init_list + */ + if ((status == JBIC_SUCCESS) && (init_list != NULL) && (version == 0)) + { + delta = version * 2; + count = 0; + while (init_list[count] != NULL) + { + equal_ptr = init_list[count]; + length = 0; + while ((*equal_ptr != '=') && (*equal_ptr != '\0')) + { + ++equal_ptr; + ++length; + } + if (*equal_ptr == '=') + { + ++equal_ptr; + value = jbi_atol(equal_ptr); + jbi_strncpy(message_buffer, init_list[count], length); + message_buffer[length] = '\0'; + for (i = 0; i < (unsigned int) symbol_count; ++i) + { + offset = (unsigned int) (symbol_table + ((11 + delta) * i)); + name_id = (version == 0) ? GET_WORD(offset + 1) : + GET_DWORD(offset + 1); +#if PORT==DOS + for (j = 0; j < 32; ++j) + { + name[j] = GET_BYTE(string_table + name_id + j); + } + name[32] = '\0'; +#else + name = (char *) &program[string_table + name_id]; +#endif + + if (jbi_stricmp(message_buffer, name) == 0) + { + variables[i] = value; + } + } + } + + ++count; + } + } + + if (status != JBIC_SUCCESS) done = 1; + + jbi_init_jtag(); + + pc = code_section; + message_buffer[0] = '\0'; + + /* + * For JBC version 2, we will execute the procedures corresponding to + * the selected ACTION + */ + if (version > 0) + { + if (action == NULL) + { + status = JBIC_ACTION_NOT_FOUND; + done = 1; + } + else + { + int action_found = 0; + + for (i = 0; (i < action_count) && !action_found; ++i) + { + name_id = GET_DWORD(action_table + (12 * i)); + +#if PORT==DOS + for (j = 0; j < 32; ++j) + { + name[j] = GET_BYTE(string_table + name_id + j); + } + name[32] = '\0'; +#else + name = (char *) &program[string_table + name_id]; +#endif + + if (jbi_stricmp(action, name) == 0) + { + action_found = 1; + current_proc = (int) GET_DWORD(action_table + (12 * i) + 8); + } + } + + if (!action_found) + { + status = JBIC_ACTION_NOT_FOUND; + done = 1; + } + } + + if (status == JBIC_SUCCESS) + { + int first_time = 1; + i = current_proc; + while ((i != 0) || first_time) + { + first_time = 0; + /* check procedure attribute byte */ + proc_attributes[i] = (unsigned char) + (GET_BYTE(proc_table + (13 * i) + 8) & 0x03); + + if (proc_attributes[i] != 0) + { + /* + * BIT0 - OPTIONAL + * BIT1 - RECOMMENDED + * BIT6 - FORCED OFF + * BIT7 - FORCED ON + */ + if (init_list != NULL) + { + name_id = GET_DWORD(proc_table + (13 * i)); +#if PORT==DOS + for (j = 0; j < 32; ++j) + { + name[j] = GET_BYTE(string_table + name_id + j); + } + name[32] = '\0'; +#else + name = (char *) &program[string_table + name_id]; +#endif + count = 0; + while (init_list[count] != NULL) + { + equal_ptr = init_list[count]; + length = 0; + while ((*equal_ptr != '=') && (*equal_ptr != '\0')) + { + ++equal_ptr; + ++length; + } + if (*equal_ptr == '=') + { + ++equal_ptr; + jbi_strncpy(message_buffer, init_list[count], length); + message_buffer[length] = '\0'; + + if (jbi_stricmp(message_buffer, name) == 0) + { + if (jbi_atol(equal_ptr) == 0) + { + proc_attributes[i] |= 0x40; + } + else + { + proc_attributes[i] |= 0x80; + } + } + } + + ++count; + } + } + } + + i = (unsigned int) GET_DWORD(proc_table + (13 * i) + 4); + } + + /* + * Set current_proc to the first procedure to be executed + */ + i = current_proc; + while ((i != 0) && + ((proc_attributes[i] == 1) || + ((proc_attributes[i] & 0xc0) == 0x40))) + { + i = (unsigned int) GET_DWORD(proc_table + (13 * i) + 4); + } + + if ((i != 0) || ((i == 0) && (current_proc == 0) && + ((proc_attributes[0] != 1) && + ((proc_attributes[0] & 0xc0) != 0x40)))) + { + current_proc = i; + pc = code_section + GET_DWORD(proc_table + (13 * i) + 9); + CHECK_PC; + } + else + { + /* there are no procedures to execute! */ + done = 1; + } + } + } + + message_buffer[0] = '\0'; + + while (!done) + { + opcode = (unsigned int) (GET_BYTE(pc) & 0xff); + opcode_address = pc; + ++pc; + + arg_count = (opcode >> 6) & 3; + for (i = 0; i < arg_count; ++i) + { + args[i] = GET_DWORD(pc); + pc += 4; + } + + switch (opcode) + { + case 0x00: /* NOP */ + /* do nothing */ + break; + + case 0x01: /* DUP */ + IF_CHECK_STACK(1) + { + stack[stack_ptr] = stack[stack_ptr - 1]; + ++stack_ptr; + } + break; + + case 0x02: /* SWP */ + IF_CHECK_STACK(2) + { + long_temp = stack[stack_ptr - 2]; + stack[stack_ptr - 2] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_temp; + } + break; + + case 0x03: /* ADD */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] += stack[stack_ptr]; + } + break; + + case 0x04: /* SUB */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] -= stack[stack_ptr]; + } + break; + + case 0x05: /* MULT */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] *= stack[stack_ptr]; + } + break; + + case 0x06: /* DIV */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] /= stack[stack_ptr]; + } + break; + + case 0x07: /* MOD */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] %= stack[stack_ptr]; + } + break; + + case 0x08: /* SHL */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] <<= stack[stack_ptr]; + } + break; + + case 0x09: /* SHR */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] >>= stack[stack_ptr]; + } + break; + + case 0x0A: /* NOT */ + IF_CHECK_STACK(1) + { + stack[stack_ptr - 1] ^= (-1L); + } + break; + + case 0x0B: /* AND */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] &= stack[stack_ptr]; + } + break; + + case 0x0C: /* OR */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] |= stack[stack_ptr]; + } + break; + + case 0x0D: /* XOR */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] ^= stack[stack_ptr]; + } + break; + + case 0x0E: /* INV */ + IF_CHECK_STACK(1) + { + stack[stack_ptr - 1] = stack[stack_ptr - 1] ? 0L : 1L; + } + break; + + case 0x0F: /* GT */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] = + (stack[stack_ptr - 1] > stack[stack_ptr]) ? 1L : 0L; + } + break; + + case 0x10: /* LT */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] = + (stack[stack_ptr - 1] < stack[stack_ptr]) ? 1L : 0L; + } + break; + + case 0x11: /* RET */ + if ((version > 0) && (stack_ptr == 0)) + { + /* + * We completed one of the main procedures of an ACTION. + * Find the next procedure to be executed and jump to it. + * If there are no more procedures, then EXIT. + */ + i = (unsigned int) GET_DWORD(proc_table + (13 * current_proc) + 4); + while ((i != 0) && + ((proc_attributes[i] == 1) || + ((proc_attributes[i] & 0xc0) == 0x40))) + { + i = (unsigned int) GET_DWORD(proc_table + (13 * i) + 4); + } + + if (i == 0) + { + /* there are no procedures to execute! */ + done = 1; + *exit_code = 0; /* success */ + } + else + { + current_proc = i; + pc = code_section + GET_DWORD(proc_table + (13 * i) + 9); + CHECK_PC; + } + } + else IF_CHECK_STACK(1) + { + pc = stack[--stack_ptr] + code_section; + CHECK_PC; + if (pc == code_section) + { + status = JBIC_BOUNDS_ERROR; + } + } + break; + + case 0x12: /* CMPS */ + /* + * Array short compare + * ...stack 0 is source 1 value + * ...stack 1 is source 2 value + * ...stack 2 is mask value + * ...stack 3 is count + */ + IF_CHECK_STACK(4) + { + long a = stack[--stack_ptr]; + long b = stack[--stack_ptr]; + long_temp = stack[--stack_ptr]; + count = (unsigned int) stack[stack_ptr - 1]; + + if ((count < 1) || (count > 32)) + { + status = JBIC_BOUNDS_ERROR; + } + else + { + long_temp &= ((-1L) >> (32 - count)); + + stack[stack_ptr - 1] = + ((a & long_temp) == (b & long_temp)) ? 1L : 0L; + } + } + break; + + case 0x13: /* PINT */ + /* + * PRINT add integer + * ...stack 0 is integer value + */ + IF_CHECK_STACK(1) + { + jbi_ltoa(&message_buffer[jbi_strlen(message_buffer)], + stack[--stack_ptr]); + } + break; + + case 0x14: /* PRNT */ + /* + * PRINT finish + */ + jbi_message(message_buffer); + message_buffer[0] = '\0'; + break; + + case 0x15: /* DSS */ + /* + * DRSCAN short + * ...stack 0 is scan data + * ...stack 1 is count + */ + IF_CHECK_STACK(2) + { + long_temp = stack[--stack_ptr]; + count = (unsigned int) stack[--stack_ptr]; + jbi_make_dword(charbuf, long_temp); + status = jbi_do_drscan(count, charbuf, 0); + } + break; + + case 0x16: /* DSSC */ + /* + * DRSCAN short with capture + * ...stack 0 is scan data + * ...stack 1 is count + */ + IF_CHECK_STACK(2) + { + long_temp = stack[--stack_ptr]; + count = (unsigned int) stack[stack_ptr - 1]; + jbi_make_dword(charbuf, long_temp); + status = jbi_swap_dr(count, charbuf, 0, charbuf, 0); + stack[stack_ptr - 1] = jbi_get_dword(charbuf); + } + break; + + case 0x17: /* ISS */ + /* + * IRSCAN short + * ...stack 0 is scan data + * ...stack 1 is count + */ + IF_CHECK_STACK(2) + { + long_temp = stack[--stack_ptr]; + count = (unsigned int) stack[--stack_ptr]; + jbi_make_dword(charbuf, long_temp); + status = jbi_do_irscan(count, charbuf, 0); + } + break; + + case 0x18: /* ISSC */ + /* + * IRSCAN short with capture + * ...stack 0 is scan data + * ...stack 1 is count + */ + IF_CHECK_STACK(2) + { + long_temp = stack[--stack_ptr]; + count = (unsigned int) stack[stack_ptr - 1]; + jbi_make_dword(charbuf, long_temp); + status = jbi_swap_ir(count, charbuf, 0, charbuf, 0); + stack[stack_ptr - 1] = jbi_get_dword(charbuf); + } + break; + + case 0x19: /* VSS */ + /* + * VECTOR short + * ...stack 0 is scan data + * ...stack 1 is count + */ + bad_opcode = 1; + break; + + case 0x1A: /* VSSC */ + /* + * VECTOR short with capture + * ...stack 0 is scan data + * ...stack 1 is count + */ + bad_opcode = 1; + break; + + case 0x1B: /* VMPF */ + /* + * VMAP finish + */ + bad_opcode = 1; + break; + + case 0x1C: /* DPR */ + IF_CHECK_STACK(1) + { + count = (unsigned int) stack[--stack_ptr]; + status = jbi_set_dr_preamble(count, 0, NULL); + } + break; + + case 0x1D: /* DPRL */ + /* + * DRPRE with literal data + * ...stack 0 is count + * ...stack 1 is literal data + */ + IF_CHECK_STACK(2) + { + count = (unsigned int) stack[--stack_ptr]; + long_temp = stack[--stack_ptr]; + jbi_make_dword(charbuf, long_temp); + status = jbi_set_dr_preamble(count, 0, charbuf); + } + break; + + case 0x1E: /* DPO */ + /* + * DRPOST + * ...stack 0 is count + */ + IF_CHECK_STACK(1) + { + count = (unsigned int) stack[--stack_ptr]; + status = jbi_set_dr_postamble(count, 0, NULL); + } + break; + + case 0x1F: /* DPOL */ + /* + * DRPOST with literal data + * ...stack 0 is count + * ...stack 1 is literal data + */ + IF_CHECK_STACK(2) + { + count = (unsigned int) stack[--stack_ptr]; + long_temp = stack[--stack_ptr]; + jbi_make_dword(charbuf, long_temp); + status = jbi_set_dr_postamble(count, 0, charbuf); + } + break; + + case 0x20: /* IPR */ + IF_CHECK_STACK(1) + { + count = (unsigned int) stack[--stack_ptr]; + status = jbi_set_ir_preamble(count, 0, NULL); + } + break; + + case 0x21: /* IPRL */ + /* + * IRPRE with literal data + * ...stack 0 is count + * ...stack 1 is literal data + */ + IF_CHECK_STACK(2) + { + count = (unsigned int) stack[--stack_ptr]; + long_temp = stack[--stack_ptr]; + jbi_make_dword(charbuf, long_temp); + status = jbi_set_ir_preamble(count, 0, charbuf); + } + break; + + case 0x22: /* IPO */ + /* + * IRPOST + * ...stack 0 is count + */ + IF_CHECK_STACK(1) + { + count = (unsigned int) stack[--stack_ptr]; + status = jbi_set_ir_postamble(count, 0, NULL); + } + break; + + case 0x23: /* IPOL */ + /* + * IRPOST with literal data + * ...stack 0 is count + * ...stack 1 is literal data + */ + IF_CHECK_STACK(2) + { + count = (unsigned int) stack[--stack_ptr]; + long_temp = stack[--stack_ptr]; + jbi_make_dword(charbuf, long_temp); + status = jbi_set_ir_postamble(count, 0, charbuf); + } + break; + + case 0x24: /* PCHR */ + IF_CHECK_STACK(1) + { + unsigned char ch; + count = jbi_strlen(message_buffer); + ch = (char) stack[--stack_ptr]; + if ((ch < 1) || (ch > 127)) + { + /* character code out of range */ + /* instead of flagging an error, force the value to 127 */ + ch = 127; + } + message_buffer[count] = ch; + message_buffer[count + 1] = '\0'; + } + break; + + case 0x25: /* EXIT */ + IF_CHECK_STACK(1) + { + *exit_code = (int) stack[--stack_ptr]; + } + done = 1; + break; + + case 0x26: /* EQU */ + IF_CHECK_STACK(2) + { + --stack_ptr; + stack[stack_ptr - 1] = + (stack[stack_ptr - 1] == stack[stack_ptr]) ? 1L : 0L; + } + break; + + case 0x27: /* POPT */ + IF_CHECK_STACK(1) + { + --stack_ptr; + } + break; + + case 0x28: /* TRST */ + bad_opcode = 1; + break; + + case 0x29: /* FRQ */ + bad_opcode = 1; + break; + + case 0x2A: /* FRQU */ + bad_opcode = 1; + break; + + case 0x2B: /* PD32 */ + bad_opcode = 1; + break; + + case 0x2C: /* ABS */ + IF_CHECK_STACK(1) + { + if (stack[stack_ptr - 1] < 0) + { + stack[stack_ptr - 1] = 0 - stack[stack_ptr - 1]; + } + } + break; + + case 0x2D: /* BCH0 */ + /* + * Batch operation 0 + * SWP + * SWPN 7 + * SWP + * SWPN 6 + * DUPN 8 + * SWPN 2 + * SWP + * DUPN 6 + * DUPN 6 + */ + + /* SWP */ + IF_CHECK_STACK(2) + { + long_temp = stack[stack_ptr - 2]; + stack[stack_ptr - 2] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_temp; + } + + /* SWPN 7 */ + index = 7 + 1; + IF_CHECK_STACK(index) + { + long_temp = stack[stack_ptr - index]; + stack[stack_ptr - index] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_temp; + } + + /* SWP */ + IF_CHECK_STACK(2) + { + long_temp = stack[stack_ptr - 2]; + stack[stack_ptr - 2] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_temp; + } + + /* SWPN 6 */ + index = 6 + 1; + IF_CHECK_STACK(index) + { + long_temp = stack[stack_ptr - index]; + stack[stack_ptr - index] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_temp; + } + + /* DUPN 8 */ + index = 8 + 1; + IF_CHECK_STACK(index) + { + stack[stack_ptr] = stack[stack_ptr - index]; + ++stack_ptr; + } + + /* SWPN 2 */ + index = 2 + 1; + IF_CHECK_STACK(index) + { + long_temp = stack[stack_ptr - index]; + stack[stack_ptr - index] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_temp; + } + + /* SWP */ + IF_CHECK_STACK(2) + { + long_temp = stack[stack_ptr - 2]; + stack[stack_ptr - 2] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_temp; + } + + /* DUPN 6 */ + index = 6 + 1; + IF_CHECK_STACK(index) + { + stack[stack_ptr] = stack[stack_ptr - index]; + ++stack_ptr; + } + + /* DUPN 6 */ + index = 6 + 1; + IF_CHECK_STACK(index) + { + stack[stack_ptr] = stack[stack_ptr - index]; + ++stack_ptr; + } + break; + + case 0x2E: /* BCH1 */ + /* + * Batch operation 1 + * SWPN 8 + * SWP + * SWPN 9 + * SWPN 3 + * SWP + * SWPN 2 + * SWP + * SWPN 7 + * SWP + * SWPN 6 + * DUPN 5 + * DUPN 5 + */ + bad_opcode = 1; + break; + + case 0x2F: /* PSH0 */ + stack[stack_ptr++] = 0; + break; + + case 0x40: /* PSHL */ + stack[stack_ptr++] = (long) args[0]; + break; + + case 0x41: /* PSHV */ + stack[stack_ptr++] = variables[args[0]]; + break; + + case 0x42: /* JMP */ + pc = args[0] + code_section; + CHECK_PC; + break; + + case 0x43: /* CALL */ + stack[stack_ptr++] = pc; + pc = args[0] + code_section; + CHECK_PC; + break; + + case 0x44: /* NEXT */ + /* + * Process FOR / NEXT loop + * ...argument 0 is variable ID + * ...stack 0 is step value + * ...stack 1 is end value + * ...stack 2 is top address + */ + IF_CHECK_STACK(3) + { + long step = stack[stack_ptr - 1]; + long end = stack[stack_ptr - 2]; + long top = stack[stack_ptr - 3]; + long iterator = variables[args[0]]; + int break_out = 0; + + if (step < 0) + { + if (iterator <= end) break_out = 1; + } + else + { + if (iterator >= end) break_out = 1; + } + + if (break_out) + { + stack_ptr -= 3; + } + else + { + variables[args[0]] = iterator + step; + pc = top + code_section; + CHECK_PC; + } + } + break; + + case 0x45: /* PSTR */ + /* + * PRINT add string + * ...argument 0 is string ID + */ +#if PORT==DOS + long_index = string_table + args[0]; + index2 = jbi_strlen(message_buffer); + + do + { + i = GET_BYTE(long_index); + message_buffer[index2] = (char) i; + ++long_index; + ++index2; + } + while ((i != '\0') && (index2 < JBIC_MESSAGE_LENGTH)); +#else + count = jbi_strlen(message_buffer); + jbi_strncpy(&message_buffer[count], + (char *) &program[string_table + args[0]], + JBIC_MESSAGE_LENGTH - count); +#endif + message_buffer[JBIC_MESSAGE_LENGTH] = '\0'; + break; + + case 0x46: /* VMAP */ + /* + * VMAP add signal name + * ...argument 0 is string ID + */ + bad_opcode = 1; + break; + + case 0x47: /* SINT */ + /* + * STATE intermediate state + * ...argument 0 is state code + */ + status = jbi_goto_jtag_state((int) args[0]); + break; + + case 0x48: /* ST */ + /* + * STATE final state + * ...argument 0 is state code + */ + status = jbi_goto_jtag_state((int) args[0]); + break; + + case 0x49: /* ISTP */ + /* + * IRSTOP state + * ...argument 0 is state code + */ + status = jbi_set_irstop_state((int) args[0]); + break; + + case 0x4A: /* DSTP */ + /* + * DRSTOP state + * ...argument 0 is state code + */ + status = jbi_set_drstop_state((int) args[0]); + break; + + case 0x4B: /* SWPN */ + /* + * Exchange top with Nth stack value + * ...argument 0 is 0-based stack entry to swap with top element + */ + index = ((int) args[0]) + 1; + IF_CHECK_STACK(index) + { + long_temp = stack[stack_ptr - index]; + stack[stack_ptr - index] = stack[stack_ptr - 1]; + stack[stack_ptr - 1] = long_temp; + } + break; + + case 0x4C: /* DUPN */ + /* + * Duplicate Nth stack value + * ...argument 0 is 0-based stack entry to duplicate + */ + index = ((int) args[0]) + 1; + IF_CHECK_STACK(index) + { + stack[stack_ptr] = stack[stack_ptr - index]; + ++stack_ptr; + } + break; + + case 0x4D: /* POPV */ + /* + * Pop stack into scalar variable + * ...argument 0 is variable ID + * ...stack 0 is value + */ + IF_CHECK_STACK(1) + { + variables[args[0]] = stack[--stack_ptr]; + } + break; + + case 0x4E: /* POPE */ + /* + * Pop stack into integer array element + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is value + */ + IF_CHECK_STACK(2) + { + variable_id = (unsigned int) args[0]; + + /* + * If variable is read-only, convert to writable array + */ + if ((version > 0) && + ((attributes[variable_id] & 0x9c) == 0x1c)) + { + /* + * Allocate a writable buffer for this array + */ + count = (unsigned int) variable_size[variable_id]; + long_temp = variables[variable_id]; + longptr_temp = (long *) jbi_malloc(count * sizeof(long)); + variables[variable_id] = (long) longptr_temp; + + if (variables[variable_id] == NULL) + { + status = JBIC_OUT_OF_MEMORY; + break; + } + else + { + /* copy previous contents into buffer */ + for (i = 0; i < count; ++i) + { + longptr_temp[i] = GET_DWORD(long_temp); + long_temp += 4L; + } + + /* set bit 7 - buffer was dynamically allocated */ + attributes[variable_id] |= 0x80; + + /* clear bit 2 - variable is writable */ + attributes[variable_id] &= ~0x04; + attributes[variable_id] |= 0x01; + } + } + +#if PORT==DOS + /* for 16-bit version, allow writing in allocated buffers */ + if ((version > 0) && + ((attributes[variable_id] & 0x9c) == 0x9c)) + { + attributes[variable_id] &= ~0x04; + attributes[variable_id] |= 0x01; + } +#endif + + /* check that variable is a writable integer array */ + if ((attributes[variable_id] & 0x1c) != 0x18) + { + status = JBIC_BOUNDS_ERROR; + } + else + { + longptr_temp = (long *) variables[variable_id]; + + /* pop the array index */ + index = (unsigned int) stack[--stack_ptr]; + + /* pop the value and store it into the array */ + longptr_temp[index] = stack[--stack_ptr]; + } + } + break; + + case 0x4F: /* POPA */ + /* + * Pop stack into Boolean array + * ...argument 0 is variable ID + * ...stack 0 is count + * ...stack 1 is array index + * ...stack 2 is value + */ + IF_CHECK_STACK(3) + { + variable_id = (unsigned int) args[0]; + + /* + * If variable is read-only, convert to writable array + */ + if ((version > 0) && + ((attributes[variable_id] & 0x9c) == 0x0c)) + { + /* + * Allocate a writable buffer for this array + */ + long_temp = (variable_size[variable_id] + 7L) >> 3L; + charptr_temp2 = (unsigned char *) variables[variable_id]; + charptr_temp = jbi_malloc((unsigned int) long_temp); + variables[variable_id] = (long) charptr_temp; + + if (variables[variable_id] == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + /* zero the buffer */ + for (long_index = 0L; + long_index < long_temp; + ++long_index) + { + charptr_temp[long_index] = 0; + } + + /* copy previous contents into buffer */ + for (long_index = 0L; + long_index < variable_size[variable_id]; + ++long_index) + { +#if PORT==DOS + if ((attributes[variable_id] & 0x02) && + ((long_index & 0x0000FFFF) == 0L)) + { + /* initialized compressed Boolean array */ + jbi_uncompress_page(variable_id, + (int) (long_index >> 16), version); + charptr_temp = jbi_aca_out_buffer; + long_index2 = long_index & 0xFFFF; + } +#else + long_index2 = long_index; +#endif + + if (charptr_temp2[long_index2 >> 3] & + (1 << (long_index2 & 7))) + { + charptr_temp[long_index >> 3] |= + (1 << (long_index & 7)); + } + } + + /* set bit 7 - buffer was dynamically allocated */ + attributes[variable_id] |= 0x80; + + /* clear bit 2 - variable is writable */ + attributes[variable_id] &= ~0x04; + attributes[variable_id] |= 0x01; + } + } + +#if PORT==DOS + /* for 16-bit version, allow writing in allocated buffers */ + if ((version > 0) && + ((attributes[variable_id] & 0x9c) == 0x8c)) + { + attributes[variable_id] &= ~0x04; + attributes[variable_id] |= 0x01; + } +#endif + + /* check that variable is a writable Boolean array */ + if ((attributes[variable_id] & 0x1c) != 0x08) + { + status = JBIC_BOUNDS_ERROR; + } + else + { + charptr_temp = (unsigned char *) variables[variable_id]; + + /* pop the count (number of bits to copy) */ + long_count = stack[--stack_ptr]; + + /* pop the array index */ + long_index = stack[--stack_ptr]; + + reverse = 0; + + if (version > 0) + { + /* stack 0 = array right index */ + /* stack 1 = array left index */ + + if (long_index > long_count) + { + reverse = 1; + long_temp = long_count; + long_count = 1 + long_index - long_count; + long_index = long_temp; + + /* reverse POPA is not supported */ + status = JBIC_BOUNDS_ERROR; + break; + } + else + { + long_count = 1 + long_count - long_index; + } + } + + /* pop the data */ + long_temp = stack[--stack_ptr]; + + if (long_count < 1) + { + status = JBIC_BOUNDS_ERROR; + } + else + { + for (i = 0; i < (unsigned int) long_count; ++i) + { + if (long_temp & (1L << (long) i)) + { + charptr_temp[long_index >> 3L] |= + (1L << (long_index & 7L)); + } + else + { + charptr_temp[long_index >> 3L] &= + ~ (unsigned int) (1L << (long_index & 7L)); + } + ++long_index; + } + } + } + } + break; + + case 0x50: /* JMPZ */ + /* + * Pop stack and branch if zero + * ...argument 0 is address + * ...stack 0 is condition value + */ + IF_CHECK_STACK(1) + { + if (stack[--stack_ptr] == 0) + { + pc = args[0] + code_section; + CHECK_PC; + } + } + break; + + case 0x51: /* DS */ + case 0x52: /* IS */ + /* + * DRSCAN + * IRSCAN + * ...argument 0 is scan data variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + IF_CHECK_STACK(2) + { + long_index = stack[--stack_ptr]; + long_count = stack[--stack_ptr]; + + reverse = 0; + + if (version > 0) + { + /* stack 0 = array right index */ + /* stack 1 = array left index */ + /* stack 2 = count */ + long_temp = long_count; + long_count = stack[--stack_ptr]; + + if (long_index > long_temp) + { + reverse = 1; + long_index = long_temp; + } + } + +#if PORT==DOS + if (((long_index & 0xFFFF0000) == 0) && + ((long_count & 0xFFFF0000) == 0)) + { + variable_id = (unsigned int) args[0]; + if ((attributes[variable_id] & 0x1e) == 0x0e) + { + /* initialized compressed Boolean array */ + jbi_uncompress_page(variable_id, + (int) (long_index >> 16), version); + long_index &= 0x0000ffff; + charptr_temp = jbi_aca_out_buffer; + } + else + { + charptr_temp = (unsigned char *) variables[variable_id]; + } + + if (reverse) + { + /* allocate a buffer and reverse the data order */ + charptr_temp2 = charptr_temp; + charptr_temp = jbi_malloc((unsigned int) + ((long_count >> 3L) + 1L)); + + if (charptr_temp == NULL) + { + status = JBIC_OUT_OF_MEMORY; + break; + } + else + { + long_temp = long_index + long_count - 1; + long_index2 = 0; + while (long_index2 < long_count) + { + if (charptr_temp2[long_temp >> 3] & + (1 << (long_temp & 7))) + { + charptr_temp[long_index2 >> 3] |= + (1 << (long_index2 & 7)); + } + else + { + charptr_temp[long_index2 >> 3] &= + ~(1 << (long_index2 & 7)); + } + + --long_temp; + ++long_index2; + } + } + } + + if (opcode == 0x51) /* DS */ + { + status = jbi_do_drscan((unsigned int) long_count, + charptr_temp, (unsigned long) long_index); + } + else /* IS */ + { + status = jbi_do_irscan((unsigned int) long_count, + charptr_temp, (unsigned int) long_index); + } + + if (reverse) jbi_free(charptr_temp); + } + else if ((opcode == 0x51) && !reverse) + { + status = jbi_do_drscan_multi_page( + (unsigned int) args[0], + (unsigned long) long_count, + (unsigned long) long_index, version); + } + else + { + /* reverse multi-page scans are not supported */ + /* multi-page IR scans are not supported */ + status = JBIC_BOUNDS_ERROR; + } +#else + charptr_temp = (unsigned char *) variables[args[0]]; + + if (reverse) + { + /* allocate a buffer and reverse the data order */ + charptr_temp2 = charptr_temp; + charptr_temp = jbi_malloc((long_count >> 3) + 1); + if (charptr_temp == NULL) + { + status = JBIC_OUT_OF_MEMORY; + break; + } + else + { + long_temp = long_index + long_count - 1; + long_index2 = 0; + while (long_index2 < long_count) + { + if (charptr_temp2[long_temp >> 3] & + (1 << (long_temp & 7))) + { + charptr_temp[long_index2 >> 3] |= + (1 << (long_index2 & 7)); + } + else + { + charptr_temp[long_index2 >> 3] &= + ~(1 << (long_index2 & 7)); + } + + --long_temp; + ++long_index2; + } + } + } + + if (opcode == 0x51) /* DS */ + { + status = jbi_do_drscan((unsigned int) long_count, + charptr_temp, (unsigned long) long_index); + } + else /* IS */ + { + status = jbi_do_irscan((unsigned int) long_count, + charptr_temp, (unsigned int) long_index); + } +#endif + + if (reverse && (charptr_temp != NULL)) + { + jbi_free(charptr_temp); + } + } + break; + + case 0x53: /* DPRA */ + /* + * DRPRE with array data + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + IF_CHECK_STACK(2) + { + index = (unsigned int) stack[--stack_ptr]; + count = (unsigned int) stack[--stack_ptr]; + + if (version > 0) + { + /* stack 0 = array right index */ + /* stack 1 = array left index */ + count = 1 + count - index; + } + + charptr_temp = (unsigned char *) variables[args[0]]; + status = jbi_set_dr_preamble(count, index, charptr_temp); + } + break; + + case 0x54: /* DPOA */ + /* + * DRPOST with array data + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + IF_CHECK_STACK(2) + { + index = (unsigned int) stack[--stack_ptr]; + count = (unsigned int) stack[--stack_ptr]; + + if (version > 0) + { + /* stack 0 = array right index */ + /* stack 1 = array left index */ + count = 1 + count - index; + } + + charptr_temp = (unsigned char *) variables[args[0]]; + status = jbi_set_dr_postamble(count, index, charptr_temp); + } + break; + + case 0x55: /* IPRA */ + /* + * IRPRE with array data + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + IF_CHECK_STACK(2) + { + index = (unsigned int) stack[--stack_ptr]; + count = (unsigned int) stack[--stack_ptr]; + + if (version > 0) + { + /* stack 0 = array right index */ + /* stack 1 = array left index */ + count = 1 + count - index; + } + + charptr_temp = (unsigned char *) variables[args[0]]; + status = jbi_set_ir_preamble(count, index, charptr_temp); + } + break; + + case 0x56: /* IPOA */ + /* + * IRPOST with array data + * ...argument 0 is variable ID + * ...stack 0 is array index + * ...stack 1 is count + */ + IF_CHECK_STACK(2) + { + index = (unsigned int) stack[--stack_ptr]; + count = (unsigned int) stack[--stack_ptr]; + + if (version > 0) + { + /* stack 0 = array right index */ + /* stack 1 = array left index */ + count = 1 + count - index; + } + + charptr_temp = (unsigned char *) variables[args[0]]; + status = jbi_set_ir_postamble(count, index, charptr_temp); + } + break; + + case 0x57: /* EXPT */ + /* + * EXPORT + * ...argument 0 is string ID + * ...stack 0 is integer expression + */ + IF_CHECK_STACK(1) + { +#if PORT==DOS + name_id = args[0]; + for (j = 0; j < 32; ++j) + { + name[j] = GET_BYTE(string_table + name_id + j); + } + name[32] = '\0'; +#else + name = (char *) &program[string_table + args[0]]; +#endif + long_temp = stack[--stack_ptr]; + jbi_export_integer(name, long_temp); + } + break; + + case 0x58: /* PSHE */ + /* + * Push integer array element + * ...argument 0 is variable ID + * ...stack 0 is array index + */ + IF_CHECK_STACK(1) + { + variable_id = (unsigned int) args[0]; + index = (unsigned int) stack[stack_ptr - 1]; + + /* check variable type */ + if ((attributes[variable_id] & 0x1f) == 0x19) + { + /* writable integer array */ + longptr_temp = (long *) variables[variable_id]; + stack[stack_ptr - 1] = longptr_temp[index]; + } + else if ((attributes[variable_id] & 0x1f) == 0x1c) + { + /* read-only integer array */ + long_temp = variables[variable_id] + (4L * index); + stack[stack_ptr - 1] = GET_DWORD(long_temp); + } + else + { + status = JBIC_BOUNDS_ERROR; + } + } + break; + + case 0x59: /* PSHA */ + /* + * Push Boolean array + * ...argument 0 is variable ID + * ...stack 0 is count + * ...stack 1 is array index + */ + IF_CHECK_STACK(2) + { + variable_id = (unsigned int) args[0]; + + /* check that variable is a Boolean array */ + if ((attributes[variable_id] & 0x18) != 0x08) + { + status = JBIC_BOUNDS_ERROR; + } + else + { + charptr_temp = (unsigned char *) variables[variable_id]; + + /* pop the count (number of bits to copy) */ + count = (unsigned int) stack[--stack_ptr]; + + /* pop the array index */ + index = (unsigned int) stack[stack_ptr - 1]; + + if (version > 0) + { + /* stack 0 = array right index */ + /* stack 1 = array left index */ + count = 1 + count - index; + } + + if ((count < 1) || (count > 32)) + { + status = JBIC_BOUNDS_ERROR; + } + else + { +#if PORT==DOS + if ((attributes[variable_id] & 0x1e) == 0x0e) + { + /* initialized compressed Boolean array */ + jbi_uncompress_page(variable_id, + (int) (stack[stack_ptr - 1] >> 16), version); + charptr_temp = jbi_aca_out_buffer; + } +#endif + long_temp = 0L; + + for (i = 0; i < count; ++i) + { + if (charptr_temp[(i + index) >> 3] & + (1 << ((i + index) & 7))) + { + long_temp |= (1L << i); + } + } + + stack[stack_ptr - 1] = long_temp; + } + } + } + break; + + case 0x5A: /* DYNA */ + /* + * Dynamically change size of array + * ...argument 0 is variable ID + * ...stack 0 is new size + */ + IF_CHECK_STACK(1) + { + variable_id = (unsigned int) args[0]; + long_temp = stack[--stack_ptr]; + + if (long_temp > variable_size[variable_id]) + { + variable_size[variable_id] = long_temp; + + if (attributes[variable_id] & 0x10) + { + /* allocate integer array */ + long_temp *= 4; + } + else + { + /* allocate Boolean array */ + long_temp = (long_temp + 7) >> 3; + } + + /* + * If the buffer was previously allocated, free it + */ + if ((attributes[variable_id] & 0x80) && + (variables[variable_id] != NULL)) + { + jbi_free((void *) variables[variable_id]); + variables[variable_id] = NULL; + } + + /* + * Allocate a new buffer of the requested size + */ + variables[variable_id] = (long) + jbi_malloc((unsigned int) long_temp); + + if (variables[variable_id] == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + /* + * Set the attribute bit to indicate that this buffer + * was dynamically allocated and should be freed later + */ + attributes[variable_id] |= 0x80; + + /* zero out memory */ + count = (unsigned int) + ((variable_size[variable_id] + 7L) / 8L); + charptr_temp = (unsigned char *) + (variables[variable_id]); + for (index = 0; index < count; ++index) + { + charptr_temp[index] = 0; + } + } + } + } + break; + + case 0x5B: /* EXPR */ + bad_opcode = 1; + break; + + case 0x5C: /* EXPV */ + /* + * Export Boolean array + * ...argument 0 is string ID + * ...stack 0 is variable ID + * ...stack 1 is array right index + * ...stack 2 is array left index + */ + IF_CHECK_STACK(3) + { + if (version == 0) + { + /* EXPV is not supported in JBC 1.0 */ + bad_opcode = 1; + break; + } +#if PORT==DOS + name_id = args[0]; + for (j = 0; j < 32; ++j) + { + name[j] = GET_BYTE(string_table + name_id + j); + } + name[32] = '\0'; +#else + name = (char *) &program[string_table + args[0]]; +#endif + variable_id = (unsigned int) stack[--stack_ptr]; + long_index = stack[--stack_ptr]; /* right index */ + long_index2 = stack[--stack_ptr]; /* left index */ + + if (long_index > long_index2) + { + /* reverse indices not supported */ + status = JBIC_BOUNDS_ERROR; + break; + } + + long_count = 1 + long_index2 - long_index; + + charptr_temp = (unsigned char *) variables[variable_id]; + charptr_temp2 = NULL; + +#if PORT==DOS + if ((attributes[variable_id] & 0x1e) == 0x0e) + { + /* initialized compressed Boolean array */ + jbi_uncompress_page(variable_id, + (int) (long_index >> 16), version); + charptr_temp = jbi_aca_out_buffer; + long_index &= 0x0000FFFF; + } +#endif + + if ((long_index & 7L) != 0) + { + charptr_temp2 = jbi_malloc((unsigned int) + ((long_count + 7L) / 8L)); + if (charptr_temp2 == NULL) + { + status = JBIC_OUT_OF_MEMORY; + break; + } + else + { + long k = long_index; + for (i = 0; i < (unsigned int) long_count; ++i) + { + if (charptr_temp[k >> 3] & (1 << (k & 7))) + { + charptr_temp2[i >> 3] |= (1 << (i & 7)); + } + else + { + charptr_temp2[i >> 3] &= ~(1 << (i & 7)); + } + + ++k; + } + charptr_temp = charptr_temp2; + } + } + else if (long_index != 0) + { + charptr_temp = &charptr_temp[long_index >> 3]; + } + + jbi_export_boolean_array(name, charptr_temp, long_count); + + /* free allocated buffer */ + if (((long_index & 7L) != 0) && (charptr_temp2 != NULL)) + { + jbi_free(charptr_temp2); + } + } + break; + + case 0x80: /* COPY */ + /* + * Array copy + * ...argument 0 is dest ID + * ...argument 1 is source ID + * ...stack 0 is count + * ...stack 1 is dest index + * ...stack 2 is source index + */ + IF_CHECK_STACK(3) + { + long copy_count = stack[--stack_ptr]; + long copy_index = stack[--stack_ptr]; + long copy_index2 = stack[--stack_ptr]; + long destleft; + long src_count; + long dest_count; + int src_reverse = 0; + int dest_reverse = 0; + + reverse = 0; + + if (version > 0) + { + /* stack 0 = source right index */ + /* stack 1 = source left index */ + /* stack 2 = destination right index */ + /* stack 3 = destination left index */ + destleft = stack[--stack_ptr]; + + if (copy_count > copy_index) + { + src_reverse = 1; + reverse = 1; + src_count = 1 + copy_count - copy_index; + /* copy_index = source start index */ + } + else + { + src_count = 1 + copy_index - copy_count; + copy_index = copy_count; /* source start index */ + } + + if (copy_index2 > destleft) + { + dest_reverse = 1; + reverse = !reverse; + dest_count = 1 + copy_index2 - destleft; + copy_index2 = destleft; /* destination start index */ + } + else + { + dest_count = 1 + destleft - copy_index2; + /* copy_index2 = destination start index */ + } + + copy_count = (src_count < dest_count) ? src_count : dest_count; + + if ((src_reverse || dest_reverse) && + (src_count != dest_count)) + { + /* If either the source or destination is reversed, */ + /* we can't tolerate a length mismatch, because we */ + /* "left justify" the arrays when copying. This */ + /* won't work correctly with reversed arrays. */ + status = JBIC_BOUNDS_ERROR; + } + } + + count = (unsigned int) copy_count; + index = (unsigned int) copy_index; + index2 = (unsigned int) copy_index2; + + /* + * If destination is a read-only array, allocate a buffer + * and convert it to a writable array + */ + variable_id = (unsigned int) args[1]; + if ((version > 0) && ((attributes[variable_id] & 0x9c) == 0x0c)) + { + /* + * Allocate a writable buffer for this array + */ + long_temp = (variable_size[variable_id] + 7L) >> 3L; + charptr_temp2 = (unsigned char *) variables[variable_id]; + charptr_temp = jbi_malloc((unsigned int) long_temp); + variables[variable_id] = (long) charptr_temp; + + if (variables[variable_id] == NULL) + { + status = JBIC_OUT_OF_MEMORY; + break; + } + else + { + /* zero the buffer */ + for (long_index = 0L; + long_index < long_temp; + ++long_index) + { + charptr_temp[long_index] = 0; + } + + /* copy previous contents into buffer */ + for (long_index = 0L; + long_index < variable_size[variable_id]; + ++long_index) + { +#if PORT==DOS + if ((attributes[variable_id] & 0x02) && + ((long_index & 0x0000FFFF) == 0L)) + { + /* initialized compressed Boolean array */ + jbi_uncompress_page(variable_id, + (int) (long_index >> 16), version); + charptr_temp = jbi_aca_out_buffer; + long_index2 = long_index & 0xFFFF; + } +#else + long_index2 = long_index; +#endif + + if (charptr_temp2[long_index2 >> 3] & + (1 << (long_index2 & 7))) + { + charptr_temp[long_index >> 3] |= + (1 << (long_index & 7)); + } + } + + /* set bit 7 - buffer was dynamically allocated */ + attributes[variable_id] |= 0x80; + + /* clear bit 2 - variable is writable */ + attributes[variable_id] &= ~0x04; + attributes[variable_id] |= 0x01; + } + } + +#if PORT==DOS + /* for 16-bit version, allow writing in allocated buffers */ + if ((version > 0) && + ((attributes[variable_id] & 0x9c) == 0x8c)) + { + attributes[variable_id] &= ~0x04; + attributes[variable_id] |= 0x01; + } +#endif + + charptr_temp = (unsigned char *) variables[args[1]]; + charptr_temp2 = (unsigned char *) variables[args[0]]; + +#if PORT==DOS + variable_id = (unsigned int) args[0]; + if ((attributes[variable_id] & 0x1e) == 0x0e) + { + /* initialized compressed Boolean array */ + jbi_uncompress_page(variable_id, + (int) (copy_index >> 16), version); + charptr_temp2 = jbi_aca_out_buffer; + } +#endif + + /* check that destination is a writable Boolean array */ + if ((attributes[args[1]] & 0x1c) != 0x08) + { + status = JBIC_BOUNDS_ERROR; + break; + } + + if (count < 1) + { + status = JBIC_BOUNDS_ERROR; + } + else + { + if (reverse) + { + index2 += (count - 1); + } + + for (i = 0; i < count; ++i) + { + if (charptr_temp2[index >> 3] & (1 << (index & 7))) + { + charptr_temp[index2 >> 3] |= (1 << (index2 & 7)); + } + else + { + charptr_temp[index2 >> 3] &= + ~(unsigned int) (1 << (index2 & 7)); + } + ++index; + if (reverse) --index2; else ++index2; + } + } + } + break; + + case 0x81: /* REVA */ + /* + * ARRAY COPY reversing bit order + * ...argument 0 is dest ID + * ...argument 1 is source ID + * ...stack 0 is dest index + * ...stack 1 is source index + * ...stack 2 is count + */ + bad_opcode = 1; + break; + + case 0x82: /* DSC */ + case 0x83: /* ISC */ + /* + * DRSCAN with capture + * IRSCAN with capture + * ...argument 0 is scan data variable ID + * ...argument 1 is capture variable ID + * ...stack 0 is capture index + * ...stack 1 is scan data index + * ...stack 2 is count + */ + IF_CHECK_STACK(3) + { + long scan_right, scan_left; + long capture_count = 0; + long scan_count = 0; + long capture_index = stack[--stack_ptr]; + long scan_index = stack[--stack_ptr]; + if (version > 0) + { + /* stack 0 = capture right index */ + /* stack 1 = capture left index */ + /* stack 2 = scan right index */ + /* stack 3 = scan left index */ + /* stack 4 = count */ + scan_right = stack[--stack_ptr]; + scan_left = stack[--stack_ptr]; + capture_count = 1 + scan_index - capture_index; + scan_count = 1 + scan_left - scan_right; + scan_index = scan_right; + } + long_count = stack[--stack_ptr]; + + /* + * If capture array is read-only, allocate a buffer + * and convert it to a writable array + */ + variable_id = (unsigned int) args[1]; + if ((version > 0) && ((attributes[variable_id] & 0x9c) == 0x0c)) + { + /* + * Allocate a writable buffer for this array + */ + long_temp = (variable_size[variable_id] + 7L) >> 3L; + charptr_temp2 = (unsigned char *) variables[variable_id]; + charptr_temp = jbi_malloc((unsigned int) long_temp); + variables[variable_id] = (long) charptr_temp; + + if (variables[variable_id] == NULL) + { + status = JBIC_OUT_OF_MEMORY; + break; + } + else + { + /* zero the buffer */ + for (long_index = 0L; + long_index < long_temp; + ++long_index) + { + charptr_temp[long_index] = 0; + } + + /* copy previous contents into buffer */ + for (long_index = 0L; + long_index < variable_size[variable_id]; + ++long_index) + { +#if PORT==DOS + if ((attributes[variable_id] & 0x02) && + ((long_index & 0x0000FFFF) == 0L)) + { + /* initialized compressed Boolean array */ + jbi_uncompress_page(variable_id, + (int) (long_index >> 16), version); + charptr_temp = jbi_aca_out_buffer; + long_index2 = long_index & 0xFFFF; + } +#else + long_index2 = long_index; +#endif + + if (charptr_temp2[long_index2 >> 3] & + (1 << (long_index2 & 7))) + { + charptr_temp[long_index >> 3] |= + (1 << (long_index & 7)); + } + } + + /* set bit 7 - buffer was dynamically allocated */ + attributes[variable_id] |= 0x80; + + /* clear bit 2 - variable is writable */ + attributes[variable_id] &= ~0x04; + attributes[variable_id] |= 0x01; + } + } + +#if PORT==DOS + /* for 16-bit version, allow writing in allocated buffers */ + if ((version > 0) && + ((attributes[variable_id] & 0x9c) == 0x8c)) + { + attributes[variable_id] &= ~0x04; + attributes[variable_id] |= 0x01; + } +#endif + + charptr_temp = (unsigned char *) variables[args[0]]; + charptr_temp2 = (unsigned char *) variables[args[1]]; + +#if PORT==DOS + variable_id = (unsigned int) args[0]; + if ((attributes[variable_id] & 0x1e) == 0x0e) + { + /* initialized compressed Boolean array */ + jbi_uncompress_page(variable_id, + (int) (scan_index >> 16), version); + scan_index &= 0x0000ffff; + charptr_temp = jbi_aca_out_buffer; + } +#endif + + if ((version > 0) && + ((long_count > capture_count) || (long_count > scan_count))) + { + status = JBIC_BOUNDS_ERROR; + } + + /* check that capture array is a writable Boolean array */ + if ((attributes[args[1]] & 0x1c) != 0x08) + { + status = JBIC_BOUNDS_ERROR; + } + + if (status == JBIC_SUCCESS) + { + if (opcode == 0x82) /* DSC */ + { + status = jbi_swap_dr((unsigned int) long_count, + charptr_temp, (unsigned long) scan_index, + charptr_temp2, (unsigned int) capture_index); + } + else /* ISC */ + { + status = jbi_swap_ir((unsigned int) long_count, + charptr_temp, (unsigned int) scan_index, + charptr_temp2, (unsigned int) capture_index); + } + } + } + break; + + case 0x84: /* WAIT */ + /* + * WAIT + * ...argument 0 is wait state + * ...argument 1 is end state + * ...stack 0 is cycles + * ...stack 1 is microseconds + */ + IF_CHECK_STACK(2) + { + long_temp = stack[--stack_ptr]; + + if (long_temp != 0L) + { + status = jbi_do_wait_cycles(long_temp, (unsigned int) args[0]); + } + + long_temp = stack[--stack_ptr]; + + if ((status == JBIC_SUCCESS) && (long_temp != 0L)) + { + status = jbi_do_wait_microseconds(long_temp, (unsigned int) args[0]); + } + + if ((status == JBIC_SUCCESS) && (args[1] != args[0])) + { + status = jbi_goto_jtag_state((unsigned int) args[1]); + } + + if (version > 0) + { + --stack_ptr; /* throw away MAX cycles */ + --stack_ptr; /* throw away MAX microseconds */ + } + } + break; + + case 0x85: /* VS */ + /* + * VECTOR + * ...argument 0 is dir data variable ID + * ...argument 1 is scan data variable ID + * ...stack 0 is dir array index + * ...stack 1 is scan array index + * ...stack 2 is count + */ + bad_opcode = 1; + break; + + case 0xC0: /* CMPA */ + /* + * Array compare + * ...argument 0 is source 1 ID + * ...argument 1 is source 2 ID + * ...argument 2 is mask ID + * ...stack 0 is source 1 index + * ...stack 1 is source 2 index + * ...stack 2 is mask index + * ...stack 3 is count + */ + IF_CHECK_STACK(4) + { + long a, b; + unsigned char *source1 = (unsigned char *) variables[args[0]]; + unsigned char *source2 = (unsigned char *) variables[args[1]]; + unsigned char *mask = (unsigned char *) variables[args[2]]; + unsigned long index1 = stack[--stack_ptr]; + unsigned long index2 = stack[--stack_ptr]; + unsigned long mask_index = stack[--stack_ptr]; + long_count = stack[--stack_ptr]; + + if (version > 0) + { + /* stack 0 = source 1 right index */ + /* stack 1 = source 1 left index */ + /* stack 2 = source 2 right index */ + /* stack 3 = source 2 left index */ + /* stack 4 = mask right index */ + /* stack 5 = mask left index */ + long mask_right = stack[--stack_ptr]; + long mask_left = stack[--stack_ptr]; + a = 1 + index2 - index1; /* source 1 count */ + b = 1 + long_count - mask_index; /* source 2 count */ + a = (a < b) ? a : b; + b = 1 + mask_left - mask_right; /* mask count */ + a = (a < b) ? a : b; + index2 = mask_index; /* source 2 start index */ + mask_index = mask_right; /* mask start index */ + long_count = a; + } + + long_temp = 1L; + + if (long_count < 1) + { + status = JBIC_BOUNDS_ERROR; + } + else + { +#if PORT==DOS + variable_id = (unsigned int) args[0]; + if ((attributes[variable_id] & 0x1e) == 0x0e) + { + jbi_uncompress_page(variable_id, + (int) (index1 >> 16), version); + index1 &= 0x0000ffff; + source1 = jbi_aca_out_buffer; + } + + variable_id = (unsigned int) args[1]; + if ((attributes[variable_id] & 0x1e) == 0x0e) + { + jbi_uncompress_page(variable_id, + (int) (index2 >> 16), version); + index2 &= 0x0000ffff; + source2 = jbi_aca_out_buffer; + } +#endif + count = (unsigned int) long_count; + + for (i = 0; i < count; ++i) + { + if (mask[mask_index >> 3] & (1 << (mask_index & 7))) + { + a = source1[index1 >> 3] & (1 << (index1 & 7)) + ? 1 : 0; + b = source2[index2 >> 3] & (1 << (index2 & 7)) + ? 1 : 0; + + if (a != b) long_temp = 0L; /* failure */ + } + ++index1; + ++index2; + ++mask_index; + } + } + + stack[stack_ptr++] = long_temp; + } + break; + + case 0xC1: /* VSC */ + /* + * VECTOR with capture + * ...argument 0 is dir data variable ID + * ...argument 1 is scan data variable ID + * ...argument 2 is capture variable ID + * ...stack 0 is capture index + * ...stack 1 is scan data index + * ...stack 2 is dir data index + * ...stack 3 is count + */ + bad_opcode = 1; + break; + + default: + /* + * Unrecognized opcode -- ERROR! + */ + bad_opcode = 1; + break; + } + + if (bad_opcode) + { + status = JBIC_ILLEGAL_OPCODE; + } + + if ((stack_ptr < 0) || (stack_ptr >= JBI_STACK_SIZE)) + { + status = JBIC_STACK_OVERFLOW; + } + + if (status != JBIC_SUCCESS) + { + done = 1; + *error_address = (long) (opcode_address - code_section); + } + } + + jbi_free_jtag_padding_buffers(reset_jtag); + + /* + * Free all dynamically allocated arrays + */ + if ((attributes != NULL) && (variables != NULL)) + { + for (i = 0; i < (unsigned int) symbol_count; ++i) + { + if ((attributes[i] & 0x80) && (variables[i] != NULL)) + { + jbi_free((void *) variables[i]); + } + } + } + + if (variables != NULL) jbi_free(variables); + + if (variable_size != NULL) jbi_free(variable_size); + + if (attributes != NULL) jbi_free(attributes); + + if (proc_attributes != NULL) jbi_free(proc_attributes); + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_get_note +( + PROGRAM_PTR program, + long program_size, + long *offset, + char *key, + char *value, + int length +) + +/* */ +/* Description: Gets key and value of NOTE fields in the JBC file. */ +/* Can be called in two modes: if offset pointer is NULL, */ +/* then the function searches for note fields which match */ +/* the key string provided. If offset is not NULL, then */ +/* the function finds the next note field of any key, */ +/* starting at the offset specified by the offset pointer. */ +/* */ +/* Returns: JBIC_SUCCESS for success, else appropriate error code */ +/* */ +/****************************************************************************/ +{ + JBI_RETURN_TYPE status = JBIC_UNEXPECTED_END; + unsigned long note_strings = 0L; + unsigned long note_table = 0L; + unsigned long note_count = 0L; + unsigned long first_word = 0L; + int version = 0; + int delta = 0; + char *key_ptr; + char *value_ptr; + int i; + +#if PORT==DOS + int count = 0; + int done = 0; + long long_index = 0; + char key_buffer[256]; + char value_buffer[256]; + + jbi_program = program; +#endif + + /* + * Read header information + */ + if (program_size > 52L) + { + first_word = GET_DWORD(0); + version = (int) (first_word & 1L); + delta = version * 8; + + note_strings = GET_DWORD(8 + delta); + note_table = GET_DWORD(12 + delta); + note_count = GET_DWORD(44 + (2 * delta)); + } + + if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) + { + status = JBIC_IO_ERROR; + } + else if (note_count > 0L) + { + if (offset == NULL) + { + /* + * We will search for the first note with a specific key, and + * return only the value + */ + for (i = 0; (i < (int) note_count) && (status != JBIC_SUCCESS); ++i) + { +#if PORT==DOS + done = 0; + count = 0; + long_index = note_strings + GET_DWORD(note_table + (8 * i)); + while ((count < 255) && !done) + { + key_buffer[count] = GET_BYTE(long_index); + if (key_buffer[count] == '\0') done = 1; + ++long_index; + ++count; + } + key_buffer[255] = '\0'; + key_ptr = key_buffer; +#else + key_ptr = (char *) &program[note_strings + + GET_DWORD(note_table + (8 * i))]; +#endif + if ((key != NULL) && (jbi_stricmp(key, key_ptr) == 0)) + { + status = JBIC_SUCCESS; + +#if PORT==DOS + done = 0; + count = 0; + long_index = note_strings + GET_DWORD(note_table + (8 * i) + 4); + while ((count < 255) && !done) + { + value_buffer[count] = GET_BYTE(long_index); + if (value_buffer[count] == '\0') done = 1; + ++long_index; + ++count; + } + value_buffer[255] = '\0'; + value_ptr = value_buffer; +#else + value_ptr = (char *) &program[note_strings + + GET_DWORD(note_table + (8 * i) + 4)]; +#endif + + if (value != NULL) + { + jbi_strncpy(value, value_ptr, length); + } + } + } + } + else + { + /* + * We will search for the next note, regardless of the key, and + * return both the value and the key + */ + + i = (int) *offset; + + if ((i >= 0) && (i < (int) note_count)) + { + status = JBIC_SUCCESS; + + if (key != NULL) + { +#if PORT==DOS + done = 0; + count = 0; + long_index = note_strings + + GET_DWORD(note_table + (8 * i)); + + while ((count < length) && !done) + { + key[count] = GET_BYTE(long_index); + if (key[count] == '\0') done = 1; + ++long_index; + ++count; + } +#else + jbi_strncpy(key, (char *) &program[note_strings + + GET_DWORD(note_table + (8 * i))], length); +#endif + } + + if (value != NULL) + { +#if PORT==DOS + done = 0; + count = 0; + long_index = note_strings + + GET_DWORD(note_table + (8 * i) + 4); + + while ((count < length) && !done) + { + value[count] = GET_BYTE(long_index); + if (value[count] == '\0') done = 1; + ++long_index; + ++count; + } +#else + jbi_strncpy(value, (char *) &program[note_strings + + GET_DWORD(note_table + (8 * i) + 4)], length); +#endif + } + + *offset = i + 1; + } + } + } + + return (status); +} + +/****************************************************************************/ +/* */ + +JBI_RETURN_TYPE jbi_check_crc +( + PROGRAM_PTR program, + long program_size, + unsigned short *expected_crc, + unsigned short *actual_crc +) + +/* */ +/* Description: This function reads the entire input file and computes */ +/* the CRC of everything up to the CRC field. */ +/* */ +/* Returns: JBIC_SUCCESS for success, JBIC_CRC_ERROR for failure */ +/* */ +/****************************************************************************/ +{ + JBI_RETURN_TYPE status = JBIC_SUCCESS; + unsigned short local_expected, local_actual, shift_reg = 0xffff; + int bit, feedback; + unsigned char databyte; + unsigned long i; + unsigned long crc_section = 0L; + unsigned long first_word = 0L; + int version = 0; + int delta = 0; + +#if PORT==DOS + jbi_program = program; +#endif + + if (program_size > 52L) + { + first_word = GET_DWORD(0); + version = (int) (first_word & 1L); + delta = version * 8; + + crc_section = GET_DWORD(32 + delta); + } + + if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) + { + status = JBIC_IO_ERROR; + } + + if (crc_section >= (unsigned long) program_size) + { + status = JBIC_IO_ERROR; + } + + if (status == JBIC_SUCCESS) + { + local_expected = (unsigned short) GET_WORD(crc_section); + if (expected_crc != NULL) *expected_crc = local_expected; + + for (i = 0; i < crc_section; ++i) + { + databyte = GET_BYTE(i); + for (bit = 0; bit < 8; bit++) /* compute for each bit */ + { + feedback = (databyte ^ shift_reg) & 0x01; + shift_reg >>= 1; /* shift the shift register */ + if (feedback) shift_reg ^= 0x8408; /* invert selected bits */ + databyte >>= 1; /* get the next bit of input_byte */ + } + } + + local_actual = (unsigned short) ~shift_reg; + if (actual_crc != NULL) *actual_crc = local_actual; + + if (local_expected != local_actual) + { + status = JBIC_CRC_ERROR; + } + } + + return (status); +} + +JBI_RETURN_TYPE jbi_get_file_info +( + PROGRAM_PTR program, + long program_size, + int *format_version, + int *action_count, + int *procedure_count +) +{ + JBI_RETURN_TYPE status = JBIC_IO_ERROR; + unsigned long first_word = 0; + int version = 0; + +#if PORT==DOS + jbi_program = program; +#endif + + /* + * Read header information + */ + if (program_size > 52L) + { + first_word = GET_DWORD(0); + + if ((first_word == 0x4A414D00L) || (first_word == 0x4A414D01L)) + { + status = JBIC_SUCCESS; + + version = (int) (first_word & 1L); + *format_version = version + 1; + + if (version > 0) + { + *action_count = (int) GET_DWORD(48); + *procedure_count = (int) GET_DWORD(52); + } + } + + } + + return (status); +} + +JBI_RETURN_TYPE jbi_get_action_info +( + PROGRAM_PTR program, + long program_size, + int index, + char **name, + char **description, + JBI_PROCINFO **procedure_list +) +{ + JBI_RETURN_TYPE status = JBIC_IO_ERROR; + JBI_PROCINFO *procptr = NULL; + JBI_PROCINFO *tmpptr = NULL; + unsigned long first_word = 0L; + unsigned long action_table = 0L; + unsigned long proc_table = 0L; + unsigned long string_table = 0L; + unsigned long note_strings = 0L; + unsigned long action_count = 0L; + unsigned long proc_count = 0L; + unsigned long act_name_id = 0L; + unsigned long act_desc_id = 0L; + unsigned long act_proc_id = 0L; + unsigned long act_proc_name = 0L; + unsigned char act_proc_attribute = 0; + +#if PORT==DOS + int i, length; + jbi_program = program; +#endif + + /* + * Read header information + */ + if (program_size > 52L) + { + first_word = GET_DWORD(0); + + if (first_word == 0x4A414D01L) + { + action_table = GET_DWORD(4); + proc_table = GET_DWORD(8); + string_table = GET_DWORD(12); + note_strings = GET_DWORD(16); + action_count = GET_DWORD(48); + proc_count = GET_DWORD(52); + + if (index < (int) action_count) + { + act_name_id = GET_DWORD(action_table + (12 * index)); + act_desc_id = GET_DWORD(action_table + (12 * index) + 4); + act_proc_id = GET_DWORD(action_table + (12 * index) + 8); + +#if PORT==DOS + length = 0; + while (GET_BYTE(string_table + act_name_id + length) != 0) ++length; + *name = jbi_malloc(length + 1); + if (*name == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + for (i = 0; i < length; ++i) + { + (*name)[i] = GET_BYTE(string_table + act_name_id + i); + } + (*name)[length] = '\0'; + } +#else + *name = (char *) &program[string_table + act_name_id]; +#endif + + if (act_desc_id < (note_strings - string_table)) + { +#if PORT==DOS + length = 0; + while (GET_BYTE(string_table + act_desc_id + length) != 0) ++length; + *description = jbi_malloc(length + 1); + if (*description == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + for (i = 0; i < length; ++i) + { + (*description)[i] = GET_BYTE(string_table + act_desc_id + i); + } + (*description)[length] = '\0'; + } +#else + *description = (char *) &program[string_table + act_desc_id]; +#endif + } + + do + { + act_proc_name = GET_DWORD(proc_table + (13 * act_proc_id)); + act_proc_attribute = (unsigned char) + (GET_BYTE(proc_table + (13 * act_proc_id) + 8) & 0x03); + + procptr = (JBI_PROCINFO *) jbi_malloc(sizeof(JBI_PROCINFO)); + + if (procptr == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { +#if PORT==DOS + length = 0; + while (GET_BYTE(string_table + act_proc_name + length) != 0) ++length; + procptr->name = jbi_malloc(length + 1); + if (procptr->name == NULL) + { + status = JBIC_OUT_OF_MEMORY; + } + else + { + for (i = 0; i < length; ++i) + { + procptr->name[i] = + GET_BYTE(string_table + act_proc_name + i); + } + procptr->name[length] = '\0'; + } +#else + procptr->name = (char *) + &program[string_table + act_proc_name]; +#endif + procptr->attributes = act_proc_attribute; + procptr->next = NULL; + + /* add record to end of linked list */ + if (*procedure_list == NULL) + { + *procedure_list = procptr; + } + else + { + tmpptr = *procedure_list; + while (tmpptr->next != NULL) tmpptr = tmpptr->next; + tmpptr->next = procptr; + } + } + + act_proc_id = + GET_DWORD(proc_table + (13 * act_proc_id) + 4); + } + while ((act_proc_id != 0) && (act_proc_id < proc_count)); + } + } + + } + + return (status); +} diff --git a/common/recipes-utils/jbi/files/code/jbiport.h b/common/recipes-utils/jbi/files/code/jbiport.h new file mode 100644 index 0000000..885e84d --- /dev/null +++ b/common/recipes-utils/jbi/files/code/jbiport.h @@ -0,0 +1,45 @@ +/****************************************************************************/ +/* */ +/* Module: jbiport.h */ +/* */ +/* Copyright (C) Altera Corporation 2000-2001 */ +/* */ +/* Description: Defines porting macros */ +/* */ +/****************************************************************************/ + +#ifndef INC_JBIPORT_H +#define INC_JBIPORT_H + +/* +* PORT defines the target platform: DOS, WINDOWS, UNIX, or EMBEDDED +* +* PORT = DOS means a 16-bit DOS console-mode application +* +* PORT = WINDOWS means a 32-bit WIN32 console-mode application for +* Windows 95, 98, 2000, ME or NT. On NT this will use the +* DeviceIoControl() API to access the Parallel Port. +* +* PORT = UNIX means any UNIX system. BitBlaster access is support via +* the standard ANSI system calls open(), read(), write(). +* The ByteBlaster is not supported. +* +* PORT = EMBEDDED means all DOS, WINDOWS, and UNIX code is excluded. +* Remaining code supports 16 and 32-bit compilers. +* Additional porting steps may be necessary. See readme +* file for more details. +*/ + +#define DOS 2 +#define WINDOWS 3 +#define UNIX 4 +#define EMBEDDED 5 + +#ifndef PORT +/* change this line to build a different port */ +#define PORT UNIX +#endif + +#define OPENBMC + +#endif /* INC_JBIPORT_H */ diff --git a/common/recipes-utils/jbi/files/code/jbistub.c b/common/recipes-utils/jbi/files/code/jbistub.c new file mode 100644 index 0000000..87e9066 --- /dev/null +++ b/common/recipes-utils/jbi/files/code/jbistub.c @@ -0,0 +1,2222 @@ +/****************************************************************************/ +/* */ +/* Module: jbistub.c */ +/* */ +/* Copyright (C) Altera Corporation 1997-2001 */ +/* */ +/* Description: Jam STAPL ByteCode Player main source file */ +/* */ +/* Supports Altera ByteBlaster hardware download cable */ +/* on Windows 95 and Windows NT operating systems. */ +/* (A device driver is required for Windows NT.) */ +/* */ +/* Also supports BitBlaster hardware download cable on */ +/* Windows 95, Windows NT, and UNIX platforms. */ +/* */ +/* Revisions: 1.1 fixed control port initialization for ByteBlaster */ +/* 2.0 added support for STAPL bytecode format, added code */ +/* to get printer port address from Windows registry */ +/* 2.1 improved messages, fixed delay-calibration bug in */ +/* 16-bit DOS port, added support for "alternative */ +/* cable X", added option to control whether to reset */ +/* the TAP after execution, moved porting macros into */ +/* jbiport.h */ +/* 2.2 added support for static memory */ +/* fixed /W4 warnings */ +/* */ +/****************************************************************************/ + +#ifndef NO_ALTERA_STDIO +#define NO_ALTERA_STDIO +#endif + +#if ( _MSC_VER >= 800 ) +#pragma warning(disable:4115) +#pragma warning(disable:4201) +#pragma warning(disable:4214) +#pragma warning(disable:4514) +#endif + +#include "jbiport.h" + +#if PORT == WINDOWS +#include <windows.h> +#else +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +#define TRUE 1 +#define FALSE 0 +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef OPENBMC +#include <io.h> +#endif +#include <fcntl.h> +#ifndef OPENBMC +#include <process.h> +#endif +#if defined(USE_STATIC_MEMORY) + #define N_STATIC_MEMORY_KBYTES ((unsigned int) USE_STATIC_MEMORY) + #define N_STATIC_MEMORY_BYTES (N_STATIC_MEMORY_KBYTES * 1024) + #define POINTER_ALIGNMENT sizeof(DWORD) +#else /* USE_STATIC_MEMORY */ + #include <malloc.h> + #define POINTER_ALIGNMENT sizeof(BYTE) +#endif /* USE_STATIC_MEMORY */ +#include <time.h> +#ifndef OPENBMC +#include <conio.h> +#endif +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef OPENBMC +//#define VERBOSE +//#define DEBUG +#include <openbmc/gpio.h> +#include <openbmc/log.h> +#include <errno.h> +#endif + +#if PORT == DOS +#include <bios.h> +#endif + +#include "jbiexprt.h" + +#if PORT == WINDOWS +#define PGDC_IOCTL_GET_DEVICE_INFO_PP 0x00166A00L +#define PGDC_IOCTL_READ_PORT_PP 0x00166A04L +#define PGDC_IOCTL_WRITE_PORT_PP 0x0016AA08L +#define PGDC_IOCTL_PROCESS_LIST_PP 0x0016AA1CL +#define PGDC_READ_INFO 0x0a80 +#define PGDC_READ_PORT 0x0a81 +#define PGDC_WRITE_PORT 0x0a82 +#define PGDC_PROCESS_LIST 0x0a87 +#define PGDC_HDLC_NTDRIVER_VERSION 2 +#define PORT_IO_BUFFER_SIZE 256 +#endif + +#if PORT == WINDOWS +#ifdef __BORLANDC__ +/* create dummy inp() and outp() functions for Borland 32-bit compile */ +WORD inp(WORD address) { address = address; return(0); } +void outp(WORD address, WORD data) { address = address; data = data; } +#else +#pragma intrinsic (inp, outp) +#endif +#endif + +/* +* For Borland C compiler (16-bit), set the stack size +*/ +#if PORT == DOS +#ifdef __BORLANDC__ +extern unsigned int _stklen = 50000; +#endif +#endif + +/************************************************************************ +* +* Global variables +*/ + +/* file buffer for Jam STAPL ByteCode input file */ +#if PORT == DOS +unsigned char **file_buffer = NULL; +#else +unsigned char *file_buffer = NULL; +#endif +long file_pointer = 0L; +long file_length = 0L; + +/* delay count for one millisecond delay */ +long one_ms_delay = 0L; + +/* serial port interface available on all platforms */ +BOOL jtag_hardware_initialized = FALSE; +char *serial_port_name = NULL; +BOOL specified_com_port = FALSE; +int com_port = -1; +void initialize_jtag_hardware(void); +void close_jtag_hardware(void); + +#ifdef OPENBMC +int g_tck = -1; +int g_tms = -1; +int g_tdo = -1; +int g_tdi = -1; +gpio_st g_gpio_tck; +gpio_st g_gpio_tms; +gpio_st g_gpio_tdo; +gpio_st g_gpio_tdi; +#endif + +#if defined(USE_STATIC_MEMORY) + unsigned char static_memory_heap[N_STATIC_MEMORY_BYTES] = { 0 }; +#endif /* USE_STATIC_MEMORY */ + +#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) + unsigned int n_bytes_allocated = 0; +#endif /* USE_STATIC_MEMORY || MEM_TRACKER */ + +#if defined(MEM_TRACKER) + unsigned int peak_memory_usage = 0; + unsigned int peak_allocations = 0; + unsigned int n_allocations = 0; +#if defined(USE_STATIC_MEMORY) + unsigned int n_bytes_not_recovered = 0; +#endif /* USE_STATIC_MEMORY */ + const DWORD BEGIN_GUARD = 0x01234567; + const DWORD END_GUARD = 0x76543210; +#endif /* MEM_TRACKER */ + +#if PORT == WINDOWS || PORT == DOS +/* parallel port interface available on PC only */ +BOOL specified_lpt_port = FALSE; +BOOL specified_lpt_addr = FALSE; +int lpt_port = 1; +int initial_lpt_ctrl = 0; +WORD lpt_addr = 0x3bc; +WORD lpt_addr_table[3] = { 0x3bc, 0x378, 0x278 }; +BOOL alternative_cable_l = FALSE; +BOOL alternative_cable_x = FALSE; +void write_byteblaster(int port, int data); +int read_byteblaster(int port); +#endif + +#if PORT==WINDOWS +#ifndef __BORLANDC__ +WORD lpt_addresses_from_registry[4] = { 0 }; +#endif +#endif + +#if PORT == WINDOWS +/* variables to manage cached I/O under Windows NT */ +BOOL windows_nt = FALSE; +int port_io_count = 0; +HANDLE nt_device_handle = INVALID_HANDLE_VALUE; +struct PORT_IO_LIST_STRUCT +{ + USHORT command; + USHORT data; +} port_io_buffer[PORT_IO_BUFFER_SIZE]; +extern void flush_ports(void); +BOOL initialize_nt_driver(void); +#endif + +/* function prototypes to allow forward reference */ +extern void delay_loop(long count); + +/* +* This structure stores information about each available vector signal +*/ +struct VECTOR_LIST_STRUCT +{ + char *signal_name; + int hardware_bit; + int vector_index; +}; + +struct VECTOR_LIST_STRUCT vector_list[] = +{ + /* add a record here for each vector signal */ + { "", 0, -1 } +}; + +#define VECTOR_SIGNAL_COUNT ((int)(sizeof(vector_list)/sizeof(vector_list[0]))) + +BOOL verbose = FALSE; + +/************************************************************************ +* +* Customized interface functions for Jam STAPL ByteCode Player I/O: +* +* jbi_jtag_io() +* jbi_message() +* jbi_delay() +*/ + +#ifdef OPENBMC + +/* + * The threshold (ns) to use spin instead of nanosleep(). + * Before adding the high resolution timer support, either spin or nanosleep() + * will not bring the process wakeup within 10ms. It turns out the system time + * update is also controlled by HZ (100). + * After I added the high resolution timer support, the spin works as the + * system time is updated more frequently. However, nanosleep() solution is + * still noticable slower comparing with spin. There could be some kernel + * scheduling tweak missing. Did not get time on that yet. + * For now, use 10ms as the threshold to determine if spin or nanosleep() + * is used. + */ +#define SPIN_THRESHOLD (10 * 1000 * 1000) +#define NANOSEC_IN_SEC (1000 * 1000 * 1000) + +static int sleep_ns(unsigned long clk) +{ + struct timespec req, rem; + int rc = 0; + if (clk <= SPIN_THRESHOLD) { + struct timespec orig; + rc = clock_gettime(CLOCK_MONOTONIC, &req); + orig = req; + while (!rc && clk) { + unsigned long tmp; + rc = clock_gettime(CLOCK_MONOTONIC, &rem); + tmp = (rem.tv_sec - req.tv_sec) * NANOSEC_IN_SEC; + if (rem.tv_nsec >= req.tv_nsec) { + tmp += rem.tv_nsec - req.tv_nsec; + } else { + tmp -= req.tv_nsec - rem.tv_nsec; + } + if (tmp >= clk) { + break; + } + clk -= tmp; + req = rem; + } + } else { + req.tv_sec = 0; + req.tv_nsec = clk; + while ((rc = nanosleep(&req, &rem)) == -1 && errno == EINTR) { + req = rem; + } + } + if (rc == -1) { + rc = errno; + LOG_ERR(rc, "Failed to sleep %u nanoseconds", clk); + } + return rc; +} + +int initialize_jtag_gpios() +{ + if (gpio_open(&g_gpio_tck, g_tck) || gpio_open(&g_gpio_tms, g_tms) + || gpio_open(&g_gpio_tdo, g_tdo) || gpio_open(&g_gpio_tdi, g_tdi)) { + return -1; + } + + /* change GPIO directions, only TDO is input, all others are output */ + if (gpio_change_direction(&g_gpio_tck, GPIO_DIRECTION_OUT) + || gpio_change_direction(&g_gpio_tms, GPIO_DIRECTION_OUT) + || gpio_change_direction(&g_gpio_tdo, GPIO_DIRECTION_IN) + || gpio_change_direction(&g_gpio_tdi, GPIO_DIRECTION_OUT)) { + return -1; + } + + /* set tck, tms, tdi to low */ + gpio_write(&g_gpio_tck, GPIO_VALUE_LOW); + gpio_write(&g_gpio_tms, GPIO_VALUE_LOW); + gpio_write(&g_gpio_tdi, GPIO_VALUE_LOW); + + jbi_delay(1); + + LOG_DBG("Opened TCK(GPIO %d), TMS(GPIO %d), TDI(GPIO %d), and TDO(GPIO %d)", + g_tck, g_tms, g_tdi, g_tdo); + + return 0; +} + +int jbi_jtag_io(int tms, int tdi, int read_tdo) +{ + int tdo = 0; + + if (!jtag_hardware_initialized) { + initialize_jtag_gpios(); + jtag_hardware_initialized = TRUE; + } + + gpio_write(&g_gpio_tms, tms ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW); + gpio_write(&g_gpio_tdi, tdi ? GPIO_VALUE_HIGH : GPIO_VALUE_LOW); + + /* sleep 500ns to make sure the signal shows up on wire */ + sleep_ns(500); + /* + * if we need to read data, the data should be ready from the + * previous clock falling edge. Read it now. + */ + if (read_tdo) { + tdo = gpio_read(&g_gpio_tdo) == GPIO_VALUE_HIGH ? 1 : 0; + } + + /* do rising edge to clock out the data */ + gpio_write(&g_gpio_tck, GPIO_VALUE_HIGH); + sleep_ns(500); + /* do falling edge clocking */ + gpio_write(&g_gpio_tck, GPIO_VALUE_LOW); + + LOG_VER("tms=%d tdi=%d do_read=%d tdo=%d", tms, tdi, read_tdo, tdo); + + return tdo; +} + +#else + +int jbi_jtag_io(int tms, int tdi, int read_tdo) +{ + int data = 0; + int tdo = 0; + int i = 0; + int result = 0; + char ch_data = 0; + + if (!jtag_hardware_initialized) + { + initialize_jtag_hardware(); + jtag_hardware_initialized = TRUE; + } + + if (specified_com_port) + { + ch_data = (char) + ((tdi ? 0x01 : 0) | (tms ? 0x02 : 0) | 0x60); + + write(com_port, &ch_data, 1); + + if (read_tdo) + { + ch_data = 0x7e; + write(com_port, &ch_data, 1); + for (i = 0; (i < 100) && (result != 1); ++i) + { + result = read(com_port, &ch_data, 1); + } + if (result == 1) + { + tdo = ch_data & 0x01; + } + else + { + fprintf(stderr, "Error: BitBlaster not responding\n"); + } + } + + ch_data = (char) + ((tdi ? 0x01 : 0) | (tms ? 0x02 : 0) | 0x64); + + write(com_port, &ch_data, 1); + } + else + { +#if PORT == WINDOWS || PORT == DOS + data = (alternative_cable_l ? ((tdi ? 0x01 : 0) | (tms ? 0x04 : 0)) : + (alternative_cable_x ? ((tdi ? 0x01 : 0) | (tms ? 0x04 : 0) | 0x10) : + ((tdi ? 0x40 : 0) | (tms ? 0x02 : 0)))); + + write_byteblaster(0, data); + + if (read_tdo) + { + tdo = read_byteblaster(1); + tdo = (alternative_cable_l ? ((tdo & 0x40) ? 1 : 0) : + (alternative_cable_x ? ((tdo & 0x10) ? 1 : 0) : + ((tdo & 0x80) ? 0 : 1))); + } + + write_byteblaster(0, data | (alternative_cable_l ? 0x02 : (alternative_cable_x ? 0x02: 0x01))); + + write_byteblaster(0, data); +#else + /* parallel port interface not available */ + tdo = 0; +#endif + } + + return (tdo); +} + +#endif + +void jbi_message(char *message_text) +{ + puts(message_text); + fflush(stdout); +} + +void jbi_export_integer(char *key, long value) +{ + if (verbose) + { + printf("Export: key = \"%s\", value = %ld\n", key, value); + fflush(stdout); + } +} + +#define HEX_LINE_CHARS 72 +#define HEX_LINE_BITS (HEX_LINE_CHARS * 4) + +char conv_to_hex(unsigned long value) +{ + char c; + + if (value > 9) + { + c = (char) (value + ('A' - 10)); + } + else + { + c = (char) (value + '0'); + } + + return (c); +} + +void jbi_export_boolean_array(char *key, unsigned char *data, long count) +{ + char string[HEX_LINE_CHARS + 1]; + long i, offset; + unsigned long size, line, lines, linebits, value, j, k; + + if (verbose) + { + if (count > HEX_LINE_BITS) + { + printf("Export: key = \"%s\", %ld bits, value = HEX\n", key, count); + lines = (count + (HEX_LINE_BITS - 1)) / HEX_LINE_BITS; + + for (line = 0; line < lines; ++line) + { + if (line < (lines - 1)) + { + linebits = HEX_LINE_BITS; + size = HEX_LINE_CHARS; + offset = count - ((line + 1) * HEX_LINE_BITS); + } + else + { + linebits = count - ((lines - 1) * HEX_LINE_BITS); + size = (linebits + 3) / 4; + offset = 0L; + } + + string[size] = '\0'; + j = size - 1; + value = 0; + + for (k = 0; k < linebits; ++k) + { + i = k + offset; + if (data[i >> 3] & (1 << (i & 7))) value |= (1 << (i & 3)); + if ((i & 3) == 3) + { + string[j] = conv_to_hex(value); + value = 0; + --j; + } + } + if ((k & 3) > 0) string[j] = conv_to_hex(value); + + printf("%s\n", string); + } + + fflush(stdout); + } + else + { + size = (count + 3) / 4; + string[size] = '\0'; + j = size - 1; + value = 0; + + for (i = 0; i < count; ++i) + { + if (data[i >> 3] & (1 << (i & 7))) value |= (1 << (i & 3)); + if ((i & 3) == 3) + { + string[j] = conv_to_hex(value); + value = 0; + --j; + } + } + if ((i & 3) > 0) string[j] = conv_to_hex(value); + + printf("Export: key = \"%s\", %ld bits, value = HEX %s\n", + key, count, string); + fflush(stdout); + } + } +} + +void jbi_delay(long microseconds) +{ +#if PORT == WINDOWS + /* if Windows NT, flush I/O cache buffer before delay loop */ + if (windows_nt && (port_io_count > 0)) flush_ports(); +#endif + +#ifdef OPENBMC + sleep_ns(microseconds * 1000); +#else + delay_loop(microseconds * + ((one_ms_delay / 1000L) + ((one_ms_delay % 1000L) ? 1 : 0))); +#endif +} + +int jbi_vector_map +( + int signal_count, + char **signals +) +{ + int signal, vector, ch_index, diff; + int matched_count = 0; + char l, r; + + for (vector = 0; (vector < VECTOR_SIGNAL_COUNT); ++vector) + { + vector_list[vector].vector_index = -1; + } + + for (signal = 0; signal < signal_count; ++signal) + { + diff = 1; + for (vector = 0; (diff != 0) && (vector < VECTOR_SIGNAL_COUNT); + ++vector) + { + if (vector_list[vector].vector_index == -1) + { + ch_index = 0; + do + { + l = signals[signal][ch_index]; + r = vector_list[vector].signal_name[ch_index]; + diff = (((l >= 'a') && (l <= 'z')) ? (l - ('a' - 'A')) : l) + - (((r >= 'a') && (r <= 'z')) ? (r - ('a' - 'A')) : r); + ++ch_index; + } + while ((diff == 0) && (l != '\0') && (r != '\0')); + + if (diff == 0) + { + vector_list[vector].vector_index = signal; + ++matched_count; + } + } + } + } + + return (matched_count); +} + +int jbi_vector_io +( + int signal_count, + long *dir_vect, + long *data_vect, + long *capture_vect +) +{ + int signal, vector, bit; + int matched_count = 0; + int data = 0; + int mask = 0; + int dir = 0; + int i = 0; + int result = 0; + char ch_data = 0; + + if (!jtag_hardware_initialized) + { + initialize_jtag_hardware(); + jtag_hardware_initialized = TRUE; + } + + /* + * Collect information about output signals + */ + for (vector = 0; vector < VECTOR_SIGNAL_COUNT; ++vector) + { + signal = vector_list[vector].vector_index; + + if ((signal >= 0) && (signal < signal_count)) + { + bit = (1 << vector_list[vector].hardware_bit); + + mask |= bit; + if (data_vect[signal >> 5] & (1L << (signal & 0x1f))) data |= bit; + if (dir_vect[signal >> 5] & (1L << (signal & 0x1f))) dir |= bit; + + ++matched_count; + } + } + + /* + * Write outputs to hardware interface, if any + */ + if (dir != 0) + { + if (specified_com_port) + { + ch_data = (char) (((data >> 6) & 0x01) | (data & 0x02) | + ((data << 2) & 0x04) | ((data << 3) & 0x08) | 0x60); + write(com_port, &ch_data, 1); + } + else + { +#if PORT == WINDOWS || PORT == DOS + + write_byteblaster(0, data); + +#endif + } + } + + /* + * Read the input signals and save information in capture_vect[] + */ + if ((dir != mask) && (capture_vect != NULL)) + { + if (specified_com_port) + { + ch_data = 0x7e; + write(com_port, &ch_data, 1); + for (i = 0; (i < 100) && (result != 1); ++i) + { + result = read(com_port, &ch_data, 1); + } + if (result == 1) + { + data = ((ch_data << 7) & 0x80) | ((ch_data << 3) & 0x10); + } + else + { + fprintf(stderr, "Error: BitBlaster not responding\n"); + } + } + else + { +#if PORT == WINDOWS || PORT == DOS + + data = read_byteblaster(1) ^ 0x80; /* parallel port inverts bit 7 */ + +#endif + } + + for (vector = 0; vector < VECTOR_SIGNAL_COUNT; ++vector) + { + signal = vector_list[vector].vector_index; + + if ((signal >= 0) && (signal < signal_count)) + { + bit = (1 << vector_list[vector].hardware_bit); + + if ((dir & bit) == 0) /* if it is an input signal... */ + { + if (data & bit) + { + capture_vect[signal >> 5] |= (1L << (signal & 0x1f)); + } + else + { + capture_vect[signal >> 5] &= ~(unsigned long) + (1L << (signal & 0x1f)); + } + } + } + } + } + + return (matched_count); +} + +void *jbi_malloc(unsigned int size) +{ + unsigned int n_bytes_to_allocate = +#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) + sizeof(unsigned int) + +#endif /* USE_STATIC_MEMORY || MEM_TRACKER */ +#if defined(MEM_TRACKER) + (2 * sizeof(DWORD)) + +#endif /* MEM_TRACKER */ + (POINTER_ALIGNMENT * ((size + POINTER_ALIGNMENT - 1) / POINTER_ALIGNMENT)); + + unsigned char *ptr = 0; + + +#if defined(MEM_TRACKER) + if ((n_bytes_allocated + n_bytes_to_allocate) > peak_memory_usage) + { + peak_memory_usage = n_bytes_allocated + n_bytes_to_allocate; + } + if ((n_allocations + 1) > peak_allocations) + { + peak_allocations = n_allocations + 1; + } +#endif /* MEM_TRACKER */ + +#if defined(USE_STATIC_MEMORY) + if ((n_bytes_allocated + n_bytes_to_allocate) <= N_STATIC_MEMORY_BYTES) + { + ptr = (&(static_memory_heap[n_bytes_allocated])); + } +#else /* USE_STATIC_MEMORY */ + ptr = (unsigned char *) malloc(n_bytes_to_allocate); +#endif /* USE_STATIC_MEMORY */ + +#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) + if (ptr != 0) + { + unsigned int i = 0; + +#if defined(MEM_TRACKER) + for (i = 0; i < sizeof(DWORD); ++i) + { + *ptr = (unsigned char) (BEGIN_GUARD >> (8 * i)); + ++ptr; + } +#endif /* MEM_TRACKER */ + + for (i = 0; i < sizeof(unsigned int); ++i) + { + *ptr = (unsigned char) (size >> (8 * i)); + ++ptr; + } + +#if defined(MEM_TRACKER) + for (i = 0; i < sizeof(DWORD); ++i) + { + *(ptr + size + i) = (unsigned char) (END_GUARD >> (8 * i)); + /* don't increment ptr */ + } + + ++n_allocations; +#endif /* MEM_TRACKER */ + + n_bytes_allocated += n_bytes_to_allocate; + } +#endif /* USE_STATIC_MEMORY || MEM_TRACKER */ + + return ptr; +} + +void jbi_free(void *ptr) +{ + if + ( +#if defined(MEM_TRACKER) + (n_allocations > 0) && +#endif /* MEM_TRACKER */ + (ptr != 0) + ) + { + unsigned char *tmp_ptr = (unsigned char *) ptr; + +#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) + unsigned int n_bytes_to_free = 0; + unsigned int i = 0; + unsigned int size = 0; +#endif /* USE_STATIC_MEMORY || MEM_TRACKER */ +#if defined(MEM_TRACKER) + DWORD begin_guard = 0; + DWORD end_guard = 0; + + + tmp_ptr -= sizeof(DWORD); +#endif /* MEM_TRACKER */ +#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) + tmp_ptr -= sizeof(unsigned int); +#endif /* USE_STATIC_MEMORY || MEM_TRACKER */ + ptr = tmp_ptr; + +#if defined(MEM_TRACKER) + for (i = 0; i < sizeof(DWORD); ++i) + { + begin_guard |= (((DWORD)(*tmp_ptr)) << (8 * i)); + ++tmp_ptr; + } +#endif /* MEM_TRACKER */ + +#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) + for (i = 0; i < sizeof(unsigned int); ++i) + { + size |= (((unsigned int)(*tmp_ptr)) << (8 * i)); + ++tmp_ptr; + } +#endif /* USE_STATIC_MEMORY || MEM_TRACKER */ + +#if defined(MEM_TRACKER) + tmp_ptr += size; + + for (i = 0; i < sizeof(DWORD); ++i) + { + end_guard |= (((DWORD)(*tmp_ptr)) << (8 * i)); + ++tmp_ptr; + } + + if ((begin_guard != BEGIN_GUARD) || (end_guard != END_GUARD)) + { + fprintf(stderr, "Error: memory corruption detected for allocation #%d... bad %s guard\n", + n_allocations, (begin_guard != BEGIN_GUARD) ? "begin" : "end"); + } + + --n_allocations; +#endif /* MEM_TRACKER */ + +#if defined(USE_STATIC_MEMORY) || defined(MEM_TRACKER) + n_bytes_to_free = +#if defined(MEM_TRACKER) + (2 * sizeof(DWORD)) + +#endif /* MEM_TRACKER */ + sizeof(unsigned int) + + (POINTER_ALIGNMENT * ((size + POINTER_ALIGNMENT - 1) / POINTER_ALIGNMENT)); +#endif /* USE_STATIC_MEMORY || MEM_TRACKER */ + +#if defined(USE_STATIC_MEMORY) + if ((((unsigned long) ptr - (unsigned long) static_memory_heap) + n_bytes_to_free) == (unsigned long) n_bytes_allocated) + { + n_bytes_allocated -= n_bytes_to_free; + } +#if defined(MEM_TRACKER) + else + { + n_bytes_not_recovered += n_bytes_to_free; + } +#endif /* MEM_TRACKER */ +#else /* USE_STATIC_MEMORY */ +#if defined(MEM_TRACKER) + n_bytes_allocated -= n_bytes_to_free; +#endif /* MEM_TRACKER */ + free(ptr); +#endif /* USE_STATIC_MEMORY */ + } +#if defined(MEM_TRACKER) + else + { + if (ptr != 0) + { + fprintf(stderr, "Error: attempt to free unallocated memory\n"); + } + } +#endif /* MEM_TRACKER */ +} + +/************************************************************************ +* +* get_tick_count() -- Get system tick count in milliseconds +* +* for DOS, use BIOS function _bios_timeofday() +* for WINDOWS use GetTickCount() function +* for UNIX use clock() system function +*/ +DWORD get_tick_count(void) +{ + DWORD tick_count = 0L; + +#if PORT == WINDOWS + tick_count = GetTickCount(); +#elif PORT == DOS + _bios_timeofday(_TIME_GETCLOCK, (long *)&tick_count); + tick_count *= 55L; /* convert to milliseconds */ +#else + /* assume clock() function returns microseconds */ + tick_count = (DWORD) (clock() / 1000L); +#endif + + return (tick_count); +} + +#define DELAY_SAMPLES 10 +#define DELAY_CHECK_LOOPS 10000 + +void calibrate_delay(void) +{ + int sample = 0; + int count = 0; + DWORD tick_count1 = 0L; + DWORD tick_count2 = 0L; + + one_ms_delay = 0L; + +#if PORT == WINDOWS || PORT == DOS || defined(OPENBMC) + for (sample = 0; sample < DELAY_SAMPLES; ++sample) + { + count = 0; + tick_count1 = get_tick_count(); + while ((tick_count2 = get_tick_count()) == tick_count1) {}; + do { delay_loop(DELAY_CHECK_LOOPS); count++; } while + ((tick_count1 = get_tick_count()) == tick_count2); + one_ms_delay += ((DELAY_CHECK_LOOPS * (DWORD)count) / + (tick_count1 - tick_count2)); + } + + one_ms_delay /= DELAY_SAMPLES; +#else + /* This is system-dependent! Update this number for target system */ + one_ms_delay = 1000L; +#endif +} + +char *error_text[] = +{ +/* JBIC_SUCCESS 0 */ "success", +/* JBIC_OUT_OF_MEMORY 1 */ "out of memory", +/* JBIC_IO_ERROR 2 */ "file access error", +/* JAMC_SYNTAX_ERROR 3 */ "syntax error", +/* JBIC_UNEXPECTED_END 4 */ "unexpected end of file", +/* JBIC_UNDEFINED_SYMBOL 5 */ "undefined symbol", +/* JAMC_REDEFINED_SYMBOL 6 */ "redefined symbol", +/* JBIC_INTEGER_OVERFLOW 7 */ "integer overflow", +/* JBIC_DIVIDE_BY_ZERO 8 */ "divide by zero", +/* JBIC_CRC_ERROR 9 */ "CRC mismatch", +/* JBIC_INTERNAL_ERROR 10 */ "internal error", +/* JBIC_BOUNDS_ERROR 11 */ "bounds error", +/* JAMC_TYPE_MISMATCH 12 */ "type mismatch", +/* JAMC_ASSIGN_TO_CONST 13 */ "assignment to constant", +/* JAMC_NEXT_UNEXPECTED 14 */ "NEXT unexpected", +/* JAMC_POP_UNEXPECTED 15 */ "POP unexpected", +/* JAMC_RETURN_UNEXPECTED 16 */ "RETURN unexpected", +/* JAMC_ILLEGAL_SYMBOL 17 */ "illegal symbol name", +/* JBIC_VECTOR_MAP_FAILED 18 */ "vector signal name not found", +/* JBIC_USER_ABORT 19 */ "execution cancelled", +/* JBIC_STACK_OVERFLOW 20 */ "stack overflow", +/* JBIC_ILLEGAL_OPCODE 21 */ "illegal instruction code", +/* JAMC_PHASE_ERROR 22 */ "phase error", +/* JAMC_SCOPE_ERROR 23 */ "scope error", +/* JBIC_ACTION_NOT_FOUND 24 */ "action not found", +}; + +#define MAX_ERROR_CODE (int)((sizeof(error_text)/sizeof(error_text[0]))+1) + +/************************************************************************/ + +int main(int argc, char **argv) +{ + BOOL help = FALSE; + BOOL error = FALSE; + char *filename = NULL; + long offset = 0L; + long error_address = 0L; + JBI_RETURN_TYPE crc_result = JBIC_SUCCESS; + JBI_RETURN_TYPE exec_result = JBIC_SUCCESS; + unsigned short expected_crc = 0; + unsigned short actual_crc = 0; + char key[33] = {0}; + char value[257] = {0}; + int exit_status = 0; + int arg = 0; + int exit_code = 0; + int format_version = 0; + time_t start_time = 0; + time_t end_time = 0; + int time_delta = 0; + char *workspace = NULL; + char *action = NULL; + char *init_list[10]; + int init_count = 0; + FILE *fp = NULL; + struct stat sbuf; + long workspace_size = 0; + char *exit_string = NULL; + int reset_jtag = 1; + int execute_program = 1; + int action_count = 0; + int procedure_count = 0; + int index = 0; + char *action_name = NULL; + char *description = NULL; + JBI_PROCINFO *procedure_list = NULL; + JBI_PROCINFO *procptr = NULL; + + verbose = FALSE; + + init_list[0] = NULL; + + /* print out the version string and copyright message */ + fprintf(stderr, "Jam STAPL ByteCode Player Version 2.2\nCopyright (C) 1998-2001 Altera Corporation\n\n"); + + for (arg = 1; arg < argc; arg++) + { +#if PORT == UNIX + if (argv[arg][0] == '-') +#else + if ((argv[arg][0] == '-') || (argv[arg][0] == '/')) +#endif + { + switch(toupper(argv[arg][1])) + { + case 'A': /* set action name */ + if (action == NULL) + { + action = &argv[arg][2]; + } + else + { + error = TRUE; + } + break; + +#if PORT == WINDOWS || PORT == DOS + case 'C': /* Use alternative ISP download cable */ + if(toupper(argv[arg][2]) == 'L') + alternative_cable_l = TRUE; + else if(toupper(argv[arg][2]) == 'X') + alternative_cable_x = TRUE; + break; +#endif + + case 'D': /* initialization list */ + if (argv[arg][2] == '"') + { + init_list[init_count] = &argv[arg][3]; + } + else + { + init_list[init_count] = &argv[arg][2]; + } + init_list[++init_count] = NULL; + break; + +#if PORT == WINDOWS || PORT == DOS + case 'P': /* set LPT port address */ + specified_lpt_port = TRUE; + if (sscanf(&argv[arg][2], "%d", &lpt_port) != 1) error = TRUE; + if ((lpt_port < 1) || (lpt_port > 3)) error = TRUE; + if (error) + { + if (sscanf(&argv[arg][2], "%x", &lpt_port) == 1) + { + if ((lpt_port == 0x3bc) || + (lpt_port == 0x378) || + (lpt_port == 0x278)) + { + error = FALSE; + specified_lpt_addr = TRUE; + lpt_addr = (WORD) lpt_port; + lpt_port = 1; + } + } + } + break; +#endif + + case 'R': /* don't reset the JTAG chain after use */ + reset_jtag = 0; + break; + +#ifdef OPENBMC + case 'G': /* GPIO directory */ + switch (toupper(argv[arg][2])) { + case 'C': + g_tck = atoi(&argv[arg][3]); + break; + case 'S': + g_tms = atoi(&argv[arg][3]); + break; + case 'I': + g_tdi = atoi(&argv[arg][3]); + break; + case 'O': + g_tdo = atoi(&argv[arg][3]); + break; + } + break; +#else + case 'S': /* set serial port address */ + serial_port_name = &argv[arg][2]; + specified_com_port = TRUE; + break; +#endif + + case 'M': /* set memory size */ + if (sscanf(&argv[arg][2], "%ld", &workspace_size) != 1) + error = TRUE; + if (workspace_size == 0) error = TRUE; + break; + + case 'H': /* help */ + help = TRUE; + break; + + case 'V': /* verbose */ + verbose = TRUE; + break; + + case 'I': /* show info only, do not execute */ + verbose = TRUE; + execute_program = 0; + break; + + default: + error = TRUE; + break; + } + } + else + { + /* it's a filename */ + if (filename == NULL) + { + filename = argv[arg]; + } + else + { + /* error -- we already found a filename */ + error = TRUE; + } + } + + if (error) + { + fprintf(stderr, "Illegal argument: \"%s\"\n", argv[arg]); + help = TRUE; + error = FALSE; + } + } + +#if PORT == WINDOWS || PORT == DOS + if (specified_lpt_port && specified_com_port) + { + fprintf(stderr, "Error: -s and -p options may not be used together\n\n"); + help = TRUE; + } +#endif + +#ifdef OPENBMC + if (execute_program) { + if (g_tck == -1 || g_tms == -1 || g_tdo == -1 || g_tdi == -1) { + fprintf(stderr, "Error: -gc, -gs, -gi, and -go must be specified\n"); + help = TRUE; + } + } +#endif + + if (help || (filename == NULL)) + { + fprintf(stderr, "Usage: jbi [options] <filename>\n"); + fprintf(stderr, "\nAvailable options:\n"); + fprintf(stderr, " -h : show help message\n"); + fprintf(stderr, " -v : show verbose messages\n"); + fprintf(stderr, " -i : show file info only - does not execute any action\n"); + fprintf(stderr, " -a<action> : specify an action name (Jam STAPL)\n"); + fprintf(stderr, " -d<var=val> : initialize variable to specified value (Jam 1.1)\n"); + fprintf(stderr, " -d<proc=1> : enable optional procedure (Jam STAPL)\n"); + fprintf(stderr, " -d<proc=0> : disable recommended procedure (Jam STAPL)\n"); +#if PORT == WINDOWS || PORT == DOS + fprintf(stderr, " -p<port> : parallel port number or address (for ByteBlaster)\n"); + fprintf(stderr, " -c<cable> : alternative download cable compatibility: -cl or -cx\n"); +#endif +#ifdef OPENBMC + fprintf(stderr, " -gc<clock> : GPIO directory for TCK\n"); + fprintf(stderr, " -gs<clock> : GPIO directory for TMS\n"); + fprintf(stderr, " -gi<clock> : GPIO directory for TDI\n"); + fprintf(stderr, " -go<clock> : GPIO directory for TDO\n"); +#else + fprintf(stderr, " -s<port> : serial port name (for BitBlaster)\n"); +#endif + fprintf(stderr, " -r : don't reset JTAG TAP after use\n"); + exit_status = 1; + } + else if ((workspace_size > 0) && + ((workspace = (char *) jbi_malloc((size_t) workspace_size)) == NULL)) + { + fprintf(stderr, "Error: can't allocate memory (%d Kbytes)\n", + (int) (workspace_size / 1024L)); + exit_status = 1; + } + else if (access(filename, 0) != 0) + { + fprintf(stderr, "Error: can't access file \"%s\"\n", filename); + exit_status = 1; + } + else + { + /* get length of file */ + if (stat(filename, &sbuf) == 0) file_length = sbuf.st_size; + + if ((fp = fopen(filename, "rb")) == NULL) + { + fprintf(stderr, "Error: can't open file \"%s\"\n", filename); + exit_status = 1; + } + else + { + /* + * Read entire file into a buffer + */ +#if PORT == DOS + int pages = 1 + (int) (file_length >> 14L); + int page; + file_buffer = (unsigned char **) jbi_malloc( + (size_t) (pages * sizeof(char *))); + + for (page = 0; page < pages; ++page) + { + /* allocate enough 16K blocks to store the file */ + file_buffer[page] = (unsigned char *) jbi_malloc (0x4000); + if (file_buffer[page] == NULL) + { + /* flag error and break out of loop */ + file_buffer = NULL; + page = pages; + } + } +#else + file_buffer = (unsigned char *) jbi_malloc((size_t) file_length); +#endif + + if (file_buffer == NULL) + { + fprintf(stderr, "Error: can't allocate memory (%d Kbytes)\n", + (int) (file_length / 1024L)); + exit_status = 1; + } + else + { +#if PORT == DOS + int pages = 1 + (int) (file_length >> 14L); + int page; + size_t page_size = 0x4000; + for (page = 0; (page < pages) && (exit_status == 0); ++page) + { + if (page == (pages - 1)) + { + /* last page may not be full 16K bytes */ + page_size = (size_t) (file_length & 0x3fffL); + } + if (fread(file_buffer[page], 1, page_size, fp) != page_size) + { + fprintf(stderr, "Error reading file \"%s\"\n", filename); + exit_status = 1; + } + } +#else + if (fread(file_buffer, 1, (size_t) file_length, fp) != + (size_t) file_length) + { + fprintf(stderr, "Error reading file \"%s\"\n", filename); + exit_status = 1; + } +#endif + } + + fclose(fp); + } + + if (exit_status == 0) + { + /* + * Get Operating System type + */ +#if PORT == WINDOWS + windows_nt = !(GetVersion() & 0x80000000); +#endif + + /* + * Calibrate the delay loop function + */ + calibrate_delay(); + + /* + * Check CRC + */ + crc_result = jbi_check_crc(file_buffer, file_length, + &expected_crc, &actual_crc); + + if (verbose || (crc_result == JBIC_CRC_ERROR)) + { + switch (crc_result) + { + case JBIC_SUCCESS: + printf("CRC matched: CRC value = %04X\n", actual_crc); + break; + + case JBIC_CRC_ERROR: + printf("CRC mismatch: expected %04X, actual %04X\n", + expected_crc, actual_crc); + break; + + case JBIC_UNEXPECTED_END: + printf("Expected CRC not found, actual CRC value = %04X\n", + actual_crc); + break; + + case JBIC_IO_ERROR: + printf("Error: File format is not recognized.\n"); + exit(1); + break; + + default: + printf("CRC function returned error code %d\n", crc_result); + break; + } + } + + if (verbose) + { + /* + * Display file format version + */ + jbi_get_file_info(file_buffer, file_length, + &format_version, &action_count, &procedure_count); + + printf("File format is %s ByteCode format\n", + (format_version == 2) ? "Jam STAPL" : "pre-standardized Jam 1.1"); + + /* + * Dump out NOTE fields + */ + while (jbi_get_note(file_buffer, file_length, + &offset, key, value, 256) == 0) + { + printf("NOTE \"%s\" = \"%s\"\n", key, value); + } + + /* + * Dump the action table + */ + if ((format_version == 2) && (action_count > 0)) + { + printf("\nActions available in this file:\n"); + + for (index = 0; index < action_count; ++index) + { + jbi_get_action_info(file_buffer, file_length, + index, &action_name, &description, &procedure_list); + + if (description == NULL) + { + printf("%s\n", action_name); + } + else + { + printf("%s \"%s\"\n", action_name, description); + } + +#if PORT == DOS + if (action_name != NULL) jbi_free(action_name); + if (description != NULL) jbi_free(description); +#endif + + procptr = procedure_list; + while (procptr != NULL) + { + if (procptr->attributes != 0) + { + printf(" %s (%s)\n", procptr->name, + (procptr->attributes == 1) ? + "optional" : "recommended"); + } + +#if PORT == DOS + if (procptr->name != NULL) jbi_free(procptr->name); +#endif + + procedure_list = procptr->next; + jbi_free(procptr); + procptr = procedure_list; + } + } + + /* add a blank line before execution messages */ + if (execute_program) printf("\n"); + } + } + + if (execute_program) + { + /* + * Execute the Jam STAPL ByteCode program + */ + time(&start_time); + exec_result = jbi_execute(file_buffer, file_length, workspace, + workspace_size, action, init_list, reset_jtag, + &error_address, &exit_code, &format_version); + time(&end_time); + + if (exec_result == JBIC_SUCCESS) + { + if (format_version == 2) + { + switch (exit_code) + { + case 0: exit_string = "Success"; break; + case 1: exit_string = "Checking chain failure"; break; + case 2: exit_string = "Reading IDCODE failure"; break; + case 3: exit_string = "Reading USERCODE failure"; break; + case 4: exit_string = "Reading UESCODE failure"; break; + case 5: exit_string = "Entering ISP failure"; break; + case 6: exit_string = "Unrecognized device"; break; + case 7: exit_string = "Device revision is not supported"; break; + case 8: exit_string = "Erase failure"; break; + case 9: exit_string = "Device is not blank"; break; + case 10: exit_string = "Device programming failure"; break; + case 11: exit_string = "Device verify failure"; break; + case 12: exit_string = "Read failure"; break; + case 13: exit_string = "Calculating checksum failure"; break; + case 14: exit_string = "Setting security bit failure"; break; + case 15: exit_string = "Querying security bit failure"; break; + case 16: exit_string = "Exiting ISP failure"; break; + case 17: exit_string = "Performing system test failure"; break; + default: exit_string = "Unknown exit code"; break; + } + } + else + { + switch (exit_code) + { + case 0: exit_string = "Success"; break; + case 1: exit_string = "Illegal initialization values"; break; + case 2: exit_string = "Unrecognized device"; break; + case 3: exit_string = "Device revision is not supported"; break; + case 4: exit_string = "Device programming failure"; break; + case 5: exit_string = "Device is not blank"; break; + case 6: exit_string = "Device verify failure"; break; + case 7: exit_string = "SRAM configuration failure"; break; + default: exit_string = "Unknown exit code"; break; + } + } + + printf("Exit code = %d... %s\n", exit_code, exit_string); + } + else if ((format_version == 2) && + (exec_result == JBIC_ACTION_NOT_FOUND)) + { + if ((action == NULL) || (*action == '\0')) + { + printf("Error: no action specified for Jam STAPL file.\nProgram terminated.\n"); + } + else + { + printf("Error: action \"%s\" is not supported for this Jam STAPL file.\nProgram terminated.\n", action); + } + } + else if (exec_result < MAX_ERROR_CODE) + { + printf("Error at address %ld: %s.\nProgram terminated.\n", + error_address, error_text[exec_result]); + } + else + { + printf("Unknown error code %ld\n", exec_result); + } + + /* + * Print out elapsed time + */ + if (verbose) + { + time_delta = (int) (end_time - start_time); + printf("Elapsed time = %02u:%02u:%02u\n", + time_delta / 3600, /* hours */ + (time_delta % 3600) / 60, /* minutes */ + time_delta % 60); /* seconds */ + } + } + } + } + + if (jtag_hardware_initialized) close_jtag_hardware(); + + if (workspace != NULL) jbi_free(workspace); + if (file_buffer != NULL) jbi_free(file_buffer); + +#if defined(MEM_TRACKER) + if (verbose) + { +#if defined(USE_STATIC_MEMORY) + fprintf(stdout, "Memory Usage Info: static memory size = %ud (%dKB)\n", N_STATIC_MEMORY_BYTES, N_STATIC_MEMORY_KBYTES); +#endif /* USE_STATIC_MEMORY */ + fprintf(stdout, "Memory Usage Info: peak memory usage = %ud (%dKB)\n", peak_memory_usage, (peak_memory_usage + 1023) / 1024); + fprintf(stdout, "Memory Usage Info: peak allocations = %d\n", peak_allocations); +#if defined(USE_STATIC_MEMORY) + if ((n_bytes_allocated - n_bytes_not_recovered) != 0) + { + fprintf(stdout, "Memory Usage Info: bytes still allocated = %d (%dKB)\n", (n_bytes_allocated - n_bytes_not_recovered), ((n_bytes_allocated - n_bytes_not_recovered) + 1023) / 1024); + } +#else /* USE_STATIC_MEMORY */ + if (n_bytes_allocated != 0) + { + fprintf(stdout, "Memory Usage Info: bytes still allocated = %d (%dKB)\n", n_bytes_allocated, (n_bytes_allocated + 1023) / 1024); + } +#endif /* USE_STATIC_MEMORY */ + if (n_allocations != 0) + { + fprintf(stdout, "Memory Usage Info: allocations not freed = %d\n", n_allocations); + } + } +#endif /* MEM_TRACKER */ + + return (exit_status); +} + +#if PORT==WINDOWS +#ifndef __BORLANDC__ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* SEARCH_DYN_DATA +* +* Searches recursively in Windows 95/98 Registry for parallel port info +* under HKEY_DYN_DATA registry key. Called by search_local_machine(). +*/ +void search_dyn_data +( + char *dd_path, + char *hardware_key, + int lpt +) +{ + DWORD index; + DWORD size; + DWORD type; + LONG result; + HKEY key; + int length; + WORD address; + char buffer[1024]; + FILETIME last_write = {0}; + WORD *word_ptr; + int i; + + length = strlen(dd_path); + + if (RegOpenKeyEx( + HKEY_DYN_DATA, + dd_path, + 0L, + KEY_READ, + &key) + == ERROR_SUCCESS) + { + size = 1023; + + if (RegQueryValueEx( + key, + "HardWareKey", + NULL, + &type, + (unsigned char *) buffer, + &size) + == ERROR_SUCCESS) + { + if ((type == REG_SZ) && (stricmp(buffer, hardware_key) == 0)) + { + size = 1023; + + if (RegQueryValueEx( + key, + "Allocation", + NULL, + &type, + (unsigned char *) buffer, + &size) + == ERROR_SUCCESS) + { + /* + * By "inspection", I have found five cases: size 32, 48, + * 56, 60, and 80 bytes. The port address seems to be + * located at different offsets in the buffer for these + * five cases, as shown below. If a valid port address + * is not found, or the size is not one of these known + * sizes, then I search through the entire buffer and + * look for a value which is a valid port address. + */ + + word_ptr = (WORD *) buffer; + + if ((type == REG_BINARY) && (size == 32)) + { + address = word_ptr[10]; + } + else if ((type == REG_BINARY) && (size == 48)) + { + address = word_ptr[18]; + } + else if ((type == REG_BINARY) && (size == 56)) + { + address = word_ptr[22]; + } + else if ((type == REG_BINARY) && (size == 60)) + { + address = word_ptr[24]; + } + else if ((type == REG_BINARY) && (size == 80)) + { + address = word_ptr[24]; + } + else address = 0; + + /* if not found, search through entire buffer */ + i = 0; + while ((i < (int) (size / 2)) && + (address != 0x278) && + (address != 0x27C) && + (address != 0x378) && + (address != 0x37C) && + (address != 0x3B8) && + (address != 0x3BC)) + { + if ((word_ptr[i] == 0x278) || + (word_ptr[i] == 0x27C) || + (word_ptr[i] == 0x378) || + (word_ptr[i] == 0x37C) || + (word_ptr[i] == 0x3B8) || + (word_ptr[i] == 0x3BC)) + { + address = word_ptr[i]; + } + ++i; + } + + if ((address == 0x278) || + (address == 0x27C) || + (address == 0x378) || + (address == 0x37C) || + (address == 0x3B8) || + (address == 0x3BC)) + { + lpt_addresses_from_registry[lpt] = address; + } + } + } + } + + index = 0; + + do + { + size = 1023; + + result = RegEnumKeyEx( + key, + index++, + buffer, + &size, + NULL, + NULL, + NULL, + &last_write); + + if (result == ERROR_SUCCESS) + { + dd_path[length] = '\\'; + dd_path[length + 1] = '\0'; + strcpy(&dd_path[length + 1], buffer); + + search_dyn_data(dd_path, hardware_key, lpt); + + dd_path[length] = '\0'; + } + } + while (result == ERROR_SUCCESS); + + RegCloseKey(key); + } +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* SEARCH_LOCAL_MACHINE +* +* Searches recursively in Windows 95/98 Registry for parallel port info +* under HKEY_LOCAL_MACHINE\Enum. When parallel port is found, calls +* search_dyn_data() to get the port address. +*/ +void search_local_machine +( + char *lm_path, + char *dd_path +) +{ + DWORD index; + DWORD size; + DWORD type; + LONG result; + HKEY key; + int length; + char buffer[1024]; + FILETIME last_write = {0}; + + length = strlen(lm_path); + + if (RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + lm_path, + 0L, + KEY_READ, + &key) + == ERROR_SUCCESS) + { + size = 1023; + + if (RegQueryValueEx( + key, + "PortName", + NULL, + &type, + (unsigned char *) buffer, + &size) + == ERROR_SUCCESS) + { + if ((type == REG_SZ) && + (size == 5) && + (buffer[0] == 'L') && + (buffer[1] == 'P') && + (buffer[2] == 'T') && + (buffer[3] >= '1') && + (buffer[3] <= '4') && + (buffer[4] == '\0')) + { + /* we found the entry in HKEY_LOCAL_MACHINE, now we need to */ + /* find the corresponding entry under HKEY_DYN_DATA. */ + /* add 5 to lm_path to skip over "Enum" and backslash */ + search_dyn_data(dd_path, &lm_path[5], (buffer[3] - '1')); + } + } + + index = 0; + + do + { + size = 1023; + + result = RegEnumKeyEx( + key, + index++, + buffer, + &size, + NULL, + NULL, + NULL, + &last_write); + + if (result == ERROR_SUCCESS) + { + lm_path[length] = '\\'; + lm_path[length + 1] = '\0'; + strcpy(&lm_path[length + 1], buffer); + + search_local_machine(lm_path, dd_path); + + lm_path[length] = '\0'; + } + } + while (result == ERROR_SUCCESS); + + RegCloseKey(key); + } +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* GET_LPT_ADDRESSES_FROM_REGISTRY +* +* Searches Win95/98 registry recursively to get I/O port addresses for +* parallel ports. +*/ +void get_lpt_addresses_from_registry() +{ + char lm_path[1024]; + char dd_path[1024]; + + strcpy(lm_path, "Enum"); + strcpy(dd_path, "Config Manager"); + search_local_machine(lm_path, dd_path); +} +#endif +#endif + +void initialize_jtag_hardware() +{ + if (specified_com_port) + { + com_port = open(serial_port_name, O_RDWR); + if (com_port == -1) + { + fprintf(stderr, "Error: can't open serial port \"%s\"\n", + serial_port_name); + } + else + { + int i = 0, result = 0; + char data = 0; + + data = 0x7e; + write(com_port, &data, 1); + + for (i = 0; (i < 100) && (result != 1); ++i) + { + result = read(com_port, &data, 1); + } + + if (result == 1) + { + data = 0x70; write(com_port, &data, 1); /* TDO echo off */ + data = 0x72; write(com_port, &data, 1); /* auto LEDs off */ + data = 0x74; write(com_port, &data, 1); /* ERROR LED off */ + data = 0x76; write(com_port, &data, 1); /* DONE LED off */ + data = 0x60; write(com_port, &data, 1); /* signals low */ + } + else + { + fprintf(stderr, "Error: BitBlaster is not responding on %s\n", + serial_port_name); + close(com_port); + com_port = -1; + } + } + } + else + { +#if PORT == WINDOWS || PORT == DOS + +#if PORT == WINDOWS + if (windows_nt) + { + initialize_nt_driver(); + } + else + { +#ifdef __BORLANDC__ + fprintf(stderr, "Error: parallel port access is not available\n"); +#else + if (!specified_lpt_addr) + { + get_lpt_addresses_from_registry(); + + lpt_addr = 0; + + if (specified_lpt_port) + { + lpt_addr = lpt_addresses_from_registry[lpt_port - 1]; + } + + if (lpt_addr == 0) + { + if (lpt_addresses_from_registry[3] != 0) + lpt_addr = lpt_addresses_from_registry[3]; + if (lpt_addresses_from_registry[2] != 0) + lpt_addr = lpt_addresses_from_registry[2]; + if (lpt_addresses_from_registry[1] != 0) + lpt_addr = lpt_addresses_from_registry[1]; + if (lpt_addresses_from_registry[0] != 0) + lpt_addr = lpt_addresses_from_registry[0]; + } + + if (lpt_addr == 0) + { + if (specified_lpt_port) + { + lpt_addr = lpt_addr_table[lpt_port - 1]; + } + else + { + lpt_addr = lpt_addr_table[0]; + } + } + } + initial_lpt_ctrl = windows_nt ? 0x0c : read_byteblaster(2); +#endif + } +#endif + +#if PORT == DOS + /* + * Read word at specific memory address to get the LPT port address + */ + WORD *bios_address = (WORD *) 0x00400008; + + if (!specified_lpt_addr) + { + lpt_addr = bios_address[lpt_port - 1]; + + if ((lpt_addr != 0x278) && + (lpt_addr != 0x27c) && + (lpt_addr != 0x378) && + (lpt_addr != 0x37c) && + (lpt_addr != 0x3b8) && + (lpt_addr != 0x3bc)) + { + lpt_addr = lpt_addr_table[lpt_port - 1]; + } + } + initial_lpt_ctrl = read_byteblaster(2); +#endif + + /* set AUTO-FEED low to enable ByteBlaster (value to port inverted) */ + /* set DIRECTION low for data output from parallel port */ + write_byteblaster(2, (initial_lpt_ctrl | 0x02) & 0xDF); +#endif + } +} + +void close_jtag_hardware() +{ + if (specified_com_port) + { + if (com_port != -1) close(com_port); + } + else + { +#if PORT == WINDOWS || PORT == DOS + /* set AUTO-FEED high to disable ByteBlaster */ + write_byteblaster(2, initial_lpt_ctrl & 0xfd); + +#if PORT == WINDOWS + if (windows_nt && (nt_device_handle != INVALID_HANDLE_VALUE)) + { + if (port_io_count > 0) flush_ports(); + + CloseHandle(nt_device_handle); + } +#endif +#endif + } +} + +#if PORT == WINDOWS +/**************************************************************************/ +/* */ + +BOOL initialize_nt_driver() + +/* */ +/* Uses CreateFile() to open a connection to the Windows NT device */ +/* driver. */ +/* */ +/**************************************************************************/ +{ + BOOL status = FALSE; + + ULONG buffer[1]; + ULONG returned_length = 0; + char nt_lpt_str[] = { '\\', '\\', '.', '\\', + 'A', 'L', 'T', 'L', 'P', 'T', '1', '\0' }; + + + nt_lpt_str[10] = (char) ('1' + (lpt_port - 1)); + + nt_device_handle = CreateFile( + nt_lpt_str, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (nt_device_handle == INVALID_HANDLE_VALUE) + { + fprintf(stderr, + "I/O error: cannot open device %s\nCheck port number and device driver installation", + nt_lpt_str); + } + else + { + if (DeviceIoControl( + nt_device_handle, /* Handle to device */ + PGDC_IOCTL_GET_DEVICE_INFO_PP, /* IO Control code */ + (ULONG *)NULL, /* Buffer to driver. */ + 0, /* Length of buffer in bytes. */ + &buffer, /* Buffer from driver. */ + sizeof(ULONG), /* Length of buffer in bytes. */ + &returned_length, /* Bytes placed in data_buffer. */ + NULL)) /* Wait for operation to complete */ + { + if (returned_length == sizeof(ULONG)) + { + if (buffer[0] == PGDC_HDLC_NTDRIVER_VERSION) + { + status = TRUE; + } + else + { + fprintf(stderr, + "I/O error: device driver %s is not compatible\n(Driver version is %lu, expected version %lu.\n", + nt_lpt_str, + (unsigned long) buffer[0], + (unsigned long) PGDC_HDLC_NTDRIVER_VERSION); + } + } + else + { + fprintf(stderr, "I/O error: device driver %s is not compatible.\n", + nt_lpt_str); + } + } + + if (!status) + { + CloseHandle(nt_device_handle); + nt_device_handle = INVALID_HANDLE_VALUE; + } + } + + if (!status) + { + /* error message already given */ + exit(1); + } + + return (status); +} +#endif + +#if PORT == WINDOWS || PORT == DOS +/**************************************************************************/ +/* */ + +void write_byteblaster +( + int port, + int data +) + +/* */ +/**************************************************************************/ +{ +#if PORT == WINDOWS + BOOL status = FALSE; + + int returned_length = 0; + int buffer[2]; + + + if (windows_nt) + { + /* + * On Windows NT, access hardware through device driver + */ + if (port == 0) + { + port_io_buffer[port_io_count].data = (USHORT) data; + port_io_buffer[port_io_count].command = PGDC_WRITE_PORT; + ++port_io_count; + + if (port_io_count >= PORT_IO_BUFFER_SIZE) flush_ports(); + } + else + { + if (port_io_count > 0) flush_ports(); + + buffer[0] = port; + buffer[1] = data; + + status = DeviceIoControl( + nt_device_handle, /* Handle to device */ + PGDC_IOCTL_WRITE_PORT_PP, /* IO Control code for write */ + (ULONG *)&buffer, /* Buffer to driver. */ + 2 * sizeof(int), /* Length of buffer in bytes. */ + (ULONG *)NULL, /* Buffer from driver. Not used. */ + 0, /* Length of buffer in bytes. */ + (ULONG *)&returned_length, /* Bytes returned. Should be zero. */ + NULL); /* Wait for operation to complete */ + + if ((!status) || (returned_length != 0)) + { + fprintf(stderr, "I/O error: Cannot access ByteBlaster hardware\n"); + CloseHandle(nt_device_handle); + exit(1); + } + } + } + else +#endif + { + /* + * On Windows 95, access hardware directly + */ + outp((WORD)(port + lpt_addr), (WORD)data); + } +} + +/**************************************************************************/ +/* */ + +int read_byteblaster +( + int port +) + +/* */ +/**************************************************************************/ +{ + int data = 0; + +#if PORT == WINDOWS + + BOOL status = FALSE; + + int returned_length = 0; + + + if (windows_nt) + { + /* flush output cache buffer before reading from device */ + if (port_io_count > 0) flush_ports(); + + /* + * On Windows NT, access hardware through device driver + */ + status = DeviceIoControl( + nt_device_handle, /* Handle to device */ + PGDC_IOCTL_READ_PORT_PP, /* IO Control code for Read */ + (ULONG *)&port, /* Buffer to driver. */ + sizeof(int), /* Length of buffer in bytes. */ + (ULONG *)&data, /* Buffer from driver. */ + sizeof(int), /* Length of buffer in bytes. */ + (ULONG *)&returned_length, /* Bytes placed in data_buffer. */ + NULL); /* Wait for operation to complete */ + + if ((!status) || (returned_length != sizeof(int))) + { + fprintf(stderr, "I/O error: Cannot access ByteBlaster hardware\n"); + CloseHandle(nt_device_handle); + exit(1); + } + } + else +#endif + { + /* + * On Windows 95, access hardware directly + */ + data = inp((WORD)(port + lpt_addr)); + } + + return (data & 0xff); +} + +#if PORT == WINDOWS +void flush_ports(void) +{ + ULONG n_writes = 0L; + BOOL status; + + status = DeviceIoControl( + nt_device_handle, /* handle to device */ + PGDC_IOCTL_PROCESS_LIST_PP, /* IO control code */ + (LPVOID)port_io_buffer, /* IN buffer (list buffer) */ + port_io_count * sizeof(struct PORT_IO_LIST_STRUCT),/* length of IN buffer in bytes */ + (LPVOID)port_io_buffer, /* OUT buffer (list buffer) */ + port_io_count * sizeof(struct PORT_IO_LIST_STRUCT),/* length of OUT buffer in bytes */ + &n_writes, /* number of writes performed */ + 0); /* wait for operation to complete */ + + if ((!status) || ((port_io_count * sizeof(struct PORT_IO_LIST_STRUCT)) != n_writes)) + { + fprintf(stderr, "I/O error: Cannot access ByteBlaster hardware\n"); + CloseHandle(nt_device_handle); + exit(1); + } + + port_io_count = 0; +} +#endif /* PORT == WINDOWS */ +#endif /* PORT == WINDOWS || PORT == DOS */ + +#if !defined (DEBUG) +#pragma optimize ("ceglt", off) +#endif + +void delay_loop(long count) +{ + while (count != 0L) count--; +} diff --git a/common/recipes-utils/jbi/files/make/Microsoft/nmake.mak b/common/recipes-utils/jbi/files/make/Microsoft/nmake.mak new file mode 100644 index 0000000..352a9c5 --- /dev/null +++ b/common/recipes-utils/jbi/files/make/Microsoft/nmake.mak @@ -0,0 +1,65 @@ +#
+# Module: makefile
+#
+# Copyright (C) Altera Corporation 1998-2001
+#
+# Description: Makefile for JAM Bytecode Player
+#
+
+OBJS = \
+ jbistub.obj \
+ jbimain.obj \
+ jbicomp.obj \
+ jbijtag.obj
+
+
+!IF "$(MEM_TRACKER)" != ""
+!IF "$(STATIC_MEMORY_SIZE)" != ""
+# MEMORY TRACKER ON, USE 'STATIC_MEMORY_SIZE' KB OF STATIC MEMORY
+.c.obj::
+ cl /W4 /c /O2 /ML /DWINNT /DMEM_TRACKER /DUSE_STATIC_MEMORY=$(STATIC_MEMORY_SIZE) $<
+!ELSE
+# MEMORY TRACKER ON, USE DYNAMIC MEMORY
+.c.obj::
+ cl /W4 /c /O2 /ML /DWINNT /DMEM_TRACKER $<
+!ENDIF
+!ELSE
+!IF "$(STATIC_MEMORY_SIZE)" != ""
+# MEMORY TRACKER OFF, USE 'STATIC_MEMORY_SIZE' KB OF STATIC MEMORY
+.c.obj::
+ cl /W4 /c /O2 /ML /DWINNT /DUSE_STATIC_MEMORY=$(STATIC_MEMORY_SIZE) $<
+!ELSE
+# MEMORY TRACKER OFF, USE DYNAMIC MEMORY
+.c.obj::
+ cl /W4 /c /O2 /ML /DWINNT $<
+!ENDIF
+!ENDIF
+
+jbi.exe : $(OBJS)
+ link $(OBJS) advapi32.lib /out:jbi.exe
+
+# Dependencies:
+
+jbistub.obj : \
+ jbistub.c \
+ jbiport.h \
+ jbiexprt.h
+
+jbimain.obj : \
+ jbimain.c \
+ jbiport.h \
+ jbiexprt.h \
+ jbijtag.h \
+ jbicomp.h
+
+jamcomp.obj : \
+ jamcomp.c \
+ jbiport.h \
+ jbiexprt.h \
+ jbicomp.h
+
+jbijtag.obj : \
+ jbijtag.c \
+ jbiport.h \
+ jbiexprt.h \
+ jbijtag.h
diff --git a/common/recipes-utils/jbi/files/make/PCVS/PVCS16.MAK b/common/recipes-utils/jbi/files/make/PCVS/PVCS16.MAK new file mode 100644 index 0000000..e943aa4 --- /dev/null +++ b/common/recipes-utils/jbi/files/make/PCVS/PVCS16.MAK @@ -0,0 +1,61 @@ +#
+# Module: makefile
+#
+# Copyright (C) Altera Corporation 1998-2001
+#
+# Description: Makefile for JAM Bytecode Player
+#
+
+OBJS = \
+ jbistub.obj \
+ jbimain.obj \
+ jbicomp.obj \
+ jbijtag.obj
+
+
+%if "$(MEM_TRACKER)" && "$(STATIC_MEMORY_SIZE)"
+# MEMORY TRACKER ON, USE 'STATIC_MEMORY_SIZE' KB OF STATIC MEMORY
+.c.obj :
+ cl /W4 /AL /c /O2 /Zp1 /DPORT=DOS /DMEM_TRACKER /DUSE_STATIC_MEMORY=$(STATIC_MEMORY_SIZE) $<
+%elseif "$(MEM_TRACKER)" && !"$(STATIC_MEMORY_SIZE)"
+# MEMORY TRACKER ON, USE DYNAMIC MEMORY
+.c.obj :
+ cl /W4 /AL /c /O2 /Zp1 /DPORT=DOS /DMEM_TRACKER $<
+%elseif !"$(MEM_TRACKER)" && "$(STATIC_MEMORY_SIZE)"
+# MEMORY TRACKER OFF, USE 'STATIC_MEMORY_SIZE' KB OF STATIC MEMORY
+.c.obj :
+ cl /W4 /AL /c /O2 /Zp1 /DPORT=DOS /DUSE_STATIC_MEMORY=$(STATIC_MEMORY_SIZE) $<
+%else !"$(MEM_TRACKER)" && !"$(STATIC_MEMORY_SIZE)"
+# MEMORY TRACKER OFF, USE DYNAMIC MEMORY
+.c.obj :
+ cl /W4 /AL /c /O2 /Zp1 /DPORT=DOS $<
+%endif
+
+jbi.exe : $(OBJS)
+ link /STACK:0x8000 $(OBJS), jbi.exe,,,,
+
+# Dependencies:
+
+jbistub.obj : \
+ jbistub.c \
+ jbiport.h \
+ jbiexprt.h
+
+jbimain.obj : \
+ jbimain.c \
+ jbiport.h \
+ jbiexprt.h \
+ jbijtag.h \
+ jbicomp.h
+
+jamcomp.obj : \
+ jamcomp.c \
+ jbiport.h \
+ jbiexprt.h \
+ jbicomp.h
+
+jbijtag.obj : \
+ jbijtag.c \
+ jbiport.h \
+ jbiexprt.h \
+ jbijtag.h
diff --git a/common/recipes-utils/jbi/files/make/PCVS/pvcs32.mak b/common/recipes-utils/jbi/files/make/PCVS/pvcs32.mak new file mode 100644 index 0000000..409ef47 --- /dev/null +++ b/common/recipes-utils/jbi/files/make/PCVS/pvcs32.mak @@ -0,0 +1,61 @@ +#
+# Module: makefile
+#
+# Copyright (C) Altera Corporation 1998-2001
+#
+# Description: Makefile for JAM Bytecode Player
+#
+
+OBJS = \
+ jbistub.obj \
+ jbimain.obj \
+ jbicomp.obj \
+ jbijtag.obj
+
+
+%if "$(MEM_TRACKER)" && "$(STATIC_MEMORY_SIZE)"
+# MEMORY TRACKER ON, USE 'STATIC_MEMORY_SIZE' KB OF STATIC MEMORY
+.c.obj :
+ cl /W4 /c /O2 /ML /DWINNT /DMEM_TRACKER /DUSE_STATIC_MEMORY=$(STATIC_MEMORY_SIZE) $<
+%elseif "$(MEM_TRACKER)" && !"$(STATIC_MEMORY_SIZE)"
+# MEMORY TRACKER ON, USE DYNAMIC MEMORY
+.c.obj :
+ cl /W4 /c /O2 /ML /DWINNT /DMEM_TRACKER $<
+%elseif !"$(MEM_TRACKER)" && "$(STATIC_MEMORY_SIZE)"
+# MEMORY TRACKER OFF, USE 'STATIC_MEMORY_SIZE' KB OF STATIC MEMORY
+.c.obj :
+ cl /W4 /c /O2 /ML /DWINNT /DUSE_STATIC_MEMORY=$(STATIC_MEMORY_SIZE) $<
+%else !"$(MEM_TRACKER)" && !"$(STATIC_MEMORY_SIZE)"
+# MEMORY TRACKER OFF, USE DYNAMIC MEMORY
+.c.obj :
+ cl /W4 /c /O2 /ML /DWINNT $<
+%endif
+
+jbi.exe : $(OBJS)
+ link $(OBJS) advapi32.lib /out:jbi.exe
+
+# Dependencies:
+
+jbistub.obj : \
+ jbistub.c \
+ jbiport.h \
+ jbiexprt.h
+
+jbimain.obj : \
+ jbimain.c \
+ jbiport.h \
+ jbiexprt.h \
+ jbijtag.h \
+ jbicomp.h
+
+jamcomp.obj : \
+ jamcomp.c \
+ jbiport.h \
+ jbiexprt.h \
+ jbicomp.h
+
+jbijtag.obj : \
+ jbijtag.c \
+ jbiport.h \
+ jbiexprt.h \
+ jbijtag.h
diff --git a/common/recipes-utils/jbi/files/readme.openbmc b/common/recipes-utils/jbi/files/readme.openbmc new file mode 100644 index 0000000..f8620f7 --- /dev/null +++ b/common/recipes-utils/jbi/files/readme.openbmc @@ -0,0 +1,5 @@ +Changeset from the original jdi_22.exe + +1. removed all files in 'exe/' +2. renamed all files in 'code' to lower case +3. converted all files in 'code' from DOS style to UNIX style
\ No newline at end of file diff --git a/common/recipes-utils/jbi/files/readme.txt b/common/recipes-utils/jbi/files/readme.txt new file mode 100644 index 0000000..813d88d --- /dev/null +++ b/common/recipes-utils/jbi/files/readme.txt @@ -0,0 +1,464 @@ +********************************************************************************************
+ Jam STAPL Byte-Code Player Version 2.2 README 7/15/2002
+********************************************************************************************
+
+CONTENTS
+
+A. DESCRIPTION
+B. INCLUDED IN THIS RELEASE
+C. NEW IN VERSION 2.2
+D. RUNNING THE PLAYER IN COMMAND-LINE MODE
+E. PORTING THE JAM STAPL BYTE-CODE PLAYER
+F. JAM STAPL BYTE-CODE PLAYER API
+G. MEMORY USAGE
+H. SUPPORT
+
+A. DESCRIPTION
+--------------
+The Jam STAPL Byte-Code Player is a software driver that allows test and programming algorithms
+for IEEE 1149.1 Joint Test Action Group (JTAG)-compliant devices to be asserted via the
+JTAG port. The Jam STAPL Byte-Code Player reads and decodes information in Jam STAPL
+Byte-Code Files (.jbc) to program and test programmable logic devices (PLDs), memories,
+and other devices in a JTAG chain. The Jam STAPL Byte-Code Player complies with STAPL
+(Standard Test and Programming Language) Specification JESD-71. The construction of the
+Player permits fast programming times, small programming files, and easy in-field upgrades.
+Upgrades are simplified, because all programming/test algorithms and data are confined to the
+Jam STAPL Byte-Code File. Version 2.2 supports Jam STAPL Byte-Code Files (.jbc) that have been
+compiled using the Jam STAPL Byte-Code Compiler. The Player is also able to read and "play"
+older Jam Byte-Code files based on Jam v1.1 syntax.
+ The .jbc File is a binary version of the ASCII Jam File (.jam). The Jam STAPL Byte-Code
+format consists, among other things, of a "byte code" representation of Jam commands, as
+they are defined in STAPL Specification JESD-71. This means that the .jbc File is simply a
+different implementation of the .jam file. This binary implementation results in smaller
+file sizes and shorter programming times.
+ This document should be used together with AN 122 (Using STAPL for ISP & ICR via
+an Embedded Processor).
+
+B. INCLUDED IN THIS RELEASE
+---------------------------
+The following tables provide the directory structure of the files on this CD-ROM:
+
+Directory Filename Description
+--------- -------- -----------------------
+\exe \16-bit-DOS\jbi16.exe Supports the BitBlaster serial,
+ ByteBlaster parallel, Xilinx
+ Parallel Download Cable III, and
+ Lattice ispDOWNLOAD cables for
+ PCs running 16-bit DOS platforms.
+
+ \Win9598-WinNT\jbi32.exe Supports the BitBlaster serial
+ ByteBlaster parallel, Xilinx
+ Parallel Download Cable III, and
+ Lattice ispDOWNLOAD cables for
+ PCs running 32-bit Windows
+ (Windows 95, Windows 98 and Windows NT)
+
+
+Directory Filename Description
+--------- -------- ------------------------------------------
+\code jbicomp.h Source code for the Jam STAPL Byte-Code Player
+ jbiexprt.h
+ jbijtag.h
+ jbiport.h
+ jbicomp.c
+ jbijtag.c
+ jbimain.c
+ jbistub.c
+
+Directory Filename Description
+--------- -------- ------------------------------------------
+\make \microsoft\makefile.mak Make file compatible with Microsoft Visual
+ C++ compiler v5.0. Builds a 32-bit windows
+ console executable.
+
+\make \pvcs\pvcs32.mak Builds a 32-bit executable.
+
+\make \pvcs\pvcs16.mak Builds a 16-bit executable.
+
+
+C. NEW IN VERSION 2.2
+---------------------
+Updates in the Jam STAPL Byte-Code Player version 2.2 include:
+
+* fixed /W4 warnings
+* updated JTAG state transition paths
+
+
+D. RUNNING THE JAM STAPL BYTE-CODE PLAYER IN COMMAND-LINE MODE
+--------------------------------------------------------------
+If the Player is going to be run on a PC or a workstation, the following commands can be
+used to execute programming or other tasks:
+
+Jam STAPL Byte-Code Player Version 2.2
+Copyright (C) 1998-2000 Altera Corporation
+
+Usage: jbi [options] <filename>
+
+Available options:
+ -h : show help message
+ -v : show verbose messages
+ -i : show file info only - do not execute
+ -a<action> : specify action name (Jam STAPL)
+ -d<var=val> : initialize variable to specified value (Jam 1.1)
+ -d<proc=1> : enable optional procedure (Jam STAPL)
+ -d<proc=0> : disable recommended procedure (Jam STAPL)
+ -p<port> : parallel port number or address (for ByteBlaster)
+ -c<cable> : alternative download cable compatibility: -cl or -cx
+ -s<port> : serial port name (for BitBlaster)
+ -r : don't reset JTAG TAP after use
+
+Command line text is not case-sensitive.
+
+Use the -a flag when applying Jam STAPL Byte-Code files. Use the -d flag when applying Jam v1.1
+Byte-Code files.
+
+Valid action names, as specified by JEDEC Standard JESD-71 are:
+
+ Action Name Description
+ ----------- -----------
+ CHECKCHAIN Verify the continuity of the IEEE 1149.1 JTAG scan chain
+ READ_IDCODE Read the IEEE 1149.1 IDCODE and EXPORT it (print it)
+ READ_USERCODE Read the IEEE 1149.1 USERCODE and EXPORT it (print it)
+ READ_UES Read the IEEE 1149.1 UESCODE and EXPORT it (print it)
+ ERASE Perform a bulk erase of the device(s)
+ BLANKCHECK Check the erased state of the device(s)
+ PROGRAM Program the device
+ VERIFY Verify the programming data of the device(s)
+ READ Read the programming data of the device(s)
+ CHECKSUM Calculate one fuse checksum of the programming data of the device(s)
+ SECURE Set the security bit of the device(s)
+ QUERY_SECURITY Check whether the security bit is set
+ TEST Perform a test. This test can include tests such as boundary-scan,
+ internal, vector, and built-in self tests
+
+Valid initialization variables and values for the -d flag are:
+
+ Initialization String Value Action
+ --------------------- ----- ------
+ DO_PROGRAM 0 Do not program the device
+ DO_PROGRAM 1 Program the device
+ DO_VERIFY 0 Do not verify the device
+ DO_VERIFY 1 Verify the device
+ DO_BLANKCHECK 0 Do not check the erased state of the device
+ DO_BLANKCHECK 1 Check the erased state of the device
+ READ_UESCODE 0 Do not read the JTAG UESCODE
+ READ_UESCODE 1 Read UESCODE and export it
+ DO_SECURE 0 Do not set the security bit
+ DO_SECURE 1 Set the security bit
+
+
+E. PORTING THE JAM STAPL BYTE-CODE PLAYER
+-----------------------------------------
+The Jam STAPL Byte-Code Player is designed to be easily ported to any processor-based hardware
+system. All platform-specific code is placed in the jbistub.c and jbimain.c files. Routines
+that perform any interaction with the outside world are confined to the jbistub.c source
+file. Preprocessor statements encase operating system-specific code and code pertaining to
+specific hardware. All changes to the source code for porting are mostly confined to the
+jbistub.c file and in some cases porting the Jam Player is as simple as changing a
+single #define statement. This process also makes debugging simple. For example, if
+the jbistub.c file has been customized for a particular embedded application, but is
+not working, the equivalent DOS Jam STAPL Byte-Code Player and a download cable can be used to
+check the hardware continuity and provide a "known good" starting point from which to attack
+the problem.
+
+The jbistub.c and jbimain.c files in this release target the DOS operating system, by default.
+To change the targeted platform, edit the following line in the jbistub.c and jbimain.c files:
+
+ #define PORT DOS
+
+The preprocessor statement takes the form:
+
+ #define PORT [PLATFORM]
+
+Change the [PLATFORM] field to one of the supported platforms: EMBEDDED, DOS, WINDOWS,
+or UNIX. The following table explains how to port the Jam STAPL Byte-Code Player for each of the
+supported platforms:
+
+PLATFORM COMPILER ACTIONS
+-------- -------- ---------------------------------------------
+EMBEDDED 16 or 32-bit Change #define and see EMBEDDED PLATFORM below
+DOS 16-bit Change #define and compile
+WINDOWS 32-bit Change #define and compile
+UNIX 32-bit Change #define and compile
+
+The source code supplied in this release is ANSI C source. In cases where a different
+download cable or other hardware is used, the DOS, WINDOWS, and UNIX platforms will require
+additional code customization, which is described below.
+
+EMBEDDED PLATFORM
+Because there are many different kinds of embedded systems, each with different hardware and
+software requirements, some additional customization must be done to port the Jam STAPL
+Byte-Code Player for embedded systems. To port the Player, the following functions may
+need to be customized:
+
+FUNCTION DESCRIPTION
+--------- ------------------------------------------------------------------
+jbi_jtag_io() Interface to the IEEE 1149.1 JTAG signals, TDI, TMS, TCK, and TDO.
+jbi_message() Prints information and error text to standard output, when available.
+jbi_export() Passes information such as the User Electronic Signature (UES) back to the
+ calling program.
+jbi_delay() Implements the programming pulses or delays needed during execution.
+
+Miscellaneous
+jbi_vector_map() Processes signal-to-pin map for non-IEEE 1149.1 JTAG signals.
+jbi_vector_io() Asserts non-IEEE 1149.1 JTAG signals as defined in the VECTOR MAP.
+
+jbi_jtag_io()
+-------------
+int jbi_jtag_io(int tms, int tdi, int read_tdo)
+
+This function provides exclusive access to the IEEE 1149.1 JTAG signals. You must always
+customize this function to write to the proper hardware port.
+
+The code in this release supports a serial mode specific to the Altera BitBlaster download
+cable. If a serial interface is required, this code can be customized for that purpose.
+However, this customization would require some additional processing external to the
+embedded processor to turn the serial data stream into valid JTAG vectors. This readme file
+does not discuss customization of serial mode. Contact Altera Applications at (800) 800-EPLD
+for more information.
+
+In most cases a parallel byte mode is used. When in byte mode, jbi_jtag_io() is passed
+the values of TMS and TDI. Likewise, the variable read_tdo tells the function whether
+reading TDO is required. (Because TCK is a clock and is always written, it is written
+implicitly within the function.) If requested, jbi_jtag_io() returns the value of TDO read.
+Sample code is shown below:
+
+int jbi_jtag_io(int tms, int tdi, int read_tdo)
+{
+ int data = 0;
+ int tdo = 0;
+
+ if (!jtag_hardware_initialized)
+ {
+ initialize_jtag_hardware();
+ jtag_hardware_initialized = TRUE;
+ }
+
+ data = ((tdi ? 0x40 : 0) | (tms ? 0x02 : 0));
+
+ write_byteblaster(0, data);
+
+ if (read_tdo)
+ {
+ tdo = (read_byteblaster(1) & 0x80) ? 0 : 1;
+ }
+
+ write_byteblaster(0, data | 0x01);
+
+ write_byteblaster(0, data);
+
+ return (tdo);
+}
+
+The code, as shown above, is configured to read/write to a PC parallel port.
+initialize_jtag_hardware() sets the control register of the port for byte mode. As shown
+above, jbi_jtag_io() reads and writes to the port as follows:
+
+|---------------------------------------------------------------|
+| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | I/O Port
+|---------------------------------------------------------------|
+| 0 | TDI | 0 | 0 | 0 | 0 | TMS | TCK | OUTPUT DATA - Base Address
+|---------------------------------------------------------------|
+| !TDO | X | X | X | X | --- | --- | --- | INPUT DATA - Base Address + 1
+|---------------------------------------------------------------|
+
+The PC parallel port inverts the actual value of TDO. Thus, jbi_jtag_io() inverts
+it again to retrieve the original data. Inverted:
+
+ tdo = (read_byteblaster(1) & 0x80) ? 0 : 1;
+
+If the target processor does not invert TDO, the code should look like:
+
+ tdo = (read_byteblaster(1) & 0x80) ? 1 : 0;
+
+To map the signals to the correct addresses simply use the left shift (<<) or right shift
+(>>) operators. For example, if TMS and TDI are at ports 2 and 3, respectively, then the
+code would be as shown below:
+
+ data = (((tdi ? 0x40 : 0)>>3) | ((tms ? 0x02 : 0)<<1));
+
+The same process applies to TCK and TDO.
+
+read_byteblaster() and write_byteblaster() use the inp() and outp() <conio.h> functions,
+respectively, to read and write to the port. If these functions are not available,
+equivalent functions should be substituted.
+
+jbi_message()
+--------------
+void jam_message(char *message_text)
+
+When the Jam STAPL Byte-Code Player encounters a PRINT command within the .jbc File, it processes
+the message text and passes it to jbi_message(). The text is sent to stdio. If a standard
+output device is not available, jbi_message() does nothing and returns. The Jam STAPL
+Byte-Code Player does not append a newline character to the end of the text message.
+This function should append a newline character for those systems that require one.
+
+jbi_export()
+------------
+void jbi_export(char *key, long value)
+
+The jbi_export() function sends information to the calling program in the form of a text
+string and associated integer value. The text string is called the key string and it
+determines the significance and interpretation of the integer value. An example use of this
+function would be to report the device USERCODE back to the calling program.
+
+jbi_delay()
+-----------
+void jbi_delay(long microseconds)
+
+jbi_delay() is used to implement programming pulse widths necessary for programming PLDs,
+memories, and configuring SRAM-based devices. These delays are implemented using software
+loops calibrated to the speed of the targeted embedded processor. The Jam STAPL Byte-Code
+Player is told how long to delay with the .jbc File WAIT command. This function can be
+customized easily to measure the passage of time via a hardware-based timer. jbi_delay()
+must perform accurately over the range of one millisecond to one second. The function can
+take as much as 10% more time than is specified, but cannot return in less time. To minimize
+the time to execute the Jam statements, it is generally recommended to calibrate the delay as
+accurately as possible.
+
+Miscellaneous Functions
+------------------------
+jbi_vector_map() and jbi_vector_io()
+
+The VMAP and VECTOR Jam commands are translated by these functions to assert signals to
+non-JTAG ports. Altera .jbc Files do not use these commands. If the Jam STAPL Byte-Code Player
+will be used only to program Altera devices, these routines can be removed. In the event
+that the Jam Player does encounter the VMAP and VECTOR commands, it will process the
+information so that non-JTAG signals can be written and read as defined by JEDEC Specification
+JESD-71.
+
+jbi_malloc()
+
+void *jam_malloc(unsigned int size)
+
+During execution, the Jam STAPL Byte-Code Player will allocate memory to perform its tasks. When
+it allocates memory, it calls the jbi_malloc() function. If malloc() is not available to the
+embedded system it must be replaced with an equivalent function.
+
+jbi_free()
+
+void jbi_free(void *ptr)
+
+This function is called when the Jam STAPL Byte-Code Player frees memory. If free() is not
+available to the embedded system, it must be replaced with an equivalent function.
+
+F. JAM STAPL Byte-Code Player API
+---------------------------------
+The main entry point for the Jam Player is the jbi_execute function:
+
+JAM_RETURN_TYPE jbi_execute
+(
+ PROGRAM_PTR program,
+ long program_size,
+ char *workspace,
+ long workspace_size,
+ char *action,
+ char **init_list,
+ long *error_line,
+ int *exit_code,
+ int *format_version
+)
+
+This routine recieves 6 parameters, passes back 2 parameters, and returns a status
+code (of JAM_RETURN_TYPE). This function is called once in main(), which is coded in the
+jbistub.c file (jbi_execute() is defined in the jbimain.c file). Some processing is done in
+main() to check for valid data being passed to jbi_execute(), and to set up some of the
+buffering required to store the .jbc File.
+
+The program parameter is a pointer to the memory location where the .jbc File is stored
+(memory space previously malloc'd and assigned in main()). jbi_execute() assigns this
+pointer to the global variable jbi_program, which provides the rest of the Jam STAPL
+Byte-Code Player with access to the .jbc File via the GET_BYTE, GET_WORD, and
+GET_DWORD macros.
+
+program_size provides the number of bytes stored in the memory buffer occupied
+by the .jbc File.
+
+workspace points to memory previously allocated in main(). This space is the sum of all
+memory reserved for all of the processing that the Jam STAPL Byte-Code Player must do, including
+the space taken by the .jbc File. Memory is only used in this way when the Jam STAPL Byte-Code
+Player is executed using the -m console option. If the -m option is not used, the Jam Byte
+Code Player is free to allocate memory dynamically as it is needed. In this case, workspace
+points to NULL. jbi_execute() assigns the workspace pointer to the global variable,
+jbi_workspace, giving the rest of the Jam STAPL Byte-Code Player access to this block of memory.
+
+workspace_size provides the size of the workspace in bytes. If the workspace pointer points
+to NULL this parameter is ignored. jbi_execute() assigns workspace_size to the global
+variable, jbi_workspace_size.
+
+action is the way the Player is told what function should be performed, as defined
+by STAPL. (i.e. PROGRAM, READ_USERCODE, etc) The action pointer points to the string
+that tells the Player what functions to execute within the .jbc file. Each action can
+contain "recommended" and "optional" sub-actions. "Recommended" sub-actions are those
+that will be executed by default, while "optional" sub-actions will be skipped.
+For example, passing "PROGRAM\0" will result in the following steps for an Altera .jbc
+file:
+ - ERASE (recommended)
+ - BLANKCHECK (optional)
+ - PROGRAM (recommended)
+ - VERIFY (recommended)
+
+So, by simply passing "PROGRAM\0" the device will be programmed and verified. This is the
+action Altera recommends using with it's .jbc files. If you want to add the BLANKCHECK step
+you must pass "DO_BLANKCHECK=1\0" via the init_list pointer. See Section D for other valid
+action strings. Note that the action string must be NULL terminated.
+
+init_list is a parameter that is used when applying pre-JEDEC, Jam v1.1 .jbc files, or when
+overriding optional sub-actions, as in the example above. While older pre-JEDEC .jbc files
+can be played, it is strongly recommended that STAPL-based .jbc files be used. When using
+STAPL-based .jbc files, init_list should point to NULL. If an older .jbc file must be used,
+see AN 88 for more details on the parameters that init_list can point to.
+
+If an error occurs during execution of the .jbc File, error_line provides the
+line number of the .jbc File where the error occured. This error is associated
+with the function of the device, as opposed to a syntax or software error in the .jbc File.
+
+exit_code provides general information about the nature of an error associated with a
+malfunction of the device or a functional error:
+
+ exit_code Description
+ --------- -----------
+ 0 Success
+ 1 Checking chain failure
+ 2 Reading IDCODE failure
+ 3 Reading USERCODE failure
+ 4 Reading UESCODE failure
+ 5 Entering ISP failure
+ 6 Unrecognized device
+ 7 Device version is not supported
+ 8 Erase failure
+ 9 Device is not blank
+ 10 Device programming failure
+ 11 Device verify failure
+ 12 Read failure
+ 13 Calculating checksum failure
+ 14 Setting security bit failure
+ 15 Querying security bit failure
+ 16 Exiting ISP failure
+ 17 Performing system test failure
+
+These codes are intended to provide general information about the nature of the failure.
+Additional analysis would need to be done to determine the root cause of any one of these
+errors. In most cases, if there is any device-related problem or hardware continuity
+problem, the "Unrecognized device" error will be issued. In this case, first take the
+steps outlined in Section D for debugging the Jam Player. If debugging is unsuccessful,
+contact Altera for support.
+
+If the "Device version is not supported" error is issued, it is most likely due to a
+.jbc File that is older than the current device revision. Always use the latest version of
+MAX+PLUS II to generate the .jbc File. For more support, see Section G.
+
+jbi_execute() returns with a code indicating the success or failure of the execution. This
+code is confined to errors associated with the syntax and structural accuracy of the .jbc
+File. These codes are defined in the jbistub.c file, where the array variable "error_text[]".
+
+format_version should be set equal to "2" when calling jbi_execute. This means that the
+Player will expect a STAPL-based .jbc file.
+
+G. MEMORY USAGE
+Memory usage is documented in detail in AN 122 (Using the Jam Language for ISP via an
+Embedded Processor).
+
+H. SUPPORT
+For additional support, submit a Service Request at http://www.altera.com/mysupport. Bugs or
+suggested enhancements can also be communicated via this channel.
\ No newline at end of file diff --git a/common/recipes-utils/jbi/jbi_2.2.bb b/common/recipes-utils/jbi/jbi_2.2.bb new file mode 100644 index 0000000..947dbac --- /dev/null +++ b/common/recipes-utils/jbi/jbi_2.2.bb @@ -0,0 +1,41 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "ALTERA Jam STAPL Byte-Code Player" +SECTION = "utils" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a" + +SRC_URI = "file://code \ + " + +S = "${WORKDIR}/code" + +DEPENDS += "liblog libgpio" + +do_install() { + bin="${D}/usr/local/bin" + install -d ${bin} + install -m 755 jbi ${bin}/jbi +} + +FILES_${PN} = "/usr/local/bin" + +FILES_${PN}-dbg += "/usr/local/bin/.debug" + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/common/recipes-utils/openbmc-gpio/files/COPYING b/common/recipes-utils/openbmc-gpio/files/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/common/recipes-utils/openbmc-gpio/files/board_gpio_table.py b/common/recipes-utils/openbmc-gpio/files/board_gpio_table.py new file mode 100644 index 0000000..3261f51 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/board_gpio_table.py @@ -0,0 +1,23 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +# This is an dummy board GPIO table. If this is included in the final image, +# please double check the configuration of your image to define the correct +# GPIO table to be used for your board. + +board_gpio_table = [ +] diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio.py new file mode 100644 index 0000000..9e92324 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio.py @@ -0,0 +1,164 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import logging +import os +import string + + +_gpio_shadow = '/tmp/gpionames' + + +def setup_shadow(shadow=None): + global _gpio_shadow + if shadow is not None: + _gpio_shadow = shadow + if not os.path.exists(_gpio_shadow): + os.makedirs(_gpio_shadow) + + +def gpio_name2value(name): + name = str(name).lower() + if name.startswith('gpio'): + name = name[4:] + try: + return int(name) + except: + # it is not just value, try treat it as name like 'A0' + pass + val = 0 + try: + if len(name) != 2 and len(name) != 3: + raise + for idx in range(0, len(name)): + ch = name[idx] + if ch in string.ascii_lowercase: + # letter cannot be the last character + if idx == len(name) - 1: + raise + tmp = ord(ch) - ord('a') + 1 + val = val * 26 + tmp + elif ch in string.digits: + # digit must be the last character + if idx != len(name) - 1: + raise + # the digit must be 0-7 + tmp = ord(ch) - ord('0') + if tmp > 7: + raise + # 'A4' is value 4 + if val > 0: + val -= 1 + val = val * 8 + tmp + else: + raise + except: + logging.exception('Invalid GPIO name "%s"' % name) + return val + + +def gpio_dir(name, check_shadow=True): + GPIODIR_FMT = '/sys/class/gpio/gpio{gpio}' + if check_shadow: + shadowdir = os.path.join(_gpio_shadow, name) + if os.path.isdir(shadowdir): + return shadowdir + val = gpio_name2value(name) + return GPIODIR_FMT.format(gpio=val) + + +def gpio_get_shadow(name): + path = gpio_dir(name, check_shadow=False) + for child in os.listdir(_gpio_shadow): + try: + child = os.path.join(_gpio_shadow, child) + if os.readlink(child) == path: + return child + except: + pass + return None + + +def gpio_export(name, shadow=None): + GPIOEXPORT = '/sys/class/gpio/export' + if shadow is not None or shadow != '': + shadowdir = os.path.join(_gpio_shadow, shadow) + if os.path.exists(shadowdir): + raise Exception('Shadow "%s" exists already' % shadowdir) + old_shadow = gpio_get_shadow(name) + if old_shadow is not None: + raise Exception('Shadow "%s" already exists for %s' + % (old_shadow, name)) + + val = gpio_name2value(name) + try: + with open(GPIOEXPORT, 'w') as f: + f.write('%d\n' % val) + except: + # in case the GPIO has been exported already + pass + if shadow is not None: + gpiodir = gpio_dir(val, check_shadow=False) + os.symlink(gpiodir, shadowdir) + + +def gpio_get(name, change_direction=True): + path = gpio_dir(name) + if change_direction: + with open(os.path.join(path, 'direction'), 'w') as f: + f.write('in\n') + with open(os.path.join(path, 'value'), 'r') as f: + val = int(f.read().rstrip('\n')) + return val + + +def gpio_set(name, value, change_direction=True): + path = gpio_dir(name) + with open(os.path.join(path, 'value'), 'w') as f: + f.write('%d\n' % (1 if value else 0)) + if change_direction: + with open(os.path.join(path, 'direction'), 'w') as f: + f.write('out\n') + + +def gpio_info(name): + res = {} + # first check if name is shadow + path = None + shadow = os.path.join(_gpio_shadow, name) + if os.path.exists(shadow): + if not os.path.islink(shadow) or not os.path.isdir(shadow): + raise Exception('Path "%s" is not a valid shadow path' % shadow) + path = os.readlink(shadow) + else: + path = gpio_dir(name, check_shadow=False) + shadow = gpio_get_shadow(name) + res['path'] = path + res['shadow'] = shadow + if os.path.isdir(path): + with open(os.path.join(path, 'direction'), 'r') as f: + res['direction'] = f.read().rstrip('\n') + with open(os.path.join(path, 'value'), 'r') as f: + res['value'] = int(f.read().rstrip('\n')) + else: + res['direction'] = None + res['value'] = None + return res diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_setup.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_setup.py new file mode 100644 index 0000000..7c126d9 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_setup.py @@ -0,0 +1,76 @@ +#!/usr/bin/python -tt +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from board_gpio_table import board_gpio_table +from soc_gpio_table import soc_gpio_table + +import openbmc_gpio +import openbmc_gpio_table + +import logging +import sys + + +def setup_board_gpio(soc_gpio_table, board_gpio_table, validate=True): + soc = openbmc_gpio_table.SocGPIOTable(soc_gpio_table) + gpio_configured = [] + for gpio in board_gpio_table: + try: + soc.config_function(gpio.gpio, write_through=False) + gpio_configured.append(gpio.gpio) + except openbmc_gpio_table.ConfigUnknownFunction as e: + # not multiple-function GPIO pin + pass + except openbmc_gpio_table.NotSmartEnoughException as e: + logging.error('Failed to configure "%s" for "%s": %s' + % (gpio.gpio, gpio.shadow, str(e))) + + soc.write_to_hw() + + if validate: + all_functions = set(soc.get_active_functions(refresh=True)) + for gpio in gpio_configured: + if gpio not in all_functions: + raise Exception('Failed to configure function "%s"' % gpio) + + for gpio in board_gpio_table: + openbmc_gpio.gpio_export(gpio.gpio, gpio.shadow) + if gpio.value == openbmc_gpio_table.GPIO_INPUT: + continue + elif gpio.value == openbmc_gpio_table.GPIO_OUT_HIGH: + openbmc_gpio.gpio_set(gpio.gpio, 1) + elif gpio.value == openbmc_gpio_table.GPIO_OUT_LOW: + openbmc_gpio.gpio_set(gpio.gpio, 0) + else: + raise Exception('Invalid value "%s"' % gpio.value) + +def main(): + print('Setting up GPIOs ... ', end='') + sys.stdout.flush() + openbmc_gpio.setup_shadow() + setup_board_gpio(soc_gpio_table, board_gpio_table) + print('Done') + sys.stdout.flush() + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py new file mode 100644 index 0000000..dda8a98 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_table.py @@ -0,0 +1,269 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from soc_gpio import soc_get_register + +import logging +import os +import sys + + +class NotSmartEnoughException(Exception): + '''There are few cases the code cannot make good decision on how to configure + the registers automatically. In such cases, this exception is thrown. + ''' + pass + + +class ConfigUnknownFunction(Exception): + '''Unknown function to configure exception''' + pass + + +class BitsEqual(object): + def __init__(self, register, bits, value): + self.register = register + self.bits = bits + self.value = value + + def __str__(self): + return '%s[%s]==0x%x' \ + % (str(soc_get_register(self.register)), self.bits, self.value) + + def get_registers(self): + return set([self.register]) + + def check(self): + return soc_get_register(self.register).bits_value(self.bits) \ + == self.value + + def satisfy(self, **kwargs): + if BitsEqual.check(self): + return + reg = soc_get_register(self.register) + value = self.value + for bit in sorted(self.bits): + if value & 0x1 == 0x1: + reg.set_bit(bit, **kwargs) + else: + reg.clear_bit(bit, **kwargs) + value >>= 1 + + def unsatisfy(self, **kwargs): + if not BitsEqual.check(self): + return + if len(self.bits) > 1: + raise NotSmartEnoughException('Not able to unsatisfy ' + 'multi-bits equal') + bit = self.bits[0] + reg = soc_get_register(self.register) + value = self.value + if value & 0x1 == 0x1: + reg.clear_bit(bit, **kwargs) + else: + reg.set_bit(bit, **kwargs) + + +class BitsNotEqual(BitsEqual): + def __str__(self): + return '%s[%s]!=0x%x' \ + % (str(soc_get_register(self.register)), self.bits, self.value) + + def check(self): + return not BitsEqual.check(self) + + def satisfy(self, **kwargs): + BitsEqual.unsatisfy(self, **kwargs) + + def unsatisfy(self, **kwargs): + BitsEqual.satisfy(self, **kwargs) + + +class AndOrBase(object): + def __init__(self, left, right): + self.left = left + self.right = right + + def get_registers(self): + return self.left.get_registers() | self.right.get_registers() + + def check(self): + raise Exception('This method must be implemented in subclass') + + +class And(AndOrBase): + def __str__(self): + return 'AND(%s, %s)' % (str(self.left), str(self.right)) + + def check(self): + return self.left.check() and self.right.check() + + def satisfy(self, **kwargs): + if self.check(): + return + self.left.satisfy(**kwargs) + self.right.satisfy(**kwargs) + + def unsatisfy(self, **kwargs): + if not self.check(): + return + raise NotSmartEnoughException('Not able to unsatisfy an AND condition') + + +class Or(AndOrBase): + def __str__(self): + return 'OR(%s, %s)' % (str(self.left), str(self.right)) + + def check(self): + return self.left.check() or self.right.check() + + def satisfy(self, **kwargs): + if self.check(): + return + raise NotSmartEnoughException('Not able to satisfy an OR condition') + + def unsatisfy(self, **kwargs): + if not self.check(): + return + self.left.unsatisfy(**kwargs) + self.right.unsatisfy(**kwargs) + + +class Function(object): + def __init__(self, name, condition=None): + self.name = name + self.condition = condition + + def __str__(self): + return 'Function(\'%s\', %s)' % (self.name, str(self.condition)) + + +class SocGPIOTable(object): + def __init__(self, gpio_table): + self.soc_gpio_table = gpio_table + self.registers = set([]) # all HW registers used for GPIO control + self.functions = {} + + self._parse_gpio_table() + self._sync_from_hw() + + def _parse_gpio_table(self): + # first get list of registers based on the SoC GPIO table + for pin, funcs in self.soc_gpio_table.iteritems(): + for func in funcs: + assert func.name not in self.functions + self.functions[func.name] = pin + if func.condition is not None: + self.registers |= func.condition.get_registers() + + def _sync_from_hw(self): + # for each register, create an object and read the value from HW + for reg in self.registers: + soc_get_register(reg).read(refresh=True) + + def write_to_hw(self): + for reg in self.registers: + soc_get_register(reg).write() + + def config_function(self, func_name, write_through=True): + logging.debug('Configure function "%s"' % func_name) + if func_name not in self.functions: + # The function is not multi-function pin + raise ConfigUnknownFunction('Unknown function "%s" ' % func_name) + funcs = self.soc_gpio_table[self.functions[func_name]] + for func in funcs: + cond = func.condition + if func.name == func_name: + # this is the function we want to configure. + # if the condition is None, we are good to go, + # otherwiset, satisfy the condition + if cond is not None: + cond.satisfy(write_through=write_through) + break + else: + # this is not the funciton we want to configure. + # have to make this condition unsatisfied, so that we can go + # to the next function + assert cond is not None + cond.unsatisfy(write_through=write_through) + + def _get_one_pin(self, pin, refresh): + if refresh: + self._sync_from_hw() + funcs = self.soc_gpio_table[pin] + active_func = None + all_funcs = [] + for func in funcs: + cond = func.condition + all_funcs.append('%s:%s' % (func.name, str(cond))) + if active_func is None and (cond is None or cond.check()): + active_func = func.name + + if active_func is None: + logging.error('Pin "%s" has no function set up. ' + 'All possibile functions are %s.' + % (pin, ', '.join(all_funcs))) + return ('', '') + else: + desc = '%s => %s, functions: %s' \ + % (pin, active_func, ', '.join(all_funcs)) + return (active_func, desc) + + def dump_pin(self, pin, out=sys.stdout, refresh=False): + if pin not in self.soc_gpio_table: + raise Exception('"%s" is not a valid pin' % pin) + + _, desc = self._get_one_pin(pin, refresh) + out.write('%s\n' % desc) + + def dump_function(self, func_name, out=sys.stdout, refresh=False): + if func_name not in self.functions: + raise Exception('"%s" is not a valid function name' % func_name) + pin = self.functions[func_name] + self.dump_pin(pin, out=out, refresh=refresh) + + def dump_functions(self, out=sys.stdout, refresh=False): + if refresh: + self._sync_from_hw() + + for pin in self.soc_gpio_table: + self.dump_pin(pin, out=out, refresh=False) + + def get_active_functions(self, refresh=False): + if refresh: + self._sync_from_hw() + + all = [] + for pin in self.soc_gpio_table: + active, _ = self._get_one_pin(pin, False) + all.append(active) + return all + + +GPIO_INPUT = 'input' +GPIO_OUT_HIGH = 'high' +GPIO_OUT_LOW = 'low' + +class BoardGPIO(object): + def __init__(self, gpio, shadow, value=GPIO_INPUT): + self.gpio = gpio + self.shadow = shadow + self.value = value diff --git a/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_util.py b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_util.py new file mode 100644 index 0000000..e4b40b0 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/openbmc_gpio_util.py @@ -0,0 +1,153 @@ +#!/usr/bin/python -tt +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +from soc_gpio_table import soc_gpio_table + +import openbmc_gpio +import openbmc_gpio_table + +import argparse +import logging +import sys + + +def _get_gpio_table(): + gpio = openbmc_gpio_table.SocGPIOTable(soc_gpio_table) + return gpio + + +def dump_func(args): + gpio = _get_gpio_table() + gpio.dump_functions() + return 0 + + +def config_func(args): + gpio = _get_gpio_table() + try: + gpio.config_function(args.function) + except openbmc_gpio_table.NotSmartEnoughException as e: + print('The code is not smart enough to set function "%s": %s\n' + 'Please set the function manually.' + % (args.function, str(e))) + print('The current HW setting for this function is:') + gpio.dump_function(args.function) + return -1 + except Exception as e: + print('Failed to set function "%s": %s\n' + 'Please set the function manually.' + % (args.function, str(e))) + print('The current HW setting for this function is:') + gpio.dump_function(args.function) + logging.exception('Exception:') + return -2 + + print('Function "%s" is set' % args.function) + return 0 + + +def export_func(args): + openbmc_gpio.gpio_export(args.gpio, args.shadow) + + +def set_func(args): + openbmc_gpio.gpio_set(args.gpio, args.value, + change_direction=False if args.keep else True) + + +def get_func(args): + val = openbmc_gpio.gpio_get( + args.gpio, change_direction=False if args.keep else True) + print('%d' % val) + + +def info_func(args): + res = openbmc_gpio.gpio_info(args.gpio) + print('GPIO info for %s:' % args.gpio) + print('Path: %s\nShadow: %s\nDirection: %s\nValue: %s' + % (res['path'], res['shadow'], res['direction'], res['value'])) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument('--debug', action='store_true', + help='Enable debug messages') + + subparser = ap.add_subparsers() + + dump_parser = subparser.add_parser( + 'dump', help='Dump the current HW GPIO settings') + dump_parser.set_defaults(func=dump_func) + + config_parser = subparser.add_parser( + 'config', help='Configure one HW pin to a function') + config_parser.add_argument( + 'function', help='The function name to set') + config_parser.set_defaults(func=config_func) + + export_parser = subparser.add_parser( + 'export', help='Export a GPIO directory') + export_parser.add_argument( + 'gpio', help='The GPIO name, i.e. "A4", or "GPIOD2"') + export_parser.add_argument( + 'shadow', default=None, + help='The shadow name given to this GPIO') + export_parser.set_defaults(func=export_func) + + + set_parser = subparser.add_parser( + 'set', help='Set a value for a GPIO') + set_parser.add_argument( + 'gpio', help='The GPIO name or number') + set_parser.add_argument( + 'value', type=int, choices=[0, 1], + help='The value to set') + set_parser.add_argument( + '-k', '--keep', action='store_true', + help='Keep the GPIO direction') + set_parser.set_defaults(func=set_func) + + get_parser = subparser.add_parser( + 'get', help='Get a GPIO\'s value') + get_parser.add_argument( + 'gpio', help='The GPIO name or number') + get_parser.add_argument( + '-k', '--keep', action='store_true', + help='Keep the GPIO direction') + get_parser.set_defaults(func=get_func) + + info_parser = subparser.add_parser( + 'info', help='Get a GPIO\'s info') + info_parser.add_argument( + 'gpio', help='The GPIO name or number') + info_parser.set_defaults(func=info_func) + + args = ap.parse_args() + + logging.basicConfig(level=logging.DEBUG if args.debug else logging.INFO, + format='%(asctime)s: %(message)s') + + return args.func(args) + + +rc = main() +sys.exit(rc) diff --git a/common/recipes-utils/openbmc-gpio/files/phymemory.py b/common/recipes-utils/openbmc-gpio/files/phymemory.py new file mode 100644 index 0000000..97a0d6e --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/phymemory.py @@ -0,0 +1,100 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import subprocess +import logging + + +class PhyMemory(object): + def __init__(self, addr, name=''): + self.addr = addr + self.name = name + self.write_pending = False + self.value = 0 + + def __del__(self): + if self.write_pending: + logging.warning('Value (0x%x) is not wrote back to address (0x%x)' + % (self.value, self.addr)) + + def __str__(self): + if self.name == '': + return '0x%x' % self.addr + else: + return self.name + + def _read_hw(self): + if self.write_pending: + raise Exception('Value (0x%x) is not wrote back to address (0x%x) ' + 'before reading HW' % (self.value, self.addr)) + cmd = ['devmem', '0x%x' % self.addr] + out = subprocess.check_output(cmd) + self.value = int(out, 16) + logging.debug('Read from %s @0x%x, got value (0x%x)' + % (str(self), self.addr, self.value)) + + def read(self, refresh=True): + if refresh: + self._read_hw() + return self.value + + def write(self, force=False): + if not force and not self.write_pending: + return + cmd = ['devmem', '0x%x' % self.addr, '32', '0x%x' % self.value] + subprocess.check_call(cmd) + self.write_pending = False + logging.debug('Wrote to %s address @0x%x with value (0x%x)' + % (str(self), self.addr, self.value)) + + def set_bit(self, bit, write_through=True): + assert 0 <= bit <= 31 + self.value |= 1 << bit + self.write_pending = True + logging.debug('Set bit %s[%d] (0x%x)' % (str(self), bit, self.value)) + if write_through: + self.write() + + def clear_bit(self, bit, write_through=True): + assert 0 <= bit <= 31 + self.value &= ~(1 << bit) + self.write_pending = True + logging.debug('Clear bit %s[%d] (0x%x)' % (str(self), bit, self.value)) + if write_through: + self.write() + + def is_bit_set(self, bit, refresh=False): + assert 0 <= bit <= 31 + self.read(refresh=refresh) + rc = True if self.value & (0x1 << bit) else False + logging.debug('Test bit %s[%d](0x%x): %s' + % (str(self), bit, self.value, rc)) + return rc + + def bits_value(self, bits, refresh=False): + self.read(refresh=refresh) + value = 0 + for bit in sorted(bits, reverse=True): + assert 0 <= bit <= 31 + value = (value << 1) | ((self.value >> bit) & 0x1) + logging.debug('%s%s is 0x%x (0x%x)' + % (str(self), bits, value, self.value)) + return value diff --git a/common/recipes-utils/openbmc-gpio/files/setup.py b/common/recipes-utils/openbmc-gpio/files/setup.py new file mode 100644 index 0000000..59c7de4 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/setup.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + + +from distutils.core import setup + +setup( + name = 'openbmc-gpio', + version = '1.0', + description = 'OpenBMC GPIO utilities', + author = 'Tian Fang', + author_email = 'tfang@fb.com', + license = 'GPLv2', + py_modules=['openbmc_gpio', + 'openbmc_gpio_table', + 'phymemory', + 'soc_gpio', + 'soc_gpio_table', + 'board_gpio_table', + ], +) diff --git a/common/recipes-utils/openbmc-gpio/files/soc_gpio.py b/common/recipes-utils/openbmc-gpio/files/soc_gpio.py new file mode 100644 index 0000000..2718af8 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/soc_gpio.py @@ -0,0 +1,19 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +def soc_get_register(addr): + raise Exception('Virtual function. Not implemented') diff --git a/common/recipes-utils/openbmc-gpio/files/soc_gpio_table.py b/common/recipes-utils/openbmc-gpio/files/soc_gpio_table.py new file mode 100644 index 0000000..45713e9 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/files/soc_gpio_table.py @@ -0,0 +1,23 @@ +# Copyright 2015-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +# This is an dummy SoC GPIO table. If this is included in the final image, +# please double check the configuration of your image to define the correct +# SoC GPIO table to be used for your board. + +soc_gpio_table = { +} diff --git a/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb b/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb new file mode 100644 index 0000000..6bf4cc1 --- /dev/null +++ b/common/recipes-utils/openbmc-gpio/openbmc-gpio_0.1.bb @@ -0,0 +1,75 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "OpenBMC GPIO utilies" +SECTION = "base" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a" + +SRC_URI = " \ + file://COPYING \ + file://board_gpio_table.py \ + file://openbmc_gpio.py \ + file://openbmc_gpio_table.py \ + file://openbmc_gpio_setup.py \ + file://openbmc_gpio_util.py \ + file://phymemory.py \ + file://setup.py \ + file://soc_gpio.py \ + file://soc_gpio_table.py \ + " + +S = "${WORKDIR}" + +OPENBMC_GPIO_UTILS = " \ + openbmc_gpio_util.py \ + " + +OPENBMC_GPIO_SOC_TABLE = "soc_gpio_table.py" + +# Change OPENBMC_GPIO_SETUP to "0" to exclude openbmc_gpio_setup.py from the image +OPENBMC_GPIO_SETUP = "1" + +inherit distutils + +DEPENDS_${PN} = "python python-distribute update-rc.d-native" + +RDEPENDS_${PN} = "python-core python-argparse python-subprocess" + +do_board_defined_soc_table() { + if [ "${OPENBMC_GPIO_SOC_TABLE}" != "soc_gpio_table.py" ]; then + mv -f "${S}/${OPENBMC_GPIO_SOC_TABLE}" "${S}/soc_gpio_table.py" + fi +} +addtask board_defined_soc_table after do_unpack before do_build + +do_install_append() { + localbindir="${D}/usr/local/bin" + install -d ${localbindir} + for f in ${OPENBMC_GPIO_UTILS}; do + install -m 755 $f ${localbindir}/${f} + done + + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + if [ "${OPENBMC_GPIO_SETUP}" == "1" ]; then + install -m 755 openbmc_gpio_setup.py ${D}${sysconfdir}/init.d/openbmc_gpio_setup.py + update-rc.d -r ${D} openbmc_gpio_setup.py start 59 S . + fi +} + +FILES_${PN} += "/usr/local/bin ${sysconfdir}" diff --git a/common/recipes-utils/openbmc-utils/files/COPYING b/common/recipes-utils/openbmc-utils/files/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/common/recipes-utils/openbmc-utils/files/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/common/recipes-utils/openbmc-utils/files/openbmc-utils.sh b/common/recipes-utils/openbmc-utils/files/openbmc-utils.sh new file mode 100644 index 0000000..885a6eb --- /dev/null +++ b/common/recipes-utils/openbmc-utils/files/openbmc-utils.sh @@ -0,0 +1,133 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +DEVMEM=/sbin/devmem +SHADOW_GPIO=/tmp/gpionames + +devmem_set_bit() { + local addr + local val + addr=$1 + val=$($DEVMEM $addr) + val=$((val | (0x1 << $2))) + $DEVMEM $addr 32 $val +} + +devmem_clear_bit() { + local addr + local val + addr=$1 + val=$($DEVMEM $addr) + val=$((val & ~(0x1 << $2))) + $DEVMEM $addr 32 $val +} + +GPIODIR="/sys/class/gpio" +GPIOEXPORT="$GPIODIR/export" + +gpio_dir() { + echo "$GPIODIR/gpio$1" +} + +gpio_name2value() { + local first remaining base val + remaining=$1 + base="${SHADOW_GPIO}/${remaining}" + if [ -L "${base}" ]; then + val=$(readlink -f ${base} 2>/dev/null) + if [ -n "${val}" ]; then + val=${val##*gpio} + if [ -n "${val}" ]; then + echo "$val" + return + fi + fi + fi + val=0 + while [ -n "$remaining" ]; do + first=${remaining:0:1} + case "$first" in + [[:lower:]]) + base=$(printf "%d" "'$first'") + base=$((base - 96)) + val=$((val * 26 + base)) + ;; + [[:upper:]]) + base=$(printf "%d" "'$first'") + base=$((base - 64)) + val=$((val * 26 + base)) + ;; + *) + if [ $val -gt 0 ]; then + val=$((val-1)) + fi + val=$((val * 8 + $remaining)) + break + ;; + esac + remaining=${remaining:1} + done + echo "$val" +} + +gpio_export() { + local gpio + gpio=$(gpio_name2value $1) + dir=$(gpio_dir $gpio) + if [ ! -d ${dir} ]; then + echo $gpio > $GPIOEXPORT + fi + if [ $# -gt 1 ]; then + if [ ! -d $SHADOW_GPIO ]; then + mkdir -p $SHADOW_GPIO + fi + ln -s $dir $SHADOW_GPIO/$2 + fi +} + +gpio_set() { + local gpio + local val + gpio=$(gpio_name2value $1) + val=$2 + dir=$(gpio_dir $gpio) + if [ ! -d ${dir} ]; then + echo $gpio > $GPIOEXPORT + fi + echo $val > ${dir}/value + echo out > ${dir}/direction +} + +gpio_get() { + local gpio + local val + gpio=$(gpio_name2value $1) + dir=$(gpio_dir $gpio) + if [ ! -d ${dir} ]; then + echo $gpio > $GPIOEXPORT + fi + echo in > ${dir}/direction + cat ${dir}/value +} + +if [ -f "/usr/local/bin/soc-utils.sh" ]; then + source "/usr/local/bin/soc-utils.sh" +fi + +if [ -f "/usr/local/bin/board-utils.sh" ]; then + source "/usr/local/bin/board-utils.sh" +fi diff --git a/common/recipes-utils/openbmc-utils/openbmc-utils_0.1.bb b/common/recipes-utils/openbmc-utils/openbmc-utils_0.1.bb new file mode 100644 index 0000000..f40d48b --- /dev/null +++ b/common/recipes-utils/openbmc-utils/openbmc-utils_0.1.bb @@ -0,0 +1,48 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "OpenBMC Utilities" +DESCRIPTION = "Various OpenBMC utilities" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a" + +SRC_URI = " \ + file://COPYING \ + file://openbmc-utils.sh \ + " + +OPENBMC_UTILS_FILES = " \ + openbmc-utils.sh \ + " + +S = "${WORKDIR}" + +do_install() { + pkgdir="/usr/local/packages/utils" + dstdir="${D}${pkgdir}" + install -d $dstdir + localbindir="${D}/usr/local/bin" + install -d ${localbindir} + for f in ${OPENBMC_UTILS_FILES}; do + install -m 755 $f ${dstdir}/${f} + ln -s ${pkgdir}/${f} ${localbindir} + done +} + +FILES_${PN} += "/usr/local" diff --git a/common/recipes-utils/spatula/files/setup-spatula.sh b/common/recipes-utils/spatula/files/setup-spatula.sh new file mode 100644 index 0000000..391a212 --- /dev/null +++ b/common/recipes-utils/spatula/files/setup-spatula.sh @@ -0,0 +1,80 @@ +#!/bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: setup-spatula-wrapper +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Set Spatula Wrapper +### END INIT INFO + +# source function library +. /etc/init.d/functions + +ACTION="$1" +CMD="/usr/local/bin/spatula_wrapper.py" +case "$ACTION" in + start) + echo -n "Setting up Spatula: " + pid=$(ps | grep -v grep | grep $CMD | awk '{print $1}') + if [ $pid ]; then + echo "already running" + else + $CMD > /var/log/spatula.log 2>&1 & + echo "done." + fi + ;; + stop) + echo -n "Stopping Spatula: " + pid=$(ps | grep -v grep | grep $CMD | awk '{print $1}') + if [ $pid ]; then + kill $pid + fi + echo "done." + ;; + restart) + echo -n "Restarting Spatula: " + pid=$(ps | grep -v grep | grep $CMD | awk '{print $1}') + if [ $pid ]; then + kill $pid + fi + sleep 1 + $CMD > /var/log/spatula.log 2>&1 & + echo "done." + ;; + status) + if [[ -n $(ps | grep -v grep | grep $CMD | awk '{print $1}') ]]; then + echo "Spatula is running" + else + echo "Spatula is stopped" + fi + ;; + *) + N=${0##*/} + N=${N#[SK]??} + echo "Usage: $N {start|stop|status|restart}" >&2 + exit 1 + ;; +esac + +exit 0 + diff --git a/common/recipes-utils/spatula/files/spatula_wrapper.py b/common/recipes-utils/spatula/files/spatula_wrapper.py new file mode 100644 index 0000000..2717bef --- /dev/null +++ b/common/recipes-utils/spatula/files/spatula_wrapper.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +import urllib2, urllib +import logging +import os +import subprocess +import time +import argparse + +SPATULA_FILE = '/etc/spatula/spatula' +LOG_FORMAT = '[%(levelname)s] %(asctime)s: %(message)s' +DATE_FORMAT = '%Y-%m-%d %H:%M:%S' +DEFAULT_SLEEP = 900 # default sleep 15 mins + +class SpatulaWrapper(object): + def __init__(self, address='fe80::2', interface='usb0', + port=8087, ssl=False): + proto = 'http' + if ssl: + proto = 'https' + self.url = '{proto}://{address}%{iface}:{port}'.format( + proto = proto, + address = address, + iface = interface, + port = port) + + def _getSpatula(self, endpoint='/spatula'): + ''' + Get the executable spatula script from the host. + ''' + url = '{}{}'.format(self.url, endpoint) + try: + request = urllib2.Request(url) + response = urllib2.urlopen(request) + return response.read() + except Exception as err: + raise Exception('failed getting Spatula {}: {}'.format(url, err)) + + def _success(self, endpoint='/success'): + ''' + Api to report the timestamp of a successful run + ''' + query = urllib.urlencode({'timestamp': time.time()}) + url = '{}{}?{}'.format(self.url, endpoint, query) + try: + request = urllib2.Request(url) + response = urllib2.urlopen(request) + return response.read() + except Exception as err: + raise Exception('failed report success {}: {}'.format(url, err)) + + def _error(self, error, endpoint='/error'): + ''' + Api to report the timestamp and the error when spatula fails + ''' + query = urllib.urlencode({'timestamp': time.time(), 'error': error}) + url = '{}{}?{}'.format(self.url, endpoint, query) + try: + request = urllib2.Request(url) + response = urllib2.urlopen(request) + return response.read() + except Exception as err: + raise Exception('failed report error [{}]: {}'.format(url, err)) + + def _execute(self): + try: + # get the executable from host + if not os.path.exists(os.path.dirname(SPATULA_FILE)): + os.makedirs(os.path.dirname(SPATULA_FILE)) + with open(SPATULA_FILE, 'w+') as file: + file.write(self._getSpatula()) + file.close() + # set the permission + os.chmod(SPATULA_FILE, 0755) + # run the executable file + spatula = subprocess.Popen([SPATULA_FILE], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = spatula.communicate() + if spatula.returncode != 0: + raise Exception('spatula failed: {}'.format(err)) + self._success() + except Exception as err: + self._error(err) + raise err + + def run(self, sleep): + while True: + try: + self._execute() + except Exception as err: + logging.error(err) + time.sleep(sleep) + +if __name__ == '__main__': + args = argparse.ArgumentParser() + args.add_argument('-s', '--sleep', default=DEFAULT_SLEEP, + help='Sleep time between spatula runs (default=%(default)s)') + params = args.parse_args() + logging.basicConfig(format=LOG_FORMAT, datefmt=DATE_FORMAT) + wrapper = SpatulaWrapper() + wrapper.run(params.sleep) diff --git a/common/recipes-utils/spatula/spatula_0.1.bb b/common/recipes-utils/spatula/spatula_0.1.bb new file mode 100644 index 0000000..dd54ccd --- /dev/null +++ b/common/recipes-utils/spatula/spatula_0.1.bb @@ -0,0 +1,47 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "Configure the BMC" +DESCRIPTION = "The script communicates with host and configures BMC." +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://spatula_wrapper.py;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0" + + +DEPENDS_append = " update-rc.d-native" + +SRC_URI = "file://setup-spatula.sh \ + file://spatula_wrapper.py \ + " + +S = "${WORKDIR}" + +binfiles = "spatula_wrapper.py" + +do_install() { + bin="${D}/usr/local/bin" + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${bin}/$f + done + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-spatula.sh ${D}${sysconfdir}/init.d/setup-spatula.sh + update-rc.d -r ${D} setup-spatula.sh start 95 2 3 4 5 . +} + +FILES_${PN} = "${prefix}/local/bin ${sysconfdir} " diff --git a/meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0002-Create-snapshot-of-OpenBMC.patch b/meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0002-Create-snapshot-of-OpenBMC.patch new file mode 100644 index 0000000..779d9a7 --- /dev/null +++ b/meta-aspeed/recipes-bsp/u-boot/files/patch-2013.07/0002-Create-snapshot-of-OpenBMC.patch @@ -0,0 +1,1234 @@ +From 19459c799ac0a521082d6d79e68ffc3decb18ea2 Mon Sep 17 00:00:00 2001 +From: Ori Bernstein <orib@fb.com> +Date: Thu, 3 Sep 2015 11:28:27 -0700 +Subject: [PATCH] Create snapshot of OpenBMC + +--- + .../u-boot-v2013.07/board/aspeed/ast2400/ast2400.c | 20 +- + .../board/aspeed/ast2400/platform.S | 35 ++ + .../u-boot/files/u-boot-v2013.07/boards.cfg | 3 + + .../files/u-boot-v2013.07/drivers/net/aspeednic.c | 3 +- + .../u-boot-v2013.07/include/configs/ast2400.h | 1 + + .../u-boot-v2013.07/include/configs/fbplatform1.h | 353 ++++++++++++++++++++ + .../u-boot-v2013.07/include/configs/fbyosemite.h | 353 ++++++++++++++++++++ + .../u-boot-v2013.07/include/configs/wedge100.h | 354 +++++++++++++++++++++ + 8 files changed, 1117 insertions(+), 5 deletions(-) + create mode 100644 meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/fbplatform1.h + create mode 100644 meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/fbyosemite.h + create mode 100644 meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/wedge100.h + +diff --git a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/board/aspeed/ast2400/ast2400.c b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/board/aspeed/ast2400/ast2400.c +index 55ed6b7..125957e 100644 +--- a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/board/aspeed/ast2400/ast2400.c ++++ b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/board/aspeed/ast2400/ast2400.c +@@ -194,15 +194,27 @@ int ast1070_calibration() + static void watchdog_init() + { + #ifdef CONFIG_ASPEED_ENABLE_WATCHDOG +-#define AST_WDT_BASE 0x1e785000 ++#define AST_WDT1_BASE 0x1e785000 ++#define AST_WDT2_BASE 0x1e785020 + #define AST_WDT_CLK (1*1000*1000) /* 1M clock source */ + u32 reload = AST_WDT_CLK * CONFIG_ASPEED_WATCHDOG_TIMEOUT; ++#ifdef CONFIG_ASPEED_ENABLE_DUAL_BOOT_WATCHDOG ++ /* dual boot watchdog is enabled */ + /* set the reload value */ +- __raw_writel(reload, AST_WDT_BASE + 0x04); ++ reload = AST_WDT_CLK * CONFIG_ASPEED_WATCHDOG_DUAL_BOOT_TIMEOUT; ++ /* set the reload value */ ++ __raw_writel(reload, AST_WDT2_BASE + 0x04); ++ /* magic word to reload */ ++ __raw_writel(0x4755, AST_WDT2_BASE + 0x08); ++ printf("Dual boot watchdog: %us\n", CONFIG_ASPEED_WATCHDOG_DUAL_BOOT_TIMEOUT); ++#endif ++ reload = AST_WDT_CLK * CONFIG_ASPEED_WATCHDOG_TIMEOUT; ++ /* set the reload value */ ++ __raw_writel(reload, AST_WDT1_BASE + 0x04); + /* magic word to reload */ +- __raw_writel(0x4755, AST_WDT_BASE + 0x08); ++ __raw_writel(0x4755, AST_WDT1_BASE + 0x08); + /* start the watchdog with 1M clk src and reset whole chip */ +- __raw_writel(0x33, AST_WDT_BASE + 0x0c); ++ __raw_writel(0x33, AST_WDT1_BASE + 0x0c); + printf("Watchdog: %us\n", CONFIG_ASPEED_WATCHDOG_TIMEOUT); + #endif + } +diff --git a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/board/aspeed/ast2400/platform.S b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/board/aspeed/ast2400/platform.S +index dd94da0..64967f4 100644 +--- a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/board/aspeed/ast2400/platform.S ++++ b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/board/aspeed/ast2400/platform.S +@@ -333,10 +333,45 @@ set_MPLL: + and r1, r2, r1 + str r1, [r0] + ++/* Yosemite Platform specific Initialization */ ++#ifdef CONFIG_YOSEMITE ++/* ++ * Disable WDT2 before the 2nd SPI flash is tried ++ * TODO: Need to detect booting from 2nd flash and recover ++ */ ++ ldr r0, =0x1e78502c ++ mov r1, #0x0 ++ str r1, [r0] ++ ++/* Use GPIOE2/GPIOE3 to select BMC Output on debug console */ ++ ldr r1, =0x0C ++ ldr r0, =0x1e780024 ++ str r1, [r0] ++ ++ ldr r0, =0x1e780020 ++ str r1, [r0] ++ ++ ldr r1, = 0x80 ++ ldr r0, =0x1e780084 ++ str r1, [r0] ++ ++ ++ ldr r1, = 0x80 ++ ldr r0, =0x1e780080 ++ str r1, [r0] ++ ++ ldr r1, = 0x0 ++ ldr r0, =0x1e780080 ++ str r1, [r0] ++#endif ++ + /* Debug - UART console message */ ++// Enable UART3/4 only for non-yosemite platform ++#ifndef CONFIG_YOSEMITE + ldr r0, =0x1e6e2080 + ldr r1, =0xFFFF0000 @ enable UART3 and UART4 + str r1, [r0] ++#endif + + ldr r0, =CONFIG_ASPEED_COM_LCR + mov r1, #0x83 +diff --git a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/boards.cfg b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/boards.cfg +index ce6bff1..556de75 100644 +--- a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/boards.cfg ++++ b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/boards.cfg +@@ -73,6 +73,9 @@ VCMA9 arm arm920t vcma9 mpl + smdk2410 arm arm920t - samsung s3c24x0 + omap1510inn arm arm925t - ti + wedge arm arm926ejs ast2400 aspeed aspeed ++wedge100 arm arm926ejs ast2400 aspeed aspeed ++fbyosemite arm arm926ejs ast2400 aspeed aspeed ++fbplatform1 arm arm926ejs ast2400 aspeed aspeed + integratorap_cm926ejs arm arm926ejs integrator armltd - integratorap:CM926EJ_S + integratorcp_cm926ejs arm arm926ejs integrator armltd - integratorcp:CM924EJ_S + aspenite arm arm926ejs - Marvell armada100 +diff --git a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/drivers/net/aspeednic.c b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/drivers/net/aspeednic.c +index d75ef67..86f6dec 100644 +--- a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/drivers/net/aspeednic.c ++++ b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/drivers/net/aspeednic.c +@@ -471,8 +471,8 @@ int aspeednic_initialize(bd_t *bis) + struct eth_device* dev; + + #if defined(CONFIG_AST2300_FPGA_2) || defined(CONFIG_AST2300) || defined(CONFIG_AST3100) || defined(CONFIG_AST2400) +-//AST2300 + //MAC1 CLOCK/RESET/PHY_LINK/MDC_MDIO in SCU ++#ifdef CONFIG_MAC1_ENABLE + SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL)); + *(volatile u_long *)(SCU_BASE + SCU_RESET_CONTROL) = cpu_to_le32(SCURegister | 0x800); + udelay(100); +@@ -494,6 +494,7 @@ int aspeednic_initialize(bd_t *bis) + SCURegister = le32_to_cpu(*(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG)); + *(volatile u_long *)(SCU_BASE + SCU_MULTIFUNCTION_PIN_CTL1_REG) = cpu_to_le32(SCURegister | (MAC1_PHY_LINK)); + #endif ++#endif + + //MAC2 CLOCK/RESET/PHY_LINK/MDC_MDIO + #ifdef CONFIG_MAC2_ENABLE +diff --git a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/ast2400.h b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/ast2400.h +index 670fcfd..4c43d6f 100644 +--- a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/ast2400.h ++++ b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/ast2400.h +@@ -284,6 +284,7 @@ + #define __LITTLE_ENDIAN_BITFIELD + #define CONFIG_MAC_PARTITION + #define CONFIG_ASPEEDNIC ++#define CONFIG_MAC1_ENABLE + #define CONFIG_MAC1_PHY_LINK_INTERRUPT + #define CONFIG_MAC2_ENABLE + #define CONFIG_MAC2_PHY_LINK_INTERRUPT +diff --git a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/fbplatform1.h b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/fbplatform1.h +new file mode 100644 +index 0000000..22718fb +--- /dev/null ++++ b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/fbplatform1.h +@@ -0,0 +1,353 @@ ++/* ++ * Copyright 2015-present Facebook. All Rights Reserved. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#ifndef __CONFIG_H ++#define __CONFIG_H ++ ++/* Uncommit the following line to enable JTAG in u-boot */ ++//#define CONFIG_ASPEED_ENABLE_JTAG ++ ++/* ++ * High Level Configuration Options ++ * (easy to change) ++ */ ++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */ ++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */ ++//#define CONFIG_FPGA_ASPEED 1 ++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */ ++#define CONFIG_ASPEED 1 ++#define CONFIG_AST2400 1 ++//#define CONFIG_AST1070 1 ++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/ ++#define CONFIG_FLASH_SPI ++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */ ++#undef CONFIG_2SPIFLASH ++#undef CONFIG_ASPEED_SLT ++#define CONFIG_FLASH_AST2300 ++//#define CONFIG_FLASH_AST2300_DMA ++//#define CONFIG_FLASH_SPIx2_Dummy ++//#define CONFIG_FLASH_SPIx4_Dummy ++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */ ++ ++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */ ++#define CONFIG_MISC_INIT_R ++ ++#define CONFIG_FBPLATFORM1 ++ ++/* ++ * DRAM Config ++ * ++ * 1. DRAM Size // ++ * CONFIG_DRAM_512MBIT // 512M bit ++ * CONFIG_DRAM_1GBIT // 1G bit (default) ++ * CONFIG_DRAM_2GBIT // 2G bit ++ * CONFIG_DRAM_4GBIT // 4G bit ++ * 2. DRAM Speed // ++ * CONFIG_DRAM_336 // 336MHz (DDR-667) ++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default) ++ * 3. VGA Mode ++ * CONFIG_CRT_DISPLAY // define to disable VGA function ++ * 4. ECC Function enable ++ * CONFIG_DRAM_ECC // define to enable ECC function ++ * 5. UART Debug Message ++ * CONFIG_DRAM_UART_OUT // enable output message at UART5 ++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200 ++ */ ++ ++//1. DRAM Size ++//#define CONFIG_DRAM_512MBIT ++#define CONFIG_DRAM_1GBIT ++//#define CONFIG_DRAM_2GBIT ++//#define CONFIG_DRAM_4GBIT ++//2. DRAM Speed ++//#define CONFIG_DRAM_336 ++#define CONFIG_DRAM_408 ++//3. VGA Mode ++//#define CONFIG_CRT_DISPLAY ++//4. ECC Function enable ++//#define CONFIG_DRAM_ECC ++//5. UART Debug Message ++#define CONFIG_DRAM_UART_OUT ++//#define CONFIG_DRAM_UART_38400 ++ ++ ++ ++/* ++ * Environment Config ++ */ ++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ ++#define CONFIG_SETUP_MEMORY_TAGS 1 ++#define CONFIG_INITRD_TAG 1 ++#define CONFIG_BOOTARGS "debug console=ttyS0,57600n8 root=/dev/ram rw" ++#define CONFIG_UPDATE "tftp 40800000 ast2400.scr; so 40800000'" ++ ++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ ++#define CONFIG_AUTOBOOT_KEYED ++#define CONFIG_AUTOBOOT_PROMPT \ ++ "autoboot in %d seconds (stop with 'Delete' key)...\n", bootdelay ++#define CONFIG_AUTOBOOT_STOP_STR "\x1b\x5b\x33\x7e" /* 'Delete', ESC[3~ */ ++#define CONFIG_ZERO_BOOTDELAY_CHECK ++ ++#ifdef CONFIG_FLASH_AST2300 ++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000" ++#else ++#ifdef CONFIG_SYS_FLASH_CFI ++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000" ++#else ++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000" ++#endif ++#endif ++#define CONFIG_BOOTFILE "all.bin" ++#define CONFIG_ENV_OVERWRITE ++ ++/* ++ * Command line configuration. ++ */ ++#include <config_cmd_default.h> ++ ++#define CONFIG_CMD_DFL ++#define CONFIG_CMD_ENV ++#define CONFIG_CMD_FLASH ++#define CONFIG_CMD_MII ++#define CONFIG_CMD_NET ++#define CONFIG_CMD_PING ++#define CONFIG_CMD_I2C ++#define CONFIG_CMD_EEPROM ++#define CONFIG_CMD_NETTEST ++#define CONFIG_CMD_SLT ++ ++/* ++ * CPU Setting ++ */ ++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */ ++ ++/* ++ * Size of malloc() pool ++ */ ++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024) ++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ ++ ++/* ++ * Stack sizes, The stack sizes are set up in start.S using the settings below ++ */ ++#define CONFIG_STACKSIZE (128*1024) /* regular stack */ ++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ ++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */ ++ ++/* ++ * Memory Configuration ++ */ ++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ ++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */ ++#define PHYS_SDRAM_1_SIZE 0x8000000 /* 128 MB */ ++ ++#define CONFIG_SYS_SDRAM_BASE 0x40000000 ++ ++/* ++ * FLASH Configuration ++ */ ++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */ ++ ++#ifdef CONFIG_FLASH_AST2300 ++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */ ++#else ++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */ ++#endif ++ ++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 ++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 } ++ ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */ ++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ ++ ++#define CONFIG_SYS_FLASH_CFI_AMD_RESET ++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE ++ ++#else /* SPI Flash */ ++ ++#ifdef CONFIG_FLASH_AST2300 ++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */ ++#else ++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */ ++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */ ++#define PHYS_FLASH_2_BASE 0x10000000 ++#endif ++ ++#ifdef CONFIG_2SPIFLASH ++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE ++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 } ++#define CONFIG_SYS_MAX_FLASH_BANKS 2 ++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */ ++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */ ++#else ++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 ++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 } ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */ ++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ ++#define CONFIG_ASPEED_WRITE_DEFAULT_ENV ++#endif ++ ++#endif ++ ++#define __LITTLE_ENDIAN 1 ++ ++#define CONFIG_MONITOR_BASE TEXT_BASE ++#define CONFIG_MONITOR_LEN (192 << 10) ++ ++/* timeout values are in ticks */ ++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */ ++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */ ++ ++/* ++ * Miscellaneous configurable options ++ */ ++#define CONFIG_SYS_LONGHELP /* undef to save memory */ ++ ++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */ ++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */ ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ ++ ++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */ ++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */ ++ ++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */ ++ ++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */ ++#define CONFIG_SYS_HZ 1000 ++#define CONFIG_ASPEED_TIMER_CLK (1*1000*1000) /* use external clk (1M) */ ++ ++/* ++ * Serial Configuration ++ */ ++#define CONFIG_SYS_NS16550 ++#define CONFIG_SYS_NS16550_SERIAL ++#define CONFIG_SYS_NS16550_MEM32 ++#define CONFIG_SYS_NS16550_REG_SIZE -4 ++#define CONFIG_SYS_NS16550_CLK 24000000 ++#define CONFIG_SYS_NS16550_COM1 0x1e783000 ++#define CONFIG_SYS_NS16550_COM2 0x1e784000 ++#define CONFIG_SYS_NS16550_COM3 0x1e78e000 ++#define CONFIG_SYS_LOADS_BAUD_CHANGE ++#define CONFIG_CONS_INDEX 2 ++#define CONFIG_BAUDRATE 57600 ++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } ++#define CONFIG_ASPEED_COM 0x1e784000 // COM2(UART5) ++#define CONFIG_ASPEED_COM_IER (CONFIG_ASPEED_COM + 0x4) ++#define CONFIG_ASPEED_COM_IIR (CONFIG_ASPEED_COM + 0x8) ++#define CONFIG_ASPEED_COM_LCR (CONFIG_ASPEED_COM + 0xc) ++ ++/* ++ * USB device configuration ++ */ ++/* ++#define CONFIG_USB_DEVICE 1 ++#define CONFIG_USB_TTY 1 ++ ++#define CONFIG_USBD_VENDORID 0x1234 ++#define CONFIG_USBD_PRODUCTID 0x5678 ++#define CONFIG_USBD_MANUFACTURER "Siemens" ++#define CONFIG_USBD_PRODUCT_NAME "SX1" ++*/ ++ ++/* ++ * I2C configuration ++ */ ++#define CONFIG_HARD_I2C ++#define CONFIG_SYS_I2C_SPEED 100000 ++#define CONFIG_SYS_I2C_SLAVE 1 ++#define CONFIG_DRIVER_ASPEED_I2C ++ ++/* ++* EEPROM configuration ++*/ ++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 ++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0 ++ ++#define __BYTE_ORDER __LITTLE_ENDIAN ++#define __LITTLE_ENDIAN_BITFIELD ++ ++/* ++ * NIC configuration ++ */ ++#define CONFIG_ASPEEDNIC ++#define CONFIG_NET_MULTI ++#define CONFIG_MAC1_ENABLE ++//#define CONFIG_MAC1_PHY_LINK_INTERRUPT ++//#define CONFIG_MAC2_ENABLE ++//#define CONFIG_MAC2_PHY_LINK_INTERRUPT ++/* ++*------------------------------------------------------------------------------- ++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration. ++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to ++* inform kernel driver. ++* The meanings of the 2 bits are: ++* 00(0): Dedicated PHY ++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA ++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly ++* 11: Reserved ++* ++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot ++* 0: Dedicated PHY ++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA ++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly ++* 3: Reserved ++*------------------------------------------------------------------------------- ++*/ ++#define CONFIG_MAC1_PHY_SETTING 2 ++#define CONFIG_MAC2_PHY_SETTING 0 ++#define CONFIG_ASPEED_MAC_NUMBER 1 ++#define CONFIG_ASPEED_MAC_CONFIG 1 // config MAC1 ++#define _PHY_SETTING_CONCAT(mac) CONFIG_MAC##mac##_PHY_SETTING ++#define _GET_MAC_PHY_SETTING(mac) _PHY_SETTING_CONCAT(mac) ++#define CONFIG_ASPEED_MAC_PHY_SETTING \ ++ _GET_MAC_PHY_SETTING(CONFIG_ASPEED_MAC_CONFIG) ++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255 ++#define CONFIG_RANDOM_MACADDR ++//#define CONFIG_GATEWAYIP 192.168.0.1 ++//#define CONFIG_NETMASK 255.255.255.0 ++//#define CONFIG_IPADDR 192.168.0.45 ++//#define CONFIG_SERVERIP 192.168.0.81 ++ ++/* ++ * SLT ++ */ ++/* ++#define CONFIG_SLT ++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST) ++*/ ++ ++#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) ++ ++#define CONFIG_ASPEED_ENABLE_WATCHDOG ++#define CONFIG_ASPEED_WATCHDOG_TIMEOUT (5*60) // 5m ++ ++#endif /* __CONFIG_H */ +diff --git a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/fbyosemite.h b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/fbyosemite.h +new file mode 100644 +index 0000000..73a3cf9 +--- /dev/null ++++ b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/fbyosemite.h +@@ -0,0 +1,353 @@ ++/* ++ * Copyright 2015-present Facebook. All Rights Reserved. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#ifndef __CONFIG_H ++#define __CONFIG_H ++ ++/* Uncommit the following line to enable JTAG in u-boot */ ++//#define CONFIG_ASPEED_ENABLE_JTAG ++ ++/* ++ * High Level Configuration Options ++ * (easy to change) ++ */ ++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */ ++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */ ++//#define CONFIG_FPGA_ASPEED 1 ++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */ ++#define CONFIG_ASPEED 1 ++#define CONFIG_AST2400 1 ++//#define CONFIG_AST1070 1 ++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/ ++#define CONFIG_FLASH_SPI ++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */ ++#undef CONFIG_2SPIFLASH ++#undef CONFIG_ASPEED_SLT ++#define CONFIG_FLASH_AST2300 ++//#define CONFIG_FLASH_AST2300_DMA ++//#define CONFIG_FLASH_SPIx2_Dummy ++//#define CONFIG_FLASH_SPIx4_Dummy ++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */ ++ ++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */ ++#define CONFIG_MISC_INIT_R ++ ++#define CONFIG_YOSEMITE ++ ++/* ++ * DRAM Config ++ * ++ * 1. DRAM Size // ++ * CONFIG_DRAM_512MBIT // 512M bit ++ * CONFIG_DRAM_1GBIT // 1G bit (default) ++ * CONFIG_DRAM_2GBIT // 2G bit ++ * CONFIG_DRAM_4GBIT // 4G bit ++ * 2. DRAM Speed // ++ * CONFIG_DRAM_336 // 336MHz (DDR-667) ++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default) ++ * 3. VGA Mode ++ * CONFIG_CRT_DISPLAY // define to disable VGA function ++ * 4. ECC Function enable ++ * CONFIG_DRAM_ECC // define to enable ECC function ++ * 5. UART Debug Message ++ * CONFIG_DRAM_UART_OUT // enable output message at UART5 ++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200 ++ */ ++ ++//1. DRAM Size ++//#define CONFIG_DRAM_512MBIT ++#define CONFIG_DRAM_1GBIT ++//#define CONFIG_DRAM_2GBIT ++//#define CONFIG_DRAM_4GBIT ++//2. DRAM Speed ++//#define CONFIG_DRAM_336 ++#define CONFIG_DRAM_408 ++//3. VGA Mode ++//#define CONFIG_CRT_DISPLAY ++//4. ECC Function enable ++//#define CONFIG_DRAM_ECC ++//5. UART Debug Message ++#define CONFIG_DRAM_UART_OUT ++//#define CONFIG_DRAM_UART_38400 ++ ++ ++ ++/* ++ * Environment Config ++ */ ++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ ++#define CONFIG_SETUP_MEMORY_TAGS 1 ++#define CONFIG_INITRD_TAG 1 ++#define CONFIG_BOOTARGS "debug console=ttyS0,57600n8 root=/dev/ram rw" ++#define CONFIG_UPDATE "tftp 40800000 ast2400.scr; so 40800000'" ++ ++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ ++#define CONFIG_AUTOBOOT_KEYED ++#define CONFIG_AUTOBOOT_PROMPT \ ++ "autoboot in %d seconds (stop with 'Delete' key)...\n", bootdelay ++#define CONFIG_AUTOBOOT_STOP_STR "\x1b\x5b\x33\x7e" /* 'Delete', ESC[3~ */ ++#define CONFIG_ZERO_BOOTDELAY_CHECK ++ ++#ifdef CONFIG_FLASH_AST2300 ++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000" ++#else ++#ifdef CONFIG_SYS_FLASH_CFI ++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000" ++#else ++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000" ++#endif ++#endif ++#define CONFIG_BOOTFILE "all.bin" ++#define CONFIG_ENV_OVERWRITE ++ ++/* ++ * Command line configuration. ++ */ ++#include <config_cmd_default.h> ++ ++#define CONFIG_CMD_DFL ++#define CONFIG_CMD_ENV ++#define CONFIG_CMD_FLASH ++#define CONFIG_CMD_MII ++#define CONFIG_CMD_NET ++#define CONFIG_CMD_PING ++#define CONFIG_CMD_I2C ++#define CONFIG_CMD_EEPROM ++#define CONFIG_CMD_NETTEST ++#define CONFIG_CMD_SLT ++ ++/* ++ * CPU Setting ++ */ ++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */ ++ ++/* ++ * Size of malloc() pool ++ */ ++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024) ++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ ++ ++/* ++ * Stack sizes, The stack sizes are set up in start.S using the settings below ++ */ ++#define CONFIG_STACKSIZE (128*1024) /* regular stack */ ++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ ++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */ ++ ++/* ++ * Memory Configuration ++ */ ++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ ++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */ ++#define PHYS_SDRAM_1_SIZE 0x8000000 /* 128 MB */ ++ ++#define CONFIG_SYS_SDRAM_BASE 0x40000000 ++ ++/* ++ * FLASH Configuration ++ */ ++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */ ++ ++#ifdef CONFIG_FLASH_AST2300 ++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */ ++#else ++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */ ++#endif ++ ++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 ++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 } ++ ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */ ++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ ++ ++#define CONFIG_SYS_FLASH_CFI_AMD_RESET ++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE ++ ++#else /* SPI Flash */ ++ ++#ifdef CONFIG_FLASH_AST2300 ++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */ ++#else ++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */ ++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */ ++#define PHYS_FLASH_2_BASE 0x10000000 ++#endif ++ ++#ifdef CONFIG_2SPIFLASH ++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE ++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 } ++#define CONFIG_SYS_MAX_FLASH_BANKS 2 ++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */ ++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */ ++#else ++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 ++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 } ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */ ++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ ++#define CONFIG_ASPEED_WRITE_DEFAULT_ENV ++#endif ++ ++#endif ++ ++#define __LITTLE_ENDIAN 1 ++ ++#define CONFIG_MONITOR_BASE TEXT_BASE ++#define CONFIG_MONITOR_LEN (192 << 10) ++ ++/* timeout values are in ticks */ ++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */ ++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */ ++ ++/* ++ * Miscellaneous configurable options ++ */ ++#define CONFIG_SYS_LONGHELP /* undef to save memory */ ++ ++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */ ++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */ ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ ++ ++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */ ++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */ ++ ++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */ ++ ++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */ ++#define CONFIG_SYS_HZ 1000 ++#define CONFIG_ASPEED_TIMER_CLK (1*1000*1000) /* use external clk (1M) */ ++ ++/* ++ * Serial Configuration ++ */ ++#define CONFIG_SYS_NS16550 ++#define CONFIG_SYS_NS16550_SERIAL ++#define CONFIG_SYS_NS16550_MEM32 ++#define CONFIG_SYS_NS16550_REG_SIZE -4 ++#define CONFIG_SYS_NS16550_CLK 24000000 ++#define CONFIG_SYS_NS16550_COM1 0x1e783000 ++#define CONFIG_SYS_NS16550_COM2 0x1e784000 ++#define CONFIG_SYS_NS16550_COM3 0x1e78e000 ++#define CONFIG_SYS_LOADS_BAUD_CHANGE ++#define CONFIG_CONS_INDEX 2 ++#define CONFIG_BAUDRATE 57600 ++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } ++#define CONFIG_ASPEED_COM 0x1e784000 // COM2(UART5) ++#define CONFIG_ASPEED_COM_IER (CONFIG_ASPEED_COM + 0x4) ++#define CONFIG_ASPEED_COM_IIR (CONFIG_ASPEED_COM + 0x8) ++#define CONFIG_ASPEED_COM_LCR (CONFIG_ASPEED_COM + 0xc) ++ ++/* ++ * USB device configuration ++ */ ++/* ++#define CONFIG_USB_DEVICE 1 ++#define CONFIG_USB_TTY 1 ++ ++#define CONFIG_USBD_VENDORID 0x1234 ++#define CONFIG_USBD_PRODUCTID 0x5678 ++#define CONFIG_USBD_MANUFACTURER "Siemens" ++#define CONFIG_USBD_PRODUCT_NAME "SX1" ++*/ ++ ++/* ++ * I2C configuration ++ */ ++#define CONFIG_HARD_I2C ++#define CONFIG_SYS_I2C_SPEED 100000 ++#define CONFIG_SYS_I2C_SLAVE 1 ++#define CONFIG_DRIVER_ASPEED_I2C ++ ++/* ++* EEPROM configuration ++*/ ++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 ++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0 ++ ++#define __BYTE_ORDER __LITTLE_ENDIAN ++#define __LITTLE_ENDIAN_BITFIELD ++ ++/* ++ * NIC configuration ++ */ ++#define CONFIG_ASPEEDNIC ++#define CONFIG_NET_MULTI ++#define CONFIG_MAC1_ENABLE ++//#define CONFIG_MAC1_PHY_LINK_INTERRUPT ++//#define CONFIG_MAC2_ENABLE ++//#define CONFIG_MAC2_PHY_LINK_INTERRUPT ++/* ++*------------------------------------------------------------------------------- ++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration. ++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to ++* inform kernel driver. ++* The meanings of the 2 bits are: ++* 00(0): Dedicated PHY ++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA ++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly ++* 11: Reserved ++* ++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot ++* 0: Dedicated PHY ++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA ++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly ++* 3: Reserved ++*------------------------------------------------------------------------------- ++*/ ++#define CONFIG_MAC1_PHY_SETTING 2 ++#define CONFIG_MAC2_PHY_SETTING 0 ++#define CONFIG_ASPEED_MAC_NUMBER 1 ++#define CONFIG_ASPEED_MAC_CONFIG 1 // config MAC1 ++#define _PHY_SETTING_CONCAT(mac) CONFIG_MAC##mac##_PHY_SETTING ++#define _GET_MAC_PHY_SETTING(mac) _PHY_SETTING_CONCAT(mac) ++#define CONFIG_ASPEED_MAC_PHY_SETTING \ ++ _GET_MAC_PHY_SETTING(CONFIG_ASPEED_MAC_CONFIG) ++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255 ++#define CONFIG_RANDOM_MACADDR ++//#define CONFIG_GATEWAYIP 192.168.0.1 ++//#define CONFIG_NETMASK 255.255.255.0 ++//#define CONFIG_IPADDR 192.168.0.45 ++//#define CONFIG_SERVERIP 192.168.0.81 ++ ++/* ++ * SLT ++ */ ++/* ++#define CONFIG_SLT ++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST) ++*/ ++ ++#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) ++ ++#define CONFIG_ASPEED_ENABLE_WATCHDOG ++#define CONFIG_ASPEED_WATCHDOG_TIMEOUT (5*60) // 5m ++ ++#endif /* __CONFIG_H */ +diff --git a/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/wedge100.h b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/wedge100.h +new file mode 100644 +index 0000000..1aa3260 +--- /dev/null ++++ b/meta-aspeed/recipes-bsp/u-boot/files/u-boot-v2013.07/include/configs/wedge100.h +@@ -0,0 +1,354 @@ ++/* ++ * Copyright 2004-present Facebook. All Rights Reserved. ++ * ++ * 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. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ */ ++ ++#ifndef __CONFIG_H ++#define __CONFIG_H ++ ++/* Uncommit the following line to enable JTAG in u-boot */ ++//#define CONFIG_ASPEED_ENABLE_JTAG ++ ++/* ++ * High Level Configuration Options ++ * (easy to change) ++ */ ++//#define CONFIG_INIT_CRITICAL /* define for U-BOOT 1.1.1 */ ++#undef CONFIG_INIT_CRITICAL /* undef for U-BOOT 1.1.4 */ ++//#define CONFIG_FPGA_ASPEED 1 ++#define CONFIG_ARM926EJS 1 /* This is an arm926ejs CPU */ ++#define CONFIG_ASPEED 1 ++#define CONFIG_AST2400 1 ++#define CONFIG_WEDGE100 1 ++//#define CONFIG_AST1070 1 ++//#define CONFIG_SYS_FLASH_CFI /* CONFIG_FLASH_CFI, CONFIG_FLASH_SPI is exclusive*/ ++#define CONFIG_FLASH_SPI ++//#define CONFIG_2SPIFLASH /* Boot SPI: CS2, 2nd SPI: CS0 */ ++#undef CONFIG_2SPIFLASH ++#undef CONFIG_ASPEED_SLT ++#define CONFIG_FLASH_AST2300 ++//#define CONFIG_FLASH_AST2300_DMA ++//#define CONFIG_FLASH_SPIx2_Dummy ++//#define CONFIG_FLASH_SPIx4_Dummy ++#define CONFIG_CRT_DISPLAY 1 /* undef if not support CRT */ ++ ++//#define CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */ ++#define CONFIG_MISC_INIT_R ++ ++/* ++ * DRAM Config ++ * ++ * 1. DRAM Size // ++ * CONFIG_DRAM_512MBIT // 512M bit ++ * CONFIG_DRAM_1GBIT // 1G bit (default) ++ * CONFIG_DRAM_2GBIT // 2G bit ++ * CONFIG_DRAM_4GBIT // 4G bit ++ * 2. DRAM Speed // ++ * CONFIG_DRAM_336 // 336MHz (DDR-667) ++ * CONFIG_DRAM_408 // 408MHz (DDR-800) (default) ++ * 3. VGA Mode ++ * CONFIG_CRT_DISPLAY // define to disable VGA function ++ * 4. ECC Function enable ++ * CONFIG_DRAM_ECC // define to enable ECC function ++ * 5. UART Debug Message ++ * CONFIG_DRAM_UART_OUT // enable output message at UART5 ++ * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200 ++ */ ++ ++//1. DRAM Size ++//#define CONFIG_DRAM_512MBIT ++#define CONFIG_DRAM_1GBIT ++//#define CONFIG_DRAM_2GBIT ++//#define CONFIG_DRAM_4GBIT ++//2. DRAM Speed ++//#define CONFIG_DRAM_336 ++#define CONFIG_DRAM_408 ++//3. VGA Mode ++//#define CONFIG_CRT_DISPLAY ++//4. ECC Function enable ++//#define CONFIG_DRAM_ECC ++//5. UART Debug Message ++#define CONFIG_DRAM_UART_OUT ++//#define CONFIG_DRAM_UART_38400 ++ ++ ++ ++/* ++ * Environment Config ++ */ ++#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ ++#define CONFIG_SETUP_MEMORY_TAGS 1 ++#define CONFIG_INITRD_TAG 1 ++#define CONFIG_BOOTARGS "debug console=ttyS2,9600n8 root=/dev/ram rw" ++#define CONFIG_UPDATE "tftp 40800000 ast2400.scr; so 40800000'" ++ ++#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ ++#define CONFIG_AUTOBOOT_KEYED ++#define CONFIG_AUTOBOOT_PROMPT \ ++ "autoboot in %d seconds (stop with 'Delete' key)...\n", bootdelay ++#define CONFIG_AUTOBOOT_STOP_STR "\x1b\x5b\x33\x7e" /* 'Delete', ESC[3~ */ ++#define CONFIG_ZERO_BOOTDELAY_CHECK ++ ++#ifdef CONFIG_FLASH_AST2300 ++#define CONFIG_BOOTCOMMAND "bootm 20080000 20300000" ++#else ++#ifdef CONFIG_SYS_FLASH_CFI ++#define CONFIG_BOOTCOMMAND "bootm 10080000 10300000" ++#else ++#define CONFIG_BOOTCOMMAND "bootm 14080000 14300000" ++#endif ++#endif ++#define CONFIG_BOOTFILE "all.bin" ++#define CONFIG_ENV_OVERWRITE ++ ++/* ++ * Command line configuration. ++ */ ++#include <config_cmd_default.h> ++ ++#define CONFIG_CMD_DFL ++#define CONFIG_CMD_ENV ++#define CONFIG_CMD_FLASH ++#define CONFIG_CMD_MII ++#define CONFIG_CMD_NET ++#define CONFIG_CMD_PING ++#define CONFIG_CMD_I2C ++#define CONFIG_CMD_EEPROM ++#define CONFIG_CMD_NETTEST ++#define CONFIG_CMD_SLT ++ ++/* ++ * CPU Setting ++ */ ++#define CPU_CLOCK_RATE 18000000 /* 16.5 MHz clock for the ARM core */ ++ ++/* ++ * Size of malloc() pool ++ */ ++#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 768*1024) ++#define CONFIG_SYS_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ ++ ++/* ++ * Stack sizes, The stack sizes are set up in start.S using the settings below ++ */ ++#define CONFIG_STACKSIZE (128*1024) /* regular stack */ ++#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ ++#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */ ++ ++/* ++ * Memory Configuration ++ */ ++#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ ++#define PHYS_SDRAM_1 0x40000000 /* SDRAM Bank #1 */ ++#define PHYS_SDRAM_1_SIZE 0x10000000 /* 256 MB */ ++ ++#define CONFIG_SYS_SDRAM_BASE 0x40000000 ++ ++/* ++ * FLASH Configuration ++ */ ++#ifdef CONFIG_SYS_FLASH_CFI /* NOR Flash */ ++ ++#ifdef CONFIG_FLASH_AST2300 ++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */ ++#else ++#define PHYS_FLASH_1 0x10000000 /* Flash Bank #1 */ ++#endif ++ ++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 ++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 } ++ ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT (256) /* max number of sectors on one chip */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */ ++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ ++ ++#define CONFIG_SYS_FLASH_CFI_AMD_RESET ++#define CONFIG_SYS_FLASH_USE_BUFFER_WRITE ++ ++#else /* SPI Flash */ ++ ++#ifdef CONFIG_FLASH_AST2300 ++#define PHYS_FLASH_1 0x20000000 /* Flash Bank #1 */ ++#else ++#define PHYS_FLASH_1 0x14000000 /* Flash Bank #1 */ ++#define PHYS_FLASH_2 0x14800000 /* Flash Bank #2 */ ++#define PHYS_FLASH_2_BASE 0x10000000 ++#endif ++ ++#ifdef CONFIG_2SPIFLASH ++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_2_BASE ++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1, PHYS_FLASH_2 } ++#define CONFIG_SYS_MAX_FLASH_BANKS 2 ++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_OFFSET 0x7F0000 /* environment starts here */ ++#define CONFIG_ENV_SIZE 0x010000 /* Total Size of Environment Sector */ ++#else ++#define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 ++#define CONFIG_FLASH_BANKS_LIST { PHYS_FLASH_1 } ++#define CONFIG_SYS_MAX_FLASH_BANKS 1 ++#define CONFIG_SYS_MAX_FLASH_SECT (1024) /* max number of sectors on one chip */ ++ ++#define CONFIG_ENV_IS_IN_FLASH 1 ++#define CONFIG_ENV_OFFSET 0x60000 /* environment starts here */ ++#define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ ++#define CONFIG_ASPEED_WRITE_DEFAULT_ENV ++#endif ++ ++#endif ++ ++#define __LITTLE_ENDIAN 1 ++ ++#define CONFIG_MONITOR_BASE TEXT_BASE ++#define CONFIG_MONITOR_LEN (192 << 10) ++ ++/* timeout values are in ticks */ ++#define CONFIG_SYS_FLASH_ERASE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Erase */ ++#define CONFIG_SYS_FLASH_WRITE_TOUT (20*CONFIG_SYS_HZ) /* Timeout for Flash Write */ ++ ++/* ++ * Miscellaneous configurable options ++ */ ++#define CONFIG_SYS_LONGHELP /* undef to save memory */ ++ ++#define CONFIG_SYS_PROMPT "boot# " /* Monitor Command Prompt */ ++#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ ++#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE+sizeof(CONFIG_SYS_PROMPT)+16) /* Print Buffer Size */ ++#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ ++#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ ++ ++#define CONFIG_SYS_MEMTEST_START 0x40000000 /* memtest works on */ ++#define CONFIG_SYS_MEMTEST_END 0x44FFFFFF /* 256 MB in DRAM */ ++ ++#define CONFIG_SYS_LOAD_ADDR 0x43000000 /* default load address */ ++ ++#define CONFIG_SYS_TIMERBASE 0x1E782000 /* use timer 1 */ ++#define CONFIG_SYS_HZ 1000 ++#define CONFIG_ASPEED_TIMER_CLK (1*1000*1000) /* use external clk (1M) */ ++ ++/* ++ * Serial Configuration ++ */ ++#define CONFIG_SYS_NS16550 ++#define CONFIG_SYS_NS16550_SERIAL ++#define CONFIG_SYS_NS16550_MEM32 ++#define CONFIG_SYS_NS16550_REG_SIZE -4 ++#define CONFIG_SYS_NS16550_CLK 24000000 ++#define CONFIG_SYS_NS16550_COM1 0x1e783000 ++#define CONFIG_SYS_NS16550_COM2 0x1e784000 ++#define CONFIG_SYS_NS16550_COM3 0x1e78e000 ++#define CONFIG_SYS_LOADS_BAUD_CHANGE ++#define CONFIG_CONS_INDEX 3 ++#define CONFIG_BAUDRATE 9600 ++#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } ++#define CONFIG_ASPEED_COM 0x1e78e000 // COM3 ++#define CONFIG_ASPEED_COM_IER (CONFIG_ASPEED_COM + 0x4) ++#define CONFIG_ASPEED_COM_IIR (CONFIG_ASPEED_COM + 0x8) ++#define CONFIG_ASPEED_COM_LCR (CONFIG_ASPEED_COM + 0xc) ++ ++/* ++ * USB device configuration ++ */ ++/* ++#define CONFIG_USB_DEVICE 1 ++#define CONFIG_USB_TTY 1 ++ ++#define CONFIG_USBD_VENDORID 0x1234 ++#define CONFIG_USBD_PRODUCTID 0x5678 ++#define CONFIG_USBD_MANUFACTURER "Siemens" ++#define CONFIG_USBD_PRODUCT_NAME "SX1" ++*/ ++ ++/* ++ * I2C configuration ++ */ ++#define CONFIG_HARD_I2C ++#define CONFIG_SYS_I2C_SPEED 100000 ++#define CONFIG_SYS_I2C_SLAVE 1 ++#define CONFIG_DRIVER_ASPEED_I2C ++ ++/* ++* EEPROM configuration ++*/ ++#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 ++#define CONFIG_SYS_I2C_EEPROM_ADDR 0xa0 ++ ++#define __BYTE_ORDER __LITTLE_ENDIAN ++#define __LITTLE_ENDIAN_BITFIELD ++ ++/* ++ * NIC configuration ++ */ ++#define CONFIG_ASPEEDNIC ++#define CONFIG_NET_MULTI ++#define CONFIG_MAC1_PHY_LINK_INTERRUPT ++#define CONFIG_MAC2_ENABLE ++#define CONFIG_MAC2_PHY_LINK_INTERRUPT ++/* ++*------------------------------------------------------------------------------- ++* NOTICE: MAC1 and MAC2 now have their own seperate PHY configuration. ++* We use 2 bits for each MAC in the scratch register(D[15:11] in 0x1E6E2040) to ++* inform kernel driver. ++* The meanings of the 2 bits are: ++* 00(0): Dedicated PHY ++* 01(1): ASPEED's EVA + INTEL's NC-SI PHY chip EVA ++* 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly ++* 11: Reserved ++* ++* We use CONFIG_MAC1_PHY_SETTING and CONFIG_MAC2_PHY_SETTING in U-Boot ++* 0: Dedicated PHY ++* 1: ASPEED's EVA + INTEL's NC-SI PHY chip EVA ++* 2: ASPEED's MAC is connected to NC-SI PHY chip directly ++* 3: Reserved ++*------------------------------------------------------------------------------- ++*/ ++#define CONFIG_MAC1_PHY_SETTING 0 ++#define CONFIG_MAC2_PHY_SETTING 0 ++#define CONFIG_ASPEED_MAC_NUMBER 2 ++#define CONFIG_ASPEED_MAC_CONFIG 2 // config MAC2 ++#define _PHY_SETTING_CONCAT(mac) CONFIG_MAC##mac##_PHY_SETTING ++#define _GET_MAC_PHY_SETTING(mac) _PHY_SETTING_CONCAT(mac) ++#define CONFIG_ASPEED_MAC_PHY_SETTING \ ++ _GET_MAC_PHY_SETTING(CONFIG_ASPEED_MAC_CONFIG) ++#define CONFIG_MAC_INTERFACE_CLOCK_DELAY 0x2255 ++#define CONFIG_RANDOM_MACADDR ++//#define CONFIG_GATEWAYIP 192.168.0.1 ++//#define CONFIG_NETMASK 255.255.255.0 ++//#define CONFIG_IPADDR 192.168.0.45 ++//#define CONFIG_SERVERIP 192.168.0.81 ++ ++/* ++ * SLT ++ */ ++/* ++#define CONFIG_SLT ++#define CFG_CMD_SLT (CFG_CMD_VIDEOTEST | CFG_CMD_MACTEST | CFG_CMD_HACTEST | CFG_CMD_MICTEST) ++*/ ++ ++#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) ++ ++#define CONFIG_ASPEED_ENABLE_WATCHDOG ++#define CONFIG_ASPEED_WATCHDOG_TIMEOUT (5*60) // 5m ++#define CONFIG_ASPEED_ENABLE_DUAL_BOOT_WATCHDOG ++#define CONFIG_ASPEED_WATCHDOG_DUAL_BOOT_TIMEOUT \ ++ (CONFIG_ASPEED_WATCHDOG_TIMEOUT - 5) ++ ++#endif /* __CONFIG_H */ +-- +1.8.1 + diff --git a/meta-aspeed/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend b/meta-aspeed/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend index c93571b..ac75c33 100644 --- a/meta-aspeed/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend +++ b/meta-aspeed/recipes-bsp/u-boot/u-boot-fw-utils_2013.07%.bbappend @@ -2,4 +2,19 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" SRC_URI += "file://patch-2013.07/0000-u-boot-aspeed-064.patch \ file://patch-2013.07/0001-u-boot-openbmc.patch \ - " + file://patch-2013.07/0002-Create-snapshot-of-OpenBMC.patch \ + " + +PV = "v2013.07" + +S = "${WORKDIR}/u-boot-v2013.07" + +# This is an ugly hack, but we want to get this out the door, rather than +# spending forever fiddling with yocto and bitbake. + +do_install_append() { + if [ -e ${WORKDIR}/fw_env.config ] ; then + install -d ${D}${sysconfdir} + install -m 644 ${WORKDIR}/fw_env.config ${D}${sysconfdir}/fw_env.config + fi +} diff --git a/meta-aspeed/recipes-bsp/u-boot/u-boot_2013.07%.bbappend b/meta-aspeed/recipes-bsp/u-boot/u-boot_2013.07%.bbappend index d4e347b..0ecbd77 100644 --- a/meta-aspeed/recipes-bsp/u-boot/u-boot_2013.07%.bbappend +++ b/meta-aspeed/recipes-bsp/u-boot/u-boot_2013.07%.bbappend @@ -1,12 +1,10 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" -SRC_URI += "file://fw_env.config \ - file://patch-2013.07/0000-u-boot-aspeed-064.patch \ +SRC_URI += "file://patch-2013.07/0000-u-boot-aspeed-064.patch \ file://patch-2013.07/0001-u-boot-openbmc.patch \ - " + file://patch-2013.07/0002-Create-snapshot-of-OpenBMC.patch \ + " -# Do not install u-boot in rootfs -do_install[postfuncs] += "remove_uboot_from_rootfs" -remove_uboot_from_rootfs() { - rm -rf ${D}/boot/u-boot* -} +PV = "v2013.07" + +S = "${WORKDIR}/u-boot-v2013.07" diff --git a/meta-aspeed/recipes-core/images/files/aspeed_device_table b/meta-aspeed/recipes-core/images/files/aspeed_device_table index fac26b9..55dc7e0 100644 --- a/meta-aspeed/recipes-core/images/files/aspeed_device_table +++ b/meta-aspeed/recipes-core/images/files/aspeed_device_table @@ -35,7 +35,6 @@ /dev/urandom c 644 root root 1 9 - - - /dev/watchdog c 660 root root 10 130 - - - /dev/zero c 644 root root 1 5 - - - -/dev/i2c- c 600 root root 89 0 0 1 10 -/dev/i2c- c 600 root root 89 11 11 1 2 +/dev/i2c- c 600 root root 89 0 0 1 13 /dev/net d 755 root root - - - - - /dev/net/tun c 600 root root 10 200 - - - diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-Create-snapshot-of-OpenBMC.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-Create-snapshot-of-OpenBMC.patch new file mode 100644 index 0000000..a2705bf --- /dev/null +++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-Create-snapshot-of-OpenBMC.patch @@ -0,0 +1,11455 @@ +From 19459c799ac0a521082d6d79e68ffc3decb18ea2 Mon Sep 17 00:00:00 2001 +From: Ori Bernstein <orib@fb.com> +Date: Thu, 3 Sep 2015 11:28:27 -0700 +Subject: [PATCH] Create snapshot of OpenBMC + +--- + .../arch/arm/configs/fbplatform1_defconfig | 1480 ++++++++++++++++++++ + .../arch/arm/configs/wedge100_defconfig | 1462 +++++++++++++++++++ + .../arch/arm/configs/wedge_defconfig | 1 + + .../arch/arm/configs/yosemite_defconfig | 1480 ++++++++++++++++++++ + .../arch/arm/include/asm/ioctls.h | 1 + + .../arch/arm/mach-aspeed/Kconfig | 12 + + .../arch/arm/mach-aspeed/gpio.c | 2 +- + .../arm/mach-aspeed/include/mach/debug-macro.S | 4 +- + .../arch/arm/mach-aspeed/include/mach/platform.h | 17 +- + .../arch/arm/mach-aspeed/include/mach/uncompress.h | 6 +- + .../arch/arm/mach-aspeed/include/mach/vmalloc.h | 4 +- + .../arch/arm/plat-aspeed/ast-scu.c | 372 ++--- + .../arch/arm/plat-aspeed/dev-eth.c | 35 +- + .../arch/arm/plat-aspeed/dev-i2c.c | 385 +++-- + .../arch/arm/plat-aspeed/dev-spi.c | 27 +- + .../arch/arm/plat-aspeed/dev-uart.c | 50 +- + .../arch/arm/plat-aspeed/irq.c | 28 +- + .../linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c | 233 +-- + .../drivers/i2c/busses/i2c-ast.c | 689 +++++---- + .../linux-aspeed-2.6.28.9/drivers/i2c/i2c-core.c | 15 +- + .../linux-aspeed-2.6.28.9/drivers/i2c/i2c-dev.c | 113 +- + .../drivers/net/ftgmac100_26.c | 1211 ++++++++++++++-- + .../drivers/net/ftgmac100_26.h | 67 +- + .../linux-aspeed-2.6.28.9/drivers/rtc/rtc-aspeed.c | 42 +- + .../linux-aspeed-2.6.28.9/drivers/serial/8250.c | 39 +- + .../linux-aspeed-2.6.28.9/drivers/watchdog/Kconfig | 9 +- + .../drivers/watchdog/ast_wdt.c | 27 + + .../files/linux-aspeed-2.6.28.9/fs/compat_ioctl.c | 51 +- + .../linux-aspeed-2.6.28.9/include/linux/i2c-dev.h | 1 + + .../linux-aspeed-2.6.28.9/include/linux/i2c.h | 6 + + ...m25p80-Add-support-for-the-Winbond-W25Q64.patch | 29 + + ...t-leak-packets-when-a-netns-is-going-down.patch | 56 + + ...int-error-value-when-skb-allocation-fails.patch | 43 + + .../recipes-kernel/linux/linux-aspeed_2.6.28.9.bb | 17 +- + 34 files changed, 7064 insertions(+), 950 deletions(-) + create mode 100644 meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/fbplatform1_defconfig + create mode 100644 meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/wedge100_defconfig + create mode 100644 meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/yosemite_defconfig + create mode 100644 meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch + create mode 100644 meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch + create mode 100644 meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch + +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/fbplatform1_defconfig b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/fbplatform1_defconfig +new file mode 100644 +index 0000000..800d597 +--- /dev/null ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/fbplatform1_defconfig +@@ -0,0 +1,1480 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.28.9 ++# Tue Feb 3 16:41:40 2015 ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y ++CONFIG_GENERIC_TIME=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_MMU=y ++# CONFIG_NO_IOPORT is not set ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y ++CONFIG_VECTORS_BASE=0xffff0000 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_BZIP2 is not set ++# CONFIG_KERNEL_LZMA is not set ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++# CONFIG_CGROUPS is not set ++# CONFIG_GROUP_SCHED is not set ++CONFIG_SYSFS_DEPRECATED=y ++CONFIG_SYSFS_DEPRECATED_V2=y ++# CONFIG_RELAY is not set ++CONFIG_NAMESPACES=y ++# CONFIG_UTS_NS is not set ++# CONFIG_IPC_NS is not set ++# CONFIG_USER_NS is not set ++# CONFIG_PID_NS is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++# CONFIG_EMBEDDED is not set ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_KALLSYMS_EXTRA_PASS=y ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++# CONFIG_MARKERS is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=y ++CONFIG_RT_MUTEXES=y ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++CONFIG_BLOCK=y ++# CONFIG_LBD is not set ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_AS is not set ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++CONFIG_CLASSIC_RCU=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_ARCH_ASPEED=y ++# CONFIG_ARCH_AAEC2000 is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_NS9XXX is not set ++# CONFIG_ARCH_LOKI is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_MSM is not set ++CONFIG_IRMP=y ++# CONFIG_PCEXT is not set ++# CONFIG_REMOTEFX is not set ++# CONFIG_ARCH_AST1100 is not set ++# CONFIG_ARCH_AST2100 is not set ++# CONFIG_ARCH_AST2200 is not set ++# CONFIG_ARCH_AST2300 is not set ++CONFIG_ARCH_AST2400=y ++CONFIG_FBPLATFORM1=y ++# CONFIG_ARCH_AST2500 is not set ++ ++# ++# FLASH Chip Select ++# ++# CONFIG_AST_CS0_NOR is not set ++# CONFIG_AST_CS0_NAND is not set ++CONFIG_AST_CS0_SPI=y ++# CONFIG_AST_CS0_NONE is not set ++# CONFIG_AST_CS1_NOR is not set ++# CONFIG_AST_CS1_NAND is not set ++# CONFIG_AST_CS1_SPI is not set ++CONFIG_AST_CS1_NONE=y ++# CONFIG_AST_CS2_NOR is not set ++# CONFIG_AST_CS2_NAND is not set ++# CONFIG_AST_CS2_SPI is not set ++CONFIG_AST_CS2_NONE=y ++# CONFIG_AST_CS3_NOR is not set ++# CONFIG_AST_CS3_NAND is not set ++# CONFIG_AST_CS3_SPI is not set ++CONFIG_AST_CS3_NONE=y ++# CONFIG_AST_CS4_NOR is not set ++# CONFIG_AST_CS4_NAND is not set ++# CONFIG_AST_CS4_SPI is not set ++CONFIG_AST_CS4_NONE=y ++# CONFIG_ARCH_AST1070 is not set ++# CONFIG_AST_SCU_LOCK is not set ++ ++# ++# Boot options ++# ++ ++# ++# Power management ++# ++CONFIG_PLAT_ASPEED=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_NOIFAR=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++# CONFIG_OUTER_CACHE is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++CONFIG_ARCH_FLATMEM_HAS_HOLES=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4096 ++# CONFIG_RESOURCES_64BIT is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++CONFIG_UNEVICTABLE_LRU=y ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0 ++CONFIG_ZBOOT_ROM_BSS=0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++ ++# ++# CPU Power Management ++# ++# CONFIG_CPU_IDLE is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++CONFIG_FPE_NWFPE_XP=y ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_HAVE_AOUT=y ++CONFIG_BINFMT_AOUT=y ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_SLEEP=y ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_APM_EMULATION is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++# CONFIG_PACKET_MMAP is not set ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE is not set ++# CONFIG_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++# CONFIG_INET_LRO is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++# CONFIG_INET6_AH is not set ++# CONFIG_INET6_ESP is not set ++# CONFIG_INET6_IPCOMP is not set ++# CONFIG_IPV6_MIP6 is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETFILTER is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_NET_DSA is not set ++CONFIG_VLAN_8021Q=m ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++CONFIG_WAN_ROUTER=y ++# CONFIG_NET_SCHED is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++# CONFIG_PHONET is not set ++# CONFIG_WIRELESS is not set ++# CONFIG_RFKILL is not set ++# CONFIG_NET_9P is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_SYS_HYPERVISOR is not set ++CONFIG_CONNECTOR=y ++CONFIG_PROC_EVENTS=y ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++CONFIG_MTD_CONCAT=y ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_MTD_OOPS is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++# CONFIG_MTD_CFI is not set ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y ++# CONFIG_MTD_DATAFLASH_OTP is not set ++CONFIG_MTD_M25P80=y ++CONFIG_M25PXX_USE_FAST_READ=y ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# CONFIG_MTD_NAND is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# UBI - Unsorted block images ++# ++# CONFIG_MTD_UBI is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++CONFIG_BLK_DEV_NBD=y ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=16384 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_RD_BZIP2 is not set ++CONFIG_RD_LZMA=y ++CONFIG_RD_GZIP=y ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_C2PORT is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_TGT=y ++# CONFIG_SCSI_NETLINK is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++CONFIG_CHR_DEV_SG=y ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++CONFIG_SCSI_SCAN_ASYNC=y ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++CONFIG_SCSI_ISCSI_ATTRS=m ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++CONFIG_BONDING=m ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++CONFIG_TUN=m ++# CONFIG_VETH is not set ++# CONFIG_NET_ETHERNET is not set ++CONFIG_NETDEV_1000=y ++CONFIG_ASPEEDMAC=y ++# CONFIG_NETDEV_10000 is not set ++ ++# ++# Wireless LAN ++# ++# CONFIG_WLAN_PRE80211 is not set ++# CONFIG_WLAN_80211 is not set ++# CONFIG_IWLWIFI_LEDS is not set ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_WAN is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_POLLDEV is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_GPIO is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_LIFEBOOK=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_SERIAL=y ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_DEVKMEM=y ++CONFIG_SERIAL_NONSTANDARD=y ++# CONFIG_N_HDLC is not set ++# CONFIG_RISCOM8 is not set ++# CONFIG_SPECIALIX is not set ++# CONFIG_RIO is not set ++# CONFIG_STALDRV is not set ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=5 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=5 ++# CONFIG_SERIAL_AST_DMA_UART is not set ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++# CONFIG_SERIAL_AST is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_AST_MISC=y ++# CONFIG_AST_VIDEO is not set ++# CONFIG_ADC_CAT9883 is not set ++# CONFIG_AST_SPI_BIOS is not set ++CONFIG_AST_PECI=y ++# CONFIG_AST_KCS is not set ++# CONFIG_AST_GPIO is not set ++# CONFIG_HW_RANDOM is not set ++CONFIG_NVRAM=y ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_OCORES is not set ++CONFIG_I2C_AST=y ++CONFIG_AST_I2C_SLAVE_MODE=y ++# CONFIG_AST_I2C_SLAVE_EEPROM is not set ++CONFIG_AST_I2C_SLAVE_RDWR=y ++# CONFIG_I2C_SIMTEC is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++# CONFIG_I2C_TINY_USB is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_STUB is not set ++ ++# ++# Miscellaneous I2C Chip support ++# ++# CONFIG_DS1682 is not set ++CONFIG_AT24=m ++# CONFIG_SENSORS_EEPROM is not set ++CONFIG_SENSORS_PCF8574=m ++# CONFIG_PCF8575 is not set ++# CONFIG_SENSORS_PCA9539 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_SENSORS_MAX6875 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++# CONFIG_I2C_DEBUG_CHIP is not set ++CONFIG_SPI=y ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++CONFIG_SPI_AST=y ++CONFIG_SPI_FMC=y ++CONFIG_SPI_BITBANG=y ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_AT25=m ++# CONFIG_SPI_SPIDEV is not set ++# CONFIG_SPI_TLE62X0 is not set ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO expanders: ++# ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_GPIO_PCF857X is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++CONFIG_HWMON=y ++# CONFIG_HWMON_VID is not set ++# CONFIG_SENSORS_AD7414 is not set ++# CONFIG_SENSORS_AD7418 is not set ++# CONFIG_SENSORS_ADCXX is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1029 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ADT7462 is not set ++# CONFIG_SENSORS_ADT7470 is not set ++# CONFIG_SENSORS_ADT7473 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_F71882FG is not set ++# CONFIG_SENSORS_F75375S is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM70 is not set ++CONFIG_SENSORS_LM75=m ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_LM93 is not set ++CONFIG_SENSORS_MAX127=m ++# CONFIG_SENSORS_MAX1111 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_MAX6650 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++# CONFIG_SENSORS_DME1737 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++CONFIG_SENSORS_ADS7828=m ++# CONFIG_SENSORS_THMC50 is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83L786NG is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++CONFIG_SENSORS_AST_ADC=y ++CONFIG_SENSORS_AST_PWM_FAN=y ++# CONFIG_SENSORS_FB_PANTHER_PLUS is not set ++CONFIG_PMBUS=m ++CONFIG_SENSORS_PMBUS=m ++CONFIG_SENSORS_ADM1275=m ++# CONFIG_SENSORS_LM25066 is not set ++# CONFIG_SENSORS_LTC2978 is not set ++# CONFIG_SENSORS_MAX16064 is not set ++# CONFIG_SENSORS_MAX34440 is not set ++# CONFIG_SENSORS_MAX8688 is not set ++CONFIG_SENSORS_PFE1100=m ++CONFIG_SENSORS_PFE3000=m ++# CONFIG_SENSORS_UCD9000 is not set ++# CONFIG_SENSORS_UCD9200 is not set ++# CONFIG_SENSORS_ZL6100 is not set ++# CONFIG_HWMON_DEBUG_CHIP is not set ++CONFIG_THERMAL=y ++CONFIG_THERMAL_HWMON=y ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_AST_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++CONFIG_SSB_POSSIBLE=y ++ ++# ++# Sonics Silicon Backplane ++# ++# CONFIG_SSB is not set ++ ++# ++# Multifunction device drivers ++# ++# CONFIG_MFD_CORE is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_MFD_ASIC3 is not set ++# CONFIG_HTC_EGPIO is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_TC6393XB is not set ++# CONFIG_PMIC_DA903X is not set ++# CONFIG_MFD_WM8400 is not set ++# CONFIG_MFD_WM8350_I2C is not set ++ ++# ++# Multimedia devices ++# ++ ++# ++# Multimedia core support ++# ++# CONFIG_VIDEO_DEV is not set ++# CONFIG_DVB_CORE is not set ++# CONFIG_VIDEO_MEDIA is not set ++ ++# ++# Multimedia drivers ++# ++# CONFIG_DAB is not set ++ ++# ++# Graphics support ++# ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_SOUND is not set ++# CONFIG_HID_SUPPORT is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_ARCH_HAS_HCD=y ++# CONFIG_USB_ARCH_HAS_OHCI is not set ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB=m ++# CONFIG_USB_DEBUG is not set ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_SUSPEND is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_EHCI_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_HWA_HCD is not set ++ ++# ++# AST USB Drivers ++# ++CONFIG_AST_USB_UHCI_HCD=y ++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set ++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set ++CONFIG_AST_USB_UHCI_MULTIPORT_4=y ++# CONFIG_USB_EHCI_SPLIT_ISO is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_TMC is not set ++ ++# ++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; ++# ++ ++# ++# see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=m ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_BERRY_CHARGE is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGET is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_VST is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_SELECTED=y ++# CONFIG_USB_GADGET_AT91 is not set ++# CONFIG_USB_GADGET_ATMEL_USBA is not set ++# CONFIG_USB_GADGET_FSL_USB2 is not set ++# CONFIG_USB_GADGET_LH7A40X is not set ++# CONFIG_USB_GADGET_OMAP is not set ++# CONFIG_USB_GADGET_PXA25X is not set ++# CONFIG_USB_GADGET_PXA27X is not set ++# CONFIG_USB_GADGET_S3C2410 is not set ++# CONFIG_USB_GADGET_M66592 is not set ++# CONFIG_USB_GADGET_AMD5536UDC is not set ++# CONFIG_USB_GADGET_FSL_QE is not set ++# CONFIG_USB_GADGET_NET2280 is not set ++# CONFIG_USB_GADGET_GOKU is not set ++CONFIG_USB_GADGET_ASPEED_AST=y ++CONFIG_USB_ASPEED_AST=y ++# CONFIG_USB_GADGET_DUMMY_HCD is not set ++CONFIG_USB_GADGET_DUALSPEED=y ++CONFIG_USB_ZERO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_FILE_STORAGE=m ++# CONFIG_USB_FILE_STORAGE_TEST is not set ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_MIDI_GADGET is not set ++# CONFIG_USB_G_PRINTER is not set ++CONFIG_USB_CDC_COMPOSITE=m ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_NEW_LEDS is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++# CONFIG_RTC_DEBUG is not set ++ ++# ++# RTC interfaces ++# ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_DEV=y ++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set ++# CONFIG_RTC_DRV_TEST is not set ++ ++# ++# I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++# CONFIG_RTC_DRV_RX8581 is not set ++ ++# ++# SPI RTC drivers ++# ++# CONFIG_RTC_DRV_M41T94 is not set ++# CONFIG_RTC_DRV_DS1305 is not set ++# CONFIG_RTC_DRV_DS1390 is not set ++# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++# CONFIG_RTC_DRV_DS3234 is not set ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_CMOS is not set ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_STK17TA8 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_M48T35 is not set ++# CONFIG_RTC_DRV_M48T59 is not set ++# CONFIG_RTC_DRV_BQ4802 is not set ++# CONFIG_RTC_DRV_V3020 is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++CONFIG_RTC_DRV_ASPEED=y ++# CONFIG_DMADEVICES is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_UIO is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++# CONFIG_EXT2_FS_XIP is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_EXT4_FS is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++# CONFIG_XFS_FS is not set ++# CONFIG_OCFS2_FS is not set ++CONFIG_DNOTIFY=y ++CONFIG_INOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_QUOTA is not set ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_FS is not set ++# CONFIG_FUSE_FS is not set ++CONFIG_GENERIC_ACL=y ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_NTFS_FS=y ++# CONFIG_NTFS_DEBUG is not set ++CONFIG_NTFS_RW=y ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_CONFIGFS_FS=m ++ ++# ++# Miscellaneous filesystems ++# ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set ++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_CRAMFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++# CONFIG_NFS_V3 is not set ++# CONFIG_NFS_V4 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_SUNRPC_REGISTER_V4 is not set ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=y ++CONFIG_NLS_CODEPAGE_932=y ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=y ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_KERNEL is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_RCU_CPU_STALL_DETECTOR is not set ++# CONFIG_LATENCYTOP is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++CONFIG_HAVE_FUNCTION_TRACER=y ++ ++# ++# Tracers ++# ++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_DEBUG_USER is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++# CONFIG_SECURITY_FILE_CAPABILITIES is not set ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++# CONFIG_CRYPTO_FIPS is not set ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_AEAD=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_SEQIV is not set ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=y ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++CONFIG_CRYPTO_HMAC=y ++# CONFIG_CRYPTO_XCBC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++CONFIG_CRYPTO_SHA1=y ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=m ++# CONFIG_CRYPTO_LZO is not set ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_HW is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++# CONFIG_CRC_CCITT is not set ++# CONFIG_CRC16 is not set ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=m ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_PLIST=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++ ++ ++# GUC USB Drivers ++# ++CONFIG_GUC_USB_UHCI_HCD=m ++# CONFIG_GUC_USB_UHCI_MULTIPORT_1 is not set ++# CONFIG_GUC_USB_UHCI_MULTIPORT_2 is not set ++CONFIG_GUC_USB_UHCI_MULTIPORT_4=y ++# CONFIG_USB_GADGET_MUSB_HDRC is not set +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/wedge100_defconfig b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/wedge100_defconfig +new file mode 100644 +index 0000000..0f9f0f7 +--- /dev/null ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/wedge100_defconfig +@@ -0,0 +1,1462 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.28.9 ++# Wed Aug 5 18:43:53 2015 ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y ++CONFIG_GENERIC_TIME=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_MMU=y ++# CONFIG_NO_IOPORT is not set ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y ++CONFIG_VECTORS_BASE=0xffff0000 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_BZIP2 is not set ++# CONFIG_KERNEL_LZMA is not set ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++# CONFIG_CGROUPS is not set ++# CONFIG_GROUP_SCHED is not set ++CONFIG_SYSFS_DEPRECATED=y ++CONFIG_SYSFS_DEPRECATED_V2=y ++# CONFIG_RELAY is not set ++CONFIG_NAMESPACES=y ++# CONFIG_UTS_NS is not set ++# CONFIG_IPC_NS is not set ++# CONFIG_USER_NS is not set ++# CONFIG_PID_NS is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++# CONFIG_EMBEDDED is not set ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_KALLSYMS_EXTRA_PASS=y ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++# CONFIG_MARKERS is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=y ++CONFIG_RT_MUTEXES=y ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++CONFIG_BLOCK=y ++# CONFIG_LBD is not set ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_AS is not set ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++CONFIG_CLASSIC_RCU=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_ARCH_ASPEED=y ++# CONFIG_ARCH_AAEC2000 is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_NS9XXX is not set ++# CONFIG_ARCH_LOKI is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_MSM is not set ++CONFIG_IRMP=y ++# CONFIG_PCEXT is not set ++# CONFIG_REMOTEFX is not set ++# CONFIG_ARCH_AST1100 is not set ++# CONFIG_ARCH_AST2100 is not set ++# CONFIG_ARCH_AST2200 is not set ++# CONFIG_ARCH_AST2300 is not set ++CONFIG_ARCH_AST2400=y ++# CONFIG_ARCH_AST2500 is not set ++ ++# ++# FLASH Chip Select ++# ++# CONFIG_AST_CS0_NOR is not set ++# CONFIG_AST_CS0_NAND is not set ++CONFIG_AST_CS0_SPI=y ++# CONFIG_AST_CS0_NONE is not set ++# CONFIG_AST_CS1_NOR is not set ++# CONFIG_AST_CS1_NAND is not set ++# CONFIG_AST_CS1_SPI is not set ++CONFIG_AST_CS1_NONE=y ++# CONFIG_AST_CS2_NOR is not set ++# CONFIG_AST_CS2_NAND is not set ++# CONFIG_AST_CS2_SPI is not set ++CONFIG_AST_CS2_NONE=y ++# CONFIG_AST_CS3_NOR is not set ++# CONFIG_AST_CS3_NAND is not set ++# CONFIG_AST_CS3_SPI is not set ++CONFIG_AST_CS3_NONE=y ++# CONFIG_AST_CS4_NOR is not set ++# CONFIG_AST_CS4_NAND is not set ++# CONFIG_AST_CS4_SPI is not set ++CONFIG_AST_CS4_NONE=y ++# CONFIG_ARCH_AST1070 is not set ++# CONFIG_AST_SCU_LOCK is not set ++# CONFIG_WEDGE is not set ++CONFIG_WEDGE100=y ++# CONFIG_YOSEMITE is not set ++ ++# ++# Boot options ++# ++ ++# ++# Power management ++# ++CONFIG_PLAT_ASPEED=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_NOIFAR=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++# CONFIG_OUTER_CACHE is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++CONFIG_ARCH_FLATMEM_HAS_HOLES=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4096 ++# CONFIG_RESOURCES_64BIT is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++CONFIG_UNEVICTABLE_LRU=y ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0 ++CONFIG_ZBOOT_ROM_BSS=0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++ ++# ++# CPU Power Management ++# ++# CONFIG_CPU_IDLE is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++CONFIG_FPE_NWFPE_XP=y ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_HAVE_AOUT=y ++CONFIG_BINFMT_AOUT=y ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_SLEEP=y ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_APM_EMULATION is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++# CONFIG_PACKET_MMAP is not set ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE is not set ++# CONFIG_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++# CONFIG_INET_LRO is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++# CONFIG_INET6_AH is not set ++# CONFIG_INET6_ESP is not set ++# CONFIG_INET6_IPCOMP is not set ++# CONFIG_IPV6_MIP6 is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETFILTER is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_NET_DSA is not set ++CONFIG_VLAN_8021Q=m ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++CONFIG_WAN_ROUTER=y ++# CONFIG_NET_SCHED is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++# CONFIG_PHONET is not set ++# CONFIG_WIRELESS is not set ++# CONFIG_RFKILL is not set ++# CONFIG_NET_9P is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_SYS_HYPERVISOR is not set ++CONFIG_CONNECTOR=y ++CONFIG_PROC_EVENTS=y ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++CONFIG_MTD_CONCAT=y ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_MTD_OOPS is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++# CONFIG_MTD_CFI is not set ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y ++# CONFIG_MTD_DATAFLASH_OTP is not set ++CONFIG_MTD_M25P80=y ++CONFIG_M25PXX_USE_FAST_READ=y ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# CONFIG_MTD_NAND is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# UBI - Unsorted block images ++# ++# CONFIG_MTD_UBI is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++CONFIG_BLK_DEV_NBD=y ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=16384 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_RD_BZIP2 is not set ++CONFIG_RD_LZMA=y ++CONFIG_RD_GZIP=y ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_C2PORT is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_TGT=y ++# CONFIG_SCSI_NETLINK is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++CONFIG_CHR_DEV_SG=y ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++CONFIG_SCSI_SCAN_ASYNC=y ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++CONFIG_SCSI_ISCSI_ATTRS=m ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++CONFIG_BONDING=m ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++CONFIG_TUN=m ++# CONFIG_VETH is not set ++# CONFIG_NET_ETHERNET is not set ++CONFIG_NETDEV_1000=y ++CONFIG_ASPEEDMAC=y ++# CONFIG_NETDEV_10000 is not set ++ ++# ++# Wireless LAN ++# ++# CONFIG_WLAN_PRE80211 is not set ++# CONFIG_WLAN_80211 is not set ++# CONFIG_IWLWIFI_LEDS is not set ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_WAN is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_POLLDEV is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_GPIO is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_LIFEBOOK=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_SERIAL=y ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_DEVKMEM=y ++CONFIG_SERIAL_NONSTANDARD=y ++# CONFIG_N_HDLC is not set ++# CONFIG_RISCOM8 is not set ++# CONFIG_SPECIALIX is not set ++# CONFIG_RIO is not set ++# CONFIG_STALDRV is not set ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=4 ++# CONFIG_SERIAL_AST_DMA_UART is not set ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++# CONFIG_SERIAL_AST is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_AST_MISC=y ++# CONFIG_AST_VIDEO is not set ++# CONFIG_ADC_CAT9883 is not set ++# CONFIG_AST_SPI_BIOS is not set ++CONFIG_AST_PECI=y ++# CONFIG_AST_KCS is not set ++# CONFIG_AST_GPIO is not set ++# CONFIG_HW_RANDOM is not set ++CONFIG_NVRAM=y ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_OCORES is not set ++CONFIG_I2C_AST=y ++CONFIG_AST_I2C_SLAVE_MODE=y ++CONFIG_AST_I2C_SLAVE_EEPROM=y ++# CONFIG_AST_I2C_SLAVE_RDWR is not set ++# CONFIG_I2C_SIMTEC is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++# CONFIG_I2C_TINY_USB is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_STUB is not set ++ ++# ++# Miscellaneous I2C Chip support ++# ++# CONFIG_DS1682 is not set ++CONFIG_AT24=m ++# CONFIG_SENSORS_EEPROM is not set ++CONFIG_SENSORS_PCF8574=m ++# CONFIG_PCF8575 is not set ++# CONFIG_SENSORS_PCA9539 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_SENSORS_MAX6875 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++# CONFIG_I2C_DEBUG_CHIP is not set ++CONFIG_SPI=y ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++CONFIG_SPI_AST=y ++CONFIG_SPI_FMC=y ++CONFIG_SPI_BITBANG=y ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_AT25=m ++CONFIG_SPI_SPIDEV=m ++# CONFIG_SPI_TLE62X0 is not set ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO expanders: ++# ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_GPIO_PCF857X is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++CONFIG_HWMON=y ++# CONFIG_HWMON_VID is not set ++# CONFIG_SENSORS_AD7414 is not set ++# CONFIG_SENSORS_AD7418 is not set ++# CONFIG_SENSORS_ADCXX is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1029 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ADT7462 is not set ++# CONFIG_SENSORS_ADT7470 is not set ++# CONFIG_SENSORS_ADT7473 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_F71882FG is not set ++# CONFIG_SENSORS_F75375S is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM70 is not set ++CONFIG_SENSORS_LM75=m ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_LM93 is not set ++CONFIG_SENSORS_MAX127=m ++# CONFIG_SENSORS_MAX1111 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_MAX6650 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++# CONFIG_SENSORS_DME1737 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++CONFIG_SENSORS_ADS7828=m ++# CONFIG_SENSORS_THMC50 is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83L786NG is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++CONFIG_SENSORS_AST_ADC=m ++# CONFIG_SENSORS_AST_PWM_FAN is not set ++CONFIG_SENSORS_FB_PANTHER_PLUS=m ++CONFIG_PMBUS=m ++CONFIG_SENSORS_PMBUS=m ++CONFIG_SENSORS_ADM1275=m ++# CONFIG_SENSORS_LM25066 is not set ++# CONFIG_SENSORS_LTC2978 is not set ++# CONFIG_SENSORS_MAX16064 is not set ++# CONFIG_SENSORS_MAX34440 is not set ++# CONFIG_SENSORS_MAX8688 is not set ++CONFIG_SENSORS_PFE1100=m ++CONFIG_SENSORS_PFE3000=m ++# CONFIG_SENSORS_UCD9000 is not set ++# CONFIG_SENSORS_UCD9200 is not set ++# CONFIG_SENSORS_ZL6100 is not set ++# CONFIG_HWMON_DEBUG_CHIP is not set ++CONFIG_THERMAL=y ++CONFIG_THERMAL_HWMON=y ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_AST_WATCHDOG=y ++CONFIG_AST_WATCHDOG_REARM_DUAL_BOOT=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++CONFIG_SSB_POSSIBLE=y ++ ++# ++# Sonics Silicon Backplane ++# ++# CONFIG_SSB is not set ++ ++# ++# Multifunction device drivers ++# ++# CONFIG_MFD_CORE is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_MFD_ASIC3 is not set ++# CONFIG_HTC_EGPIO is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_TC6393XB is not set ++# CONFIG_PMIC_DA903X is not set ++# CONFIG_MFD_WM8400 is not set ++# CONFIG_MFD_WM8350_I2C is not set ++ ++# ++# Multimedia devices ++# ++ ++# ++# Multimedia core support ++# ++# CONFIG_VIDEO_DEV is not set ++# CONFIG_DVB_CORE is not set ++# CONFIG_VIDEO_MEDIA is not set ++ ++# ++# Multimedia drivers ++# ++# CONFIG_DAB is not set ++ ++# ++# Graphics support ++# ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_SOUND is not set ++# CONFIG_HID_SUPPORT is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_ARCH_HAS_HCD=y ++# CONFIG_USB_ARCH_HAS_OHCI is not set ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB=m ++# CONFIG_USB_DEBUG is not set ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_SUSPEND is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_EHCI_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_HWA_HCD is not set ++ ++# ++# AST USB Drivers ++# ++CONFIG_AST_USB_UHCI_HCD=m ++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set ++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set ++CONFIG_AST_USB_UHCI_MULTIPORT_4=y ++# CONFIG_USB_GADGET_MUSB_HDRC is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_TMC is not set ++ ++# ++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; ++# ++ ++# ++# see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=m ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_BERRY_CHARGE is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGET is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_VST is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_SELECTED=y ++# CONFIG_USB_GADGET_AT91 is not set ++# CONFIG_USB_GADGET_ATMEL_USBA is not set ++# CONFIG_USB_GADGET_FSL_USB2 is not set ++# CONFIG_USB_GADGET_LH7A40X is not set ++# CONFIG_USB_GADGET_OMAP is not set ++# CONFIG_USB_GADGET_PXA25X is not set ++# CONFIG_USB_GADGET_PXA27X is not set ++# CONFIG_USB_GADGET_S3C2410 is not set ++# CONFIG_USB_GADGET_M66592 is not set ++# CONFIG_USB_GADGET_AMD5536UDC is not set ++# CONFIG_USB_GADGET_FSL_QE is not set ++# CONFIG_USB_GADGET_NET2280 is not set ++# CONFIG_USB_GADGET_GOKU is not set ++CONFIG_USB_GADGET_ASPEED_AST=y ++CONFIG_USB_ASPEED_AST=y ++# CONFIG_USB_GADGET_DUMMY_HCD is not set ++CONFIG_USB_GADGET_DUALSPEED=y ++CONFIG_USB_ZERO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_FILE_STORAGE=m ++# CONFIG_USB_FILE_STORAGE_TEST is not set ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_MIDI_GADGET is not set ++# CONFIG_USB_G_PRINTER is not set ++CONFIG_USB_CDC_COMPOSITE=m ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_NEW_LEDS is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++# CONFIG_RTC_DEBUG is not set ++ ++# ++# RTC interfaces ++# ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_DEV=y ++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set ++# CONFIG_RTC_DRV_TEST is not set ++ ++# ++# I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++# CONFIG_RTC_DRV_RX8581 is not set ++ ++# ++# SPI RTC drivers ++# ++# CONFIG_RTC_DRV_M41T94 is not set ++# CONFIG_RTC_DRV_DS1305 is not set ++# CONFIG_RTC_DRV_DS1390 is not set ++# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++# CONFIG_RTC_DRV_DS3234 is not set ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_CMOS is not set ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_STK17TA8 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_M48T35 is not set ++# CONFIG_RTC_DRV_M48T59 is not set ++# CONFIG_RTC_DRV_BQ4802 is not set ++# CONFIG_RTC_DRV_V3020 is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++CONFIG_RTC_DRV_ASPEED=y ++# CONFIG_DMADEVICES is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_UIO is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++# CONFIG_EXT2_FS_XIP is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_EXT4_FS is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++# CONFIG_XFS_FS is not set ++# CONFIG_OCFS2_FS is not set ++CONFIG_DNOTIFY=y ++CONFIG_INOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_QUOTA is not set ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_FS is not set ++# CONFIG_FUSE_FS is not set ++CONFIG_GENERIC_ACL=y ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_NTFS_FS=y ++# CONFIG_NTFS_DEBUG is not set ++CONFIG_NTFS_RW=y ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_CONFIGFS_FS=m ++ ++# ++# Miscellaneous filesystems ++# ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_CRAMFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++# CONFIG_NFS_V3 is not set ++# CONFIG_NFS_V4 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_SUNRPC_REGISTER_V4 is not set ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=y ++CONFIG_NLS_CODEPAGE_932=y ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=y ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_KERNEL is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_RCU_CPU_STALL_DETECTOR is not set ++# CONFIG_LATENCYTOP is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++CONFIG_HAVE_FUNCTION_TRACER=y ++ ++# ++# Tracers ++# ++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_DEBUG_USER is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++# CONFIG_SECURITY_FILE_CAPABILITIES is not set ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++# CONFIG_CRYPTO_FIPS is not set ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_AEAD=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_SEQIV is not set ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=y ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++CONFIG_CRYPTO_HMAC=y ++# CONFIG_CRYPTO_XCBC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++CONFIG_CRYPTO_SHA1=y ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=m ++# CONFIG_CRYPTO_LZO is not set ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_HW is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++# CONFIG_CRC_CCITT is not set ++# CONFIG_CRC16 is not set ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=m ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_PLIST=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/wedge_defconfig b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/wedge_defconfig +index 23a9fe3..41fe288 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/wedge_defconfig ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/wedge_defconfig +@@ -174,6 +174,7 @@ CONFIG_IRMP=y + # CONFIG_ARCH_AST2200 is not set + # CONFIG_ARCH_AST2300 is not set + CONFIG_ARCH_AST2400=y ++CONFIG_WEDGE=y + # CONFIG_ARCH_AST2500 is not set + + # +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/yosemite_defconfig b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/yosemite_defconfig +new file mode 100644 +index 0000000..d32f18e +--- /dev/null ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/configs/yosemite_defconfig +@@ -0,0 +1,1480 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.28.9 ++# Tue Feb 3 16:41:40 2015 ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y ++CONFIG_GENERIC_TIME=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_MMU=y ++# CONFIG_NO_IOPORT is not set ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y ++CONFIG_VECTORS_BASE=0xffff0000 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_BZIP2 is not set ++# CONFIG_KERNEL_LZMA is not set ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++# CONFIG_CGROUPS is not set ++# CONFIG_GROUP_SCHED is not set ++CONFIG_SYSFS_DEPRECATED=y ++CONFIG_SYSFS_DEPRECATED_V2=y ++# CONFIG_RELAY is not set ++CONFIG_NAMESPACES=y ++# CONFIG_UTS_NS is not set ++# CONFIG_IPC_NS is not set ++# CONFIG_USER_NS is not set ++# CONFIG_PID_NS is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++# CONFIG_EMBEDDED is not set ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_KALLSYMS_EXTRA_PASS=y ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++# CONFIG_MARKERS is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=y ++CONFIG_RT_MUTEXES=y ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++CONFIG_BLOCK=y ++# CONFIG_LBD is not set ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_AS is not set ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++CONFIG_CLASSIC_RCU=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_ARCH_ASPEED=y ++# CONFIG_ARCH_AAEC2000 is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_NS9XXX is not set ++# CONFIG_ARCH_LOKI is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_MSM is not set ++CONFIG_IRMP=y ++# CONFIG_PCEXT is not set ++# CONFIG_REMOTEFX is not set ++# CONFIG_ARCH_AST1100 is not set ++# CONFIG_ARCH_AST2100 is not set ++# CONFIG_ARCH_AST2200 is not set ++# CONFIG_ARCH_AST2300 is not set ++CONFIG_ARCH_AST2400=y ++CONFIG_YOSEMITE=y ++# CONFIG_ARCH_AST2500 is not set ++ ++# ++# FLASH Chip Select ++# ++# CONFIG_AST_CS0_NOR is not set ++# CONFIG_AST_CS0_NAND is not set ++CONFIG_AST_CS0_SPI=y ++# CONFIG_AST_CS0_NONE is not set ++# CONFIG_AST_CS1_NOR is not set ++# CONFIG_AST_CS1_NAND is not set ++# CONFIG_AST_CS1_SPI is not set ++CONFIG_AST_CS1_NONE=y ++# CONFIG_AST_CS2_NOR is not set ++# CONFIG_AST_CS2_NAND is not set ++# CONFIG_AST_CS2_SPI is not set ++CONFIG_AST_CS2_NONE=y ++# CONFIG_AST_CS3_NOR is not set ++# CONFIG_AST_CS3_NAND is not set ++# CONFIG_AST_CS3_SPI is not set ++CONFIG_AST_CS3_NONE=y ++# CONFIG_AST_CS4_NOR is not set ++# CONFIG_AST_CS4_NAND is not set ++# CONFIG_AST_CS4_SPI is not set ++CONFIG_AST_CS4_NONE=y ++# CONFIG_ARCH_AST1070 is not set ++# CONFIG_AST_SCU_LOCK is not set ++ ++# ++# Boot options ++# ++ ++# ++# Power management ++# ++CONFIG_PLAT_ASPEED=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_NOIFAR=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++# CONFIG_OUTER_CACHE is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++CONFIG_ARCH_FLATMEM_HAS_HOLES=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4096 ++# CONFIG_RESOURCES_64BIT is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++CONFIG_UNEVICTABLE_LRU=y ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0 ++CONFIG_ZBOOT_ROM_BSS=0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++ ++# ++# CPU Power Management ++# ++# CONFIG_CPU_IDLE is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++CONFIG_FPE_NWFPE_XP=y ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_HAVE_AOUT=y ++CONFIG_BINFMT_AOUT=y ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_SLEEP=y ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_APM_EMULATION is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++# CONFIG_PACKET_MMAP is not set ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE is not set ++# CONFIG_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++# CONFIG_INET_LRO is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++# CONFIG_INET6_AH is not set ++# CONFIG_INET6_ESP is not set ++# CONFIG_INET6_IPCOMP is not set ++# CONFIG_IPV6_MIP6 is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETFILTER is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_NET_DSA is not set ++CONFIG_VLAN_8021Q=m ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++CONFIG_WAN_ROUTER=y ++# CONFIG_NET_SCHED is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++# CONFIG_PHONET is not set ++# CONFIG_WIRELESS is not set ++# CONFIG_RFKILL is not set ++# CONFIG_NET_9P is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_SYS_HYPERVISOR is not set ++CONFIG_CONNECTOR=y ++CONFIG_PROC_EVENTS=y ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++CONFIG_MTD_CONCAT=y ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_MTD_OOPS is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++# CONFIG_MTD_CFI is not set ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y ++# CONFIG_MTD_DATAFLASH_OTP is not set ++CONFIG_MTD_M25P80=y ++CONFIG_M25PXX_USE_FAST_READ=y ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# CONFIG_MTD_NAND is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# UBI - Unsorted block images ++# ++# CONFIG_MTD_UBI is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++CONFIG_BLK_DEV_NBD=y ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=16384 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_RD_BZIP2 is not set ++CONFIG_RD_LZMA=y ++CONFIG_RD_GZIP=y ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_C2PORT is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_TGT=y ++# CONFIG_SCSI_NETLINK is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++CONFIG_CHR_DEV_SG=y ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++CONFIG_SCSI_SCAN_ASYNC=y ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++CONFIG_SCSI_ISCSI_ATTRS=m ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++CONFIG_BONDING=m ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++CONFIG_TUN=m ++# CONFIG_VETH is not set ++# CONFIG_NET_ETHERNET is not set ++CONFIG_NETDEV_1000=y ++CONFIG_ASPEEDMAC=y ++# CONFIG_NETDEV_10000 is not set ++ ++# ++# Wireless LAN ++# ++# CONFIG_WLAN_PRE80211 is not set ++# CONFIG_WLAN_80211 is not set ++# CONFIG_IWLWIFI_LEDS is not set ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_WAN is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_POLLDEV is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_GPIO is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_LIFEBOOK=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_SERIAL=y ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_DEVKMEM=y ++CONFIG_SERIAL_NONSTANDARD=y ++# CONFIG_N_HDLC is not set ++# CONFIG_RISCOM8 is not set ++# CONFIG_SPECIALIX is not set ++# CONFIG_RIO is not set ++# CONFIG_STALDRV is not set ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=5 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=5 ++# CONFIG_SERIAL_AST_DMA_UART is not set ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++# CONFIG_SERIAL_AST is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_AST_MISC=y ++# CONFIG_AST_VIDEO is not set ++# CONFIG_ADC_CAT9883 is not set ++# CONFIG_AST_SPI_BIOS is not set ++CONFIG_AST_PECI=y ++# CONFIG_AST_KCS is not set ++# CONFIG_AST_GPIO is not set ++# CONFIG_HW_RANDOM is not set ++CONFIG_NVRAM=y ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_OCORES is not set ++CONFIG_I2C_AST=y ++CONFIG_AST_I2C_SLAVE_MODE=y ++# CONFIG_AST_I2C_SLAVE_EEPROM is not set ++CONFIG_AST_I2C_SLAVE_RDWR=y ++# CONFIG_I2C_SIMTEC is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++# CONFIG_I2C_TINY_USB is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_STUB is not set ++ ++# ++# Miscellaneous I2C Chip support ++# ++# CONFIG_DS1682 is not set ++CONFIG_AT24=m ++# CONFIG_SENSORS_EEPROM is not set ++CONFIG_SENSORS_PCF8574=m ++# CONFIG_PCF8575 is not set ++# CONFIG_SENSORS_PCA9539 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_SENSORS_MAX6875 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++# CONFIG_I2C_DEBUG_CHIP is not set ++CONFIG_SPI=y ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++CONFIG_SPI_AST=y ++CONFIG_SPI_FMC=y ++CONFIG_SPI_BITBANG=y ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_AT25=m ++# CONFIG_SPI_SPIDEV is not set ++# CONFIG_SPI_TLE62X0 is not set ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO expanders: ++# ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_GPIO_PCF857X is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++CONFIG_HWMON=y ++# CONFIG_HWMON_VID is not set ++# CONFIG_SENSORS_AD7414 is not set ++# CONFIG_SENSORS_AD7418 is not set ++# CONFIG_SENSORS_ADCXX is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1029 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ADT7462 is not set ++# CONFIG_SENSORS_ADT7470 is not set ++# CONFIG_SENSORS_ADT7473 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_F71882FG is not set ++# CONFIG_SENSORS_F75375S is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM70 is not set ++CONFIG_SENSORS_LM75=m ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_LM93 is not set ++CONFIG_SENSORS_MAX127=m ++# CONFIG_SENSORS_MAX1111 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_MAX6650 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++# CONFIG_SENSORS_DME1737 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++CONFIG_SENSORS_ADS7828=m ++# CONFIG_SENSORS_THMC50 is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83L786NG is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++CONFIG_SENSORS_AST_ADC=y ++CONFIG_SENSORS_AST_PWM_FAN=y ++# CONFIG_SENSORS_FB_PANTHER_PLUS is not set ++CONFIG_PMBUS=m ++CONFIG_SENSORS_PMBUS=m ++CONFIG_SENSORS_ADM1275=m ++# CONFIG_SENSORS_LM25066 is not set ++# CONFIG_SENSORS_LTC2978 is not set ++# CONFIG_SENSORS_MAX16064 is not set ++# CONFIG_SENSORS_MAX34440 is not set ++# CONFIG_SENSORS_MAX8688 is not set ++CONFIG_SENSORS_PFE1100=m ++CONFIG_SENSORS_PFE3000=m ++# CONFIG_SENSORS_UCD9000 is not set ++# CONFIG_SENSORS_UCD9200 is not set ++# CONFIG_SENSORS_ZL6100 is not set ++# CONFIG_HWMON_DEBUG_CHIP is not set ++CONFIG_THERMAL=y ++CONFIG_THERMAL_HWMON=y ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_AST_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++CONFIG_SSB_POSSIBLE=y ++ ++# ++# Sonics Silicon Backplane ++# ++# CONFIG_SSB is not set ++ ++# ++# Multifunction device drivers ++# ++# CONFIG_MFD_CORE is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_MFD_ASIC3 is not set ++# CONFIG_HTC_EGPIO is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_TC6393XB is not set ++# CONFIG_PMIC_DA903X is not set ++# CONFIG_MFD_WM8400 is not set ++# CONFIG_MFD_WM8350_I2C is not set ++ ++# ++# Multimedia devices ++# ++ ++# ++# Multimedia core support ++# ++# CONFIG_VIDEO_DEV is not set ++# CONFIG_DVB_CORE is not set ++# CONFIG_VIDEO_MEDIA is not set ++ ++# ++# Multimedia drivers ++# ++# CONFIG_DAB is not set ++ ++# ++# Graphics support ++# ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_SOUND is not set ++# CONFIG_HID_SUPPORT is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_ARCH_HAS_HCD=y ++# CONFIG_USB_ARCH_HAS_OHCI is not set ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB=m ++# CONFIG_USB_DEBUG is not set ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_SUSPEND is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_EHCI_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_HWA_HCD is not set ++ ++# ++# AST USB Drivers ++# ++CONFIG_AST_USB_UHCI_HCD=y ++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set ++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set ++CONFIG_AST_USB_UHCI_MULTIPORT_4=y ++# CONFIG_USB_EHCI_SPLIT_ISO is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_TMC is not set ++ ++# ++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; ++# ++ ++# ++# see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=m ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_BERRY_CHARGE is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGET is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_VST is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_SELECTED=y ++# CONFIG_USB_GADGET_AT91 is not set ++# CONFIG_USB_GADGET_ATMEL_USBA is not set ++# CONFIG_USB_GADGET_FSL_USB2 is not set ++# CONFIG_USB_GADGET_LH7A40X is not set ++# CONFIG_USB_GADGET_OMAP is not set ++# CONFIG_USB_GADGET_PXA25X is not set ++# CONFIG_USB_GADGET_PXA27X is not set ++# CONFIG_USB_GADGET_S3C2410 is not set ++# CONFIG_USB_GADGET_M66592 is not set ++# CONFIG_USB_GADGET_AMD5536UDC is not set ++# CONFIG_USB_GADGET_FSL_QE is not set ++# CONFIG_USB_GADGET_NET2280 is not set ++# CONFIG_USB_GADGET_GOKU is not set ++CONFIG_USB_GADGET_ASPEED_AST=y ++CONFIG_USB_ASPEED_AST=y ++# CONFIG_USB_GADGET_DUMMY_HCD is not set ++CONFIG_USB_GADGET_DUALSPEED=y ++CONFIG_USB_ZERO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_FILE_STORAGE=m ++# CONFIG_USB_FILE_STORAGE_TEST is not set ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_MIDI_GADGET is not set ++# CONFIG_USB_G_PRINTER is not set ++CONFIG_USB_CDC_COMPOSITE=m ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_NEW_LEDS is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++# CONFIG_RTC_DEBUG is not set ++ ++# ++# RTC interfaces ++# ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_DEV=y ++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set ++# CONFIG_RTC_DRV_TEST is not set ++ ++# ++# I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++# CONFIG_RTC_DRV_RX8581 is not set ++ ++# ++# SPI RTC drivers ++# ++# CONFIG_RTC_DRV_M41T94 is not set ++# CONFIG_RTC_DRV_DS1305 is not set ++# CONFIG_RTC_DRV_DS1390 is not set ++# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++# CONFIG_RTC_DRV_DS3234 is not set ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_CMOS is not set ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_STK17TA8 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_M48T35 is not set ++# CONFIG_RTC_DRV_M48T59 is not set ++# CONFIG_RTC_DRV_BQ4802 is not set ++# CONFIG_RTC_DRV_V3020 is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++CONFIG_RTC_DRV_ASPEED=y ++# CONFIG_DMADEVICES is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_UIO is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++# CONFIG_EXT2_FS_XIP is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_EXT4_FS is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++# CONFIG_XFS_FS is not set ++# CONFIG_OCFS2_FS is not set ++CONFIG_DNOTIFY=y ++CONFIG_INOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_QUOTA is not set ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_FS is not set ++# CONFIG_FUSE_FS is not set ++CONFIG_GENERIC_ACL=y ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_NTFS_FS=y ++# CONFIG_NTFS_DEBUG is not set ++CONFIG_NTFS_RW=y ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_CONFIGFS_FS=m ++ ++# ++# Miscellaneous filesystems ++# ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set ++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_CRAMFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++# CONFIG_NFS_V3 is not set ++# CONFIG_NFS_V4 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_SUNRPC_REGISTER_V4 is not set ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=y ++CONFIG_NLS_CODEPAGE_932=y ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=y ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_KERNEL is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_RCU_CPU_STALL_DETECTOR is not set ++# CONFIG_LATENCYTOP is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++CONFIG_HAVE_FUNCTION_TRACER=y ++ ++# ++# Tracers ++# ++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_DEBUG_USER is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++# CONFIG_SECURITY_FILE_CAPABILITIES is not set ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++# CONFIG_CRYPTO_FIPS is not set ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_AEAD=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_SEQIV is not set ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=y ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++CONFIG_CRYPTO_HMAC=y ++# CONFIG_CRYPTO_XCBC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++CONFIG_CRYPTO_SHA1=y ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=m ++# CONFIG_CRYPTO_LZO is not set ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_HW is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++# CONFIG_CRC_CCITT is not set ++# CONFIG_CRC16 is not set ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=m ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_PLIST=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++ ++ ++# GUC USB Drivers ++# ++CONFIG_GUC_USB_UHCI_HCD=m ++# CONFIG_GUC_USB_UHCI_MULTIPORT_1 is not set ++# CONFIG_GUC_USB_UHCI_MULTIPORT_2 is not set ++CONFIG_GUC_USB_UHCI_MULTIPORT_4=y ++# CONFIG_USB_GADGET_MUSB_HDRC is not set +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/include/asm/ioctls.h b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/include/asm/ioctls.h +index a91d8a1..fd50ffe 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/include/asm/ioctls.h ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/include/asm/ioctls.h +@@ -65,6 +65,7 @@ + #define TIOCSERGETLSR 0x5459 /* Get line status register */ + #define TIOCSERGETMULTI 0x545A /* Get multiport config */ + #define TIOCSERSETMULTI 0x545B /* Set multiport config */ ++#define TIOCSERWAITTEMT 0x5499 /* Wait for empty */ + + #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ + #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/Kconfig b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/Kconfig +index a948ab8..6d548f8 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/Kconfig ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/Kconfig +@@ -203,6 +203,18 @@ endchoice + config AST_SCU_LOCK + bool "AST SCU Protection Key" + ++config WEDGE ++ bool "Facebook Wedge/6-Pack" ++ ++config WEDGE100 ++ bool "Facebook Wedge100" ++ ++config YOSEMITE ++ bool "Facebook Yosemite" ++ ++config FBPLATFORM1 ++ bool "Facebook Platform1" ++ + # Support PCIE + config PCIE + bool "ASPEED PCIE support" +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/gpio.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/gpio.c +index 3a633e9..e56ca35 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/gpio.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/gpio.c +@@ -232,7 +232,7 @@ static struct ast_gpio_bank ast_gpio_gp[] = { + AST_GPIO_BANK("GPIOR", IO_ADDRESS(AST_GPIO_BASE), 1, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110), + AST_GPIO_BANK("GPIOS", IO_ADDRESS(AST_GPIO_BASE), 2, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110), + #if defined(CONFIG_ARCH_AST2400) +- AST_GPIO_BANK("GPIOT", IO_ADDRESS(AST_GPIO_BASE), 4, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110), ++ AST_GPIO_BANK("GPIOT", IO_ADDRESS(AST_GPIO_BASE), 3, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110), + AST_GPIO_BANK("GPIOU", IO_ADDRESS(AST_GPIO_BASE), 0, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140), + AST_GPIO_BANK("GPIOV", IO_ADDRESS(AST_GPIO_BASE), 1, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140), + AST_GPIO_BANK("GPIOW", IO_ADDRESS(AST_GPIO_BASE), 2, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140), +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/debug-macro.S b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/debug-macro.S +index ff3195a..33fc879 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/debug-macro.S ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/debug-macro.S +@@ -13,8 +13,8 @@ + .macro addruart, rx, tmp + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? +- ldreq \rx, =AST_UART3_BASE +- ldrne \rx, =IO_ADDRESS(AST_UART3_BASE) ++ ldreq \rx, =AST_UART_BASE ++ ldrne \rx, =IO_ADDRESS(AST_UART_BASE) + .endm + + #define UART_SHIFT 2 +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/platform.h b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/platform.h +index 8951ffc..4d6c50c 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/platform.h ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/platform.h +@@ -62,5 +62,20 @@ + * Watchdog + */ + #define AST_WDT_VA_BASE (IO_ADDRESS(AST_WDT_BASE)) +- ++ ++/* ++ * Console UART ++ */ ++#ifdef CONFIG_WEDGE ++#define AST_UART_BASE AST_UART3_BASE ++#elif defined(CONFIG_WEDGE100) ++#define AST_UART_BASE AST_UART3_BASE ++#elif defined(CONFIG_YOSEMITE) ++#define AST_UART_BASE AST_UART0_BASE ++#elif defined(CONFIG_FBPLATFORM1) ++#define AST_UART_BASE AST_UART0_BASE ++#else ++#define AST_UART_BASE AST_UART0_BASE ++#endif ++ + #endif +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/uncompress.h b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/uncompress.h +index 80e560d..3be04b0 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/uncompress.h ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/uncompress.h +@@ -12,8 +12,8 @@ + #include <mach/platform.h> + #include <mach/aspeed_serial.h> + +-#define UART_PUT_CHAR (*(volatile unsigned char *)(AST_UART3_BASE + UART_THR)) +-#define UART_GET_LSR (*(volatile unsigned char *)(AST_UART3_BASE + UART_LSR)) ++#define UART_PUT_CHAR (*(volatile unsigned char *)(AST_UART_BASE + UART_THR)) ++#define UART_GET_LSR (*(volatile unsigned char *)(AST_UART_BASE + UART_LSR)) + + static void putc(int c) + { +@@ -21,7 +21,7 @@ static void putc(int c) + /* wait for space in the UART's transmitter */ + while (!(UART_GET_LSR & UART_LSR_THRE)) + barrier(); +- ++ + /* send the character out. */ + UART_PUT_CHAR = c; + } +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/vmalloc.h b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/vmalloc.h +index 51912ae..bc1b471 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/vmalloc.h ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/mach-aspeed/include/mach/vmalloc.h +@@ -25,5 +25,5 @@ + #define VMALLOC_VMADDR(x) ((unsigned long)(x)) + #define VMALLOC_END (PAGE_OFFSET + 0x20000000) + #else +-#define VMALLOC_END 0xf8000000UL +-#endif +\ No newline at end of file ++#define VMALLOC_END 0xf8000000UL ++#endif +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/ast-scu.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/ast-scu.c +index 76722f4..101b141 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/ast-scu.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/ast-scu.c +@@ -1,20 +1,20 @@ + /******************************************************************************** +-* File Name : arch/arm/plat-aspeed/ast-scu.c ++* File Name : arch/arm/plat-aspeed/ast-scu.c + * Author : Ryan Chen +-* Description : AST SCU +-* ++* Description : AST SCU ++* + * Copyright (C) 2012-2020 ASPEED Technology 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. +-* You should have received a copy of the GNU General Public License +-* along with this program; if not, write to the Free Software +-* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- +-CLK24M ++* 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. ++* You should have received a copy of the GNU General Public License ++* along with this program; if not, write to the Free Software ++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++CLK24M + | + |--> H-PLL -->HCLK + | +@@ -27,9 +27,9 @@ CLK24M + |--> USB2PHY -->UTMICLK + + +-* History : ++* History : + * 1. 2012/08/15 Ryan Chen Create +-* ++* + ********************************************************************************/ + #include <linux/kernel.h> + #include <linux/module.h> +@@ -56,34 +56,34 @@ CLK24M + + static u32 ast_scu_base = IO_ADDRESS(AST_SCU_BASE); + +-static inline u32 ++static inline u32 + ast_scu_read(u32 reg) + { + u32 val; +- ++ + val = readl(ast_scu_base + reg); +- ++ + SCUDBUG("ast_scu_read : reg = 0x%08x, val = 0x%08x\n", reg, val); +- ++ + return val; + } + + static inline void +-ast_scu_write(u32 val, u32 reg) ++ast_scu_write(u32 val, u32 reg) + { + SCUDBUG("ast_scu_write : reg = 0x%08x, val = 0x%08x\n", reg, val); + #ifdef CONFIG_AST_SCU_LOCK +- //unlock ++ //unlock + writel(SCU_PROTECT_UNLOCK, ast_scu_base); + writel(val, ast_scu_base + reg); + //lock +- writel(0xaa,ast_scu_base); ++ writel(0xaa,ast_scu_base); + #else + writel(val, ast_scu_base + reg); + #endif + } + +-//SoC mapping Table ++//SoC mapping Table + struct soc_id { + const char * name; + u32 rev_id; +@@ -180,9 +180,9 @@ ast_scu_init_video(u8 dynamic_en) + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_VIDEO_SLOW_MASK) | SCU_CLK_VIDEO_SLOW_EN | SCU_CLK_VIDEO_SLOW_SET(0), AST_SCU_CLK_SEL); + else + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_ECLK_SOURCE_MASK) | SCU_ECLK_SOURCE(2), AST_SCU_CLK_SEL); +- ++ + // Enable CLK +- ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~(SCU_ECLK_STOP_EN | SCU_VCLK_STOP_EN), AST_SCU_CLK_STOP); ++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~(SCU_ECLK_STOP_EN | SCU_VCLK_STOP_EN), AST_SCU_CLK_STOP); + mdelay(10); + ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_VIDEO, AST_SCU_RESET); + udelay(100); +@@ -201,32 +201,32 @@ ast_scu_init_eth(u8 num) + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_MAC_MASK) | SCU_CLK_MAC_DIV(4), AST_SCU_CLK_SEL); + + //Set MAC delay Timing +- ast_scu_write(0x2255, AST_SCU_MAC_CLK); ++ ast_scu_write(0x2255, AST_SCU_MAC_CLK); + + switch(num) { + case 0: +- ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC0, +- AST_SCU_RESET); ++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC0, ++ AST_SCU_RESET); + udelay(100); +- ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC0CLK_STOP_EN, +- AST_SCU_CLK_STOP); ++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC0CLK_STOP_EN, ++ AST_SCU_CLK_STOP); + udelay(1000); +- ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC0, +- AST_SCU_RESET); +- ++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC0, ++ AST_SCU_RESET); ++ + break; + case 1: +- ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC1, +- AST_SCU_RESET); ++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC1, ++ AST_SCU_RESET); + udelay(100); +- ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC1CLK_STOP_EN, +- AST_SCU_CLK_STOP); ++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC1CLK_STOP_EN, ++ AST_SCU_CLK_STOP); + udelay(1000); +- ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC1, +- AST_SCU_RESET); ++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC1, ++ AST_SCU_RESET); + break; +- +- } ++ ++ } + } + + +@@ -292,7 +292,7 @@ ast_scu_init_sdhci(void) + { + //SDHCI Host's Clock Enable and Reset + ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_SD, AST_SCU_RESET); +- ++ + ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_SDCLK_STOP_EN, AST_SCU_CLK_STOP); + mdelay(10); + +@@ -300,10 +300,10 @@ ast_scu_init_sdhci(void) + mdelay(10); + + // SDCLK = H-PLL / 4 +- ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_SD_MASK) | SCU_CLK_SD_DIV(1), ++ ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_SD_MASK) | SCU_CLK_SD_DIV(1), + AST_SCU_CLK_SEL); + mdelay(10); +- ++ + ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_SD, AST_SCU_RESET); + } + +@@ -358,13 +358,13 @@ EXPORT_SYMBOL(ast_scu_init_jtag); + extern void + ast_scu_init_lpc(void) + { +- //Note .. It have been enable in U-boot..... ++ //Note .. It have been enable in U-boot..... + // ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_LPC, AST_SCU_RESET); + + //enable LPC clock LHCLK = H-PLL/8 +- ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) | +- SCU_SET_LHCLK_DIV(3) | +- SCU_LHCLK_SOURCE_EN, ++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) | ++ SCU_SET_LHCLK_DIV(3) | ++ SCU_LHCLK_SOURCE_EN, + AST_SCU_CLK_STOP); + + } +@@ -377,7 +377,7 @@ ast_scu_get_lpc_plus_enable(void) + { + if(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & SCU_FUN_PIN_LPC_PLUS) + return 1; +- else ++ else + return 0; + } + +@@ -390,10 +390,10 @@ ast_scu_init_crt(void) + #if defined(CONFIG_AST_DAC) || defined(CONFIG_AST_DVO) + ast_scu_write((ast_scu_read(AST_SCU_MISC1_CTRL) & ~(SCU_MISC_D2_PLL_DIS | SCU_MISC_DAC_MASK)) + | SCU_MISC_DAC_SOURCE_CRT | SCU_MISC_DVO_SOURCE_CRT | SCU_MISC_2D_CRT_EN , AST_SCU_MISC1_CTRL); +-#elif defined(CONFIG_AST_DVO) ++#elif defined(CONFIG_AST_DVO) + ast_scu_write((ast_scu_read(AST_SCU_MISC1_CTRL) & ~(SCU_MISC_D2_PLL_DIS)) | + SCU_MISC_DVO_SOURCE_CRT| SCU_MISC_2D_CRT_EN, AST_SCU_MISC1_CTRL); +-#else //default(CONFIG_AST_DAC) ++#else //default(CONFIG_AST_DAC) + ast_scu_write((ast_scu_read(AST_SCU_MISC1_CTRL) & ~(SCU_MISC_D2_PLL_DIS | SCU_MISC_DAC_MASK)) + | SCU_MISC_DAC_SOURCE_CRT | SCU_MISC_2D_CRT_EN, AST_SCU_MISC1_CTRL); + #endif +@@ -401,7 +401,7 @@ ast_scu_init_crt(void) + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_VIDEO_DELAY_MASK) | + SCU_CLK_VIDEO_DELAY(5), AST_SCU_CLK_SEL); + +- /* Reset CRT */ ++ /* Reset CRT */ + ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_CRT, AST_SCU_RESET); + + //enable D2 CLK +@@ -409,7 +409,7 @@ ast_scu_init_crt(void) + + udelay(10); + ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_CRT, AST_SCU_RESET); +- ++ + } + + EXPORT_SYMBOL(ast_scu_init_crt); +@@ -448,7 +448,7 @@ ast_get_h_pll_clk(void) + + if(h_pll_set & SCU_H_PLL_OFF) + return 0; +- ++ + if(h_pll_set & SCU_H_PLL_PARAMETER) { + // Programming + clk = ast_get_clk_source(); +@@ -470,21 +470,21 @@ ast_get_h_pll_clk(void) + speed = SCU_HW_STRAP_GET_H_PLL_CLK(ast_scu_read(AST_SCU_HW_STRAP1)); + switch (speed) { + case 0: +- clk = 384000000; ++ clk = 384000000; + break; + case 1: +- clk = 360000000; ++ clk = 360000000; + break; + case 2: +- clk = 336000000; ++ clk = 336000000; + break; + case 3: +- clk = 408000000; ++ clk = 408000000; + break; + default: +- BUG(); ++ BUG(); + break; +- } ++ } + } + SCUDBUG("h_pll = %d\n",clk); + return clk; +@@ -500,7 +500,7 @@ ast_get_m_pll_clk(void) + + if(m_pll_set & SCU_M_PLL_OFF) + return 0; +- ++ + // Programming + clk = ast_get_clk_source(); + if(m_pll_set & SCU_M_PLL_BYPASS_EN) { +@@ -542,10 +542,10 @@ ast_get_ahbclk(void) + case 3: + div = 4; + break; +- ++ + } +- +- SCUDBUG("HPLL=%d, Div=%d, AHB CLK=%d\n", hpll, div, hpll/div); ++ ++ SCUDBUG("HPLL=%d, Div=%d, AHB CLK=%d\n", hpll, div, hpll/div); + return (hpll/div); + + } +@@ -559,8 +559,8 @@ ast_get_pclk(void) + hpll = ast_get_h_pll_clk(); + div = SCU_GET_PCLK_DIV(ast_scu_read(AST_SCU_CLK_SEL)); + div = (div+1) << 1; +- +- SCUDBUG("HPLL=%d, Div=%d, PCLK=%d\n", hpll, div, hpll/div); ++ ++ SCUDBUG("HPLL=%d, Div=%d, PCLK=%d\n", hpll, div, hpll/div); + return (hpll/div); + + } +@@ -572,7 +572,7 @@ ast_get_lhclk(void) + unsigned int div, hpll; + u32 clk_sel = ast_scu_read(AST_SCU_CLK_SEL); + //FPGA AST1070 is default 100/2 Mhz input +-// return 50000000; ++// return 50000000; + hpll = ast_get_h_pll_clk(); + if(SCU_LHCLK_SOURCE_EN & clk_sel) { + div = SCU_GET_LHCLK_DIV(clk_sel); +@@ -600,10 +600,10 @@ ast_get_lhclk(void) + break; + case 7: + div = 16; +- break; ++ break; + } +- +- SCUDBUG("HPLL=%d, Div=%d, LHCLK = %d\n", hpll, div, hpll/div); ++ ++ SCUDBUG("HPLL=%d, Div=%d, LHCLK = %d\n", hpll, div, hpll/div); + return (hpll/div); + } else { + SCUMSG("LPC CLK not enable \n"); +@@ -704,7 +704,7 @@ ast_get_sd_clock_src(void) + sd_div = SCU_CLK_SD_GET_DIV(ast_scu_read(AST_SCU_CLK_SEL)); + SCUDBUG("div %d, sdclk =%d \n",((sd_div + 1) * 2),clk/((sd_div + 1) * 2)); + clk /= ((sd_div + 1) * 2); +- ++ + #endif + return clk; + } +@@ -717,7 +717,7 @@ ast_scu_show_system_info (void) + u32 h_pll, div; + + h_pll = ast_get_h_pll_clk(); +- ++ + div = SCU_HW_STRAP_GET_CPU_AHB_RATIO(ast_scu_read(AST_SCU_HW_STRAP1)); + switch(div) { + case 0: +@@ -732,10 +732,10 @@ ast_scu_show_system_info (void) + case 3: + div = 4; + break; +- ++ + } + +- SCUMSG("CPU = %d MHz ,AHB = %d MHz (%d:1) \n", h_pll/1000000, h_pll/div/1000000,div); ++ SCUMSG("CPU = %d MHz ,AHB = %d MHz (%d:1) \n", h_pll/1000000, h_pll/div/1000000,div); + + return ; + } +@@ -750,54 +750,68 @@ ast_scu_multi_func_uart(u8 uart) + case 1: + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | + SCU_FUN_PIN_UART1_RXD | ++#ifdef CONFIG_YOSEMITE ++ SCU_FUN_PIN_UART1_TXD, ++#else + SCU_FUN_PIN_UART1_TXD | + SCU_FUN_PIN_UART1_NRTS | + SCU_FUN_PIN_UART1_NDTR | + SCU_FUN_PIN_UART1_NRI | + SCU_FUN_PIN_UART1_NDSR | + SCU_FUN_PIN_UART1_NDCD | +- SCU_FUN_PIN_UART1_NCTS, +- AST_SCU_FUN_PIN_CTRL2); +- break; ++ SCU_FUN_PIN_UART1_NCTS, ++#endif ++ AST_SCU_FUN_PIN_CTRL2); ++ break; + case 2: + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | + SCU_FUN_PIN_UART2_RXD | ++#ifdef CONFIG_YOSEMITE ++ SCU_FUN_PIN_UART2_TXD, ++#else + SCU_FUN_PIN_UART2_TXD | + SCU_FUN_PIN_UART2_NRTS | + SCU_FUN_PIN_UART2_NDTR | + SCU_FUN_PIN_UART2_NRI | + SCU_FUN_PIN_UART2_NDSR | + SCU_FUN_PIN_UART2_NDCD | +- SCU_FUN_PIN_UART2_NCTS, +- AST_SCU_FUN_PIN_CTRL2); +- break; ++ SCU_FUN_PIN_UART2_NCTS, ++#endif ++ AST_SCU_FUN_PIN_CTRL2); ++ break; + case 3: + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | + SCU_FUN_PIN_UART3_RXD | ++#ifdef CONFIG_YOSEMITE ++ SCU_FUN_PIN_UART3_TXD, ++#else + SCU_FUN_PIN_UART3_TXD | + SCU_FUN_PIN_UART3_NRTS | + SCU_FUN_PIN_UART3_NDTR | + SCU_FUN_PIN_UART3_NRI | + SCU_FUN_PIN_UART3_NDSR | + SCU_FUN_PIN_UART3_NDCD | +- SCU_FUN_PIN_UART3_NCTS, +- AST_SCU_FUN_PIN_CTRL1); ++ SCU_FUN_PIN_UART3_NCTS, ++#endif ++ AST_SCU_FUN_PIN_CTRL1); + break; + case 4: + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | + SCU_FUN_PIN_UART4_RXD | ++#ifdef CONFIG_YOSEMITE ++ SCU_FUN_PIN_UART4_TXD, ++#else + SCU_FUN_PIN_UART4_TXD | + SCU_FUN_PIN_UART4_NRTS | + SCU_FUN_PIN_UART4_NDTR | + SCU_FUN_PIN_UART4_NRI | + SCU_FUN_PIN_UART4_NDSR | + SCU_FUN_PIN_UART4_NDCD | +- SCU_FUN_PIN_UART4_NCTS, +- AST_SCU_FUN_PIN_CTRL1); ++ SCU_FUN_PIN_UART4_NCTS, ++#endif ++ AST_SCU_FUN_PIN_CTRL1); + break; + } +- +- + } + + extern void +@@ -806,13 +820,13 @@ ast_scu_multi_func_video() + #if defined(CONFIG_ARCH_2100) || defined(CONFIG_ARCH_2200) + ast_scu_write(ast_scu_read(AST_SCU_MULTI_FUNC_2) | + MULTI_FUNC_VIDEO_RGB18 | +- MULTI_FUNC_VIDEO_SINGLE_EDGE, +- AST_SCU_MULTI_FUNC_2); ++ MULTI_FUNC_VIDEO_SINGLE_EDGE, ++ AST_SCU_MULTI_FUNC_2); + #elif defined(CONFIG_ARCH_1100) || defined(CONFIG_ARCH_2050) + ast_scu_write(ast_scu_read(AST_SCU_MULTI_FUNC_2) | + MULTI_FUNC_VIDEO_RGB18 | +- MULTI_FUNC_VIDEO_SINGLE_EDGE, +- AST_SCU_MULTI_FUNC_2); ++ MULTI_FUNC_VIDEO_SINGLE_EDGE, ++ AST_SCU_MULTI_FUNC_2); + #else + + #endif +@@ -823,40 +837,40 @@ ast_scu_multi_func_eth(u8 num) + { + switch(num) { + case 0: +- if(ast_scu_read(AST_SCU_HW_STRAP1) && SCU_HW_STRAP_MAC0_RGMII) { ++ if(ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC0_RGMII) { + SCUMSG("MAC0 : RGMII \n"); +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | +- SCU_FUN_PIN_MAC0_PHY_LINK, +- AST_SCU_FUN_PIN_CTRL1); ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | ++ SCU_FUN_PIN_MAC0_PHY_LINK, ++ AST_SCU_FUN_PIN_CTRL1); + } else { +- SCUMSG("MAC0 : RMII/NCSI \n"); ++ SCUMSG("MAC0 : RMII/NCSI \n"); + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) & +- ~SCU_FUN_PIN_MAC0_PHY_LINK, +- AST_SCU_FUN_PIN_CTRL1); ++ ~SCU_FUN_PIN_MAC0_PHY_LINK, ++ AST_SCU_FUN_PIN_CTRL1); + } + +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | + SCU_FUN_PIN_MAC0_MDIO | +- SCU_FUN_PIN_MAC0_MDC, +- AST_SCU_FUN_PIN_CTRL3); +- ++ SCU_FUN_PIN_MAC0_MDC, ++ AST_SCU_FUN_PIN_CTRL3); ++ + break; + case 1: +- if(ast_scu_read(AST_SCU_HW_STRAP1) && SCU_HW_STRAP_MAC1_RGMII) { ++ if(ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC1_RGMII) { + SCUMSG("MAC1 : RGMII \n"); +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | +- SCU_FUN_PIN_MAC1_PHY_LINK, +- AST_SCU_FUN_PIN_CTRL1); ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | ++ SCU_FUN_PIN_MAC1_PHY_LINK, ++ AST_SCU_FUN_PIN_CTRL1); + } else { + SCUMSG("MAC1 : RMII/NCSI \n"); +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) & +- ~SCU_FUN_PIN_MAC1_PHY_LINK, +- AST_SCU_FUN_PIN_CTRL1); ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) & ++ ~SCU_FUN_PIN_MAC1_PHY_LINK, ++ AST_SCU_FUN_PIN_CTRL1); + } +- +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | ++ ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | + SCU_FUC_PIN_MAC1_MDIO, +- AST_SCU_FUN_PIN_CTRL5); ++ AST_SCU_FUN_PIN_CTRL5); + + break; + } +@@ -866,18 +880,18 @@ extern void + ast_scu_multi_func_nand(void) + { + //enable NAND flash multipin FLBUSY and FLWP +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | +- SCU_FUN_PIN_NAND_FLBUSY | SCU_FUN_PIN_NAND_FLWP, +- AST_SCU_FUN_PIN_CTRL2); ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | ++ SCU_FUN_PIN_NAND_FLBUSY | SCU_FUN_PIN_NAND_FLWP, ++ AST_SCU_FUN_PIN_CTRL2); + + } + + extern void + ast_scu_multi_func_nor(void) + { +- //Address ++ //Address + //ROMA2~17 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL8) | ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL8) | + SCU_FUN_PIN_ROMA2 | SCU_FUN_PIN_ROMA3 | + SCU_FUN_PIN_ROMA4 | SCU_FUN_PIN_ROMA5 | + SCU_FUN_PIN_ROMA6 | SCU_FUN_PIN_ROMA7 | +@@ -885,39 +899,39 @@ ast_scu_multi_func_nor(void) + SCU_FUN_PIN_ROMA10 | SCU_FUN_PIN_ROMA11 | + SCU_FUN_PIN_ROMA12 | SCU_FUN_PIN_ROMA13 | + SCU_FUN_PIN_ROMA14 | SCU_FUN_PIN_ROMA15 | +- SCU_FUN_PIN_ROMA16 | SCU_FUN_PIN_ROMA17, ++ SCU_FUN_PIN_ROMA16 | SCU_FUN_PIN_ROMA17, + AST_SCU_FUN_PIN_CTRL8); + + //ROMA18~21 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL9) | ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL9) | + SCU_FUN_PIN_ROMA18 | SCU_FUN_PIN_ROMA19 | +- SCU_FUN_PIN_ROMA20 | SCU_FUN_PIN_ROMA21, +- AST_SCU_FUN_PIN_CTRL9); +- ++ SCU_FUN_PIN_ROMA20 | SCU_FUN_PIN_ROMA21, ++ AST_SCU_FUN_PIN_CTRL9); ++ + //ROMA22,23 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | SCU_FUN_PIN_ROMA22 | SCU_FUN_PIN_ROMA23, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | SCU_FUN_PIN_ROMA22 | SCU_FUN_PIN_ROMA23, + AST_SCU_FUN_PIN_CTRL4); +- ++ + //ROMA24,25 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | SCU_FUN_PIN_ROMA24 | SCU_FUN_PIN_ROMA25, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | SCU_FUN_PIN_ROMA24 | SCU_FUN_PIN_ROMA25, + AST_SCU_FUN_PIN_CTRL3); + + //SCU94 [1] = 0 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL6) & SCU_VIDEO_OUT_MASK, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL6) & SCU_VIDEO_OUT_MASK, + AST_SCU_FUN_PIN_CTRL6); + +- ++ + //data + //ROMD 4~7 //ROMWE#, OE# +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | + SCU_FUN_PIN_ROMOE | SCU_FUN_PIN_ROMWE | + SCU_FUN_PIN_ROMD4 | SCU_FUN_PIN_ROMD5 | + SCU_FUN_PIN_ROMD6 | SCU_FUN_PIN_ROMD7, + AST_SCU_FUN_PIN_CTRL4); +- ++ + //ROMD 8~15 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | +- SCU_FUC_PIN_ROM_16BIT, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | ++ SCU_FUC_PIN_ROM_16BIT, + AST_SCU_FUN_PIN_CTRL5); + + } +@@ -925,44 +939,44 @@ ast_scu_multi_func_nor(void) + extern void + ast_scu_multi_func_romcs(u8 num) + { +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | +- SCU_FUN_PIN_ROMCS(num), ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | ++ SCU_FUN_PIN_ROMCS(num), + AST_SCU_FUN_PIN_CTRL3); + } + + extern void + ast_scu_multi_func_i2c(void) + { +- //TODO check ... //In AST2400 Due to share pin with SD , please not enable I2C 10 ~14 ++ //TODO check ... //In AST2400 Due to share pin with SD , please not enable I2C 10 ~14 + // AST 2400 have 14 , AST 2300 9 ... + #ifdef CONFIG_MMC_AST +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | +- SCU_FUC_PIN_I2C3 | +- SCU_FUC_PIN_I2C4 | +- SCU_FUC_PIN_I2C5 | +- SCU_FUC_PIN_I2C6 | +- SCU_FUC_PIN_I2C7 | +- SCU_FUC_PIN_I2C8 | +- SCU_FUC_PIN_I2C9, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | ++ SCU_FUC_PIN_I2C3 | ++ SCU_FUC_PIN_I2C4 | ++ SCU_FUC_PIN_I2C5 | ++ SCU_FUC_PIN_I2C6 | ++ SCU_FUC_PIN_I2C7 | ++ SCU_FUC_PIN_I2C8 | ++ SCU_FUC_PIN_I2C9, + AST_SCU_FUN_PIN_CTRL5); + #else +- ast_scu_write((ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | +- SCU_FUC_PIN_I2C3 | +- SCU_FUC_PIN_I2C4 | +- SCU_FUC_PIN_I2C5 | +- SCU_FUC_PIN_I2C6 | +- SCU_FUC_PIN_I2C7 | +- SCU_FUC_PIN_I2C8 | +- SCU_FUC_PIN_I2C9 | +- SCU_FUC_PIN_I2C10 | +- SCU_FUC_PIN_I2C11 | +- SCU_FUC_PIN_I2C12 | +- SCU_FUC_PIN_I2C13 | ++ ast_scu_write((ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | ++ SCU_FUC_PIN_I2C3 | ++ SCU_FUC_PIN_I2C4 | ++ SCU_FUC_PIN_I2C5 | ++ SCU_FUC_PIN_I2C6 | ++ SCU_FUC_PIN_I2C7 | ++ SCU_FUC_PIN_I2C8 | ++ SCU_FUC_PIN_I2C9 | ++ SCU_FUC_PIN_I2C10 | ++ SCU_FUC_PIN_I2C11 | ++ SCU_FUC_PIN_I2C12 | ++ SCU_FUC_PIN_I2C13 | + SCU_FUC_PIN_I2C14) & +- ~(SCU_FUC_PIN_SD1 | SCU_FUC_PIN_SD2), ++ ~(SCU_FUC_PIN_SD1 | SCU_FUC_PIN_SD2), + AST_SCU_FUN_PIN_CTRL5); + #endif +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_i2c); + +@@ -972,7 +986,7 @@ ast_scu_multi_func_pwm_tacho(void) + //TODO check + u32 sts = ast_scu_read(AST_SCU_FUN_PIN_CTRL3) &~0xcfffff; + ast_scu_write(sts | 0xc000ff, AST_SCU_FUN_PIN_CTRL3); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_pwm_tacho); + +@@ -981,12 +995,12 @@ extern void + ast_scu_multi_func_usb20_host_hub(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB20_HOST, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB20_HOST, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB20_HOST, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB20_HOST, + AST_SCU_FUN_PIN_CTRL5); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_usb20_host_hub); + +@@ -995,12 +1009,12 @@ extern void + ast_scu_multi_func_usb11_host_port4(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT4, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT4, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT4, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT4, + AST_SCU_FUN_PIN_CTRL5); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_usb11_host_port4); + +@@ -1009,26 +1023,26 @@ extern void + ast_scu_multi_func_usb11_host_port2(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT2, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT2, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT2, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT2, + AST_SCU_FUN_PIN_CTRL5); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_usb11_host_port2); + +-//0 : 1: SD1 function ++//0 : 1: SD1 function + extern void + ast_scu_multi_func_sdhc_slot1(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD1, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD1, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD1, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD1, + AST_SCU_FUN_PIN_CTRL5); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_sdhc_slot1); + +@@ -1036,13 +1050,13 @@ extern void + ast_scu_multi_func_sdhc_slot2(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD2, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD2, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD2, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD2, + AST_SCU_FUN_PIN_CTRL5); + +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_sdhc_slot2); + +@@ -1053,11 +1067,11 @@ ast_scu_multi_func_crt(void) + + //Digital vodeo input function pins : 00 disable, 10 24bits mode 888, + ast_scu_write((ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & +- ~SCU_FUC_PIN_DIGI_V_OUT_MASK) | ++ ~SCU_FUC_PIN_DIGI_V_OUT_MASK) | + SCU_FUC_PIN_DIGI_V_OUT(VIDEO_24BITS),AST_SCU_FUN_PIN_CTRL5); + + //VPI input +-#if 0 ++#if 0 + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | + SCU_FUN_PIN_VPIB9 | SCU_FUN_PIN_VPIB8 | + SCU_FUN_PIN_VPIB7 | SCU_FUN_PIN_VPIB6 | +@@ -1070,11 +1084,11 @@ ast_scu_multi_func_crt(void) + + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | + SCU_FUN_PIN_VPIR9 | SCU_FUN_PIN_VPIR8 | +- SCU_FUN_PIN_VPIR7 | SCU_FUN_PIN_VPIR6 | ++ SCU_FUN_PIN_VPIR7 | SCU_FUN_PIN_VPIR6 | + SCU_FUN_PIN_VPIR5 | SCU_FUN_PIN_VPIR4 | + SCU_FUN_PIN_VPIR3 | SCU_FUN_PIN_VPIR2 | + SCU_FUN_PIN_VPIR1 | SCU_FUN_PIN_VPIR0 | +- SCU_FUN_PIN_VPIG9 | SCU_FUN_PIN_VPIG8 | ++ SCU_FUN_PIN_VPIG9 | SCU_FUN_PIN_VPIG8 | + SCU_FUN_PIN_VPIG7 | SCU_FUN_PIN_VPIG6 | + SCU_FUN_PIN_VPIG5 | SCU_FUN_PIN_VPIG4 | + SCU_FUN_PIN_VPIG3 | SCU_FUN_PIN_VPIG2 | +@@ -1097,9 +1111,9 @@ ast_scu_revision_id(void) + SCUMSG("UnKnow-SOC : %x \n",rev_id); + else + SCUMSG("SOC : %4s \n",soc_map_table[i].name); +- ++ + return rev_id; +-} ++} + + EXPORT_SYMBOL(ast_scu_revision_id); + +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-eth.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-eth.c +index 5d33e33..b115c5a 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-eth.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-eth.c +@@ -7,11 +7,11 @@ + * 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. +-* ++* + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -37,7 +37,7 @@ + #if defined(CONFIG_ASPEEDMAC) || defined(CONFIG_ASPEEDMAC_MODULE) + #ifdef AST_MAC0_BASE + static struct ftgmac100_eth_data ast_eth0_data = { +- .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x22}, ++ .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x22}, + .phy_id = 1, + }; + +@@ -69,7 +69,7 @@ static struct platform_device ast_eth0_device = { + #endif + #ifdef AST_MAC1_BASE + static struct ftgmac100_eth_data ast_eth1_data = { +- .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x23}, ++ .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x23}, + .phy_id = 1, + }; + +@@ -131,11 +131,16 @@ void __init ast_add_device_gmac(void) + } + + ast_eth0_data.DF_support = !isRevA0; +- ++ ++ // Wedge/6-Pack hardware attaches to MAC1; there's nothing on ++ // MAC0. Older drivers would drop interfaces without PHYs, but ++ // the latest open source drivers do not, so we drop the first ++ // MAC specs. ++#if !defined(CONFIG_WEDGE) && !defined(CONFIG_WEDGE100) + ast_scu_init_eth(0); + ast_scu_multi_func_eth(0); +- +- ++ ++ + /* + * D[15:11] in 0x1E6E2040 is NCSI scratch from U-Boot. D[15:14] = MAC1, D[13:12] = MAC2 + * The meanings of the 2 bits are: +@@ -144,7 +149,7 @@ void __init ast_add_device_gmac(void) + * 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly + * 11: Reserved + */ +- ++ + phy_mode = ast_scu_get_phy_config(0); + switch(phy_mode) { + case 0: +@@ -152,12 +157,12 @@ void __init ast_add_device_gmac(void) + ast_eth0_data.NCSI_support = 0; + break; + case 1: +- ast_eth0_data.NCSI_support = 1; ++ ast_eth0_data.INTEL_NCSI_EVA_support = 1; + break; + case 2: +- ast_eth0_data.INTEL_NCSI_EVA_support = 1; ++ ast_eth0_data.NCSI_support = 1; + break; +- ++ + } + + phy_inter = ast_scu_get_phy_interface(0); +@@ -165,12 +170,13 @@ void __init ast_add_device_gmac(void) + // We assume the Clock Stop register does not disable the MAC1 or MAC2 clock + // unless Reset Control also holds the MAC in reset. + +- ++ + platform_device_register(&ast_eth0_device); ++#endif + + #ifdef AST_MAC1_BASE + ast_scu_init_eth(1); +- ast_scu_multi_func_eth(1); ++ ast_scu_multi_func_eth(1); + + ast_eth1_data.DF_support = !isRevA0; + +@@ -186,7 +192,7 @@ void __init ast_add_device_gmac(void) + case 2: + ast_eth1_data.INTEL_NCSI_EVA_support = 1; + break; +- ++ + } + phy_inter = ast_scu_get_phy_interface(1); + +@@ -198,4 +204,3 @@ void __init ast_add_device_gmac(void) + #else + void __init ast_add_device_gmac(void) {} + #endif +- +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-i2c.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-i2c.c +index 9905390..fffa480 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-i2c.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-i2c.c +@@ -7,11 +7,11 @@ + * 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. +-* ++* + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -47,59 +47,59 @@ + #if defined (CONFIG_ARCH_AST2400) + #define I2C_PAGE_SIZE 8 + static spinlock_t page_info_lock = SPIN_LOCK_UNLOCKED; +-static struct buf_page page_info[I2C_PAGE_SIZE] = +-{ ++static struct buf_page page_info[I2C_PAGE_SIZE] = ++{ + [0] = { + .flag = 0, + .page_no = 0, + .page_size = 256, +- .page_addr_point = 0, ++ .page_addr_point = 0, + }, + [1] = { + .flag = 0, +- .page_no = 1, ++ .page_no = 1, + .page_size = 256, +- .page_addr_point = 0, ++ .page_addr_point = 0, + }, + [2] = { + .flag = 0, +- .page_no = 2, ++ .page_no = 2, + .page_size = 256, + .page_addr_point = 0, + }, + [3] = { + .flag = 0, +- .page_no = 3, ++ .page_no = 3, + .page_size = 256, + .page_addr_point = 0, + }, + [4] = { + .flag = 0, +- .page_no = 4, ++ .page_no = 4, + .page_size = 256, + .page_addr_point = 0, + }, + [5] = { + .flag = 0, +- .page_no = 5, ++ .page_no = 5, + .page_size = 256, + .page_addr_point = 0, + }, + [6] = { + .flag = 0, +- .page_no = 6, ++ .page_no = 6, + .page_size = 256, + .page_addr_point = 0, + }, + [7] = { + .flag = 0, +- .page_no = 7, ++ .page_no = 7, + .page_size = 256, + .page_addr_point = 0, + }, + }; + +-static void pool_buff_page_init(u32 buf_pool_addr) ++static void pool_buff_page_init(u32 buf_pool_addr) + { + u32 offset; + int i ,j; +@@ -108,7 +108,7 @@ static void pool_buff_page_init(u32 buf_pool_addr) + offset = 0; + for(j=0;j<i;j++) + offset += page_info[i].page_size; +- ++ + page_info[i].page_addr = buf_pool_addr + offset; + // I2CDBUG( "page[%d],addr :%x \n", i, page_info[i].page_addr); + } +@@ -130,7 +130,7 @@ static u8 request_pool_buff_page(struct buf_page **req_page) + break; + } + } +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + return (i >= I2C_PAGE_SIZE); + } + +@@ -140,17 +140,17 @@ static void free_pool_buff_page(struct buf_page *req_page) + spin_lock_irqsave(&page_info_lock, flags); + + req_page->flag = 0; +-// I2CDBUG( "free page addr %x \n", req_page->page_addr); ++// I2CDBUG( "free page addr %x \n", req_page->page_addr); + req_page = NULL; +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + } + + #elif defined (CONFIG_ARCH_AST2300) + #define I2C_PAGE_SIZE 5 + + static spinlock_t page_info_lock = SPIN_LOCK_UNLOCKED; +-static struct buf_page page_info[I2C_PAGE_SIZE] = +-{ ++static struct buf_page page_info[I2C_PAGE_SIZE] = ++{ + [0] = { + .flag = 0, + .page_size = 128, +@@ -173,7 +173,7 @@ static struct buf_page page_info[I2C_PAGE_SIZE] = + }, + }; + +-static void pool_buff_page_init(u32 buf_pool_addr) ++static void pool_buff_page_init(u32 buf_pool_addr) + { + + u32 offset; +@@ -183,7 +183,7 @@ static void pool_buff_page_init(u32 buf_pool_addr) + offset = 0; + for(j=0;j<i;j++) + offset += page_info[i].page_size; +- ++ + page_info[i].page_addr = buf_pool_addr + offset; + page_info[i].page_addr_point = page_info[i].page_addr/4; + // printk("page[%d],addr :%x , point : %d\n", i, page_info[i].page_addr, page_info[i].page_addr_point); +@@ -201,11 +201,11 @@ static u8 request_pool_buff_page(struct buf_page **req_page) + if(page_info[i].flag ==0) { + page_info[i].flag = 1; + *req_page = &page_info[i]; +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + return 0; + } + } +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + return 1; + + } +@@ -217,10 +217,10 @@ static void free_pool_buff_page(struct buf_page *req_page) + spin_lock_irqsave(&page_info_lock, flags); + req_page->flag = 0; + req_page = NULL; +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + } + +-#else ++#else + //DO nothing + static void pool_buff_page_init(void) {} + static u8 request_pool_buff_page(struct buf_page **req_page) {return 0;} +@@ -228,15 +228,15 @@ static void free_pool_buff_page(struct buf_page *req_page) {} + #endif + + static struct ast_i2c_driver_data ast_i2c_data = { +- .bus_clk = 100000, //bus clock 100KHz ++ .bus_clk = 100000, //bus clock 100KHz + .master_dma = BUFF_MODE, + .slave_dma = BYTE_MODE, + .request_pool_buff_page = request_pool_buff_page, + .free_pool_buff_page = free_pool_buff_page, +-#ifdef CONFIG_AST_I2C_SLAVE_MODE ++#ifdef CONFIG_AST_I2C_SLAVE_MODE + .slave_xfer = i2c_slave_xfer, + .slave_init = i2c_slave_init, +-#endif ++#endif + .get_i2c_clock = ast_get_pclk, + }; + +@@ -285,7 +285,7 @@ struct platform_device ast_i2c_dev2_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev2_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev2_resources), +@@ -310,7 +310,7 @@ struct platform_device ast_i2c_dev3_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev3_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev3_resources), +@@ -335,7 +335,7 @@ struct platform_device ast_i2c_dev4_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev4_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev4_resources), +@@ -360,7 +360,7 @@ struct platform_device ast_i2c_dev5_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev5_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev5_resources), +@@ -385,7 +385,7 @@ struct platform_device ast_i2c_dev6_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev6_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev6_resources), +@@ -410,7 +410,7 @@ struct platform_device ast_i2c_dev7_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev7_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev7_resources), +@@ -435,7 +435,7 @@ struct platform_device ast_i2c_dev8_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev8_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev8_resources), +@@ -460,7 +460,7 @@ struct platform_device ast_i2c_dev9_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev9_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev9_resources), +@@ -486,7 +486,7 @@ struct platform_device ast_i2c_dev10_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev10_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev10_resources), +@@ -511,7 +511,7 @@ struct platform_device ast_i2c_dev11_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev11_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev11_resources), +@@ -536,7 +536,7 @@ struct platform_device ast_i2c_dev12_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev12_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev12_resources), +@@ -561,7 +561,7 @@ struct platform_device ast_i2c_dev13_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev13_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev13_resources), +@@ -586,7 +586,7 @@ struct platform_device ast_i2c_dev14_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev14_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev14_resources), +@@ -594,12 +594,196 @@ struct platform_device ast_i2c_dev14_device = { + #endif + + /*--------- I2C Board devices ------------*/ +-//ASPEED AST2300 EVB I2C Device ++//ASPEED AST2300 EVB I2C Device + #if defined(CONFIG_ARCH_AST2300) || defined(CONFIG_ARCH_AST2400) ++ ++#if defined(CONFIG_WEDGE100) ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus1[] = { ++ /* shared NIC, no kernel driver */ ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus2[] = { ++ /* TODO: one IR3581 and two IR3584 */ ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus3[] = { ++ /* TODO: one PWR1014A */ ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus4[] = { ++ { ++ I2C_BOARD_INFO("tmp75", 0x48), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x49), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x4a), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x4b), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x4c), ++ }, ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus5[] = { ++ /* Panther+ microserver */ ++ { ++ I2C_BOARD_INFO("fb_panther_plus", 0x40), ++ }, ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus6[] = { ++ /* TODO: USB hub */ ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus7[] = { ++ { ++ I2C_BOARD_INFO("pcf8574", 0x2f), ++ }, ++ { ++ I2C_BOARD_INFO("24c64", 0x51), ++ } ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus8[] = { ++ /* BMC PHY EEPROM */ ++ { ++ I2C_BOARD_INFO("24c02", 0x50), ++ }, ++ // EEPROM on the pfe1100 power supplies ++ { ++ I2C_BOARD_INFO("24c64", 0x51), ++ }, ++ { ++ I2C_BOARD_INFO("24c64", 0x52), ++ }, ++ /* PSU driver */ ++ { ++ I2C_BOARD_INFO("pfe1100", 0x59), ++ }, ++ { ++ I2C_BOARD_INFO("pfe1100", 0x5a), ++ }, ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus9[] = { ++ { ++ I2C_BOARD_INFO("fancpld", 0x33), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x48), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x49), ++ }, ++}; ++ ++/* i2c bus 10-12 on wedge100 are not connected as i2c bus */ ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus13[] = { ++ { ++ I2C_BOARD_INFO("syscpld", 0x31), ++ }, ++}; ++ ++/* i2c bus 14 on wedge100 are not connected as i2c bus */ ++ ++/* end of defined(CONFIG_WEDGE100) */ ++ ++#elif defined(CONFIG_YOSEMITE) || defined(CONFIG_FBPLATFORM1) ++ ++//Under I2C Dev 1 ++static struct i2c_board_info __initdata ast_i2c_board_info_1[] = { ++ // Slot#0 NIC sideband ++}; ++ ++//Under I2C Dev 2 ++static struct i2c_board_info __initdata ast_i2c_board_info_2[] = { ++ // Slot#0 IPMB interface ++}; ++ ++//Under I2C Dev 3 ++static struct i2c_board_info __initdata ast_i2c_board_info_3[] = { ++ // Slot#1 NIC sideband ++}; ++ ++ ++//Under I2C Dev 4 ++static struct i2c_board_info __initdata ast_i2c_board_info_4[] = { ++ // Slot#1 IPMB interface ++}; ++ ++//Under I2C Dev 5 ++static struct i2c_board_info __initdata ast_i2c_board_info_5[] = { ++ // Slot#2 NIC sideband ++}; ++ ++//Under I2C Dev 6 ++static struct i2c_board_info __initdata ast_i2c_board_info_6[] = { ++ // Slot#2 IPMB interface ++}; ++ ++//Under I2C Dev 7 ++static struct i2c_board_info __initdata ast_i2c_board_info_7[] = { ++ // Slot#3 NIC sideband ++}; ++ ++//Under I2C Dev 8 ++static struct i2c_board_info __initdata ast_i2c_board_info_8[] = { ++ // Slot#3 IPMB interface ++}; ++ ++//Under I2C Dev 9 ++static struct i2c_board_info __initdata ast_i2c_board_info_9[] = { ++ // FRUID ++ { ++ I2C_BOARD_INFO("24c64", 0x51), ++ }, ++}; ++ ++//Under I2C Dev 10 ++static struct i2c_board_info __initdata ast_i2c_board_info_10[] = { ++ // Inlet and Outlet temp. sensors ++ { ++ I2C_BOARD_INFO("tmp75", 0x4e), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x4f), ++ }, ++}; ++ ++//Under I2C Dev 11 ++static struct i2c_board_info __initdata ast_i2c_board_info_11[] = { ++ // Hotswap Sensor ++ { ++ I2C_BOARD_INFO("adm1278", 0x40), ++ }, ++}; ++ ++//Under I2C Dev 12 ++static struct i2c_board_info __initdata ast_i2c_board_info_12[] = { ++ // Mezz Card LAN_SMB bus (PHY, Temp. Sensor) ++}; ++ ++//Under I2C Dev 13 ++static struct i2c_board_info __initdata ast_i2c_board_info_13[] = { ++ // Mezz Card Mezz_SMB bus (FRUID, GPIO expander, QSFP+) ++}; ++ ++/* end of CONFIG_YOSEMITE */ ++ ++#else ++ ++/* wedge */ ++ + //Under I2C Dev 1 + static struct i2c_board_info __initdata ast_i2c_board_info_1[] = { + { +- I2C_BOARD_INFO("cat9883", 0x4d), ++ I2C_BOARD_INFO("cat9883", 0x4d), + } + }; + +@@ -612,15 +796,6 @@ static struct i2c_board_info __initdata ast_i2c_board_info_2[] = { + { + I2C_BOARD_INFO("ncp4200", 0x60), + }, +- { +- I2C_BOARD_INFO("ncp4200", 0x61), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x62), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x63), +- }, + }; + + +@@ -632,15 +807,6 @@ static struct i2c_board_info __initdata ast_i2c_board_info_3[] = { + { + I2C_BOARD_INFO("ncp4200", 0x60), + }, +- { +- I2C_BOARD_INFO("ncp4200", 0x61), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x62), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x63), +- }, + }; + + +@@ -675,7 +841,7 @@ static struct i2c_board_info __initdata ast_i2c_board_info_5[] = { + I2C_BOARD_INFO("24c128", 0x51), + }, + }; +- ++ + //Under I2C Dev 7 + static struct i2c_board_info __initdata ast_i2c_board_info_7[] = { + // Wedge devices +@@ -688,15 +854,23 @@ static struct i2c_board_info __initdata ast_i2c_board_info_7[] = { + }, + { + I2C_BOARD_INFO("24c64", 0x50), +- } ++ }, + }; + + + //Under I2C Dev 8 + static struct i2c_board_info __initdata ast_i2c_board_info_8[] = { + { ++ // 6pack power supply ++ I2C_BOARD_INFO("pfe3000", 0x10), ++ }, ++ { + // Eval board: +- I2C_BOARD_INFO("lm75b", 0x4a), ++ I2C_BOARD_INFO("lm75b", 0x4a), ++ }, ++ { ++ // 6pack power supply EEPROM ++ I2C_BOARD_INFO("24c64", 0x50), + }, + // EEPROMS on the pfe1100 power supplies + { +@@ -722,20 +896,12 @@ static struct i2c_board_info __initdata ast_i2c_board_info_9[] = { + { + I2C_BOARD_INFO("ncp4200", 0x60), + }, +- { +- I2C_BOARD_INFO("ncp4200", 0x61), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x62), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x63), +- }, + }; + + //Under I2C Dev 12 + static struct i2c_board_info __initdata ast_i2c_board_info_12[] = { + { ++ // Early version of 6pack + I2C_BOARD_INFO("pfe3000", 0x10), + }, + }; +@@ -747,6 +913,10 @@ static struct i2c_board_info __initdata ast_i2c_board_info_13[] = { + }, + }; + ++/* end of WEDGE case */ ++#endif ++ ++/* end of defined(CONFIG_ARCH_AST2300) || defined(CONFIG_ARCH_AST2400) */ + #endif + + /*-------------------------------------*/ +@@ -755,7 +925,7 @@ void __init ast_add_device_i2c(void) + //I2C Multi-Pin + ast_scu_multi_func_i2c(); + +- //SCU I2C Reset ++ //SCU I2C Reset + ast_scu_init_i2c(); + + ast_i2c_data.reg_gr = ioremap(AST_I2C_BASE, 4*SZ_16); +@@ -777,8 +947,48 @@ void __init ast_add_device_i2c(void) + return; + } + #endif +- //TODO +- pool_buff_page_init(ast_i2c_data.buf_pool); ++ ++ pool_buff_page_init(ast_i2c_data.buf_pool); ++ ++#if defined(CONFIG_WEDGE100) ++ ++ platform_device_register(&ast_i2c_dev1_device); ++ i2c_register_board_info(0, wedge100_i2c_bus1, ARRAY_SIZE(wedge100_i2c_bus1)); ++ ++ platform_device_register(&ast_i2c_dev2_device); ++ i2c_register_board_info(1, wedge100_i2c_bus2, ARRAY_SIZE(wedge100_i2c_bus2)); ++ ++ platform_device_register(&ast_i2c_dev3_device); ++ i2c_register_board_info(2, wedge100_i2c_bus3, ARRAY_SIZE(wedge100_i2c_bus3)); ++ ++ platform_device_register(&ast_i2c_dev4_device); ++ i2c_register_board_info(3, wedge100_i2c_bus4, ARRAY_SIZE(wedge100_i2c_bus4)); ++ ++ platform_device_register(&ast_i2c_dev5_device); ++ i2c_register_board_info(4, wedge100_i2c_bus5, ARRAY_SIZE(wedge100_i2c_bus5)); ++ ++ platform_device_register(&ast_i2c_dev6_device); ++ i2c_register_board_info(5, wedge100_i2c_bus6, ARRAY_SIZE(wedge100_i2c_bus6)); ++ ++ platform_device_register(&ast_i2c_dev7_device); ++ i2c_register_board_info(6, wedge100_i2c_bus7, ARRAY_SIZE(wedge100_i2c_bus7)); ++ ++ platform_device_register(&ast_i2c_dev8_device); ++ i2c_register_board_info(7, wedge100_i2c_bus8, ARRAY_SIZE(wedge100_i2c_bus8)); ++ ++ platform_device_register(&ast_i2c_dev9_device); ++ i2c_register_board_info(8, wedge100_i2c_bus9, ARRAY_SIZE(wedge100_i2c_bus9)); ++ ++ /* i2c bus 10 - 12 are not used as i2c on wedge100 */ ++ ++ platform_device_register(&ast_i2c_dev13_device); ++ i2c_register_board_info(12, wedge100_i2c_bus13, ARRAY_SIZE(wedge100_i2c_bus13)); ++ ++ /* i2c bug 14 is not used as i2c on wedge100 */ ++ ++ /* end of defined(CONFIG_WEDGE100) */ ++#else ++ + platform_device_register(&ast_i2c_dev1_device); + i2c_register_board_info(0, ast_i2c_board_info_1, ARRAY_SIZE(ast_i2c_board_info_1)); + platform_device_register(&ast_i2c_dev2_device); +@@ -790,17 +1000,27 @@ void __init ast_add_device_i2c(void) + platform_device_register(&ast_i2c_dev5_device); + i2c_register_board_info(4, ast_i2c_board_info_5, ARRAY_SIZE(ast_i2c_board_info_5)); + platform_device_register(&ast_i2c_dev6_device); ++#if defined(CONFIG_YOSEMITE) ++ i2c_register_board_info(5, ast_i2c_board_info_6, ARRAY_SIZE(ast_i2c_board_info_6)); ++#endif + platform_device_register(&ast_i2c_dev7_device); + i2c_register_board_info(6, ast_i2c_board_info_7, ARRAY_SIZE(ast_i2c_board_info_7)); + platform_device_register(&ast_i2c_dev8_device); + i2c_register_board_info(7, ast_i2c_board_info_8, ARRAY_SIZE(ast_i2c_board_info_8)); +- platform_device_register(&ast_i2c_dev9_device); ++ platform_device_register(&ast_i2c_dev9_device); + i2c_register_board_info(8, ast_i2c_board_info_9, ARRAY_SIZE(ast_i2c_board_info_9)); + + #if defined(CONFIG_ARCH_AST2400) + platform_device_register(&ast_i2c_dev10_device); ++ ++#if defined(CONFIG_YOSEMITE) ++ i2c_register_board_info(9, ast_i2c_board_info_10, ARRAY_SIZE(ast_i2c_board_info_10)); ++ platform_device_register(&ast_i2c_dev11_device); ++ i2c_register_board_info(10, ast_i2c_board_info_11, ARRAY_SIZE(ast_i2c_board_info_11)); ++#endif ++ + #if defined(CONFIG_MMC_AST) +- //Due to share pin with SD ++ //Due to share pin with SD + #else + /* + * On Wedge, bus 13 is used as i2c bus. Bus 12 is used on other +@@ -812,7 +1032,12 @@ void __init ast_add_device_i2c(void) + i2c_register_board_info(11, ast_i2c_board_info_12, ARRAY_SIZE(ast_i2c_board_info_12)); + platform_device_register(&ast_i2c_dev13_device); + i2c_register_board_info(12, ast_i2c_board_info_13, ARRAY_SIZE(ast_i2c_board_info_13)); +-#endif ++#endif ++ ++ /* end of defined(CONFIG_ARCH_AST2400) */ ++#endif ++ ++ /* end of else of defined(CONFIG_WEDGE100) */ + #endif + } + #else +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-spi.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-spi.c +index e22c49e..0cb0189 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-spi.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-spi.c +@@ -344,8 +344,8 @@ static struct flash_platform_data wedge_spi_flash_data = { + + + /* Device info for the flash on ast-spi */ +-#ifdef CONFIG_ARCH_AST2400 +-static struct mtd_partition ast_spi5_flash_partitions[] = { ++#ifdef CONFIG_WEDGE ++static struct mtd_partition wedge_spi5_flash_partitions[] = { + { + .name = "led-fpga", + .offset = 0, /* From 0 */ +@@ -355,8 +355,8 @@ static struct mtd_partition ast_spi5_flash_partitions[] = { + + static struct flash_platform_data wedge_spi5_flash_data = { + .type = "at45db011d", +- .nr_parts = ARRAY_SIZE(ast_spi5_flash_partitions), +- .parts = ast_spi5_flash_partitions, ++ .nr_parts = ARRAY_SIZE(wedge_spi5_flash_partitions), ++ .parts = wedge_spi5_flash_partitions, + }; + #endif + +@@ -372,6 +372,7 @@ static struct spi_board_info ast_spi_devices[] = { + }, + #endif + #ifdef CONFIG_ARCH_AST2400 ++#ifdef CONFIG_WEDGE + { + .modalias = "mtd_dataflash", + .platform_data = &wedge_spi5_flash_data, +@@ -380,6 +381,15 @@ static struct spi_board_info ast_spi_devices[] = { + .bus_num = 5, + .mode = SPI_MODE_0, + }, ++#elif defined CONFIG_WEDGE100 ++ { ++ .modalias = "spidev", ++ .chip_select = 0, ++ .max_speed_hz = 33 * 1000 * 1000, ++ .bus_num = 5, ++ .mode = SPI_MODE_0, ++ }, ++#endif + { + .modalias = "m25p80", + .platform_data = &wedge_spi_flash_data, +@@ -389,13 +399,6 @@ static struct spi_board_info ast_spi_devices[] = { + .mode = SPI_MODE_0, + }, + #endif +- { +- .modalias = "spidev", +- .chip_select = 0, +- .max_speed_hz = 30 * 1000 * 1000, +- .bus_num = 1, +- .mode = SPI_MODE_0, +- }, + }; + + #if defined(AST_SPI1_BASE) +@@ -490,5 +493,3 @@ void __init ast_add_device_spi(void) + #else + void __init ast_add_device_spi(void) {} + #endif +- +- +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-uart.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-uart.c +index 0b7b614..e424a5a 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-uart.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/dev-uart.c +@@ -6,11 +6,11 @@ + * 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. +-* ++* + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -50,14 +50,14 @@ static struct plat_serial8250_port ast_uart_data[] = { + .irq = IRQ_UART0, + .uartclk = (24*1000000L), + .regshift = 2, +-#if defined(CONFIG_COLDFIRE) ++#if defined(CONFIG_COLDFIRE) + .iotype = UPIO_MEM32, + #else + .iotype = UPIO_MEM, +-#endif ++#endif + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, +-#if defined(CONFIG_ARCH_AST1010) ++#if defined(CONFIG_ARCH_AST1010) + { + .mapbase = AST_UART1_BASE, + .irq = IRQ_UART1, +@@ -65,7 +65,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM32, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + { + .mapbase = AST_UART2_BASE, + .irq = IRQ_UART2, +@@ -73,7 +73,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM32, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + #else + //BMC UART 1 ,2 default to LPC + #ifdef CONFIG_ARCH_AST1070 +@@ -85,7 +85,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + #endif + #ifdef AST_UART2_BASE + { +@@ -95,7 +95,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + #endif + #endif + #ifdef AST_UART1_BASE +@@ -109,6 +109,19 @@ static struct plat_serial8250_port ast_uart_data[] = { + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + #endif ++#if defined(CONFIG_YOSEMITE) //Without this, tty offset might change for others ++#ifdef AST_UART2_BASE ++ { ++ .mapbase = AST_UART2_BASE, ++ .membase = (char*)(IO_ADDRESS(AST_UART2_BASE)), ++ .irq = IRQ_UART2, ++ .uartclk = (24*1000000L), ++ .regshift = 2, ++ .iotype = UPIO_MEM, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ }, ++#endif ++#endif + #ifdef AST_UART3_BASE + { + .mapbase = AST_UART3_BASE, +@@ -117,7 +130,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + #endif + #ifdef AST_UART4_BASE + { +@@ -127,9 +140,9 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, ++#endif + #endif +-#endif + { }, + }; + +@@ -144,11 +157,16 @@ struct platform_device ast_uart_device = { + void __init ast_add_device_uart(void) + { + #if defined(CONFIG_ARCH_AST1010) ++#elif defined(CONFIG_YOSEMITE) ++ ast_scu_multi_func_uart(1); ++ ast_scu_multi_func_uart(2); ++ ast_scu_multi_func_uart(3); ++ ast_scu_multi_func_uart(4); + #else +- ast_scu_multi_func_uart(1); +- ast_scu_multi_func_uart(3); +- ast_scu_multi_func_uart(4); +-#endif ++ ast_scu_multi_func_uart(1); ++ ast_scu_multi_func_uart(3); ++ ast_scu_multi_func_uart(4); ++#endif + platform_device_register(&ast_uart_device); + } + #else +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/irq.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/irq.c +index b118359..f6100fa 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/irq.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/arch/arm/plat-aspeed/irq.c +@@ -48,13 +48,14 @@ static void ast_mask_irq(unsigned int irq) + if((irq >= IRQ_TIMER0) && (irq <= IRQ_TIMER2)) + timer = 1; + #endif +- +- if (irq > 32) { ++ ++ // for irq0-irq31 use LOW register; for irq32-irq63 use HIGH register set. ++ if (irq >= 32) { + i=1; + irq = irq - 32; + } else + i=0; +- ++ + regVal = readl(AST_INTR_DIS(i)); + regVal |= (1 << irq); + writel(regVal, AST_INTR_DIS(i)); +@@ -63,8 +64,8 @@ static void ast_mask_irq(unsigned int irq) + * clear the interrupt + */ + if(timer) +- IRQ_EDGE_CLEAR(i,irq); +- ++ IRQ_EDGE_CLEAR(i,irq); ++ + } + + static void ast_unmask_irq(unsigned int irq) +@@ -72,12 +73,13 @@ static void ast_unmask_irq(unsigned int irq) + int i; + u32 regVal; + +- if (irq > 32) { ++ // for irq0-irq31 use LOW register; for irq32-irq63 use HIGH register set. ++ if (irq >= 32) { + i=1; + irq = irq - 32; + } else + i=0; +- ++ + regVal = readl(AST_INTR_EN(i)); + regVal |= (1 << irq); + writel(regVal, AST_INTR_EN(i)); +@@ -88,8 +90,8 @@ static struct irq_chip ast_irq_chip = { + .ack = ast_mask_irq, + .mask = ast_mask_irq, + .unmask = ast_unmask_irq, +-}; +- ++}; ++ + void __init ast_init_irq(void) + { + unsigned int i; +@@ -107,8 +109,8 @@ void __init ast_init_irq(void) + writel(0xFFFFFFFF, AST_INTR_EDGE_CLR(1)); + #endif + +- //TOTAL IRQ NUM = +- for (i = 0; i < AST_VIC_NUM; i++) ++ //TOTAL IRQ NUM = ++ for (i = 0; i < AST_VIC_NUM; i++) + { + if(i<32) { + if((i >= IRQ_TIMER0) && (i <= IRQ_TIMER2)) //Timer0/1/2 +@@ -125,9 +127,9 @@ void __init ast_init_irq(void) + IRQ_SET_HIGH_LEVEL(1,i-32); + IRQ_SET_LEVEL_TRIGGER(1,i-32); + } +-#endif ++#endif + } +- ++ + set_irq_chip(i, &ast_irq_chip); + set_irq_handler(i, handle_level_irq); + set_irq_flags(i, IRQF_VALID); +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c +index 3f95dc6..8f5aa54 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c +@@ -13,10 +13,10 @@ + * 2012.11.26: Initial version [Ryan Chen] + */ + +-/* attr ADC sysfs 0~max adc channel ++/* attr ADC sysfs 0~max adc channel + * 0 - show/store enable + * 3 - show value +-* 1 - show/store alarm_en set enable ++* 1 - show/store alarm_en set enable + * 2 - show alarm get statuse + * 4 - show/store upper + * 5 - show/store lower */ +@@ -44,13 +44,33 @@ + + #define REST_DESIGN 5 + ++ ++#ifdef CONFIG_YOSEMITE ++enum { ++ ADC_P5V = 0, ++ ADC_P12V, ++ ADC_P3V3_STBY, ++ ADC_P12V_SLOT0, ++ ADC_P12V_SLOT1, ++ ADC_P12V_SLOT2, ++ ADC_P12V_SLOT3, ++ ADC_P3V3, ++}; ++ ++enum { ++ REST_DESIGN_P3V3 = 6, ++ REST_DESIGN_P5V = 7, ++ REST_DESIGN_P12V = 8, ++}; ++#endif // CONFIG_YOSEMITE ++ + struct adc_vcc_ref_data { + int v2; + int r1; +- int r2; ++ int r2; + }; + +-static struct adc_vcc_ref_data adc_vcc_ref[6] = { ++static struct adc_vcc_ref_data adc_vcc_ref[9] = { + [0] = { + .v2 = 0, + .r1 = 5600, +@@ -81,6 +101,24 @@ static struct adc_vcc_ref_data adc_vcc_ref[6] = { + .r1 = 1000, + .r2 = 1000, + }, ++ // P3V3 ++ [6] = { ++ .v2 = 0, ++ .r1 = 5110, ++ .r2 = 8250, ++ }, ++ // P5V ++ [7] = { ++ .v2 = 0, ++ .r1 = 5110, ++ .r2 = 3480, ++ }, ++ // P12V ++ [8] = { ++ .v2 = 0, ++ .r1 = 5110, ++ .r2 = 1020, ++ }, + }; + + /* Divisors for voltage sense; right now adc5 & adc6 divide by 2 */ +@@ -93,7 +131,7 @@ static int adc_divisor[] = { 1, 1, 1, 1, + struct ast_adc_data { + struct device *hwmon_dev; + void __iomem *reg_base; /* virtual */ +- int irq; //ADC IRQ number ++ int irq; //ADC IRQ number + int compen_value; //Compensating value + }; + +@@ -123,14 +161,14 @@ static void ast_adc_ctrl_init(void) + ast_adc_write(ast_adc, AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); + + //Set wait a sensing cycle t (s) = 1000 * 12 * (1/PCLK) * 2 * (ADC0c[31:17] + 1) * (ADC0c[9:0] +1) +- //ex : pclk = 48Mhz , ADC0c[31:17] = 0, ADC0c[9:0] = 0x40 : 64, ADC0c[31:17] = 0x3e7 : 999 ++ //ex : pclk = 48Mhz , ADC0c[31:17] = 0, ADC0c[9:0] = 0x40 : 64, ADC0c[31:17] = 0x3e7 : 999 + // --> 0.0325s = 12 * 2 * (0x3e7 + 1) *(64+1) / 48000000 +- // --> 0.0005s = 12 * 2 * (0x3e7 + 1) / 48000000 +- ++ // --> 0.0005s = 12 * 2 * (0x3e7 + 1) / 48000000 ++ + pclk = ast_get_pclk(); + + #if defined(CONFIG_ARCH_AST2300) +- ast_adc_write(ast_adc, 0x3e7, AST_ADC_CLK); ++ ast_adc_write(ast_adc, 0x3e7, AST_ADC_CLK); + + ast_adc_write(ast_adc, AST_ADC_CTRL_CH12_EN | AST_ADC_CTRL_COMPEN_CLR| ast_adc_read(ast_adc, AST_ADC_CTRL), AST_ADC_CTRL); + +@@ -141,16 +179,16 @@ static void ast_adc_ctrl_init(void) + ast_adc->compen_value = 0x200 - (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK); + else + ast_adc->compen_value = 0 - (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK); +- +- printk("compensating value %d \n",ast_adc->compen_value); +- ++ ++ // printk("compensating value %d \n",ast_adc->compen_value); ++ + #elif defined(CONFIG_ARCH_AST2400) + + //For AST2400 A0 workaround ... ADC0c = 1 ; + // ast_adc_write(ast_adc, 1, AST_ADC_CLK); + // ast_adc_write(ast_adc, (0x3e7<< 17) | 0x40, AST_ADC_CLK); + ast_adc_write(ast_adc, 0x40, AST_ADC_CLK); +- ++ + ast_adc_write(ast_adc, AST_ADC_CTRL_CH0_EN | AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); + + ast_adc_read(ast_adc, AST_ADC_CTRL); +@@ -159,15 +197,15 @@ static void ast_adc_ctrl_init(void) + + //compensating value = 0x200 - ADC10[9:0] + ast_adc->compen_value = 0x200 - (ast_adc_read(ast_adc, AST_ADC_CH0_1) & AST_ADC_L_CH_MASK); +- printk("compensating value %d \n",ast_adc->compen_value); ++ // printk("compensating value %d \n",ast_adc->compen_value); + + #elif defined(CONFIG_ARCH_AST2500) +-// TODO ... +-// scu read trim ++// TODO ... ++// scu read trim + // write trim 0xc4 [3:0] +- ++ + ast_adc_write(ast_adc, 0x40, AST_ADC_CLK); +- ++ + ast_adc_write(ast_adc, AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); + + while(!ast_adc_read(ast_adc, AST_ADC_CTRL) & 0x100); +@@ -175,17 +213,17 @@ static void ast_adc_ctrl_init(void) + ast_adc_write(ast_adc, AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); + + while(ast_adc_read(ast_adc, AST_ADC_CTRL) & AST_ADC_CTRL_COMPEN); +- ++ + //compensating value = 0x200 - ADC10[9:0] + ast_adc->compen_value = 0x200 - ((ast_adc_read(ast_adc, AST_ADC_TRIM) >> 16) & 0x3ff); +- printk("compensating value %d \n",ast_adc->compen_value); +- ++ // printk("compensating value %d \n",ast_adc->compen_value); ++ + #else + #err "No define for ADC " + #endif + + ast_adc_write(ast_adc, AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); +- ++ + } + + static u16 +@@ -203,9 +241,9 @@ ast_get_adc_hyster_lower(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_hyster_lower(struct ast_adc_data *ast_adc, u8 adc_ch, u16 value) + { +- ast_adc_write(ast_adc, ++ ast_adc_write(ast_adc, + (ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & ~AST_ADC_L_BOUND) | +- value, ++ value, + AST_ADC_HYSTER0 + (adc_ch *4)); + + } +@@ -224,9 +262,9 @@ ast_get_adc_hyster_upper(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_hyster_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value) + { +- ast_adc_write(ast_adc, ++ ast_adc_write(ast_adc, + (ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & ~AST_ADC_H_BOUND) | +- (value << 16), ++ (value << 16), + AST_ADC_HYSTER0 + (adc_ch *4)); + + } +@@ -244,7 +282,7 @@ ast_get_adc_hyster_en(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_hyster_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) + { +- //tacho source ++ //tacho source + if(enable == 1) + ast_adc_write(ast_adc, + ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) | AST_ADC_HYSTER_EN, +@@ -270,9 +308,9 @@ ast_get_adc_lower(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_lower(struct ast_adc_data *ast_adc, u8 adc_ch, u16 value) + { +- ast_adc_write(ast_adc, ++ ast_adc_write(ast_adc, + (ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & ~AST_ADC_L_BOUND) | +- value, ++ value, + AST_ADC_BOUND0 + (adc_ch *4)); + + } +@@ -293,9 +331,9 @@ ast_get_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value) + { +- ast_adc_write(ast_adc, ++ ast_adc_write(ast_adc, + (ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & ~AST_ADC_H_BOUND) | +- (value << 16), ++ (value << 16), + AST_ADC_BOUND0 + (adc_ch *4)); + + } +@@ -304,7 +342,7 @@ ast_set_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value) + static u8 + ast_get_adc_alarm(struct ast_adc_data *ast_adc, u8 adc_ch) + { +- //adc ch source ++ //adc ch source + if(ast_adc_read(ast_adc, AST_ADC_IER) & (0x1 << adc_ch)) + return 1; + else +@@ -322,61 +360,61 @@ ast_get_adc_value(struct ast_adc_data *ast_adc, u8 adc_ch) + break; + case 1: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH0_1) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 2: + tmp = ast_adc_read(ast_adc, AST_ADC_CH2_3) & AST_ADC_L_CH_MASK; + break; + case 3: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH2_3) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 4: + tmp = ast_adc_read(ast_adc, AST_ADC_CH4_5) & AST_ADC_L_CH_MASK; + break; + case 5: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH4_5) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 6: + tmp = ast_adc_read(ast_adc, AST_ADC_CH6_7) & AST_ADC_L_CH_MASK; + break; + case 7: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH6_7) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 8: + tmp = ast_adc_read(ast_adc, AST_ADC_CH8_9) & AST_ADC_L_CH_MASK; + break; + case 9: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH8_9) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 10: + tmp = ast_adc_read(ast_adc, AST_ADC_CH10_11) & AST_ADC_L_CH_MASK; + break; + case 11: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH10_11) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 12: + tmp = ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK; + break; + case 13: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 14: + tmp = ast_adc_read(ast_adc, AST_ADC_CH14_15) & AST_ADC_L_CH_MASK; + break; + case 15: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH14_15) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + + } + + tmp += ast_adc->compen_value; + + // printk("voltage = %d \n",tmp); +- ++ + return tmp; + + } + +-static u8 ++static u8 + ast_get_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch) + { + u8 tmp=0; +@@ -390,7 +428,7 @@ ast_get_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch) + + } + +-static void ++static void + ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) + { + if(enable) +@@ -401,7 +439,7 @@ ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) + + + /* NAME sysfs */ +-static ssize_t ++static ssize_t + show_name(struct device *dev, struct device_attribute *devattr, + char *buf) + { +@@ -416,38 +454,63 @@ static const struct attribute_group name_attribute_groups = { + .attrs = name_attributes, + }; + +-/* attr ADC sysfs 0~max adc channel ++/* attr ADC sysfs 0~max adc channel + * 0 - show/store channel enable +-* 1 - show value ++* 1 - show value + * 2 - show alarm get statuse + * 3 - show/store upper +-* 4 - show/store lower +-* 5 - show/store hystersis enable +-* 6 - show/store hystersis upper +-* 7 - show/store hystersis low ++* 4 - show/store lower ++* 5 - show/store hystersis enable ++* 6 - show/store hystersis upper ++* 7 - show/store hystersis low + */ + +-static u32 ++static u32 + ast_get_voltage(int idx) { ++ u8 rest_design = REST_DESIGN; + u16 tmp; + u32 voltage, tmp1, tmp2, tmp3; + tmp = ast_get_adc_value(ast_adc, idx); ++ ++#ifdef CONFIG_YOSEMITE ++ switch (idx) { ++ case ADC_P3V3: ++ case ADC_P3V3_STBY: ++ rest_design = REST_DESIGN_P3V3; ++ break; ++ case ADC_P5V: ++ rest_design = REST_DESIGN_P5V; ++ break; ++ case ADC_P12V: ++ case ADC_P12V_SLOT0: ++ case ADC_P12V_SLOT1: ++ case ADC_P12V_SLOT2: ++ case ADC_P12V_SLOT3: ++ rest_design = REST_DESIGN_P12V; ++ break; ++ default: ++ rest_design = REST_DESIGN; ++ } ++#endif // CONFIG_YOSEMITE ++ + // Voltage Sense Method +- tmp1 = (adc_vcc_ref[REST_DESIGN].r1 + adc_vcc_ref[REST_DESIGN].r2) * tmp * 25 * 10; +- tmp2 = adc_vcc_ref[REST_DESIGN].r2 * 1024 ; +- tmp3 = (adc_vcc_ref[REST_DESIGN].r1 * adc_vcc_ref[REST_DESIGN].v2) / adc_vcc_ref[REST_DESIGN].r2; ++ tmp1 = (adc_vcc_ref[rest_design].r1 + adc_vcc_ref[rest_design].r2) * tmp * 25 * 10; ++ tmp2 = adc_vcc_ref[rest_design].r2 * 1024 ; ++ tmp3 = (adc_vcc_ref[rest_design].r1 * adc_vcc_ref[rest_design].v2) / adc_vcc_ref[rest_design].r2; + // printk("tmp3 = %d \n",tmp3); + voltage = (tmp1/tmp2) - tmp3; + ++#ifndef CONFIG_YOSEMITE + // Higher voltage inputs require a divisor + + if (adc_divisor[idx]) + voltage /= adc_divisor[idx]; ++#endif //CONFIG_YOSEMITE + + return voltage; + } + +-static ssize_t ++static ssize_t + ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) + { + struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); +@@ -455,7 +518,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) + + //sensor_attr->index : pwm_ch# + //sensor_attr->nr : attr# +- switch(sensor_attr->nr) ++ switch(sensor_attr->nr) + { + case 0: //channel enable, disable + return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_en(ast_adc,sensor_attr->index),ast_get_adc_en(ast_adc,sensor_attr->index) ? "Enable":"Disable"); +@@ -466,23 +529,23 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) + break; + case 2: //alarm + return sprintf(sysfsbuf, "%d \n", ast_get_adc_alarm(ast_adc,sensor_attr->index)); +- break; ++ break; + case 3: //upper + return sprintf(sysfsbuf, "%d \n", ast_get_adc_upper(ast_adc,sensor_attr->index)); +- break; ++ break; + case 4: //lower + return sprintf(sysfsbuf, "%d \n", ast_get_adc_lower(ast_adc,sensor_attr->index)); +- break; +- case 5: //hystersis enable ++ break; ++ case 5: //hystersis enable + return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_hyster_en(ast_adc,sensor_attr->index),ast_get_adc_hyster_en(ast_adc,sensor_attr->index) ? "Enable":"Disable"); +- break; ++ break; + case 6: //hystersis upper + return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_upper(ast_adc,sensor_attr->index)); +- break; ++ break; + case 7: //hystersis lower + return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_lower(ast_adc,sensor_attr->index)); +- break; +- case 8: ++ break; ++ case 8: + voltage = ast_get_voltage(sensor_attr->index); + return sprintf(sysfsbuf, "%d\n",voltage * 10); + +@@ -492,7 +555,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) + } + } + +-static ssize_t ++static ssize_t + ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count) + { + u32 input_val; +@@ -503,16 +566,16 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys + + //sensor_attr->index : pwm_ch# + //sensor_attr->nr : attr# +- switch(sensor_attr->nr) ++ switch(sensor_attr->nr) + { + case 0: //enable, disable + ast_set_adc_en(ast_adc, sensor_attr->index, input_val); + break; + case 1: //value +- ++ + break; + case 2: //alarm +- break; ++ break; + case 3: + ast_set_adc_upper(ast_adc, sensor_attr->index, input_val); + break; +@@ -521,14 +584,14 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys + break; + case 5: //hystersis + ast_set_adc_hyster_en(ast_adc, sensor_attr->index, input_val); +- break; ++ break; + case 6: + ast_set_adc_hyster_upper(ast_adc, sensor_attr->index, input_val); + break; + case 7: + ast_set_adc_hyster_lower(ast_adc, sensor_attr->index, input_val); + break; +- ++ + default: + return -EINVAL; + break; +@@ -537,15 +600,15 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys + return count; + } + +-/* attr ADC sysfs 0~max adc channel ++/* attr ADC sysfs 0~max adc channel + * 0 - show/store channel enable +-* 1 - show value ++* 1 - show value + * 2 - show alarm get statuse + * 3 - show/store upper +-* 4 - show/store lower +-* 5 - show/store hystersis enable +-* 6 - show/store hystersis upper +-* 7 - show/store hystersis low ++* 4 - show/store lower ++* 5 - show/store hystersis enable ++* 6 - show/store hystersis upper ++* 7 - show/store hystersis low + * 8 - show value as 1000s, expected by lm-sensors + */ + +@@ -624,18 +687,18 @@ static const struct attribute_group adc_attribute_groups[] = { + { .attrs = adc7_attributes }, + { .attrs = adc8_attributes }, + { .attrs = adc9_attributes }, +- { .attrs = adc10_attributes }, ++ { .attrs = adc10_attributes }, + { .attrs = adc11_attributes }, + #if defined(CONFIG_ARCH_AST2400) || defined(CONFIG_ARCH_AST2500) + { .attrs = adc12_attributes }, + { .attrs = adc13_attributes }, + { .attrs = adc14_attributes }, + { .attrs = adc15_attributes }, +-#endif ++#endif + }; + + +-static int ++static int + ast_adc_probe(struct platform_device *pdev) + { + struct resource *res; +@@ -695,7 +758,7 @@ ast_adc_probe(struct platform_device *pdev) + } + + ast_adc_ctrl_init(); +- ++ + printk(KERN_INFO "ast_adc: driver successfully loaded.\n"); + + return 0; +@@ -714,7 +777,7 @@ out: + return ret; + } + +-static int ++static int + ast_adc_remove(struct platform_device *pdev) + { + int i=0; +@@ -739,14 +802,14 @@ ast_adc_remove(struct platform_device *pdev) + } + + #ifdef CONFIG_PM +-static int ++static int + ast_adc_suspend(struct platform_device *pdev, pm_message_t state) + { + printk("ast_adc_suspend : TODO \n"); + return 0; + } + +-static int ++static int + ast_adc_resume(struct platform_device *pdev) + { + ast_adc_ctrl_init(); +@@ -769,13 +832,13 @@ static struct platform_driver ast_adc_driver = { + }, + }; + +-static int __init ++static int __init + ast_adc_init(void) + { + return platform_driver_register(&ast_adc_driver); + } + +-static void __exit ++static void __exit + ast_adc_exit(void) + { + platform_driver_unregister(&ast_adc_driver); +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/busses/i2c-ast.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/busses/i2c-ast.c +index 7a083de..9bb3154 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/busses/i2c-ast.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/busses/i2c-ast.c +@@ -40,63 +40,68 @@ + #include <plat/ast_i2c.h> + #endif + +-//AST2400 buffer mode issue , force I2C slave write use byte mode , read use buffer mode ++//AST2400 buffer mode issue , force I2C slave write use byte mode , read use buffer mode + /* Use platform_data instead of module parameters */ + /* Fast Mode = 400 kHz, Standard = 100 kHz */ + //static int clock = 100; /* Default: 100 kHz */ + + + /***************************************************************************/ ++ ++#ifdef CONFIG_AST_I2C_SLAVE_RDWR ++#define I2C_S_BUF_SIZE 64 ++#define I2C_S_RX_BUF_NUM 4 ++#define BUFF_FULL 0xff00 ++#define BUFF_ONGOING 1 ++#endif ++ ++#define AST_LOCKUP_DETECTED (0x1 << 15) ++ + struct ast_i2c_dev { + struct ast_i2c_driver_data *ast_i2c_data; + struct device *dev; +- void __iomem *reg_base; /* virtual */ +- int irq; //I2C IRQ number +- u32 bus_id; //for i2c dev# IRQ number check +- u32 state; //I2C xfer mode state matchine ++ void __iomem *reg_base; /* virtual */ ++ int irq; //I2C IRQ number ++ u32 bus_id; //for i2c dev# IRQ number check ++ u32 state; //I2C xfer mode state matchine + struct i2c_adapter adap; +- struct buf_page *req_page; ++ struct buf_page *req_page; + //dma or buff mode needed + unsigned char *dma_buf; + dma_addr_t dma_addr; +- +-//master ++ ++//master + int xfer_last; //cur xfer is last msgs for stop msgs + struct i2c_msg *master_msgs; //cur xfer msgs +- int master_xfer_len; //cur xfer len ++ int master_xfer_len; //cur xfer len + int master_xfer_cnt; //total xfer count + u32 master_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx + struct completion cmd_complete; + int cmd_err; + u8 blk_r_flag; //for smbus block read +- void (*do_master_xfer)(struct ast_i2c_dev *i2c_dev); +-//Slave structure ++ void (*do_master_xfer)(struct ast_i2c_dev *i2c_dev); ++ spinlock_t master_lock; ++//Slave structure + u8 slave_operation; + u8 slave_event; + struct i2c_msg *slave_msgs; //cur slave xfer msgs +- int slave_xfer_len; +- int slave_xfer_cnt; +- u32 slave_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx ++ int slave_xfer_len; ++ int slave_xfer_cnt; ++ u32 slave_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx + void (*do_slave_xfer)(struct ast_i2c_dev *i2c_dev); +-}; +- + #ifdef CONFIG_AST_I2C_SLAVE_RDWR +-#define I2C_S_BUF_SIZE 64 +-#define I2C_S_RX_BUF_NUM 4 +-#define BUFF_FULL 0xff00 +-#define BUFF_ONGOING 1 +- +-struct i2c_msg slave_rx_msg[I2C_S_RX_BUF_NUM + 1]; +-struct i2c_msg slave_tx_msg; +-static spinlock_t slave_rx_lock = SPIN_LOCK_UNLOCKED; ++ struct i2c_msg slave_rx_msg[I2C_S_RX_BUF_NUM + 1]; ++ struct i2c_msg slave_tx_msg; ++ spinlock_t slave_rx_lock; + #endif ++}; ++ + +-static spinlock_t g_master_lock = SPIN_LOCK_UNLOCKED; + + static inline void + ast_i2c_write(struct ast_i2c_dev *i2c_dev, u32 val, u32 reg) + { +-// dev_dbg(i2c_dev->dev, "ast_i2c_write : val: %x , reg : %x \n",val,reg); ++// dev_dbg(i2c_dev->dev, "ast_i2c_write : val: %x , reg : %x \n",val,reg); + writel(val, i2c_dev->reg_base+ reg); + } + +@@ -107,7 +112,7 @@ ast_i2c_read(struct ast_i2c_dev *i2c_dev, u32 reg) + u32 val = readl(i2c_dev->reg_base + reg); + printk("R : reg %x , val: %x \n",reg, val); + return val; +-#else ++#else + return readl(i2c_dev->reg_base + reg); + #endif + } +@@ -152,7 +157,7 @@ static void ast_slave_issue_alert(struct ast_i2c_dev *i2c_dev, u8 enable) + static void ast_slave_mode_enable(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msgs) + { + if(msgs->buf[0] == 1) { +- ast_i2c_write(i2c_dev, msgs->addr, I2C_DEV_ADDR_REG); ++ ast_i2c_write(i2c_dev, msgs->addr, I2C_DEV_ADDR_REG); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG) | AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG); + } else + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG) & ~AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG); +@@ -162,12 +167,14 @@ static void ast_slave_mode_enable(struct ast_i2c_dev *i2c_dev, struct i2c_msg *m + + static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) + { +- //I2CG Reset ++ //I2CG Reset + ast_i2c_write(i2c_dev, 0, I2C_FUN_CTRL_REG); + +-#ifdef CONFIG_AST_I2C_SLAVE_EEPROM ++#ifdef CONFIG_AST_I2C_SLAVE_EEPROM + i2c_dev->ast_i2c_data->slave_init(&(i2c_dev->slave_msgs)); + ast_slave_mode_enable(i2c_dev, i2c_dev->slave_msgs); ++#else ++ i2c_dev->slave_msgs = i2c_dev->slave_rx_msg; + #endif + + //Enable Master Mode +@@ -177,20 +184,20 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) + /* Set AC Timing */ + #if defined(CONFIG_ARCH_AST2400) + if(i2c_dev->ast_i2c_data->bus_clk/1000 > 400) { +- printk("high speed mode enable clk [%dkhz]\n",i2c_dev->ast_i2c_data->bus_clk/1000); ++ printk("high speed mode enable clk [%dkhz]\n",i2c_dev->ast_i2c_data->bus_clk/1000); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) | + AST_I2CD_M_HIGH_SPEED_EN | + AST_I2CD_M_SDA_DRIVE_1T_EN | +- AST_I2CD_SDA_DRIVE_1T_EN ++ AST_I2CD_SDA_DRIVE_1T_EN + , I2C_FUN_CTRL_REG); +- ++ + /* Set AC Timing */ + ast_i2c_write(i2c_dev, 0x3, I2C_AC_TIMING_REG2); +- ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); ++ ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); + }else { +- /* target apeed is xxKhz*/ ++ /* target apeed is xxKhz*/ + ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); +- ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2); ++ ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2); + } + #else + /* target apeed is xxKhz*/ +@@ -206,12 +213,12 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) + + //TODO + // ast_i2c_write(i2c_dev, 0xAF, I2C_INTR_CTRL_REG); +- //Enable Interrupt, STOP Interrupt has bug in AST2000 +- ++ //Enable Interrupt, STOP Interrupt has bug in AST2000 ++ + /* Set interrupt generation of I2C controller */ + ast_i2c_write(i2c_dev, +- AST_I2CD_SDA_DL_TO_INTR_EN | +- AST_I2CD_BUS_RECOVER_INTR_EN | ++ AST_I2CD_SDA_DL_TO_INTR_EN | ++ AST_I2CD_BUS_RECOVER_INTR_EN | + AST_I2CD_SMBUS_ALT_INTR_EN | + // AST_I2CD_SLAVE_MATCH_INTR_EN | + AST_I2CD_SCL_TO_INTR_EN | +@@ -230,16 +237,16 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) + static void ast_i2c_slave_buff_init(struct ast_i2c_dev *i2c_dev) + { + int i; +- //Tx buf 1 +- slave_tx_msg.len = I2C_S_BUF_SIZE; +- slave_tx_msg.buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); ++ //Tx buf 1 ++ i2c_dev->slave_tx_msg.len = I2C_S_BUF_SIZE; ++ i2c_dev->slave_tx_msg.buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); + //Rx buf 4 + for(i=0; i<I2C_S_RX_BUF_NUM+1; i++) { +- slave_rx_msg[i].addr = ~BUFF_ONGOING; +- slave_rx_msg[i].flags = 0; //mean empty buffer +- slave_rx_msg[i].len = I2C_S_BUF_SIZE; +- slave_rx_msg[i].buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); +- } ++ i2c_dev->slave_rx_msg[i].addr = ~BUFF_ONGOING; ++ i2c_dev->slave_rx_msg[i].flags = 0; //mean empty buffer ++ i2c_dev->slave_rx_msg[i].len = I2C_S_BUF_SIZE; ++ i2c_dev->slave_rx_msg[i].buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); ++ } + } + + static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) +@@ -247,13 +254,13 @@ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) + int i; + unsigned long flags; + +- spin_lock_irqsave(&slave_rx_lock, flags); +- ++ spin_lock_irqsave(&i2c_dev->slave_rx_lock, flags); ++ + switch(i2c_dev->slave_event) { + case I2C_SLAVE_EVENT_START_WRITE: + for(i=0; i<I2C_S_RX_BUF_NUM; i++) { +- if((slave_rx_msg[i].flags == 0) && (slave_rx_msg[i].addr != BUFF_ONGOING)) { +- slave_rx_msg[i].addr = BUFF_ONGOING; ++ if((i2c_dev->slave_rx_msg[i].flags == 0) && (i2c_dev->slave_rx_msg[i].addr != BUFF_ONGOING)) { ++ i2c_dev->slave_rx_msg[i].addr = BUFF_ONGOING; + break; + } + } +@@ -261,40 +268,40 @@ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) + printk("RX buffer full ........use tmp msgs buff \n"); + //TODO... + } +- printk("I2C_SLAVE_EVENT_START_WRITE ... %d \n", i); ++ //printk("I2C_SLAVE_EVENT_START_WRITE ... %d \n", i); + +- i2c_dev->slave_msgs = &slave_rx_msg[i]; ++ i2c_dev->slave_msgs = &i2c_dev->slave_rx_msg[i]; + break; + case I2C_SLAVE_EVENT_START_READ: +- printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); +- i2c_dev->slave_msgs = &slave_tx_msg; ++ //printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + case I2C_SLAVE_EVENT_WRITE: +- printk("I2C_SLAVE_EVENT_WRITE next write ERROR ...\n"); +- i2c_dev->slave_msgs = &slave_tx_msg; ++ //printk("I2C_SLAVE_EVENT_WRITE next write ERROR ...\n"); ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + case I2C_SLAVE_EVENT_READ: +- printk("I2C_SLAVE_EVENT_READ ERROR ... \n"); +- i2c_dev->slave_msgs = &slave_tx_msg; ++ printk("I2C_SLAVE_EVENT_READ ERROR ... \n"); ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + case I2C_SLAVE_EVENT_NACK: +- printk("I2C_SLAVE_EVENT_NACK ERROR ... \n"); +- i2c_dev->slave_msgs = &slave_tx_msg; ++ //printk("I2C_SLAVE_EVENT_NACK ERROR ... \n"); ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + case I2C_SLAVE_EVENT_STOP: +- printk("I2C_SLAVE_EVENT_STOP \n"); ++ //printk("I2C_SLAVE_EVENT_STOP \n"); + for(i=0; i<I2C_S_RX_BUF_NUM; i++) { +- if(slave_rx_msg[i].addr == BUFF_ONGOING) { +- slave_rx_msg[i].flags = BUFF_FULL; +- slave_rx_msg[i].addr = 0; ++ if(i2c_dev->slave_rx_msg[i].addr == BUFF_ONGOING) { ++ i2c_dev->slave_rx_msg[i].flags = BUFF_FULL; ++ i2c_dev->slave_rx_msg[i].addr = 0; + break; + } + } +- +- i2c_dev->slave_msgs = &slave_tx_msg; ++ ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + } +- spin_unlock_irqrestore(&slave_rx_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->slave_rx_lock, flags); + + } + +@@ -308,29 +315,29 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) + case 0: + // printk("slave read \n"); + //cur_msg = get_free_msg; +- spin_lock_irqsave(&slave_rx_lock, flags); ++ spin_lock_irqsave(&i2c_dev->slave_rx_lock, flags); + + for(i=0; i<I2C_S_RX_BUF_NUM; i++) { +- if((slave_rx_msg[i].addr == 0) && (slave_rx_msg[i].flags == BUFF_FULL)) { +- memcpy(msgs->buf, slave_rx_msg[i].buf, slave_rx_msg[i].len); +- msgs->len = slave_rx_msg[i].len; +- slave_rx_msg[i].flags = 0; +- slave_rx_msg[i].len = 0; ++ if((i2c_dev->slave_rx_msg[i].addr == 0) && (i2c_dev->slave_rx_msg[i].flags == BUFF_FULL)) { ++ memcpy(msgs->buf, i2c_dev->slave_rx_msg[i].buf, i2c_dev->slave_rx_msg[i].len); ++ msgs->len = i2c_dev->slave_rx_msg[i].len; ++ i2c_dev->slave_rx_msg[i].flags = 0; ++ i2c_dev->slave_rx_msg[i].len = 0; + break; + } + } +- spin_unlock_irqrestore(&slave_rx_lock, flags); +- ++ spin_unlock_irqrestore(&i2c_dev->slave_rx_lock, flags); ++ + if(i == I2C_S_RX_BUF_NUM) { +- printk("No buffer ........ \n"); ++ //printk("No buffer ........ \n"); + msgs->len = 0; + ret = -1; + } + break; + case I2C_M_RD: //slave write + // printk("slave write \n"); +- memcpy(msgs->buf, slave_tx_msg.buf, I2C_S_BUF_SIZE); +- break; ++ memcpy(msgs->buf, i2c_dev->slave_tx_msg.buf, I2C_S_BUF_SIZE); ++ break; + case I2C_S_EN: + if((msgs->addr < 0x1) || (msgs->addr > 0xff)) { + ret = -1; +@@ -352,7 +359,7 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) + default: + printk("slave xfer error \n"); + break; +- ++ + } + return ret; + } +@@ -360,16 +367,16 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) + + #endif + +-static u8 ++static u8 + ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + { + u32 sts; +- int r; ++ int r; + u32 i = 0; +- ++ + //Check 0x14's SDA and SCL status + sts = ast_i2c_read(i2c_dev,I2C_CMD_REG); +- ++ + if ((sts & AST_I2CD_SDA_LINE_STS) && (sts & AST_I2CD_SCL_LINE_STS)) { + //Means bus is idle. + dev_dbg(i2c_dev->dev, "I2C bus (%d) is idle. I2C slave doesn't exist?!\n", i2c_dev->bus_id); +@@ -377,11 +384,11 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + } + + dev_dbg(i2c_dev->dev, "ERROR!! I2C(%d) bus hanged, try to recovery it!\n", i2c_dev->bus_id); +- +- ++ ++ + if ((sts & AST_I2CD_SDA_LINE_STS) && !(sts & AST_I2CD_SCL_LINE_STS)) { + //if SDA == 1 and SCL == 0, it means the master is locking the bus. +- //Send a stop command to unlock the bus. ++ //Send a stop command to unlock the bus. + dev_dbg(i2c_dev->dev, "I2C's master is locking the bus, try to stop it.\n"); + // + init_completion(&i2c_dev->cmd_complete); +@@ -397,12 +404,12 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + dev_dbg(i2c_dev->dev, "recovery error \n"); + return -1; + } +- ++ + if (r == 0) { + dev_dbg(i2c_dev->dev, "recovery timed out\n"); + return -1; + } else { +- dev_dbg(i2c_dev->dev, "Recovery successfully\n"); ++ dev_dbg(i2c_dev->dev, "Recovery successfully\n"); + return 0; + } + +@@ -415,11 +422,11 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + for (i = 0; i < 10; i++) { + ast_i2c_dev_init(i2c_dev); + //Do the recovery command BIT11 +- init_completion(&i2c_dev->cmd_complete); ++ init_completion(&i2c_dev->cmd_complete); + ast_i2c_write(i2c_dev, AST_I2CD_BUS_RECOVER_CMD_EN, I2C_CMD_REG); +- ++ + r = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, +- i2c_dev->adap.timeout*HZ); ++ i2c_dev->adap.timeout*HZ); + if (i2c_dev->cmd_err != 0 && + i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { + dev_dbg(i2c_dev->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", i2c_dev->cmd_err); +@@ -438,31 +445,56 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + dev_dbg(i2c_dev->dev, "Don't know how to handle this case?!\n"); + return -1; + } +- dev_dbg(i2c_dev->dev, "Recovery successfully\n"); ++ dev_dbg(i2c_dev->dev, "Recovery successfully\n"); + return 0; + } + +-static void ast_master_alert_recv(struct ast_i2c_dev *i2c_dev) ++static void ast_master_alert_recv(struct ast_i2c_dev *i2c_dev) + { + printk("ast_master_alert_recv bus id %d, Disable Alt, Please Imple \n",i2c_dev->bus_id); + } + + static int ast_i2c_wait_bus_not_busy(struct ast_i2c_dev *i2c_dev) + { +- int timeout = 32; //TODO number ++ int timeout = 10; //TODO number ++ volatile u8 mode = 0; + // printk("ast_i2c_wait_bus_not_busy \n"); ++ ++ // Wait for slave transfer to finish ++ mode = i2c_dev->slave_operation; ++ while (mode == 1) { ++ if (timeout <= 0) { ++ break; ++ } ++ mode = i2c_dev->slave_operation; ++ timeout--; ++ msleep(1); ++ } ++ ++ if (timeout <= 0) { ++ return -EAGAIN; ++ } ++ ++ // Wait for Bus to go IDLE ++ timeout = 10; + while (ast_i2c_read(i2c_dev,I2C_CMD_REG) & AST_I2CD_BUS_BUSY_STS) { +- ast_i2c_bus_error_recover(i2c_dev); +- if(timeout<=0) ++ if(timeout<=0) { + break; ++ } ++ + timeout--; +- msleep(2); ++ msleep(1); + } + +- return timeout <= 0 ? EAGAIN : 0; ++ if (timeout <=0) { ++ ast_i2c_bus_error_recover(i2c_dev); ++ return 0; ++ } ++ ++ return 0; + } + +-static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) ++static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + { + u32 cmd = 0; + int i; +@@ -470,49 +502,49 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + i2c_dev->master_xfer_mode = DMA_XFER; + i2c_dev->slave_xfer_mode = DMA_XFER; + +- if(i2c_dev->slave_operation == 1) { ++ if(i2c_dev->slave_operation == 1) { + if(i2c_dev->slave_msgs->flags & I2C_M_RD) { + //DMA tx mode + if(i2c_dev->slave_msgs->len > AST_I2C_DMA_SIZE) + i2c_dev->slave_xfer_len = AST_I2C_DMA_SIZE; +- else ++ else + i2c_dev->slave_xfer_len = i2c_dev->slave_msgs->len; +- ++ + dev_dbg(i2c_dev->dev, "(<--) slave tx DMA \n"); + for(i=0; i<i2c_dev->slave_xfer_len; i++) + i2c_dev->dma_buf[i] = i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt + i]; +- ++ + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); + ast_i2c_write(i2c_dev, (i2c_dev->slave_xfer_len-1), I2C_DMA_LEN_REG); +- ast_i2c_write(i2c_dev, AST_I2CD_TX_DMA_ENABLE | AST_I2CD_S_TX_CMD,I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_TX_DMA_ENABLE | AST_I2CD_S_TX_CMD,I2C_CMD_REG); + } else { + //DMA prepare rx + dev_dbg(i2c_dev->dev, "(-->) slave rx DMA \n"); + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); + ast_i2c_write(i2c_dev, (AST_I2C_DMA_SIZE-1), I2C_DMA_LEN_REG); +- ast_i2c_write(i2c_dev, AST_I2CD_RX_DMA_ENABLE, I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_RX_DMA_ENABLE, I2C_CMD_REG); + } + } else { + dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); + if(i2c_dev->master_xfer_cnt == -1) { +- //send start ++ //send start + dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n", + i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write", + i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "", + i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr); + + if(i2c_dev->master_msgs->flags & I2C_M_RD) { +- //workaround .. HW can;t send start read addr with buff mode ++ //workaround .. HW can;t send start read addr with buff mode + cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD; + ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); + + // tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 + i2c_dev->master_xfer_len = 1; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { + //tx +- cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_DMA_ENABLE; ++ cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_DMA_ENABLE; + + i2c_dev->dma_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 + //next data write +@@ -520,44 +552,44 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE; + else + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len + 1; +- ++ + for(i = 1; i < i2c_dev->master_xfer_len; i++) + i2c_dev->dma_buf[i] = i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt+i]; +- ++ + if (i2c_dev->xfer_last == 1) { + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); + ast_i2c_write(i2c_dev, (i2c_dev->master_xfer_len-1), I2C_DMA_LEN_REG); +- ++ + } +- ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); + dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); + + } else if (i2c_dev->master_xfer_cnt < i2c_dev->master_msgs->len){ +- //Next send ++ //Next send + if(i2c_dev->master_msgs->flags & I2C_M_RD) { + //Rx data + cmd = AST_I2CD_M_RX_CMD | AST_I2CD_RX_DMA_ENABLE; +- ++ + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > AST_I2C_DMA_SIZE) { + i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); +- ++ + } else { + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt; + if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { + dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n"); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { + #ifdef CONFIG_AST1010 + //Workaround for ast1010 can't send NACK +@@ -568,7 +600,7 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + i2c_dev->master_xfer_mode = BYTE_XFER; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & + ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); +- ++ + } else if (i2c_dev->master_xfer_len > 1) { + i2c_dev->master_xfer_len -=1; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +@@ -578,8 +610,8 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + } + #else + if(i2c_dev->xfer_last == 1) { +- dev_dbg(i2c_dev->dev, "last stop \n"); +- cmd |= AST_I2CD_M_STOP_CMD; ++ dev_dbg(i2c_dev->dev, "last stop \n"); ++ cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & + ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { +@@ -588,9 +620,9 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + } + //TODO check.... + cmd |= AST_I2CD_M_S_RX_CMD_LAST; +-#endif ++#endif + } +- ++ + } + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); + ast_i2c_write(i2c_dev, i2c_dev->master_xfer_len-1, I2C_DMA_LEN_REG); +@@ -603,23 +635,23 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > AST_I2C_DMA_SIZE) { + i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt; + if(i2c_dev->xfer_last == 1) { + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } + } + +- for(i = 0; i < i2c_dev->master_xfer_len; i++) ++ for(i = 0; i < i2c_dev->master_xfer_len; i++) + i2c_dev->dma_buf[i] = i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i]; + + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); +@@ -627,33 +659,33 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + ast_i2c_write(i2c_dev, cmd , I2C_CMD_REG); + dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); + +- } ++ } + }else { +- //should send next msg ++ //should send next msg + if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) + printk("complete rx ... bus=%d addr=0x%x (%d vs. %d) ERROR\n", + i2c_dev->bus_id, i2c_dev->master_msgs->addr, + i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); +- ++ + dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n"); + i2c_dev->cmd_err = 0; +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + } +- ++ + } + +- ++ + } + +-static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) ++static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + { + u32 cmd = 0; + int i; + u32 *tx_buf; + + i2c_dev->master_xfer_mode = BUFF_XFER; +- i2c_dev->slave_xfer_mode = BUFF_XFER; +- ++ i2c_dev->slave_xfer_mode = BUFF_XFER; ++ + #if defined(CONFIG_ARCH_AST2400) + ast_i2c_write(i2c_dev, + (ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) & +@@ -665,15 +697,15 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + tx_buf = (u32 *) i2c_dev->req_page->page_addr; + + +- if(i2c_dev->slave_operation == 1) { ++ if(i2c_dev->slave_operation == 1) { + if(i2c_dev->slave_msgs->flags & I2C_M_RD) { + dev_dbg(i2c_dev->dev, "(<--) slave tx buf \n"); +- ++ + if(i2c_dev->slave_msgs->len > i2c_dev->req_page->page_size) + i2c_dev->slave_xfer_len = i2c_dev->req_page->page_size; + else + i2c_dev->slave_xfer_len = i2c_dev->slave_msgs->len; +- ++ + for(i = 0; i< i2c_dev->slave_xfer_len; i++) { + if(i%4 == 0) + tx_buf[i/4] = 0; +@@ -681,80 +713,80 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + dev_dbg(i2c_dev->dev, "[%x] ",tx_buf[i/4]); + } + dev_dbg(i2c_dev->dev, "\n"); +- +- ast_i2c_write(i2c_dev, AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->slave_xfer_len-1)) | +- AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)), ++ ++ ast_i2c_write(i2c_dev, AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->slave_xfer_len-1)) | ++ AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)), + I2C_BUF_CTRL_REG); +- ++ + ast_i2c_write(i2c_dev, AST_I2CD_TX_BUFF_ENABLE | AST_I2CD_S_TX_CMD, I2C_CMD_REG); + } else { + //prepare for new rx + dev_dbg(i2c_dev->dev, "(-->) slave prepare rx buf \n"); +- ast_i2c_write(i2c_dev, ++ ast_i2c_write(i2c_dev, + AST_I2CD_RX_BUF_END_ADDR_SET((i2c_dev->req_page->page_size-1)) | + AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)), + I2C_BUF_CTRL_REG); + +- ast_i2c_write(i2c_dev, AST_I2CD_RX_BUFF_ENABLE, I2C_CMD_REG); +- ++ ast_i2c_write(i2c_dev, AST_I2CD_RX_BUFF_ENABLE, I2C_CMD_REG); ++ + } + } else { + dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); + if(i2c_dev->master_xfer_cnt == -1) { +- //send start ++ //send start + dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n", + i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write", + i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "", + i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr); + + if(i2c_dev->master_msgs->flags & I2C_M_RD) { +-//workaround .. HW can;t send start read addr with buff mode ++//workaround .. HW can;t send start read addr with buff mode + cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD; + ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); + + // tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 + i2c_dev->master_xfer_len = 1; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { +- cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_BUFF_ENABLE; ++ cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_BUFF_ENABLE; + tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 + //next data write + if((i2c_dev->master_msgs->len + 1) > i2c_dev->req_page->page_size) + i2c_dev->master_xfer_len = i2c_dev->req_page->page_size; + else + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len + 1; +- ++ + for(i = 1; i < i2c_dev->master_xfer_len; i++) { + if(i%4 == 0) + tx_buf[i/4] = 0; + tx_buf[i/4] |= (i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] << ((i%4)*8)) ; + } +- ++ + if (i2c_dev->xfer_last == 1) { + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } +- ast_i2c_write(i2c_dev, ++ ast_i2c_write(i2c_dev, + AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->master_xfer_len - 1)) | + AST_I2CD_BUF_BASE_ADDR_SET(i2c_dev->req_page->page_addr_point), + I2C_BUF_CTRL_REG); + } +- ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); + dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); + + } else if (i2c_dev->master_xfer_cnt < i2c_dev->master_msgs->len){ +- //Next send ++ //Next send + if(i2c_dev->master_msgs->flags & I2C_M_RD) { + //Rx data + cmd = AST_I2CD_M_RX_CMD | AST_I2CD_RX_BUFF_ENABLE; +- ++ + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > i2c_dev->req_page->page_size) { + i2c_dev->master_xfer_len = i2c_dev->req_page->page_size; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +@@ -764,11 +796,11 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { + dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n"); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { + if(i2c_dev->xfer_last == 1) { +- dev_dbg(i2c_dev->dev, "last stop \n"); +- cmd |= AST_I2CD_M_STOP_CMD; ++ dev_dbg(i2c_dev->dev, "last stop \n"); ++ cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & + ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { +@@ -791,46 +823,46 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > i2c_dev->req_page->page_size) { + i2c_dev->master_xfer_len = i2c_dev->req_page->page_size; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt; + if(i2c_dev->xfer_last == 1) { + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } + } +- ++ + for(i = 0; i < i2c_dev->master_xfer_len; i++) { + if(i%4 == 0) + tx_buf[i/4] = 0; + tx_buf[i/4] |= (i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] << ((i%4)*8)) ; + } +-// printk("count %x \n",ast_i2c_read(i2c_dev,I2C_CMD_REG)); +- ast_i2c_write(i2c_dev, ++// printk("count %x \n",ast_i2c_read(i2c_dev,I2C_CMD_REG)); ++ ast_i2c_write(i2c_dev, + AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->master_xfer_len - 1)) | + AST_I2CD_BUF_BASE_ADDR_SET(i2c_dev->req_page->page_addr_point), + I2C_BUF_CTRL_REG); +- ++ + ast_i2c_write(i2c_dev, cmd , I2C_CMD_REG); + dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); + } + } else { +- //should send next msg ++ //should send next msg + if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) + printk("complete rx ... bus=%d addr=0x%x (%d vs. %d) ERROR\n", + i2c_dev->bus_id, i2c_dev->master_msgs->addr, + i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); +- ++ + dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n"); + i2c_dev->cmd_err = 0; +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + } + + } +@@ -843,16 +875,16 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + i2c_dev->master_xfer_mode = BYTE_XFER; + i2c_dev->master_xfer_len = 1; + +- i2c_dev->slave_xfer_mode = BYTE_XFER; ++ i2c_dev->slave_xfer_mode = BYTE_XFER; + i2c_dev->slave_xfer_len = 1; +- +- if(i2c_dev->slave_operation == 1) { ++ ++ if(i2c_dev->slave_operation == 1) { + dev_dbg(i2c_dev->dev,"S cnt %d, xf len %d \n",i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->len); + if(i2c_dev->slave_msgs->flags & I2C_M_RD) { + //READ <-- TX + dev_dbg(i2c_dev->dev, "(<--) slave(tx) buf %d [%x]\n", i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt]); + ast_i2c_write(i2c_dev, i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt], I2C_BYTE_BUF_REG); +- ast_i2c_write(i2c_dev, AST_I2CD_S_TX_CMD, I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_S_TX_CMD, I2C_CMD_REG); + } else { + // Write -->Rx + //no need to handle in byte mode +@@ -862,21 +894,21 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + } else { + dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); + if(i2c_dev->master_xfer_cnt == -1) { +- //first start ++ //first start + dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n", + i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write", + i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "", + i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr); +- +- +- if(i2c_dev->master_msgs->flags & I2C_M_RD) ++ ++ ++ if(i2c_dev->master_msgs->flags & I2C_M_RD) + ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); + else + ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1), I2C_BYTE_BUF_REG); + + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD | AST_I2CD_M_START_CMD, I2C_CMD_REG); + + +@@ -888,7 +920,7 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->master_xfer_cnt == 0)) { + dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n"); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + + } else if((i2c_dev->xfer_last == 1) && (i2c_dev->master_xfer_cnt + 1 == i2c_dev->master_msgs->len)) { + cmd |= AST_I2CD_M_S_RX_CMD_LAST | AST_I2CD_M_STOP_CMD; +@@ -897,11 +929,11 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } + + dev_dbg(i2c_dev->dev, "(<--) rx byte, cmd = %x \n",cmd); +- ++ + ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); + + +@@ -911,29 +943,29 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + ast_i2c_write(i2c_dev, *(xfer_buf + i2c_dev->master_xfer_cnt), I2C_BYTE_BUF_REG); + if((i2c_dev->xfer_last == 1) && (i2c_dev->master_xfer_cnt + 1 == i2c_dev->master_msgs->len)) { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD | AST_I2CD_M_STOP_CMD, I2C_CMD_REG); + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD, I2C_CMD_REG); + } + } +- ++ + } else { +- //should send next msg ++ //should send next msg + if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) + printk("CNT ERROR bus=%d addr=0x%x (%d vs. %d)\n", + i2c_dev->bus_id, i2c_dev->master_msgs->addr, + i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); +- ++ + dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n"); + i2c_dev->cmd_err = 0; +- complete(&i2c_dev->cmd_complete); +- ++ complete(&i2c_dev->cmd_complete); ++ + } + } +- ++ + } + + static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) +@@ -941,8 +973,8 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + u32 xfer_len; + int i; + u8 *rx_buf; +- +- dev_dbg(i2c_dev->dev, "ast_i2c_slave_xfer_done [%d]\n",i2c_dev->slave_xfer_mode); ++ ++ dev_dbg(i2c_dev->dev, "ast_i2c_slave_xfer_done [%d]\n",i2c_dev->slave_xfer_mode); + + if (i2c_dev->slave_msgs->flags & I2C_M_RD) { + //tx done , only check tx count ... +@@ -979,16 +1011,16 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); + if(xfer_len == 0) + xfer_len = AST_I2C_PAGE_SIZE; +- ++ + dev_dbg(i2c_dev->dev,"rx buff done len %d \n",xfer_len); +- ++ + rx_buf = (u8 *)i2c_dev->req_page->page_addr; +- ++ + for(i=0;i<xfer_len;i++) { + i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i] = rx_buf[i]; + dev_dbg(i2c_dev->dev,"%d, [%x] \n",i2c_dev->slave_xfer_cnt+i ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i]); + } +- ++ + } else { + //RX DMA DOWN + xfer_len = ast_i2c_read(i2c_dev, I2C_DMA_LEN_REG); +@@ -996,15 +1028,15 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + xfer_len = i2c_dev->slave_xfer_len; + else + xfer_len = i2c_dev->slave_xfer_len - xfer_len - 1; +- ++ + dev_dbg(i2c_dev->dev, " rx dma done len %d \n", xfer_len); +- ++ + for(i=0;i<xfer_len;i++) { + i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i] = i2c_dev->dma_buf[i]; + dev_dbg(i2c_dev->dev,"%d, [%x] \n",i2c_dev->slave_xfer_cnt+i ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i]); + } + } +- ++ + } + + if(xfer_len !=i2c_dev->slave_xfer_len) { +@@ -1012,7 +1044,7 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + printk(" **slave xfer error ====\n"); + //should goto stop.... + } else +- i2c_dev->slave_xfer_cnt += i2c_dev->slave_xfer_len; ++ i2c_dev->slave_xfer_cnt += i2c_dev->slave_xfer_len; + + + if((i2c_dev->slave_event == I2C_SLAVE_EVENT_NACK) || (i2c_dev->slave_event == I2C_SLAVE_EVENT_STOP)) { +@@ -1020,33 +1052,33 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + ast_i2c_slave_rdwr_xfer(i2c_dev); + #else + i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); +-#endif ++#endif + i2c_dev->slave_xfer_cnt = 0; + } else { + if(i2c_dev->slave_xfer_cnt == i2c_dev->slave_msgs->len) { +- dev_dbg(i2c_dev->dev,"slave next msgs \n"); ++ dev_dbg(i2c_dev->dev,"slave next msgs \n"); + #ifdef CONFIG_AST_I2C_SLAVE_RDWR + ast_i2c_slave_rdwr_xfer(i2c_dev); + #else + i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); +-#endif ++#endif + + i2c_dev->slave_xfer_cnt = 0; +- } ++ } + i2c_dev->do_slave_xfer(i2c_dev); + } + + + if(AST_I2CD_IDLE == i2c_dev->state) { +- dev_dbg(i2c_dev->dev,"** Slave go IDLE **\n"); ++ dev_dbg(i2c_dev->dev,"** Slave go IDLE **\n"); + i2c_dev->slave_operation = 0; +- ++ + if(i2c_dev->slave_xfer_mode == BUFF_XFER) { + i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page); +- } +- +- } +- ++ } ++ ++ } ++ + } + + //TX/Rx Done +@@ -1057,7 +1089,7 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + u8 *pool_buf; + unsigned long flags; + +- spin_lock_irqsave(&g_master_lock, flags); ++ spin_lock_irqsave(&i2c_dev->master_lock, flags); + + /* + * This function shall be involked during interrupt handling. +@@ -1068,8 +1100,8 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + goto unlock_out; + } + +- dev_dbg(i2c_dev->dev, "ast_i2c_master_xfer_done mode[%d]\n",i2c_dev->master_xfer_mode); +- ++ dev_dbg(i2c_dev->dev, "ast_i2c_master_xfer_done mode[%d]\n",i2c_dev->master_xfer_mode); ++ + if (i2c_dev->master_msgs->flags & I2C_M_RD) { + if(i2c_dev->master_xfer_cnt == -1) { + xfer_len = 1; +@@ -1077,16 +1109,16 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + } + if(i2c_dev->master_xfer_mode == BYTE_XFER) { + if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { +- i2c_dev->master_msgs->len += (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; ++ i2c_dev->master_msgs->len += (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; + i2c_dev->blk_r_flag = 1; +- dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); ++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); + } + xfer_len = 1; + i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt] = (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; + } else if (i2c_dev->master_xfer_mode == BUFF_XFER) { + pool_buf = (u8 *)i2c_dev->req_page->page_addr; + xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); +- ++ + if(xfer_len == 0) + xfer_len = AST_I2C_PAGE_SIZE; + +@@ -1098,7 +1130,7 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { + i2c_dev->master_msgs->len += pool_buf[0]; + i2c_dev->blk_r_flag = 1; +- dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); ++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); + } + } else { + //DMA Mode +@@ -1114,13 +1146,13 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + dev_dbg(i2c_dev->dev, "buf[%x] \n", i2c_dev->dma_buf[i]); + dev_dbg(i2c_dev->dev, "buf[%x] \n", i2c_dev->dma_buf[i+1]); + } +- ++ + if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { + i2c_dev->master_msgs->len += i2c_dev->dma_buf[0]; + i2c_dev->blk_r_flag = 1; +- dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); ++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); + } +- ++ + } + + }else { +@@ -1153,28 +1185,28 @@ next_xfer: + i2c_dev->cmd_err = 1; + goto done_out; + } else +- i2c_dev->master_xfer_cnt += i2c_dev->master_xfer_len; ++ i2c_dev->master_xfer_cnt += i2c_dev->master_xfer_len; + + if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) { + dev_dbg(i2c_dev->dev,"do next cnt \n"); + i2c_dev->do_master_xfer(i2c_dev); + } else { +-#if 0 +- int i; ++#if 0 ++ int i; + printk(" ===== \n"); + for(i=0;i<i2c_dev->master_msgs->len;i++) + printk("rx buf i,[%x]\n",i,i2c_dev->master_msgs->buf[i]); +- printk(" ===== \n"); +-#endif ++ printk(" ===== \n"); ++#endif + i2c_dev->cmd_err = 0; + + done_out: + dev_dbg(i2c_dev->dev,"msgs complete \n"); +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + } + + unlock_out: +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + } + + static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) +@@ -1187,7 +1219,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + i2c_dev->slave_msgs->buf[0] = match; + dev_dbg(i2c_dev->dev, "S Start Addr match [%x] \n",match); + +- ++ + if(match & 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_START_READ; + } else { +@@ -1201,7 +1233,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + #else + i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); + i2c_dev->slave_xfer_cnt = 0; +-#endif ++#endif + + //request + if(i2c_dev->ast_i2c_data->slave_dma == BYTE_MODE) +@@ -1211,7 +1243,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + else { + if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) + i2c_dev->do_slave_xfer = ast_i2c_do_pool_xfer; +- else ++ else + i2c_dev->do_slave_xfer = ast_i2c_do_byte_xfer; + } + +@@ -1221,7 +1253,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + + static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + { +- u32 sts; ++ u32 sts; + + struct ast_i2c_dev *i2c_dev = dev_id; + u32 isr_sts = readl(i2c_dev->ast_i2c_data->reg_gr); +@@ -1231,7 +1263,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + + i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; + sts = ast_i2c_read(i2c_dev,I2C_INTR_STS_REG); +-// printk("ISR : %x , sts [%x]\n",sts , xfer_sts); ++// printk("ISR : %x , sts [%x]\n",sts , xfer_sts); + // dev_dbg(i2c_dev->dev,"ISR : %x , sts [%x]\n",sts , xfer_sts); + + // dev_dbg(i2c_dev->dev,"sts machine %x, slave_op %d \n", xfer_sts,i2c_dev->slave_operation); +@@ -1244,9 +1276,9 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + I2C_INTR_CTRL_REG); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SMBUS_ALT, I2C_INTR_STS_REG); + ast_master_alert_recv(i2c_dev); +- sts &= ~AST_I2CD_SMBUS_ALT_INTR_EN; ++ sts &= ~AST_I2CD_SMBUS_ALT_INTR_EN; + } +- ++ + if(AST_I2CD_INTR_STS_ABNORMAL & sts) { + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ABNORMAL; + // Turn off interrupts for further abnormal +@@ -1257,6 +1289,8 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + I2C_INTR_CTRL_REG); + complete(&i2c_dev->cmd_complete); + sts &= ~AST_I2CD_INTR_STS_ABNORMAL; ++ // Need to clear the interrupt ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ABNORMAL, I2C_INTR_STS_REG); + } + + switch(sts) { +@@ -1265,7 +1299,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + i2c_dev->slave_event = I2C_SLAVE_EVENT_READ; + ast_i2c_slave_xfer_done(i2c_dev); + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); +@@ -1280,9 +1314,17 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_master_xfer_done(i2c_dev); +- ++ + } else { +- printk("TODO ...\n"); ++ printk("ast_i2c: TX_ACK | NORMAL_STOP; xfer_last %d\n", i2c_dev->xfer_last); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ uint32_t new_val = ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | ++ AST_I2CD_NORMAL_STOP_INTR_EN | ++ AST_I2CD_TX_ACK_INTR_EN; ++ ast_i2c_write(i2c_dev, new_val, I2C_INTR_CTRL_REG); ++ //take care ++ i2c_dev->cmd_err |= AST_LOCKUP_DETECTED; ++ complete(&i2c_dev->cmd_complete); + } + break; + +@@ -1291,8 +1333,8 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; + ast_i2c_slave_xfer_done(i2c_dev); + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); +- ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); ++ + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); +@@ -1310,7 +1352,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP: + if(i2c_dev->slave_operation == 1) { + printk("SLAVE TODO .... \n"); +- ++ + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK| AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); +@@ -1320,47 +1362,47 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + } + break; + +- //Issue : Workaround for I2C slave mode ++ //Issue : Workaround for I2C slave mode + case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH: + if(i2c_dev->slave_operation == 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; + ast_i2c_slave_xfer_done(i2c_dev); + ast_i2c_slave_addr_match(i2c_dev); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); + } else { + printk("ERROR !!!!\n"); + } + break; + case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH: + ast_i2c_slave_addr_match(i2c_dev); +- dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts); ++ dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); + break; +- ++ + case AST_I2CD_INTR_STS_RX_DOWN: + if(i2c_dev->slave_operation == 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_WRITE; + ast_i2c_slave_xfer_done(i2c_dev); + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); + ast_i2c_master_xfer_done(i2c_dev); +- ++ + } + break; +- ++ + case AST_I2CD_INTR_STS_NORMAL_STOP: + if(i2c_dev->slave_operation == 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_STOP; + ast_i2c_slave_xfer_done(i2c_dev); + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + dev_dbg(i2c_dev->dev, "state [%x] \n",i2c_dev->state); +- } else { ++ } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_NORMAL_STOP; + complete(&i2c_dev->cmd_complete); + } +@@ -1380,24 +1422,24 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + break; + case AST_I2CD_INTR_STS_SCL_TO: + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SCL_TO; +- complete(&i2c_dev->cmd_complete); +- ++ complete(&i2c_dev->cmd_complete); ++ + break; + case AST_I2CD_INTR_STS_GCALL_ADDR: + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_GCALL_ADDR; +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + + break; + case AST_I2CD_INTR_STS_SMBUS_DEF_ADDR: + break; + case AST_I2CD_INTR_STS_SMBUS_DEV_ALT: +- ++ + break; +- ++ + case AST_I2CD_INTR_STS_SMBUS_ARP_ADDR: + break; + case AST_I2CD_INTR_STS_SDA_DL_TO: +@@ -1405,25 +1447,50 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + case AST_I2CD_INTR_STS_BUS_RECOVER: + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_BUS_RECOVER= %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_BUS_RECOVER, I2C_INTR_STS_REG); +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + break; + default: +- if(sts) +- printk("GR %x : No one care : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); +- return IRQ_NONE; ++ //TODO: Clearing this interrupt for now, but needs to cleanup this ISR function ++ ast_i2c_write(i2c_dev, sts, I2C_INTR_STS_REG); ++ ++ // Handle Arbitration Loss ++ if (sts & AST_I2CD_INTR_STS_ARBIT_LOSS) { ++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; ++ complete(&i2c_dev->cmd_complete); ++ sts &= (~AST_I2CD_INTR_STS_ARBIT_LOSS); ++ } ++ ++ // Handle the write transaction ACK ++ if (sts & AST_I2CD_INTR_STS_TX_ACK) { ++ ast_i2c_master_xfer_done(i2c_dev); ++ complete(&i2c_dev->cmd_complete); ++ sts &= (~AST_I2CD_INTR_STS_TX_ACK); ++ } ++ ++ // Handle the Slave address match ++ if (sts & AST_I2CD_INTR_STS_SLAVE_MATCH) { ++ ast_i2c_slave_addr_match(i2c_dev); ++ sts &= (~AST_I2CD_INTR_STS_SLAVE_MATCH); ++ } ++ ++ // TODO: Debug print for any unhandled condition ++ if(sts) { ++ printk("GR %x : Status : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); ++ } ++ ++ return IRQ_HANDLED; + } + + return IRQ_HANDLED; +- + } + + static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msgs, int num) + { + int i; +- int ret = 1; ++ int ret = 1; + unsigned long flags; + +- spin_lock_irqsave(&g_master_lock, flags); ++ spin_lock_irqsave(&i2c_dev->master_lock, flags); + + //request + if(i2c_dev->ast_i2c_data->master_dma == BYTE_MODE) +@@ -1433,7 +1500,7 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg + else { + if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) + i2c_dev->do_master_xfer = ast_i2c_do_pool_xfer; +- else ++ else + i2c_dev->do_master_xfer = ast_i2c_do_byte_xfer; + } + +@@ -1458,12 +1525,12 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg + + i2c_dev->do_master_xfer(i2c_dev); + +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + + ret = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, + i2c_dev->adap.timeout*HZ); +- +- spin_lock_irqsave(&g_master_lock, flags); ++ ++ spin_lock_irqsave(&i2c_dev->master_lock, flags); + i2c_dev->master_msgs = NULL; + + if (ret == 0) { +@@ -1471,25 +1538,30 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg + i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; + // printk("sts [%x], isr sts [%x] \n",i2c_dev->state, ast_i2c_read(i2c_dev,I2C_INTR_STS_REG)); + ret = -ETIMEDOUT; +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + goto stop; + } +- ++ + if(i2c_dev->cmd_err != 0 && + i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { ++ if (i2c_dev->cmd_err & AST_LOCKUP_DETECTED) { ++ printk("ast-i2c: error got unexpected STOP\n"); ++ // reset the bus ++ ast_i2c_bus_error_recover(i2c_dev); ++ } + ret = -EAGAIN; +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + goto stop; + } + } + +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + + if(i2c_dev->cmd_err == 0 || + i2c_dev->cmd_err == AST_I2CD_INTR_STS_NORMAL_STOP) { + ret = num; + goto out; +- ++ + } + stop: + init_completion(&i2c_dev->cmd_complete); +@@ -1503,8 +1575,8 @@ out: + //Free .. + if(i2c_dev->master_xfer_mode == BUFF_XFER) { + i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page); +- +- } ++ ++ } + dev_dbg(i2c_dev->dev, "end xfer ret = %d, xfer mode[%d]\n",ret, i2c_dev->master_xfer_mode); + return ret; + +@@ -1521,7 +1593,7 @@ static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + /* + * Wait for the bus to become free. + */ +- ++ + ret = ast_i2c_wait_bus_not_busy(i2c_dev); + if (ret) { + dev_err(&i2c_dev->adap.dev, "i2c_ast: timeout waiting for bus free\n"); +@@ -1536,7 +1608,7 @@ static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + dev_dbg(&adap->dev, "Retrying transmission [%d]\n",i); + udelay(100); + } +- ++ + ret = -EREMOTEIO; + out: + +@@ -1550,9 +1622,9 @@ static u32 ast_i2c_functionality(struct i2c_adapter *adap) + + static const struct i2c_algorithm i2c_ast_algorithm = { + .master_xfer = ast_i2c_xfer, +-#ifdef CONFIG_AST_I2C_SLAVE_RDWR ++#ifdef CONFIG_AST_I2C_SLAVE_RDWR + .slave_xfer = ast_i2c_slave_xfer, +-#endif ++#endif + .functionality = ast_i2c_functionality, + }; + +@@ -1572,23 +1644,23 @@ static int ast_i2c_probe(struct platform_device *pdev) + + i2c_dev->ast_i2c_data = pdev->dev.platform_data; + if(i2c_dev->ast_i2c_data->master_dma == BUFF_MODE) { +- dev_dbg(&pdev->dev, "use buffer pool mode 256\n"); +- ++ dev_dbg(&pdev->dev, "use buffer pool mode 256\n"); ++ + } else if ((i2c_dev->ast_i2c_data->master_dma == DMA_MODE) || (i2c_dev->ast_i2c_data->slave_dma == DMA_MODE)) { +- dev_dbg(&pdev->dev, "use dma mode \n"); ++ dev_dbg(&pdev->dev, "use dma mode \n"); + if (!i2c_dev->dma_buf) { + i2c_dev->dma_buf = dma_alloc_coherent(NULL, AST_I2C_DMA_SIZE, &i2c_dev->dma_addr, GFP_KERNEL); + if (!i2c_dev->dma_buf) { + printk("unable to allocate tx Buffer memory\n"); + ret = -ENOMEM; +- goto err_no_dma; ++ goto err_no_dma; + } + if(i2c_dev->dma_addr%4 !=0) { + printk("not 4 byte boundary \n"); + ret = -ENOMEM; +- goto err_no_dma; +- } +-// printk("dma_buf = [0x%x] dma_addr = [0x%x], please check 4byte boundary \n",i2c_dev->dma_buf,i2c_dev->dma_addr); ++ goto err_no_dma; ++ } ++// printk("dma_buf = [0x%x] dma_addr = [0x%x], please check 4byte boundary \n",i2c_dev->dma_buf,i2c_dev->dma_addr); + memset (i2c_dev->dma_buf, 0, AST_I2C_DMA_SIZE); + } + +@@ -1596,7 +1668,7 @@ static int ast_i2c_probe(struct platform_device *pdev) + //master_mode 0: use byte mode + dev_dbg(&pdev->dev, "use default byte mode \n"); + } +- ++ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (NULL == res) { + dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n"); +@@ -1628,11 +1700,11 @@ static int ast_i2c_probe(struct platform_device *pdev) + if(i2c_dev->irq == IRQ_C0_I2C) { + i2c_dev->bus_id = pdev->id - NUM_BUS; + dev_dbg(&pdev->dev, "C0 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); +-#if (CONFIG_AST1070_NR >= 2) ++#if (CONFIG_AST1070_NR >= 2) + } else if(i2c_dev->irq == IRQ_C1_I2C) { + i2c_dev->bus_id = pdev->id - (NUM_BUS + 8); +- dev_dbg(&pdev->dev, "C1 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); +-#endif ++ dev_dbg(&pdev->dev, "C1 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); ++#endif + } else { + i2c_dev->bus_id = pdev->id; + dev_dbg(&pdev->dev, "AST pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); +@@ -1644,13 +1716,13 @@ static int ast_i2c_probe(struct platform_device *pdev) + /* Initialize the I2C adapter */ + i2c_dev->adap.owner = THIS_MODULE; + //TODO +- i2c_dev->adap.retries = 0; ++ i2c_dev->adap.retries = 0; + +-// i2c_dev->adap.retries = 3; ++// i2c_dev->adap.retries = 3; + +- i2c_dev->adap.timeout = 5; ++ i2c_dev->adap.timeout = 5; + +- i2c_dev->master_xfer_mode = BYTE_XFER; ++ i2c_dev->master_xfer_mode = BYTE_XFER; + + /* + * If "pdev->id" is negative we consider it as zero. +@@ -1662,7 +1734,7 @@ static int ast_i2c_probe(struct platform_device *pdev) + i2c_dev->adap.nr); + + i2c_dev->slave_operation = 0; +- i2c_dev->blk_r_flag = 0; ++ i2c_dev->blk_r_flag = 0; + i2c_dev->adap.algo = &i2c_ast_algorithm; + + ast_i2c_dev_init(i2c_dev); +@@ -1674,8 +1746,11 @@ static int ast_i2c_probe(struct platform_device *pdev) + goto ereqirq; + } + ++ spin_lock_init(&i2c_dev->master_lock); ++ + #ifdef CONFIG_AST_I2C_SLAVE_RDWR + ast_i2c_slave_buff_init(i2c_dev); ++ spin_lock_init(&i2c_dev->slave_rx_lock); + #endif + + i2c_dev->adap.algo_data = i2c_dev; +@@ -1718,7 +1793,7 @@ static int ast_i2c_remove(struct platform_device *pdev) + + platform_set_drvdata(pdev, NULL); + i2c_del_adapter(&i2c_dev->adap); +- ++ + free_irq(i2c_dev->irq, i2c_dev); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -1742,7 +1817,7 @@ static int ast_i2c_resume(struct platform_device *pdev) + { + //TODO + // struct ast_i2c_dev *i2c_dev = platform_get_drvdata(pdev); +- //Should reset i2c ??? ++ //Should reset i2c ??? + return 0; + } + #else +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/i2c-core.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/i2c-core.c +index c8e3cf6..06d9042 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/i2c-core.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/i2c-core.c +@@ -1064,7 +1064,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) + EXPORT_SYMBOL(i2c_transfer); + + #ifdef CONFIG_AST_I2C_SLAVE_RDWR +-int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs) ++int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + { + unsigned long orig_jiffies; + int ret, try; +@@ -1075,9 +1075,18 @@ int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs) + "len=%d\n", (msgs->flags & I2C_S_RD) + ? 'R' : 'W', msgs->addr, msgs->len); + #endif +- i2c_lock_adapter(adap); ++ if (in_atomic() || irqs_disabled()) { ++ ret = mutex_trylock(&adap->bus_lock); ++ if (!ret) ++ /* I2C activity is ongoing. */ ++ return -EAGAIN; ++ } else { ++ mutex_lock_nested(&adap->bus_lock, adap->level); ++ } ++ + ret = adap->algo->slave_xfer(adap, msgs); +- i2c_unlock_adapter(adap); ++ ++ mutex_unlock(&adap->bus_lock); + + return ret; + } else { +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/i2c-dev.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/i2c-dev.c +index 07f393d..82f2c7c 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/i2c-dev.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/i2c/i2c-dev.c +@@ -38,7 +38,7 @@ + #include <asm/uaccess.h> + + #ifdef CONFIG_AST_I2C_SLAVE_RDWR +-#include <asm/arch/ast_i2c.h> ++#include <plat/ast_i2c.h> + #endif + + static struct i2c_driver i2cdev_driver; +@@ -310,6 +310,113 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, + return res; + } + ++static noinline int i2cdev_ioctl_slave_rdrw(struct i2c_client *client, ++ unsigned long arg) ++{ ++ struct i2c_rdwr_ioctl_data rdwr_arg; ++ struct i2c_msg *rdwr_pa; ++ u8 __user **data_ptrs; ++ int i, res; ++ ++ if (copy_from_user(&rdwr_arg, ++ (struct i2c_rdwr_ioctl_data __user *)arg, ++ sizeof(rdwr_arg))) ++ return -EFAULT; ++ ++ /* Put an arbitrary limit on the number of messages that can ++ * be sent at once */ ++ if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) ++ return -EINVAL; ++ ++ rdwr_pa = (struct i2c_msg *) ++ kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), ++ GFP_KERNEL); ++ if (!rdwr_pa) ++ return -ENOMEM; ++ ++ if (copy_from_user(rdwr_pa, rdwr_arg.msgs, ++ rdwr_arg.nmsgs * sizeof(struct i2c_msg))) { ++ kfree(rdwr_pa); ++ return -EFAULT; ++ } ++ ++ data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); ++ if (data_ptrs == NULL) { ++ kfree(rdwr_pa); ++ return -ENOMEM; ++ } ++ ++ res = 0; ++ for (i = 0; i < rdwr_arg.nmsgs; i++) { ++ /* Limit the size of the message to a sane amount; ++ * and don't let length change either. */ ++ if (rdwr_pa[i].len > 8192) { ++ res = -EINVAL; ++ break; ++ } ++ data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; ++ rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL); ++ if (rdwr_pa[i].buf == NULL) { ++ res = -ENOMEM; ++ break; ++ } ++ if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i], ++ rdwr_pa[i].len)) { ++ ++i; /* Needs to be kfreed too */ ++ res = -EFAULT; ++ break; ++ } ++ ++ /* From Linux 3.5: */ ++ /* ++ * If the message length is received from the slave (similar ++ * to SMBus block read), we must ensure that the buffer will ++ * be large enough to cope with a message length of ++ * I2C_SMBUS_BLOCK_MAX as this is the maximum underlying bus ++ * drivers allow. The first byte in the buffer must be ++ * pre-filled with the number of extra bytes, which must be ++ * at least one to hold the message length, but can be ++ * greater (for example to account for a checksum byte at ++ * the end of the message.) ++ */ ++ if (rdwr_pa[i].flags & I2C_M_RECV_LEN) { ++ if (!(rdwr_pa[i].flags & I2C_M_RD) || ++ rdwr_pa[i].buf[0] < 1 || ++ rdwr_pa[i].len < rdwr_pa[i].buf[0] + ++ I2C_SMBUS_BLOCK_MAX) { ++ res = -EINVAL; ++ break; ++ } ++ ++ rdwr_pa[i].len = rdwr_pa[i].buf[0]; ++ } ++ ++ } ++ if (res < 0) { ++ int j; ++ for (j = 0; j < i; ++j) ++ kfree(rdwr_pa[j].buf); ++ kfree(data_ptrs); ++ kfree(rdwr_pa); ++ return res; ++ } ++ ++ res = i2c_slave_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs); ++ while (i-- > 0) { ++ if (res >= 0 ) { ++ if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, ++ rdwr_pa[i].len)) ++ res = -EFAULT; ++ ++ rdwr_arg.msgs[i].len = rdwr_pa[i].len; ++ } ++ kfree(rdwr_pa[i].buf); ++ } ++ kfree(data_ptrs); ++ kfree(rdwr_pa); ++ return res; ++} ++ + static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, + unsigned long arg) + { +@@ -448,8 +555,8 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + + #ifdef CONFIG_AST_I2C_SLAVE_RDWR + case I2C_SLAVE_RDWR: +- return i2cdev_ioctl_slave_rdrw(client->adapter, (struct i2c_msg __user *)arg); +-#endif ++ return i2cdev_ioctl_slave_rdrw(client, arg); ++#endif + + case I2C_SMBUS: + return i2cdev_ioctl_smbus(client, arg); +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.c +index fdc77fc..3a5d796 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.c +@@ -1,16 +1,16 @@ + /******************************************************************************** + * File Name : ftgmac100_26.c +-* ++* + * Copyright (C) 2012-2020 ASPEED Technology 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. +-* You should have received a copy of the GNU General Public License +-* along with this program; if not, write to the Free Software +-* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++* 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. ++* You should have received a copy of the GNU General Public License ++* along with this program; if not, write to the Free Software ++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + ********************************************************************************/ + //----------------------------------------------------------------------------- + // "ASPEED MAC Driver, (Linux Kernel 2.6.15.7) 10/02/07 - by ASPEED\n" +@@ -76,7 +76,7 @@ + //AST2300 SDK 0.14 + //19.09/13/2010 - by river@aspeed + // Support Realtek RTL8201EL 10/100M PHY +-//AST2400 ++//AST2400 + //20.06/25/2013 - by CC@aspeed + // Support BCM54612E 10/100/1000M PHY + //----------------------------------------------------------------------------- +@@ -120,7 +120,12 @@ + #err "Not define include for GMAC" + #endif + ++#ifdef CONFIG_WEDGE100 ++#define PHY_DEFAULT_ADDR 0x18 ++#else ++/* wedge */ + #define PHY_DEFAULT_ADDR 0x1F ++#endif + + /*------------------------------------------------------------------------ + . +@@ -172,7 +177,6 @@ static int ftgmac100_wait_to_send_packet(struct sk_buff * skb, struct net_device + + static volatile int trans_busy = 0; + +- + void ftgmac100_phy_rw_waiting(unsigned int ioaddr) + { + unsigned int tmp; +@@ -255,6 +259,7 @@ static void getMacHwConfig( struct net_device* dev, struct AstMacHwConfig* out ) + + // out->macId = dev->dev_id; + //.. getMacAndPhy(dev, out); ++ out->phyAddr = PHY_DEFAULT_ADDR; + out->miiPhyId = 0; + + // We assume the Clock Stop register does not disable the MAC1 or MAC2 clock +@@ -272,7 +277,7 @@ no_phy_access: + out->phyAddr = 1; + } + #if 0 +- if (out->miiPhyId == 0x0362) { ++ if (out->miiPhyId == 0x0362) { + out->phyAddr = 1; + } + #endif +@@ -297,6 +302,902 @@ no_phy_access: + return; + } + ++// -------------------------------------------------------------------- ++// NCSI function ++// -------------------------------------------------------------------- ++void NCSI_Struct_Initialize(struct net_device *dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long i; ++ ++ for (i = 0; i < 6; i++) { ++ lp->NCSI_Request.DA[i] = 0xFF; ++ lp->NCSI_Respond.DA[i] = 0xFF; ++ lp->NCSI_Respond.SA[i] = 0xFF; ++ lp->NCSI_Request.SA[i] = dev->dev_addr[i]; ++ } ++ lp->NCSI_Request.EtherType = 0xF888; ++ lp->NCSI_Request.MC_ID = 0; ++ lp->NCSI_Request.Header_Revision = 0x01; ++ lp->NCSI_Request.Reserved_1 = 0; ++ lp->NCSI_Request.Reserved_2 = 0; ++ lp->NCSI_Request.Reserved_3 = 0; ++ lp->NCSI_Respond.EtherType = 0xF888; ++ lp->NCSI_Respond.MC_ID = 0; ++ lp->NCSI_Respond.Header_Revision = 0x01; ++ lp->NCSI_Respond.Reserved_1 = 0; ++ lp->NCSI_Respond.Reserved_2 = 0; ++ lp->NCSI_Respond.Reserved_3 = 0; ++ ++ lp->InstanceID = 0; ++ lp->Payload_Checksum = 0; ++ for (i = 0; i < 4; i++) { ++ lp->Payload_Pad[i] = 0; ++ } ++ for (i = 0; i < 64; i++) { ++ lp->Payload_Data[i] = 0; ++ } ++} ++ ++void Calculate_Checksum(struct net_device * dev, unsigned char *buffer_base, int Length) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned int i, CheckSum = 0; ++ unsigned int Data, Data1; ++ ++ for (i = 0; i < ((Length - 14) / 2); i++) { ++ Data = buffer_base[i * 2]; ++ Data1 = buffer_base[i * 2 + 1]; ++ CheckSum += ((Data << 8) + Data1); ++ } ++ lp->Payload_Checksum = (~(CheckSum) + 1); //2's complement ++//Inverse for insert into buffer ++ Data = (lp->Payload_Checksum & 0xFF000000) >> 24; ++ Data1 = (lp->Payload_Checksum & 0x000000FF) << 24; ++ lp->Payload_Checksum = (lp->Payload_Checksum & 0x00FFFF00) + Data + Data1; ++ Data = (lp->Payload_Checksum & 0x00FF0000) >> 8; ++ Data1 = (lp->Payload_Checksum & 0x0000FF00) << 8; ++ lp->Payload_Checksum = (lp->Payload_Checksum & 0xFF0000FF) + Data + Data1; ++} ++ ++void copy_data (struct net_device * dev, struct sk_buff * skb, int Length) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ ++ memcpy ((unsigned char *)(skb->data + 30), &lp->Payload_Data, Length); ++ Calculate_Checksum(dev, skb->data + 14, 30 + Length); ++ memcpy ((unsigned char *)(skb->data + 30 + Length), &lp->Payload_Checksum, 4); ++} ++ ++void NCSI_Rx (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long status, length, i = 0; ++ volatile RX_DESC *cur_desc; ++ ++ncsi_rx: ++ i = 0; ++ cur_desc = &lp->rx_descs[lp->rx_idx]; ++ do { ++ status = cur_desc->RXPKT_RDY; ++ i++; ++ } while (!(((status & RX_OWNBY_SOFTWARE) != 0) || (i >= NCSI_LOOP))); ++ ++ if (i < NCSI_LOOP) { ++ if (cur_desc->LRS) { ++ length = cur_desc->VDBC; ++ unsigned char *tbuf = (unsigned char *)phys_to_virt(cur_desc->RXBUF_BADR); ++ if (length <= 128 && tbuf[12] == 0x88 && tbuf[13] == 0xF8) { ++ memcpy (&lp->NCSI_Respond, (unsigned char *)phys_to_virt(cur_desc->RXBUF_BADR), length); ++ } else { ++ printk("NCSI_RX: Skip len: %d, proto: %x:%x\n", length, tbuf[12], tbuf[13]); ++ lp->rx_descs[lp->rx_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100; ++ lp->rx_idx = (lp->rx_idx+1)%RXDES_NUM; ++ goto ncsi_rx; ++ } ++ ++ } ++ lp->rx_descs[lp->rx_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100; ++ lp->rx_idx = (lp->rx_idx+1)%RXDES_NUM; ++ } else { ++ printk("NCSI_Rx: Failed\n"); ++ } ++} ++ ++void DeSelect_Package (struct net_device * dev, int Package_ID) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DESELECT_PACKAGE; ++ Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++int Select_Package (struct net_device * dev, int Package_ID) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, Found = 0; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = SELECT_PACKAGE; ++ Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (4 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 4; ++ memset ((void *)lp->Payload_Data, 0, 4); ++ lp->Payload_Data[3] = 1; //Arbitration Disable ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ Found = 0; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ Found = 1; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ ++ return Found; ++} ++ ++ ++void DeSelect_Active_Package (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DESELECT_PACKAGE; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++ ++int Select_Active_Package (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, Found = 0; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = SELECT_PACKAGE; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (4 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 4; ++ memset ((void *)lp->Payload_Data, 0, 4); ++ lp->Payload_Data[3] = 1; //Arbitration Disable ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ Found = 0; ++ } ++ else { ++ lp->Retry = 0; ++ Found = 1; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ ++ return Found; ++} ++ ++int Clear_Initial_State (struct net_device * dev, int Channel_ID) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, Found = 0; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = CLEAR_INITIAL_STATE; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + Channel_ID; //Internal Channel ID = 0 ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (CLEAR_INITIAL_STATE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ Found = 0; ++ } ++ else { ++ lp->Retry = 0; ++ Found = 1; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ ++ return Found; ++} ++ ++void Get_Version_ID (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = GET_VERSION_ID; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_VERSION_ID | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Get_Capabilities (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = GET_CAPABILITIES; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_CAPABILITIES | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ lp->NCSI_Cap.Capabilities_Flags = lp->NCSI_Respond.Payload_Data[0]; ++ lp->NCSI_Cap.Broadcast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[1]; ++ lp->NCSI_Cap.Multicast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[2]; ++ lp->NCSI_Cap.Buffering_Capabilities = lp->NCSI_Respond.Payload_Data[3]; ++ lp->NCSI_Cap.AEN_Control_Support = lp->NCSI_Respond.Payload_Data[4]; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_AEN (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = AEN_ENABLE; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (8 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 8; ++ lp->Payload_Data[3] = 0; //MC ID ++ lp->Payload_Data[7] = 1; //Link Status Change AEN ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (AEN_ENABLE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Get_MAC_Address (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, i; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = 0x50; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (8 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 8; ++ lp->Payload_Data[0] = 0x00; ++ lp->Payload_Data[1] = 0x00; ++ lp->Payload_Data[2] = 0x81; ++ lp->Payload_Data[3] = 0x19; ++ ++ lp->Payload_Data[4] = 0x00; ++ lp->Payload_Data[5] = 0x00; ++ lp->Payload_Data[6] = 0x1B; ++ lp->Payload_Data[7] = 0x00; ++ ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (0x50 | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ ++ // Update MAC Address ++printk("NCSI: MAC "); ++for (i = 0; i < 6; i++) ++ printk("%02X:", lp->NCSI_Respond.Payload_Data[12+i]); ++printk("\n"); ++ memcpy(lp->NCSI_Request.SA, &lp->NCSI_Respond.Payload_Data[12], 6); ++ memcpy(dev->dev_addr, &lp->NCSI_Respond.Payload_Data[12], 6); ++ ++ /* Update the MAC address */ ++ ast_gmac_set_mac(lp, dev->dev_addr); ++} ++ ++void Set_MAC_Affinity (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, i; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = 0x50; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (60 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ ++ lp->NCSI_Request.Payload_Length = 60; ++ memset(lp->Payload_Data, 0x00, 60); ++ lp->Payload_Data[0] = 0x00; ++ lp->Payload_Data[1] = 0x00; ++ lp->Payload_Data[2] = 0x81; ++ lp->Payload_Data[3] = 0x19; ++ ++ lp->Payload_Data[4] = 0x00; ++ lp->Payload_Data[5] = 0x01; ++ lp->Payload_Data[6] = 0x07; ++ lp->Payload_Data[7] = 0x00; ++ ++ for (i = 0; i < 6; i++) { ++ lp->Payload_Data[8+i] = lp->NCSI_Request.SA[i]; ++ } ++ ++ lp->Payload_Data[14] = 0x09; ++ ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (0x50 | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_Set_MAC_Address (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, i; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = SET_MAC_ADDRESS; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (8 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 8; ++ for (i = 0; i < 6; i++) { ++ lp->Payload_Data[i] = lp->NCSI_Request.SA[i]; ++ } ++ lp->Payload_Data[6] = 1; //MAC Address Num = 1 --> address filter 1, fixed in sample code ++ lp->Payload_Data[7] = UNICAST + 0 + ENABLE_MAC_ADDRESS_FILTER; //AT + Reserved + E ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SET_MAC_ADDRESS | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_Broadcast_Filter (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = ENABLE_BROADCAST_FILTERING; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (4 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 4; ++ memset ((void *)lp->Payload_Data, 0, 4); ++ lp->Payload_Data[3] = 0x1; //ARP, DHCP, NetBIOS ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (ENABLE_BROADCAST_FILTERING | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Disable_VLAN (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DISABLE_VLAN; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_VLAN | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Get_Parameters (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = GET_PARAMETERS; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_PARAMETERS | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++// printk ("Retry: Command = %x, Response_Code = %x, Resonpd.Command = %x, IID = %x, lp->InstanceID = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code, lp->NCSI_Respond.Command, lp->NCSI_Respond.IID, lp->InstanceID); ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ lp->NCSI_Cap.Capabilities_Flags = lp->NCSI_Respond.Payload_Data[0]; ++ lp->NCSI_Cap.Broadcast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[1]; ++ lp->NCSI_Cap.Multicast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[2]; ++ lp->NCSI_Cap.Buffering_Capabilities = lp->NCSI_Respond.Payload_Data[3]; ++ lp->NCSI_Cap.AEN_Control_Support = lp->NCSI_Respond.Payload_Data[4]; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_Network_TX (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = ENABLE_CHANNEL_NETWORK_TX; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (ENABLE_CHANNEL_NETWORK_TX | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Disable_Network_TX (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DISABLE_CHANNEL_NETWORK_TX; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + (lp->NCSI_Request.Payload_Length % 4) + 8; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_CHANNEL_NETWORK_TX | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_Channel (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = ENABLE_CHANNEL; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (ENABLE_CHANNEL | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Disable_Channel (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DISABLE_CHANNEL; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (4 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 4; ++ memset ((void *)lp->Payload_Data, 0, 4); ++ lp->Payload_Data[3] = 0x1; //ALD ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_CHANNEL | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++int Get_Link_Status (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = GET_LINK_STATUS; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_LINK_STATUS | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ if (lp->NCSI_Respond.Payload_Data[3] & 0x40) { ++ return (lp->NCSI_Respond.Payload_Data[3] & 0x01); //Link Up or Not ++ } ++ else { ++ return 0; //Auto Negotiate did not finish ++ } ++} ++ ++void Set_Link (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = SET_LINK; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (8 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 8; ++ memset ((void *)lp->Payload_Data, 0, 8); ++ lp->Payload_Data[2] = 0x02; //full duplex ++ lp->Payload_Data[3] = 0x04; //100M, auto-disable ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SET_LINK | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} + + static void ftgmac100_reset( struct net_device* dev ) + { +@@ -308,64 +1209,71 @@ static void ftgmac100_reset( struct net_device* dev ) + PRINTK("%s:ftgmac100_reset, phyAddr=0x%x, miiPhyId=0x%04x_%04x\n", + dev->name, ids->phyAddr, (ids->miiPhyId >> 16), (ids->miiPhyId & 0xffff)); + +- if (ids->miiPhyId < 1) +- return; // Cannot access MAC registers +- +- // Check the link speed and duplex. +- // They are not valid until auto-neg is resolved, which is reg.1 bit[5], +- // or the link is up, which is reg.1 bit[2]. +- +- if (ids->phyAddr < 0xff) +- tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x1); +- else tmp = 0; +- +- if (0==(tmp & (1u<<5 | 1u<<2)) || ids->phyAddr >= 0xff) { +- // No PHY chip, or link has not negotiated. +- speed = PHY_SPEED_100M; +- duplex = 1; +- netif_carrier_off(dev); +- } +- else if (((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) { +- tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00); +- duplex = (tmp & 0x0100) ? 1 : 0; +- speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M; +- } +- else if (((ids->miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || +- ((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { +- // Use reg.17_0.bit[15:13] for {speed[1:0], duplex}. +- tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x11); +- duplex = (tmp & PHY_DUPLEX_mask)>>13; +- speed = (tmp & PHY_SPEED_mask)>>14; +- netif_carrier_on(dev); +- } +- else if (priv->ids.miiPhyId == PHYID_BCM54612E +- || priv->ids.miiPhyId == PHYID_BCM54616S) { +- // Get link status +- // First Switch shadow register selector +- ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000); +- tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C); +- if ( (tmp & 0x0080) == 0x0080 ) +- duplex = 0; +- else +- duplex = 1; +- +- switch(tmp & 0x0018) { +- case 0x0000: +- speed = PHY_SPEED_1G; break; +- case 0x0008: +- speed = PHY_SPEED_100M; break; +- case 0x0010: +- speed = PHY_SPEED_10M; break; +- default: +- speed = PHY_SPEED_100M; +- } ++ if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) { ++ ids->miiPhyId = 0xFFFF; ++ // NCSI mode always is 100M and full duplex ++ duplex = 1; ++ speed = PHY_SPEED_100M; ++ } else { ++ if (ids->miiPhyId < 1) ++ return; // Cannot access MAC registers ++ ++ // Check the link speed and duplex. ++ // They are not valid until auto-neg is resolved, which is reg.1 bit[5], ++ // or the link is up, which is reg.1 bit[2]. ++ ++ if (ids->phyAddr < 0xff) ++ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x1); ++ else tmp = 0; ++ ++ if (0==(tmp & (1u<<5 | 1u<<2)) || ids->phyAddr >= 0xff) { ++ // No PHY chip, or link has not negotiated. ++ speed = PHY_SPEED_100M; ++ duplex = 1; ++ netif_carrier_off(dev); + } +- else { +- // Assume Broadcom BCM5221. Use reg.18 bits [1:0] for {100Mb/s, fdx}. +- tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x18); +- duplex = (tmp & 0x0001); +- speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M; +- } ++ else if (((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) { ++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00); ++ duplex = (tmp & 0x0100) ? 1 : 0; ++ speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M; ++ } ++ else if (((ids->miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || ++ ((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { ++ // Use reg.17_0.bit[15:13] for {speed[1:0], duplex}. ++ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x11); ++ duplex = (tmp & PHY_DUPLEX_mask)>>13; ++ speed = (tmp & PHY_SPEED_mask)>>14; ++ netif_carrier_on(dev); ++ } ++ else if (priv->ids.miiPhyId == PHYID_BCM54612E ++ || priv->ids.miiPhyId == PHYID_BCM54616S) { ++ // Get link status ++ // First Switch shadow register selector ++ ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000); ++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C); ++ if ( (tmp & 0x0080) == 0x0080 ) ++ duplex = 0; ++ else ++ duplex = 1; ++ ++ switch(tmp & 0x0018) { ++ case 0x0000: ++ speed = PHY_SPEED_1G; break; ++ case 0x0008: ++ speed = PHY_SPEED_100M; break; ++ case 0x0010: ++ speed = PHY_SPEED_10M; break; ++ default: ++ speed = PHY_SPEED_100M; ++ } ++ } ++ else { ++ // Assume Broadcom BCM5221. Use reg.18 bits [1:0] for {100Mb/s, fdx}. ++ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x18); ++ duplex = (tmp & 0x0001); ++ speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M; ++ } ++ }// NCSI_Check + + if (speed == PHY_SPEED_1G) { + // Set SPEED_100_bit too, for consistency. +@@ -385,9 +1293,9 @@ static void ftgmac100_reset( struct net_device* dev ) + } + if (duplex) + priv->maccr_val |= FULLDUP_bit; +- else ++ else + priv->maccr_val &= ~FULLDUP_bit; +- ++ + outl( SW_RST_bit, dev->base_addr + MACCR_REG ); + + #ifdef not_complete_yet +@@ -419,6 +1327,7 @@ static void ftgmac100_enable( struct net_device *dev ) + unsigned int rfifo_rsize; //Richard + unsigned int tfifo_rsize; //Richard + unsigned int rxbuf_size; ++ unsigned long Package_Found = 0, Channel_Found = 0, Re_Send = 0, Link_Status; + + rxbuf_size = RX_BUF_SIZE & 0x3fff; + outl( rxbuf_size , dev->base_addr + RBSR_REG); //for NC Body +@@ -475,7 +1384,7 @@ static void ftgmac100_enable( struct net_device *dev ) + + /// enable trans/recv,... + outl(priv->maccr_val, dev->base_addr + MACCR_REG ); +-#if 0 ++ + //NCSI Start + //DeSelect Package/ Select Package + if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) { +@@ -491,16 +1400,18 @@ static void ftgmac100_enable( struct net_device *dev ) + } + if (Package_Found != 0) { + //Initiali State +- for (i = 0; i < 2; i++) { //Suppose 2 channels in current version, You could modify it to 0x1F to support 31 channels +- Channel_Found = Clear_Initial_State(dev, i); ++ for (i = 0; i < 1; i++) { //Suppose 2 channels in current version, You could modify it to 0x1F to support 31 channels ++ //Channel_Found = Clear_Initial_State(dev, i); ++ Channel_Found = 1; + if (Channel_Found == 1) { + priv->NCSI_Cap.Channel_ID = i; + printk ("Found NCSI Network Controller at (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID); ++ Get_MAC_Address(dev); ++ Set_MAC_Affinity(dev); ++ Clear_Initial_State(dev, i); + //Get Version and Capabilities + Get_Version_ID(dev); + Get_Capabilities(dev); +-//Configuration +- Select_Active_Package(dev); + //Set MAC Address + Enable_Set_MAC_Address(dev); + //Enable Broadcast Filter +@@ -508,16 +1419,18 @@ static void ftgmac100_enable( struct net_device *dev ) + //Disable VLAN + Disable_VLAN(dev); + //Enable AEN +- Enable_AEN(dev); ++ //Enable_AEN(dev); + //Get Parameters + Get_Parameters(dev); +-//Enable TX ++//Enable TX + Enable_Network_TX(dev); + //Enable Channel + Enable_Channel(dev); + //Get Link Status + Re_Get_Link_Status: +- Link_Status = Get_Link_Status(dev); ++ //TODO: Workaround for CX4 Link status issue ++ //Link_Status = Get_Link_Status(dev); ++ Link_Status = LINK_UP; + if (Link_Status == LINK_UP) { + printk ("Using NCSI Network Controller (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID); + netif_carrier_on(dev); +@@ -528,7 +1441,7 @@ Re_Get_Link_Status: + netif_carrier_off(dev); + goto Re_Get_Link_Status; + } +-//Disable TX ++//Disable TX + Disable_Network_TX(dev); + //Disable Channel + // Disable_Channel(dev); +@@ -537,9 +1450,19 @@ Re_Get_Link_Status: + } + } + } ++ // Enable Interrupts ++ outl( ++ AHB_ERR_bit | ++ TPKT_LOST_bit | ++ TPKT2E_bit | ++ RXBUF_UNAVA_bit | ++ RPKT2B_bit ++ ,dev->base_addr + IER_REG ++ ); ++ ++ return; + } + /* now, enable interrupts */ +-#endif + if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || + ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { + outl( +@@ -564,7 +1487,7 @@ Re_Get_Link_Status: + ); + } + else if (priv->ids.miiPhyId == PHYID_BCM54612E +- || priv->ids.miiPhyId == PHYID_BCM54616S) { ++ || priv->ids.miiPhyId == PHYID_BCM54616S) { + outl( + // no link PHY link status pin PHYSTS_CHG_bit | + AHB_ERR_bit | +@@ -583,7 +1506,7 @@ Re_Get_Link_Status: + RXBUF_UNAVA_bit | + RPKT2B_bit + ,dev->base_addr + IER_REG +- ); ++ ); + } + } + +@@ -619,7 +1542,7 @@ static void aspeed_mac_timer(unsigned long data) + speed = (tmp & PHY_SPEED_mask)>>14; + } + else if (priv->ids.miiPhyId == PHYID_BCM54612E +- || priv->ids.miiPhyId == PHYID_BCM54616S) { ++ || priv->ids.miiPhyId == PHYID_BCM54616S) { + // Get link status + // First Switch shadow register selector + ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000); +@@ -628,23 +1551,23 @@ static void aspeed_mac_timer(unsigned long data) + duplex = 0; + else + duplex = 1; +- ++ + switch(tmp & 0x0018) { + case 0x0000: +- speed = PHY_SPEED_1G; +- ++ speed = PHY_SPEED_1G; ++ + break; +- case 0x0008: +- speed = PHY_SPEED_100M; +- ++ case 0x0008: ++ speed = PHY_SPEED_100M; ++ + break; +- case 0x0010: +- speed = PHY_SPEED_10M; +- ++ case 0x0010: ++ speed = PHY_SPEED_10M; ++ + break; + default: + speed = PHY_SPEED_100M; +- } ++ } + } + else { + duplex = 1; speed = PHY_SPEED_100M; +@@ -730,27 +1653,26 @@ static int ftgmac100_wait_to_send_packet( struct sk_buff * skb, struct net_devic + PRINTK3("%s:ftgmac100_wait_to_send_packet, skb=%x\n", dev->name, skb); + cur_desc = &priv->tx_descs[priv->tx_idx]; + +-#ifdef not_complete_yet +- if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor ++#ifdef not_complete_yet ++ if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor + { + DO_PRINT("no empty transmit descriptor\n"); + DO_PRINT("jiffies = %d\n", jiffies); + priv->stats.tx_dropped++; +- netif_stop_queue(dev); /// waiting to do: ++ netif_stop_queue(dev); /// waiting to do: + spin_unlock_irqrestore(&priv->tx_lock, flags); + + return 1; + } + #endif /* end_of_not */ + +- if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor ++ if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor + { + DO_PRINT("no empty TX descriptor:0x%x:0x%x\n", + (unsigned int)cur_desc,((unsigned int *)cur_desc)[0]); + priv->stats.tx_dropped++; +- netif_stop_queue(dev); /// waiting to do: ++ netif_stop_queue(dev); /// waiting to do: + spin_unlock_irqrestore(&priv->tx_lock, flags); +- + return 1; + } + priv->tx_skbuff[priv->tx_idx] = skb; +@@ -803,18 +1725,18 @@ static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv) + int i; + struct sk_buff *skb; + +- priv->rx_descs = dma_alloc_coherent(priv->dev, +- sizeof(RX_DESC)*RXDES_NUM, ++ priv->rx_descs = dma_alloc_coherent(priv->dev, ++ sizeof(RX_DESC)*RXDES_NUM, + &priv->rx_descs_dma, GFP_KERNEL); + + if(!priv->rx_descs) + return -ENOMEM; +- ++ + memset(priv->rx_descs, 0, sizeof(RX_DESC)*RXDES_NUM); + priv->rx_descs[RXDES_NUM-1].EDORR = 1; + + for (i=0; i<RXDES_NUM; i++) { +- dma_addr_t mapping; ++ dma_addr_t mapping; + skb = dev_alloc_skb(RX_BUF_SIZE + NET_IP_ALIGN); + skb_reserve(skb, NET_IP_ALIGN); + +@@ -829,8 +1751,8 @@ static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv) + priv->rx_descs[i].VIR_RXBUF_BADR = skb->data; + } + +- priv->tx_descs = dma_alloc_coherent(priv->dev, +- sizeof(TX_DESC)*TXDES_NUM, ++ priv->tx_descs = dma_alloc_coherent(priv->dev, ++ sizeof(TX_DESC)*TXDES_NUM, + &priv->tx_descs_dma ,GFP_KERNEL); + + if(!priv->tx_descs) +@@ -838,7 +1760,7 @@ static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv) + + memset((void*)priv->tx_descs, 0, sizeof(TX_DESC)*TXDES_NUM); + priv->tx_descs[TXDES_NUM-1].EDOTR = 1; // is last descriptor +- ++ + } + + #if FTMAC100_DEBUG > 2 +@@ -918,20 +1840,14 @@ static void ftgmac100_phy_configure(struct net_device* dev) + } + break; + case PHYID_VENDOR_BROADCOM: +- switch (priv->ids.miiPhyId) { +- case PHYID_BCM54612E: +- case PHYID_BCM54616S: +- ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable +- ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew +- break; +- case PHYID_BCM5221A4: +- default: +- tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1b); +- tmp |= 0x0004; +- ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1b, (u16) tmp); +- break; +- } +- break; ++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1b); ++ tmp |= 0x0004; ++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1b, (u16) tmp); ++ break; ++ case PHYID_VENDOR_BCM5461X: ++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable ++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew ++ break; + } + } + +@@ -960,26 +1876,26 @@ static void ftgmac100_timeout (struct net_device *dev) + } + + +-static void ftgmac100_free_tx (struct net_device *dev) ++static void ftgmac100_free_tx (struct net_device *dev) + { + struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv; +- int entry = priv->old_tx % TXDES_NUM; ++ int entry = priv->old_tx % TXDES_NUM; + unsigned long flags = 0; +- ++ + spin_lock_irqsave(&priv->tx_lock,flags); +- ++ + /* Free used tx skbuffs */ + + while ((priv->tx_descs[entry].TXDMA_OWN == TX_OWNBY_SOFTWARE) && (priv->tx_skbuff[entry] != NULL)) { + struct sk_buff *skb; +- ++ + skb = priv->tx_skbuff[entry]; + dev_kfree_skb_any (skb); + priv->tx_skbuff[entry] = 0; + entry = (entry + 1) % TXDES_NUM; + priv->tx_free++; + } +- ++ + spin_unlock_irqrestore(&priv->tx_lock, flags); + priv->old_tx = entry; + if ((netif_queue_stopped(dev)) && (priv->tx_free > 0)) { +@@ -1295,7 +2211,7 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * + DO_PRINT("PHYSTS_CHG \n"); + // Is this interrupt for changes of the PHYLINK pin? + // Note: PHYLINK is optional; not all boards connect it. +- if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || ++ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || + ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) + { + tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13); +@@ -1312,7 +2228,7 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * + tmp &= 0x000e; + } + else if (priv->ids.miiPhyId == PHYID_BCM54612E +- || priv->ids.miiPhyId == PHYID_BCM54616S) { ++ || priv->ids.miiPhyId == PHYID_BCM54616S) { + tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1A); + PRINTK("%s: PHY interrupt status, read_phy_reg(0x1A) = 0x%04x\n", + dev->name, tmp); +@@ -1403,10 +2319,10 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * + . Get the current statistics. + . This may be called with the card open or closed. + .-------------------------------------------------------------*/ +-static struct net_device_stats* ftgmac100_query_statistics(struct net_device *dev) ++static struct net_device_stats* ftgmac100_query_statistics(struct net_device *dev) + { + struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv; +- ++ + return &priv->stats; + } + +@@ -1416,7 +2332,7 @@ static struct net_device_stats* ftgmac100_query_statistics(struct net_device *de + // Finds the CRC32 of a set of bytes. + // Again, from Peter Cammaert's code. + // -------------------------------------------------------------------- +-static int crc32( char * s, int length ) ++static int crc32( char * s, int length ) + { + /* indices */ + int perByte; +@@ -1446,7 +2362,7 @@ static int crc32( char * s, int length ) + . packets before they take up memory. + */ + +-static void ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs ) ++static void ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs ) + { + struct dev_mc_list * cur_addr; + int crc_val; +@@ -1455,12 +2371,12 @@ static void ftgmac100_setmulticast( struct net_device *dev, int count, struct de + struct AstMacHwConfig* ids = &priv->ids; + unsigned long Combined_Channel_ID, i; + struct sk_buff * skb; +- cur_addr = addrs; ++ cur_addr = addrs; + + //TX +-#if 0 ++#if 1 + if (priv->NCSI_support == 1) { +- skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); + priv->InstanceID++; + priv->NCSI_Request.IID = priv->InstanceID; + priv->NCSI_Request.Command = SET_MAC_ADDRESS; +@@ -1597,7 +2513,7 @@ static int ast_gmac_stop(struct net_device *dev) + priv->rx_descs = NULL; priv->rx_descs_dma = 0; + priv->tx_descs = NULL; priv->tx_descs_dma = 0; + priv->tx_buf = NULL; priv->tx_buf_dma = 0; +- ++ + + return 0; + } +@@ -1651,10 +2567,10 @@ static int ftgmac100_open(struct net_device *netdev) + ftgmac100_reset(netdev); + ftgmac100_enable(netdev); + +- if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) || ++ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) || + ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL) || + (priv->ids.miiPhyId == PHYID_BCM54612E) || +- (priv->ids.miiPhyId == PHYID_BCM54616S)) { ++ (priv->ids.miiPhyId == PHYID_BCM54616S)) { + + init_timer(&priv->timer); + priv->timer.data = (unsigned long)netdev; +@@ -1702,7 +2618,7 @@ static int __init ast_gmac_probe(struct platform_device *pdev) + + + // SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops); +- ++ + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)) + netdev->netdev_ops = &ftgmac100_netdev_ops; + #else +@@ -1715,13 +2631,12 @@ static int __init ast_gmac_probe(struct platform_device *pdev) + netdev->hard_start_xmit = ftgmac100_wait_to_send_packet; + netdev->tx_timeout = ftgmac100_timeout; + netdev->get_stats = ftgmac100_query_statistics; +-//#ifdef HAVE_MULTICAST +-#if 0 ++#ifdef HAVE_MULTICAST + netdev->set_multicast_list = &ftgmac100_set_multicast_list; + #endif + + #endif +- ++ + + #ifdef CONFIG_AST_NPAI + // netdev->features = NETIF_F_GRO; +@@ -1734,12 +2649,12 @@ static int __init ast_gmac_probe(struct platform_device *pdev) + priv = netdev_priv(netdev); + priv->netdev = netdev; + priv->dev = &pdev->dev; +- ++ + + priv->ids.macId = pdev->id; +- ++ + priv->NCSI_support = ast_eth_data->NCSI_support; +- priv->INTEL_NCSI_EVA_support= ast_eth_data->INTEL_NCSI_EVA_support; ++ priv->INTEL_NCSI_EVA_support= ast_eth_data->INTEL_NCSI_EVA_support; + spin_lock_init(&priv->tx_lock); + + #if 0 +@@ -1833,7 +2748,7 @@ err_ioremap: + err_req_mem: + // netif_napi_del(&priv->napi); + platform_set_drvdata(pdev, NULL); +-err_netdev: ++err_netdev: + free_netdev(netdev); + err_alloc_etherdev: + return err; +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.h b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.h +index 0d47024..2493111 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.h ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/net/ftgmac100_26.h +@@ -1,16 +1,16 @@ + /******************************************************************************** + * File Name : ftgmac100_26.h +-* ++* + * Copyright (C) 2012-2020 ASPEED Technology 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. +-* You should have received a copy of the GNU General Public License +-* along with this program; if not, write to the Free Software +-* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++* 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. ++* You should have received a copy of the GNU General Public License ++* along with this program; if not, write to the Free Software ++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + ********************************************************************************/ + // -------------------------------------------------------------------- + +@@ -78,7 +78,7 @@ + + + // -------------------------------------------------------------------- +-// APTC_REG ++// APTC_REG + // -------------------------------------------------------------------- + + +@@ -99,18 +99,18 @@ typedef struct + #define PHY_READ_bit (1UL<<26) + #define PHY_WRITE_bit (1UL<<27) + // -------------------------------------------------------------------- +-// PHYCR_REG ++// PHYCR_REG + // -------------------------------------------------------------------- + #define PHY_AUTO_OK_bit (1UL<<5) + // -------------------------------------------------------------------- +-// PHY INT_STAT_REG ++// PHY INT_STAT_REG + // -------------------------------------------------------------------- + #define PHY_SPEED_CHG_bit (1UL<<14) + #define PHY_DUPLEX_CHG_bit (1UL<<13) + #define PHY_LINK_CHG_bit (1UL<<10) + #define PHY_AUTO_COMP_bit (1UL<<11) + // -------------------------------------------------------------------- +-// PHY SPE_STAT_REG ++// PHY SPE_STAT_REG + // -------------------------------------------------------------------- + #define PHY_RESOLVED_bit (1UL<<11) + #define PHY_SPEED_mask 0xC000 +@@ -269,7 +269,7 @@ typedef struct { + unsigned short Reserved_5; + unsigned short Response_Code; + unsigned short Reason_Code; +- unsigned char Payload_Data[64]; ++ unsigned char Payload_Data[128]; + } NCSI_Response_Packet; + + //Standard Response Code +@@ -365,30 +365,30 @@ typedef struct + u32 FRS:1; + u32 EDORR:1; + u32 RXPKT_RDY:1; // 1 ==> owned by FTMAC100, 0 ==> owned by software +- ++ + // RXDES1 + u32 VLAN_TAGC:16; + u32 Reserved4:4; + u32 PROTL_TYPE:2; + u32 LLC_PKT:1; + u32 DF:1; +- u32 VLAN_AVA:1; ++ u32 VLAN_AVA:1; + u32 TCPCS_FAIL:1; + u32 UDPCS_FAIL:1; + u32 IPCS_FAIL:1; + u32 Reserved5:4; +- ++ + // RXDES2 + u32 Reserved6:32; +- ++ + // RXDES3 + u32 RXBUF_BADR; +- ++ + u32 VIR_RXBUF_BADR; // not defined, the virtual address of receive buffer is placed here +- +- u32 RESERVED; +- u32 RESERVED1; +- u32 RESERVED2; ++ ++ u32 RESERVED; ++ u32 RESERVED1; ++ u32 RESERVED2; + }RX_DESC; + + +@@ -405,7 +405,7 @@ typedef struct + u32 FTS:1; + u32 EDOTR:1; + u32 TXDMA_OWN:1; +- ++ + // TXDES1 + u32 VLAN_TAGC:16; + u32 INS_VLAN:1; +@@ -416,8 +416,8 @@ typedef struct + u32 LLC_PKT:1; + u32 Reserved6:7; + u32 TX2FIC:1; +- u32 TXIC:1; +- ++ u32 TXIC:1; ++ + // TXDES2 + u32 Reserved7:32; + +@@ -427,8 +427,8 @@ typedef struct + u32 VIR_TXBUF_BADR; // Reserve, the virtual address of transmit buffer is placed here + + u32 RESERVED; +- u32 RESERVED1; +- u32 RESERVED2; ++ u32 RESERVED1; ++ u32 RESERVED2; + + }TX_DESC; + +@@ -450,7 +450,7 @@ typedef struct + // -------------------------------------------------------------------- + + +-//#define RXDES_NUM 64//64 // we defined 32 descriptor for OTG issue ++//#define RXDES_NUM 64//64 // we defined 32 descriptor for OTG issue + #define RXDES_NUM 32 + + #define RX_BUF_SIZE 1536 +@@ -464,6 +464,7 @@ typedef struct + #define PHYID_REVISION_MASK 0x0000000f + #define PHYID_VENDOR_MARVELL 0x01410c00 + #define PHYID_VENDOR_BROADCOM 0x00406000 ++#define PHYID_VENDOR_BCM5461X 0x03625c00 + #define PHYID_VENDOR_REALTEK 0x001cc800 + + #define PHYID_BCM5221A4 0x004061e4 +@@ -521,7 +522,7 @@ struct ftgmac100_priv { + int tx_idx; + int old_tx; + struct sk_buff *tx_skbuff[TXDES_NUM]; +- ++ + int maccr_val; + struct timer_list timer; + u32 GigaBit_MAHT0; +@@ -533,7 +534,7 @@ struct ftgmac100_priv { + NCSI_Capability NCSI_Cap; + unsigned int InstanceID; + unsigned int Retry; +- unsigned char Payload_Data[16]; ++ unsigned char Payload_Data[64]; + unsigned char Payload_Pad[4]; + unsigned long Payload_Checksum; + int tx_free; +@@ -575,7 +576,7 @@ struct ftgmac100_priv { + #define STOP_DONE (1 << 4) + + +- ++ + #endif /* _SMC_91111_H_ */ + + +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/rtc/rtc-aspeed.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/rtc/rtc-aspeed.c +index 477032e..de9e995 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/rtc/rtc-aspeed.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/rtc/rtc-aspeed.c +@@ -7,11 +7,11 @@ + * 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. +-* ++* + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -67,8 +67,16 @@ ast_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) + { + struct ast_rtc *ast_rtc = dev_get_drvdata(dev); + pr_debug("cmd = 0x%08x, arg = 0x%08lx\n", cmd, arg); +- ++ + switch (cmd) { ++ case RTC_SET_TIME: ++ case RTC_RD_TIME: ++ case RTC_ALM_READ: ++ case RTC_ALM_SET: ++ { ++ // use rtc-dev.c fallback ++ return -ENOIOCTLCMD; ++ } + case RTC_AIE_ON: /* alarm on */ + { + rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) | ENABLE_ALL_ALARM, RTC_CONTROL); +@@ -105,7 +113,7 @@ ast_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) + default: + return -ENOTTY; + } +- ++ + return 0; + } + +@@ -122,7 +130,7 @@ ast_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm) + + reg_time = rtc_read(ast_rtc->base, RTC_CNTR_STS_1); + reg_date = rtc_read(ast_rtc->base, RTC_CNTR_STS_2); +- ++ + spin_unlock_irqrestore(&ast_rtc->lock, flags); + + rtc_tm->tm_year = GET_CENT_VAL(reg_date)*1000 | GET_YEAR_VAL(reg_date); +@@ -132,7 +140,7 @@ ast_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm) + rtc_tm->tm_hour = GET_HOUR_VAL(reg_time); + rtc_tm->tm_min = GET_MIN_VAL(reg_time); + rtc_tm->tm_sec = GET_SEC_VAL(reg_time); +- ++ + pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, + rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); +@@ -155,7 +163,7 @@ ast_rtc_set_time(struct device *dev, struct rtc_time *tm) + + /* set hours */ + reg_time = SET_DAY_VAL(tm->tm_mday) | SET_HOUR_VAL(tm->tm_hour) | SET_MIN_VAL(tm->tm_min) | SET_SEC_VAL(tm->tm_sec); +- ++ + /* set century */ + /* set mon */ + reg_date = SET_CENT_VAL(tm->tm_year / 1000) | SET_YEAR_VAL(tm->tm_year % 1000) | SET_MON_VAL(tm->tm_mon); +@@ -166,10 +174,10 @@ ast_rtc_set_time(struct device *dev, struct rtc_time *tm) + rtc_write(ast_rtc->base, reg_date, RTC_CNTR_STS_2); + + rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) &~RTC_LOCK , RTC_CONTROL); +- ++ + spin_unlock_irqrestore(&ast_rtc->lock, flags); + +- return 0; ++ return 0; + } + static int + ast_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +@@ -183,7 +191,7 @@ ast_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) + alarm_reg = rtc_read(ast_rtc->base, RTC_ALARM); + spin_unlock_irqrestore(&ast_rtc->lock, flags); + +-//DAY ++//DAY + alm_tm->tm_mday = GET_DAY_VAL(alarm_reg); + + //HR +@@ -221,7 +229,7 @@ ast_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) + if (tm->tm_mday <= 31 && tm->tm_mday >= 1) { + reg_alarm |= SET_DAY_VAL(tm->tm_mday); + } +- ++ + //HR + /* set ten hours */ + if (tm->tm_hour <= 23 && tm->tm_hour >= 0) { +@@ -245,8 +253,8 @@ ast_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) + spin_lock_irqsave(&ast_rtc->lock, flags); + + rtc_write(ast_rtc->base, reg_alarm, RTC_ALARM); +- +- if(alarm->enabled) ++ ++ if(alarm->enabled) + rtc_write(ast_rtc->base, reg_alarm, RTC_CONTROL); + else + rtc_write(ast_rtc->base, reg_alarm, RTC_CONTROL); +@@ -366,14 +374,14 @@ static int __init ast_rtc_probe(struct platform_device *pdev) + ret = -EBUSY; + goto free_rtc; + } +- ++ + ast_rtc->base = ioremap(res->start, resource_size(res)); + if (!ast_rtc->base) { + dev_err(&pdev->dev, "cannot map SocleDev registers\n"); + ret = -ENOMEM; + goto release_mem; + } +- ++ + pr_debug("base = 0x%p, irq = %d\n", ast_rtc->base, ast_rtc->irq); + + rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &ast_rtcops, THIS_MODULE); +@@ -381,7 +389,7 @@ static int __init ast_rtc_probe(struct platform_device *pdev) + ret = PTR_ERR(rtc_dev); + goto unmap; + } +- ++ + ast_rtc->res = res; + ast_rtc->rtc_dev = rtc_dev; + spin_lock_init(&ast_rtc->lock); +@@ -406,7 +414,7 @@ static int __init ast_rtc_probe(struct platform_device *pdev) + printk("no need to enable RTC \n"); + + spin_unlock_irq(&ast_rtc->lock); +- ++ + /* register ISR */ + ret = request_irq(ast_rtc->irq, ast_rtc_interrupt, IRQF_DISABLED, dev_name(&rtc_dev->dev), ast_rtc); + if (ret) { +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/serial/8250.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/serial/8250.c +index a181ccf..f16da59 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/serial/8250.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/serial/8250.c +@@ -38,6 +38,7 @@ + #include <linux/serial_8250.h> + #include <linux/nmi.h> + #include <linux/mutex.h> ++#include <linux/gpio.h> + + #include <asm/io.h> + #include <asm/irq.h> +@@ -59,6 +60,8 @@ static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; + + static struct uart_driver serial8250_reg; + ++DECLARE_WAIT_QUEUE_HEAD(thre_wait); ++ + static int serial_index(struct uart_port *port) + { + return (serial8250_reg.minor - 64) + port->line; +@@ -1225,7 +1228,10 @@ static void autoconfig_irq(struct uart_8250_port *up) + + static inline void __stop_tx(struct uart_8250_port *p) + { +- if (p->ier & UART_IER_THRI) { ++ int status = serial_in(p, UART_LSR); ++ // only turn off THRE interrupt if THRE is *currently* asserted ++ // (we still want to catch it a final time after the FIFO empties) ++ if ((p->ier & UART_IER_THRI) && (status & UART_LSR_THRE)) { + p->ier &= ~UART_IER_THRI; + serial_out(p, UART_IER, p->ier); + } +@@ -1527,6 +1533,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) + + DEBUG_INTR("end.\n"); + ++ wake_up(&thre_wait); + return IRQ_RETVAL(handled); + } + +@@ -2526,6 +2533,35 @@ serial8250_type(struct uart_port *port) + return uart_config[type].name; + } + ++static int serial8250_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg) { ++ struct uart_8250_port *up = (struct uart_8250_port *)port; ++ unsigned long flags; ++ int ret = -ENOIOCTLCMD; ++ // kernel-space RS485 drain-and-switch hack ++ if (cmd == TIOCSERWAITTEMT) { ++ // wait for kernel buffers and UART FIFO to both empty ++ struct circ_buf *xmit = &up->port.info->xmit; ++ wait_event_interruptible( ++ thre_wait, ++ uart_circ_empty(xmit) && ++ (serial_in(up, UART_LSR) & UART_LSR_THRE)); ++ // spin until TEMT (transmit shift register empty) ++ spin_lock_irqsave(&up->port.lock, flags); ++ wait_for_xmitr(up, BOTH_EMPTY); ++ if (arg != 0) { ++ // turn off RS485 DE pin ++ gpio_set_value(arg, 0); ++ } ++ // grab any phantom char seen on RX when transceiver switches ++ (void) serial_inp(up, UART_RX); ++ // enable read ++ up->port.ignore_status_mask &= ~UART_LSR_DR; ++ spin_unlock_irqrestore(&up->port.lock, flags); ++ return 0; ++ } ++ return ret; ++} ++ + static struct uart_ops serial8250_pops = { + .tx_empty = serial8250_tx_empty, + .set_mctrl = serial8250_set_mctrl, +@@ -2544,6 +2580,7 @@ static struct uart_ops serial8250_pops = { + .request_port = serial8250_request_port, + .config_port = serial8250_config_port, + .verify_port = serial8250_verify_port, ++ .ioctl = serial8250_ioctl, + #ifdef CONFIG_CONSOLE_POLL + .poll_get_char = serial8250_get_poll_char, + .poll_put_char = serial8250_put_poll_char, +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/Kconfig b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/Kconfig +index 5702145..0b01ba8 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/Kconfig ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/Kconfig +@@ -235,10 +235,17 @@ config ORION5X_WATCHDOG + + config AST_WATCHDOG + tristate "ASPEED GUC watchdog" +- depends on WATCHDOG ++ depends on WATCHDOG + help + Watchdog timer for ASPEED chips. + ++config AST_WATCHDOG_REARM_DUAL_BOOT ++ bool "Rearm dual boot watchdog" ++ default n ++ depends on AST_WATCHDOG ++ help ++ Rearm dual boot watchdog or not during boot ++ + # ARM26 Architecture + + # AVR32 Architecture +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/ast_wdt.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/ast_wdt.c +index 9e7e84f..e599a55 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/ast_wdt.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/drivers/watchdog/ast_wdt.c +@@ -68,6 +68,7 @@ typedef unsigned char bool_T; + + #else + #define WDT_BASE_VA (IO_ADDRESS(AST_WDT_BASE)) ++#define WDT2_BASE_VA (IO_ADDRESS(AST_WDT_BASE + 20)) + #endif + + #define WDT_CntSts (WDT_BASE_VA+0x00) +@@ -78,6 +79,14 @@ typedef unsigned char bool_T; + #define WDT_Clr (WDT_BASE_VA+0x14) + #define WDT_RstWd (WDT_BASE_VA+0x18) + ++#define WDT2_CntSts (WDT2_BASE_VA+0x00) ++#define WDT2_Reload (WDT2_BASE_VA+0x04) ++#define WDT2_Restart (WDT2_BASE_VA+0x08) ++#define WDT2_Ctrl (WDT2_BASE_VA+0x0C) ++#define WDT2_TimeOut (WDT2_BASE_VA+0x10) ++#define WDT2_Clr (WDT2_BASE_VA+0x14) ++#define WDT2_RstWd (WDT2_BASE_VA+0x18) ++ + #define WDT_CTRL_B_SECOND_BOOT (0x1 << 7) + #define WDT_CTRL_B_RESET_SOC (0x00 << 5) /* yes, 0x00 */ + #define WDT_CTRL_B_RESET_FULL (0x01 << 5) +@@ -101,6 +110,11 @@ typedef unsigned char bool_T; + #define WDT_TIMO 30 /* Default heartbeat = 30 seconds */ + + #define WDT_INITIAL_TIMO (8*60) /* Initial timeout, 8m */ ++/* ++ * Dual boot watchdog is 5s shorter so that dual boot watchdog ++ * will kick in first. ++ */ ++#define WDT_DUAL_BOOT_TIMO (WDT_INITIAL_TIMO - 5) + #define WDT_TIMO2TICKS(t) (TICKS_PER_uSEC * 1000000 * (t)) + + static int heartbeat = WDT_TIMO; +@@ -233,6 +247,14 @@ bool_T wdt_is_enabled(void) + return reg & WDT_CTRL_B_ENABLE; + } + ++#ifdef CONFIG_AST_WATCHDOG_REARM_DUAL_BOOT ++void wdt_dual_boot_restart(unsigned int timeo) ++{ ++ AST_WRITE_REG(WDT2_Reload, WDT_TIMO2TICKS(timeo)); ++ AST_WRITE_REG(WDT2_Restart, 0x4755); /* reload! */ ++ printk(KERN_INFO "Re-arm the dual boot watchdog for %u seconds\n", timeo); ++} ++#endif + + void wdt_restart_new(unsigned int nPeriod, int sourceClk, bool_T bResetOut, + bool_T bIntrSys, bool_T bClrAfter, bool_T bResetARMOnly) +@@ -542,6 +564,11 @@ static int ast_wdt_probe(struct platform_device *pdev) + return ret; + } + ++#ifdef CONFIG_AST_WATCHDOG_REARM_DUAL_BOOT ++ /* re-arm dual boot watchdog */ ++ wdt_dual_boot_restart(WDT_DUAL_BOOT_TIMO); ++#endif ++ + /* interrupt the system while WDT timeout */ + wdt_restart_new(WDT_TIMO2TICKS(WDT_INITIAL_TIMO), WDT_CLK_SRC_EXT, + /* No Ext, No intr, Self clear, Full chip reset */ +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/fs/compat_ioctl.c b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/fs/compat_ioctl.c +index 61cb48f..5dc69ab 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/fs/compat_ioctl.c ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/fs/compat_ioctl.c +@@ -3,7 +3,7 @@ + * + * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) +- * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs ++ * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs + * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) + * + * These routines maintain argument size conversion between 32bit and 64bit +@@ -125,7 +125,7 @@ static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) + mm_segment_t old_fs = get_fs(); + int err; + unsigned long val; +- ++ + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&val); + set_fs (old_fs); +@@ -133,14 +133,14 @@ static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) + return -EFAULT; + return err; + } +- ++ + static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) + { + mm_segment_t old_fs = get_fs(); + u32 __user *argptr = compat_ptr(arg); + int err; + unsigned long val; +- ++ + if(get_user(val, argptr)) + return -EFAULT; + set_fs (KERNEL_DS); +@@ -365,17 +365,17 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) + if (copy_in_user(ifr, ifr32, sizeof(struct ifreq32))) + return -EFAULT; + ifr++; +- ifr32++; ++ ifr32++; + } + } + if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) + return -EFAULT; + +- err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)uifc); ++ err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)uifc); + if (err) + return err; + +- if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) ++ if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) + return -EFAULT; + + ifr = ifc.ifc_req; +@@ -411,7 +411,7 @@ static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) + struct ifreq32 __user *ifr32; + u32 data; + void __user *datap; +- ++ + ifr = compat_alloc_user_space(sizeof(*ifr)); + ifr32 = compat_ptr(arg); + +@@ -507,7 +507,7 @@ static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) + struct ifmap32 __user *uifmap32; + mm_segment_t old_fs; + int err; +- ++ + uifr32 = compat_ptr(arg); + uifmap32 = &uifr32->ifr_ifru.ifru_map; + switch (cmd) { +@@ -610,7 +610,7 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) + char devname[16]; + u32 rtdev; + mm_segment_t old_fs = get_fs(); +- ++ + struct socket *mysock = sockfd_lookup(fd, &ret); + + if (mysock && mysock->sk && mysock->sk->sk_family == AF_INET6) { /* ipv6 */ +@@ -624,7 +624,7 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) + ret |= __get_user (r6.rtmsg_info, &(ur6->rtmsg_info)); + ret |= __get_user (r6.rtmsg_flags, &(ur6->rtmsg_flags)); + ret |= __get_user (r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); +- ++ + r = (void *) &r6; + } else { /* ipv4 */ + struct rtentry32 __user *ur4 = compat_ptr(arg); +@@ -1046,14 +1046,14 @@ static int vt_check(struct file *file) + struct tty_struct *tty; + struct inode *inode = file->f_path.dentry->d_inode; + struct vc_data *vc; +- ++ + if (file->f_op->unlocked_ioctl != tty_ioctl) + return -EINVAL; +- ++ + tty = (struct tty_struct *)file->private_data; + if (tty_paranoia_check(tty, inode, "tty_ioctl")) + return -EINVAL; +- ++ + if (tty->ops->ioctl != vt_ioctl) + return -EINVAL; + +@@ -1067,7 +1067,7 @@ static int vt_check(struct file *file) + */ + if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) + return 1; +- return 0; ++ return 0; + } + + struct consolefontdesc32 { +@@ -1085,7 +1085,7 @@ static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, + + perm = vt_check(file); + if (perm < 0) return perm; +- ++ + switch (cmd) { + case PIO_FONTX: + if (!perm) +@@ -1130,16 +1130,16 @@ struct console_font_op32 { + compat_uint_t charcount; + compat_caddr_t data; /* font data with height fixed to 32 */ + }; +- ++ + static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) + { + struct console_font_op op; + struct console_font_op32 __user *fontop = compat_ptr(arg); + int perm = vt_check(file), i; + struct vc_data *vc; +- ++ + if (perm < 0) return perm; +- ++ + if (copy_from_user(&op, fontop, sizeof(struct console_font_op32))) + return -EFAULT; + if (!perm && op.op != KD_FONT_OP_GET) +@@ -1303,7 +1303,7 @@ static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg) + u32 data; + void __user *datap; + int err; +- ++ + sioc = compat_alloc_user_space(sizeof(*sioc)); + sioc32 = compat_ptr(arg); + +@@ -1328,7 +1328,7 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) + { + int i; + unsigned int cmd = 0; +- ++ + switch (cmd32) { + case SONET_GETSTAT: + case SONET_GETSTATZ: +@@ -1349,11 +1349,11 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) + } + if (i == NR_ATM_IOCTL) + return -EINVAL; +- ++ + switch (cmd) { + case ATM_GETNAMES: + return do_atm_iobuf(fd, cmd, arg); +- ++ + case ATM_GETLINKRATE: + case ATM_GETTYPE: + case ATM_GETESI: +@@ -1444,7 +1444,7 @@ static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg) + } + + return err; +-} ++} + + #ifdef CONFIG_BLOCK + struct raw32_config_request +@@ -1798,7 +1798,7 @@ static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg) + val32 = kval; + return put_user(val32, (unsigned int __user *)arg); + case RTC_IRQP_SET32: +- return sys_ioctl(fd, RTC_IRQP_SET, arg); ++ return sys_ioctl(fd, RTC_IRQP_SET, arg); + case RTC_EPOCH_SET32: + return sys_ioctl(fd, RTC_EPOCH_SET, arg); + default: +@@ -2678,6 +2678,7 @@ COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) + /* i2c */ + HANDLE_IOCTL(I2C_FUNCS, w_long) + HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) ++HANDLE_IOCTL(I2C_SLAVE_RDWR, do_i2c_rdwr_ioctl) + HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl) + /* bridge */ + HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/include/linux/i2c-dev.h b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/include/linux/i2c-dev.h +index 311315b..ed9b48d 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/include/linux/i2c-dev.h ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/include/linux/i2c-dev.h +@@ -46,6 +46,7 @@ + #define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ + + #define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */ ++#define I2C_SLAVE_RDWR 0x0709 /* Slave Read Write */ + + #define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ + #define I2C_SMBUS 0x0720 /* SMBus transfer */ +diff --git a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/include/linux/i2c.h b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/include/linux/i2c.h +index 59167e2..f037cde 100644 +--- a/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/include/linux/i2c.h ++++ b/meta-aspeed/recipes-kernel/linux/files/linux-aspeed-2.6.28.9/include/linux/i2c.h +@@ -62,6 +62,9 @@ extern int i2c_master_recv(struct i2c_client *client, char *buf, int count); + extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); + ++extern int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num); ++ + /* This is the very generalized SMBus access routine. You probably do not + want to use this, though; one of the functions below may be much easier, + and probably just as fast. +@@ -333,6 +336,7 @@ struct i2c_algorithm { + processed, or a negative value on error */ + int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); ++ int (*slave_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs); + int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data); +@@ -516,6 +520,8 @@ struct i2c_msg { + __u16 flags; + #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ + #define I2C_M_RD 0x0001 /* read data, from slave to master */ ++#define I2C_S_EN 0x0002 /* Slave Enable */ ++#define I2C_S_ALT 0x0004 /* Slave Alert */ + #define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch +new file mode 100644 +index 0000000..52aef04 +--- /dev/null ++++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch +@@ -0,0 +1,29 @@ ++From d2ac467a108400ff1ae682a423c7d41265e62d47 Mon Sep 17 00:00:00 2001 ++From: Thierry Reding <thierry.reding@avionic-design.de> ++Date: Mon, 30 Aug 2010 13:00:48 +0200 ++Subject: [PATCH] mtd: m25p80: Add support for the Winbond W25Q64 ++ ++This patch adds support for the Winbond W25Q64 serial flash. ++ ++Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> ++Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> ++Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> ++--- ++ drivers/mtd/devices/m25p80.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c ++index 1f0f703..b6fd7c2 100644 ++--- a/drivers/mtd/devices/m25p80.c +++++ b/drivers/mtd/devices/m25p80.c ++@@ -716,6 +716,7 @@ static const struct spi_device_id m25p_ids[] = { ++ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, ++ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, ++ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, +++ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, ++ ++ /* Catalyst / On Semiconductor -- non-JEDEC */ ++ { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, ++-- ++1.8.5.6 ++ +diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch +new file mode 100644 +index 0000000..ad04217 +--- /dev/null ++++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch +@@ -0,0 +1,56 @@ ++From 0a36b345ab99d6b3c96999e7e3b79bd243cf9bf7 Mon Sep 17 00:00:00 2001 ++From: "Eric W. Biederman" <ebiederm@xmission.com> ++Date: Wed, 5 Nov 2008 16:00:24 -0800 ++Subject: [PATCH] net: Don't leak packets when a netns is going down ++ ++I have been tracking for a while a case where when the ++network namespace exits the cleanup gets stck in an ++endless precessess of: ++ ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++ ++It turns out that if you listen on a multicast address an unsubscribe ++packet is sent when the network device goes down. If you shutdown ++the network namespace without carefully cleaning up this can trigger ++the unsubscribe packet to be sent over the loopback interface while ++the network namespace is going down. ++ ++All of which is fine except when we drop the packet and forget to ++free it leaking the skb and the dst entry attached to. As it ++turns out the dst entry hold a reference to the idev which holds ++the dev and keeps everything from being cleaned up. Yuck! ++ ++By fixing my earlier thinko and add the needed kfree_skb and everything ++cleans up beautifully. ++ ++Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ net/core/dev.c | 4 +++- ++ 1 file changed, 3 insertions(+), 1 deletion(-) ++ ++diff --git a/net/core/dev.c b/net/core/dev.c ++index 811507c..a0c60607 100644 ++--- a/net/core/dev.c +++++ b/net/core/dev.c ++@@ -2253,8 +2253,10 @@ int netif_receive_skb(struct sk_buff *skb) ++ rcu_read_lock(); ++ ++ /* Don't receive packets in an exiting network namespace */ ++- if (!net_alive(dev_net(skb->dev))) +++ if (!net_alive(dev_net(skb->dev))) { +++ kfree_skb(skb); ++ goto out; +++ } ++ ++ #ifdef CONFIG_NET_CLS_ACT ++ if (skb->tc_verd & TC_NCLS) { ++-- ++1.8.1 ++ +diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch +new file mode 100644 +index 0000000..b638996 +--- /dev/null ++++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch +@@ -0,0 +1,43 @@ ++From 5777cee30776da63ecbe2b6d4929e01d82c7d72e Mon Sep 17 00:00:00 2001 ++From: Brian Haley <brian.haley@hp.com> ++Date: Tue, 2 Jun 2009 00:20:26 -0700 ++Subject: [PATCH] IPv6: Print error value when skb allocation fails ++ ++Print-out the error value when sock_alloc_send_skb() fails in ++the IPv6 neighbor discovery code - can be useful for debugging. ++ ++Signed-off-by: Brian Haley <brian.haley@hp.com> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ net/ipv6/ndisc.c | 8 ++++---- ++ 1 file changed, 4 insertions(+), 4 deletions(-) ++ ++diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c ++index d0f54d1..45529b1 100644 ++--- a/net/ipv6/ndisc.c +++++ b/net/ipv6/ndisc.c ++@@ -483,8 +483,8 @@ static void __ndisc_send(struct net_device *dev, ++ 1, &err); ++ if (!skb) { ++ ND_PRINTK0(KERN_ERR ++- "ICMPv6 ND: %s() failed to allocate an skb.\n", ++- __func__); +++ "ICMPv6 ND: %s() failed to allocate an skb, err=%d.\n", +++ __func__, err); ++ dst_release(dst); ++ return; ++ } ++@@ -1533,8 +1533,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, ++ 1, &err); ++ if (buff == NULL) { ++ ND_PRINTK0(KERN_ERR ++- "ICMPv6 Redirect: %s() failed to allocate an skb.\n", ++- __func__); +++ "ICMPv6 Redirect: %s() failed to allocate an skb, err=%d.\n", +++ __func__, err); ++ dst_release(dst); ++ return; ++ } ++-- ++1.8.1 ++ +diff --git a/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb b/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb +index 54f410a..c61e0c2 100644 +--- a/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb ++++ b/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb +@@ -15,6 +15,9 @@ SRC_URI = "file://linux-aspeed-2.6.28.9 \ + file://patch-2.6.28.9/0026-mtd-m25p80-modify-info-for-Micron-N25Q128.patch \ + file://patch-2.6.28.9/0027-mtd-m25p80-n25q064-is-Micron-not-Intel-Numonyx.patch \ + file://patch-2.6.28.9/0028-ipv6-Plug-sk_buff-leak-in-ipv6_rcv-net-ipv6-ip6_inpu.patch \ ++ file://patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch \ ++ file://patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch \ ++ file://patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch \ + file://patch-2.6.28.9/0001-bzip2-lzma-library-support-for-gzip-bzip2-and-lzma-d.patch \ + file://patch-2.6.28.9/0002-bzip2-lzma-config-and-initramfs-support-for-bzip2-lz.patch \ + " +@@ -25,6 +28,16 @@ LINUX_VERSION_EXTENSION ?= "-aspeed" + PR = "r1" + PV = "${LINUX_VERSION}" + +-KERNEL_CONFIG_COMMAND = "oe_runmake wedge_defconfig && oe_runmake oldconfig" +- + include linux-aspeed.inc ++ ++# Install bounds.h for external module install ++# The default install script handles this. However, it looks for bounds.h from ++# 'include/generated', which doesnot match 2.6.28, where the file is in ++# 'include/linux'. ++do_install[postfuncs] += "install_bounds_h" ++install_bounds_h() { ++ kerneldir=${D}${KERNEL_SRC_PATH} ++ if [ -f include/linux/bounds.h ]; then ++ cp -l include/linux/bounds.h $kerneldir/include/linux/bounds.h ++ fi ++} +-- +1.8.1 + diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch new file mode 100644 index 0000000..52aef04 --- /dev/null +++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch @@ -0,0 +1,29 @@ +From d2ac467a108400ff1ae682a423c7d41265e62d47 Mon Sep 17 00:00:00 2001 +From: Thierry Reding <thierry.reding@avionic-design.de> +Date: Mon, 30 Aug 2010 13:00:48 +0200 +Subject: [PATCH] mtd: m25p80: Add support for the Winbond W25Q64 + +This patch adds support for the Winbond W25Q64 serial flash. + +Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> +Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> +Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> +--- + drivers/mtd/devices/m25p80.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c +index 1f0f703..b6fd7c2 100644 +--- a/drivers/mtd/devices/m25p80.c ++++ b/drivers/mtd/devices/m25p80.c +@@ -716,6 +716,7 @@ static const struct spi_device_id m25p_ids[] = { + { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, + { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, + { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, ++ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, + + /* Catalyst / On Semiconductor -- non-JEDEC */ + { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, +-- +1.8.5.6 + diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch new file mode 100644 index 0000000..ad04217 --- /dev/null +++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch @@ -0,0 +1,56 @@ +From 0a36b345ab99d6b3c96999e7e3b79bd243cf9bf7 Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" <ebiederm@xmission.com> +Date: Wed, 5 Nov 2008 16:00:24 -0800 +Subject: [PATCH] net: Don't leak packets when a netns is going down + +I have been tracking for a while a case where when the +network namespace exits the cleanup gets stck in an +endless precessess of: + +unregister_netdevice: waiting for lo to become free. Usage count = 3 +unregister_netdevice: waiting for lo to become free. Usage count = 3 +unregister_netdevice: waiting for lo to become free. Usage count = 3 +unregister_netdevice: waiting for lo to become free. Usage count = 3 +unregister_netdevice: waiting for lo to become free. Usage count = 3 +unregister_netdevice: waiting for lo to become free. Usage count = 3 +unregister_netdevice: waiting for lo to become free. Usage count = 3 + +It turns out that if you listen on a multicast address an unsubscribe +packet is sent when the network device goes down. If you shutdown +the network namespace without carefully cleaning up this can trigger +the unsubscribe packet to be sent over the loopback interface while +the network namespace is going down. + +All of which is fine except when we drop the packet and forget to +free it leaking the skb and the dst entry attached to. As it +turns out the dst entry hold a reference to the idev which holds +the dev and keeps everything from being cleaned up. Yuck! + +By fixing my earlier thinko and add the needed kfree_skb and everything +cleans up beautifully. + +Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + net/core/dev.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/core/dev.c b/net/core/dev.c +index 811507c..a0c60607 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2253,8 +2253,10 @@ int netif_receive_skb(struct sk_buff *skb) + rcu_read_lock(); + + /* Don't receive packets in an exiting network namespace */ +- if (!net_alive(dev_net(skb->dev))) ++ if (!net_alive(dev_net(skb->dev))) { ++ kfree_skb(skb); + goto out; ++ } + + #ifdef CONFIG_NET_CLS_ACT + if (skb->tc_verd & TC_NCLS) { +-- +1.8.1 + diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch new file mode 100644 index 0000000..b638996 --- /dev/null +++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch @@ -0,0 +1,43 @@ +From 5777cee30776da63ecbe2b6d4929e01d82c7d72e Mon Sep 17 00:00:00 2001 +From: Brian Haley <brian.haley@hp.com> +Date: Tue, 2 Jun 2009 00:20:26 -0700 +Subject: [PATCH] IPv6: Print error value when skb allocation fails + +Print-out the error value when sock_alloc_send_skb() fails in +the IPv6 neighbor discovery code - can be useful for debugging. + +Signed-off-by: Brian Haley <brian.haley@hp.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +--- + net/ipv6/ndisc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index d0f54d1..45529b1 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -483,8 +483,8 @@ static void __ndisc_send(struct net_device *dev, + 1, &err); + if (!skb) { + ND_PRINTK0(KERN_ERR +- "ICMPv6 ND: %s() failed to allocate an skb.\n", +- __func__); ++ "ICMPv6 ND: %s() failed to allocate an skb, err=%d.\n", ++ __func__, err); + dst_release(dst); + return; + } +@@ -1533,8 +1533,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, + 1, &err); + if (buff == NULL) { + ND_PRINTK0(KERN_ERR +- "ICMPv6 Redirect: %s() failed to allocate an skb.\n", +- __func__); ++ "ICMPv6 Redirect: %s() failed to allocate an skb, err=%d.\n", ++ __func__, err); + dst_release(dst); + return; + } +-- +1.8.1 + diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0032-Create-snapshot-of-OpenBMC.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0032-Create-snapshot-of-OpenBMC.patch new file mode 100644 index 0000000..f84dc62 --- /dev/null +++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0032-Create-snapshot-of-OpenBMC.patch @@ -0,0 +1,8462 @@ +From 19459c799ac0a521082d6d79e68ffc3decb18ea2 Mon Sep 17 00:00:00 2001 +From: Ori Bernstein <orib@fb.com> +Date: Thu, 3 Sep 2015 11:28:27 -0700 +Subject: [PATCH] Create snapshot of OpenBMC + +--- + .../arch/arm/configs/wedge_defconfig | 1 + + .../arch/arm/configs/yosemite_defconfig | 1480 ++++++++++++++++++++ + .../arch/arm/include/asm/ioctls.h | 1 + + .../arch/arm/mach-aspeed/Kconfig | 12 + + .../arch/arm/mach-aspeed/gpio.c | 2 +- + .../arm/mach-aspeed/include/mach/debug-macro.S | 4 +- + .../arch/arm/mach-aspeed/include/mach/platform.h | 17 +- + .../arch/arm/mach-aspeed/include/mach/uncompress.h | 6 +- + .../arch/arm/mach-aspeed/include/mach/vmalloc.h | 4 +- + .../arch/arm/plat-aspeed/ast-scu.c | 372 ++--- + .../arch/arm/plat-aspeed/dev-eth.c | 35 +- + .../arch/arm/plat-aspeed/dev-i2c.c | 385 +++-- + .../arch/arm/plat-aspeed/dev-spi.c | 27 +- + .../arch/arm/plat-aspeed/dev-uart.c | 50 +- + .../arch/arm/plat-aspeed/irq.c | 28 +- + .../linux-aspeed-2.6.28.9/drivers/hwmon/ast_adc.c | 233 +-- + .../drivers/i2c/busses/i2c-ast.c | 689 +++++---- + .../linux-aspeed-2.6.28.9/drivers/i2c/i2c-core.c | 15 +- + .../linux-aspeed-2.6.28.9/drivers/i2c/i2c-dev.c | 113 +- + .../drivers/net/ftgmac100_26.c | 1211 ++++++++++++++-- + .../drivers/net/ftgmac100_26.h | 67 +- + .../linux-aspeed-2.6.28.9/drivers/rtc/rtc-aspeed.c | 42 +- + .../linux-aspeed-2.6.28.9/drivers/serial/8250.c | 39 +- + .../linux-aspeed-2.6.28.9/drivers/watchdog/Kconfig | 9 +- + .../drivers/watchdog/ast_wdt.c | 27 + + .../files/linux-aspeed-2.6.28.9/fs/compat_ioctl.c | 51 +- + .../linux-aspeed-2.6.28.9/include/linux/i2c-dev.h | 1 + + .../linux-aspeed-2.6.28.9/include/linux/i2c.h | 6 + + ...m25p80-Add-support-for-the-Winbond-W25Q64.patch | 29 + + ...t-leak-packets-when-a-netns-is-going-down.patch | 56 + + ...int-error-value-when-skb-allocation-fails.patch | 43 + + .../recipes-kernel/linux/linux-aspeed_2.6.28.9.bb | 17 +- + 34 files changed, 7064 insertions(+), 950 deletions(-) + create mode 100644 arch/arm/configs/fbplatform1_defconfig + create mode 100644 arch/arm/configs/yosemite_defconfig + create mode 100644 meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch + create mode 100644 meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch + create mode 100644 meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch + +diff --git a/arch/arm/configs/wedge_defconfig b/arch/arm/configs/wedge_defconfig +index 23a9fe3..41fe288 100644 +--- a/arch/arm/configs/wedge_defconfig ++++ b/arch/arm/configs/wedge_defconfig +@@ -174,6 +174,7 @@ CONFIG_IRMP=y + # CONFIG_ARCH_AST2200 is not set + # CONFIG_ARCH_AST2300 is not set + CONFIG_ARCH_AST2400=y ++CONFIG_WEDGE=y + # CONFIG_ARCH_AST2500 is not set + + # +diff --git a/arch/arm/configs/yosemite_defconfig b/arch/arm/configs/yosemite_defconfig +new file mode 100644 +index 0000000..d32f18e +--- /dev/null ++++ b/arch/arm/configs/yosemite_defconfig +@@ -0,0 +1,1480 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.28.9 ++# Tue Feb 3 16:41:40 2015 ++# ++CONFIG_ARM=y ++CONFIG_SYS_SUPPORTS_APM_EMULATION=y ++CONFIG_GENERIC_GPIO=y ++CONFIG_GENERIC_TIME=y ++CONFIG_GENERIC_CLOCKEVENTS=y ++CONFIG_MMU=y ++# CONFIG_NO_IOPORT is not set ++CONFIG_GENERIC_HARDIRQS=y ++CONFIG_STACKTRACE_SUPPORT=y ++CONFIG_HAVE_LATENCYTOP_SUPPORT=y ++CONFIG_LOCKDEP_SUPPORT=y ++CONFIG_TRACE_IRQFLAGS_SUPPORT=y ++CONFIG_HARDIRQS_SW_RESEND=y ++CONFIG_GENERIC_IRQ_PROBE=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++# CONFIG_ARCH_HAS_ILOG2_U32 is not set ++# CONFIG_ARCH_HAS_ILOG2_U64 is not set ++CONFIG_GENERIC_HWEIGHT=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y ++CONFIG_VECTORS_BASE=0xffff0000 ++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" ++ ++# ++# General setup ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++CONFIG_LOCALVERSION="" ++# CONFIG_LOCALVERSION_AUTO is not set ++CONFIG_KERNEL_GZIP=y ++# CONFIG_KERNEL_BZIP2 is not set ++# CONFIG_KERNEL_LZMA is not set ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_SYSVIPC_SYSCTL=y ++CONFIG_POSIX_MQUEUE=y ++# CONFIG_BSD_PROCESS_ACCT is not set ++# CONFIG_TASKSTATS is not set ++# CONFIG_AUDIT is not set ++CONFIG_IKCONFIG=m ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++# CONFIG_CGROUPS is not set ++# CONFIG_GROUP_SCHED is not set ++CONFIG_SYSFS_DEPRECATED=y ++CONFIG_SYSFS_DEPRECATED_V2=y ++# CONFIG_RELAY is not set ++CONFIG_NAMESPACES=y ++# CONFIG_UTS_NS is not set ++# CONFIG_IPC_NS is not set ++# CONFIG_USER_NS is not set ++# CONFIG_PID_NS is not set ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL=y ++CONFIG_ANON_INODES=y ++# CONFIG_EMBEDDED is not set ++CONFIG_UID16=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_KALLSYMS=y ++CONFIG_KALLSYMS_EXTRA_PASS=y ++CONFIG_HOTPLUG=y ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_ELF_CORE=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_SIGNALFD=y ++CONFIG_TIMERFD=y ++CONFIG_EVENTFD=y ++CONFIG_SHMEM=y ++CONFIG_AIO=y ++CONFIG_VM_EVENT_COUNTERS=y ++CONFIG_SLUB_DEBUG=y ++CONFIG_COMPAT_BRK=y ++# CONFIG_SLAB is not set ++CONFIG_SLUB=y ++# CONFIG_SLOB is not set ++# CONFIG_PROFILING is not set ++# CONFIG_MARKERS is not set ++CONFIG_HAVE_OPROFILE=y ++# CONFIG_KPROBES is not set ++CONFIG_HAVE_KPROBES=y ++CONFIG_HAVE_KRETPROBES=y ++CONFIG_HAVE_GENERIC_DMA_COHERENT=y ++CONFIG_SLABINFO=y ++CONFIG_RT_MUTEXES=y ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++CONFIG_MODULES=y ++# CONFIG_MODULE_FORCE_LOAD is not set ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++CONFIG_BLOCK=y ++# CONFIG_LBD is not set ++# CONFIG_BLK_DEV_IO_TRACE is not set ++# CONFIG_LSF is not set ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_BLK_DEV_INTEGRITY is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_DEFAULT_AS is not set ++# CONFIG_DEFAULT_DEADLINE is not set ++CONFIG_DEFAULT_CFQ=y ++# CONFIG_DEFAULT_NOOP is not set ++CONFIG_DEFAULT_IOSCHED="cfq" ++CONFIG_CLASSIC_RCU=y ++CONFIG_FREEZER=y ++ ++# ++# System Type ++# ++CONFIG_ARCH_ASPEED=y ++# CONFIG_ARCH_AAEC2000 is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_AT91 is not set ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_EBSA110 is not set ++# CONFIG_ARCH_EP93XX is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_NETX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_IOP13XX is not set ++# CONFIG_ARCH_IOP32X is not set ++# CONFIG_ARCH_IOP33X is not set ++# CONFIG_ARCH_IXP23XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_KIRKWOOD is not set ++# CONFIG_ARCH_KS8695 is not set ++# CONFIG_ARCH_NS9XXX is not set ++# CONFIG_ARCH_LOKI is not set ++# CONFIG_ARCH_MV78XX0 is not set ++# CONFIG_ARCH_MXC is not set ++# CONFIG_ARCH_ORION5X is not set ++# CONFIG_ARCH_PNX4008 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_DAVINCI is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_MSM is not set ++CONFIG_IRMP=y ++# CONFIG_PCEXT is not set ++# CONFIG_REMOTEFX is not set ++# CONFIG_ARCH_AST1100 is not set ++# CONFIG_ARCH_AST2100 is not set ++# CONFIG_ARCH_AST2200 is not set ++# CONFIG_ARCH_AST2300 is not set ++CONFIG_ARCH_AST2400=y ++CONFIG_YOSEMITE=y ++# CONFIG_ARCH_AST2500 is not set ++ ++# ++# FLASH Chip Select ++# ++# CONFIG_AST_CS0_NOR is not set ++# CONFIG_AST_CS0_NAND is not set ++CONFIG_AST_CS0_SPI=y ++# CONFIG_AST_CS0_NONE is not set ++# CONFIG_AST_CS1_NOR is not set ++# CONFIG_AST_CS1_NAND is not set ++# CONFIG_AST_CS1_SPI is not set ++CONFIG_AST_CS1_NONE=y ++# CONFIG_AST_CS2_NOR is not set ++# CONFIG_AST_CS2_NAND is not set ++# CONFIG_AST_CS2_SPI is not set ++CONFIG_AST_CS2_NONE=y ++# CONFIG_AST_CS3_NOR is not set ++# CONFIG_AST_CS3_NAND is not set ++# CONFIG_AST_CS3_SPI is not set ++CONFIG_AST_CS3_NONE=y ++# CONFIG_AST_CS4_NOR is not set ++# CONFIG_AST_CS4_NAND is not set ++# CONFIG_AST_CS4_SPI is not set ++CONFIG_AST_CS4_NONE=y ++# CONFIG_ARCH_AST1070 is not set ++# CONFIG_AST_SCU_LOCK is not set ++ ++# ++# Boot options ++# ++ ++# ++# Power management ++# ++CONFIG_PLAT_ASPEED=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM926T=y ++CONFIG_CPU_32v5=y ++CONFIG_CPU_ABRT_EV5TJ=y ++CONFIG_CPU_PABRT_NOIFAR=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++CONFIG_CPU_CP15=y ++CONFIG_CPU_CP15_MMU=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++# CONFIG_CPU_CACHE_ROUND_ROBIN is not set ++# CONFIG_OUTER_CACHE is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++# CONFIG_PCI_SYSCALL is not set ++# CONFIG_ARCH_SUPPORTS_MSI is not set ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++CONFIG_TICK_ONESHOT=y ++CONFIG_NO_HZ=y ++CONFIG_HIGH_RES_TIMERS=y ++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y ++CONFIG_VMSPLIT_3G=y ++# CONFIG_VMSPLIT_2G is not set ++# CONFIG_VMSPLIT_1G is not set ++CONFIG_PAGE_OFFSET=0xC0000000 ++# CONFIG_PREEMPT is not set ++CONFIG_HZ=100 ++CONFIG_AEABI=y ++CONFIG_OABI_COMPAT=y ++CONFIG_ARCH_FLATMEM_HAS_HOLES=y ++# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set ++# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set ++CONFIG_SELECT_MEMORY_MODEL=y ++CONFIG_FLATMEM_MANUAL=y ++# CONFIG_DISCONTIGMEM_MANUAL is not set ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_FLATMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_PAGEFLAGS_EXTENDED=y ++CONFIG_SPLIT_PTLOCK_CPUS=4096 ++# CONFIG_RESOURCES_64BIT is not set ++# CONFIG_PHYS_ADDR_T_64BIT is not set ++CONFIG_ZONE_DMA_FLAG=0 ++CONFIG_VIRT_TO_BUS=y ++CONFIG_UNEVICTABLE_LRU=y ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0 ++CONFIG_ZBOOT_ROM_BSS=0 ++CONFIG_CMDLINE="" ++# CONFIG_XIP_KERNEL is not set ++# CONFIG_KEXEC is not set ++ ++# ++# CPU Power Management ++# ++# CONFIG_CPU_IDLE is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++CONFIG_FPE_NWFPE_XP=y ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_VFP=y ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++CONFIG_HAVE_AOUT=y ++CONFIG_BINFMT_AOUT=y ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Power management options ++# ++CONFIG_PM=y ++# CONFIG_PM_DEBUG is not set ++CONFIG_PM_SLEEP=y ++CONFIG_SUSPEND=y ++CONFIG_SUSPEND_FREEZER=y ++# CONFIG_APM_EMULATION is not set ++CONFIG_ARCH_SUSPEND_POSSIBLE=y ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++# CONFIG_PACKET_MMAP is not set ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++# CONFIG_XFRM_SUB_POLICY is not set ++# CONFIG_XFRM_MIGRATE is not set ++# CONFIG_XFRM_STATISTICS is not set ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE is not set ++# CONFIG_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_XFRM_TUNNEL is not set ++CONFIG_INET_TUNNEL=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=y ++CONFIG_INET_XFRM_MODE_TUNNEL=y ++CONFIG_INET_XFRM_MODE_BEET=y ++# CONFIG_INET_LRO is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_CUBIC=y ++CONFIG_DEFAULT_TCP_CONG="cubic" ++# CONFIG_TCP_MD5SIG is not set ++CONFIG_IPV6=m ++# CONFIG_IPV6_PRIVACY is not set ++# CONFIG_IPV6_ROUTER_PREF is not set ++# CONFIG_IPV6_OPTIMISTIC_DAD is not set ++# CONFIG_INET6_AH is not set ++# CONFIG_INET6_ESP is not set ++# CONFIG_INET6_IPCOMP is not set ++# CONFIG_IPV6_MIP6 is not set ++# CONFIG_INET6_XFRM_TUNNEL is not set ++# CONFIG_INET6_TUNNEL is not set ++CONFIG_INET6_XFRM_MODE_TRANSPORT=m ++CONFIG_INET6_XFRM_MODE_TUNNEL=m ++CONFIG_INET6_XFRM_MODE_BEET=m ++# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set ++CONFIG_IPV6_SIT=m ++CONFIG_IPV6_NDISC_NODETYPE=y ++# CONFIG_IPV6_TUNNEL is not set ++# CONFIG_IPV6_MULTIPLE_TABLES is not set ++# CONFIG_IPV6_MROUTE is not set ++# CONFIG_NETWORK_SECMARK is not set ++# CONFIG_NETFILTER is not set ++# CONFIG_IP_DCCP is not set ++# CONFIG_IP_SCTP is not set ++# CONFIG_TIPC is not set ++# CONFIG_ATM is not set ++# CONFIG_BRIDGE is not set ++# CONFIG_NET_DSA is not set ++CONFIG_VLAN_8021Q=m ++# CONFIG_VLAN_8021Q_GVRP is not set ++# CONFIG_DECNET is not set ++# CONFIG_LLC2 is not set ++# CONFIG_IPX is not set ++# CONFIG_ATALK is not set ++# CONFIG_X25 is not set ++# CONFIG_LAPB is not set ++# CONFIG_ECONET is not set ++CONFIG_WAN_ROUTER=y ++# CONFIG_NET_SCHED is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_CAN is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++# CONFIG_AF_RXRPC is not set ++# CONFIG_PHONET is not set ++# CONFIG_WIRELESS is not set ++# CONFIG_RFKILL is not set ++# CONFIG_NET_9P is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++CONFIG_FIRMWARE_IN_KERNEL=y ++CONFIG_EXTRA_FIRMWARE="" ++# CONFIG_SYS_HYPERVISOR is not set ++CONFIG_CONNECTOR=y ++CONFIG_PROC_EVENTS=y ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++CONFIG_MTD_CONCAT=y ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_REDBOOT_PARTS is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++# CONFIG_MTD_AR7_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLKDEVS=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++# CONFIG_RFD_FTL is not set ++# CONFIG_SSFDC is not set ++# CONFIG_MTD_OOPS is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++# CONFIG_MTD_CFI is not set ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_MAP_BANK_WIDTH_1=y ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++CONFIG_MTD_MAP_BANK_WIDTH_4=y ++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set ++CONFIG_MTD_CFI_I1=y ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++CONFIG_MTD_DATAFLASH=m ++CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y ++# CONFIG_MTD_DATAFLASH_OTP is not set ++CONFIG_MTD_M25P80=y ++CONFIG_M25PXX_USE_FAST_READ=y ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLOCK2MTD is not set ++ ++# ++# Disk-On-Chip Device Drivers ++# ++# CONFIG_MTD_DOC2000 is not set ++# CONFIG_MTD_DOC2001 is not set ++# CONFIG_MTD_DOC2001PLUS is not set ++# CONFIG_MTD_NAND is not set ++# CONFIG_MTD_ONENAND is not set ++ ++# ++# UBI - Unsorted block images ++# ++# CONFIG_MTD_UBI is not set ++# CONFIG_PARPORT is not set ++CONFIG_BLK_DEV=y ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++CONFIG_BLK_DEV_NBD=y ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=16384 ++# CONFIG_BLK_DEV_XIP is not set ++# CONFIG_RD_BZIP2 is not set ++CONFIG_RD_LZMA=y ++CONFIG_RD_GZIP=y ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++CONFIG_MISC_DEVICES=y ++# CONFIG_EEPROM_93CX6 is not set ++# CONFIG_ICS932S401 is not set ++# CONFIG_ENCLOSURE_SERVICES is not set ++# CONFIG_C2PORT is not set ++CONFIG_HAVE_IDE=y ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_DMA=y ++CONFIG_SCSI_TGT=y ++# CONFIG_SCSI_NETLINK is not set ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++CONFIG_CHR_DEV_SG=y ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++CONFIG_SCSI_SCAN_ASYNC=y ++CONFIG_SCSI_WAIT_SCAN=m ++ ++# ++# SCSI Transports ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++CONFIG_SCSI_ISCSI_ATTRS=m ++# CONFIG_SCSI_SAS_LIBSAS is not set ++# CONFIG_SCSI_SRP_ATTRS is not set ++# CONFIG_SCSI_LOWLEVEL is not set ++# CONFIG_SCSI_DH is not set ++# CONFIG_ATA is not set ++# CONFIG_MD is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++CONFIG_BONDING=m ++# CONFIG_MACVLAN is not set ++# CONFIG_EQUALIZER is not set ++CONFIG_TUN=m ++# CONFIG_VETH is not set ++# CONFIG_NET_ETHERNET is not set ++CONFIG_NETDEV_1000=y ++CONFIG_ASPEEDMAC=y ++# CONFIG_NETDEV_10000 is not set ++ ++# ++# Wireless LAN ++# ++# CONFIG_WLAN_PRE80211 is not set ++# CONFIG_WLAN_80211 is not set ++# CONFIG_IWLWIFI_LEDS is not set ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_WAN is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_NETCONSOLE is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++# CONFIG_INPUT_FF_MEMLESS is not set ++# CONFIG_INPUT_POLLDEV is not set ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_STOWAWAY is not set ++# CONFIG_KEYBOARD_GPIO is not set ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_PS2_ALPS=y ++CONFIG_MOUSE_PS2_LOGIPS2PP=y ++CONFIG_MOUSE_PS2_SYNAPTICS=y ++CONFIG_MOUSE_PS2_LIFEBOOK=y ++CONFIG_MOUSE_PS2_TRACKPOINT=y ++# CONFIG_MOUSE_PS2_ELANTECH is not set ++# CONFIG_MOUSE_PS2_TOUCHKIT is not set ++CONFIG_MOUSE_SERIAL=y ++# CONFIG_MOUSE_APPLETOUCH is not set ++# CONFIG_MOUSE_BCM5974 is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_MOUSE_GPIO is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TABLET is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_CONSOLE_TRANSLATIONS=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_VT_HW_CONSOLE_BINDING is not set ++CONFIG_DEVKMEM=y ++CONFIG_SERIAL_NONSTANDARD=y ++# CONFIG_N_HDLC is not set ++# CONFIG_RISCOM8 is not set ++# CONFIG_SPECIALIX is not set ++# CONFIG_RIO is not set ++# CONFIG_STALDRV is not set ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=5 ++CONFIG_SERIAL_8250_RUNTIME_UARTS=5 ++# CONFIG_SERIAL_AST_DMA_UART is not set ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++# CONFIG_SERIAL_AST is not set ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++# CONFIG_IPMI_HANDLER is not set ++CONFIG_AST_MISC=y ++# CONFIG_AST_VIDEO is not set ++# CONFIG_ADC_CAT9883 is not set ++# CONFIG_AST_SPI_BIOS is not set ++CONFIG_AST_PECI=y ++# CONFIG_AST_KCS is not set ++# CONFIG_AST_GPIO is not set ++# CONFIG_HW_RANDOM is not set ++CONFIG_NVRAM=y ++# CONFIG_R3964 is not set ++# CONFIG_RAW_DRIVER is not set ++# CONFIG_TCG_TPM is not set ++CONFIG_I2C=y ++CONFIG_I2C_BOARDINFO=y ++CONFIG_I2C_CHARDEV=y ++CONFIG_I2C_HELPER_AUTO=y ++ ++# ++# I2C Hardware Bus support ++# ++ ++# ++# I2C system bus drivers (mostly embedded / system-on-chip) ++# ++# CONFIG_I2C_GPIO is not set ++# CONFIG_I2C_OCORES is not set ++CONFIG_I2C_AST=y ++CONFIG_AST_I2C_SLAVE_MODE=y ++# CONFIG_AST_I2C_SLAVE_EEPROM is not set ++CONFIG_AST_I2C_SLAVE_RDWR=y ++# CONFIG_I2C_SIMTEC is not set ++ ++# ++# External I2C/SMBus adapter drivers ++# ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_TAOS_EVM is not set ++# CONFIG_I2C_TINY_USB is not set ++ ++# ++# Other I2C/SMBus bus drivers ++# ++# CONFIG_I2C_PCA_PLATFORM is not set ++# CONFIG_I2C_STUB is not set ++ ++# ++# Miscellaneous I2C Chip support ++# ++# CONFIG_DS1682 is not set ++CONFIG_AT24=m ++# CONFIG_SENSORS_EEPROM is not set ++CONFIG_SENSORS_PCF8574=m ++# CONFIG_PCF8575 is not set ++# CONFIG_SENSORS_PCA9539 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_TPS65010 is not set ++# CONFIG_SENSORS_MAX6875 is not set ++# CONFIG_SENSORS_TSL2550 is not set ++# CONFIG_I2C_DEBUG_CORE is not set ++# CONFIG_I2C_DEBUG_ALGO is not set ++# CONFIG_I2C_DEBUG_BUS is not set ++# CONFIG_I2C_DEBUG_CHIP is not set ++CONFIG_SPI=y ++CONFIG_SPI_MASTER=y ++ ++# ++# SPI Master Controller Drivers ++# ++CONFIG_SPI_AST=y ++CONFIG_SPI_FMC=y ++CONFIG_SPI_BITBANG=y ++ ++# ++# SPI Protocol Masters ++# ++CONFIG_SPI_AT25=m ++# CONFIG_SPI_SPIDEV is not set ++# CONFIG_SPI_TLE62X0 is not set ++CONFIG_ARCH_REQUIRE_GPIOLIB=y ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_SYSFS=y ++ ++# ++# Memory mapped GPIO expanders: ++# ++ ++# ++# I2C GPIO expanders: ++# ++# CONFIG_GPIO_MAX732X is not set ++# CONFIG_GPIO_PCA953X is not set ++# CONFIG_GPIO_PCF857X is not set ++ ++# ++# PCI GPIO expanders: ++# ++ ++# ++# SPI GPIO expanders: ++# ++# CONFIG_GPIO_MAX7301 is not set ++# CONFIG_GPIO_MCP23S08 is not set ++# CONFIG_W1 is not set ++# CONFIG_POWER_SUPPLY is not set ++CONFIG_HWMON=y ++# CONFIG_HWMON_VID is not set ++# CONFIG_SENSORS_AD7414 is not set ++# CONFIG_SENSORS_AD7418 is not set ++# CONFIG_SENSORS_ADCXX is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1026 is not set ++# CONFIG_SENSORS_ADM1029 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ADM9240 is not set ++# CONFIG_SENSORS_ADT7462 is not set ++# CONFIG_SENSORS_ADT7470 is not set ++# CONFIG_SENSORS_ADT7473 is not set ++# CONFIG_SENSORS_ATXP1 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_F71805F is not set ++# CONFIG_SENSORS_F71882FG is not set ++# CONFIG_SENSORS_F75375S is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_GL520SM is not set ++# CONFIG_SENSORS_IT87 is not set ++# CONFIG_SENSORS_LM63 is not set ++# CONFIG_SENSORS_LM70 is not set ++CONFIG_SENSORS_LM75=m ++# CONFIG_SENSORS_LM77 is not set ++# CONFIG_SENSORS_LM78 is not set ++# CONFIG_SENSORS_LM80 is not set ++# CONFIG_SENSORS_LM83 is not set ++# CONFIG_SENSORS_LM85 is not set ++# CONFIG_SENSORS_LM87 is not set ++# CONFIG_SENSORS_LM90 is not set ++# CONFIG_SENSORS_LM92 is not set ++# CONFIG_SENSORS_LM93 is not set ++CONFIG_SENSORS_MAX127=m ++# CONFIG_SENSORS_MAX1111 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_MAX6650 is not set ++# CONFIG_SENSORS_PC87360 is not set ++# CONFIG_SENSORS_PC87427 is not set ++# CONFIG_SENSORS_DME1737 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47M192 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++CONFIG_SENSORS_ADS7828=m ++# CONFIG_SENSORS_THMC50 is not set ++# CONFIG_SENSORS_VT1211 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83791D is not set ++# CONFIG_SENSORS_W83792D is not set ++# CONFIG_SENSORS_W83793 is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83L786NG is not set ++# CONFIG_SENSORS_W83627HF is not set ++# CONFIG_SENSORS_W83627EHF is not set ++CONFIG_SENSORS_AST_ADC=y ++CONFIG_SENSORS_AST_PWM_FAN=y ++# CONFIG_SENSORS_FB_PANTHER_PLUS is not set ++CONFIG_PMBUS=m ++CONFIG_SENSORS_PMBUS=m ++CONFIG_SENSORS_ADM1275=m ++# CONFIG_SENSORS_LM25066 is not set ++# CONFIG_SENSORS_LTC2978 is not set ++# CONFIG_SENSORS_MAX16064 is not set ++# CONFIG_SENSORS_MAX34440 is not set ++# CONFIG_SENSORS_MAX8688 is not set ++CONFIG_SENSORS_PFE1100=m ++CONFIG_SENSORS_PFE3000=m ++# CONFIG_SENSORS_UCD9000 is not set ++# CONFIG_SENSORS_UCD9200 is not set ++# CONFIG_SENSORS_ZL6100 is not set ++# CONFIG_HWMON_DEBUG_CHIP is not set ++CONFIG_THERMAL=y ++CONFIG_THERMAL_HWMON=y ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_AST_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++CONFIG_SSB_POSSIBLE=y ++ ++# ++# Sonics Silicon Backplane ++# ++# CONFIG_SSB is not set ++ ++# ++# Multifunction device drivers ++# ++# CONFIG_MFD_CORE is not set ++# CONFIG_MFD_SM501 is not set ++# CONFIG_MFD_ASIC3 is not set ++# CONFIG_HTC_EGPIO is not set ++# CONFIG_HTC_PASIC3 is not set ++# CONFIG_MFD_TMIO is not set ++# CONFIG_MFD_TC6393XB is not set ++# CONFIG_PMIC_DA903X is not set ++# CONFIG_MFD_WM8400 is not set ++# CONFIG_MFD_WM8350_I2C is not set ++ ++# ++# Multimedia devices ++# ++ ++# ++# Multimedia core support ++# ++# CONFIG_VIDEO_DEV is not set ++# CONFIG_DVB_CORE is not set ++# CONFIG_VIDEO_MEDIA is not set ++ ++# ++# Multimedia drivers ++# ++# CONFIG_DAB is not set ++ ++# ++# Graphics support ++# ++# CONFIG_VGASTATE is not set ++# CONFIG_VIDEO_OUTPUT_CONTROL is not set ++# CONFIG_FB is not set ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Display device support ++# ++# CONFIG_DISPLAY_SUPPORT is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++# CONFIG_SOUND is not set ++# CONFIG_HID_SUPPORT is not set ++CONFIG_USB_SUPPORT=y ++CONFIG_USB_ARCH_HAS_HCD=y ++# CONFIG_USB_ARCH_HAS_OHCI is not set ++CONFIG_USB_ARCH_HAS_EHCI=y ++CONFIG_USB=m ++# CONFIG_USB_DEBUG is not set ++# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++CONFIG_USB_DEVICE_CLASS=y ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_SUSPEND is not set ++# CONFIG_USB_OTG is not set ++# CONFIG_USB_MON is not set ++# CONFIG_USB_WUSB is not set ++# CONFIG_USB_WUSB_CBAF is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_C67X00_HCD is not set ++# CONFIG_USB_EHCI_HCD is not set ++# CONFIG_USB_ISP116X_HCD is not set ++# CONFIG_USB_SL811_HCD is not set ++# CONFIG_USB_R8A66597_HCD is not set ++# CONFIG_USB_HWA_HCD is not set ++ ++# ++# AST USB Drivers ++# ++CONFIG_AST_USB_UHCI_HCD=y ++# CONFIG_AST_USB_UHCI_MULTIPORT_1 is not set ++# CONFIG_AST_USB_UHCI_MULTIPORT_2 is not set ++CONFIG_AST_USB_UHCI_MULTIPORT_4=y ++# CONFIG_USB_EHCI_SPLIT_ISO is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++# CONFIG_USB_WDM is not set ++# CONFIG_USB_TMC is not set ++ ++# ++# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; ++# ++ ++# ++# see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=m ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++# CONFIG_USB_STORAGE_ALAUDA is not set ++# CONFIG_USB_STORAGE_ONETOUCH is not set ++# CONFIG_USB_STORAGE_KARMA is not set ++# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set ++# CONFIG_USB_LIBUSUAL is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_ADUTUX is not set ++# CONFIG_USB_SEVSEG is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_BERRY_CHARGE is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYPRESS_CY7C63 is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGET is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_FTDI_ELAN is not set ++# CONFIG_USB_APPLEDISPLAY is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TRANCEVIBRATOR is not set ++# CONFIG_USB_IOWARRIOR is not set ++# CONFIG_USB_TEST is not set ++# CONFIG_USB_ISIGHTFW is not set ++# CONFIG_USB_VST is not set ++CONFIG_USB_GADGET=y ++# CONFIG_USB_GADGET_DEBUG_FILES is not set ++CONFIG_USB_GADGET_VBUS_DRAW=2 ++CONFIG_USB_GADGET_SELECTED=y ++# CONFIG_USB_GADGET_AT91 is not set ++# CONFIG_USB_GADGET_ATMEL_USBA is not set ++# CONFIG_USB_GADGET_FSL_USB2 is not set ++# CONFIG_USB_GADGET_LH7A40X is not set ++# CONFIG_USB_GADGET_OMAP is not set ++# CONFIG_USB_GADGET_PXA25X is not set ++# CONFIG_USB_GADGET_PXA27X is not set ++# CONFIG_USB_GADGET_S3C2410 is not set ++# CONFIG_USB_GADGET_M66592 is not set ++# CONFIG_USB_GADGET_AMD5536UDC is not set ++# CONFIG_USB_GADGET_FSL_QE is not set ++# CONFIG_USB_GADGET_NET2280 is not set ++# CONFIG_USB_GADGET_GOKU is not set ++CONFIG_USB_GADGET_ASPEED_AST=y ++CONFIG_USB_ASPEED_AST=y ++# CONFIG_USB_GADGET_DUMMY_HCD is not set ++CONFIG_USB_GADGET_DUALSPEED=y ++CONFIG_USB_ZERO=m ++CONFIG_USB_ETH=m ++CONFIG_USB_ETH_RNDIS=y ++CONFIG_USB_GADGETFS=m ++CONFIG_USB_FILE_STORAGE=m ++# CONFIG_USB_FILE_STORAGE_TEST is not set ++CONFIG_USB_G_SERIAL=m ++# CONFIG_USB_MIDI_GADGET is not set ++# CONFIG_USB_G_PRINTER is not set ++CONFIG_USB_CDC_COMPOSITE=m ++# CONFIG_MMC is not set ++# CONFIG_MEMSTICK is not set ++# CONFIG_ACCESSIBILITY is not set ++# CONFIG_NEW_LEDS is not set ++CONFIG_RTC_LIB=y ++CONFIG_RTC_CLASS=y ++# CONFIG_RTC_HCTOSYS is not set ++# CONFIG_RTC_DEBUG is not set ++ ++# ++# RTC interfaces ++# ++CONFIG_RTC_INTF_SYSFS=y ++CONFIG_RTC_INTF_PROC=y ++CONFIG_RTC_INTF_DEV=y ++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set ++# CONFIG_RTC_DRV_TEST is not set ++ ++# ++# I2C RTC drivers ++# ++# CONFIG_RTC_DRV_DS1307 is not set ++# CONFIG_RTC_DRV_DS1374 is not set ++# CONFIG_RTC_DRV_DS1672 is not set ++# CONFIG_RTC_DRV_MAX6900 is not set ++# CONFIG_RTC_DRV_RS5C372 is not set ++# CONFIG_RTC_DRV_ISL1208 is not set ++# CONFIG_RTC_DRV_X1205 is not set ++# CONFIG_RTC_DRV_PCF8563 is not set ++# CONFIG_RTC_DRV_PCF8583 is not set ++# CONFIG_RTC_DRV_M41T80 is not set ++# CONFIG_RTC_DRV_S35390A is not set ++# CONFIG_RTC_DRV_FM3130 is not set ++# CONFIG_RTC_DRV_RX8581 is not set ++ ++# ++# SPI RTC drivers ++# ++# CONFIG_RTC_DRV_M41T94 is not set ++# CONFIG_RTC_DRV_DS1305 is not set ++# CONFIG_RTC_DRV_DS1390 is not set ++# CONFIG_RTC_DRV_MAX6902 is not set ++# CONFIG_RTC_DRV_R9701 is not set ++# CONFIG_RTC_DRV_RS5C348 is not set ++# CONFIG_RTC_DRV_DS3234 is not set ++ ++# ++# Platform RTC drivers ++# ++# CONFIG_RTC_DRV_CMOS is not set ++# CONFIG_RTC_DRV_DS1286 is not set ++# CONFIG_RTC_DRV_DS1511 is not set ++# CONFIG_RTC_DRV_DS1553 is not set ++# CONFIG_RTC_DRV_DS1742 is not set ++# CONFIG_RTC_DRV_STK17TA8 is not set ++# CONFIG_RTC_DRV_M48T86 is not set ++# CONFIG_RTC_DRV_M48T35 is not set ++# CONFIG_RTC_DRV_M48T59 is not set ++# CONFIG_RTC_DRV_BQ4802 is not set ++# CONFIG_RTC_DRV_V3020 is not set ++ ++# ++# on-CPU RTC drivers ++# ++# CONFIG_RTC_DRV_PL030 is not set ++# CONFIG_RTC_DRV_PL031 is not set ++CONFIG_RTC_DRV_ASPEED=y ++# CONFIG_DMADEVICES is not set ++# CONFIG_REGULATOR is not set ++# CONFIG_UIO is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++# CONFIG_EXT2_FS_XIP is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_EXT4_FS is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++CONFIG_FS_POSIX_ACL=y ++CONFIG_FILE_LOCKING=y ++# CONFIG_XFS_FS is not set ++# CONFIG_OCFS2_FS is not set ++CONFIG_DNOTIFY=y ++CONFIG_INOTIFY=y ++CONFIG_INOTIFY_USER=y ++# CONFIG_QUOTA is not set ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_FS is not set ++# CONFIG_FUSE_FS is not set ++CONFIG_GENERIC_ACL=y ++ ++# ++# CD-ROM/DVD Filesystems ++# ++# CONFIG_ISO9660_FS is not set ++# CONFIG_UDF_FS is not set ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_NTFS_FS=y ++# CONFIG_NTFS_DEBUG is not set ++CONFIG_NTFS_RW=y ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_PROC_SYSCTL=y ++CONFIG_PROC_PAGE_MONITOR=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++CONFIG_TMPFS_POSIX_ACL=y ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_CONFIGFS_FS=m ++ ++# ++# Miscellaneous filesystems ++# ++# CONFIG_ADFS_FS is not set ++# CONFIG_AFFS_FS is not set ++# CONFIG_HFS_FS is not set ++# CONFIG_HFSPLUS_FS is not set ++# CONFIG_BEFS_FS is not set ++# CONFIG_BFS_FS is not set ++# CONFIG_EFS_FS is not set ++CONFIG_YAFFS_FS=y ++CONFIG_YAFFS_YAFFS1=y ++# CONFIG_YAFFS_9BYTE_TAGS is not set ++# CONFIG_YAFFS_DOES_ECC is not set ++CONFIG_YAFFS_YAFFS2=y ++CONFIG_YAFFS_AUTO_YAFFS2=y ++# CONFIG_YAFFS_DISABLE_TAGS_ECC is not set ++# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set ++# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set ++# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set ++CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y ++# CONFIG_YAFFS_EMPTY_LOST_AND_FOUND is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set ++# CONFIG_JFFS2_SUMMARY is not set ++# CONFIG_JFFS2_FS_XATTR is not set ++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set ++CONFIG_JFFS2_ZLIB=y ++# CONFIG_JFFS2_LZO is not set ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_CRAMFS is not set ++# CONFIG_VXFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_OMFS_FS is not set ++# CONFIG_HPFS_FS is not set ++# CONFIG_QNX4FS_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_SYSV_FS is not set ++# CONFIG_UFS_FS is not set ++CONFIG_NETWORK_FILESYSTEMS=y ++CONFIG_NFS_FS=y ++# CONFIG_NFS_V3 is not set ++# CONFIG_NFS_V4 is not set ++CONFIG_ROOT_NFS=y ++# CONFIG_NFSD is not set ++CONFIG_LOCKD=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_SUNRPC_REGISTER_V4 is not set ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS is not set ++# CONFIG_CIFS is not set ++# CONFIG_NCP_FS is not set ++# CONFIG_CODA_FS is not set ++# CONFIG_AFS_FS is not set ++ ++# ++# Partition Types ++# ++# CONFIG_PARTITION_ADVANCED is not set ++CONFIG_MSDOS_PARTITION=y ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="utf8" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++# CONFIG_NLS_CODEPAGE_850 is not set ++# CONFIG_NLS_CODEPAGE_852 is not set ++# CONFIG_NLS_CODEPAGE_855 is not set ++# CONFIG_NLS_CODEPAGE_857 is not set ++# CONFIG_NLS_CODEPAGE_860 is not set ++# CONFIG_NLS_CODEPAGE_861 is not set ++# CONFIG_NLS_CODEPAGE_862 is not set ++# CONFIG_NLS_CODEPAGE_863 is not set ++# CONFIG_NLS_CODEPAGE_864 is not set ++# CONFIG_NLS_CODEPAGE_865 is not set ++# CONFIG_NLS_CODEPAGE_866 is not set ++# CONFIG_NLS_CODEPAGE_869 is not set ++CONFIG_NLS_CODEPAGE_936=y ++CONFIG_NLS_CODEPAGE_950=y ++CONFIG_NLS_CODEPAGE_932=y ++# CONFIG_NLS_CODEPAGE_949 is not set ++# CONFIG_NLS_CODEPAGE_874 is not set ++# CONFIG_NLS_ISO8859_8 is not set ++# CONFIG_NLS_CODEPAGE_1250 is not set ++# CONFIG_NLS_CODEPAGE_1251 is not set ++CONFIG_NLS_ASCII=y ++CONFIG_NLS_ISO8859_1=y ++# CONFIG_NLS_ISO8859_2 is not set ++# CONFIG_NLS_ISO8859_3 is not set ++# CONFIG_NLS_ISO8859_4 is not set ++# CONFIG_NLS_ISO8859_5 is not set ++# CONFIG_NLS_ISO8859_6 is not set ++# CONFIG_NLS_ISO8859_7 is not set ++# CONFIG_NLS_ISO8859_9 is not set ++# CONFIG_NLS_ISO8859_13 is not set ++# CONFIG_NLS_ISO8859_14 is not set ++# CONFIG_NLS_ISO8859_15 is not set ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=y ++# CONFIG_DLM is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++# CONFIG_ENABLE_WARN_DEPRECATED is not set ++CONFIG_ENABLE_MUST_CHECK=y ++CONFIG_FRAME_WARN=1024 ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_UNUSED_SYMBOLS is not set ++# CONFIG_DEBUG_FS is not set ++# CONFIG_HEADERS_CHECK is not set ++# CONFIG_DEBUG_KERNEL is not set ++# CONFIG_SLUB_DEBUG_ON is not set ++# CONFIG_SLUB_STATS is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_MEMORY_INIT=y ++CONFIG_FRAME_POINTER=y ++# CONFIG_RCU_CPU_STALL_DETECTOR is not set ++# CONFIG_LATENCYTOP is not set ++# CONFIG_SYSCTL_SYSCALL_CHECK is not set ++CONFIG_HAVE_FUNCTION_TRACER=y ++ ++# ++# Tracers ++# ++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set ++# CONFIG_SAMPLES is not set ++CONFIG_HAVE_ARCH_KGDB=y ++# CONFIG_DEBUG_USER is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++# CONFIG_SECURITYFS is not set ++# CONFIG_SECURITY_FILE_CAPABILITIES is not set ++CONFIG_CRYPTO=y ++ ++# ++# Crypto core or helper ++# ++# CONFIG_CRYPTO_FIPS is not set ++CONFIG_CRYPTO_ALGAPI=y ++CONFIG_CRYPTO_ALGAPI2=y ++CONFIG_CRYPTO_AEAD=m ++CONFIG_CRYPTO_AEAD2=y ++CONFIG_CRYPTO_BLKCIPHER=y ++CONFIG_CRYPTO_BLKCIPHER2=y ++CONFIG_CRYPTO_HASH=y ++CONFIG_CRYPTO_HASH2=y ++CONFIG_CRYPTO_RNG2=y ++CONFIG_CRYPTO_MANAGER=y ++CONFIG_CRYPTO_MANAGER2=y ++# CONFIG_CRYPTO_GF128MUL is not set ++CONFIG_CRYPTO_NULL=y ++# CONFIG_CRYPTO_CRYPTD is not set ++CONFIG_CRYPTO_AUTHENC=m ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Authenticated Encryption with Associated Data ++# ++# CONFIG_CRYPTO_CCM is not set ++# CONFIG_CRYPTO_GCM is not set ++# CONFIG_CRYPTO_SEQIV is not set ++ ++# ++# Block modes ++# ++CONFIG_CRYPTO_CBC=y ++# CONFIG_CRYPTO_CTR is not set ++# CONFIG_CRYPTO_CTS is not set ++# CONFIG_CRYPTO_ECB is not set ++# CONFIG_CRYPTO_LRW is not set ++# CONFIG_CRYPTO_PCBC is not set ++# CONFIG_CRYPTO_XTS is not set ++ ++# ++# Hash modes ++# ++CONFIG_CRYPTO_HMAC=y ++# CONFIG_CRYPTO_XCBC is not set ++ ++# ++# Digest ++# ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_RMD128 is not set ++# CONFIG_CRYPTO_RMD160 is not set ++# CONFIG_CRYPTO_RMD256 is not set ++# CONFIG_CRYPTO_RMD320 is not set ++CONFIG_CRYPTO_SHA1=y ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++# CONFIG_CRYPTO_WP512 is not set ++ ++# ++# Ciphers ++# ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_CAMELLIA is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_FCRYPT is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_SALSA20 is not set ++# CONFIG_CRYPTO_SEED is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++ ++# ++# Compression ++# ++CONFIG_CRYPTO_DEFLATE=m ++# CONFIG_CRYPTO_LZO is not set ++ ++# ++# Random Number Generation ++# ++# CONFIG_CRYPTO_ANSI_CPRNG is not set ++# CONFIG_CRYPTO_HW is not set ++ ++# ++# Library routines ++# ++CONFIG_BITREVERSE=y ++# CONFIG_CRC_CCITT is not set ++# CONFIG_CRC16 is not set ++# CONFIG_CRC_T10DIF is not set ++CONFIG_CRC_ITU_T=m ++CONFIG_CRC32=y ++# CONFIG_CRC7 is not set ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y ++CONFIG_PLIST=y ++CONFIG_HAS_IOMEM=y ++CONFIG_HAS_IOPORT=y ++CONFIG_HAS_DMA=y ++ ++ ++# GUC USB Drivers ++# ++CONFIG_GUC_USB_UHCI_HCD=m ++# CONFIG_GUC_USB_UHCI_MULTIPORT_1 is not set ++# CONFIG_GUC_USB_UHCI_MULTIPORT_2 is not set ++CONFIG_GUC_USB_UHCI_MULTIPORT_4=y ++# CONFIG_USB_GADGET_MUSB_HDRC is not set +diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h +index a91d8a1..fd50ffe 100644 +--- a/arch/arm/include/asm/ioctls.h ++++ b/arch/arm/include/asm/ioctls.h +@@ -65,6 +65,7 @@ + #define TIOCSERGETLSR 0x5459 /* Get line status register */ + #define TIOCSERGETMULTI 0x545A /* Get multiport config */ + #define TIOCSERSETMULTI 0x545B /* Set multiport config */ ++#define TIOCSERWAITTEMT 0x5499 /* Wait for empty */ + + #define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ + #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig +index a948ab8..6d548f8 100644 +--- a/arch/arm/mach-aspeed/Kconfig ++++ b/arch/arm/mach-aspeed/Kconfig +@@ -203,6 +203,18 @@ endchoice + config AST_SCU_LOCK + bool "AST SCU Protection Key" + ++config WEDGE ++ bool "Facebook Wedge/6-Pack" ++ ++config WEDGE100 ++ bool "Facebook Wedge100" ++ ++config YOSEMITE ++ bool "Facebook Yosemite" ++ ++config FBPLATFORM1 ++ bool "Facebook Platform1" ++ + # Support PCIE + config PCIE + bool "ASPEED PCIE support" +diff --git a/arch/arm/mach-aspeed/gpio.c b/arch/arm/mach-aspeed/gpio.c +index 3a633e9..e56ca35 100644 +--- a/arch/arm/mach-aspeed/gpio.c ++++ b/arch/arm/mach-aspeed/gpio.c +@@ -232,7 +232,7 @@ static struct ast_gpio_bank ast_gpio_gp[] = { + AST_GPIO_BANK("GPIOR", IO_ADDRESS(AST_GPIO_BASE), 1, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110), + AST_GPIO_BANK("GPIOS", IO_ADDRESS(AST_GPIO_BASE), 2, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110), + #if defined(CONFIG_ARCH_AST2400) +- AST_GPIO_BANK("GPIOT", IO_ADDRESS(AST_GPIO_BASE), 4, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110), ++ AST_GPIO_BANK("GPIOT", IO_ADDRESS(AST_GPIO_BASE), 3, 0x080, 0x084, 0x118, 0x11c, 0x128, 0x12c, 0x130, 0x110), + AST_GPIO_BANK("GPIOU", IO_ADDRESS(AST_GPIO_BASE), 0, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140), + AST_GPIO_BANK("GPIOV", IO_ADDRESS(AST_GPIO_BASE), 1, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140), + AST_GPIO_BANK("GPIOW", IO_ADDRESS(AST_GPIO_BASE), 2, 0x088, 0x08c, 0x148, 0x14c, 0x158, 0x15c, 0x160, 0x140), +diff --git a/arch/arm/mach-aspeed/include/mach/debug-macro.S b/arch/arm/mach-aspeed/include/mach/debug-macro.S +index ff3195a..33fc879 100644 +--- a/arch/arm/mach-aspeed/include/mach/debug-macro.S ++++ b/arch/arm/mach-aspeed/include/mach/debug-macro.S +@@ -13,8 +13,8 @@ + .macro addruart, rx, tmp + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? +- ldreq \rx, =AST_UART3_BASE +- ldrne \rx, =IO_ADDRESS(AST_UART3_BASE) ++ ldreq \rx, =AST_UART_BASE ++ ldrne \rx, =IO_ADDRESS(AST_UART_BASE) + .endm + + #define UART_SHIFT 2 +diff --git a/arch/arm/mach-aspeed/include/mach/platform.h b/arch/arm/mach-aspeed/include/mach/platform.h +index 8951ffc..4d6c50c 100644 +--- a/arch/arm/mach-aspeed/include/mach/platform.h ++++ b/arch/arm/mach-aspeed/include/mach/platform.h +@@ -62,5 +62,20 @@ + * Watchdog + */ + #define AST_WDT_VA_BASE (IO_ADDRESS(AST_WDT_BASE)) +- ++ ++/* ++ * Console UART ++ */ ++#ifdef CONFIG_WEDGE ++#define AST_UART_BASE AST_UART3_BASE ++#elif defined(CONFIG_WEDGE100) ++#define AST_UART_BASE AST_UART3_BASE ++#elif defined(CONFIG_YOSEMITE) ++#define AST_UART_BASE AST_UART0_BASE ++#elif defined(CONFIG_FBPLATFORM1) ++#define AST_UART_BASE AST_UART0_BASE ++#else ++#define AST_UART_BASE AST_UART0_BASE ++#endif ++ + #endif +diff --git a/arch/arm/mach-aspeed/include/mach/uncompress.h b/arch/arm/mach-aspeed/include/mach/uncompress.h +index 80e560d..3be04b0 100644 +--- a/arch/arm/mach-aspeed/include/mach/uncompress.h ++++ b/arch/arm/mach-aspeed/include/mach/uncompress.h +@@ -12,8 +12,8 @@ + #include <mach/platform.h> + #include <mach/aspeed_serial.h> + +-#define UART_PUT_CHAR (*(volatile unsigned char *)(AST_UART3_BASE + UART_THR)) +-#define UART_GET_LSR (*(volatile unsigned char *)(AST_UART3_BASE + UART_LSR)) ++#define UART_PUT_CHAR (*(volatile unsigned char *)(AST_UART_BASE + UART_THR)) ++#define UART_GET_LSR (*(volatile unsigned char *)(AST_UART_BASE + UART_LSR)) + + static void putc(int c) + { +@@ -21,7 +21,7 @@ static void putc(int c) + /* wait for space in the UART's transmitter */ + while (!(UART_GET_LSR & UART_LSR_THRE)) + barrier(); +- ++ + /* send the character out. */ + UART_PUT_CHAR = c; + } +diff --git a/arch/arm/mach-aspeed/include/mach/vmalloc.h b/arch/arm/mach-aspeed/include/mach/vmalloc.h +index 51912ae..bc1b471 100644 +--- a/arch/arm/mach-aspeed/include/mach/vmalloc.h ++++ b/arch/arm/mach-aspeed/include/mach/vmalloc.h +@@ -25,5 +25,5 @@ + #define VMALLOC_VMADDR(x) ((unsigned long)(x)) + #define VMALLOC_END (PAGE_OFFSET + 0x20000000) + #else +-#define VMALLOC_END 0xf8000000UL +-#endif +\ No newline at end of file ++#define VMALLOC_END 0xf8000000UL ++#endif +diff --git a/arch/arm/plat-aspeed/ast-scu.c b/arch/arm/plat-aspeed/ast-scu.c +index 76722f4..101b141 100644 +--- a/arch/arm/plat-aspeed/ast-scu.c ++++ b/arch/arm/plat-aspeed/ast-scu.c +@@ -1,20 +1,20 @@ + /******************************************************************************** +-* File Name : arch/arm/plat-aspeed/ast-scu.c ++* File Name : arch/arm/plat-aspeed/ast-scu.c + * Author : Ryan Chen +-* Description : AST SCU +-* ++* Description : AST SCU ++* + * Copyright (C) 2012-2020 ASPEED Technology 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. +-* You should have received a copy of the GNU General Public License +-* along with this program; if not, write to the Free Software +-* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +- +-CLK24M ++* 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. ++* You should have received a copy of the GNU General Public License ++* along with this program; if not, write to the Free Software ++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++CLK24M + | + |--> H-PLL -->HCLK + | +@@ -27,9 +27,9 @@ CLK24M + |--> USB2PHY -->UTMICLK + + +-* History : ++* History : + * 1. 2012/08/15 Ryan Chen Create +-* ++* + ********************************************************************************/ + #include <linux/kernel.h> + #include <linux/module.h> +@@ -56,34 +56,34 @@ CLK24M + + static u32 ast_scu_base = IO_ADDRESS(AST_SCU_BASE); + +-static inline u32 ++static inline u32 + ast_scu_read(u32 reg) + { + u32 val; +- ++ + val = readl(ast_scu_base + reg); +- ++ + SCUDBUG("ast_scu_read : reg = 0x%08x, val = 0x%08x\n", reg, val); +- ++ + return val; + } + + static inline void +-ast_scu_write(u32 val, u32 reg) ++ast_scu_write(u32 val, u32 reg) + { + SCUDBUG("ast_scu_write : reg = 0x%08x, val = 0x%08x\n", reg, val); + #ifdef CONFIG_AST_SCU_LOCK +- //unlock ++ //unlock + writel(SCU_PROTECT_UNLOCK, ast_scu_base); + writel(val, ast_scu_base + reg); + //lock +- writel(0xaa,ast_scu_base); ++ writel(0xaa,ast_scu_base); + #else + writel(val, ast_scu_base + reg); + #endif + } + +-//SoC mapping Table ++//SoC mapping Table + struct soc_id { + const char * name; + u32 rev_id; +@@ -180,9 +180,9 @@ ast_scu_init_video(u8 dynamic_en) + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_VIDEO_SLOW_MASK) | SCU_CLK_VIDEO_SLOW_EN | SCU_CLK_VIDEO_SLOW_SET(0), AST_SCU_CLK_SEL); + else + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_ECLK_SOURCE_MASK) | SCU_ECLK_SOURCE(2), AST_SCU_CLK_SEL); +- ++ + // Enable CLK +- ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~(SCU_ECLK_STOP_EN | SCU_VCLK_STOP_EN), AST_SCU_CLK_STOP); ++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~(SCU_ECLK_STOP_EN | SCU_VCLK_STOP_EN), AST_SCU_CLK_STOP); + mdelay(10); + ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_VIDEO, AST_SCU_RESET); + udelay(100); +@@ -201,32 +201,32 @@ ast_scu_init_eth(u8 num) + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_MAC_MASK) | SCU_CLK_MAC_DIV(4), AST_SCU_CLK_SEL); + + //Set MAC delay Timing +- ast_scu_write(0x2255, AST_SCU_MAC_CLK); ++ ast_scu_write(0x2255, AST_SCU_MAC_CLK); + + switch(num) { + case 0: +- ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC0, +- AST_SCU_RESET); ++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC0, ++ AST_SCU_RESET); + udelay(100); +- ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC0CLK_STOP_EN, +- AST_SCU_CLK_STOP); ++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC0CLK_STOP_EN, ++ AST_SCU_CLK_STOP); + udelay(1000); +- ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC0, +- AST_SCU_RESET); +- ++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC0, ++ AST_SCU_RESET); ++ + break; + case 1: +- ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC1, +- AST_SCU_RESET); ++ ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_MAC1, ++ AST_SCU_RESET); + udelay(100); +- ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC1CLK_STOP_EN, +- AST_SCU_CLK_STOP); ++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_MAC1CLK_STOP_EN, ++ AST_SCU_CLK_STOP); + udelay(1000); +- ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC1, +- AST_SCU_RESET); ++ ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_MAC1, ++ AST_SCU_RESET); + break; +- +- } ++ ++ } + } + + +@@ -292,7 +292,7 @@ ast_scu_init_sdhci(void) + { + //SDHCI Host's Clock Enable and Reset + ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_SD, AST_SCU_RESET); +- ++ + ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) & ~SCU_SDCLK_STOP_EN, AST_SCU_CLK_STOP); + mdelay(10); + +@@ -300,10 +300,10 @@ ast_scu_init_sdhci(void) + mdelay(10); + + // SDCLK = H-PLL / 4 +- ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_SD_MASK) | SCU_CLK_SD_DIV(1), ++ ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_SD_MASK) | SCU_CLK_SD_DIV(1), + AST_SCU_CLK_SEL); + mdelay(10); +- ++ + ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_SD, AST_SCU_RESET); + } + +@@ -358,13 +358,13 @@ EXPORT_SYMBOL(ast_scu_init_jtag); + extern void + ast_scu_init_lpc(void) + { +- //Note .. It have been enable in U-boot..... ++ //Note .. It have been enable in U-boot..... + // ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_LPC, AST_SCU_RESET); + + //enable LPC clock LHCLK = H-PLL/8 +- ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) | +- SCU_SET_LHCLK_DIV(3) | +- SCU_LHCLK_SOURCE_EN, ++ ast_scu_write(ast_scu_read(AST_SCU_CLK_STOP) | ++ SCU_SET_LHCLK_DIV(3) | ++ SCU_LHCLK_SOURCE_EN, + AST_SCU_CLK_STOP); + + } +@@ -377,7 +377,7 @@ ast_scu_get_lpc_plus_enable(void) + { + if(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & SCU_FUN_PIN_LPC_PLUS) + return 1; +- else ++ else + return 0; + } + +@@ -390,10 +390,10 @@ ast_scu_init_crt(void) + #if defined(CONFIG_AST_DAC) || defined(CONFIG_AST_DVO) + ast_scu_write((ast_scu_read(AST_SCU_MISC1_CTRL) & ~(SCU_MISC_D2_PLL_DIS | SCU_MISC_DAC_MASK)) + | SCU_MISC_DAC_SOURCE_CRT | SCU_MISC_DVO_SOURCE_CRT | SCU_MISC_2D_CRT_EN , AST_SCU_MISC1_CTRL); +-#elif defined(CONFIG_AST_DVO) ++#elif defined(CONFIG_AST_DVO) + ast_scu_write((ast_scu_read(AST_SCU_MISC1_CTRL) & ~(SCU_MISC_D2_PLL_DIS)) | + SCU_MISC_DVO_SOURCE_CRT| SCU_MISC_2D_CRT_EN, AST_SCU_MISC1_CTRL); +-#else //default(CONFIG_AST_DAC) ++#else //default(CONFIG_AST_DAC) + ast_scu_write((ast_scu_read(AST_SCU_MISC1_CTRL) & ~(SCU_MISC_D2_PLL_DIS | SCU_MISC_DAC_MASK)) + | SCU_MISC_DAC_SOURCE_CRT | SCU_MISC_2D_CRT_EN, AST_SCU_MISC1_CTRL); + #endif +@@ -401,7 +401,7 @@ ast_scu_init_crt(void) + ast_scu_write((ast_scu_read(AST_SCU_CLK_SEL) & ~SCU_CLK_VIDEO_DELAY_MASK) | + SCU_CLK_VIDEO_DELAY(5), AST_SCU_CLK_SEL); + +- /* Reset CRT */ ++ /* Reset CRT */ + ast_scu_write(ast_scu_read(AST_SCU_RESET) | SCU_RESET_CRT, AST_SCU_RESET); + + //enable D2 CLK +@@ -409,7 +409,7 @@ ast_scu_init_crt(void) + + udelay(10); + ast_scu_write(ast_scu_read(AST_SCU_RESET) & ~SCU_RESET_CRT, AST_SCU_RESET); +- ++ + } + + EXPORT_SYMBOL(ast_scu_init_crt); +@@ -448,7 +448,7 @@ ast_get_h_pll_clk(void) + + if(h_pll_set & SCU_H_PLL_OFF) + return 0; +- ++ + if(h_pll_set & SCU_H_PLL_PARAMETER) { + // Programming + clk = ast_get_clk_source(); +@@ -470,21 +470,21 @@ ast_get_h_pll_clk(void) + speed = SCU_HW_STRAP_GET_H_PLL_CLK(ast_scu_read(AST_SCU_HW_STRAP1)); + switch (speed) { + case 0: +- clk = 384000000; ++ clk = 384000000; + break; + case 1: +- clk = 360000000; ++ clk = 360000000; + break; + case 2: +- clk = 336000000; ++ clk = 336000000; + break; + case 3: +- clk = 408000000; ++ clk = 408000000; + break; + default: +- BUG(); ++ BUG(); + break; +- } ++ } + } + SCUDBUG("h_pll = %d\n",clk); + return clk; +@@ -500,7 +500,7 @@ ast_get_m_pll_clk(void) + + if(m_pll_set & SCU_M_PLL_OFF) + return 0; +- ++ + // Programming + clk = ast_get_clk_source(); + if(m_pll_set & SCU_M_PLL_BYPASS_EN) { +@@ -542,10 +542,10 @@ ast_get_ahbclk(void) + case 3: + div = 4; + break; +- ++ + } +- +- SCUDBUG("HPLL=%d, Div=%d, AHB CLK=%d\n", hpll, div, hpll/div); ++ ++ SCUDBUG("HPLL=%d, Div=%d, AHB CLK=%d\n", hpll, div, hpll/div); + return (hpll/div); + + } +@@ -559,8 +559,8 @@ ast_get_pclk(void) + hpll = ast_get_h_pll_clk(); + div = SCU_GET_PCLK_DIV(ast_scu_read(AST_SCU_CLK_SEL)); + div = (div+1) << 1; +- +- SCUDBUG("HPLL=%d, Div=%d, PCLK=%d\n", hpll, div, hpll/div); ++ ++ SCUDBUG("HPLL=%d, Div=%d, PCLK=%d\n", hpll, div, hpll/div); + return (hpll/div); + + } +@@ -572,7 +572,7 @@ ast_get_lhclk(void) + unsigned int div, hpll; + u32 clk_sel = ast_scu_read(AST_SCU_CLK_SEL); + //FPGA AST1070 is default 100/2 Mhz input +-// return 50000000; ++// return 50000000; + hpll = ast_get_h_pll_clk(); + if(SCU_LHCLK_SOURCE_EN & clk_sel) { + div = SCU_GET_LHCLK_DIV(clk_sel); +@@ -600,10 +600,10 @@ ast_get_lhclk(void) + break; + case 7: + div = 16; +- break; ++ break; + } +- +- SCUDBUG("HPLL=%d, Div=%d, LHCLK = %d\n", hpll, div, hpll/div); ++ ++ SCUDBUG("HPLL=%d, Div=%d, LHCLK = %d\n", hpll, div, hpll/div); + return (hpll/div); + } else { + SCUMSG("LPC CLK not enable \n"); +@@ -704,7 +704,7 @@ ast_get_sd_clock_src(void) + sd_div = SCU_CLK_SD_GET_DIV(ast_scu_read(AST_SCU_CLK_SEL)); + SCUDBUG("div %d, sdclk =%d \n",((sd_div + 1) * 2),clk/((sd_div + 1) * 2)); + clk /= ((sd_div + 1) * 2); +- ++ + #endif + return clk; + } +@@ -717,7 +717,7 @@ ast_scu_show_system_info (void) + u32 h_pll, div; + + h_pll = ast_get_h_pll_clk(); +- ++ + div = SCU_HW_STRAP_GET_CPU_AHB_RATIO(ast_scu_read(AST_SCU_HW_STRAP1)); + switch(div) { + case 0: +@@ -732,10 +732,10 @@ ast_scu_show_system_info (void) + case 3: + div = 4; + break; +- ++ + } + +- SCUMSG("CPU = %d MHz ,AHB = %d MHz (%d:1) \n", h_pll/1000000, h_pll/div/1000000,div); ++ SCUMSG("CPU = %d MHz ,AHB = %d MHz (%d:1) \n", h_pll/1000000, h_pll/div/1000000,div); + + return ; + } +@@ -750,54 +750,68 @@ ast_scu_multi_func_uart(u8 uart) + case 1: + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | + SCU_FUN_PIN_UART1_RXD | ++#ifdef CONFIG_YOSEMITE ++ SCU_FUN_PIN_UART1_TXD, ++#else + SCU_FUN_PIN_UART1_TXD | + SCU_FUN_PIN_UART1_NRTS | + SCU_FUN_PIN_UART1_NDTR | + SCU_FUN_PIN_UART1_NRI | + SCU_FUN_PIN_UART1_NDSR | + SCU_FUN_PIN_UART1_NDCD | +- SCU_FUN_PIN_UART1_NCTS, +- AST_SCU_FUN_PIN_CTRL2); +- break; ++ SCU_FUN_PIN_UART1_NCTS, ++#endif ++ AST_SCU_FUN_PIN_CTRL2); ++ break; + case 2: + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | + SCU_FUN_PIN_UART2_RXD | ++#ifdef CONFIG_YOSEMITE ++ SCU_FUN_PIN_UART2_TXD, ++#else + SCU_FUN_PIN_UART2_TXD | + SCU_FUN_PIN_UART2_NRTS | + SCU_FUN_PIN_UART2_NDTR | + SCU_FUN_PIN_UART2_NRI | + SCU_FUN_PIN_UART2_NDSR | + SCU_FUN_PIN_UART2_NDCD | +- SCU_FUN_PIN_UART2_NCTS, +- AST_SCU_FUN_PIN_CTRL2); +- break; ++ SCU_FUN_PIN_UART2_NCTS, ++#endif ++ AST_SCU_FUN_PIN_CTRL2); ++ break; + case 3: + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | + SCU_FUN_PIN_UART3_RXD | ++#ifdef CONFIG_YOSEMITE ++ SCU_FUN_PIN_UART3_TXD, ++#else + SCU_FUN_PIN_UART3_TXD | + SCU_FUN_PIN_UART3_NRTS | + SCU_FUN_PIN_UART3_NDTR | + SCU_FUN_PIN_UART3_NRI | + SCU_FUN_PIN_UART3_NDSR | + SCU_FUN_PIN_UART3_NDCD | +- SCU_FUN_PIN_UART3_NCTS, +- AST_SCU_FUN_PIN_CTRL1); ++ SCU_FUN_PIN_UART3_NCTS, ++#endif ++ AST_SCU_FUN_PIN_CTRL1); + break; + case 4: + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | + SCU_FUN_PIN_UART4_RXD | ++#ifdef CONFIG_YOSEMITE ++ SCU_FUN_PIN_UART4_TXD, ++#else + SCU_FUN_PIN_UART4_TXD | + SCU_FUN_PIN_UART4_NRTS | + SCU_FUN_PIN_UART4_NDTR | + SCU_FUN_PIN_UART4_NRI | + SCU_FUN_PIN_UART4_NDSR | + SCU_FUN_PIN_UART4_NDCD | +- SCU_FUN_PIN_UART4_NCTS, +- AST_SCU_FUN_PIN_CTRL1); ++ SCU_FUN_PIN_UART4_NCTS, ++#endif ++ AST_SCU_FUN_PIN_CTRL1); + break; + } +- +- + } + + extern void +@@ -806,13 +820,13 @@ ast_scu_multi_func_video() + #if defined(CONFIG_ARCH_2100) || defined(CONFIG_ARCH_2200) + ast_scu_write(ast_scu_read(AST_SCU_MULTI_FUNC_2) | + MULTI_FUNC_VIDEO_RGB18 | +- MULTI_FUNC_VIDEO_SINGLE_EDGE, +- AST_SCU_MULTI_FUNC_2); ++ MULTI_FUNC_VIDEO_SINGLE_EDGE, ++ AST_SCU_MULTI_FUNC_2); + #elif defined(CONFIG_ARCH_1100) || defined(CONFIG_ARCH_2050) + ast_scu_write(ast_scu_read(AST_SCU_MULTI_FUNC_2) | + MULTI_FUNC_VIDEO_RGB18 | +- MULTI_FUNC_VIDEO_SINGLE_EDGE, +- AST_SCU_MULTI_FUNC_2); ++ MULTI_FUNC_VIDEO_SINGLE_EDGE, ++ AST_SCU_MULTI_FUNC_2); + #else + + #endif +@@ -823,40 +837,40 @@ ast_scu_multi_func_eth(u8 num) + { + switch(num) { + case 0: +- if(ast_scu_read(AST_SCU_HW_STRAP1) && SCU_HW_STRAP_MAC0_RGMII) { ++ if(ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC0_RGMII) { + SCUMSG("MAC0 : RGMII \n"); +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | +- SCU_FUN_PIN_MAC0_PHY_LINK, +- AST_SCU_FUN_PIN_CTRL1); ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | ++ SCU_FUN_PIN_MAC0_PHY_LINK, ++ AST_SCU_FUN_PIN_CTRL1); + } else { +- SCUMSG("MAC0 : RMII/NCSI \n"); ++ SCUMSG("MAC0 : RMII/NCSI \n"); + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) & +- ~SCU_FUN_PIN_MAC0_PHY_LINK, +- AST_SCU_FUN_PIN_CTRL1); ++ ~SCU_FUN_PIN_MAC0_PHY_LINK, ++ AST_SCU_FUN_PIN_CTRL1); + } + +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | + SCU_FUN_PIN_MAC0_MDIO | +- SCU_FUN_PIN_MAC0_MDC, +- AST_SCU_FUN_PIN_CTRL3); +- ++ SCU_FUN_PIN_MAC0_MDC, ++ AST_SCU_FUN_PIN_CTRL3); ++ + break; + case 1: +- if(ast_scu_read(AST_SCU_HW_STRAP1) && SCU_HW_STRAP_MAC1_RGMII) { ++ if(ast_scu_read(AST_SCU_HW_STRAP1) & SCU_HW_STRAP_MAC1_RGMII) { + SCUMSG("MAC1 : RGMII \n"); +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | +- SCU_FUN_PIN_MAC1_PHY_LINK, +- AST_SCU_FUN_PIN_CTRL1); ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) | ++ SCU_FUN_PIN_MAC1_PHY_LINK, ++ AST_SCU_FUN_PIN_CTRL1); + } else { + SCUMSG("MAC1 : RMII/NCSI \n"); +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) & +- ~SCU_FUN_PIN_MAC1_PHY_LINK, +- AST_SCU_FUN_PIN_CTRL1); ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL1) & ++ ~SCU_FUN_PIN_MAC1_PHY_LINK, ++ AST_SCU_FUN_PIN_CTRL1); + } +- +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | ++ ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | + SCU_FUC_PIN_MAC1_MDIO, +- AST_SCU_FUN_PIN_CTRL5); ++ AST_SCU_FUN_PIN_CTRL5); + + break; + } +@@ -866,18 +880,18 @@ extern void + ast_scu_multi_func_nand(void) + { + //enable NAND flash multipin FLBUSY and FLWP +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | +- SCU_FUN_PIN_NAND_FLBUSY | SCU_FUN_PIN_NAND_FLWP, +- AST_SCU_FUN_PIN_CTRL2); ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | ++ SCU_FUN_PIN_NAND_FLBUSY | SCU_FUN_PIN_NAND_FLWP, ++ AST_SCU_FUN_PIN_CTRL2); + + } + + extern void + ast_scu_multi_func_nor(void) + { +- //Address ++ //Address + //ROMA2~17 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL8) | ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL8) | + SCU_FUN_PIN_ROMA2 | SCU_FUN_PIN_ROMA3 | + SCU_FUN_PIN_ROMA4 | SCU_FUN_PIN_ROMA5 | + SCU_FUN_PIN_ROMA6 | SCU_FUN_PIN_ROMA7 | +@@ -885,39 +899,39 @@ ast_scu_multi_func_nor(void) + SCU_FUN_PIN_ROMA10 | SCU_FUN_PIN_ROMA11 | + SCU_FUN_PIN_ROMA12 | SCU_FUN_PIN_ROMA13 | + SCU_FUN_PIN_ROMA14 | SCU_FUN_PIN_ROMA15 | +- SCU_FUN_PIN_ROMA16 | SCU_FUN_PIN_ROMA17, ++ SCU_FUN_PIN_ROMA16 | SCU_FUN_PIN_ROMA17, + AST_SCU_FUN_PIN_CTRL8); + + //ROMA18~21 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL9) | ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL9) | + SCU_FUN_PIN_ROMA18 | SCU_FUN_PIN_ROMA19 | +- SCU_FUN_PIN_ROMA20 | SCU_FUN_PIN_ROMA21, +- AST_SCU_FUN_PIN_CTRL9); +- ++ SCU_FUN_PIN_ROMA20 | SCU_FUN_PIN_ROMA21, ++ AST_SCU_FUN_PIN_CTRL9); ++ + //ROMA22,23 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | SCU_FUN_PIN_ROMA22 | SCU_FUN_PIN_ROMA23, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | SCU_FUN_PIN_ROMA22 | SCU_FUN_PIN_ROMA23, + AST_SCU_FUN_PIN_CTRL4); +- ++ + //ROMA24,25 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | SCU_FUN_PIN_ROMA24 | SCU_FUN_PIN_ROMA25, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | SCU_FUN_PIN_ROMA24 | SCU_FUN_PIN_ROMA25, + AST_SCU_FUN_PIN_CTRL3); + + //SCU94 [1] = 0 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL6) & SCU_VIDEO_OUT_MASK, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL6) & SCU_VIDEO_OUT_MASK, + AST_SCU_FUN_PIN_CTRL6); + +- ++ + //data + //ROMD 4~7 //ROMWE#, OE# +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL4) | + SCU_FUN_PIN_ROMOE | SCU_FUN_PIN_ROMWE | + SCU_FUN_PIN_ROMD4 | SCU_FUN_PIN_ROMD5 | + SCU_FUN_PIN_ROMD6 | SCU_FUN_PIN_ROMD7, + AST_SCU_FUN_PIN_CTRL4); +- ++ + //ROMD 8~15 +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | +- SCU_FUC_PIN_ROM_16BIT, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | ++ SCU_FUC_PIN_ROM_16BIT, + AST_SCU_FUN_PIN_CTRL5); + + } +@@ -925,44 +939,44 @@ ast_scu_multi_func_nor(void) + extern void + ast_scu_multi_func_romcs(u8 num) + { +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | +- SCU_FUN_PIN_ROMCS(num), ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | ++ SCU_FUN_PIN_ROMCS(num), + AST_SCU_FUN_PIN_CTRL3); + } + + extern void + ast_scu_multi_func_i2c(void) + { +- //TODO check ... //In AST2400 Due to share pin with SD , please not enable I2C 10 ~14 ++ //TODO check ... //In AST2400 Due to share pin with SD , please not enable I2C 10 ~14 + // AST 2400 have 14 , AST 2300 9 ... + #ifdef CONFIG_MMC_AST +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | +- SCU_FUC_PIN_I2C3 | +- SCU_FUC_PIN_I2C4 | +- SCU_FUC_PIN_I2C5 | +- SCU_FUC_PIN_I2C6 | +- SCU_FUC_PIN_I2C7 | +- SCU_FUC_PIN_I2C8 | +- SCU_FUC_PIN_I2C9, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | ++ SCU_FUC_PIN_I2C3 | ++ SCU_FUC_PIN_I2C4 | ++ SCU_FUC_PIN_I2C5 | ++ SCU_FUC_PIN_I2C6 | ++ SCU_FUC_PIN_I2C7 | ++ SCU_FUC_PIN_I2C8 | ++ SCU_FUC_PIN_I2C9, + AST_SCU_FUN_PIN_CTRL5); + #else +- ast_scu_write((ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | +- SCU_FUC_PIN_I2C3 | +- SCU_FUC_PIN_I2C4 | +- SCU_FUC_PIN_I2C5 | +- SCU_FUC_PIN_I2C6 | +- SCU_FUC_PIN_I2C7 | +- SCU_FUC_PIN_I2C8 | +- SCU_FUC_PIN_I2C9 | +- SCU_FUC_PIN_I2C10 | +- SCU_FUC_PIN_I2C11 | +- SCU_FUC_PIN_I2C12 | +- SCU_FUC_PIN_I2C13 | ++ ast_scu_write((ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | ++ SCU_FUC_PIN_I2C3 | ++ SCU_FUC_PIN_I2C4 | ++ SCU_FUC_PIN_I2C5 | ++ SCU_FUC_PIN_I2C6 | ++ SCU_FUC_PIN_I2C7 | ++ SCU_FUC_PIN_I2C8 | ++ SCU_FUC_PIN_I2C9 | ++ SCU_FUC_PIN_I2C10 | ++ SCU_FUC_PIN_I2C11 | ++ SCU_FUC_PIN_I2C12 | ++ SCU_FUC_PIN_I2C13 | + SCU_FUC_PIN_I2C14) & +- ~(SCU_FUC_PIN_SD1 | SCU_FUC_PIN_SD2), ++ ~(SCU_FUC_PIN_SD1 | SCU_FUC_PIN_SD2), + AST_SCU_FUN_PIN_CTRL5); + #endif +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_i2c); + +@@ -972,7 +986,7 @@ ast_scu_multi_func_pwm_tacho(void) + //TODO check + u32 sts = ast_scu_read(AST_SCU_FUN_PIN_CTRL3) &~0xcfffff; + ast_scu_write(sts | 0xc000ff, AST_SCU_FUN_PIN_CTRL3); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_pwm_tacho); + +@@ -981,12 +995,12 @@ extern void + ast_scu_multi_func_usb20_host_hub(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB20_HOST, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB20_HOST, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB20_HOST, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB20_HOST, + AST_SCU_FUN_PIN_CTRL5); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_usb20_host_hub); + +@@ -995,12 +1009,12 @@ extern void + ast_scu_multi_func_usb11_host_port4(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT4, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT4, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT4, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT4, + AST_SCU_FUN_PIN_CTRL5); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_usb11_host_port4); + +@@ -1009,26 +1023,26 @@ extern void + ast_scu_multi_func_usb11_host_port2(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT2, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_USB11_PORT2, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT2, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_USB11_PORT2, + AST_SCU_FUN_PIN_CTRL5); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_usb11_host_port2); + +-//0 : 1: SD1 function ++//0 : 1: SD1 function + extern void + ast_scu_multi_func_sdhc_slot1(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD1, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD1, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD1, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD1, + AST_SCU_FUN_PIN_CTRL5); +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_sdhc_slot1); + +@@ -1036,13 +1050,13 @@ extern void + ast_scu_multi_func_sdhc_slot2(u8 mode) + { + if(mode) +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD2, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) | SCU_FUC_PIN_SD2, + AST_SCU_FUN_PIN_CTRL5); + else +- ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD2, ++ ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & ~SCU_FUC_PIN_SD2, + AST_SCU_FUN_PIN_CTRL5); + +-} ++} + + EXPORT_SYMBOL(ast_scu_multi_func_sdhc_slot2); + +@@ -1053,11 +1067,11 @@ ast_scu_multi_func_crt(void) + + //Digital vodeo input function pins : 00 disable, 10 24bits mode 888, + ast_scu_write((ast_scu_read(AST_SCU_FUN_PIN_CTRL5) & +- ~SCU_FUC_PIN_DIGI_V_OUT_MASK) | ++ ~SCU_FUC_PIN_DIGI_V_OUT_MASK) | + SCU_FUC_PIN_DIGI_V_OUT(VIDEO_24BITS),AST_SCU_FUN_PIN_CTRL5); + + //VPI input +-#if 0 ++#if 0 + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL2) | + SCU_FUN_PIN_VPIB9 | SCU_FUN_PIN_VPIB8 | + SCU_FUN_PIN_VPIB7 | SCU_FUN_PIN_VPIB6 | +@@ -1070,11 +1084,11 @@ ast_scu_multi_func_crt(void) + + ast_scu_write(ast_scu_read(AST_SCU_FUN_PIN_CTRL3) | + SCU_FUN_PIN_VPIR9 | SCU_FUN_PIN_VPIR8 | +- SCU_FUN_PIN_VPIR7 | SCU_FUN_PIN_VPIR6 | ++ SCU_FUN_PIN_VPIR7 | SCU_FUN_PIN_VPIR6 | + SCU_FUN_PIN_VPIR5 | SCU_FUN_PIN_VPIR4 | + SCU_FUN_PIN_VPIR3 | SCU_FUN_PIN_VPIR2 | + SCU_FUN_PIN_VPIR1 | SCU_FUN_PIN_VPIR0 | +- SCU_FUN_PIN_VPIG9 | SCU_FUN_PIN_VPIG8 | ++ SCU_FUN_PIN_VPIG9 | SCU_FUN_PIN_VPIG8 | + SCU_FUN_PIN_VPIG7 | SCU_FUN_PIN_VPIG6 | + SCU_FUN_PIN_VPIG5 | SCU_FUN_PIN_VPIG4 | + SCU_FUN_PIN_VPIG3 | SCU_FUN_PIN_VPIG2 | +@@ -1097,9 +1111,9 @@ ast_scu_revision_id(void) + SCUMSG("UnKnow-SOC : %x \n",rev_id); + else + SCUMSG("SOC : %4s \n",soc_map_table[i].name); +- ++ + return rev_id; +-} ++} + + EXPORT_SYMBOL(ast_scu_revision_id); + +diff --git a/arch/arm/plat-aspeed/dev-eth.c b/arch/arm/plat-aspeed/dev-eth.c +index 5d33e33..b115c5a 100644 +--- a/arch/arm/plat-aspeed/dev-eth.c ++++ b/arch/arm/plat-aspeed/dev-eth.c +@@ -7,11 +7,11 @@ + * 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. +-* ++* + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -37,7 +37,7 @@ + #if defined(CONFIG_ASPEEDMAC) || defined(CONFIG_ASPEEDMAC_MODULE) + #ifdef AST_MAC0_BASE + static struct ftgmac100_eth_data ast_eth0_data = { +- .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x22}, ++ .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x22}, + .phy_id = 1, + }; + +@@ -69,7 +69,7 @@ static struct platform_device ast_eth0_device = { + #endif + #ifdef AST_MAC1_BASE + static struct ftgmac100_eth_data ast_eth1_data = { +- .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x23}, ++ .dev_addr = { 0x00, 0x84, 0x14, 0xA0, 0xB0, 0x23}, + .phy_id = 1, + }; + +@@ -131,11 +131,16 @@ void __init ast_add_device_gmac(void) + } + + ast_eth0_data.DF_support = !isRevA0; +- ++ ++ // Wedge/6-Pack hardware attaches to MAC1; there's nothing on ++ // MAC0. Older drivers would drop interfaces without PHYs, but ++ // the latest open source drivers do not, so we drop the first ++ // MAC specs. ++#if !defined(CONFIG_WEDGE) && !defined(CONFIG_WEDGE100) + ast_scu_init_eth(0); + ast_scu_multi_func_eth(0); +- +- ++ ++ + /* + * D[15:11] in 0x1E6E2040 is NCSI scratch from U-Boot. D[15:14] = MAC1, D[13:12] = MAC2 + * The meanings of the 2 bits are: +@@ -144,7 +149,7 @@ void __init ast_add_device_gmac(void) + * 10(2): ASPEED's MAC is connected to NC-SI PHY chip directly + * 11: Reserved + */ +- ++ + phy_mode = ast_scu_get_phy_config(0); + switch(phy_mode) { + case 0: +@@ -152,12 +157,12 @@ void __init ast_add_device_gmac(void) + ast_eth0_data.NCSI_support = 0; + break; + case 1: +- ast_eth0_data.NCSI_support = 1; ++ ast_eth0_data.INTEL_NCSI_EVA_support = 1; + break; + case 2: +- ast_eth0_data.INTEL_NCSI_EVA_support = 1; ++ ast_eth0_data.NCSI_support = 1; + break; +- ++ + } + + phy_inter = ast_scu_get_phy_interface(0); +@@ -165,12 +170,13 @@ void __init ast_add_device_gmac(void) + // We assume the Clock Stop register does not disable the MAC1 or MAC2 clock + // unless Reset Control also holds the MAC in reset. + +- ++ + platform_device_register(&ast_eth0_device); ++#endif + + #ifdef AST_MAC1_BASE + ast_scu_init_eth(1); +- ast_scu_multi_func_eth(1); ++ ast_scu_multi_func_eth(1); + + ast_eth1_data.DF_support = !isRevA0; + +@@ -186,7 +192,7 @@ void __init ast_add_device_gmac(void) + case 2: + ast_eth1_data.INTEL_NCSI_EVA_support = 1; + break; +- ++ + } + phy_inter = ast_scu_get_phy_interface(1); + +@@ -198,4 +204,3 @@ void __init ast_add_device_gmac(void) + #else + void __init ast_add_device_gmac(void) {} + #endif +- +diff --git a/arch/arm/plat-aspeed/dev-i2c.c b/arch/arm/plat-aspeed/dev-i2c.c +index 9905390..fffa480 100644 +--- a/arch/arm/plat-aspeed/dev-i2c.c ++++ b/arch/arm/plat-aspeed/dev-i2c.c +@@ -7,11 +7,11 @@ + * 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. +-* ++* + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -47,59 +47,59 @@ + #if defined (CONFIG_ARCH_AST2400) + #define I2C_PAGE_SIZE 8 + static spinlock_t page_info_lock = SPIN_LOCK_UNLOCKED; +-static struct buf_page page_info[I2C_PAGE_SIZE] = +-{ ++static struct buf_page page_info[I2C_PAGE_SIZE] = ++{ + [0] = { + .flag = 0, + .page_no = 0, + .page_size = 256, +- .page_addr_point = 0, ++ .page_addr_point = 0, + }, + [1] = { + .flag = 0, +- .page_no = 1, ++ .page_no = 1, + .page_size = 256, +- .page_addr_point = 0, ++ .page_addr_point = 0, + }, + [2] = { + .flag = 0, +- .page_no = 2, ++ .page_no = 2, + .page_size = 256, + .page_addr_point = 0, + }, + [3] = { + .flag = 0, +- .page_no = 3, ++ .page_no = 3, + .page_size = 256, + .page_addr_point = 0, + }, + [4] = { + .flag = 0, +- .page_no = 4, ++ .page_no = 4, + .page_size = 256, + .page_addr_point = 0, + }, + [5] = { + .flag = 0, +- .page_no = 5, ++ .page_no = 5, + .page_size = 256, + .page_addr_point = 0, + }, + [6] = { + .flag = 0, +- .page_no = 6, ++ .page_no = 6, + .page_size = 256, + .page_addr_point = 0, + }, + [7] = { + .flag = 0, +- .page_no = 7, ++ .page_no = 7, + .page_size = 256, + .page_addr_point = 0, + }, + }; + +-static void pool_buff_page_init(u32 buf_pool_addr) ++static void pool_buff_page_init(u32 buf_pool_addr) + { + u32 offset; + int i ,j; +@@ -108,7 +108,7 @@ static void pool_buff_page_init(u32 buf_pool_addr) + offset = 0; + for(j=0;j<i;j++) + offset += page_info[i].page_size; +- ++ + page_info[i].page_addr = buf_pool_addr + offset; + // I2CDBUG( "page[%d],addr :%x \n", i, page_info[i].page_addr); + } +@@ -130,7 +130,7 @@ static u8 request_pool_buff_page(struct buf_page **req_page) + break; + } + } +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + return (i >= I2C_PAGE_SIZE); + } + +@@ -140,17 +140,17 @@ static void free_pool_buff_page(struct buf_page *req_page) + spin_lock_irqsave(&page_info_lock, flags); + + req_page->flag = 0; +-// I2CDBUG( "free page addr %x \n", req_page->page_addr); ++// I2CDBUG( "free page addr %x \n", req_page->page_addr); + req_page = NULL; +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + } + + #elif defined (CONFIG_ARCH_AST2300) + #define I2C_PAGE_SIZE 5 + + static spinlock_t page_info_lock = SPIN_LOCK_UNLOCKED; +-static struct buf_page page_info[I2C_PAGE_SIZE] = +-{ ++static struct buf_page page_info[I2C_PAGE_SIZE] = ++{ + [0] = { + .flag = 0, + .page_size = 128, +@@ -173,7 +173,7 @@ static struct buf_page page_info[I2C_PAGE_SIZE] = + }, + }; + +-static void pool_buff_page_init(u32 buf_pool_addr) ++static void pool_buff_page_init(u32 buf_pool_addr) + { + + u32 offset; +@@ -183,7 +183,7 @@ static void pool_buff_page_init(u32 buf_pool_addr) + offset = 0; + for(j=0;j<i;j++) + offset += page_info[i].page_size; +- ++ + page_info[i].page_addr = buf_pool_addr + offset; + page_info[i].page_addr_point = page_info[i].page_addr/4; + // printk("page[%d],addr :%x , point : %d\n", i, page_info[i].page_addr, page_info[i].page_addr_point); +@@ -201,11 +201,11 @@ static u8 request_pool_buff_page(struct buf_page **req_page) + if(page_info[i].flag ==0) { + page_info[i].flag = 1; + *req_page = &page_info[i]; +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + return 0; + } + } +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + return 1; + + } +@@ -217,10 +217,10 @@ static void free_pool_buff_page(struct buf_page *req_page) + spin_lock_irqsave(&page_info_lock, flags); + req_page->flag = 0; + req_page = NULL; +- spin_unlock_irqrestore(&page_info_lock, flags); ++ spin_unlock_irqrestore(&page_info_lock, flags); + } + +-#else ++#else + //DO nothing + static void pool_buff_page_init(void) {} + static u8 request_pool_buff_page(struct buf_page **req_page) {return 0;} +@@ -228,15 +228,15 @@ static void free_pool_buff_page(struct buf_page *req_page) {} + #endif + + static struct ast_i2c_driver_data ast_i2c_data = { +- .bus_clk = 100000, //bus clock 100KHz ++ .bus_clk = 100000, //bus clock 100KHz + .master_dma = BUFF_MODE, + .slave_dma = BYTE_MODE, + .request_pool_buff_page = request_pool_buff_page, + .free_pool_buff_page = free_pool_buff_page, +-#ifdef CONFIG_AST_I2C_SLAVE_MODE ++#ifdef CONFIG_AST_I2C_SLAVE_MODE + .slave_xfer = i2c_slave_xfer, + .slave_init = i2c_slave_init, +-#endif ++#endif + .get_i2c_clock = ast_get_pclk, + }; + +@@ -285,7 +285,7 @@ struct platform_device ast_i2c_dev2_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev2_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev2_resources), +@@ -310,7 +310,7 @@ struct platform_device ast_i2c_dev3_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev3_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev3_resources), +@@ -335,7 +335,7 @@ struct platform_device ast_i2c_dev4_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev4_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev4_resources), +@@ -360,7 +360,7 @@ struct platform_device ast_i2c_dev5_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev5_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev5_resources), +@@ -385,7 +385,7 @@ struct platform_device ast_i2c_dev6_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev6_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev6_resources), +@@ -410,7 +410,7 @@ struct platform_device ast_i2c_dev7_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev7_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev7_resources), +@@ -435,7 +435,7 @@ struct platform_device ast_i2c_dev8_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev8_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev8_resources), +@@ -460,7 +460,7 @@ struct platform_device ast_i2c_dev9_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev9_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev9_resources), +@@ -486,7 +486,7 @@ struct platform_device ast_i2c_dev10_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev10_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev10_resources), +@@ -511,7 +511,7 @@ struct platform_device ast_i2c_dev11_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev11_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev11_resources), +@@ -536,7 +536,7 @@ struct platform_device ast_i2c_dev12_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev12_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev12_resources), +@@ -561,7 +561,7 @@ struct platform_device ast_i2c_dev13_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev13_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev13_resources), +@@ -586,7 +586,7 @@ struct platform_device ast_i2c_dev14_device = { + .dev = { + .dma_mask = &ast_i2c_dma_mask, + .coherent_dma_mask = 0xffffffff, +- .platform_data = &ast_i2c_data, ++ .platform_data = &ast_i2c_data, + }, + .resource = ast_i2c_dev14_resources, + .num_resources = ARRAY_SIZE(ast_i2c_dev14_resources), +@@ -594,12 +594,196 @@ struct platform_device ast_i2c_dev14_device = { + #endif + + /*--------- I2C Board devices ------------*/ +-//ASPEED AST2300 EVB I2C Device ++//ASPEED AST2300 EVB I2C Device + #if defined(CONFIG_ARCH_AST2300) || defined(CONFIG_ARCH_AST2400) ++ ++#if defined(CONFIG_WEDGE100) ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus1[] = { ++ /* shared NIC, no kernel driver */ ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus2[] = { ++ /* TODO: one IR3581 and two IR3584 */ ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus3[] = { ++ /* TODO: one PWR1014A */ ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus4[] = { ++ { ++ I2C_BOARD_INFO("tmp75", 0x48), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x49), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x4a), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x4b), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x4c), ++ }, ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus5[] = { ++ /* Panther+ microserver */ ++ { ++ I2C_BOARD_INFO("fb_panther_plus", 0x40), ++ }, ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus6[] = { ++ /* TODO: USB hub */ ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus7[] = { ++ { ++ I2C_BOARD_INFO("pcf8574", 0x2f), ++ }, ++ { ++ I2C_BOARD_INFO("24c64", 0x51), ++ } ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus8[] = { ++ /* BMC PHY EEPROM */ ++ { ++ I2C_BOARD_INFO("24c02", 0x50), ++ }, ++ // EEPROM on the pfe1100 power supplies ++ { ++ I2C_BOARD_INFO("24c64", 0x51), ++ }, ++ { ++ I2C_BOARD_INFO("24c64", 0x52), ++ }, ++ /* PSU driver */ ++ { ++ I2C_BOARD_INFO("pfe1100", 0x59), ++ }, ++ { ++ I2C_BOARD_INFO("pfe1100", 0x5a), ++ }, ++}; ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus9[] = { ++ { ++ I2C_BOARD_INFO("fancpld", 0x33), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x48), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x49), ++ }, ++}; ++ ++/* i2c bus 10-12 on wedge100 are not connected as i2c bus */ ++ ++static struct i2c_board_info __initdata wedge100_i2c_bus13[] = { ++ { ++ I2C_BOARD_INFO("syscpld", 0x31), ++ }, ++}; ++ ++/* i2c bus 14 on wedge100 are not connected as i2c bus */ ++ ++/* end of defined(CONFIG_WEDGE100) */ ++ ++#elif defined(CONFIG_YOSEMITE) || defined(CONFIG_FBPLATFORM1) ++ ++//Under I2C Dev 1 ++static struct i2c_board_info __initdata ast_i2c_board_info_1[] = { ++ // Slot#0 NIC sideband ++}; ++ ++//Under I2C Dev 2 ++static struct i2c_board_info __initdata ast_i2c_board_info_2[] = { ++ // Slot#0 IPMB interface ++}; ++ ++//Under I2C Dev 3 ++static struct i2c_board_info __initdata ast_i2c_board_info_3[] = { ++ // Slot#1 NIC sideband ++}; ++ ++ ++//Under I2C Dev 4 ++static struct i2c_board_info __initdata ast_i2c_board_info_4[] = { ++ // Slot#1 IPMB interface ++}; ++ ++//Under I2C Dev 5 ++static struct i2c_board_info __initdata ast_i2c_board_info_5[] = { ++ // Slot#2 NIC sideband ++}; ++ ++//Under I2C Dev 6 ++static struct i2c_board_info __initdata ast_i2c_board_info_6[] = { ++ // Slot#2 IPMB interface ++}; ++ ++//Under I2C Dev 7 ++static struct i2c_board_info __initdata ast_i2c_board_info_7[] = { ++ // Slot#3 NIC sideband ++}; ++ ++//Under I2C Dev 8 ++static struct i2c_board_info __initdata ast_i2c_board_info_8[] = { ++ // Slot#3 IPMB interface ++}; ++ ++//Under I2C Dev 9 ++static struct i2c_board_info __initdata ast_i2c_board_info_9[] = { ++ // FRUID ++ { ++ I2C_BOARD_INFO("24c64", 0x51), ++ }, ++}; ++ ++//Under I2C Dev 10 ++static struct i2c_board_info __initdata ast_i2c_board_info_10[] = { ++ // Inlet and Outlet temp. sensors ++ { ++ I2C_BOARD_INFO("tmp75", 0x4e), ++ }, ++ { ++ I2C_BOARD_INFO("tmp75", 0x4f), ++ }, ++}; ++ ++//Under I2C Dev 11 ++static struct i2c_board_info __initdata ast_i2c_board_info_11[] = { ++ // Hotswap Sensor ++ { ++ I2C_BOARD_INFO("adm1278", 0x40), ++ }, ++}; ++ ++//Under I2C Dev 12 ++static struct i2c_board_info __initdata ast_i2c_board_info_12[] = { ++ // Mezz Card LAN_SMB bus (PHY, Temp. Sensor) ++}; ++ ++//Under I2C Dev 13 ++static struct i2c_board_info __initdata ast_i2c_board_info_13[] = { ++ // Mezz Card Mezz_SMB bus (FRUID, GPIO expander, QSFP+) ++}; ++ ++/* end of CONFIG_YOSEMITE */ ++ ++#else ++ ++/* wedge */ ++ + //Under I2C Dev 1 + static struct i2c_board_info __initdata ast_i2c_board_info_1[] = { + { +- I2C_BOARD_INFO("cat9883", 0x4d), ++ I2C_BOARD_INFO("cat9883", 0x4d), + } + }; + +@@ -612,15 +796,6 @@ static struct i2c_board_info __initdata ast_i2c_board_info_2[] = { + { + I2C_BOARD_INFO("ncp4200", 0x60), + }, +- { +- I2C_BOARD_INFO("ncp4200", 0x61), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x62), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x63), +- }, + }; + + +@@ -632,15 +807,6 @@ static struct i2c_board_info __initdata ast_i2c_board_info_3[] = { + { + I2C_BOARD_INFO("ncp4200", 0x60), + }, +- { +- I2C_BOARD_INFO("ncp4200", 0x61), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x62), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x63), +- }, + }; + + +@@ -675,7 +841,7 @@ static struct i2c_board_info __initdata ast_i2c_board_info_5[] = { + I2C_BOARD_INFO("24c128", 0x51), + }, + }; +- ++ + //Under I2C Dev 7 + static struct i2c_board_info __initdata ast_i2c_board_info_7[] = { + // Wedge devices +@@ -688,15 +854,23 @@ static struct i2c_board_info __initdata ast_i2c_board_info_7[] = { + }, + { + I2C_BOARD_INFO("24c64", 0x50), +- } ++ }, + }; + + + //Under I2C Dev 8 + static struct i2c_board_info __initdata ast_i2c_board_info_8[] = { + { ++ // 6pack power supply ++ I2C_BOARD_INFO("pfe3000", 0x10), ++ }, ++ { + // Eval board: +- I2C_BOARD_INFO("lm75b", 0x4a), ++ I2C_BOARD_INFO("lm75b", 0x4a), ++ }, ++ { ++ // 6pack power supply EEPROM ++ I2C_BOARD_INFO("24c64", 0x50), + }, + // EEPROMS on the pfe1100 power supplies + { +@@ -722,20 +896,12 @@ static struct i2c_board_info __initdata ast_i2c_board_info_9[] = { + { + I2C_BOARD_INFO("ncp4200", 0x60), + }, +- { +- I2C_BOARD_INFO("ncp4200", 0x61), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x62), +- }, +- { +- I2C_BOARD_INFO("ncp4200", 0x63), +- }, + }; + + //Under I2C Dev 12 + static struct i2c_board_info __initdata ast_i2c_board_info_12[] = { + { ++ // Early version of 6pack + I2C_BOARD_INFO("pfe3000", 0x10), + }, + }; +@@ -747,6 +913,10 @@ static struct i2c_board_info __initdata ast_i2c_board_info_13[] = { + }, + }; + ++/* end of WEDGE case */ ++#endif ++ ++/* end of defined(CONFIG_ARCH_AST2300) || defined(CONFIG_ARCH_AST2400) */ + #endif + + /*-------------------------------------*/ +@@ -755,7 +925,7 @@ void __init ast_add_device_i2c(void) + //I2C Multi-Pin + ast_scu_multi_func_i2c(); + +- //SCU I2C Reset ++ //SCU I2C Reset + ast_scu_init_i2c(); + + ast_i2c_data.reg_gr = ioremap(AST_I2C_BASE, 4*SZ_16); +@@ -777,8 +947,48 @@ void __init ast_add_device_i2c(void) + return; + } + #endif +- //TODO +- pool_buff_page_init(ast_i2c_data.buf_pool); ++ ++ pool_buff_page_init(ast_i2c_data.buf_pool); ++ ++#if defined(CONFIG_WEDGE100) ++ ++ platform_device_register(&ast_i2c_dev1_device); ++ i2c_register_board_info(0, wedge100_i2c_bus1, ARRAY_SIZE(wedge100_i2c_bus1)); ++ ++ platform_device_register(&ast_i2c_dev2_device); ++ i2c_register_board_info(1, wedge100_i2c_bus2, ARRAY_SIZE(wedge100_i2c_bus2)); ++ ++ platform_device_register(&ast_i2c_dev3_device); ++ i2c_register_board_info(2, wedge100_i2c_bus3, ARRAY_SIZE(wedge100_i2c_bus3)); ++ ++ platform_device_register(&ast_i2c_dev4_device); ++ i2c_register_board_info(3, wedge100_i2c_bus4, ARRAY_SIZE(wedge100_i2c_bus4)); ++ ++ platform_device_register(&ast_i2c_dev5_device); ++ i2c_register_board_info(4, wedge100_i2c_bus5, ARRAY_SIZE(wedge100_i2c_bus5)); ++ ++ platform_device_register(&ast_i2c_dev6_device); ++ i2c_register_board_info(5, wedge100_i2c_bus6, ARRAY_SIZE(wedge100_i2c_bus6)); ++ ++ platform_device_register(&ast_i2c_dev7_device); ++ i2c_register_board_info(6, wedge100_i2c_bus7, ARRAY_SIZE(wedge100_i2c_bus7)); ++ ++ platform_device_register(&ast_i2c_dev8_device); ++ i2c_register_board_info(7, wedge100_i2c_bus8, ARRAY_SIZE(wedge100_i2c_bus8)); ++ ++ platform_device_register(&ast_i2c_dev9_device); ++ i2c_register_board_info(8, wedge100_i2c_bus9, ARRAY_SIZE(wedge100_i2c_bus9)); ++ ++ /* i2c bus 10 - 12 are not used as i2c on wedge100 */ ++ ++ platform_device_register(&ast_i2c_dev13_device); ++ i2c_register_board_info(12, wedge100_i2c_bus13, ARRAY_SIZE(wedge100_i2c_bus13)); ++ ++ /* i2c bug 14 is not used as i2c on wedge100 */ ++ ++ /* end of defined(CONFIG_WEDGE100) */ ++#else ++ + platform_device_register(&ast_i2c_dev1_device); + i2c_register_board_info(0, ast_i2c_board_info_1, ARRAY_SIZE(ast_i2c_board_info_1)); + platform_device_register(&ast_i2c_dev2_device); +@@ -790,17 +1000,27 @@ void __init ast_add_device_i2c(void) + platform_device_register(&ast_i2c_dev5_device); + i2c_register_board_info(4, ast_i2c_board_info_5, ARRAY_SIZE(ast_i2c_board_info_5)); + platform_device_register(&ast_i2c_dev6_device); ++#if defined(CONFIG_YOSEMITE) ++ i2c_register_board_info(5, ast_i2c_board_info_6, ARRAY_SIZE(ast_i2c_board_info_6)); ++#endif + platform_device_register(&ast_i2c_dev7_device); + i2c_register_board_info(6, ast_i2c_board_info_7, ARRAY_SIZE(ast_i2c_board_info_7)); + platform_device_register(&ast_i2c_dev8_device); + i2c_register_board_info(7, ast_i2c_board_info_8, ARRAY_SIZE(ast_i2c_board_info_8)); +- platform_device_register(&ast_i2c_dev9_device); ++ platform_device_register(&ast_i2c_dev9_device); + i2c_register_board_info(8, ast_i2c_board_info_9, ARRAY_SIZE(ast_i2c_board_info_9)); + + #if defined(CONFIG_ARCH_AST2400) + platform_device_register(&ast_i2c_dev10_device); ++ ++#if defined(CONFIG_YOSEMITE) ++ i2c_register_board_info(9, ast_i2c_board_info_10, ARRAY_SIZE(ast_i2c_board_info_10)); ++ platform_device_register(&ast_i2c_dev11_device); ++ i2c_register_board_info(10, ast_i2c_board_info_11, ARRAY_SIZE(ast_i2c_board_info_11)); ++#endif ++ + #if defined(CONFIG_MMC_AST) +- //Due to share pin with SD ++ //Due to share pin with SD + #else + /* + * On Wedge, bus 13 is used as i2c bus. Bus 12 is used on other +@@ -812,7 +1032,12 @@ void __init ast_add_device_i2c(void) + i2c_register_board_info(11, ast_i2c_board_info_12, ARRAY_SIZE(ast_i2c_board_info_12)); + platform_device_register(&ast_i2c_dev13_device); + i2c_register_board_info(12, ast_i2c_board_info_13, ARRAY_SIZE(ast_i2c_board_info_13)); +-#endif ++#endif ++ ++ /* end of defined(CONFIG_ARCH_AST2400) */ ++#endif ++ ++ /* end of else of defined(CONFIG_WEDGE100) */ + #endif + } + #else +diff --git a/arch/arm/plat-aspeed/dev-spi.c b/arch/arm/plat-aspeed/dev-spi.c +index e22c49e..0cb0189 100644 +--- a/arch/arm/plat-aspeed/dev-spi.c ++++ b/arch/arm/plat-aspeed/dev-spi.c +@@ -344,8 +344,8 @@ static struct flash_platform_data wedge_spi_flash_data = { + + + /* Device info for the flash on ast-spi */ +-#ifdef CONFIG_ARCH_AST2400 +-static struct mtd_partition ast_spi5_flash_partitions[] = { ++#ifdef CONFIG_WEDGE ++static struct mtd_partition wedge_spi5_flash_partitions[] = { + { + .name = "led-fpga", + .offset = 0, /* From 0 */ +@@ -355,8 +355,8 @@ static struct mtd_partition ast_spi5_flash_partitions[] = { + + static struct flash_platform_data wedge_spi5_flash_data = { + .type = "at45db011d", +- .nr_parts = ARRAY_SIZE(ast_spi5_flash_partitions), +- .parts = ast_spi5_flash_partitions, ++ .nr_parts = ARRAY_SIZE(wedge_spi5_flash_partitions), ++ .parts = wedge_spi5_flash_partitions, + }; + #endif + +@@ -372,6 +372,7 @@ static struct spi_board_info ast_spi_devices[] = { + }, + #endif + #ifdef CONFIG_ARCH_AST2400 ++#ifdef CONFIG_WEDGE + { + .modalias = "mtd_dataflash", + .platform_data = &wedge_spi5_flash_data, +@@ -380,6 +381,15 @@ static struct spi_board_info ast_spi_devices[] = { + .bus_num = 5, + .mode = SPI_MODE_0, + }, ++#elif defined CONFIG_WEDGE100 ++ { ++ .modalias = "spidev", ++ .chip_select = 0, ++ .max_speed_hz = 33 * 1000 * 1000, ++ .bus_num = 5, ++ .mode = SPI_MODE_0, ++ }, ++#endif + { + .modalias = "m25p80", + .platform_data = &wedge_spi_flash_data, +@@ -389,13 +399,6 @@ static struct spi_board_info ast_spi_devices[] = { + .mode = SPI_MODE_0, + }, + #endif +- { +- .modalias = "spidev", +- .chip_select = 0, +- .max_speed_hz = 30 * 1000 * 1000, +- .bus_num = 1, +- .mode = SPI_MODE_0, +- }, + }; + + #if defined(AST_SPI1_BASE) +@@ -490,5 +493,3 @@ void __init ast_add_device_spi(void) + #else + void __init ast_add_device_spi(void) {} + #endif +- +- +diff --git a/arch/arm/plat-aspeed/dev-uart.c b/arch/arm/plat-aspeed/dev-uart.c +index 0b7b614..e424a5a 100644 +--- a/arch/arm/plat-aspeed/dev-uart.c ++++ b/arch/arm/plat-aspeed/dev-uart.c +@@ -6,11 +6,11 @@ + * 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. +-* ++* + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -50,14 +50,14 @@ static struct plat_serial8250_port ast_uart_data[] = { + .irq = IRQ_UART0, + .uartclk = (24*1000000L), + .regshift = 2, +-#if defined(CONFIG_COLDFIRE) ++#if defined(CONFIG_COLDFIRE) + .iotype = UPIO_MEM32, + #else + .iotype = UPIO_MEM, +-#endif ++#endif + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, +-#if defined(CONFIG_ARCH_AST1010) ++#if defined(CONFIG_ARCH_AST1010) + { + .mapbase = AST_UART1_BASE, + .irq = IRQ_UART1, +@@ -65,7 +65,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM32, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + { + .mapbase = AST_UART2_BASE, + .irq = IRQ_UART2, +@@ -73,7 +73,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM32, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + #else + //BMC UART 1 ,2 default to LPC + #ifdef CONFIG_ARCH_AST1070 +@@ -85,7 +85,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + #endif + #ifdef AST_UART2_BASE + { +@@ -95,7 +95,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + #endif + #endif + #ifdef AST_UART1_BASE +@@ -109,6 +109,19 @@ static struct plat_serial8250_port ast_uart_data[] = { + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + }, + #endif ++#if defined(CONFIG_YOSEMITE) //Without this, tty offset might change for others ++#ifdef AST_UART2_BASE ++ { ++ .mapbase = AST_UART2_BASE, ++ .membase = (char*)(IO_ADDRESS(AST_UART2_BASE)), ++ .irq = IRQ_UART2, ++ .uartclk = (24*1000000L), ++ .regshift = 2, ++ .iotype = UPIO_MEM, ++ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, ++ }, ++#endif ++#endif + #ifdef AST_UART3_BASE + { + .mapbase = AST_UART3_BASE, +@@ -117,7 +130,7 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, + #endif + #ifdef AST_UART4_BASE + { +@@ -127,9 +140,9 @@ static struct plat_serial8250_port ast_uart_data[] = { + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, +- }, ++ }, ++#endif + #endif +-#endif + { }, + }; + +@@ -144,11 +157,16 @@ struct platform_device ast_uart_device = { + void __init ast_add_device_uart(void) + { + #if defined(CONFIG_ARCH_AST1010) ++#elif defined(CONFIG_YOSEMITE) ++ ast_scu_multi_func_uart(1); ++ ast_scu_multi_func_uart(2); ++ ast_scu_multi_func_uart(3); ++ ast_scu_multi_func_uart(4); + #else +- ast_scu_multi_func_uart(1); +- ast_scu_multi_func_uart(3); +- ast_scu_multi_func_uart(4); +-#endif ++ ast_scu_multi_func_uart(1); ++ ast_scu_multi_func_uart(3); ++ ast_scu_multi_func_uart(4); ++#endif + platform_device_register(&ast_uart_device); + } + #else +diff --git a/arch/arm/plat-aspeed/irq.c b/arch/arm/plat-aspeed/irq.c +index b118359..f6100fa 100644 +--- a/arch/arm/plat-aspeed/irq.c ++++ b/arch/arm/plat-aspeed/irq.c +@@ -48,13 +48,14 @@ static void ast_mask_irq(unsigned int irq) + if((irq >= IRQ_TIMER0) && (irq <= IRQ_TIMER2)) + timer = 1; + #endif +- +- if (irq > 32) { ++ ++ // for irq0-irq31 use LOW register; for irq32-irq63 use HIGH register set. ++ if (irq >= 32) { + i=1; + irq = irq - 32; + } else + i=0; +- ++ + regVal = readl(AST_INTR_DIS(i)); + regVal |= (1 << irq); + writel(regVal, AST_INTR_DIS(i)); +@@ -63,8 +64,8 @@ static void ast_mask_irq(unsigned int irq) + * clear the interrupt + */ + if(timer) +- IRQ_EDGE_CLEAR(i,irq); +- ++ IRQ_EDGE_CLEAR(i,irq); ++ + } + + static void ast_unmask_irq(unsigned int irq) +@@ -72,12 +73,13 @@ static void ast_unmask_irq(unsigned int irq) + int i; + u32 regVal; + +- if (irq > 32) { ++ // for irq0-irq31 use LOW register; for irq32-irq63 use HIGH register set. ++ if (irq >= 32) { + i=1; + irq = irq - 32; + } else + i=0; +- ++ + regVal = readl(AST_INTR_EN(i)); + regVal |= (1 << irq); + writel(regVal, AST_INTR_EN(i)); +@@ -88,8 +90,8 @@ static struct irq_chip ast_irq_chip = { + .ack = ast_mask_irq, + .mask = ast_mask_irq, + .unmask = ast_unmask_irq, +-}; +- ++}; ++ + void __init ast_init_irq(void) + { + unsigned int i; +@@ -107,8 +109,8 @@ void __init ast_init_irq(void) + writel(0xFFFFFFFF, AST_INTR_EDGE_CLR(1)); + #endif + +- //TOTAL IRQ NUM = +- for (i = 0; i < AST_VIC_NUM; i++) ++ //TOTAL IRQ NUM = ++ for (i = 0; i < AST_VIC_NUM; i++) + { + if(i<32) { + if((i >= IRQ_TIMER0) && (i <= IRQ_TIMER2)) //Timer0/1/2 +@@ -125,9 +127,9 @@ void __init ast_init_irq(void) + IRQ_SET_HIGH_LEVEL(1,i-32); + IRQ_SET_LEVEL_TRIGGER(1,i-32); + } +-#endif ++#endif + } +- ++ + set_irq_chip(i, &ast_irq_chip); + set_irq_handler(i, handle_level_irq); + set_irq_flags(i, IRQF_VALID); +diff --git a/drivers/hwmon/ast_adc.c b/drivers/hwmon/ast_adc.c +index 3f95dc6..8f5aa54 100644 +--- a/drivers/hwmon/ast_adc.c ++++ b/drivers/hwmon/ast_adc.c +@@ -13,10 +13,10 @@ + * 2012.11.26: Initial version [Ryan Chen] + */ + +-/* attr ADC sysfs 0~max adc channel ++/* attr ADC sysfs 0~max adc channel + * 0 - show/store enable + * 3 - show value +-* 1 - show/store alarm_en set enable ++* 1 - show/store alarm_en set enable + * 2 - show alarm get statuse + * 4 - show/store upper + * 5 - show/store lower */ +@@ -44,13 +44,33 @@ + + #define REST_DESIGN 5 + ++ ++#ifdef CONFIG_YOSEMITE ++enum { ++ ADC_P5V = 0, ++ ADC_P12V, ++ ADC_P3V3_STBY, ++ ADC_P12V_SLOT0, ++ ADC_P12V_SLOT1, ++ ADC_P12V_SLOT2, ++ ADC_P12V_SLOT3, ++ ADC_P3V3, ++}; ++ ++enum { ++ REST_DESIGN_P3V3 = 6, ++ REST_DESIGN_P5V = 7, ++ REST_DESIGN_P12V = 8, ++}; ++#endif // CONFIG_YOSEMITE ++ + struct adc_vcc_ref_data { + int v2; + int r1; +- int r2; ++ int r2; + }; + +-static struct adc_vcc_ref_data adc_vcc_ref[6] = { ++static struct adc_vcc_ref_data adc_vcc_ref[9] = { + [0] = { + .v2 = 0, + .r1 = 5600, +@@ -81,6 +101,24 @@ static struct adc_vcc_ref_data adc_vcc_ref[6] = { + .r1 = 1000, + .r2 = 1000, + }, ++ // P3V3 ++ [6] = { ++ .v2 = 0, ++ .r1 = 5110, ++ .r2 = 8250, ++ }, ++ // P5V ++ [7] = { ++ .v2 = 0, ++ .r1 = 5110, ++ .r2 = 3480, ++ }, ++ // P12V ++ [8] = { ++ .v2 = 0, ++ .r1 = 5110, ++ .r2 = 1020, ++ }, + }; + + /* Divisors for voltage sense; right now adc5 & adc6 divide by 2 */ +@@ -93,7 +131,7 @@ static int adc_divisor[] = { 1, 1, 1, 1, + struct ast_adc_data { + struct device *hwmon_dev; + void __iomem *reg_base; /* virtual */ +- int irq; //ADC IRQ number ++ int irq; //ADC IRQ number + int compen_value; //Compensating value + }; + +@@ -123,14 +161,14 @@ static void ast_adc_ctrl_init(void) + ast_adc_write(ast_adc, AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); + + //Set wait a sensing cycle t (s) = 1000 * 12 * (1/PCLK) * 2 * (ADC0c[31:17] + 1) * (ADC0c[9:0] +1) +- //ex : pclk = 48Mhz , ADC0c[31:17] = 0, ADC0c[9:0] = 0x40 : 64, ADC0c[31:17] = 0x3e7 : 999 ++ //ex : pclk = 48Mhz , ADC0c[31:17] = 0, ADC0c[9:0] = 0x40 : 64, ADC0c[31:17] = 0x3e7 : 999 + // --> 0.0325s = 12 * 2 * (0x3e7 + 1) *(64+1) / 48000000 +- // --> 0.0005s = 12 * 2 * (0x3e7 + 1) / 48000000 +- ++ // --> 0.0005s = 12 * 2 * (0x3e7 + 1) / 48000000 ++ + pclk = ast_get_pclk(); + + #if defined(CONFIG_ARCH_AST2300) +- ast_adc_write(ast_adc, 0x3e7, AST_ADC_CLK); ++ ast_adc_write(ast_adc, 0x3e7, AST_ADC_CLK); + + ast_adc_write(ast_adc, AST_ADC_CTRL_CH12_EN | AST_ADC_CTRL_COMPEN_CLR| ast_adc_read(ast_adc, AST_ADC_CTRL), AST_ADC_CTRL); + +@@ -141,16 +179,16 @@ static void ast_adc_ctrl_init(void) + ast_adc->compen_value = 0x200 - (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK); + else + ast_adc->compen_value = 0 - (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK); +- +- printk("compensating value %d \n",ast_adc->compen_value); +- ++ ++ // printk("compensating value %d \n",ast_adc->compen_value); ++ + #elif defined(CONFIG_ARCH_AST2400) + + //For AST2400 A0 workaround ... ADC0c = 1 ; + // ast_adc_write(ast_adc, 1, AST_ADC_CLK); + // ast_adc_write(ast_adc, (0x3e7<< 17) | 0x40, AST_ADC_CLK); + ast_adc_write(ast_adc, 0x40, AST_ADC_CLK); +- ++ + ast_adc_write(ast_adc, AST_ADC_CTRL_CH0_EN | AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); + + ast_adc_read(ast_adc, AST_ADC_CTRL); +@@ -159,15 +197,15 @@ static void ast_adc_ctrl_init(void) + + //compensating value = 0x200 - ADC10[9:0] + ast_adc->compen_value = 0x200 - (ast_adc_read(ast_adc, AST_ADC_CH0_1) & AST_ADC_L_CH_MASK); +- printk("compensating value %d \n",ast_adc->compen_value); ++ // printk("compensating value %d \n",ast_adc->compen_value); + + #elif defined(CONFIG_ARCH_AST2500) +-// TODO ... +-// scu read trim ++// TODO ... ++// scu read trim + // write trim 0xc4 [3:0] +- ++ + ast_adc_write(ast_adc, 0x40, AST_ADC_CLK); +- ++ + ast_adc_write(ast_adc, AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); + + while(!ast_adc_read(ast_adc, AST_ADC_CTRL) & 0x100); +@@ -175,17 +213,17 @@ static void ast_adc_ctrl_init(void) + ast_adc_write(ast_adc, AST_ADC_CTRL_COMPEN | AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); + + while(ast_adc_read(ast_adc, AST_ADC_CTRL) & AST_ADC_CTRL_COMPEN); +- ++ + //compensating value = 0x200 - ADC10[9:0] + ast_adc->compen_value = 0x200 - ((ast_adc_read(ast_adc, AST_ADC_TRIM) >> 16) & 0x3ff); +- printk("compensating value %d \n",ast_adc->compen_value); +- ++ // printk("compensating value %d \n",ast_adc->compen_value); ++ + #else + #err "No define for ADC " + #endif + + ast_adc_write(ast_adc, AST_ADC_CTRL_NORMAL | AST_ADC_CTRL_EN, AST_ADC_CTRL); +- ++ + } + + static u16 +@@ -203,9 +241,9 @@ ast_get_adc_hyster_lower(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_hyster_lower(struct ast_adc_data *ast_adc, u8 adc_ch, u16 value) + { +- ast_adc_write(ast_adc, ++ ast_adc_write(ast_adc, + (ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & ~AST_ADC_L_BOUND) | +- value, ++ value, + AST_ADC_HYSTER0 + (adc_ch *4)); + + } +@@ -224,9 +262,9 @@ ast_get_adc_hyster_upper(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_hyster_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value) + { +- ast_adc_write(ast_adc, ++ ast_adc_write(ast_adc, + (ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) & ~AST_ADC_H_BOUND) | +- (value << 16), ++ (value << 16), + AST_ADC_HYSTER0 + (adc_ch *4)); + + } +@@ -244,7 +282,7 @@ ast_get_adc_hyster_en(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_hyster_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) + { +- //tacho source ++ //tacho source + if(enable == 1) + ast_adc_write(ast_adc, + ast_adc_read(ast_adc, AST_ADC_HYSTER0 + (adc_ch *4)) | AST_ADC_HYSTER_EN, +@@ -270,9 +308,9 @@ ast_get_adc_lower(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_lower(struct ast_adc_data *ast_adc, u8 adc_ch, u16 value) + { +- ast_adc_write(ast_adc, ++ ast_adc_write(ast_adc, + (ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & ~AST_ADC_L_BOUND) | +- value, ++ value, + AST_ADC_BOUND0 + (adc_ch *4)); + + } +@@ -293,9 +331,9 @@ ast_get_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch) + static void + ast_set_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value) + { +- ast_adc_write(ast_adc, ++ ast_adc_write(ast_adc, + (ast_adc_read(ast_adc, AST_ADC_BOUND0 + (adc_ch *4)) & ~AST_ADC_H_BOUND) | +- (value << 16), ++ (value << 16), + AST_ADC_BOUND0 + (adc_ch *4)); + + } +@@ -304,7 +342,7 @@ ast_set_adc_upper(struct ast_adc_data *ast_adc, u8 adc_ch, u32 value) + static u8 + ast_get_adc_alarm(struct ast_adc_data *ast_adc, u8 adc_ch) + { +- //adc ch source ++ //adc ch source + if(ast_adc_read(ast_adc, AST_ADC_IER) & (0x1 << adc_ch)) + return 1; + else +@@ -322,61 +360,61 @@ ast_get_adc_value(struct ast_adc_data *ast_adc, u8 adc_ch) + break; + case 1: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH0_1) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 2: + tmp = ast_adc_read(ast_adc, AST_ADC_CH2_3) & AST_ADC_L_CH_MASK; + break; + case 3: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH2_3) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 4: + tmp = ast_adc_read(ast_adc, AST_ADC_CH4_5) & AST_ADC_L_CH_MASK; + break; + case 5: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH4_5) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 6: + tmp = ast_adc_read(ast_adc, AST_ADC_CH6_7) & AST_ADC_L_CH_MASK; + break; + case 7: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH6_7) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 8: + tmp = ast_adc_read(ast_adc, AST_ADC_CH8_9) & AST_ADC_L_CH_MASK; + break; + case 9: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH8_9) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 10: + tmp = ast_adc_read(ast_adc, AST_ADC_CH10_11) & AST_ADC_L_CH_MASK; + break; + case 11: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH10_11) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 12: + tmp = ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_L_CH_MASK; + break; + case 13: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH12_13) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + case 14: + tmp = ast_adc_read(ast_adc, AST_ADC_CH14_15) & AST_ADC_L_CH_MASK; + break; + case 15: + tmp = (ast_adc_read(ast_adc, AST_ADC_CH14_15) & AST_ADC_H_CH_MASK) >> 16; +- break; ++ break; + + } + + tmp += ast_adc->compen_value; + + // printk("voltage = %d \n",tmp); +- ++ + return tmp; + + } + +-static u8 ++static u8 + ast_get_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch) + { + u8 tmp=0; +@@ -390,7 +428,7 @@ ast_get_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch) + + } + +-static void ++static void + ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) + { + if(enable) +@@ -401,7 +439,7 @@ ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) + + + /* NAME sysfs */ +-static ssize_t ++static ssize_t + show_name(struct device *dev, struct device_attribute *devattr, + char *buf) + { +@@ -416,38 +454,63 @@ static const struct attribute_group name_attribute_groups = { + .attrs = name_attributes, + }; + +-/* attr ADC sysfs 0~max adc channel ++/* attr ADC sysfs 0~max adc channel + * 0 - show/store channel enable +-* 1 - show value ++* 1 - show value + * 2 - show alarm get statuse + * 3 - show/store upper +-* 4 - show/store lower +-* 5 - show/store hystersis enable +-* 6 - show/store hystersis upper +-* 7 - show/store hystersis low ++* 4 - show/store lower ++* 5 - show/store hystersis enable ++* 6 - show/store hystersis upper ++* 7 - show/store hystersis low + */ + +-static u32 ++static u32 + ast_get_voltage(int idx) { ++ u8 rest_design = REST_DESIGN; + u16 tmp; + u32 voltage, tmp1, tmp2, tmp3; + tmp = ast_get_adc_value(ast_adc, idx); ++ ++#ifdef CONFIG_YOSEMITE ++ switch (idx) { ++ case ADC_P3V3: ++ case ADC_P3V3_STBY: ++ rest_design = REST_DESIGN_P3V3; ++ break; ++ case ADC_P5V: ++ rest_design = REST_DESIGN_P5V; ++ break; ++ case ADC_P12V: ++ case ADC_P12V_SLOT0: ++ case ADC_P12V_SLOT1: ++ case ADC_P12V_SLOT2: ++ case ADC_P12V_SLOT3: ++ rest_design = REST_DESIGN_P12V; ++ break; ++ default: ++ rest_design = REST_DESIGN; ++ } ++#endif // CONFIG_YOSEMITE ++ + // Voltage Sense Method +- tmp1 = (adc_vcc_ref[REST_DESIGN].r1 + adc_vcc_ref[REST_DESIGN].r2) * tmp * 25 * 10; +- tmp2 = adc_vcc_ref[REST_DESIGN].r2 * 1024 ; +- tmp3 = (adc_vcc_ref[REST_DESIGN].r1 * adc_vcc_ref[REST_DESIGN].v2) / adc_vcc_ref[REST_DESIGN].r2; ++ tmp1 = (adc_vcc_ref[rest_design].r1 + adc_vcc_ref[rest_design].r2) * tmp * 25 * 10; ++ tmp2 = adc_vcc_ref[rest_design].r2 * 1024 ; ++ tmp3 = (adc_vcc_ref[rest_design].r1 * adc_vcc_ref[rest_design].v2) / adc_vcc_ref[rest_design].r2; + // printk("tmp3 = %d \n",tmp3); + voltage = (tmp1/tmp2) - tmp3; + ++#ifndef CONFIG_YOSEMITE + // Higher voltage inputs require a divisor + + if (adc_divisor[idx]) + voltage /= adc_divisor[idx]; ++#endif //CONFIG_YOSEMITE + + return voltage; + } + +-static ssize_t ++static ssize_t + ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) + { + struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); +@@ -455,7 +518,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) + + //sensor_attr->index : pwm_ch# + //sensor_attr->nr : attr# +- switch(sensor_attr->nr) ++ switch(sensor_attr->nr) + { + case 0: //channel enable, disable + return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_en(ast_adc,sensor_attr->index),ast_get_adc_en(ast_adc,sensor_attr->index) ? "Enable":"Disable"); +@@ -466,23 +529,23 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) + break; + case 2: //alarm + return sprintf(sysfsbuf, "%d \n", ast_get_adc_alarm(ast_adc,sensor_attr->index)); +- break; ++ break; + case 3: //upper + return sprintf(sysfsbuf, "%d \n", ast_get_adc_upper(ast_adc,sensor_attr->index)); +- break; ++ break; + case 4: //lower + return sprintf(sysfsbuf, "%d \n", ast_get_adc_lower(ast_adc,sensor_attr->index)); +- break; +- case 5: //hystersis enable ++ break; ++ case 5: //hystersis enable + return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_hyster_en(ast_adc,sensor_attr->index),ast_get_adc_hyster_en(ast_adc,sensor_attr->index) ? "Enable":"Disable"); +- break; ++ break; + case 6: //hystersis upper + return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_upper(ast_adc,sensor_attr->index)); +- break; ++ break; + case 7: //hystersis lower + return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_lower(ast_adc,sensor_attr->index)); +- break; +- case 8: ++ break; ++ case 8: + voltage = ast_get_voltage(sensor_attr->index); + return sprintf(sysfsbuf, "%d\n",voltage * 10); + +@@ -492,7 +555,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) + } + } + +-static ssize_t ++static ssize_t + ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sysfsbuf, size_t count) + { + u32 input_val; +@@ -503,16 +566,16 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys + + //sensor_attr->index : pwm_ch# + //sensor_attr->nr : attr# +- switch(sensor_attr->nr) ++ switch(sensor_attr->nr) + { + case 0: //enable, disable + ast_set_adc_en(ast_adc, sensor_attr->index, input_val); + break; + case 1: //value +- ++ + break; + case 2: //alarm +- break; ++ break; + case 3: + ast_set_adc_upper(ast_adc, sensor_attr->index, input_val); + break; +@@ -521,14 +584,14 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys + break; + case 5: //hystersis + ast_set_adc_hyster_en(ast_adc, sensor_attr->index, input_val); +- break; ++ break; + case 6: + ast_set_adc_hyster_upper(ast_adc, sensor_attr->index, input_val); + break; + case 7: + ast_set_adc_hyster_lower(ast_adc, sensor_attr->index, input_val); + break; +- ++ + default: + return -EINVAL; + break; +@@ -537,15 +600,15 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys + return count; + } + +-/* attr ADC sysfs 0~max adc channel ++/* attr ADC sysfs 0~max adc channel + * 0 - show/store channel enable +-* 1 - show value ++* 1 - show value + * 2 - show alarm get statuse + * 3 - show/store upper +-* 4 - show/store lower +-* 5 - show/store hystersis enable +-* 6 - show/store hystersis upper +-* 7 - show/store hystersis low ++* 4 - show/store lower ++* 5 - show/store hystersis enable ++* 6 - show/store hystersis upper ++* 7 - show/store hystersis low + * 8 - show value as 1000s, expected by lm-sensors + */ + +@@ -624,18 +687,18 @@ static const struct attribute_group adc_attribute_groups[] = { + { .attrs = adc7_attributes }, + { .attrs = adc8_attributes }, + { .attrs = adc9_attributes }, +- { .attrs = adc10_attributes }, ++ { .attrs = adc10_attributes }, + { .attrs = adc11_attributes }, + #if defined(CONFIG_ARCH_AST2400) || defined(CONFIG_ARCH_AST2500) + { .attrs = adc12_attributes }, + { .attrs = adc13_attributes }, + { .attrs = adc14_attributes }, + { .attrs = adc15_attributes }, +-#endif ++#endif + }; + + +-static int ++static int + ast_adc_probe(struct platform_device *pdev) + { + struct resource *res; +@@ -695,7 +758,7 @@ ast_adc_probe(struct platform_device *pdev) + } + + ast_adc_ctrl_init(); +- ++ + printk(KERN_INFO "ast_adc: driver successfully loaded.\n"); + + return 0; +@@ -714,7 +777,7 @@ out: + return ret; + } + +-static int ++static int + ast_adc_remove(struct platform_device *pdev) + { + int i=0; +@@ -739,14 +802,14 @@ ast_adc_remove(struct platform_device *pdev) + } + + #ifdef CONFIG_PM +-static int ++static int + ast_adc_suspend(struct platform_device *pdev, pm_message_t state) + { + printk("ast_adc_suspend : TODO \n"); + return 0; + } + +-static int ++static int + ast_adc_resume(struct platform_device *pdev) + { + ast_adc_ctrl_init(); +@@ -769,13 +832,13 @@ static struct platform_driver ast_adc_driver = { + }, + }; + +-static int __init ++static int __init + ast_adc_init(void) + { + return platform_driver_register(&ast_adc_driver); + } + +-static void __exit ++static void __exit + ast_adc_exit(void) + { + platform_driver_unregister(&ast_adc_driver); +diff --git a/drivers/i2c/busses/i2c-ast.c b/drivers/i2c/busses/i2c-ast.c +index 7a083de..9bb3154 100644 +--- a/drivers/i2c/busses/i2c-ast.c ++++ b/drivers/i2c/busses/i2c-ast.c +@@ -40,63 +40,68 @@ + #include <plat/ast_i2c.h> + #endif + +-//AST2400 buffer mode issue , force I2C slave write use byte mode , read use buffer mode ++//AST2400 buffer mode issue , force I2C slave write use byte mode , read use buffer mode + /* Use platform_data instead of module parameters */ + /* Fast Mode = 400 kHz, Standard = 100 kHz */ + //static int clock = 100; /* Default: 100 kHz */ + + + /***************************************************************************/ ++ ++#ifdef CONFIG_AST_I2C_SLAVE_RDWR ++#define I2C_S_BUF_SIZE 64 ++#define I2C_S_RX_BUF_NUM 4 ++#define BUFF_FULL 0xff00 ++#define BUFF_ONGOING 1 ++#endif ++ ++#define AST_LOCKUP_DETECTED (0x1 << 15) ++ + struct ast_i2c_dev { + struct ast_i2c_driver_data *ast_i2c_data; + struct device *dev; +- void __iomem *reg_base; /* virtual */ +- int irq; //I2C IRQ number +- u32 bus_id; //for i2c dev# IRQ number check +- u32 state; //I2C xfer mode state matchine ++ void __iomem *reg_base; /* virtual */ ++ int irq; //I2C IRQ number ++ u32 bus_id; //for i2c dev# IRQ number check ++ u32 state; //I2C xfer mode state matchine + struct i2c_adapter adap; +- struct buf_page *req_page; ++ struct buf_page *req_page; + //dma or buff mode needed + unsigned char *dma_buf; + dma_addr_t dma_addr; +- +-//master ++ ++//master + int xfer_last; //cur xfer is last msgs for stop msgs + struct i2c_msg *master_msgs; //cur xfer msgs +- int master_xfer_len; //cur xfer len ++ int master_xfer_len; //cur xfer len + int master_xfer_cnt; //total xfer count + u32 master_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx + struct completion cmd_complete; + int cmd_err; + u8 blk_r_flag; //for smbus block read +- void (*do_master_xfer)(struct ast_i2c_dev *i2c_dev); +-//Slave structure ++ void (*do_master_xfer)(struct ast_i2c_dev *i2c_dev); ++ spinlock_t master_lock; ++//Slave structure + u8 slave_operation; + u8 slave_event; + struct i2c_msg *slave_msgs; //cur slave xfer msgs +- int slave_xfer_len; +- int slave_xfer_cnt; +- u32 slave_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx ++ int slave_xfer_len; ++ int slave_xfer_cnt; ++ u32 slave_xfer_mode; //cur xfer mode ... 0 : no_op , master: 1 byte , 2 : buffer , 3: dma , slave : xxxx + void (*do_slave_xfer)(struct ast_i2c_dev *i2c_dev); +-}; +- + #ifdef CONFIG_AST_I2C_SLAVE_RDWR +-#define I2C_S_BUF_SIZE 64 +-#define I2C_S_RX_BUF_NUM 4 +-#define BUFF_FULL 0xff00 +-#define BUFF_ONGOING 1 +- +-struct i2c_msg slave_rx_msg[I2C_S_RX_BUF_NUM + 1]; +-struct i2c_msg slave_tx_msg; +-static spinlock_t slave_rx_lock = SPIN_LOCK_UNLOCKED; ++ struct i2c_msg slave_rx_msg[I2C_S_RX_BUF_NUM + 1]; ++ struct i2c_msg slave_tx_msg; ++ spinlock_t slave_rx_lock; + #endif ++}; ++ + +-static spinlock_t g_master_lock = SPIN_LOCK_UNLOCKED; + + static inline void + ast_i2c_write(struct ast_i2c_dev *i2c_dev, u32 val, u32 reg) + { +-// dev_dbg(i2c_dev->dev, "ast_i2c_write : val: %x , reg : %x \n",val,reg); ++// dev_dbg(i2c_dev->dev, "ast_i2c_write : val: %x , reg : %x \n",val,reg); + writel(val, i2c_dev->reg_base+ reg); + } + +@@ -107,7 +112,7 @@ ast_i2c_read(struct ast_i2c_dev *i2c_dev, u32 reg) + u32 val = readl(i2c_dev->reg_base + reg); + printk("R : reg %x , val: %x \n",reg, val); + return val; +-#else ++#else + return readl(i2c_dev->reg_base + reg); + #endif + } +@@ -152,7 +157,7 @@ static void ast_slave_issue_alert(struct ast_i2c_dev *i2c_dev, u8 enable) + static void ast_slave_mode_enable(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msgs) + { + if(msgs->buf[0] == 1) { +- ast_i2c_write(i2c_dev, msgs->addr, I2C_DEV_ADDR_REG); ++ ast_i2c_write(i2c_dev, msgs->addr, I2C_DEV_ADDR_REG); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG) | AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG); + } else + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG) & ~AST_I2CD_SLAVE_EN, I2C_FUN_CTRL_REG); +@@ -162,12 +167,14 @@ static void ast_slave_mode_enable(struct ast_i2c_dev *i2c_dev, struct i2c_msg *m + + static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) + { +- //I2CG Reset ++ //I2CG Reset + ast_i2c_write(i2c_dev, 0, I2C_FUN_CTRL_REG); + +-#ifdef CONFIG_AST_I2C_SLAVE_EEPROM ++#ifdef CONFIG_AST_I2C_SLAVE_EEPROM + i2c_dev->ast_i2c_data->slave_init(&(i2c_dev->slave_msgs)); + ast_slave_mode_enable(i2c_dev, i2c_dev->slave_msgs); ++#else ++ i2c_dev->slave_msgs = i2c_dev->slave_rx_msg; + #endif + + //Enable Master Mode +@@ -177,20 +184,20 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) + /* Set AC Timing */ + #if defined(CONFIG_ARCH_AST2400) + if(i2c_dev->ast_i2c_data->bus_clk/1000 > 400) { +- printk("high speed mode enable clk [%dkhz]\n",i2c_dev->ast_i2c_data->bus_clk/1000); ++ printk("high speed mode enable clk [%dkhz]\n",i2c_dev->ast_i2c_data->bus_clk/1000); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) | + AST_I2CD_M_HIGH_SPEED_EN | + AST_I2CD_M_SDA_DRIVE_1T_EN | +- AST_I2CD_SDA_DRIVE_1T_EN ++ AST_I2CD_SDA_DRIVE_1T_EN + , I2C_FUN_CTRL_REG); +- ++ + /* Set AC Timing */ + ast_i2c_write(i2c_dev, 0x3, I2C_AC_TIMING_REG2); +- ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); ++ ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); + }else { +- /* target apeed is xxKhz*/ ++ /* target apeed is xxKhz*/ + ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); +- ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2); ++ ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2); + } + #else + /* target apeed is xxKhz*/ +@@ -206,12 +213,12 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) + + //TODO + // ast_i2c_write(i2c_dev, 0xAF, I2C_INTR_CTRL_REG); +- //Enable Interrupt, STOP Interrupt has bug in AST2000 +- ++ //Enable Interrupt, STOP Interrupt has bug in AST2000 ++ + /* Set interrupt generation of I2C controller */ + ast_i2c_write(i2c_dev, +- AST_I2CD_SDA_DL_TO_INTR_EN | +- AST_I2CD_BUS_RECOVER_INTR_EN | ++ AST_I2CD_SDA_DL_TO_INTR_EN | ++ AST_I2CD_BUS_RECOVER_INTR_EN | + AST_I2CD_SMBUS_ALT_INTR_EN | + // AST_I2CD_SLAVE_MATCH_INTR_EN | + AST_I2CD_SCL_TO_INTR_EN | +@@ -230,16 +237,16 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) + static void ast_i2c_slave_buff_init(struct ast_i2c_dev *i2c_dev) + { + int i; +- //Tx buf 1 +- slave_tx_msg.len = I2C_S_BUF_SIZE; +- slave_tx_msg.buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); ++ //Tx buf 1 ++ i2c_dev->slave_tx_msg.len = I2C_S_BUF_SIZE; ++ i2c_dev->slave_tx_msg.buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); + //Rx buf 4 + for(i=0; i<I2C_S_RX_BUF_NUM+1; i++) { +- slave_rx_msg[i].addr = ~BUFF_ONGOING; +- slave_rx_msg[i].flags = 0; //mean empty buffer +- slave_rx_msg[i].len = I2C_S_BUF_SIZE; +- slave_rx_msg[i].buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); +- } ++ i2c_dev->slave_rx_msg[i].addr = ~BUFF_ONGOING; ++ i2c_dev->slave_rx_msg[i].flags = 0; //mean empty buffer ++ i2c_dev->slave_rx_msg[i].len = I2C_S_BUF_SIZE; ++ i2c_dev->slave_rx_msg[i].buf = kzalloc(I2C_S_BUF_SIZE, GFP_KERNEL); ++ } + } + + static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) +@@ -247,13 +254,13 @@ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) + int i; + unsigned long flags; + +- spin_lock_irqsave(&slave_rx_lock, flags); +- ++ spin_lock_irqsave(&i2c_dev->slave_rx_lock, flags); ++ + switch(i2c_dev->slave_event) { + case I2C_SLAVE_EVENT_START_WRITE: + for(i=0; i<I2C_S_RX_BUF_NUM; i++) { +- if((slave_rx_msg[i].flags == 0) && (slave_rx_msg[i].addr != BUFF_ONGOING)) { +- slave_rx_msg[i].addr = BUFF_ONGOING; ++ if((i2c_dev->slave_rx_msg[i].flags == 0) && (i2c_dev->slave_rx_msg[i].addr != BUFF_ONGOING)) { ++ i2c_dev->slave_rx_msg[i].addr = BUFF_ONGOING; + break; + } + } +@@ -261,40 +268,40 @@ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) + printk("RX buffer full ........use tmp msgs buff \n"); + //TODO... + } +- printk("I2C_SLAVE_EVENT_START_WRITE ... %d \n", i); ++ //printk("I2C_SLAVE_EVENT_START_WRITE ... %d \n", i); + +- i2c_dev->slave_msgs = &slave_rx_msg[i]; ++ i2c_dev->slave_msgs = &i2c_dev->slave_rx_msg[i]; + break; + case I2C_SLAVE_EVENT_START_READ: +- printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); +- i2c_dev->slave_msgs = &slave_tx_msg; ++ //printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + case I2C_SLAVE_EVENT_WRITE: +- printk("I2C_SLAVE_EVENT_WRITE next write ERROR ...\n"); +- i2c_dev->slave_msgs = &slave_tx_msg; ++ //printk("I2C_SLAVE_EVENT_WRITE next write ERROR ...\n"); ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + case I2C_SLAVE_EVENT_READ: +- printk("I2C_SLAVE_EVENT_READ ERROR ... \n"); +- i2c_dev->slave_msgs = &slave_tx_msg; ++ printk("I2C_SLAVE_EVENT_READ ERROR ... \n"); ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + case I2C_SLAVE_EVENT_NACK: +- printk("I2C_SLAVE_EVENT_NACK ERROR ... \n"); +- i2c_dev->slave_msgs = &slave_tx_msg; ++ //printk("I2C_SLAVE_EVENT_NACK ERROR ... \n"); ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + case I2C_SLAVE_EVENT_STOP: +- printk("I2C_SLAVE_EVENT_STOP \n"); ++ //printk("I2C_SLAVE_EVENT_STOP \n"); + for(i=0; i<I2C_S_RX_BUF_NUM; i++) { +- if(slave_rx_msg[i].addr == BUFF_ONGOING) { +- slave_rx_msg[i].flags = BUFF_FULL; +- slave_rx_msg[i].addr = 0; ++ if(i2c_dev->slave_rx_msg[i].addr == BUFF_ONGOING) { ++ i2c_dev->slave_rx_msg[i].flags = BUFF_FULL; ++ i2c_dev->slave_rx_msg[i].addr = 0; + break; + } + } +- +- i2c_dev->slave_msgs = &slave_tx_msg; ++ ++ i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; + break; + } +- spin_unlock_irqrestore(&slave_rx_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->slave_rx_lock, flags); + + } + +@@ -308,29 +315,29 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) + case 0: + // printk("slave read \n"); + //cur_msg = get_free_msg; +- spin_lock_irqsave(&slave_rx_lock, flags); ++ spin_lock_irqsave(&i2c_dev->slave_rx_lock, flags); + + for(i=0; i<I2C_S_RX_BUF_NUM; i++) { +- if((slave_rx_msg[i].addr == 0) && (slave_rx_msg[i].flags == BUFF_FULL)) { +- memcpy(msgs->buf, slave_rx_msg[i].buf, slave_rx_msg[i].len); +- msgs->len = slave_rx_msg[i].len; +- slave_rx_msg[i].flags = 0; +- slave_rx_msg[i].len = 0; ++ if((i2c_dev->slave_rx_msg[i].addr == 0) && (i2c_dev->slave_rx_msg[i].flags == BUFF_FULL)) { ++ memcpy(msgs->buf, i2c_dev->slave_rx_msg[i].buf, i2c_dev->slave_rx_msg[i].len); ++ msgs->len = i2c_dev->slave_rx_msg[i].len; ++ i2c_dev->slave_rx_msg[i].flags = 0; ++ i2c_dev->slave_rx_msg[i].len = 0; + break; + } + } +- spin_unlock_irqrestore(&slave_rx_lock, flags); +- ++ spin_unlock_irqrestore(&i2c_dev->slave_rx_lock, flags); ++ + if(i == I2C_S_RX_BUF_NUM) { +- printk("No buffer ........ \n"); ++ //printk("No buffer ........ \n"); + msgs->len = 0; + ret = -1; + } + break; + case I2C_M_RD: //slave write + // printk("slave write \n"); +- memcpy(msgs->buf, slave_tx_msg.buf, I2C_S_BUF_SIZE); +- break; ++ memcpy(msgs->buf, i2c_dev->slave_tx_msg.buf, I2C_S_BUF_SIZE); ++ break; + case I2C_S_EN: + if((msgs->addr < 0x1) || (msgs->addr > 0xff)) { + ret = -1; +@@ -352,7 +359,7 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) + default: + printk("slave xfer error \n"); + break; +- ++ + } + return ret; + } +@@ -360,16 +367,16 @@ static int ast_i2c_slave_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs) + + #endif + +-static u8 ++static u8 + ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + { + u32 sts; +- int r; ++ int r; + u32 i = 0; +- ++ + //Check 0x14's SDA and SCL status + sts = ast_i2c_read(i2c_dev,I2C_CMD_REG); +- ++ + if ((sts & AST_I2CD_SDA_LINE_STS) && (sts & AST_I2CD_SCL_LINE_STS)) { + //Means bus is idle. + dev_dbg(i2c_dev->dev, "I2C bus (%d) is idle. I2C slave doesn't exist?!\n", i2c_dev->bus_id); +@@ -377,11 +384,11 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + } + + dev_dbg(i2c_dev->dev, "ERROR!! I2C(%d) bus hanged, try to recovery it!\n", i2c_dev->bus_id); +- +- ++ ++ + if ((sts & AST_I2CD_SDA_LINE_STS) && !(sts & AST_I2CD_SCL_LINE_STS)) { + //if SDA == 1 and SCL == 0, it means the master is locking the bus. +- //Send a stop command to unlock the bus. ++ //Send a stop command to unlock the bus. + dev_dbg(i2c_dev->dev, "I2C's master is locking the bus, try to stop it.\n"); + // + init_completion(&i2c_dev->cmd_complete); +@@ -397,12 +404,12 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + dev_dbg(i2c_dev->dev, "recovery error \n"); + return -1; + } +- ++ + if (r == 0) { + dev_dbg(i2c_dev->dev, "recovery timed out\n"); + return -1; + } else { +- dev_dbg(i2c_dev->dev, "Recovery successfully\n"); ++ dev_dbg(i2c_dev->dev, "Recovery successfully\n"); + return 0; + } + +@@ -415,11 +422,11 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + for (i = 0; i < 10; i++) { + ast_i2c_dev_init(i2c_dev); + //Do the recovery command BIT11 +- init_completion(&i2c_dev->cmd_complete); ++ init_completion(&i2c_dev->cmd_complete); + ast_i2c_write(i2c_dev, AST_I2CD_BUS_RECOVER_CMD_EN, I2C_CMD_REG); +- ++ + r = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, +- i2c_dev->adap.timeout*HZ); ++ i2c_dev->adap.timeout*HZ); + if (i2c_dev->cmd_err != 0 && + i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { + dev_dbg(i2c_dev->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", i2c_dev->cmd_err); +@@ -438,31 +445,56 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) + dev_dbg(i2c_dev->dev, "Don't know how to handle this case?!\n"); + return -1; + } +- dev_dbg(i2c_dev->dev, "Recovery successfully\n"); ++ dev_dbg(i2c_dev->dev, "Recovery successfully\n"); + return 0; + } + +-static void ast_master_alert_recv(struct ast_i2c_dev *i2c_dev) ++static void ast_master_alert_recv(struct ast_i2c_dev *i2c_dev) + { + printk("ast_master_alert_recv bus id %d, Disable Alt, Please Imple \n",i2c_dev->bus_id); + } + + static int ast_i2c_wait_bus_not_busy(struct ast_i2c_dev *i2c_dev) + { +- int timeout = 32; //TODO number ++ int timeout = 10; //TODO number ++ volatile u8 mode = 0; + // printk("ast_i2c_wait_bus_not_busy \n"); ++ ++ // Wait for slave transfer to finish ++ mode = i2c_dev->slave_operation; ++ while (mode == 1) { ++ if (timeout <= 0) { ++ break; ++ } ++ mode = i2c_dev->slave_operation; ++ timeout--; ++ msleep(1); ++ } ++ ++ if (timeout <= 0) { ++ return -EAGAIN; ++ } ++ ++ // Wait for Bus to go IDLE ++ timeout = 10; + while (ast_i2c_read(i2c_dev,I2C_CMD_REG) & AST_I2CD_BUS_BUSY_STS) { +- ast_i2c_bus_error_recover(i2c_dev); +- if(timeout<=0) ++ if(timeout<=0) { + break; ++ } ++ + timeout--; +- msleep(2); ++ msleep(1); + } + +- return timeout <= 0 ? EAGAIN : 0; ++ if (timeout <=0) { ++ ast_i2c_bus_error_recover(i2c_dev); ++ return 0; ++ } ++ ++ return 0; + } + +-static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) ++static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + { + u32 cmd = 0; + int i; +@@ -470,49 +502,49 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + i2c_dev->master_xfer_mode = DMA_XFER; + i2c_dev->slave_xfer_mode = DMA_XFER; + +- if(i2c_dev->slave_operation == 1) { ++ if(i2c_dev->slave_operation == 1) { + if(i2c_dev->slave_msgs->flags & I2C_M_RD) { + //DMA tx mode + if(i2c_dev->slave_msgs->len > AST_I2C_DMA_SIZE) + i2c_dev->slave_xfer_len = AST_I2C_DMA_SIZE; +- else ++ else + i2c_dev->slave_xfer_len = i2c_dev->slave_msgs->len; +- ++ + dev_dbg(i2c_dev->dev, "(<--) slave tx DMA \n"); + for(i=0; i<i2c_dev->slave_xfer_len; i++) + i2c_dev->dma_buf[i] = i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt + i]; +- ++ + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); + ast_i2c_write(i2c_dev, (i2c_dev->slave_xfer_len-1), I2C_DMA_LEN_REG); +- ast_i2c_write(i2c_dev, AST_I2CD_TX_DMA_ENABLE | AST_I2CD_S_TX_CMD,I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_TX_DMA_ENABLE | AST_I2CD_S_TX_CMD,I2C_CMD_REG); + } else { + //DMA prepare rx + dev_dbg(i2c_dev->dev, "(-->) slave rx DMA \n"); + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); + ast_i2c_write(i2c_dev, (AST_I2C_DMA_SIZE-1), I2C_DMA_LEN_REG); +- ast_i2c_write(i2c_dev, AST_I2CD_RX_DMA_ENABLE, I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_RX_DMA_ENABLE, I2C_CMD_REG); + } + } else { + dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); + if(i2c_dev->master_xfer_cnt == -1) { +- //send start ++ //send start + dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n", + i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write", + i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "", + i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr); + + if(i2c_dev->master_msgs->flags & I2C_M_RD) { +- //workaround .. HW can;t send start read addr with buff mode ++ //workaround .. HW can;t send start read addr with buff mode + cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD; + ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); + + // tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 + i2c_dev->master_xfer_len = 1; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { + //tx +- cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_DMA_ENABLE; ++ cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_DMA_ENABLE; + + i2c_dev->dma_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 + //next data write +@@ -520,44 +552,44 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE; + else + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len + 1; +- ++ + for(i = 1; i < i2c_dev->master_xfer_len; i++) + i2c_dev->dma_buf[i] = i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt+i]; +- ++ + if (i2c_dev->xfer_last == 1) { + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); + ast_i2c_write(i2c_dev, (i2c_dev->master_xfer_len-1), I2C_DMA_LEN_REG); +- ++ + } +- ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); + dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); + + } else if (i2c_dev->master_xfer_cnt < i2c_dev->master_msgs->len){ +- //Next send ++ //Next send + if(i2c_dev->master_msgs->flags & I2C_M_RD) { + //Rx data + cmd = AST_I2CD_M_RX_CMD | AST_I2CD_RX_DMA_ENABLE; +- ++ + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > AST_I2C_DMA_SIZE) { + i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); +- ++ + } else { + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt; + if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { + dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n"); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { + #ifdef CONFIG_AST1010 + //Workaround for ast1010 can't send NACK +@@ -568,7 +600,7 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + i2c_dev->master_xfer_mode = BYTE_XFER; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & + ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); +- ++ + } else if (i2c_dev->master_xfer_len > 1) { + i2c_dev->master_xfer_len -=1; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +@@ -578,8 +610,8 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + } + #else + if(i2c_dev->xfer_last == 1) { +- dev_dbg(i2c_dev->dev, "last stop \n"); +- cmd |= AST_I2CD_M_STOP_CMD; ++ dev_dbg(i2c_dev->dev, "last stop \n"); ++ cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & + ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { +@@ -588,9 +620,9 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + } + //TODO check.... + cmd |= AST_I2CD_M_S_RX_CMD_LAST; +-#endif ++#endif + } +- ++ + } + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); + ast_i2c_write(i2c_dev, i2c_dev->master_xfer_len-1, I2C_DMA_LEN_REG); +@@ -603,23 +635,23 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > AST_I2C_DMA_SIZE) { + i2c_dev->master_xfer_len = AST_I2C_DMA_SIZE; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt; + if(i2c_dev->xfer_last == 1) { + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } + } + +- for(i = 0; i < i2c_dev->master_xfer_len; i++) ++ for(i = 0; i < i2c_dev->master_xfer_len; i++) + i2c_dev->dma_buf[i] = i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i]; + + ast_i2c_write(i2c_dev, i2c_dev->dma_addr, I2C_DMA_BASE_REG); +@@ -627,33 +659,33 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) + ast_i2c_write(i2c_dev, cmd , I2C_CMD_REG); + dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); + +- } ++ } + }else { +- //should send next msg ++ //should send next msg + if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) + printk("complete rx ... bus=%d addr=0x%x (%d vs. %d) ERROR\n", + i2c_dev->bus_id, i2c_dev->master_msgs->addr, + i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); +- ++ + dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n"); + i2c_dev->cmd_err = 0; +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + } +- ++ + } + +- ++ + } + +-static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) ++static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + { + u32 cmd = 0; + int i; + u32 *tx_buf; + + i2c_dev->master_xfer_mode = BUFF_XFER; +- i2c_dev->slave_xfer_mode = BUFF_XFER; +- ++ i2c_dev->slave_xfer_mode = BUFF_XFER; ++ + #if defined(CONFIG_ARCH_AST2400) + ast_i2c_write(i2c_dev, + (ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) & +@@ -665,15 +697,15 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + tx_buf = (u32 *) i2c_dev->req_page->page_addr; + + +- if(i2c_dev->slave_operation == 1) { ++ if(i2c_dev->slave_operation == 1) { + if(i2c_dev->slave_msgs->flags & I2C_M_RD) { + dev_dbg(i2c_dev->dev, "(<--) slave tx buf \n"); +- ++ + if(i2c_dev->slave_msgs->len > i2c_dev->req_page->page_size) + i2c_dev->slave_xfer_len = i2c_dev->req_page->page_size; + else + i2c_dev->slave_xfer_len = i2c_dev->slave_msgs->len; +- ++ + for(i = 0; i< i2c_dev->slave_xfer_len; i++) { + if(i%4 == 0) + tx_buf[i/4] = 0; +@@ -681,80 +713,80 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + dev_dbg(i2c_dev->dev, "[%x] ",tx_buf[i/4]); + } + dev_dbg(i2c_dev->dev, "\n"); +- +- ast_i2c_write(i2c_dev, AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->slave_xfer_len-1)) | +- AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)), ++ ++ ast_i2c_write(i2c_dev, AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->slave_xfer_len-1)) | ++ AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)), + I2C_BUF_CTRL_REG); +- ++ + ast_i2c_write(i2c_dev, AST_I2CD_TX_BUFF_ENABLE | AST_I2CD_S_TX_CMD, I2C_CMD_REG); + } else { + //prepare for new rx + dev_dbg(i2c_dev->dev, "(-->) slave prepare rx buf \n"); +- ast_i2c_write(i2c_dev, ++ ast_i2c_write(i2c_dev, + AST_I2CD_RX_BUF_END_ADDR_SET((i2c_dev->req_page->page_size-1)) | + AST_I2CD_BUF_BASE_ADDR_SET((i2c_dev->req_page->page_addr_point)), + I2C_BUF_CTRL_REG); + +- ast_i2c_write(i2c_dev, AST_I2CD_RX_BUFF_ENABLE, I2C_CMD_REG); +- ++ ast_i2c_write(i2c_dev, AST_I2CD_RX_BUFF_ENABLE, I2C_CMD_REG); ++ + } + } else { + dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); + if(i2c_dev->master_xfer_cnt == -1) { +- //send start ++ //send start + dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n", + i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write", + i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "", + i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr); + + if(i2c_dev->master_msgs->flags & I2C_M_RD) { +-//workaround .. HW can;t send start read addr with buff mode ++//workaround .. HW can;t send start read addr with buff mode + cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD; + ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); + + // tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 + i2c_dev->master_xfer_len = 1; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } else { +- cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_BUFF_ENABLE; ++ cmd = AST_I2CD_M_START_CMD | AST_I2CD_M_TX_CMD | AST_I2CD_TX_BUFF_ENABLE; + tx_buf[0] = (i2c_dev->master_msgs->addr <<1); //+1 + //next data write + if((i2c_dev->master_msgs->len + 1) > i2c_dev->req_page->page_size) + i2c_dev->master_xfer_len = i2c_dev->req_page->page_size; + else + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len + 1; +- ++ + for(i = 1; i < i2c_dev->master_xfer_len; i++) { + if(i%4 == 0) + tx_buf[i/4] = 0; + tx_buf[i/4] |= (i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] << ((i%4)*8)) ; + } +- ++ + if (i2c_dev->xfer_last == 1) { + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } +- ast_i2c_write(i2c_dev, ++ ast_i2c_write(i2c_dev, + AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->master_xfer_len - 1)) | + AST_I2CD_BUF_BASE_ADDR_SET(i2c_dev->req_page->page_addr_point), + I2C_BUF_CTRL_REG); + } +- ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); + dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); + + } else if (i2c_dev->master_xfer_cnt < i2c_dev->master_msgs->len){ +- //Next send ++ //Next send + if(i2c_dev->master_msgs->flags & I2C_M_RD) { + //Rx data + cmd = AST_I2CD_M_RX_CMD | AST_I2CD_RX_BUFF_ENABLE; +- ++ + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > i2c_dev->req_page->page_size) { + i2c_dev->master_xfer_len = i2c_dev->req_page->page_size; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +@@ -764,11 +796,11 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { + dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n"); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { + if(i2c_dev->xfer_last == 1) { +- dev_dbg(i2c_dev->dev, "last stop \n"); +- cmd |= AST_I2CD_M_STOP_CMD; ++ dev_dbg(i2c_dev->dev, "last stop \n"); ++ cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & + ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { +@@ -791,46 +823,46 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) + if((i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt) > i2c_dev->req_page->page_size) { + i2c_dev->master_xfer_len = i2c_dev->req_page->page_size; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + i2c_dev->master_xfer_len = i2c_dev->master_msgs->len - i2c_dev->master_xfer_cnt; + if(i2c_dev->xfer_last == 1) { + dev_dbg(i2c_dev->dev, "last stop \n"); + cmd |= AST_I2CD_M_STOP_CMD; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + } + } +- ++ + for(i = 0; i < i2c_dev->master_xfer_len; i++) { + if(i%4 == 0) + tx_buf[i/4] = 0; + tx_buf[i/4] |= (i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt + i] << ((i%4)*8)) ; + } +-// printk("count %x \n",ast_i2c_read(i2c_dev,I2C_CMD_REG)); +- ast_i2c_write(i2c_dev, ++// printk("count %x \n",ast_i2c_read(i2c_dev,I2C_CMD_REG)); ++ ast_i2c_write(i2c_dev, + AST_I2CD_TX_DATA_BUF_END_SET((i2c_dev->master_xfer_len - 1)) | + AST_I2CD_BUF_BASE_ADDR_SET(i2c_dev->req_page->page_addr_point), + I2C_BUF_CTRL_REG); +- ++ + ast_i2c_write(i2c_dev, cmd , I2C_CMD_REG); + dev_dbg(i2c_dev->dev, "txfer size %d , cmd = %x \n",i2c_dev->master_xfer_len, cmd); + } + } else { +- //should send next msg ++ //should send next msg + if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) + printk("complete rx ... bus=%d addr=0x%x (%d vs. %d) ERROR\n", + i2c_dev->bus_id, i2c_dev->master_msgs->addr, + i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); +- ++ + dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n"); + i2c_dev->cmd_err = 0; +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + } + + } +@@ -843,16 +875,16 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + i2c_dev->master_xfer_mode = BYTE_XFER; + i2c_dev->master_xfer_len = 1; + +- i2c_dev->slave_xfer_mode = BYTE_XFER; ++ i2c_dev->slave_xfer_mode = BYTE_XFER; + i2c_dev->slave_xfer_len = 1; +- +- if(i2c_dev->slave_operation == 1) { ++ ++ if(i2c_dev->slave_operation == 1) { + dev_dbg(i2c_dev->dev,"S cnt %d, xf len %d \n",i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->len); + if(i2c_dev->slave_msgs->flags & I2C_M_RD) { + //READ <-- TX + dev_dbg(i2c_dev->dev, "(<--) slave(tx) buf %d [%x]\n", i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt]); + ast_i2c_write(i2c_dev, i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt], I2C_BYTE_BUF_REG); +- ast_i2c_write(i2c_dev, AST_I2CD_S_TX_CMD, I2C_CMD_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_S_TX_CMD, I2C_CMD_REG); + } else { + // Write -->Rx + //no need to handle in byte mode +@@ -862,21 +894,21 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + } else { + dev_dbg(i2c_dev->dev,"M cnt %d, xf len %d \n",i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); + if(i2c_dev->master_xfer_cnt == -1) { +- //first start ++ //first start + dev_dbg(i2c_dev->dev, " %sing %d byte%s %s 0x%02x\n", + i2c_dev->master_msgs->flags & I2C_M_RD ? "read" : "write", + i2c_dev->master_msgs->len, i2c_dev->master_msgs->len > 1 ? "s" : "", + i2c_dev->master_msgs->flags & I2C_M_RD ? "from" : "to", i2c_dev->master_msgs->addr); +- +- +- if(i2c_dev->master_msgs->flags & I2C_M_RD) ++ ++ ++ if(i2c_dev->master_msgs->flags & I2C_M_RD) + ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1) |0x1, I2C_BYTE_BUF_REG); + else + ast_i2c_write(i2c_dev, (i2c_dev->master_msgs->addr <<1), I2C_BYTE_BUF_REG); + + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); +- ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ + ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD | AST_I2CD_M_START_CMD, I2C_CMD_REG); + + +@@ -888,7 +920,7 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + if((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->master_xfer_cnt == 0)) { + dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN \n"); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + + } else if((i2c_dev->xfer_last == 1) && (i2c_dev->master_xfer_cnt + 1 == i2c_dev->master_msgs->len)) { + cmd |= AST_I2CD_M_S_RX_CMD_LAST | AST_I2CD_M_STOP_CMD; +@@ -897,11 +929,11 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + ~AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + } + + dev_dbg(i2c_dev->dev, "(<--) rx byte, cmd = %x \n",cmd); +- ++ + ast_i2c_write(i2c_dev, cmd, I2C_CMD_REG); + + +@@ -911,29 +943,29 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) + ast_i2c_write(i2c_dev, *(xfer_buf + i2c_dev->master_xfer_cnt), I2C_BYTE_BUF_REG); + if((i2c_dev->xfer_last == 1) && (i2c_dev->master_xfer_cnt + 1 == i2c_dev->master_msgs->len)) { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & +- ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ ~AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD | AST_I2CD_M_STOP_CMD, I2C_CMD_REG); + } else { + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | +- AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); ++ AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_write(i2c_dev, AST_I2CD_M_TX_CMD, I2C_CMD_REG); + } + } +- ++ + } else { +- //should send next msg ++ //should send next msg + if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) + printk("CNT ERROR bus=%d addr=0x%x (%d vs. %d)\n", + i2c_dev->bus_id, i2c_dev->master_msgs->addr, + i2c_dev->master_xfer_cnt, i2c_dev->master_msgs->len); +- ++ + dev_dbg(i2c_dev->dev, "ast_i2c_do_byte_xfer complete \n"); + i2c_dev->cmd_err = 0; +- complete(&i2c_dev->cmd_complete); +- ++ complete(&i2c_dev->cmd_complete); ++ + } + } +- ++ + } + + static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) +@@ -941,8 +973,8 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + u32 xfer_len; + int i; + u8 *rx_buf; +- +- dev_dbg(i2c_dev->dev, "ast_i2c_slave_xfer_done [%d]\n",i2c_dev->slave_xfer_mode); ++ ++ dev_dbg(i2c_dev->dev, "ast_i2c_slave_xfer_done [%d]\n",i2c_dev->slave_xfer_mode); + + if (i2c_dev->slave_msgs->flags & I2C_M_RD) { + //tx done , only check tx count ... +@@ -979,16 +1011,16 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); + if(xfer_len == 0) + xfer_len = AST_I2C_PAGE_SIZE; +- ++ + dev_dbg(i2c_dev->dev,"rx buff done len %d \n",xfer_len); +- ++ + rx_buf = (u8 *)i2c_dev->req_page->page_addr; +- ++ + for(i=0;i<xfer_len;i++) { + i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i] = rx_buf[i]; + dev_dbg(i2c_dev->dev,"%d, [%x] \n",i2c_dev->slave_xfer_cnt+i ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i]); + } +- ++ + } else { + //RX DMA DOWN + xfer_len = ast_i2c_read(i2c_dev, I2C_DMA_LEN_REG); +@@ -996,15 +1028,15 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + xfer_len = i2c_dev->slave_xfer_len; + else + xfer_len = i2c_dev->slave_xfer_len - xfer_len - 1; +- ++ + dev_dbg(i2c_dev->dev, " rx dma done len %d \n", xfer_len); +- ++ + for(i=0;i<xfer_len;i++) { + i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i] = i2c_dev->dma_buf[i]; + dev_dbg(i2c_dev->dev,"%d, [%x] \n",i2c_dev->slave_xfer_cnt+i ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt+i]); + } + } +- ++ + } + + if(xfer_len !=i2c_dev->slave_xfer_len) { +@@ -1012,7 +1044,7 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + printk(" **slave xfer error ====\n"); + //should goto stop.... + } else +- i2c_dev->slave_xfer_cnt += i2c_dev->slave_xfer_len; ++ i2c_dev->slave_xfer_cnt += i2c_dev->slave_xfer_len; + + + if((i2c_dev->slave_event == I2C_SLAVE_EVENT_NACK) || (i2c_dev->slave_event == I2C_SLAVE_EVENT_STOP)) { +@@ -1020,33 +1052,33 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) + ast_i2c_slave_rdwr_xfer(i2c_dev); + #else + i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); +-#endif ++#endif + i2c_dev->slave_xfer_cnt = 0; + } else { + if(i2c_dev->slave_xfer_cnt == i2c_dev->slave_msgs->len) { +- dev_dbg(i2c_dev->dev,"slave next msgs \n"); ++ dev_dbg(i2c_dev->dev,"slave next msgs \n"); + #ifdef CONFIG_AST_I2C_SLAVE_RDWR + ast_i2c_slave_rdwr_xfer(i2c_dev); + #else + i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); +-#endif ++#endif + + i2c_dev->slave_xfer_cnt = 0; +- } ++ } + i2c_dev->do_slave_xfer(i2c_dev); + } + + + if(AST_I2CD_IDLE == i2c_dev->state) { +- dev_dbg(i2c_dev->dev,"** Slave go IDLE **\n"); ++ dev_dbg(i2c_dev->dev,"** Slave go IDLE **\n"); + i2c_dev->slave_operation = 0; +- ++ + if(i2c_dev->slave_xfer_mode == BUFF_XFER) { + i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page); +- } +- +- } +- ++ } ++ ++ } ++ + } + + //TX/Rx Done +@@ -1057,7 +1089,7 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + u8 *pool_buf; + unsigned long flags; + +- spin_lock_irqsave(&g_master_lock, flags); ++ spin_lock_irqsave(&i2c_dev->master_lock, flags); + + /* + * This function shall be involked during interrupt handling. +@@ -1068,8 +1100,8 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + goto unlock_out; + } + +- dev_dbg(i2c_dev->dev, "ast_i2c_master_xfer_done mode[%d]\n",i2c_dev->master_xfer_mode); +- ++ dev_dbg(i2c_dev->dev, "ast_i2c_master_xfer_done mode[%d]\n",i2c_dev->master_xfer_mode); ++ + if (i2c_dev->master_msgs->flags & I2C_M_RD) { + if(i2c_dev->master_xfer_cnt == -1) { + xfer_len = 1; +@@ -1077,16 +1109,16 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + } + if(i2c_dev->master_xfer_mode == BYTE_XFER) { + if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { +- i2c_dev->master_msgs->len += (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; ++ i2c_dev->master_msgs->len += (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; + i2c_dev->blk_r_flag = 1; +- dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); ++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); + } + xfer_len = 1; + i2c_dev->master_msgs->buf[i2c_dev->master_xfer_cnt] = (ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) & AST_I2CD_RX_BYTE_BUFFER) >> 8; + } else if (i2c_dev->master_xfer_mode == BUFF_XFER) { + pool_buf = (u8 *)i2c_dev->req_page->page_addr; + xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); +- ++ + if(xfer_len == 0) + xfer_len = AST_I2C_PAGE_SIZE; + +@@ -1098,7 +1130,7 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { + i2c_dev->master_msgs->len += pool_buf[0]; + i2c_dev->blk_r_flag = 1; +- dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); ++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); + } + } else { + //DMA Mode +@@ -1114,13 +1146,13 @@ static void ast_i2c_master_xfer_done(struct ast_i2c_dev *i2c_dev) + dev_dbg(i2c_dev->dev, "buf[%x] \n", i2c_dev->dma_buf[i]); + dev_dbg(i2c_dev->dev, "buf[%x] \n", i2c_dev->dma_buf[i+1]); + } +- ++ + if ((i2c_dev->master_msgs->flags & I2C_M_RECV_LEN) && (i2c_dev->blk_r_flag == 0)) { + i2c_dev->master_msgs->len += i2c_dev->dma_buf[0]; + i2c_dev->blk_r_flag = 1; +- dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); ++ dev_dbg(i2c_dev->dev, "I2C_M_RECV_LEN %d \n", i2c_dev->master_msgs->len -1); + } +- ++ + } + + }else { +@@ -1153,28 +1185,28 @@ next_xfer: + i2c_dev->cmd_err = 1; + goto done_out; + } else +- i2c_dev->master_xfer_cnt += i2c_dev->master_xfer_len; ++ i2c_dev->master_xfer_cnt += i2c_dev->master_xfer_len; + + if(i2c_dev->master_xfer_cnt != i2c_dev->master_msgs->len) { + dev_dbg(i2c_dev->dev,"do next cnt \n"); + i2c_dev->do_master_xfer(i2c_dev); + } else { +-#if 0 +- int i; ++#if 0 ++ int i; + printk(" ===== \n"); + for(i=0;i<i2c_dev->master_msgs->len;i++) + printk("rx buf i,[%x]\n",i,i2c_dev->master_msgs->buf[i]); +- printk(" ===== \n"); +-#endif ++ printk(" ===== \n"); ++#endif + i2c_dev->cmd_err = 0; + + done_out: + dev_dbg(i2c_dev->dev,"msgs complete \n"); +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + } + + unlock_out: +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + } + + static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) +@@ -1187,7 +1219,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + i2c_dev->slave_msgs->buf[0] = match; + dev_dbg(i2c_dev->dev, "S Start Addr match [%x] \n",match); + +- ++ + if(match & 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_START_READ; + } else { +@@ -1201,7 +1233,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + #else + i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); + i2c_dev->slave_xfer_cnt = 0; +-#endif ++#endif + + //request + if(i2c_dev->ast_i2c_data->slave_dma == BYTE_MODE) +@@ -1211,7 +1243,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + else { + if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) + i2c_dev->do_slave_xfer = ast_i2c_do_pool_xfer; +- else ++ else + i2c_dev->do_slave_xfer = ast_i2c_do_byte_xfer; + } + +@@ -1221,7 +1253,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) + + static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + { +- u32 sts; ++ u32 sts; + + struct ast_i2c_dev *i2c_dev = dev_id; + u32 isr_sts = readl(i2c_dev->ast_i2c_data->reg_gr); +@@ -1231,7 +1263,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + + i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; + sts = ast_i2c_read(i2c_dev,I2C_INTR_STS_REG); +-// printk("ISR : %x , sts [%x]\n",sts , xfer_sts); ++// printk("ISR : %x , sts [%x]\n",sts , xfer_sts); + // dev_dbg(i2c_dev->dev,"ISR : %x , sts [%x]\n",sts , xfer_sts); + + // dev_dbg(i2c_dev->dev,"sts machine %x, slave_op %d \n", xfer_sts,i2c_dev->slave_operation); +@@ -1244,9 +1276,9 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + I2C_INTR_CTRL_REG); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SMBUS_ALT, I2C_INTR_STS_REG); + ast_master_alert_recv(i2c_dev); +- sts &= ~AST_I2CD_SMBUS_ALT_INTR_EN; ++ sts &= ~AST_I2CD_SMBUS_ALT_INTR_EN; + } +- ++ + if(AST_I2CD_INTR_STS_ABNORMAL & sts) { + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ABNORMAL; + // Turn off interrupts for further abnormal +@@ -1257,6 +1289,8 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + I2C_INTR_CTRL_REG); + complete(&i2c_dev->cmd_complete); + sts &= ~AST_I2CD_INTR_STS_ABNORMAL; ++ // Need to clear the interrupt ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ABNORMAL, I2C_INTR_STS_REG); + } + + switch(sts) { +@@ -1265,7 +1299,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + i2c_dev->slave_event = I2C_SLAVE_EVENT_READ; + ast_i2c_slave_xfer_done(i2c_dev); + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_ACK = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); +@@ -1280,9 +1314,17 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_master_xfer_done(i2c_dev); +- ++ + } else { +- printk("TODO ...\n"); ++ printk("ast_i2c: TX_ACK | NORMAL_STOP; xfer_last %d\n", i2c_dev->xfer_last); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ uint32_t new_val = ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | ++ AST_I2CD_NORMAL_STOP_INTR_EN | ++ AST_I2CD_TX_ACK_INTR_EN; ++ ast_i2c_write(i2c_dev, new_val, I2C_INTR_CTRL_REG); ++ //take care ++ i2c_dev->cmd_err |= AST_LOCKUP_DETECTED; ++ complete(&i2c_dev->cmd_complete); + } + break; + +@@ -1291,8 +1333,8 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; + ast_i2c_slave_xfer_done(i2c_dev); + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); +- ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); ++ + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); +@@ -1310,7 +1352,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP: + if(i2c_dev->slave_operation == 1) { + printk("SLAVE TODO .... \n"); +- ++ + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK| AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); +@@ -1320,47 +1362,47 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + } + break; + +- //Issue : Workaround for I2C slave mode ++ //Issue : Workaround for I2C slave mode + case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH: + if(i2c_dev->slave_operation == 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; + ast_i2c_slave_xfer_done(i2c_dev); + ast_i2c_slave_addr_match(i2c_dev); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); + } else { + printk("ERROR !!!!\n"); + } + break; + case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH: + ast_i2c_slave_addr_match(i2c_dev); +- dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts); ++ dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); + break; +- ++ + case AST_I2CD_INTR_STS_RX_DOWN: + if(i2c_dev->slave_operation == 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_WRITE; + ast_i2c_slave_xfer_done(i2c_dev); + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); + } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); + ast_i2c_master_xfer_done(i2c_dev); +- ++ + } + break; +- ++ + case AST_I2CD_INTR_STS_NORMAL_STOP: + if(i2c_dev->slave_operation == 1) { + i2c_dev->slave_event = I2C_SLAVE_EVENT_STOP; + ast_i2c_slave_xfer_done(i2c_dev); + dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + dev_dbg(i2c_dev->dev, "state [%x] \n",i2c_dev->state); +- } else { ++ } else { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); +- ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); ++ ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_NORMAL_STOP; + complete(&i2c_dev->cmd_complete); + } +@@ -1380,24 +1422,24 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + break; + case AST_I2CD_INTR_STS_SCL_TO: + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SCL_TO; +- complete(&i2c_dev->cmd_complete); +- ++ complete(&i2c_dev->cmd_complete); ++ + break; + case AST_I2CD_INTR_STS_GCALL_ADDR: + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_GCALL_ADDR; +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + + break; + case AST_I2CD_INTR_STS_SMBUS_DEF_ADDR: + break; + case AST_I2CD_INTR_STS_SMBUS_DEV_ALT: +- ++ + break; +- ++ + case AST_I2CD_INTR_STS_SMBUS_ARP_ADDR: + break; + case AST_I2CD_INTR_STS_SDA_DL_TO: +@@ -1405,25 +1447,50 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) + case AST_I2CD_INTR_STS_BUS_RECOVER: + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_BUS_RECOVER= %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_BUS_RECOVER, I2C_INTR_STS_REG); +- complete(&i2c_dev->cmd_complete); ++ complete(&i2c_dev->cmd_complete); + break; + default: +- if(sts) +- printk("GR %x : No one care : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); +- return IRQ_NONE; ++ //TODO: Clearing this interrupt for now, but needs to cleanup this ISR function ++ ast_i2c_write(i2c_dev, sts, I2C_INTR_STS_REG); ++ ++ // Handle Arbitration Loss ++ if (sts & AST_I2CD_INTR_STS_ARBIT_LOSS) { ++ i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; ++ complete(&i2c_dev->cmd_complete); ++ sts &= (~AST_I2CD_INTR_STS_ARBIT_LOSS); ++ } ++ ++ // Handle the write transaction ACK ++ if (sts & AST_I2CD_INTR_STS_TX_ACK) { ++ ast_i2c_master_xfer_done(i2c_dev); ++ complete(&i2c_dev->cmd_complete); ++ sts &= (~AST_I2CD_INTR_STS_TX_ACK); ++ } ++ ++ // Handle the Slave address match ++ if (sts & AST_I2CD_INTR_STS_SLAVE_MATCH) { ++ ast_i2c_slave_addr_match(i2c_dev); ++ sts &= (~AST_I2CD_INTR_STS_SLAVE_MATCH); ++ } ++ ++ // TODO: Debug print for any unhandled condition ++ if(sts) { ++ printk("GR %x : Status : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); ++ } ++ ++ return IRQ_HANDLED; + } + + return IRQ_HANDLED; +- + } + + static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msgs, int num) + { + int i; +- int ret = 1; ++ int ret = 1; + unsigned long flags; + +- spin_lock_irqsave(&g_master_lock, flags); ++ spin_lock_irqsave(&i2c_dev->master_lock, flags); + + //request + if(i2c_dev->ast_i2c_data->master_dma == BYTE_MODE) +@@ -1433,7 +1500,7 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg + else { + if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) + i2c_dev->do_master_xfer = ast_i2c_do_pool_xfer; +- else ++ else + i2c_dev->do_master_xfer = ast_i2c_do_byte_xfer; + } + +@@ -1458,12 +1525,12 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg + + i2c_dev->do_master_xfer(i2c_dev); + +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + + ret = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, + i2c_dev->adap.timeout*HZ); +- +- spin_lock_irqsave(&g_master_lock, flags); ++ ++ spin_lock_irqsave(&i2c_dev->master_lock, flags); + i2c_dev->master_msgs = NULL; + + if (ret == 0) { +@@ -1471,25 +1538,30 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg + i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; + // printk("sts [%x], isr sts [%x] \n",i2c_dev->state, ast_i2c_read(i2c_dev,I2C_INTR_STS_REG)); + ret = -ETIMEDOUT; +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + goto stop; + } +- ++ + if(i2c_dev->cmd_err != 0 && + i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { ++ if (i2c_dev->cmd_err & AST_LOCKUP_DETECTED) { ++ printk("ast-i2c: error got unexpected STOP\n"); ++ // reset the bus ++ ast_i2c_bus_error_recover(i2c_dev); ++ } + ret = -EAGAIN; +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + goto stop; + } + } + +- spin_unlock_irqrestore(&g_master_lock, flags); ++ spin_unlock_irqrestore(&i2c_dev->master_lock, flags); + + if(i2c_dev->cmd_err == 0 || + i2c_dev->cmd_err == AST_I2CD_INTR_STS_NORMAL_STOP) { + ret = num; + goto out; +- ++ + } + stop: + init_completion(&i2c_dev->cmd_complete); +@@ -1503,8 +1575,8 @@ out: + //Free .. + if(i2c_dev->master_xfer_mode == BUFF_XFER) { + i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page); +- +- } ++ ++ } + dev_dbg(i2c_dev->dev, "end xfer ret = %d, xfer mode[%d]\n",ret, i2c_dev->master_xfer_mode); + return ret; + +@@ -1521,7 +1593,7 @@ static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + /* + * Wait for the bus to become free. + */ +- ++ + ret = ast_i2c_wait_bus_not_busy(i2c_dev); + if (ret) { + dev_err(&i2c_dev->adap.dev, "i2c_ast: timeout waiting for bus free\n"); +@@ -1536,7 +1608,7 @@ static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + dev_dbg(&adap->dev, "Retrying transmission [%d]\n",i); + udelay(100); + } +- ++ + ret = -EREMOTEIO; + out: + +@@ -1550,9 +1622,9 @@ static u32 ast_i2c_functionality(struct i2c_adapter *adap) + + static const struct i2c_algorithm i2c_ast_algorithm = { + .master_xfer = ast_i2c_xfer, +-#ifdef CONFIG_AST_I2C_SLAVE_RDWR ++#ifdef CONFIG_AST_I2C_SLAVE_RDWR + .slave_xfer = ast_i2c_slave_xfer, +-#endif ++#endif + .functionality = ast_i2c_functionality, + }; + +@@ -1572,23 +1644,23 @@ static int ast_i2c_probe(struct platform_device *pdev) + + i2c_dev->ast_i2c_data = pdev->dev.platform_data; + if(i2c_dev->ast_i2c_data->master_dma == BUFF_MODE) { +- dev_dbg(&pdev->dev, "use buffer pool mode 256\n"); +- ++ dev_dbg(&pdev->dev, "use buffer pool mode 256\n"); ++ + } else if ((i2c_dev->ast_i2c_data->master_dma == DMA_MODE) || (i2c_dev->ast_i2c_data->slave_dma == DMA_MODE)) { +- dev_dbg(&pdev->dev, "use dma mode \n"); ++ dev_dbg(&pdev->dev, "use dma mode \n"); + if (!i2c_dev->dma_buf) { + i2c_dev->dma_buf = dma_alloc_coherent(NULL, AST_I2C_DMA_SIZE, &i2c_dev->dma_addr, GFP_KERNEL); + if (!i2c_dev->dma_buf) { + printk("unable to allocate tx Buffer memory\n"); + ret = -ENOMEM; +- goto err_no_dma; ++ goto err_no_dma; + } + if(i2c_dev->dma_addr%4 !=0) { + printk("not 4 byte boundary \n"); + ret = -ENOMEM; +- goto err_no_dma; +- } +-// printk("dma_buf = [0x%x] dma_addr = [0x%x], please check 4byte boundary \n",i2c_dev->dma_buf,i2c_dev->dma_addr); ++ goto err_no_dma; ++ } ++// printk("dma_buf = [0x%x] dma_addr = [0x%x], please check 4byte boundary \n",i2c_dev->dma_buf,i2c_dev->dma_addr); + memset (i2c_dev->dma_buf, 0, AST_I2C_DMA_SIZE); + } + +@@ -1596,7 +1668,7 @@ static int ast_i2c_probe(struct platform_device *pdev) + //master_mode 0: use byte mode + dev_dbg(&pdev->dev, "use default byte mode \n"); + } +- ++ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (NULL == res) { + dev_err(&pdev->dev, "cannot get IORESOURCE_MEM\n"); +@@ -1628,11 +1700,11 @@ static int ast_i2c_probe(struct platform_device *pdev) + if(i2c_dev->irq == IRQ_C0_I2C) { + i2c_dev->bus_id = pdev->id - NUM_BUS; + dev_dbg(&pdev->dev, "C0 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); +-#if (CONFIG_AST1070_NR >= 2) ++#if (CONFIG_AST1070_NR >= 2) + } else if(i2c_dev->irq == IRQ_C1_I2C) { + i2c_dev->bus_id = pdev->id - (NUM_BUS + 8); +- dev_dbg(&pdev->dev, "C1 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); +-#endif ++ dev_dbg(&pdev->dev, "C1 :: pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); ++#endif + } else { + i2c_dev->bus_id = pdev->id; + dev_dbg(&pdev->dev, "AST pdev->id %d , i2c_dev->bus_id = %d, i2c_dev->irq =%d\n",pdev->id, i2c_dev->bus_id,i2c_dev->irq); +@@ -1644,13 +1716,13 @@ static int ast_i2c_probe(struct platform_device *pdev) + /* Initialize the I2C adapter */ + i2c_dev->adap.owner = THIS_MODULE; + //TODO +- i2c_dev->adap.retries = 0; ++ i2c_dev->adap.retries = 0; + +-// i2c_dev->adap.retries = 3; ++// i2c_dev->adap.retries = 3; + +- i2c_dev->adap.timeout = 5; ++ i2c_dev->adap.timeout = 5; + +- i2c_dev->master_xfer_mode = BYTE_XFER; ++ i2c_dev->master_xfer_mode = BYTE_XFER; + + /* + * If "pdev->id" is negative we consider it as zero. +@@ -1662,7 +1734,7 @@ static int ast_i2c_probe(struct platform_device *pdev) + i2c_dev->adap.nr); + + i2c_dev->slave_operation = 0; +- i2c_dev->blk_r_flag = 0; ++ i2c_dev->blk_r_flag = 0; + i2c_dev->adap.algo = &i2c_ast_algorithm; + + ast_i2c_dev_init(i2c_dev); +@@ -1674,8 +1746,11 @@ static int ast_i2c_probe(struct platform_device *pdev) + goto ereqirq; + } + ++ spin_lock_init(&i2c_dev->master_lock); ++ + #ifdef CONFIG_AST_I2C_SLAVE_RDWR + ast_i2c_slave_buff_init(i2c_dev); ++ spin_lock_init(&i2c_dev->slave_rx_lock); + #endif + + i2c_dev->adap.algo_data = i2c_dev; +@@ -1718,7 +1793,7 @@ static int ast_i2c_remove(struct platform_device *pdev) + + platform_set_drvdata(pdev, NULL); + i2c_del_adapter(&i2c_dev->adap); +- ++ + free_irq(i2c_dev->irq, i2c_dev); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +@@ -1742,7 +1817,7 @@ static int ast_i2c_resume(struct platform_device *pdev) + { + //TODO + // struct ast_i2c_dev *i2c_dev = platform_get_drvdata(pdev); +- //Should reset i2c ??? ++ //Should reset i2c ??? + return 0; + } + #else +diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c +index c8e3cf6..06d9042 100644 +--- a/drivers/i2c/i2c-core.c ++++ b/drivers/i2c/i2c-core.c +@@ -1064,7 +1064,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) + EXPORT_SYMBOL(i2c_transfer); + + #ifdef CONFIG_AST_I2C_SLAVE_RDWR +-int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs) ++int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + { + unsigned long orig_jiffies; + int ret, try; +@@ -1075,9 +1075,18 @@ int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs) + "len=%d\n", (msgs->flags & I2C_S_RD) + ? 'R' : 'W', msgs->addr, msgs->len); + #endif +- i2c_lock_adapter(adap); ++ if (in_atomic() || irqs_disabled()) { ++ ret = mutex_trylock(&adap->bus_lock); ++ if (!ret) ++ /* I2C activity is ongoing. */ ++ return -EAGAIN; ++ } else { ++ mutex_lock_nested(&adap->bus_lock, adap->level); ++ } ++ + ret = adap->algo->slave_xfer(adap, msgs); +- i2c_unlock_adapter(adap); ++ ++ mutex_unlock(&adap->bus_lock); + + return ret; + } else { +diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c +index 07f393d..82f2c7c 100644 +--- a/drivers/i2c/i2c-dev.c ++++ b/drivers/i2c/i2c-dev.c +@@ -38,7 +38,7 @@ + #include <asm/uaccess.h> + + #ifdef CONFIG_AST_I2C_SLAVE_RDWR +-#include <asm/arch/ast_i2c.h> ++#include <plat/ast_i2c.h> + #endif + + static struct i2c_driver i2cdev_driver; +@@ -310,6 +310,113 @@ static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, + return res; + } + ++static noinline int i2cdev_ioctl_slave_rdrw(struct i2c_client *client, ++ unsigned long arg) ++{ ++ struct i2c_rdwr_ioctl_data rdwr_arg; ++ struct i2c_msg *rdwr_pa; ++ u8 __user **data_ptrs; ++ int i, res; ++ ++ if (copy_from_user(&rdwr_arg, ++ (struct i2c_rdwr_ioctl_data __user *)arg, ++ sizeof(rdwr_arg))) ++ return -EFAULT; ++ ++ /* Put an arbitrary limit on the number of messages that can ++ * be sent at once */ ++ if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) ++ return -EINVAL; ++ ++ rdwr_pa = (struct i2c_msg *) ++ kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), ++ GFP_KERNEL); ++ if (!rdwr_pa) ++ return -ENOMEM; ++ ++ if (copy_from_user(rdwr_pa, rdwr_arg.msgs, ++ rdwr_arg.nmsgs * sizeof(struct i2c_msg))) { ++ kfree(rdwr_pa); ++ return -EFAULT; ++ } ++ ++ data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); ++ if (data_ptrs == NULL) { ++ kfree(rdwr_pa); ++ return -ENOMEM; ++ } ++ ++ res = 0; ++ for (i = 0; i < rdwr_arg.nmsgs; i++) { ++ /* Limit the size of the message to a sane amount; ++ * and don't let length change either. */ ++ if (rdwr_pa[i].len > 8192) { ++ res = -EINVAL; ++ break; ++ } ++ data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; ++ rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL); ++ if (rdwr_pa[i].buf == NULL) { ++ res = -ENOMEM; ++ break; ++ } ++ if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i], ++ rdwr_pa[i].len)) { ++ ++i; /* Needs to be kfreed too */ ++ res = -EFAULT; ++ break; ++ } ++ ++ /* From Linux 3.5: */ ++ /* ++ * If the message length is received from the slave (similar ++ * to SMBus block read), we must ensure that the buffer will ++ * be large enough to cope with a message length of ++ * I2C_SMBUS_BLOCK_MAX as this is the maximum underlying bus ++ * drivers allow. The first byte in the buffer must be ++ * pre-filled with the number of extra bytes, which must be ++ * at least one to hold the message length, but can be ++ * greater (for example to account for a checksum byte at ++ * the end of the message.) ++ */ ++ if (rdwr_pa[i].flags & I2C_M_RECV_LEN) { ++ if (!(rdwr_pa[i].flags & I2C_M_RD) || ++ rdwr_pa[i].buf[0] < 1 || ++ rdwr_pa[i].len < rdwr_pa[i].buf[0] + ++ I2C_SMBUS_BLOCK_MAX) { ++ res = -EINVAL; ++ break; ++ } ++ ++ rdwr_pa[i].len = rdwr_pa[i].buf[0]; ++ } ++ ++ } ++ if (res < 0) { ++ int j; ++ for (j = 0; j < i; ++j) ++ kfree(rdwr_pa[j].buf); ++ kfree(data_ptrs); ++ kfree(rdwr_pa); ++ return res; ++ } ++ ++ res = i2c_slave_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs); ++ while (i-- > 0) { ++ if (res >= 0 ) { ++ if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, ++ rdwr_pa[i].len)) ++ res = -EFAULT; ++ ++ rdwr_arg.msgs[i].len = rdwr_pa[i].len; ++ } ++ kfree(rdwr_pa[i].buf); ++ } ++ kfree(data_ptrs); ++ kfree(rdwr_pa); ++ return res; ++} ++ + static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, + unsigned long arg) + { +@@ -448,8 +555,8 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + + #ifdef CONFIG_AST_I2C_SLAVE_RDWR + case I2C_SLAVE_RDWR: +- return i2cdev_ioctl_slave_rdrw(client->adapter, (struct i2c_msg __user *)arg); +-#endif ++ return i2cdev_ioctl_slave_rdrw(client, arg); ++#endif + + case I2C_SMBUS: + return i2cdev_ioctl_smbus(client, arg); +diff --git a/drivers/net/ftgmac100_26.c b/drivers/net/ftgmac100_26.c +index fdc77fc..3a5d796 100644 +--- a/drivers/net/ftgmac100_26.c ++++ b/drivers/net/ftgmac100_26.c +@@ -1,16 +1,16 @@ + /******************************************************************************** + * File Name : ftgmac100_26.c +-* ++* + * Copyright (C) 2012-2020 ASPEED Technology 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. +-* You should have received a copy of the GNU General Public License +-* along with this program; if not, write to the Free Software +-* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++* 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. ++* You should have received a copy of the GNU General Public License ++* along with this program; if not, write to the Free Software ++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + ********************************************************************************/ + //----------------------------------------------------------------------------- + // "ASPEED MAC Driver, (Linux Kernel 2.6.15.7) 10/02/07 - by ASPEED\n" +@@ -76,7 +76,7 @@ + //AST2300 SDK 0.14 + //19.09/13/2010 - by river@aspeed + // Support Realtek RTL8201EL 10/100M PHY +-//AST2400 ++//AST2400 + //20.06/25/2013 - by CC@aspeed + // Support BCM54612E 10/100/1000M PHY + //----------------------------------------------------------------------------- +@@ -120,7 +120,12 @@ + #err "Not define include for GMAC" + #endif + ++#ifdef CONFIG_WEDGE100 ++#define PHY_DEFAULT_ADDR 0x18 ++#else ++/* wedge */ + #define PHY_DEFAULT_ADDR 0x1F ++#endif + + /*------------------------------------------------------------------------ + . +@@ -172,7 +177,6 @@ static int ftgmac100_wait_to_send_packet(struct sk_buff * skb, struct net_device + + static volatile int trans_busy = 0; + +- + void ftgmac100_phy_rw_waiting(unsigned int ioaddr) + { + unsigned int tmp; +@@ -255,6 +259,7 @@ static void getMacHwConfig( struct net_device* dev, struct AstMacHwConfig* out ) + + // out->macId = dev->dev_id; + //.. getMacAndPhy(dev, out); ++ out->phyAddr = PHY_DEFAULT_ADDR; + out->miiPhyId = 0; + + // We assume the Clock Stop register does not disable the MAC1 or MAC2 clock +@@ -272,7 +277,7 @@ no_phy_access: + out->phyAddr = 1; + } + #if 0 +- if (out->miiPhyId == 0x0362) { ++ if (out->miiPhyId == 0x0362) { + out->phyAddr = 1; + } + #endif +@@ -297,6 +302,902 @@ no_phy_access: + return; + } + ++// -------------------------------------------------------------------- ++// NCSI function ++// -------------------------------------------------------------------- ++void NCSI_Struct_Initialize(struct net_device *dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long i; ++ ++ for (i = 0; i < 6; i++) { ++ lp->NCSI_Request.DA[i] = 0xFF; ++ lp->NCSI_Respond.DA[i] = 0xFF; ++ lp->NCSI_Respond.SA[i] = 0xFF; ++ lp->NCSI_Request.SA[i] = dev->dev_addr[i]; ++ } ++ lp->NCSI_Request.EtherType = 0xF888; ++ lp->NCSI_Request.MC_ID = 0; ++ lp->NCSI_Request.Header_Revision = 0x01; ++ lp->NCSI_Request.Reserved_1 = 0; ++ lp->NCSI_Request.Reserved_2 = 0; ++ lp->NCSI_Request.Reserved_3 = 0; ++ lp->NCSI_Respond.EtherType = 0xF888; ++ lp->NCSI_Respond.MC_ID = 0; ++ lp->NCSI_Respond.Header_Revision = 0x01; ++ lp->NCSI_Respond.Reserved_1 = 0; ++ lp->NCSI_Respond.Reserved_2 = 0; ++ lp->NCSI_Respond.Reserved_3 = 0; ++ ++ lp->InstanceID = 0; ++ lp->Payload_Checksum = 0; ++ for (i = 0; i < 4; i++) { ++ lp->Payload_Pad[i] = 0; ++ } ++ for (i = 0; i < 64; i++) { ++ lp->Payload_Data[i] = 0; ++ } ++} ++ ++void Calculate_Checksum(struct net_device * dev, unsigned char *buffer_base, int Length) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned int i, CheckSum = 0; ++ unsigned int Data, Data1; ++ ++ for (i = 0; i < ((Length - 14) / 2); i++) { ++ Data = buffer_base[i * 2]; ++ Data1 = buffer_base[i * 2 + 1]; ++ CheckSum += ((Data << 8) + Data1); ++ } ++ lp->Payload_Checksum = (~(CheckSum) + 1); //2's complement ++//Inverse for insert into buffer ++ Data = (lp->Payload_Checksum & 0xFF000000) >> 24; ++ Data1 = (lp->Payload_Checksum & 0x000000FF) << 24; ++ lp->Payload_Checksum = (lp->Payload_Checksum & 0x00FFFF00) + Data + Data1; ++ Data = (lp->Payload_Checksum & 0x00FF0000) >> 8; ++ Data1 = (lp->Payload_Checksum & 0x0000FF00) << 8; ++ lp->Payload_Checksum = (lp->Payload_Checksum & 0xFF0000FF) + Data + Data1; ++} ++ ++void copy_data (struct net_device * dev, struct sk_buff * skb, int Length) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ ++ memcpy ((unsigned char *)(skb->data + 30), &lp->Payload_Data, Length); ++ Calculate_Checksum(dev, skb->data + 14, 30 + Length); ++ memcpy ((unsigned char *)(skb->data + 30 + Length), &lp->Payload_Checksum, 4); ++} ++ ++void NCSI_Rx (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long status, length, i = 0; ++ volatile RX_DESC *cur_desc; ++ ++ncsi_rx: ++ i = 0; ++ cur_desc = &lp->rx_descs[lp->rx_idx]; ++ do { ++ status = cur_desc->RXPKT_RDY; ++ i++; ++ } while (!(((status & RX_OWNBY_SOFTWARE) != 0) || (i >= NCSI_LOOP))); ++ ++ if (i < NCSI_LOOP) { ++ if (cur_desc->LRS) { ++ length = cur_desc->VDBC; ++ unsigned char *tbuf = (unsigned char *)phys_to_virt(cur_desc->RXBUF_BADR); ++ if (length <= 128 && tbuf[12] == 0x88 && tbuf[13] == 0xF8) { ++ memcpy (&lp->NCSI_Respond, (unsigned char *)phys_to_virt(cur_desc->RXBUF_BADR), length); ++ } else { ++ printk("NCSI_RX: Skip len: %d, proto: %x:%x\n", length, tbuf[12], tbuf[13]); ++ lp->rx_descs[lp->rx_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100; ++ lp->rx_idx = (lp->rx_idx+1)%RXDES_NUM; ++ goto ncsi_rx; ++ } ++ ++ } ++ lp->rx_descs[lp->rx_idx].RXPKT_RDY = RX_OWNBY_FTGMAC100; ++ lp->rx_idx = (lp->rx_idx+1)%RXDES_NUM; ++ } else { ++ printk("NCSI_Rx: Failed\n"); ++ } ++} ++ ++void DeSelect_Package (struct net_device * dev, int Package_ID) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DESELECT_PACKAGE; ++ Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++int Select_Package (struct net_device * dev, int Package_ID) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, Found = 0; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = SELECT_PACKAGE; ++ Combined_Channel_ID = (Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (4 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 4; ++ memset ((void *)lp->Payload_Data, 0, 4); ++ lp->Payload_Data[3] = 1; //Arbitration Disable ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ Found = 0; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ Found = 1; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ ++ return Found; ++} ++ ++ ++void DeSelect_Active_Package (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DESELECT_PACKAGE; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F, 0x1F means all channel ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DESELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++ ++int Select_Active_Package (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, Found = 0; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = SELECT_PACKAGE; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + 0x1F; //Internal Channel ID = 0x1F ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (4 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 4; ++ memset ((void *)lp->Payload_Data, 0, 4); ++ lp->Payload_Data[3] = 1; //Arbitration Disable ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SELECT_PACKAGE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ Found = 0; ++ } ++ else { ++ lp->Retry = 0; ++ Found = 1; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ ++ return Found; ++} ++ ++int Clear_Initial_State (struct net_device * dev, int Channel_ID) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, Found = 0; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = CLEAR_INITIAL_STATE; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + Channel_ID; //Internal Channel ID = 0 ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (CLEAR_INITIAL_STATE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ Found = 0; ++ } ++ else { ++ lp->Retry = 0; ++ Found = 1; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ ++ return Found; ++} ++ ++void Get_Version_ID (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = GET_VERSION_ID; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_VERSION_ID | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Get_Capabilities (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = GET_CAPABILITIES; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_CAPABILITIES | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ lp->NCSI_Cap.Capabilities_Flags = lp->NCSI_Respond.Payload_Data[0]; ++ lp->NCSI_Cap.Broadcast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[1]; ++ lp->NCSI_Cap.Multicast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[2]; ++ lp->NCSI_Cap.Buffering_Capabilities = lp->NCSI_Respond.Payload_Data[3]; ++ lp->NCSI_Cap.AEN_Control_Support = lp->NCSI_Respond.Payload_Data[4]; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_AEN (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = AEN_ENABLE; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (8 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 8; ++ lp->Payload_Data[3] = 0; //MC ID ++ lp->Payload_Data[7] = 1; //Link Status Change AEN ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (AEN_ENABLE | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Get_MAC_Address (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, i; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = 0x50; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (8 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 8; ++ lp->Payload_Data[0] = 0x00; ++ lp->Payload_Data[1] = 0x00; ++ lp->Payload_Data[2] = 0x81; ++ lp->Payload_Data[3] = 0x19; ++ ++ lp->Payload_Data[4] = 0x00; ++ lp->Payload_Data[5] = 0x00; ++ lp->Payload_Data[6] = 0x1B; ++ lp->Payload_Data[7] = 0x00; ++ ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (0x50 | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ ++ // Update MAC Address ++printk("NCSI: MAC "); ++for (i = 0; i < 6; i++) ++ printk("%02X:", lp->NCSI_Respond.Payload_Data[12+i]); ++printk("\n"); ++ memcpy(lp->NCSI_Request.SA, &lp->NCSI_Respond.Payload_Data[12], 6); ++ memcpy(dev->dev_addr, &lp->NCSI_Respond.Payload_Data[12], 6); ++ ++ /* Update the MAC address */ ++ ast_gmac_set_mac(lp, dev->dev_addr); ++} ++ ++void Set_MAC_Affinity (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, i; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = 0x50; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (60 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ ++ lp->NCSI_Request.Payload_Length = 60; ++ memset(lp->Payload_Data, 0x00, 60); ++ lp->Payload_Data[0] = 0x00; ++ lp->Payload_Data[1] = 0x00; ++ lp->Payload_Data[2] = 0x81; ++ lp->Payload_Data[3] = 0x19; ++ ++ lp->Payload_Data[4] = 0x00; ++ lp->Payload_Data[5] = 0x01; ++ lp->Payload_Data[6] = 0x07; ++ lp->Payload_Data[7] = 0x00; ++ ++ for (i = 0; i < 6; i++) { ++ lp->Payload_Data[8+i] = lp->NCSI_Request.SA[i]; ++ } ++ ++ lp->Payload_Data[14] = 0x09; ++ ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (0x50 | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_Set_MAC_Address (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID, i; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = SET_MAC_ADDRESS; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (8 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 8; ++ for (i = 0; i < 6; i++) { ++ lp->Payload_Data[i] = lp->NCSI_Request.SA[i]; ++ } ++ lp->Payload_Data[6] = 1; //MAC Address Num = 1 --> address filter 1, fixed in sample code ++ lp->Payload_Data[7] = UNICAST + 0 + ENABLE_MAC_ADDRESS_FILTER; //AT + Reserved + E ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SET_MAC_ADDRESS | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_Broadcast_Filter (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = ENABLE_BROADCAST_FILTERING; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (4 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 4; ++ memset ((void *)lp->Payload_Data, 0, 4); ++ lp->Payload_Data[3] = 0x1; //ARP, DHCP, NetBIOS ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (ENABLE_BROADCAST_FILTERING | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Disable_VLAN (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DISABLE_VLAN; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_VLAN | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Get_Parameters (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = GET_PARAMETERS; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_PARAMETERS | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++// printk ("Retry: Command = %x, Response_Code = %x, Resonpd.Command = %x, IID = %x, lp->InstanceID = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code, lp->NCSI_Respond.Command, lp->NCSI_Respond.IID, lp->InstanceID); ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ lp->NCSI_Cap.Capabilities_Flags = lp->NCSI_Respond.Payload_Data[0]; ++ lp->NCSI_Cap.Broadcast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[1]; ++ lp->NCSI_Cap.Multicast_Packet_Filter_Capabilities = lp->NCSI_Respond.Payload_Data[2]; ++ lp->NCSI_Cap.Buffering_Capabilities = lp->NCSI_Respond.Payload_Data[3]; ++ lp->NCSI_Cap.AEN_Control_Support = lp->NCSI_Respond.Payload_Data[4]; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_Network_TX (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = ENABLE_CHANNEL_NETWORK_TX; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (ENABLE_CHANNEL_NETWORK_TX | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Disable_Network_TX (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DISABLE_CHANNEL_NETWORK_TX; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + (lp->NCSI_Request.Payload_Length % 4) + 8; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_CHANNEL_NETWORK_TX | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Enable_Channel (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = ENABLE_CHANNEL; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (ENABLE_CHANNEL | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++void Disable_Channel (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = DISABLE_CHANNEL; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (4 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 4; ++ memset ((void *)lp->Payload_Data, 0, 4); ++ lp->Payload_Data[3] = 0x1; //ALD ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_CHANNEL | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} ++ ++int Get_Link_Status (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = GET_LINK_STATUS; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = 0; ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (GET_LINK_STATUS | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++ if (lp->NCSI_Respond.Payload_Data[3] & 0x40) { ++ return (lp->NCSI_Respond.Payload_Data[3] & 0x01); //Link Up or Not ++ } ++ else { ++ return 0; //Auto Negotiate did not finish ++ } ++} ++ ++void Set_Link (struct net_device * dev) ++{ ++ struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; ++ unsigned long Combined_Channel_ID; ++ struct sk_buff * skb; ++ ++ do { ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ memset(skb->data, 0, TX_BUF_SIZE + 16); ++//TX ++ lp->InstanceID++; ++ lp->NCSI_Request.IID = lp->InstanceID; ++ lp->NCSI_Request.Command = SET_LINK; ++ Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; ++ lp->NCSI_Request.Channel_ID = Combined_Channel_ID; ++ lp->NCSI_Request.Payload_Length = (8 << 8); ++ memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); ++ lp->NCSI_Request.Payload_Length = 8; ++ memset ((void *)lp->Payload_Data, 0, 8); ++ lp->Payload_Data[2] = 0x02; //full duplex ++ lp->Payload_Data[3] = 0x04; //100M, auto-disable ++ copy_data (dev, skb, lp->NCSI_Request.Payload_Length); ++ skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; ++ ftgmac100_wait_to_send_packet (skb, dev); ++//RX ++ NCSI_Rx(dev); ++ if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (SET_LINK | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { ++ printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); ++ printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); ++ lp->Retry++; ++ lp->InstanceID--; ++ } ++ else { ++ lp->Retry = 0; ++ } ++ } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); ++ lp->Retry = 0; ++} + + static void ftgmac100_reset( struct net_device* dev ) + { +@@ -308,64 +1209,71 @@ static void ftgmac100_reset( struct net_device* dev ) + PRINTK("%s:ftgmac100_reset, phyAddr=0x%x, miiPhyId=0x%04x_%04x\n", + dev->name, ids->phyAddr, (ids->miiPhyId >> 16), (ids->miiPhyId & 0xffff)); + +- if (ids->miiPhyId < 1) +- return; // Cannot access MAC registers +- +- // Check the link speed and duplex. +- // They are not valid until auto-neg is resolved, which is reg.1 bit[5], +- // or the link is up, which is reg.1 bit[2]. +- +- if (ids->phyAddr < 0xff) +- tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x1); +- else tmp = 0; +- +- if (0==(tmp & (1u<<5 | 1u<<2)) || ids->phyAddr >= 0xff) { +- // No PHY chip, or link has not negotiated. +- speed = PHY_SPEED_100M; +- duplex = 1; +- netif_carrier_off(dev); +- } +- else if (((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) { +- tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00); +- duplex = (tmp & 0x0100) ? 1 : 0; +- speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M; +- } +- else if (((ids->miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || +- ((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { +- // Use reg.17_0.bit[15:13] for {speed[1:0], duplex}. +- tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x11); +- duplex = (tmp & PHY_DUPLEX_mask)>>13; +- speed = (tmp & PHY_SPEED_mask)>>14; +- netif_carrier_on(dev); +- } +- else if (priv->ids.miiPhyId == PHYID_BCM54612E +- || priv->ids.miiPhyId == PHYID_BCM54616S) { +- // Get link status +- // First Switch shadow register selector +- ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000); +- tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C); +- if ( (tmp & 0x0080) == 0x0080 ) +- duplex = 0; +- else +- duplex = 1; +- +- switch(tmp & 0x0018) { +- case 0x0000: +- speed = PHY_SPEED_1G; break; +- case 0x0008: +- speed = PHY_SPEED_100M; break; +- case 0x0010: +- speed = PHY_SPEED_10M; break; +- default: +- speed = PHY_SPEED_100M; +- } ++ if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) { ++ ids->miiPhyId = 0xFFFF; ++ // NCSI mode always is 100M and full duplex ++ duplex = 1; ++ speed = PHY_SPEED_100M; ++ } else { ++ if (ids->miiPhyId < 1) ++ return; // Cannot access MAC registers ++ ++ // Check the link speed and duplex. ++ // They are not valid until auto-neg is resolved, which is reg.1 bit[5], ++ // or the link is up, which is reg.1 bit[2]. ++ ++ if (ids->phyAddr < 0xff) ++ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x1); ++ else tmp = 0; ++ ++ if (0==(tmp & (1u<<5 | 1u<<2)) || ids->phyAddr >= 0xff) { ++ // No PHY chip, or link has not negotiated. ++ speed = PHY_SPEED_100M; ++ duplex = 1; ++ netif_carrier_off(dev); + } +- else { +- // Assume Broadcom BCM5221. Use reg.18 bits [1:0] for {100Mb/s, fdx}. +- tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x18); +- duplex = (tmp & 0x0001); +- speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M; +- } ++ else if (((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL)) { ++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x00); ++ duplex = (tmp & 0x0100) ? 1 : 0; ++ speed = (tmp & 0x2000) ? PHY_SPEED_100M : PHY_SPEED_10M; ++ } ++ else if (((ids->miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || ++ ((ids->miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { ++ // Use reg.17_0.bit[15:13] for {speed[1:0], duplex}. ++ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x11); ++ duplex = (tmp & PHY_DUPLEX_mask)>>13; ++ speed = (tmp & PHY_SPEED_mask)>>14; ++ netif_carrier_on(dev); ++ } ++ else if (priv->ids.miiPhyId == PHYID_BCM54612E ++ || priv->ids.miiPhyId == PHYID_BCM54616S) { ++ // Get link status ++ // First Switch shadow register selector ++ ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000); ++ tmp = ftgmac100_read_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C); ++ if ( (tmp & 0x0080) == 0x0080 ) ++ duplex = 0; ++ else ++ duplex = 1; ++ ++ switch(tmp & 0x0018) { ++ case 0x0000: ++ speed = PHY_SPEED_1G; break; ++ case 0x0008: ++ speed = PHY_SPEED_100M; break; ++ case 0x0010: ++ speed = PHY_SPEED_10M; break; ++ default: ++ speed = PHY_SPEED_100M; ++ } ++ } ++ else { ++ // Assume Broadcom BCM5221. Use reg.18 bits [1:0] for {100Mb/s, fdx}. ++ tmp = ftgmac100_read_phy_register(dev->base_addr, ids->phyAddr, 0x18); ++ duplex = (tmp & 0x0001); ++ speed = (tmp & 0x0002) ? PHY_SPEED_100M : PHY_SPEED_10M; ++ } ++ }// NCSI_Check + + if (speed == PHY_SPEED_1G) { + // Set SPEED_100_bit too, for consistency. +@@ -385,9 +1293,9 @@ static void ftgmac100_reset( struct net_device* dev ) + } + if (duplex) + priv->maccr_val |= FULLDUP_bit; +- else ++ else + priv->maccr_val &= ~FULLDUP_bit; +- ++ + outl( SW_RST_bit, dev->base_addr + MACCR_REG ); + + #ifdef not_complete_yet +@@ -419,6 +1327,7 @@ static void ftgmac100_enable( struct net_device *dev ) + unsigned int rfifo_rsize; //Richard + unsigned int tfifo_rsize; //Richard + unsigned int rxbuf_size; ++ unsigned long Package_Found = 0, Channel_Found = 0, Re_Send = 0, Link_Status; + + rxbuf_size = RX_BUF_SIZE & 0x3fff; + outl( rxbuf_size , dev->base_addr + RBSR_REG); //for NC Body +@@ -475,7 +1384,7 @@ static void ftgmac100_enable( struct net_device *dev ) + + /// enable trans/recv,... + outl(priv->maccr_val, dev->base_addr + MACCR_REG ); +-#if 0 ++ + //NCSI Start + //DeSelect Package/ Select Package + if ((priv->NCSI_support == 1) || (priv->INTEL_NCSI_EVA_support == 1)) { +@@ -491,16 +1400,18 @@ static void ftgmac100_enable( struct net_device *dev ) + } + if (Package_Found != 0) { + //Initiali State +- for (i = 0; i < 2; i++) { //Suppose 2 channels in current version, You could modify it to 0x1F to support 31 channels +- Channel_Found = Clear_Initial_State(dev, i); ++ for (i = 0; i < 1; i++) { //Suppose 2 channels in current version, You could modify it to 0x1F to support 31 channels ++ //Channel_Found = Clear_Initial_State(dev, i); ++ Channel_Found = 1; + if (Channel_Found == 1) { + priv->NCSI_Cap.Channel_ID = i; + printk ("Found NCSI Network Controller at (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID); ++ Get_MAC_Address(dev); ++ Set_MAC_Affinity(dev); ++ Clear_Initial_State(dev, i); + //Get Version and Capabilities + Get_Version_ID(dev); + Get_Capabilities(dev); +-//Configuration +- Select_Active_Package(dev); + //Set MAC Address + Enable_Set_MAC_Address(dev); + //Enable Broadcast Filter +@@ -508,16 +1419,18 @@ static void ftgmac100_enable( struct net_device *dev ) + //Disable VLAN + Disable_VLAN(dev); + //Enable AEN +- Enable_AEN(dev); ++ //Enable_AEN(dev); + //Get Parameters + Get_Parameters(dev); +-//Enable TX ++//Enable TX + Enable_Network_TX(dev); + //Enable Channel + Enable_Channel(dev); + //Get Link Status + Re_Get_Link_Status: +- Link_Status = Get_Link_Status(dev); ++ //TODO: Workaround for CX4 Link status issue ++ //Link_Status = Get_Link_Status(dev); ++ Link_Status = LINK_UP; + if (Link_Status == LINK_UP) { + printk ("Using NCSI Network Controller (%d, %d)\n", priv->NCSI_Cap.Package_ID, priv->NCSI_Cap.Channel_ID); + netif_carrier_on(dev); +@@ -528,7 +1441,7 @@ Re_Get_Link_Status: + netif_carrier_off(dev); + goto Re_Get_Link_Status; + } +-//Disable TX ++//Disable TX + Disable_Network_TX(dev); + //Disable Channel + // Disable_Channel(dev); +@@ -537,9 +1450,19 @@ Re_Get_Link_Status: + } + } + } ++ // Enable Interrupts ++ outl( ++ AHB_ERR_bit | ++ TPKT_LOST_bit | ++ TPKT2E_bit | ++ RXBUF_UNAVA_bit | ++ RPKT2B_bit ++ ,dev->base_addr + IER_REG ++ ); ++ ++ return; + } + /* now, enable interrupts */ +-#endif + if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || + ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) { + outl( +@@ -564,7 +1487,7 @@ Re_Get_Link_Status: + ); + } + else if (priv->ids.miiPhyId == PHYID_BCM54612E +- || priv->ids.miiPhyId == PHYID_BCM54616S) { ++ || priv->ids.miiPhyId == PHYID_BCM54616S) { + outl( + // no link PHY link status pin PHYSTS_CHG_bit | + AHB_ERR_bit | +@@ -583,7 +1506,7 @@ Re_Get_Link_Status: + RXBUF_UNAVA_bit | + RPKT2B_bit + ,dev->base_addr + IER_REG +- ); ++ ); + } + } + +@@ -619,7 +1542,7 @@ static void aspeed_mac_timer(unsigned long data) + speed = (tmp & PHY_SPEED_mask)>>14; + } + else if (priv->ids.miiPhyId == PHYID_BCM54612E +- || priv->ids.miiPhyId == PHYID_BCM54616S) { ++ || priv->ids.miiPhyId == PHYID_BCM54616S) { + // Get link status + // First Switch shadow register selector + ftgmac100_write_phy_register(dev->base_addr, priv->ids.phyAddr, 0x1C, 0x2000); +@@ -628,23 +1551,23 @@ static void aspeed_mac_timer(unsigned long data) + duplex = 0; + else + duplex = 1; +- ++ + switch(tmp & 0x0018) { + case 0x0000: +- speed = PHY_SPEED_1G; +- ++ speed = PHY_SPEED_1G; ++ + break; +- case 0x0008: +- speed = PHY_SPEED_100M; +- ++ case 0x0008: ++ speed = PHY_SPEED_100M; ++ + break; +- case 0x0010: +- speed = PHY_SPEED_10M; +- ++ case 0x0010: ++ speed = PHY_SPEED_10M; ++ + break; + default: + speed = PHY_SPEED_100M; +- } ++ } + } + else { + duplex = 1; speed = PHY_SPEED_100M; +@@ -730,27 +1653,26 @@ static int ftgmac100_wait_to_send_packet( struct sk_buff * skb, struct net_devic + PRINTK3("%s:ftgmac100_wait_to_send_packet, skb=%x\n", dev->name, skb); + cur_desc = &priv->tx_descs[priv->tx_idx]; + +-#ifdef not_complete_yet +- if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor ++#ifdef not_complete_yet ++ if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor + { + DO_PRINT("no empty transmit descriptor\n"); + DO_PRINT("jiffies = %d\n", jiffies); + priv->stats.tx_dropped++; +- netif_stop_queue(dev); /// waiting to do: ++ netif_stop_queue(dev); /// waiting to do: + spin_unlock_irqrestore(&priv->tx_lock, flags); + + return 1; + } + #endif /* end_of_not */ + +- if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor ++ if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor + { + DO_PRINT("no empty TX descriptor:0x%x:0x%x\n", + (unsigned int)cur_desc,((unsigned int *)cur_desc)[0]); + priv->stats.tx_dropped++; +- netif_stop_queue(dev); /// waiting to do: ++ netif_stop_queue(dev); /// waiting to do: + spin_unlock_irqrestore(&priv->tx_lock, flags); +- + return 1; + } + priv->tx_skbuff[priv->tx_idx] = skb; +@@ -803,18 +1725,18 @@ static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv) + int i; + struct sk_buff *skb; + +- priv->rx_descs = dma_alloc_coherent(priv->dev, +- sizeof(RX_DESC)*RXDES_NUM, ++ priv->rx_descs = dma_alloc_coherent(priv->dev, ++ sizeof(RX_DESC)*RXDES_NUM, + &priv->rx_descs_dma, GFP_KERNEL); + + if(!priv->rx_descs) + return -ENOMEM; +- ++ + memset(priv->rx_descs, 0, sizeof(RX_DESC)*RXDES_NUM); + priv->rx_descs[RXDES_NUM-1].EDORR = 1; + + for (i=0; i<RXDES_NUM; i++) { +- dma_addr_t mapping; ++ dma_addr_t mapping; + skb = dev_alloc_skb(RX_BUF_SIZE + NET_IP_ALIGN); + skb_reserve(skb, NET_IP_ALIGN); + +@@ -829,8 +1751,8 @@ static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv) + priv->rx_descs[i].VIR_RXBUF_BADR = skb->data; + } + +- priv->tx_descs = dma_alloc_coherent(priv->dev, +- sizeof(TX_DESC)*TXDES_NUM, ++ priv->tx_descs = dma_alloc_coherent(priv->dev, ++ sizeof(TX_DESC)*TXDES_NUM, + &priv->tx_descs_dma ,GFP_KERNEL); + + if(!priv->tx_descs) +@@ -838,7 +1760,7 @@ static int ftgmac100_ringbuf_alloc(struct ftgmac100_priv *priv) + + memset((void*)priv->tx_descs, 0, sizeof(TX_DESC)*TXDES_NUM); + priv->tx_descs[TXDES_NUM-1].EDOTR = 1; // is last descriptor +- ++ + } + + #if FTMAC100_DEBUG > 2 +@@ -918,20 +1840,14 @@ static void ftgmac100_phy_configure(struct net_device* dev) + } + break; + case PHYID_VENDOR_BROADCOM: +- switch (priv->ids.miiPhyId) { +- case PHYID_BCM54612E: +- case PHYID_BCM54616S: +- ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable +- ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew +- break; +- case PHYID_BCM5221A4: +- default: +- tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1b); +- tmp |= 0x0004; +- ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1b, (u16) tmp); +- break; +- } +- break; ++ tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1b); ++ tmp |= 0x0004; ++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1b, (u16) tmp); ++ break; ++ case PHYID_VENDOR_BCM5461X: ++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x1C, 0x8C00); // Disable GTXCLK Clock Delay Enable ++ ftgmac100_write_phy_register(ioaddr, priv->ids.phyAddr, 0x18, 0xF0E7); // Disable RGMII RXD to RXC Skew ++ break; + } + } + +@@ -960,26 +1876,26 @@ static void ftgmac100_timeout (struct net_device *dev) + } + + +-static void ftgmac100_free_tx (struct net_device *dev) ++static void ftgmac100_free_tx (struct net_device *dev) + { + struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv; +- int entry = priv->old_tx % TXDES_NUM; ++ int entry = priv->old_tx % TXDES_NUM; + unsigned long flags = 0; +- ++ + spin_lock_irqsave(&priv->tx_lock,flags); +- ++ + /* Free used tx skbuffs */ + + while ((priv->tx_descs[entry].TXDMA_OWN == TX_OWNBY_SOFTWARE) && (priv->tx_skbuff[entry] != NULL)) { + struct sk_buff *skb; +- ++ + skb = priv->tx_skbuff[entry]; + dev_kfree_skb_any (skb); + priv->tx_skbuff[entry] = 0; + entry = (entry + 1) % TXDES_NUM; + priv->tx_free++; + } +- ++ + spin_unlock_irqrestore(&priv->tx_lock, flags); + priv->old_tx = entry; + if ((netif_queue_stopped(dev)) && (priv->tx_free > 0)) { +@@ -1295,7 +2211,7 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * + DO_PRINT("PHYSTS_CHG \n"); + // Is this interrupt for changes of the PHYLINK pin? + // Note: PHYLINK is optional; not all boards connect it. +- if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || ++ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_MARVELL) || + ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8211)) + { + tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x13); +@@ -1312,7 +2228,7 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * + tmp &= 0x000e; + } + else if (priv->ids.miiPhyId == PHYID_BCM54612E +- || priv->ids.miiPhyId == PHYID_BCM54616S) { ++ || priv->ids.miiPhyId == PHYID_BCM54616S) { + tmp = ftgmac100_read_phy_register(ioaddr, priv->ids.phyAddr, 0x1A); + PRINTK("%s: PHY interrupt status, read_phy_reg(0x1A) = 0x%04x\n", + dev->name, tmp); +@@ -1403,10 +2319,10 @@ static irqreturn_t ftgmac100_interrupt(int irq, void * dev_id, struct pt_regs * + . Get the current statistics. + . This may be called with the card open or closed. + .-------------------------------------------------------------*/ +-static struct net_device_stats* ftgmac100_query_statistics(struct net_device *dev) ++static struct net_device_stats* ftgmac100_query_statistics(struct net_device *dev) + { + struct ftgmac100_priv *priv = (struct ftgmac100_priv *)dev->priv; +- ++ + return &priv->stats; + } + +@@ -1416,7 +2332,7 @@ static struct net_device_stats* ftgmac100_query_statistics(struct net_device *de + // Finds the CRC32 of a set of bytes. + // Again, from Peter Cammaert's code. + // -------------------------------------------------------------------- +-static int crc32( char * s, int length ) ++static int crc32( char * s, int length ) + { + /* indices */ + int perByte; +@@ -1446,7 +2362,7 @@ static int crc32( char * s, int length ) + . packets before they take up memory. + */ + +-static void ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs ) ++static void ftgmac100_setmulticast( struct net_device *dev, int count, struct dev_mc_list * addrs ) + { + struct dev_mc_list * cur_addr; + int crc_val; +@@ -1455,12 +2371,12 @@ static void ftgmac100_setmulticast( struct net_device *dev, int count, struct de + struct AstMacHwConfig* ids = &priv->ids; + unsigned long Combined_Channel_ID, i; + struct sk_buff * skb; +- cur_addr = addrs; ++ cur_addr = addrs; + + //TX +-#if 0 ++#if 1 + if (priv->NCSI_support == 1) { +- skb = dev_alloc_skb (TX_BUF_SIZE + 16); ++ skb = dev_alloc_skb (TX_BUF_SIZE + 16); + priv->InstanceID++; + priv->NCSI_Request.IID = priv->InstanceID; + priv->NCSI_Request.Command = SET_MAC_ADDRESS; +@@ -1597,7 +2513,7 @@ static int ast_gmac_stop(struct net_device *dev) + priv->rx_descs = NULL; priv->rx_descs_dma = 0; + priv->tx_descs = NULL; priv->tx_descs_dma = 0; + priv->tx_buf = NULL; priv->tx_buf_dma = 0; +- ++ + + return 0; + } +@@ -1651,10 +2567,10 @@ static int ftgmac100_open(struct net_device *netdev) + ftgmac100_reset(netdev); + ftgmac100_enable(netdev); + +- if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) || ++ if (((priv->ids.miiPhyId & PHYID_VENDOR_MASK) == PHYID_VENDOR_BROADCOM) || + ((priv->ids.miiPhyId & PHYID_VENDOR_MODEL_MASK) == PHYID_RTL8201EL) || + (priv->ids.miiPhyId == PHYID_BCM54612E) || +- (priv->ids.miiPhyId == PHYID_BCM54616S)) { ++ (priv->ids.miiPhyId == PHYID_BCM54616S)) { + + init_timer(&priv->timer); + priv->timer.data = (unsigned long)netdev; +@@ -1702,7 +2618,7 @@ static int __init ast_gmac_probe(struct platform_device *pdev) + + + // SET_ETHTOOL_OPS(netdev, &ftgmac100_ethtool_ops); +- ++ + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30)) + netdev->netdev_ops = &ftgmac100_netdev_ops; + #else +@@ -1715,13 +2631,12 @@ static int __init ast_gmac_probe(struct platform_device *pdev) + netdev->hard_start_xmit = ftgmac100_wait_to_send_packet; + netdev->tx_timeout = ftgmac100_timeout; + netdev->get_stats = ftgmac100_query_statistics; +-//#ifdef HAVE_MULTICAST +-#if 0 ++#ifdef HAVE_MULTICAST + netdev->set_multicast_list = &ftgmac100_set_multicast_list; + #endif + + #endif +- ++ + + #ifdef CONFIG_AST_NPAI + // netdev->features = NETIF_F_GRO; +@@ -1734,12 +2649,12 @@ static int __init ast_gmac_probe(struct platform_device *pdev) + priv = netdev_priv(netdev); + priv->netdev = netdev; + priv->dev = &pdev->dev; +- ++ + + priv->ids.macId = pdev->id; +- ++ + priv->NCSI_support = ast_eth_data->NCSI_support; +- priv->INTEL_NCSI_EVA_support= ast_eth_data->INTEL_NCSI_EVA_support; ++ priv->INTEL_NCSI_EVA_support= ast_eth_data->INTEL_NCSI_EVA_support; + spin_lock_init(&priv->tx_lock); + + #if 0 +@@ -1833,7 +2748,7 @@ err_ioremap: + err_req_mem: + // netif_napi_del(&priv->napi); + platform_set_drvdata(pdev, NULL); +-err_netdev: ++err_netdev: + free_netdev(netdev); + err_alloc_etherdev: + return err; +diff --git a/drivers/net/ftgmac100_26.h b/drivers/net/ftgmac100_26.h +index 0d47024..2493111 100644 +--- a/drivers/net/ftgmac100_26.h ++++ b/drivers/net/ftgmac100_26.h +@@ -1,16 +1,16 @@ + /******************************************************************************** + * File Name : ftgmac100_26.h +-* ++* + * Copyright (C) 2012-2020 ASPEED Technology 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. +-* You should have received a copy of the GNU General Public License +-* along with this program; if not, write to the Free Software +-* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++* 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. ++* You should have received a copy of the GNU General Public License ++* along with this program; if not, write to the Free Software ++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + ********************************************************************************/ + // -------------------------------------------------------------------- + +@@ -78,7 +78,7 @@ + + + // -------------------------------------------------------------------- +-// APTC_REG ++// APTC_REG + // -------------------------------------------------------------------- + + +@@ -99,18 +99,18 @@ typedef struct + #define PHY_READ_bit (1UL<<26) + #define PHY_WRITE_bit (1UL<<27) + // -------------------------------------------------------------------- +-// PHYCR_REG ++// PHYCR_REG + // -------------------------------------------------------------------- + #define PHY_AUTO_OK_bit (1UL<<5) + // -------------------------------------------------------------------- +-// PHY INT_STAT_REG ++// PHY INT_STAT_REG + // -------------------------------------------------------------------- + #define PHY_SPEED_CHG_bit (1UL<<14) + #define PHY_DUPLEX_CHG_bit (1UL<<13) + #define PHY_LINK_CHG_bit (1UL<<10) + #define PHY_AUTO_COMP_bit (1UL<<11) + // -------------------------------------------------------------------- +-// PHY SPE_STAT_REG ++// PHY SPE_STAT_REG + // -------------------------------------------------------------------- + #define PHY_RESOLVED_bit (1UL<<11) + #define PHY_SPEED_mask 0xC000 +@@ -269,7 +269,7 @@ typedef struct { + unsigned short Reserved_5; + unsigned short Response_Code; + unsigned short Reason_Code; +- unsigned char Payload_Data[64]; ++ unsigned char Payload_Data[128]; + } NCSI_Response_Packet; + + //Standard Response Code +@@ -365,30 +365,30 @@ typedef struct + u32 FRS:1; + u32 EDORR:1; + u32 RXPKT_RDY:1; // 1 ==> owned by FTMAC100, 0 ==> owned by software +- ++ + // RXDES1 + u32 VLAN_TAGC:16; + u32 Reserved4:4; + u32 PROTL_TYPE:2; + u32 LLC_PKT:1; + u32 DF:1; +- u32 VLAN_AVA:1; ++ u32 VLAN_AVA:1; + u32 TCPCS_FAIL:1; + u32 UDPCS_FAIL:1; + u32 IPCS_FAIL:1; + u32 Reserved5:4; +- ++ + // RXDES2 + u32 Reserved6:32; +- ++ + // RXDES3 + u32 RXBUF_BADR; +- ++ + u32 VIR_RXBUF_BADR; // not defined, the virtual address of receive buffer is placed here +- +- u32 RESERVED; +- u32 RESERVED1; +- u32 RESERVED2; ++ ++ u32 RESERVED; ++ u32 RESERVED1; ++ u32 RESERVED2; + }RX_DESC; + + +@@ -405,7 +405,7 @@ typedef struct + u32 FTS:1; + u32 EDOTR:1; + u32 TXDMA_OWN:1; +- ++ + // TXDES1 + u32 VLAN_TAGC:16; + u32 INS_VLAN:1; +@@ -416,8 +416,8 @@ typedef struct + u32 LLC_PKT:1; + u32 Reserved6:7; + u32 TX2FIC:1; +- u32 TXIC:1; +- ++ u32 TXIC:1; ++ + // TXDES2 + u32 Reserved7:32; + +@@ -427,8 +427,8 @@ typedef struct + u32 VIR_TXBUF_BADR; // Reserve, the virtual address of transmit buffer is placed here + + u32 RESERVED; +- u32 RESERVED1; +- u32 RESERVED2; ++ u32 RESERVED1; ++ u32 RESERVED2; + + }TX_DESC; + +@@ -450,7 +450,7 @@ typedef struct + // -------------------------------------------------------------------- + + +-//#define RXDES_NUM 64//64 // we defined 32 descriptor for OTG issue ++//#define RXDES_NUM 64//64 // we defined 32 descriptor for OTG issue + #define RXDES_NUM 32 + + #define RX_BUF_SIZE 1536 +@@ -464,6 +464,7 @@ typedef struct + #define PHYID_REVISION_MASK 0x0000000f + #define PHYID_VENDOR_MARVELL 0x01410c00 + #define PHYID_VENDOR_BROADCOM 0x00406000 ++#define PHYID_VENDOR_BCM5461X 0x03625c00 + #define PHYID_VENDOR_REALTEK 0x001cc800 + + #define PHYID_BCM5221A4 0x004061e4 +@@ -521,7 +522,7 @@ struct ftgmac100_priv { + int tx_idx; + int old_tx; + struct sk_buff *tx_skbuff[TXDES_NUM]; +- ++ + int maccr_val; + struct timer_list timer; + u32 GigaBit_MAHT0; +@@ -533,7 +534,7 @@ struct ftgmac100_priv { + NCSI_Capability NCSI_Cap; + unsigned int InstanceID; + unsigned int Retry; +- unsigned char Payload_Data[16]; ++ unsigned char Payload_Data[64]; + unsigned char Payload_Pad[4]; + unsigned long Payload_Checksum; + int tx_free; +@@ -575,7 +576,7 @@ struct ftgmac100_priv { + #define STOP_DONE (1 << 4) + + +- ++ + #endif /* _SMC_91111_H_ */ + + +diff --git a/drivers/rtc/rtc-aspeed.c b/drivers/rtc/rtc-aspeed.c +index 477032e..de9e995 100644 +--- a/drivers/rtc/rtc-aspeed.c ++++ b/drivers/rtc/rtc-aspeed.c +@@ -7,11 +7,11 @@ + * 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. +-* ++* + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -67,8 +67,16 @@ ast_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) + { + struct ast_rtc *ast_rtc = dev_get_drvdata(dev); + pr_debug("cmd = 0x%08x, arg = 0x%08lx\n", cmd, arg); +- ++ + switch (cmd) { ++ case RTC_SET_TIME: ++ case RTC_RD_TIME: ++ case RTC_ALM_READ: ++ case RTC_ALM_SET: ++ { ++ // use rtc-dev.c fallback ++ return -ENOIOCTLCMD; ++ } + case RTC_AIE_ON: /* alarm on */ + { + rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) | ENABLE_ALL_ALARM, RTC_CONTROL); +@@ -105,7 +113,7 @@ ast_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) + default: + return -ENOTTY; + } +- ++ + return 0; + } + +@@ -122,7 +130,7 @@ ast_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm) + + reg_time = rtc_read(ast_rtc->base, RTC_CNTR_STS_1); + reg_date = rtc_read(ast_rtc->base, RTC_CNTR_STS_2); +- ++ + spin_unlock_irqrestore(&ast_rtc->lock, flags); + + rtc_tm->tm_year = GET_CENT_VAL(reg_date)*1000 | GET_YEAR_VAL(reg_date); +@@ -132,7 +140,7 @@ ast_rtc_get_time(struct device *dev, struct rtc_time *rtc_tm) + rtc_tm->tm_hour = GET_HOUR_VAL(reg_time); + rtc_tm->tm_min = GET_MIN_VAL(reg_time); + rtc_tm->tm_sec = GET_SEC_VAL(reg_time); +- ++ + pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, + rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); +@@ -155,7 +163,7 @@ ast_rtc_set_time(struct device *dev, struct rtc_time *tm) + + /* set hours */ + reg_time = SET_DAY_VAL(tm->tm_mday) | SET_HOUR_VAL(tm->tm_hour) | SET_MIN_VAL(tm->tm_min) | SET_SEC_VAL(tm->tm_sec); +- ++ + /* set century */ + /* set mon */ + reg_date = SET_CENT_VAL(tm->tm_year / 1000) | SET_YEAR_VAL(tm->tm_year % 1000) | SET_MON_VAL(tm->tm_mon); +@@ -166,10 +174,10 @@ ast_rtc_set_time(struct device *dev, struct rtc_time *tm) + rtc_write(ast_rtc->base, reg_date, RTC_CNTR_STS_2); + + rtc_write(ast_rtc->base, rtc_read(ast_rtc->base, RTC_CONTROL) &~RTC_LOCK , RTC_CONTROL); +- ++ + spin_unlock_irqrestore(&ast_rtc->lock, flags); + +- return 0; ++ return 0; + } + static int + ast_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +@@ -183,7 +191,7 @@ ast_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) + alarm_reg = rtc_read(ast_rtc->base, RTC_ALARM); + spin_unlock_irqrestore(&ast_rtc->lock, flags); + +-//DAY ++//DAY + alm_tm->tm_mday = GET_DAY_VAL(alarm_reg); + + //HR +@@ -221,7 +229,7 @@ ast_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) + if (tm->tm_mday <= 31 && tm->tm_mday >= 1) { + reg_alarm |= SET_DAY_VAL(tm->tm_mday); + } +- ++ + //HR + /* set ten hours */ + if (tm->tm_hour <= 23 && tm->tm_hour >= 0) { +@@ -245,8 +253,8 @@ ast_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) + spin_lock_irqsave(&ast_rtc->lock, flags); + + rtc_write(ast_rtc->base, reg_alarm, RTC_ALARM); +- +- if(alarm->enabled) ++ ++ if(alarm->enabled) + rtc_write(ast_rtc->base, reg_alarm, RTC_CONTROL); + else + rtc_write(ast_rtc->base, reg_alarm, RTC_CONTROL); +@@ -366,14 +374,14 @@ static int __init ast_rtc_probe(struct platform_device *pdev) + ret = -EBUSY; + goto free_rtc; + } +- ++ + ast_rtc->base = ioremap(res->start, resource_size(res)); + if (!ast_rtc->base) { + dev_err(&pdev->dev, "cannot map SocleDev registers\n"); + ret = -ENOMEM; + goto release_mem; + } +- ++ + pr_debug("base = 0x%p, irq = %d\n", ast_rtc->base, ast_rtc->irq); + + rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &ast_rtcops, THIS_MODULE); +@@ -381,7 +389,7 @@ static int __init ast_rtc_probe(struct platform_device *pdev) + ret = PTR_ERR(rtc_dev); + goto unmap; + } +- ++ + ast_rtc->res = res; + ast_rtc->rtc_dev = rtc_dev; + spin_lock_init(&ast_rtc->lock); +@@ -406,7 +414,7 @@ static int __init ast_rtc_probe(struct platform_device *pdev) + printk("no need to enable RTC \n"); + + spin_unlock_irq(&ast_rtc->lock); +- ++ + /* register ISR */ + ret = request_irq(ast_rtc->irq, ast_rtc_interrupt, IRQF_DISABLED, dev_name(&rtc_dev->dev), ast_rtc); + if (ret) { +diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c +index a181ccf..f16da59 100644 +--- a/drivers/serial/8250.c ++++ b/drivers/serial/8250.c +@@ -38,6 +38,7 @@ + #include <linux/serial_8250.h> + #include <linux/nmi.h> + #include <linux/mutex.h> ++#include <linux/gpio.h> + + #include <asm/io.h> + #include <asm/irq.h> +@@ -59,6 +60,8 @@ static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; + + static struct uart_driver serial8250_reg; + ++DECLARE_WAIT_QUEUE_HEAD(thre_wait); ++ + static int serial_index(struct uart_port *port) + { + return (serial8250_reg.minor - 64) + port->line; +@@ -1225,7 +1228,10 @@ static void autoconfig_irq(struct uart_8250_port *up) + + static inline void __stop_tx(struct uart_8250_port *p) + { +- if (p->ier & UART_IER_THRI) { ++ int status = serial_in(p, UART_LSR); ++ // only turn off THRE interrupt if THRE is *currently* asserted ++ // (we still want to catch it a final time after the FIFO empties) ++ if ((p->ier & UART_IER_THRI) && (status & UART_LSR_THRE)) { + p->ier &= ~UART_IER_THRI; + serial_out(p, UART_IER, p->ier); + } +@@ -1527,6 +1533,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) + + DEBUG_INTR("end.\n"); + ++ wake_up(&thre_wait); + return IRQ_RETVAL(handled); + } + +@@ -2526,6 +2533,35 @@ serial8250_type(struct uart_port *port) + return uart_config[type].name; + } + ++static int serial8250_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg) { ++ struct uart_8250_port *up = (struct uart_8250_port *)port; ++ unsigned long flags; ++ int ret = -ENOIOCTLCMD; ++ // kernel-space RS485 drain-and-switch hack ++ if (cmd == TIOCSERWAITTEMT) { ++ // wait for kernel buffers and UART FIFO to both empty ++ struct circ_buf *xmit = &up->port.info->xmit; ++ wait_event_interruptible( ++ thre_wait, ++ uart_circ_empty(xmit) && ++ (serial_in(up, UART_LSR) & UART_LSR_THRE)); ++ // spin until TEMT (transmit shift register empty) ++ spin_lock_irqsave(&up->port.lock, flags); ++ wait_for_xmitr(up, BOTH_EMPTY); ++ if (arg != 0) { ++ // turn off RS485 DE pin ++ gpio_set_value(arg, 0); ++ } ++ // grab any phantom char seen on RX when transceiver switches ++ (void) serial_inp(up, UART_RX); ++ // enable read ++ up->port.ignore_status_mask &= ~UART_LSR_DR; ++ spin_unlock_irqrestore(&up->port.lock, flags); ++ return 0; ++ } ++ return ret; ++} ++ + static struct uart_ops serial8250_pops = { + .tx_empty = serial8250_tx_empty, + .set_mctrl = serial8250_set_mctrl, +@@ -2544,6 +2580,7 @@ static struct uart_ops serial8250_pops = { + .request_port = serial8250_request_port, + .config_port = serial8250_config_port, + .verify_port = serial8250_verify_port, ++ .ioctl = serial8250_ioctl, + #ifdef CONFIG_CONSOLE_POLL + .poll_get_char = serial8250_get_poll_char, + .poll_put_char = serial8250_put_poll_char, +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +index 5702145..0b01ba8 100644 +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -235,10 +235,17 @@ config ORION5X_WATCHDOG + + config AST_WATCHDOG + tristate "ASPEED GUC watchdog" +- depends on WATCHDOG ++ depends on WATCHDOG + help + Watchdog timer for ASPEED chips. + ++config AST_WATCHDOG_REARM_DUAL_BOOT ++ bool "Rearm dual boot watchdog" ++ default n ++ depends on AST_WATCHDOG ++ help ++ Rearm dual boot watchdog or not during boot ++ + # ARM26 Architecture + + # AVR32 Architecture +diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c +index 9e7e84f..e599a55 100644 +--- a/drivers/watchdog/ast_wdt.c ++++ b/drivers/watchdog/ast_wdt.c +@@ -68,6 +68,7 @@ typedef unsigned char bool_T; + + #else + #define WDT_BASE_VA (IO_ADDRESS(AST_WDT_BASE)) ++#define WDT2_BASE_VA (IO_ADDRESS(AST_WDT_BASE + 20)) + #endif + + #define WDT_CntSts (WDT_BASE_VA+0x00) +@@ -78,6 +79,14 @@ typedef unsigned char bool_T; + #define WDT_Clr (WDT_BASE_VA+0x14) + #define WDT_RstWd (WDT_BASE_VA+0x18) + ++#define WDT2_CntSts (WDT2_BASE_VA+0x00) ++#define WDT2_Reload (WDT2_BASE_VA+0x04) ++#define WDT2_Restart (WDT2_BASE_VA+0x08) ++#define WDT2_Ctrl (WDT2_BASE_VA+0x0C) ++#define WDT2_TimeOut (WDT2_BASE_VA+0x10) ++#define WDT2_Clr (WDT2_BASE_VA+0x14) ++#define WDT2_RstWd (WDT2_BASE_VA+0x18) ++ + #define WDT_CTRL_B_SECOND_BOOT (0x1 << 7) + #define WDT_CTRL_B_RESET_SOC (0x00 << 5) /* yes, 0x00 */ + #define WDT_CTRL_B_RESET_FULL (0x01 << 5) +@@ -101,6 +110,11 @@ typedef unsigned char bool_T; + #define WDT_TIMO 30 /* Default heartbeat = 30 seconds */ + + #define WDT_INITIAL_TIMO (8*60) /* Initial timeout, 8m */ ++/* ++ * Dual boot watchdog is 5s shorter so that dual boot watchdog ++ * will kick in first. ++ */ ++#define WDT_DUAL_BOOT_TIMO (WDT_INITIAL_TIMO - 5) + #define WDT_TIMO2TICKS(t) (TICKS_PER_uSEC * 1000000 * (t)) + + static int heartbeat = WDT_TIMO; +@@ -233,6 +247,14 @@ bool_T wdt_is_enabled(void) + return reg & WDT_CTRL_B_ENABLE; + } + ++#ifdef CONFIG_AST_WATCHDOG_REARM_DUAL_BOOT ++void wdt_dual_boot_restart(unsigned int timeo) ++{ ++ AST_WRITE_REG(WDT2_Reload, WDT_TIMO2TICKS(timeo)); ++ AST_WRITE_REG(WDT2_Restart, 0x4755); /* reload! */ ++ printk(KERN_INFO "Re-arm the dual boot watchdog for %u seconds\n", timeo); ++} ++#endif + + void wdt_restart_new(unsigned int nPeriod, int sourceClk, bool_T bResetOut, + bool_T bIntrSys, bool_T bClrAfter, bool_T bResetARMOnly) +@@ -542,6 +564,11 @@ static int ast_wdt_probe(struct platform_device *pdev) + return ret; + } + ++#ifdef CONFIG_AST_WATCHDOG_REARM_DUAL_BOOT ++ /* re-arm dual boot watchdog */ ++ wdt_dual_boot_restart(WDT_DUAL_BOOT_TIMO); ++#endif ++ + /* interrupt the system while WDT timeout */ + wdt_restart_new(WDT_TIMO2TICKS(WDT_INITIAL_TIMO), WDT_CLK_SRC_EXT, + /* No Ext, No intr, Self clear, Full chip reset */ +diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c +index 61cb48f..5dc69ab 100644 +--- a/fs/compat_ioctl.c ++++ b/fs/compat_ioctl.c +@@ -3,7 +3,7 @@ + * + * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) + * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) +- * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs ++ * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs + * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) + * + * These routines maintain argument size conversion between 32bit and 64bit +@@ -125,7 +125,7 @@ static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) + mm_segment_t old_fs = get_fs(); + int err; + unsigned long val; +- ++ + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&val); + set_fs (old_fs); +@@ -133,14 +133,14 @@ static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) + return -EFAULT; + return err; + } +- ++ + static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) + { + mm_segment_t old_fs = get_fs(); + u32 __user *argptr = compat_ptr(arg); + int err; + unsigned long val; +- ++ + if(get_user(val, argptr)) + return -EFAULT; + set_fs (KERNEL_DS); +@@ -365,17 +365,17 @@ static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) + if (copy_in_user(ifr, ifr32, sizeof(struct ifreq32))) + return -EFAULT; + ifr++; +- ifr32++; ++ ifr32++; + } + } + if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) + return -EFAULT; + +- err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)uifc); ++ err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)uifc); + if (err) + return err; + +- if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) ++ if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) + return -EFAULT; + + ifr = ifc.ifc_req; +@@ -411,7 +411,7 @@ static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) + struct ifreq32 __user *ifr32; + u32 data; + void __user *datap; +- ++ + ifr = compat_alloc_user_space(sizeof(*ifr)); + ifr32 = compat_ptr(arg); + +@@ -507,7 +507,7 @@ static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) + struct ifmap32 __user *uifmap32; + mm_segment_t old_fs; + int err; +- ++ + uifr32 = compat_ptr(arg); + uifmap32 = &uifr32->ifr_ifru.ifru_map; + switch (cmd) { +@@ -610,7 +610,7 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) + char devname[16]; + u32 rtdev; + mm_segment_t old_fs = get_fs(); +- ++ + struct socket *mysock = sockfd_lookup(fd, &ret); + + if (mysock && mysock->sk && mysock->sk->sk_family == AF_INET6) { /* ipv6 */ +@@ -624,7 +624,7 @@ static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) + ret |= __get_user (r6.rtmsg_info, &(ur6->rtmsg_info)); + ret |= __get_user (r6.rtmsg_flags, &(ur6->rtmsg_flags)); + ret |= __get_user (r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); +- ++ + r = (void *) &r6; + } else { /* ipv4 */ + struct rtentry32 __user *ur4 = compat_ptr(arg); +@@ -1046,14 +1046,14 @@ static int vt_check(struct file *file) + struct tty_struct *tty; + struct inode *inode = file->f_path.dentry->d_inode; + struct vc_data *vc; +- ++ + if (file->f_op->unlocked_ioctl != tty_ioctl) + return -EINVAL; +- ++ + tty = (struct tty_struct *)file->private_data; + if (tty_paranoia_check(tty, inode, "tty_ioctl")) + return -EINVAL; +- ++ + if (tty->ops->ioctl != vt_ioctl) + return -EINVAL; + +@@ -1067,7 +1067,7 @@ static int vt_check(struct file *file) + */ + if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) + return 1; +- return 0; ++ return 0; + } + + struct consolefontdesc32 { +@@ -1085,7 +1085,7 @@ static int do_fontx_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, + + perm = vt_check(file); + if (perm < 0) return perm; +- ++ + switch (cmd) { + case PIO_FONTX: + if (!perm) +@@ -1130,16 +1130,16 @@ struct console_font_op32 { + compat_uint_t charcount; + compat_caddr_t data; /* font data with height fixed to 32 */ + }; +- ++ + static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) + { + struct console_font_op op; + struct console_font_op32 __user *fontop = compat_ptr(arg); + int perm = vt_check(file), i; + struct vc_data *vc; +- ++ + if (perm < 0) return perm; +- ++ + if (copy_from_user(&op, fontop, sizeof(struct console_font_op32))) + return -EFAULT; + if (!perm && op.op != KD_FONT_OP_GET) +@@ -1303,7 +1303,7 @@ static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg) + u32 data; + void __user *datap; + int err; +- ++ + sioc = compat_alloc_user_space(sizeof(*sioc)); + sioc32 = compat_ptr(arg); + +@@ -1328,7 +1328,7 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) + { + int i; + unsigned int cmd = 0; +- ++ + switch (cmd32) { + case SONET_GETSTAT: + case SONET_GETSTATZ: +@@ -1349,11 +1349,11 @@ static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) + } + if (i == NR_ATM_IOCTL) + return -EINVAL; +- ++ + switch (cmd) { + case ATM_GETNAMES: + return do_atm_iobuf(fd, cmd, arg); +- ++ + case ATM_GETLINKRATE: + case ATM_GETTYPE: + case ATM_GETESI: +@@ -1444,7 +1444,7 @@ static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg) + } + + return err; +-} ++} + + #ifdef CONFIG_BLOCK + struct raw32_config_request +@@ -1798,7 +1798,7 @@ static int rtc_ioctl(unsigned fd, unsigned cmd, unsigned long arg) + val32 = kval; + return put_user(val32, (unsigned int __user *)arg); + case RTC_IRQP_SET32: +- return sys_ioctl(fd, RTC_IRQP_SET, arg); ++ return sys_ioctl(fd, RTC_IRQP_SET, arg); + case RTC_EPOCH_SET32: + return sys_ioctl(fd, RTC_EPOCH_SET, arg); + default: +@@ -2678,6 +2678,7 @@ COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) + /* i2c */ + HANDLE_IOCTL(I2C_FUNCS, w_long) + HANDLE_IOCTL(I2C_RDWR, do_i2c_rdwr_ioctl) ++HANDLE_IOCTL(I2C_SLAVE_RDWR, do_i2c_rdwr_ioctl) + HANDLE_IOCTL(I2C_SMBUS, do_i2c_smbus_ioctl) + /* bridge */ + HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl) +diff --git a/include/linux/i2c-dev.h b/include/linux/i2c-dev.h +index 311315b..ed9b48d 100644 +--- a/include/linux/i2c-dev.h ++++ b/include/linux/i2c-dev.h +@@ -46,6 +46,7 @@ + #define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ + + #define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */ ++#define I2C_SLAVE_RDWR 0x0709 /* Slave Read Write */ + + #define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ + #define I2C_SMBUS 0x0720 /* SMBus transfer */ +diff --git a/include/linux/i2c.h b/include/linux/i2c.h +index 59167e2..f037cde 100644 +--- a/include/linux/i2c.h ++++ b/include/linux/i2c.h +@@ -62,6 +62,9 @@ extern int i2c_master_recv(struct i2c_client *client, char *buf, int count); + extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); + ++extern int i2c_slave_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, ++ int num); ++ + /* This is the very generalized SMBus access routine. You probably do not + want to use this, though; one of the functions below may be much easier, + and probably just as fast. +@@ -333,6 +336,7 @@ struct i2c_algorithm { + processed, or a negative value on error */ + int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num); ++ int (*slave_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs); + int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data); +@@ -516,6 +520,8 @@ struct i2c_msg { + __u16 flags; + #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ + #define I2C_M_RD 0x0001 /* read data, from slave to master */ ++#define I2C_S_EN 0x0002 /* Slave Enable */ ++#define I2C_S_ALT 0x0004 /* Slave Alert */ + #define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch +new file mode 100644 +index 0000000..52aef04 +--- /dev/null ++++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0029-mtd-m25p80-Add-support-for-the-Winbond-W25Q64.patch +@@ -0,0 +1,29 @@ ++From d2ac467a108400ff1ae682a423c7d41265e62d47 Mon Sep 17 00:00:00 2001 ++From: Thierry Reding <thierry.reding@avionic-design.de> ++Date: Mon, 30 Aug 2010 13:00:48 +0200 ++Subject: [PATCH] mtd: m25p80: Add support for the Winbond W25Q64 ++ ++This patch adds support for the Winbond W25Q64 serial flash. ++ ++Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de> ++Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> ++Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> ++--- ++ drivers/mtd/devices/m25p80.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c ++index 1f0f703..b6fd7c2 100644 ++--- a/drivers/mtd/devices/m25p80.c +++++ b/drivers/mtd/devices/m25p80.c ++@@ -716,6 +716,7 @@ static const struct spi_device_id m25p_ids[] = { ++ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, ++ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, ++ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, +++ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, ++ ++ /* Catalyst / On Semiconductor -- non-JEDEC */ ++ { "cat25c11", CAT25_INFO( 16, 8, 16, 1) }, ++-- ++1.8.5.6 ++ +diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch +new file mode 100644 +index 0000000..ad04217 +--- /dev/null ++++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0030-net-Don-t-leak-packets-when-a-netns-is-going-down.patch +@@ -0,0 +1,56 @@ ++From 0a36b345ab99d6b3c96999e7e3b79bd243cf9bf7 Mon Sep 17 00:00:00 2001 ++From: "Eric W. Biederman" <ebiederm@xmission.com> ++Date: Wed, 5 Nov 2008 16:00:24 -0800 ++Subject: [PATCH] net: Don't leak packets when a netns is going down ++ ++I have been tracking for a while a case where when the ++network namespace exits the cleanup gets stck in an ++endless precessess of: ++ ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++unregister_netdevice: waiting for lo to become free. Usage count = 3 ++ ++It turns out that if you listen on a multicast address an unsubscribe ++packet is sent when the network device goes down. If you shutdown ++the network namespace without carefully cleaning up this can trigger ++the unsubscribe packet to be sent over the loopback interface while ++the network namespace is going down. ++ ++All of which is fine except when we drop the packet and forget to ++free it leaking the skb and the dst entry attached to. As it ++turns out the dst entry hold a reference to the idev which holds ++the dev and keeps everything from being cleaned up. Yuck! ++ ++By fixing my earlier thinko and add the needed kfree_skb and everything ++cleans up beautifully. ++ ++Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ net/core/dev.c | 4 +++- ++ 1 file changed, 3 insertions(+), 1 deletion(-) ++ ++diff --git a/net/core/dev.c b/net/core/dev.c ++index 811507c..a0c60607 100644 ++--- a/net/core/dev.c +++++ b/net/core/dev.c ++@@ -2253,8 +2253,10 @@ int netif_receive_skb(struct sk_buff *skb) ++ rcu_read_lock(); ++ ++ /* Don't receive packets in an exiting network namespace */ ++- if (!net_alive(dev_net(skb->dev))) +++ if (!net_alive(dev_net(skb->dev))) { +++ kfree_skb(skb); ++ goto out; +++ } ++ ++ #ifdef CONFIG_NET_CLS_ACT ++ if (skb->tc_verd & TC_NCLS) { ++-- ++1.8.1 ++ +diff --git a/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch +new file mode 100644 +index 0000000..b638996 +--- /dev/null ++++ b/meta-aspeed/recipes-kernel/linux/files/patch-2.6.28.9/0031-IPv6-Print-error-value-when-skb-allocation-fails.patch +@@ -0,0 +1,43 @@ ++From 5777cee30776da63ecbe2b6d4929e01d82c7d72e Mon Sep 17 00:00:00 2001 ++From: Brian Haley <brian.haley@hp.com> ++Date: Tue, 2 Jun 2009 00:20:26 -0700 ++Subject: [PATCH] IPv6: Print error value when skb allocation fails ++ ++Print-out the error value when sock_alloc_send_skb() fails in ++the IPv6 neighbor discovery code - can be useful for debugging. ++ ++Signed-off-by: Brian Haley <brian.haley@hp.com> ++Signed-off-by: David S. Miller <davem@davemloft.net> ++--- ++ net/ipv6/ndisc.c | 8 ++++---- ++ 1 file changed, 4 insertions(+), 4 deletions(-) ++ ++diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c ++index d0f54d1..45529b1 100644 ++--- a/net/ipv6/ndisc.c +++++ b/net/ipv6/ndisc.c ++@@ -483,8 +483,8 @@ static void __ndisc_send(struct net_device *dev, ++ 1, &err); ++ if (!skb) { ++ ND_PRINTK0(KERN_ERR ++- "ICMPv6 ND: %s() failed to allocate an skb.\n", ++- __func__); +++ "ICMPv6 ND: %s() failed to allocate an skb, err=%d.\n", +++ __func__, err); ++ dst_release(dst); ++ return; ++ } ++@@ -1533,8 +1533,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, ++ 1, &err); ++ if (buff == NULL) { ++ ND_PRINTK0(KERN_ERR ++- "ICMPv6 Redirect: %s() failed to allocate an skb.\n", ++- __func__); +++ "ICMPv6 Redirect: %s() failed to allocate an skb, err=%d.\n", +++ __func__, err); ++ dst_release(dst); ++ return; ++ } ++-- ++1.8.1 ++ diff --git a/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb b/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb index 077e21b..bda2ea3 100644 --- a/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb +++ b/meta-aspeed/recipes-kernel/linux/linux-aspeed_2.6.28.9.bb @@ -1,10 +1,7 @@ - # This revision corresponds to the tag "v2.6.28.9" # We use the revision in order to avoid having to fetch it from the repo during parse SRCREV = "1e85856853e24e9013d142adaad38c2adc7e48ac" -PV = "2.6.28.9" - SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git;protocol=https;branch=linux-2.6.28.y \ file://patch-2.6.28.9/0000-linux-aspeed-064.patch \ file://patch-2.6.28.9/0000-linux-openbmc.patch \ @@ -25,14 +22,30 @@ SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git file://patch-2.6.28.9/0028-ipv6-Plug-sk_buff-leak-in-ipv6_rcv-net-ipv6-ip6_inpu.patch \ file://patch-2.6.28.9/0001-bzip2-lzma-library-support-for-gzip-bzip2-and-lzma-d.patch \ file://patch-2.6.28.9/0002-bzip2-lzma-config-and-initramfs-support-for-bzip2-lz.patch \ + file://patch-2.6.28.9/0032-Create-snapshot-of-OpenBMC.patch \ " S = "${WORKDIR}/git" -LINUX_VERSION = "2.6.28.9" +LINUX_VERSION ?= "2.6.28.9" LINUX_VERSION_EXTENSION ?= "-aspeed" PR = "r1" +PV = "${LINUX_VERSION}" + +include linux-aspeed.inc + +# Install bounds.h for external module install +# The default install script handles this. However, it looks for bounds.h from +# 'include/generated', which doesnot match 2.6.28, where the file is in +# 'include/linux'. +do_install[postfuncs] += "install_bounds_h" +install_bounds_h() { + kerneldir=${D}${KERNEL_SRC_PATH} + if [ -f include/linux/bounds.h ]; then + cp -l include/linux/bounds.h $kerneldir/include/linux/bounds.h + fi +} KERNEL_CONFIG_COMMAND = "oe_runmake wedge_defconfig && oe_runmake oldconfig" diff --git a/meta-facebook/meta-wedge/conf/machine/wedge.conf b/meta-facebook/meta-wedge/conf/machine/wedge.conf index 69f3a90..3ed8ec1 100644 --- a/meta-facebook/meta-wedge/conf/machine/wedge.conf +++ b/meta-facebook/meta-wedge/conf/machine/wedge.conf @@ -5,3 +5,8 @@ UBOOT_MACHINE_wedge = "wedge_config" require conf/machine/include/ast1250.inc + +# configuration for preferred version of packages +PREFERRED_VERSION_libipmi = "0.1" +PREFERRED_VERSION_ipmid = "0.1" +PREFERRED_VERSION_rest-api = "0.1" diff --git a/meta-facebook/meta-wedge/recipes-core/images/wedge-image.inc b/meta-facebook/meta-wedge/recipes-core/images/wedge-image.inc index 15a4252..7cd89de 100644 --- a/meta-facebook/meta-wedge/recipes-core/images/wedge-image.inc +++ b/meta-facebook/meta-wedge/recipes-core/images/wedge-image.inc @@ -39,9 +39,8 @@ NTP_PKGS = " \ # Include modules in rootfs IMAGE_INSTALL += " \ kernel-modules \ - u-boot \ u-boot-fw-utils \ - fbutils \ + openbmc-utils \ fan-ctrl \ rackmon \ watchdog-ctrl \ @@ -49,6 +48,8 @@ IMAGE_INSTALL += " \ sensor-setup \ usb-console \ oob-nic \ + lldp-util \ + bmc-log \ lmsensors-sensors \ wedge-eeprom \ sms-kcsd \ @@ -61,6 +62,7 @@ IMAGE_INSTALL += " \ ${NTP_PKGS} \ iproute2 \ dhcp-client \ + spatula \ " IMAGE_FEATURES += " \ diff --git a/meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/dhcpv6_down b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/dhcpv6_down new file mode 100644 index 0000000..a44deb4 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/dhcpv6_down @@ -0,0 +1,27 @@ +#!/bin/bash +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +pid="/var/run/dhclient6.${IFACE}.pid" + +if [ -f "${pid}" ]; then + kill -9 `cat ${pid}` 2>/dev/null +fi + +exit 0 diff --git a/meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/dhcpv6_up b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/dhcpv6_up new file mode 100644 index 0000000..6469b9f --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/files/dhcpv6_up @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +# only care about 'eth0' and 'oob' intf +[ "$IFACE" != "eth0" ] && [ "$IFACE" != "oob" ] && exit 0 + +pid="/var/run/dhclient6.${IFACE}.pid" + +dhclient -6 -nw -pf ${pid} ${IFACE} + +exit 0 diff --git a/meta-facebook/meta-wedge/recipes-core/init-ifupdown/init-ifupdown_%.bbappend b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/init-ifupdown_%.bbappend index 7d74521..e715c27 100644 --- a/meta-facebook/meta-wedge/recipes-core/init-ifupdown/init-ifupdown_%.bbappend +++ b/meta-facebook/meta-wedge/recipes-core/init-ifupdown/init-ifupdown_%.bbappend @@ -1,2 +1,18 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += "file://dhcpv6_up \ + file://dhcpv6_down \ + " + +do_install_append() { + # rules to request dhcpv6 + install -d ${D}/${sysconfdir}/network/if-up.d + install -m 755 ${WORKDIR}/dhcpv6_up ${D}${sysconfdir}/network/if-up.d/dhcpv6_up + install -d ${D}/${sysconfdir}/network/if-down.d + install -m 755 ${WORKDIR}/dhcpv6_down ${D}${sysconfdir}/network/if-down.d/dhcpv6_down +} + +FILES_${PN} += "${sysconfdir}/network/if-up.d/dhcpv6_up \ + ${sysconfdir}/network/if-down.d/dhcpv6_down \ + " diff --git a/meta-facebook/meta-wedge/recipes-kernel/linux/linux-aspeed_2.6%.bbappend b/meta-facebook/meta-wedge/recipes-kernel/linux/linux-aspeed_2.6%.bbappend index 6bf04da..3c5b71c 100644 --- a/meta-facebook/meta-wedge/recipes-kernel/linux/linux-aspeed_2.6%.bbappend +++ b/meta-facebook/meta-wedge/recipes-kernel/linux/linux-aspeed_2.6%.bbappend @@ -2,4 +2,4 @@ LINUX_VERSION_EXTENSION = "-wedge" COMPATIBLE_MACHINE = "wedge" -KERNEL_DEFCONFIG_aspeed = "wedge_defconfig" +KERNEL_CONFIG_COMMAND = "oe_runmake wedge_defconfig && oe_runmake oldconfig" diff --git a/meta-facebook/meta-wedge/recipes-wedge/bmc-log/bmc-log_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/bmc-log_0.1.bb new file mode 100644 index 0000000..2788a36 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/bmc-log_0.1.bb @@ -0,0 +1,50 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +SUMMARY = "Logging Utility" +DESCRIPTION = "Util for logging" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://bmc-log.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI = "file://bmc-log.c \ + file://bmc-log.h \ + file://Makefile \ + file://bmc-log-config \ + file://bmc-log.sh \ + " + +S = "${WORKDIR}" + +do_install() { + install -d ${D}${sbindir} + install -m 755 bmc-log ${D}${sbindir}/bmc-log + install -d ${D}${sysconfdir}/default + install -m 755 bmc-log-config ${D}${sysconfdir}/default/bmc-log + install -d ${D}${sysconfdir}/init.d + install -m 755 bmc-log.sh ${D}${sysconfdir}/init.d/bmc-log.sh + update-rc.d -r ${D} bmc-log.sh start 92 S . +} + +FILES_${PN} = "${sbindir} ${sysconfdir} " + +# Inhibit complaints about .debug directories + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/Makefile b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/Makefile new file mode 100644 index 0000000..5004556 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/Makefile @@ -0,0 +1,24 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +LIBS = -lutil + +all: + ${CC} ${CFLAGS} -o bmc-log bmc-log.c ${LIBS} + +clean: + rm -rf *.o bmc-log diff --git a/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log-config b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log-config new file mode 100644 index 0000000..529adf2 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log-config @@ -0,0 +1,16 @@ +# Configuration used by bmc-log script + +#Serial port connected to the micro-server +US_TTY="" + +#IP version of the log collecting server +LOG_SERVER_IP_VERSION="" + +#Host name of the log collecting server +LOG_SERVER_NAME="" + +#Port number of the log collecting server +LOG_SERVER_PORT="" + +#Baud rate to set for the US_TTY +TTY_BAUD_RATE="" diff --git a/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log.c b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log.c new file mode 100644 index 0000000..078db7b --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log.c @@ -0,0 +1,559 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdbool.h> +#include <unistd.h> +#include <string.h> +#include <linux/serial.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/param.h> +#include <time.h> +#include <arpa/inet.h> +#include <sys/stat.h> +#include <pty.h> +#include <errno.h> +#include <signal.h> +#include <netinet/in.h> +#include <netdb.h> +#include "bmc-log.h" + +FILE *error_file = NULL; + +bool kill_received = false; // To check if a killing interrupt is received + +speed_t baud_rate = B57600; // Default baud rate - change if user inputs a different one + +int fd_tty = -1, fd_soc = -1; + +/* Hostname and port of the server */ +char *hostname; +int port; + +struct termios orig_tty_state; + +char *get_time() +{ + static char mytime[TIME_FORMAT_SIZE]; + memset(mytime, 0, sizeof(mytime)); + time_t this_time; + struct tm *this_tm; + this_time = time(NULL); + this_tm = localtime(&this_time); + + snprintf(mytime, sizeof(mytime), "%04d-%02d-%02d %02d:%02d:%02d", + 1900 + this_tm->tm_year, this_tm->tm_mon + 1, + this_tm->tm_mday, this_tm->tm_hour, + this_tm->tm_min, this_tm->tm_sec); + return mytime; +} + +void errlog(char *frmt, ...) +{ + va_list args; + va_start(args, frmt); + struct stat st; + + char *time_now = get_time(); + + fprintf(stderr, "[%s] ", time_now); + vfprintf(stderr, frmt, args); + + if (error_file) { + stat(error_log_file, &st); + if (st.st_size >= MAX_LOG_FILE_SIZE) { + truncate(error_log_file, 0); + } + fprintf(error_file, "[%s] ", time_now); + vfprintf(error_file, frmt, args); + fflush(error_file); + } +} + +/* Get the address info of netcons server */ +struct addrinfo *get_addr_info(int ip_version) +{ + int ip_family = (ip_version == IPV4) ? AF_INET : AF_INET6; + struct addrinfo hints; + + struct addrinfo *result; + result = malloc(sizeof(*result)); + if (!result) { + errlog("Error: Unable to allocate memory - %m\n"); + return NULL; + } + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = ip_family; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ + hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ + hints.ai_protocol = 0; /* Any protocol */ + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + if (getaddrinfo(hostname, NULL, &hints, &result)) { + errlog("Error: getaddrinfo failed - %m\n"); + return NULL; + } + + return result; +} + +/* Prepare Ipv4 Socket */ +bool prepare_sock(struct sockaddr_in * tgt_addr) +{ + struct addrinfo *addr_info; + memset(tgt_addr, 0, sizeof(*tgt_addr)); + + if ((addr_info = get_addr_info(IPV4)) == NULL) { + errlog("Error: Unable to get address info\n"); + return false; + } + + tgt_addr->sin_addr = ((struct sockaddr_in *)addr_info->ai_addr)->sin_addr; + tgt_addr->sin_port = htons(port); + tgt_addr->sin_family = AF_INET; + + return true; +} + +/* Prepare Ipv6 Socket */ +bool prepare_sock6(struct sockaddr_in6 * tgt_addr6) +{ + struct addrinfo *addr_info; + memset(tgt_addr6, 0, sizeof(*tgt_addr6)); + + if ((addr_info = get_addr_info(IPV6)) == NULL) { + errlog("Erorr: Unable to get address info\n"); + return false; + } + + tgt_addr6->sin6_addr = ((struct sockaddr_in6 *)addr_info->ai_addr)->sin6_addr; + tgt_addr6->sin6_port = htons(port); + tgt_addr6->sin6_family = AF_INET6; + + return true; +} + +/* Set TTY to raw mode */ +bool set_tty(int fd) +{ + struct termios tty_state; + + if (tcgetattr(fd, &tty_state) < 0) { + return false; + } + + if (tcgetattr(fd, &orig_tty_state) < 0) // Save original settings + { + return false; + } + + if (cfsetspeed(&tty_state, baud_rate) == -1) { + errlog("Error: Baud Rate not set - %m\n"); + return false; + } + + tty_state.c_lflag &= ~(ICANON | IEXTEN | ISIG | ECHO); + tty_state.c_iflag &= ~(IGNCR | ICRNL | INPCK | ISTRIP | IXON | BRKINT); + tty_state.c_iflag |= (IGNCR | ICRNL); + tty_state.c_oflag &= ~OPOST; + tty_state.c_cflag |= CS8; + + tty_state.c_cc[VMIN] = 1; + tty_state.c_cc[VTIME] = 0; + + if (tcsetattr(fd, TCSAFLUSH, &tty_state) < 0) { + return false; + } + + return true; +} + +/* Create a pseudo terminal for other process to use (as this program is using up the actual TTY) */ +int create_pseudo_tty() +{ + int amaster, aslave; + int flags; + + if (openpty(&amaster, &aslave, NULL, NULL, NULL) == -1) { + errlog("Error: Openpty failed - %m\n"); + return -1; + } + + /* Set to non blocking mode */ + flags = fcntl(amaster, F_GETFL); + flags |= O_NONBLOCK; + fcntl(amaster, F_SETFL, flags); + + FILE *pseudo_save_file = fopen(pseudo_tty_save_file, "w+"); + if (!pseudo_save_file) { + errlog("Error: Unable to open the pseudo info file - %m\n"); + return -1; + } + /* Save the name of the created pseudo tty in a text file for other processes to use */ + if (fprintf(pseudo_save_file, "%s\n", ttyname(aslave)) == -1) { + errlog("Error writing to the pseudo info file\n"); + fclose(pseudo_save_file); + return -1; + } + fclose(pseudo_save_file); + + if (set_tty(aslave) == -1) { + errlog("Error: Slave TTY not set properly\n"); + return -1; + } + + return amaster; +} + +/* Prepare logs from the read_buf and send them to the server */ +bool prepare_log_send(char *read_buf, int max_read, int fd_socket) +{ + size_t buff_index = 0; // Index for the read_buf string + + static char line[LINE_LEN] = { 0 }; + static size_t line_index = 0; // Index for the line string + + char msg[MSG_LEN] = { 0 }; // Message to be sent to the server + + /* Kernel Version */ + static char kernel_version[KERNEL_VERSION_LEN] = "dummy_kernel"; + static int kernel_search_pos = 0; + + while (buff_index < max_read && read_buf[buff_index] != '\0') { + if (read_buf[buff_index] == 'L') // Check if there is a possibility of new kernel version + { + kernel_search_pos = line_index; + } + + /* Send the log when a line is read */ + if (read_buf[buff_index] == '\n') { + if (kernel_search_pos > 0) { + if (strncmp(line + kernel_search_pos, "Linux version ", kernel_search_len) == 0) { + sscanf(line + kernel_search_pos + kernel_search_len, "%s", kernel_version); + } + kernel_search_pos = 0; + } + + /* Prepare the message */ + memset(msg, 0, sizeof(msg)); + if (snprintf(msg, sizeof(msg), "%s %s %s %s", "kernel:", kernel_version, "- msg", line) < 0) { + errlog("Error copying the message - %m\n"); + return false; + } + + /* Send message to the server */ + if (write(fd_socket, msg, strlen(msg)) < 0) { + errlog("Error: Write to socket failed - %m\n"); + return false; + } + + /* Reset the line buffer */ + line_index = 0; + memset(line, 0, sizeof(line)); + + buff_index++; + continue; + } + + /* If line is too big, send only the first few bytes and discard others. */ + if (line_index >= sizeof(line)) { + line[line_index - 1] = 0; + buff_index++; + continue; + } + + line[line_index++] = read_buf[buff_index++]; + } + + return true; +} + +/* Read text from the TTY and send to send as logs */ +bool read_send(int fd_tty, int fd_socket) +{ + char read_buf[LINE_LEN] = { 0 }; // Buffer to be read into. + int read_size = 0; + fd_set readset; + int sel; + int fdmax; + + int pseudo_tty = create_pseudo_tty(); + + if (pseudo_tty == -1) { + errlog("Error: Cannot create a psuedo terminal\n"); + return false; + } + + fdmax = MAX(fd_tty, pseudo_tty); + + while (!kill_received) { + do { + FD_ZERO(&readset); + FD_SET(fd_tty, &readset); + FD_SET(pseudo_tty, &readset); + + sel = select(fdmax + 1, &readset, NULL, NULL, NULL); + } + while (sel == -1 && errno == EINTR && !kill_received); + + memset(read_buf, 0, sizeof(read_buf)); + if (FD_ISSET(fd_tty, &readset)) { + read_size = read(fd_tty, read_buf, sizeof(read_buf) - 1); + + if (read_size == 0) { + continue; + } + if (read_size < 0) { + if (errno == EAGAIN) { + continue; + } + errlog("Error: Read from tty failed - %m\n"); + return false; + } + + /* Send the read data to the pseudo terminal */ + if (write(pseudo_tty, read_buf, read_size) < 0) { + if (errno == EAGAIN) // Output buffer full - flush it. + { + tcflush(pseudo_tty, TCIOFLUSH); + continue; + } + + errlog("Error: Write to pseudo tty failed - %m\n"); + return false; + } + + /* Prepare log message and send to the server */ + if (!prepare_log_send(read_buf, sizeof(read_buf), fd_socket)) { + errlog("Error: Sending log failed - %m\n"); + return false; + } + } + /*if (FD_ISSET(fd_tty, &readset)) */ + if (kill_received) { + break; + } + + /* Check if there is an data in the pseudo terminal's buffer */ + if (FD_ISSET(pseudo_tty, &readset)) { + read_size = read(pseudo_tty, read_buf, sizeof(read_buf) - 1); + + if (read_size == 0) { + continue; + } + if (read_size < 0) { + if (errno == EAGAIN) { + continue; + } + errlog("Error: Read from pseudo tty failed - %m\n"); + return false; + } + + if (write(fd_tty, read_buf, read_size) < 0) { + if (errno == EAGAIN) // Output buffer full - flush it. + { + tcflush(fd_tty, TCIOFLUSH); + continue; + } + + errlog("Error: Write to tty failed - %m\n"); + return false; + } + } /*if (FD_ISSET(pseudo_tty,&readset)) */ + } /*while (!kill_received) */ + + return true; +} + +void cleanup() +{ + remove(pseudo_tty_save_file); + tcsetattr(fd_tty, TCSAFLUSH, &orig_tty_state); //Restore original settings + close(fd_tty); + close(fd_soc); + fclose(error_file); +} + +void sig_kill(int signum) +{ + kill_received = true; +} + +void register_kill() +{ + struct sigaction sigact; + sigset_t sigset; + + sigemptyset(&sigset); + memset(&sigact, 0, sizeof sigact); + sigact.sa_handler = sig_kill; + sigact.sa_mask = sigset; + + sigaction(SIGHUP, &sigact, NULL); + sigaction(SIGINT, &sigact, NULL); + sigaction(SIGQUIT, &sigact, NULL); + sigaction(SIGPIPE, &sigact, NULL); + sigaction(SIGTERM, &sigact, NULL); + sigaction(SIGKILL, &sigact, NULL); + sigaction(SIGABRT, &sigact, NULL); +} + +void usage(char *prog_name) +{ + printf("Usage:\n"); + printf("\t%s TTY ip_version(4 or 6) hostname port [baud rate (like 57600)]\n", prog_name); + printf("\t%s -h : For this help\n", prog_name); + printf("Example:\n\t./bmc-log /dev/ttyS1 4 netcons.any.facebook.com 1514\n"); + printf("\tOR\n\t./bmc-log /dev/ttyS1 6 netcons6.any.facebook.com 1514 57600\n"); +} + +bool parse_user_input(int nargs, char **args, char *read_tty, int read_tty_size, int *ip_version) +{ + if (nargs < 5) { + if ((nargs > 1) && ((strcmp(args[1], "-h") == 0) || (strcmp(args[1], "--help") == 0))) { + usage(args[0]); + return false; // Not an error but returning -1 for the main function to return + } + fprintf(stderr, "Error: Invalid number of arguments\n"); + usage(args[0]); + return false; + } + + if (strlen(args[1]) > read_tty_size) { + fprintf(stderr, "Error: TTY too long\n"); + usage(args[0]); + return false; + } + + /* TTT to read the logs from */ + strncpy(read_tty, args[1], read_tty_size); + + /* IP Version, IP Address and Port of the netcons server */ + *ip_version = atoi(args[2]); + if (*ip_version != IPV4 && *ip_version != IPV6) { + fprintf(stderr, "Error: Invalid IP Version input\n"); + usage(args[0]); + return false; + } + + hostname = args[3]; + port = atoi(args[4]); + + baud_rate = B57600; + if (nargs == 6) + baud_rate = atoi(args[5]); + + return true; +} + +int main(int argc, char **argv) +{ + char read_tty[TTY_LEN] = { 0 }; + int ip_version; + int socket_domain = AF_UNSPEC; + char cmd[COMMAND_LEN] = { 0 }; + + /* Open the error log file */ + error_file = fopen(error_log_file, "a+"); + if (!error_file) { + printf("Error: Unable to open log file - %m\n"); + return 1; + } + + /* Register actions upon interrupts */ + register_kill(); + + /* Parse the user input */ + if (!parse_user_input(argc, argv, read_tty, sizeof(read_tty), &ip_version)) { + return 2; + } + + snprintf(cmd, sizeof(cmd), "%s %s", uS_console, "connect"); + if (system(cmd) == -1) { + errlog("Error: Unable to connect to the micro-server\n"); + return 3; + } + + /* Create a socket to communicate with the netcons server */ + socket_domain = (ip_version == IPV4) ? AF_INET : AF_INET6; + fd_soc = socket(socket_domain, SOCK_DGRAM, 0); + if (fd_soc == -1) { + errlog("Error: Socket creation failed - %m\n"); + return 4; + } + + if (ip_version == IPV4) { /* IPv4 */ + struct sockaddr_in tgt_addr; + if (!prepare_sock(&tgt_addr)) { + close(fd_soc); + errlog("Error: Socket not valid\n"); + return 5; + } + + if (connect(fd_soc, (struct sockaddr *)&tgt_addr, sizeof(tgt_addr)) == -1) { + close(fd_soc); + errlog("Error: Socket connection failed - %m\n"); + return 6; + } + + } else { /* IPv6 */ + + struct sockaddr_in6 tgt_addr6; + if (!prepare_sock6(&tgt_addr6)) { + close(fd_soc); + errlog("Error: Socket not valid\n"); + return 5; + } + + if (connect(fd_soc, (struct sockaddr *)&tgt_addr6, sizeof(tgt_addr6)) == -1) { + close(fd_soc); + errlog("Error: Socket connection failed - %m\n"); + return 6; + } + } + + /* TTY Operations */ + if ((fd_tty = open(read_tty, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1) { + close(fd_soc); + errlog("Error: Serial Port %s open failed - %m\n", read_tty); + return 7; + } + + if (!set_tty(fd_tty)) { + errlog("Error: tty not set properly\n"); + cleanup(); + return 8; + } + + /* Read, prepare and send the logs */ + if (!read_send(fd_tty, fd_soc)) { + errlog("Error: Sending logs failed\n"); + cleanup(); + return 9; + } + + cleanup(); + return 0; +} diff --git a/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log.h b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log.h new file mode 100644 index 0000000..5795e6a --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log.h @@ -0,0 +1,46 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef BMC_LOG_H_ +#define BMC_LOG_H_ + +/* IP Version */ +#define IPV4 (4) +#define IPV6 (6) + +/* Search string for the kernel version */ +#define KERNEL_SEARCH_STR "Linux version " + +/* Size constants */ +#define TIME_FORMAT_SIZE (100) +#define MAX_LOG_FILE_SIZE (1024*1024*5) //5MB +#define TTY_LEN (50) +#define LINE_LEN (257) +#define MSG_LEN (1025) +#define COMMAND_LEN (100) +#define KERNEL_VERSION_LEN (100) + +static char *uS_console = "/usr/local/fbpackages/utils/us_console.sh"; + +static char *error_log_file = "/var/log/bmc-log"; + +static char *pseudo_tty_save_file = "/etc/us_pseudo_tty"; + +static int kernel_search_len = sizeof(KERNEL_SEARCH_STR) - 1; + +#endif diff --git a/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log.sh b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log.sh new file mode 100755 index 0000000..00bf63c --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/bmc-log/files/bmc-log.sh @@ -0,0 +1,77 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: bmc-log +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Collect micro-server kernel logs through serial port +### END INIT INFO + +. /etc/default/bmc-log +. /etc/init.d/functions + +DAEMON=/usr/sbin/bmc-log +NAME=bmc-log +DESC="Micro-Server log collection" + +TTY=${US_TTY:-/dev/ttyS1} +IP=${LOG_SERVER_IP_VERSION:-4} +LOG_SERVER=${LOG_SERVER_NAME:-} +PORT=${LOG_SERVER_PORT:-} +BAUD_RATE=${TTY_BAUD_RATE:-} + +if [ -z "$LOG_SERVER" ] || [ -z "$PORT" ] +then + echo "Error: Server and/or port not set" + exit 0 +fi + + +ACTION="$1" + +case "$ACTION" in + start) + echo -e "Starting $DESC" + $DAEMON $TTY $IP $LOG_SERVER $PORT $BAUD_RATE + ;; + stop) + echo -e "Stopping $DESC: " + start-stop-daemon --stop --quiet --exec $DAEMON + ;; + restart|force-reload) + echo -e "Restarting $DESC: " + start-stop-daemon --stop --quiet --exec $DAEMON + sleep 1 + $DAEMON $TTY $IP $LOG_SERVER $PORT $BAUD_RATE + ;; + status) + stat $DAEMON + exit $? + ;; + *) + N=${0##*/} + N=${N#[SK]??} + echo "Usage: $N {start|stop|status|restart|force-reload}" >&2 + exit 1 + ;; +esac diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/setup-fan.sh b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/setup-fan.sh index 0cbdb24..146a787 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/setup-fan.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl/setup-fan.sh @@ -2,6 +2,22 @@ # # Copyright 2014-present Facebook. All Rights Reserved. # +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + ### BEGIN INIT INFO # Provides: setup-fan # Required-Start: board-id @@ -11,7 +27,7 @@ # Short-Description: Set fan speed ### END INIT INFO -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh # Enable the isolation buffer wedge_iso_buf_enable diff --git a/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bbappend b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bbappend new file mode 100644 index 0000000..ef2932e --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/fan-ctrl/fan-ctrl_0.1.bbappend @@ -0,0 +1,64 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +DEPENDS_append = "libwedge-eeprom update-rc.d-native" + +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" +SRC_URI += "file://get_fan_speed.sh \ + file://init_pwm.sh \ + file://set_fan_speed.sh \ + file://setup-fan.sh \ + " + +S = "${WORKDIR}" + +binfiles += "get_fan_speed.sh \ + init_pwm.sh \ + set_fan_speed.sh \ + " + +LDFLAGS_append = " -lwedge_eeprom" +CXXFLAGS_prepend = "-DCONFIG_WEDGE " + +pkgdir = "fan_ctrl" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${dst}/$f + ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f + done + for f in ${otherfiles}; do + install -m 644 $f ${dst}/$f + done + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-fan.sh ${D}${sysconfdir}/init.d/setup-fan.sh + update-rc.d -r ${D} setup-fan.sh start 91 S . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/fan_ctrl ${prefix}/local/bin ${sysconfdir} " + +# Inhibit complaints about .debug directories for the fand binary: + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/Makefile b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/Makefile index 74ce8f3..2f27a8c 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/Makefile +++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/alert_control/Makefile @@ -1,8 +1,24 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + lib: libalert_control.so libalert_control.so: alert_control.c - $(CC) $(CCFLAGS) -fPIC -c -o alert_control.o alert_control.c + $(CC) $(CFLAGS) -fPIC -c -o alert_control.o alert_control.c $(CC) -shared -o libalert_control.so alert_control.o -lc .PHONY: clean diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/Makefile b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/Makefile index 8cb69e7..369819c 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/Makefile +++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/files/ipmi/Makefile @@ -1,8 +1,24 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + lib: libipmi.so libipmi.so: ipmi.c - $(CC) $(CCFLAGS) -fPIC -c -o ipmi.o ipmi.c + $(CC) $(CFLAGS) -fPIC -c -o ipmi.o ipmi.c $(CC) -shared -o libipmi.so ipmi.o -lc .PHONY: clean diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/libalert-control_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/fblibs/libalert-control_0.1.bb index 2ae4ea7..ec02d04 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fblibs/libalert-control_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/libalert-control_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "Wedge Alert Control Library" DESCRIPTION = "library for Wedge Alert Control" SECTION = "base" @@ -20,5 +35,4 @@ do_install() { } FILES_${PN} = "${libdir}/libalert_control.so" -FILES_${PN}-dbg = "${libdir}/.debug" FILES_${PN}-dev = "${includedir}/facebook/alert_control.h" diff --git a/meta-facebook/meta-wedge/recipes-wedge/fblibs/libipmi_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/fblibs/libipmi_0.1.bb index 0b6f3d3..83292be 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fblibs/libipmi_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/fblibs/libipmi_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "Wedge IPMI Client Library" DESCRIPTION = "library for Wedge IPMI Client" SECTION = "base" @@ -21,5 +36,4 @@ do_install() { } FILES_${PN} = "${libdir}/libipmi.so" -FILES_${PN}-dbg = "${libdir}/.debug" FILES_${PN}-dev = "${includedir}/facebook/ipmi.h" diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93cx6.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93cx6.py new file mode 100644 index 0000000..514a06b --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93cx6.py @@ -0,0 +1,318 @@ +# Copyright 2004-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +import subprocess +import struct +import sys + + +AT93C46 = 'at93c46' +AT93C56 = 'at93c56' +AT93C66 = 'at93c66' +AT93C86 = 'at93c86' + + +class VerboseLogger: + def __init__(self, verbose=False): + self.verbose = verbose + + def _verbose_print(self, caption, bytestream=None): + ''' + Print a bytestream to stdout if verbose is enabled. + ''' + if self.verbose: + if bytestream is not None: + sys.stderr.write( + "{}: {}\n" .format( + caption, " ".join(['{:02X}'.format(ord(x)) + for x in bytestream]))) + else: + sys.stderr.write("{}\n".format(caption)) + + +class AT93CX6SPI(VerboseLogger): + '''The class to access AT93CX6 through SPI intf''' + SPI_CMD = 'spi-bb' + + def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di, + model, verbose=False): + addr_bits_map = { + AT93C46 : 6, + AT93C56 : 8, + AT93C66 : 8, + AT93C86 : 10, + } + if bus_width != 8 and bus_width != 16: + raise Exception("Invalid bus width for AT93CX6!") + if model not in addr_bits_map: + raise Exception("Invalid model '%s'" % model) + + self.bus_width = bus_width + self.gpio_cs = gpio_cs + self.gpio_ck = gpio_ck + self.gpio_do = gpio_do + self.gpio_di = gpio_di + self.verbose = verbose + + self.addr_bits = addr_bits_map[model] \ + + (0 if self.bus_width == 16 else 1) + self.addr_mask = (1 << self.addr_bits) - 1 + + def __shift(self, bytestream, value): + ''' + Shift an entire byte stream by value bits. + ''' + binary = "".join(['{:08b}'.format(ord(x)) for x in bytestream]) + if value > 0: + binary = binary[value:] + '0' * value + else: + binary = '0' * (-value) + binary[:value] + return "".join([chr(int(binary[x:x+8],2)) + for x in range(0, len(binary), 8)]) + + def __io(self, op, addr, data=None): + ''' + Perform an IO operation against the EEPROM + ''' + write_bits = self.addr_bits + 3 + if data is not None: + # If giving data, we are doing a write command so + # no need to read any data. + write_bits = write_bits + self.bus_width + read_bits = 0 + else: + # If not giving data, we are doing either a read + # command or a set command, so read the result. + # We pad with an extra bit due to a dummy bit introduced + # by a delay for address decoding on chip. + read_bits = self.addr_bits + 4 + self.bus_width + + # Format the command itself + instruction = addr & self.addr_mask + instruction = instruction | ((0x4 | (op & 0x3)) << self.addr_bits) + if data is not None: + if self.bus_width == 16: + write_data = struct.pack(">HH", instruction, data & 0xFFFF) + else: + write_data = struct.pack(">HB", instruction, data & 0xFF) + else: + write_data = struct.pack(">H", instruction) + write_data = self.__shift(write_data, 16 - (self.addr_bits + 3)) + + self._verbose_print("Write data", write_data) + + # Run the command with the bitbang driver + if read_bits > 0: + data_portion = "-r {} -w {}".format(read_bits, write_bits) + else: + data_portion = "-w {}".format(write_bits) + + cmd = "{} -s {} -c {} -o {} -i {} -b {}".format( + self.SPI_CMD, self.gpio_cs, self.gpio_ck, self.gpio_do, + self.gpio_di, data_portion + ) + + self._verbose_print("Command: {}".format(cmd)) + + out = subprocess.Popen(cmd.split(), + stdout=subprocess.PIPE, + stdin = subprocess.PIPE)\ + .communicate(input=write_data) + + # Format the response + read_data = self.__shift(out[0], self.addr_bits + 4) + if self.bus_width == 16: + read_data = read_data[:2] + self._verbose_print("Read data", read_data) + return struct.unpack(">H", read_data)[0] + else: + read_data = read_data[:1] + self._verbose_print("Read data", read_data) + return struct.unpack(">B", read_data)[0] + + def read(self, addr): + return self.__io(0x2, addr) + + def ewen(self): + self.__io(0x0, 0x3 << (self.addr_bits - 2)) + + def erase(self, addr): + self.__io(0x3, addr) + + def write(self, addr, data): + self.__io(0x1, addr, data) + + def eral(self): + self.__io(0x0, 0x2 << (self.addr_bits - 2)) + + def wral(self, data): + self.__io(0x0, 0x1 << (self.addr_bits - 2), data) + + def ewds(self): + self.__io(0x0, 0x0) + + +class AT93CX6(VerboseLogger): + ''' + The class which handles accessing memory on the AT93CX6 chip. + ''' + + def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di, + byte_swap, model=AT93C46, verbose=False): + mem_size_map = { + # in bytes + AT93C46 : 128, + AT93C56 : 256, + AT93C66 : 512, + AT93C86 : 2048, + } + self.bus_width = bus_width + self.verbose = verbose + self.byte_swap = byte_swap + self.model = model + self.memory_size = mem_size_map[model] + + self.spi = AT93CX6SPI(bus_width=bus_width, gpio_cs=gpio_cs, + gpio_ck=gpio_ck, gpio_do=gpio_do, + gpio_di=gpio_di, model=model, + verbose=verbose) + + def __swap(self, value): + ''' + Swap bytes for a 16-bit integer if instructed to do so. + ''' + if self.bus_width == 16: + if self.byte_swap: + return ((value >> 8) & 0xFF) | ((value << 8) & 0xFF00) + else: + return value + else: + return value + + def get_memory_size(self): + return self.memory_size + + def erase(self, offset=None, limit=None): + ''' + Erase the chip. + ''' + if offset is None: + offset = 0 + if limit is None: + limit = self.memory_size + + if offset < 0 or offset + limit > self.memory_size: + raise Exception("Erase would be out of bounds!") + if self.bus_width == 16 and \ + ((offset & 1) != 0 or ((offset + limit) & 1) != 0): + raise Exception("Erase can't start or end on odd boundary in " + "16-bit mode!") + + if offset == 0 and limit == self.memory_size: + # Special case when we are erasing the entire chip + self.spi.ewen() + self.spi.eral() + self.spi.ewds() + + self._verbose_print("Erased entire chip") + else: + # Regular case + if self.bus_width == 16: + real_offset = offset / 2 + real_limit = limit / 2 + else: + real_offset = offset + real_limit = limit + + self.spi.ewen() + for addr in range(real_offset, real_offset + real_limit): + self.spi.erase(addr) + self.spi.ewds() + + self._verbose_print("Erased {} bytes from offset {}" + .format(limit, offset)) + + def read(self, offset=None, limit=None): + ''' + Read the chip into a memory buffer. + ''' + if offset is None: + offset = 0 + if limit is None: + limit = self.memory_size + + if offset < 0 or offset + limit > self.memory_size: + raise Exception("Read would be out of bounds!") + if self.bus_width == 16 and \ + ((offset & 1) != 0 or ((offset + limit) & 1) != 0): + raise Exception("Read can't start or end on odd boundary in 16-bit " + "mode!") + + output = "" + if self.bus_width == 16: + real_offset = offset / 2 + real_limit = limit / 2 + pack_instruction = "=H" + else: + real_offset = offset + real_offset + pack_instruction = "=B" + + for addr in range(real_offset, real_offset + real_limit): + output = output + struct.pack(pack_instruction, + self.__swap(self.spi.read(addr))) + + self._verbose_print("Read {} bytes from offset {}".format(limit, offset) + , output) + + return output + + def write(self, data, offset=None): + ''' + Write a memory buffer to the chip. + ''' + if offset is None: + offset = 0 + + if offset < 0 or offset + len(data) > self.memory_size: + raise Exception("Write would be out of bounds!") + if self.bus_width == 16 and \ + ((offset & 1) != 0 or ((offset + len(data)) & 1) != 0): + raise Exception("Write can't start or end on odd boundary in " + "16-bit mode!") + + if self.bus_width == 16: + offset_divisor = 2 + pack_instruction = "=H" + else: + offset_divisor = 1 + pack_instruction = "=B" + + self.spi.ewen() + for addr in range(offset, offset + len(data), offset_divisor): + actual_addr = addr / offset_divisor + value = self.__swap(struct.unpack( + pack_instruction, data[(addr - offset):(addr - offset) + + offset_divisor])[0]) + + self.spi.erase(actual_addr) + self.spi.write(actual_addr, value) + self.spi.ewds() + + self._verbose_print("Wrote {} bytes from offset {}" + .format(len(data), offset), data) diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93cx6_util.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93cx6_util.py new file mode 100755 index 0000000..8ae7664 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/at93cx6_util.py @@ -0,0 +1,223 @@ +#!/usr/bin/python -S +# Copyright 2004-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + + +from argparse import ArgumentParser +import at93cx6 +import sys + + +def get_raw(args): + return at93cx6.AT93CX6SPI( + args.bus_width, args.cs, args.clk, args.mosi, args.miso, + args.model, args.verbose) + +def get_chip(args): + return at93cx6.AT93CX6( + args.bus_width, args.cs, args.clk, args.mosi, args.miso, + args.byte_swap if hasattr(args, 'byte_swap') else None, + args.model, args.verbose) + +def model_parser(ap): + # Default, based on currenct HW configuration + MODEL_DEFAULT = at93cx6.AT93C46 + + ap.add_argument('--model', default=at93cx6.AT93C46, + choices=[at93cx6.AT93C46, at93cx6.AT93C56, + at93cx6.AT93C66, at93cx6.AT93C86], + help='The chip model (default: %(default)s)') + +def access_parser(ap): + # Default, based on currenct HW configuration + SPI_CS_DEFAULT = 68 + SPI_CLK_DEFAULT = 69 + SPI_MOSI_DEFAULT = 70 + SPI_MISO_DEFAULT = 71 + + spi_group = ap.add_argument_group('SPI Access') + spi_group.add_argument('--cs', type=int, default=SPI_CS_DEFAULT, + help='The GPIO number for SPI CS pin ' + '(default: %(default)s)') + spi_group.add_argument('--clk', type=int, default=SPI_CLK_DEFAULT, + help='The GPIO number for SPI CLK pin ' + '(default: %(default)s)') + spi_group.add_argument('--mosi', type=int, default=SPI_MOSI_DEFAULT, + help='The GPIO number for SPI MOSI pin ' + '(default: %(default)s)') + spi_group.add_argument('--miso', type=int, default=SPI_MISO_DEFAULT, + help='The GPIO number for SPI MISO pin ' + '(default: %(default)s)') + +def bus_width_parser(ap): + # Default, based on currenct HW configuration + AT83C46_BUS_WIDTH = 16 + + bus_group = ap.add_argument_group('Bus Width') + bus_group.add_argument('--bus-width', type=int, default=AT83C46_BUS_WIDTH, + help='The configured bus width ' + '(default: %(default)s)') + +def read_raw(args): + raw = get_raw(args) + val = raw.read(args.address) + + if args.int: + print "{}".format(val) + else: + if args.bus_width == 16: + print "0x{:04X}".format(val) + else: + print "0x{:02X}".format(val) + +def write_raw(args): + if args.value[:2] == "0x": + value = int(args.value, 16) + else: + value = int(args.value) + + raw = get_raw(args) + raw.ewen() + raw.erase(args.address) + raw.write(args.address, value) + raw.ewds() + +def erase_raw(args): + raw = get_raw(args) + raw.ewen() + raw.erase(args.address) + raw.ewds() + +def raw_subparser(subparsers): + raw_parser = subparsers.add_parser( + 'raw', help='Raw memory access') + raw_sub = raw_parser.add_subparsers() + + read_parser = raw_sub.add_parser( + 'read', help='Read a single memory address') + read_parser.add_argument( + 'address', type=int, help='The memory address') + read_parser.add_argument('--int', action='store_true', + help='Display output as an integer') + read_parser.set_defaults(func=read_raw) + + write_parser = raw_sub.add_parser( + 'write', help='Write a single memory address') + write_parser.add_argument( + 'address', type=int, help='The memory address') + write_parser.add_argument( + 'value', type=str, help='The value to write, either integer or hex') + write_parser.set_defaults(func=write_raw) + + erase_parser = raw_sub.add_parser( + 'erase', help='Erase a single memory address') + erase_parser.add_argument('address', type=int, help='The memory address') + erase_parser.set_defaults(func=erase_raw) + +def read_chip(args): + chip = get_chip(args) + data = chip.read(args.start, args.length) + + if args.file is None: + sys.stdout.write(data) + else: + with open(args.file, "wb") as fp: + fp.write(data) + +def write_chip(args): + chip = get_chip(args) + + # Either way, limit reads to the size of the chip + if args.file is None: + data = sys.stdin.read(chip.get_memory_size()) + else: + with open(args.file, "rb") as fp: + data = fp.read(chip.get_memory_size()) + + if args.length is not None: + # Make sure length is correct + if len(data) < args.length: + data = data + '\x00' * (args.length - len(data)) + if len(data) > args.length: + data = data[:args.length] + + chip.write(data, args.start) + +def erase_chip(args): + chip = get_chip(args) + chip.erase(args.start, args.length) + +def chip_subparser(subparsers): + chip_parser = subparsers.add_parser('chip', help='Chip-level access') + chip_sub = chip_parser.add_subparsers() + + read_parser = chip_sub.add_parser('read', help='Read from the chip') + read_parser.add_argument('--start', type=int, + help='The memory address to start at (default: 0)') + read_parser.add_argument('--length', type=int, + help='The number of bytes to read ' + '(default: whole chip)') + read_parser.add_argument('--file', type=str, + help='File to operate on (default: stdout)') + read_parser.add_argument('--byte-swap', default=False, action='store_true', + help='Byte swap values for 16-bit reads/writes ' + '(default: %(default)s)') + read_parser.set_defaults(func=read_chip) + + write_parser = chip_sub.add_parser('write', help='Write to the chip') + write_parser.add_argument('--start', type=int, + help='The memory address to start at ' + '(default: 0)') + write_parser.add_argument('--length', type=int, + help='The number of bytes to write ' + '(default: file length)') + write_parser.add_argument('--file', type=str, + help='File to operate on (default: stdin)') + write_parser.add_argument('--byte-swap', default=False, action='store_true', + help='Byte swap values for 16-bit reads/writes ' + '(default: %(default)s)') + write_parser.set_defaults(func=write_chip) + + erase_parser = chip_sub.add_parser('erase', help='Erase the chip') + erase_parser.add_argument('--start', type=int, + help='The memory address to start at ' + '(default: 0)') + erase_parser.add_argument('--length', type=int, + help='The number of bytes to erase ' + '(default: whole chip)') + erase_parser.set_defaults(func=erase_chip) + +if __name__ == "__main__": + # General arguments + ap = ArgumentParser() + ap.add_argument('--verbose', action='store_true', + help='Print verbose debugging information') + + # Model, SPI, and bus width arguments + model_parser(ap) + access_parser(ap) + bus_width_parser(ap) + + # Functionality + subparsers = ap.add_subparsers() + raw_subparser(subparsers) + chip_subparser(subparsers) + + # Command runner + args = ap.parse_args() + args.func(args) diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py index e1aba47..91d9a85 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396.py @@ -16,10 +16,13 @@ # 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301 USA # +from __future__ import print_function + import subprocess import time + class Bcm5396MDIO: '''The class to access BCM5396 through MDIO intf''' MDIO_CMD = 'mdio-bb' @@ -254,23 +257,35 @@ class Bcm5396SPI: except Exception as e: print(e) + class Bcm5396: '''The class for BCM5396 Switch''' MDIO_ACCESS = 0 SPI_ACCESS = 1 - def __init__(self, access, **kwargs): + def __init__(self, access, verbose=False, **kwargs): + self.verbose = verbose if access == self.MDIO_ACCESS: self.access = Bcm5396MDIO(**kwargs) else: self.access = Bcm5396SPI(**kwargs) def write(self, page, reg, value, n_bytes): + if self.verbose: + print('WRITE {:2x} {:2x} {:2x} '.format(page, reg, n_bytes), end='') + bytes = '{:2x}'.format(value) + print([bytes[i:i+2] for i in range(0, len(bytes), 2)][-n_bytes:]) return self.access.write(page, reg, value, n_bytes) def read(self, page, reg, n_bytes): - return self.access.read(page, reg, n_bytes) + if self.verbose: + print('READ {:2x} {:2x} {:2x} '.format(page, reg, n_bytes), end='') + result = self.access.read(page, reg, n_bytes) + if self.verbose: + bytes = '{:2x}'.format(result) + print([bytes[i:i+2] for i in range(0, len(bytes), 2)][-n_bytes:]) + return result def __add_remove_vlan(self, add, vid, untag, fwd, spt): VLAN_PAGE = 0x5 diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py index 1496412..0759b08 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/bcm5396_util.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python -tt # Copyright 2004-present Facebook. All rights reserved. # # This program file is free software; you can redistribute it and/or modify it @@ -29,9 +29,11 @@ def auto_int(x): def get_bcm(args): if args.spi: return Bcm5396(Bcm5396.SPI_ACCESS, cs=args.cs, clk=args.clk, - mosi=args.mosi, miso=args.miso) + mosi=args.mosi, miso=args.miso, + verbose=args.verbose) else: - return Bcm5396(Bcm5396.MDIO_ACCESS, mdc=args.mdc, mdio=args.mdio) + return Bcm5396(Bcm5396.MDIO_ACCESS, mdc=args.mdc, mdio=args.mdio, + verbose=args.verbose) def read_register(args): @@ -249,6 +251,10 @@ def access_parser(ap): if __name__ == '__main__': ap = ArgumentParser() + ap.add_argument('-v', '--verbose', action='store_true', + help='Dump the switch page, register, and value ' + 'for each operation') + access_parser(ap) subparsers = ap.add_subparsers() diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/board-utils.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/board-utils.sh new file mode 100644 index 0000000..e4d34aa --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/board-utils.sh @@ -0,0 +1,163 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +wedge_iso_buf_enable() { + # GPIOC2 (18) to low, SCU90[0] and SCU90[24] must be 0 + devmem_clear_bit $(scu_addr 90) 0 + devmem_clear_bit $(scu_addr 90) 24 + gpio_set 18 0 +} + +wedge_iso_buf_disable() { + # GPIOC2 (18) to low, SCU90[0] and SCU90[24] must be 0 + devmem_clear_bit $(scu_addr 90) 0 + devmem_clear_bit $(scu_addr 90) 24 + gpio_set 18 1 +} + +wedge_is_us_on() { + local val n retries prog + if [ $# -gt 0 ]; then + retries="$1" + else + retries=1 + fi + if [ $# -gt 1 ]; then + prog="$2" + else + prog="" + fi + if [ $# -gt 2 ]; then + default=$3 # value 0 means defaul is 'ON' + else + default=1 + fi + n=1 + while true; do + val=$(cat /sys/class/i2c-adapter/i2c-4/4-0040/gpio_inputs 2>/dev/null) + if [ -n "$val" ]; then + break + fi + n=$((n+1)) + if [ $n -gt $retries ]; then + echo -n " failed to read GPIO. " + return $default + break + fi + echo -n "$prog" + sleep 1 + done + if [ "$((val & (0x1 << 14)))" != "0" ]; then + # powered on already + return 0 + else + return 1 + fi +} + + +# Return the board type, 'LC', 'FC-LEFT', 'FC-RIGHT', or, 'WEDGE' +wedge_board_type() { + local pn + pn=$(/usr/bin/weutil 2> /dev/null | grep -i '^Location on Fabric:') + case "$pn" in + *LEFT*) + echo 'FC-LEFT' + ;; + *RIGHT*) + echo 'FC-RIGHT' + ;; + *LC*) + echo 'LC' + ;; + *) + echo 'WEDGE' + ;; + esac +} + +# On FC, +# board rev < 2: +# FAB_SLOT_ID (GPIOU0), low == FC0; high == FC1 +# else: +# FAB_SLOT_ID (GPIOU6), low == FC0; high == FC1 +## On LC, Wedge, +# board rev < 3: +# GPIOU0(ID0), GPIOU1(ID1), GPIOU2(ID2), GPIOU3(ID3) +# else: +# GPIOU6(ID0), GPIOU7(ID1), GPIOV0(ID2), GPIOV1(ID3) +# +# ID[2:0] ID3 Slot# +# 000 0 1 +# 000 1 2 +# 001 0 3 +# 001 1 4 +# 010 0 5 +# 010 1 6 +# 011 0 7 +# 011 1 8 + +wedge_slot_id() { + local type slot id3 id2 id1 id0 FC_CARD_BASE board_rev + FC_CARD_BASE=65 + # need to check the board rev + board_rev=$(wedge_board_rev) + case "$1" in + FC-LEFT|FC-RIGHT) + # On FC + if [ $board_rev -lt 2 ]; then + slot=$(gpio_get U0) + else + slot=$(gpio_get U6) + fi + if [ "$1" = "FC-LEFT" ]; then + # fabric card left + slot=$((FC_CARD_BASE + slot * 2)) + else + # fabric card right + slot=$((FC_CARD_BASE + slot * 2 + 1)) + fi + ;; + *) + # either edge or LC + if [ $board_rev -lt 3 ]; then + id0=$(gpio_get U0) + id1=$(gpio_get U1) + id2=$(gpio_get U2) + id3=$(gpio_get U3) + else + id0=$(gpio_get U6) + id1=$(gpio_get U7) + id2=$(gpio_get V0) + id3=$(gpio_get V1) + fi + slot=$(((id2 * 4 + id1 * 2 + id0) * 2 + id3 + 1)) + esac + echo "$slot" +} + +# wedge_board_rev() is only valid after GPIO Y0, Y1, and Y2 are enabled +wedge_board_rev() { + local val0 val1 val2 + val0=$(cat /sys/class/gpio/gpio192/value 2>/dev/null) + val1=$(cat /sys/class/gpio/gpio193/value 2>/dev/null) + val2=$(cat /sys/class/gpio/gpio194/value 2>/dev/null) + echo $((val0 | (val1 << 1) | (val2 << 2))) +} + +# Should we enable OOB interface or not +wedge_should_enable_oob() { + board_rev=$(wedge_board_rev) + board_type=$(wedge_board_type) + case "$board_type" in + FC-LEFT|FC-RIGHT) + if [ $board_rev -lt 2 ]; then + return 0 + fi + ;; + *) + if [ $board_rev -lt 3 ]; then + return 0 + fi + ;; + esac + return -1 +} diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf index 2cf7a9a..8c7e74b 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/create_vlan_intf @@ -21,7 +21,7 @@ # only care about 'eth0' and 'oob' intf [ "$IFACE" != "eth0" ] && [ "$IFACE" != "oob" ] && exit 0 -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh board=$(wedge_board_type) diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh index 1cdbcb6..f244bd0 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/eth0_mac_fixup.sh @@ -29,13 +29,27 @@ PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin +# get the MAC from EEPROM mac=$(weutil 2>/dev/null | grep '^Local MAC' 2>/dev/null | cut -d' ' -f3 2>/dev/null) +# get the MAC from u-boot environment +ethaddr=$(fw_printenv ethaddr 2>/dev/null | cut -d'=' -f2 2>/dev/null) + +if [ -z "$mac" ] && [ -n "$ethaddr" ]; then + # no MAC from EEPROM, use the one from u-boot environment + mac="$ethaddr" +fi + if [ -n "$mac" ]; then ifconfig eth0 hw ether $mac - # compare the 'ethaddr' from u-boot env - ethaddr=$(fw_printenv ethaddr 2>/dev/null | cut -d'=' -f2 2>/dev/null) - if [ "$ethaddr" != "$mac" ]; then - fw_setenv "ethaddr" "$mac" - fi +else + # no MAC from either EEPROM or u-boot environment + mac=$(ifconfig eth0 2>/dev/null |grep HWaddr 2>/dev/null |awk '{ print $5 }') + +fi + +if [ "$ethaddr" != "$mac" ]; then + # set the MAC from EEPROM or ifconfig back to u-boot environment so that u-boot + # can use it + fw_setenv "ethaddr" "$mac" fi diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh index c23349f..b653cb3 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/post_led.sh @@ -24,7 +24,7 @@ usage() { echo "Usage: $0 <value>" } -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh # Function to set the less significant hex digit display_lower() { diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh index 843b79a..ace3c6a 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power-on.sh @@ -25,7 +25,7 @@ # Default-Stop: # Short-Description: Power on micro-server ### END INIT INFO -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh index 20206a1..066646e 100755 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/power_led.sh @@ -23,7 +23,7 @@ usage() { exit -1 } -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh PATH=/sbin:/bin:/usr/sbin:/usr/bin diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh index 7d1c2c6..c63ed10 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/reset_usb.sh @@ -18,7 +18,7 @@ # Boston, MA 02110-1301 USA # -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh echo -n "Reset USB Switch ... " diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh index 9f0b543..717bcd8 100755 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup-gpio.sh @@ -39,7 +39,7 @@ # When defined, the system doesn't reboot cleanly. We're still # investigating this. -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh # Set up to read the board revision pins, Y0, Y1, Y2 devmem_set_bit $(scu_addr 70) 19 @@ -182,8 +182,8 @@ devmem_set_bit $(scu_addr 70) 13 # GPIOQ5 is ISO_FLASH_HOLD, must be 1 to be out of reset # To use GPIOQ4 and GPIOQ5, SCU90[27] must be 0 devmem_clear_bit $(scu_addr 90) 27 -gpio_set 134 1 -gpio_set 135 1 +gpio_set Q4 1 +gpio_set Q5 1 # GPIOD6 is ISO_FL_PRG_SEL, set it to 0 so that BMC does not have control # on the EEPROM by default. # To use GPIOD6, SCU90[1] must be 0, SCU8C[21] must be 0, and Strap[21] must be 0 @@ -244,31 +244,139 @@ board_type=$(wedge_board_type) case "$board_type" in FC-LEFT|FC-RIGHT) # On FC - # FAB_SLOT_ID is GPIOU0 - # PEER_FAB_PRSNT is GPIOU1 - devmem_set_bit $(scu_addr a0) 8 - devmem_set_bit $(scu_addr a0) 9 - gpio_export U0 - gpio_export U1 - # T2_POWER_UP is GPIOT6 - devmem_set_bit $(scu_addr a0) 6 - gpio_export T6 - # HS_FAULT_N is GPIOT7 - devmem_set_bit $(scu_addr a0) 7 - gpio_export T7 - if [ "$board_type" = "FC-LEFT" ]; then - # GPIOE2 is CPU_EEPROM_SEL, on FC-LEFT - devmem_clear_bit $(scu_addr 80) 18 - devmem_clear_bit $(scu_addr 8c) 13 - devmem_clear_bit $(scu_addr 70) 22 - gpio_export E2 - # GPIOA6 and GPIOA7 are MAC2 MDIO pins, we use them as - # GPIO for bitbang driver - devmem_clear_bit $(scu_addr 90) 2 - devmem_clear_bit $(scu_addr 80) 6 - devmem_clear_bit $(scu_addr 80) 7 - gpio_export A6 - gpio_export A7 + if [ $board_rev -lt 2 ]; then + # EVT board + # FAB_SLOT_ID is GPIOU0 + # PEER_FAB_PRSNT is GPIOU1 + devmem_set_bit $(scu_addr a0) 8 + devmem_set_bit $(scu_addr a0) 9 + gpio_export U0 + gpio_export U1 + # T2_POWER_UP is GPIOT6 + devmem_set_bit $(scu_addr a0) 6 + gpio_export T6 T2_POWER_UP + # HS_FAULT_N is GPIOT7 + devmem_set_bit $(scu_addr a0) 7 + gpio_export T7 + if [ "$board_type" = "FC-LEFT" ]; then + # GPIOE2 is CPU_EEPROM_SEL, on FC-LEFT + devmem_clear_bit $(scu_addr 80) 18 + devmem_clear_bit $(scu_addr 8c) 13 + devmem_clear_bit $(scu_addr 70) 22 + gpio_export E2 + # GPIOA6 and GPIOA7 are MAC2 MDIO pins, we use them as + # GPIO for bitbang driver + devmem_clear_bit $(scu_addr 90) 2 + devmem_clear_bit $(scu_addr 80) 6 + devmem_clear_bit $(scu_addr 80) 7 + gpio_export A6 + gpio_export A7 + fi + else + # DVT board + if [ "$board_type" = "FC-LEFT" ]; then # Left FC + # BMC_SW_RST is GPIOL0, 16p switch + # SCU84[16] must be 0 + devmem_clear_bit $(scu_addr 84) 16 + gpio_set L0 1 + + # MDC|MDIO_CONT are GPIOR6 and GPIOR7, 16p switch + # SCU88[30:31] must be 0 + devmem_clear_bit $(scu_addr 88) 30 + devmem_clear_bit $(scu_addr 88) 31 + gpio_set R6 1 + gpio_set R7 1 + + # SWITCH_EEPROM1_WRT is GPIOE2, 16p switch EEPROM (U61) + # SCU80[18], SCU8C[13], and SCU70[22] must be 0 + devmem_clear_bit $(scu_addr 80) 18 + devmem_clear_bit $(scu_addr 8C) 13 + devmem_clear_bit $(scu_addr 70) 22 + gpio_export E2 + + # SPI bus to 16p switch EEPROM + # GPIOI4 <--> BMC_EEPROM1_SPI_SS + # GPIOI5 <--> BMC_EEPROM1_SPI_SCK + # GPIOI6 <--> BMC_EEPROM1_SPI_MOSI + # GPIOI7 <--> BMC_EEPROM1_SPI_MISO + # The EEPROM SPI clk does not match with the BMC SPI master. + # Have to configure these pins as GPIO to use with + # SPI bitbang driver. + # SCU70[13:12,5] must be 0 + devmem_clear_bit $(scu_addr 70) 5 + devmem_clear_bit $(scu_addr 70) 12 + devmem_clear_bit $(scu_addr 70) 13 + gpio_export I4 + gpio_export I5 + gpio_export I6 + gpio_export I7 + + # BMC_PHY_RST is GPIOT0, Front Panel Port PHY on the 16p switch + # SCUA0[0] must be 1 + devmem_set_bit $(scu_addr a0) 0 + gpio_set T0 1 + + # BMC_5PORTSW_RST is GPIOT1, 5p switch + # SCUA0[1] must be 1 + devmem_set_bit $(scu_addr a0) 1 + gpio_set T1 1 + + # ISO_SWITCH1_MDC|MDIO are GPIOT4 and GPIOT5, 5p switch + # SCUA0[4:5] must be 1 + devmem_set_bit $(scu_addr a0) 4 + devmem_set_bit $(scu_addr a0) 5 + gpio_set T4 1 + gpio_set T5 1 + + # ISO_SWITCH_EEPROM2_WRT is GPIOV0, 5p switch EEPROM (U114) + # SCUA0[16] must be 1 + devmem_set_bit $(scu_addr a0) 16 + gpio_export V0 + + # SPI bus to 5p switch EEPROM (U114) + # GPIOI0 <--> ISO_BMC_EEPROM2_SPI_SS + # GPIOI1 <--> ISO_BMC_EEPROM2_SPI_SCK + # GPIOI2 <--> ISO_BMC_EEPROM2_SPI_MOSI + # GPIOI3 <--> ISO_BMC_EEPROM2_SPI_MISO + # The EEPROM SPI clk does not match with the BMC SPI master. + # Have to configure these pins as GPIO to use with + # SPI bitbang driver. + # SCU70[13] must be 0, has already been set when + # preparing for GPIOI4-GPIOI7 + gpio_export I0 + gpio_export I1 + gpio_export I2 + gpio_export I3 + + # BMC_PHYL_RST is GPIOF0, Left BMC PHY + # SCU80[24] must be 0 + devmem_clear_bit $(scu_addr 80) 24 + gpio_set F0 1 + else # Right FC + # BMC_PHYR_RST is GPIOL1, Right BMC PHY + # SCU84[17] must be 0 + devmem_clear_bit $(scu_addr 84) 17 + gpio_set L1 1 + fi + # T2_POWER_UP is GPIOU4 + # SCUA0[12] must be 1 + devmem_set_bit $(scu_addr a0) 12 + gpio_export U4 T2_POWER_UP + + # HS_FAULT_N is GPIOU5 + # SCUA0[13] must be 1 + devmem_set_bit $(scu_addr a0) 13 + gpio_export U5 + + # FAB_SLOT_ID is GPIOU6 + # SCUA0[14] must be 1 + devmem_set_bit $(scu_addr a0) 14 + gpio_export U6 + + # PEER_FAB_PRSNT is GPIOU7 + # SCUA0[15] must be 1 + devmem_set_bit $(scu_addr a0) 15 + gpio_export U7 fi ;; *) @@ -289,7 +397,7 @@ case "$board_type" in gpio_export U3 # T2_POWER_UP is GPIOT6 devmem_set_bit $(scu_addr a0) 6 - gpio_export T6 + gpio_export T6 T2_POWER_UP # HS_FAULT_N is GPIOT7 devmem_set_bit $(scu_addr a0) 7 gpio_export T7 @@ -307,7 +415,7 @@ case "$board_type" in gpio_export V1 # T2_POWER_UP is GPIOU4 devmem_set_bit $(scu_addr a0) 12 - gpio_export U4 + gpio_export U4 T2_POWER_UP # HS_FAULT_N is GPIOU5 devmem_set_bit $(scu_addr a0) 13 gpio_export U5 diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh index 749fe65..1400464 100755 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/setup_rov.sh @@ -24,7 +24,7 @@ # outgoing voltage on the first buck converter, and bring T2 up out of # reset. -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh # read the T2 ROV after the GPIOs are enabled t2_rov() { diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh index ccbdc61..2998c81 100755 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/sol.sh @@ -18,7 +18,14 @@ # Boston, MA 02110-1301 USA # -CONSOLE_SH=/usr/local/fbpackages/utils/us_console.sh +CONSOLE_SH=/usr/local/bin/us_console.sh +FILE=/etc/us_pseudo_tty +TTY=/dev/ttyS1 + +if [ -a $FILE ] + then + read -r TTY<$FILE +fi $CONSOLE_SH connect @@ -29,7 +36,7 @@ echo trap '"$CONSOLE_SH" disconnect' INT TERM QUIT EXIT -/usr/bin/microcom -s 57600 /dev/ttyS1 +/usr/bin/microcom -s 57600 $TTY echo echo diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/start_us_monitor.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/start_us_monitor.sh new file mode 100644 index 0000000..19f3198 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/start_us_monitor.sh @@ -0,0 +1,73 @@ +#! /bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: us-monitor +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Start the microserver reset monitoring script +# +### END INIT INFO + +PATH=/sbin:/bin:/usr/sbin:/usr/bin +NAME="us_monitor" +DESC="monitoring microserver reset" +DAEMON="us_monitor.sh" + +# source function library +. /etc/init.d/functions + +. /usr/local/bin/openbmc-utils.sh + +STOPPER= +ACTION="$1" + +case "$ACTION" in + start) + echo -n "Starting $DESC: " + /usr/local/bin/${DAEMON} > /dev/null 2>&1 & + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + killall ${DAEMON} + echo "$NAME." + ;; + restart|force-reload) + echo -n "Restarting $DESC: " + killall ${DAEMON} + /usr/local/bin/${DAEMON} > /dev/null 2>&1 & + echo "$NAME." + ;; + status) + status ${DAEMON} + exit $? + ;; + *) + N=${0##*/} + N=${N#[SK]??} + echo "Usage: $N {start|stop|status|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh index 6f445ee..75bbcea 100755 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_console.sh @@ -22,7 +22,7 @@ usage() { echo "$0 <connect | disconnect>" } -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh if [ $# -ne 1 ]; then usage diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_monitor.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_monitor.sh new file mode 100644 index 0000000..b7a9cb6 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/us_monitor.sh @@ -0,0 +1,56 @@ +#!/bin/bash +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +. /usr/local/bin/openbmc-utils.sh + +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + +# Because the voltage leak from uS COM pins could cause uS to struck when +# transitting from S5 to S0, we will need to explicitely pull down uS COM +# pins before powering off/reset and restoring COM pins after + +pull_down_us_com() { + # set GPIOL6 and GPIOL7 low + devmem_clear_bit $(scu_addr 84) 22 + devmem_clear_bit $(scu_addr 84) 23 + gpio_set 94 0 + gpio_set 95 0 + # now, connect uart from BMC to the uS + gpio_set 32 1 +} + +restore_us_com() { + devmem_set_bit $(scu_addr 84) 22 + devmem_set_bit $(scu_addr 84) 23 + # if sol.sh is running, keep uart from uS connected with BMC + if pidof -x sol.sh > /dev/null 2>&1; then + gpio_set 32 1 + else + gpio_set 32 0 + fi +} + +while true; do + if ! wedge_is_us_on 1 '' 0 > /dev/null 2>&1; then + pull_down_us_com + else + restore_us_com + fi + usleep 400000 # 400ms +done diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh index 5ba5311..ce734ef 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/files/wedge_power.sh @@ -18,7 +18,7 @@ # Boston, MA 02110-1301 USA # -. /usr/local/fbpackages/utils/ast-functions +. /usr/local/bin/openbmc-utils.sh PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin @@ -43,31 +43,6 @@ usage() { echo } -# Because the voltage leak from uS COM pins could cause uS to struck when transitting -# from S5 to S0, we will need to explicitely pull down uS COM pins before powering off/reset -# and restoring COM pins after - -pull_down_us_com() { - # set GPIOL6 and GPIOL7 low - devmem_clear_bit $(scu_addr 84) 22 - devmem_clear_bit $(scu_addr 84) 23 - gpio_set 94 0 - gpio_set 95 0 - # now, connect uart from BMC to the uS - gpio_set 32 1 -} - -restore_us_com() { - devmem_set_bit $(scu_addr 84) 22 - devmem_set_bit $(scu_addr 84) 23 - # if sol.sh is running, keep uart from uS connected with BMC - if ps | grep sol.sh > /dev/null 2>&1; then - gpio_set 32 1 - else - gpio_set 32 0 - fi -} - do_status() { echo -n "Microserver power is " if wedge_is_us_on; then @@ -79,7 +54,7 @@ do_status() { } do_on() { - local force opt + local force opt pulse_us n retries force=0 while getopts "f" opt; do case $opt in @@ -103,14 +78,31 @@ do_on() { fi # first make sure, GPIOD1 (25) is high gpio_set 25 1 + sleep 1 # then, put GPIOP7 (127) to low gpio_set 127 0 - # generate the power on pulse - gpio_set 25 0 - sleep 1 - gpio_set 25 1 - sleep 1 - restore_us_com + pulse_us=500000 # 500ms + retries=3 + n=1 + while true; do + # first make sure, GPIOD1 (25) is high + gpio_set 25 1 + usleep $pulse_us + # generate the power on pulse + gpio_set 25 0 + usleep $pulse_us + gpio_set 25 1 + sleep 3 + if wedge_is_us_on 1 '' 1; then + break + fi + n=$((n+1)) + if [ $n -gt $retries ]; then + echo " Failed" + return 1 + fi + echo -n "..." + done # Turn on the power LED (GPIOE5) /usr/local/bin/power_led.sh on echo " Done" @@ -119,7 +111,6 @@ do_on() { do_off() { echo -n "Power off microserver ..." - pull_down_us_com # first make sure, GPIOD1 (25) is high gpio_set 25 1 # then, put GPIOP7 (127) to low @@ -158,14 +149,12 @@ do_reset() { return -1 fi echo -n "Power reset microserver ..." - pull_down_us_com # then, put GPIOP7 (127) to low gpio_set 127 0 gpio_set 17 0 sleep 1 gpio_set 17 1 sleep 1 - restore_us_com fi echo " Done" return 0 diff --git a/meta-facebook/meta-wedge/recipes-wedge/fbutils/openbmc-utils_%.bbappend b/meta-facebook/meta-wedge/recipes-wedge/fbutils/openbmc-utils_%.bbappend new file mode 100644 index 0000000..d6641c9 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/fbutils/openbmc-utils_%.bbappend @@ -0,0 +1,95 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += "file://board-utils.sh \ + file://us_console.sh \ + file://sol.sh \ + file://power_led.sh \ + file://post_led.sh \ + file://reset_usb.sh \ + file://setup-gpio.sh \ + file://setup_rov.sh \ + file://mdio.py \ + file://bcm5396.py \ + file://bcm5396_util.py \ + file://at93cx6.py \ + file://at93cx6_util.py \ + file://mount_data0.sh \ + file://eth0_mac_fixup.sh \ + file://wedge_power.sh \ + file://power-on.sh \ + file://wedge_us_mac.sh \ + file://setup_switch.py \ + file://create_vlan_intf \ + file://rc.early \ + file://rc.local \ + file://src \ + file://start_us_monitor.sh \ + file://us_monitor.sh \ + " + +OPENBMC_UTILS_FILES += " \ + board-utils.sh us_console.sh sol.sh power_led.sh post_led.sh \ + reset_usb.sh mdio.py setup_rov.sh wedge_power.sh wedge_us_mac.sh \ + bcm5396.py bcm5396_util.py setup_switch.py us_monitor.sh \ + at93cx6.py at93cx6_util.py \ + " + +DEPENDS_append = "update-rc.d-native" + +do_install_board() { + # for backward compatible, create /usr/local/fbpackages/utils/ast-functions + olddir="/usr/local/fbpackages/utils" + install -d ${D}${olddir} + ln -s "/usr/local/bin/openbmc-utils.sh" ${D}${olddir}/ast-functions + + # common lib and include files + install -d ${D}${includedir}/facebook + install -m 0644 src/include/i2c-dev.h ${D}${includedir}/facebook/i2c-dev.h + + # init + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + # the script to mount /mnt/data + install -m 0755 ${WORKDIR}/mount_data0.sh ${D}${sysconfdir}/init.d/mount_data0.sh + update-rc.d -r ${D} mount_data0.sh start 03 S . + install -m 0755 ${WORKDIR}/rc.early ${D}${sysconfdir}/init.d/rc.early + update-rc.d -r ${D} rc.early start 04 S . + install -m 755 setup-gpio.sh ${D}${sysconfdir}/init.d/setup-gpio.sh + update-rc.d -r ${D} setup-gpio.sh start 59 S . + # create VLAN intf automatically + install -d ${D}/${sysconfdir}/network/if-up.d + install -m 755 create_vlan_intf ${D}${sysconfdir}/network/if-up.d/create_vlan_intf + # networking is done after rcS, any start level within rcS + # for mac fixup should work + install -m 755 eth0_mac_fixup.sh ${D}${sysconfdir}/init.d/eth0_mac_fixup.sh + update-rc.d -r ${D} eth0_mac_fixup.sh start 70 S . + install -m 755 start_us_monitor.sh ${D}${sysconfdir}/init.d/start_us_monitor.sh + update-rc.d -r ${D} start_us_monitor.sh start 84 S . + install -m 755 power-on.sh ${D}${sysconfdir}/init.d/power-on.sh + update-rc.d -r ${D} power-on.sh start 85 S . + install -m 0755 ${WORKDIR}/rc.local ${D}${sysconfdir}/init.d/rc.local + update-rc.d -r ${D} rc.local start 99 2 3 4 5 . +} + +do_install_append() { + do_install_board +} + +FILES_${PN} += "${sysconfdir}" diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/Makefile b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/Makefile index 8282964..c21df07 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/Makefile +++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/Makefile @@ -1,4 +1,20 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + all: ipmid ipmid: ipmid.c \ diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/setup-ipmid.sh b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/setup-ipmid.sh index b1fbbb1..b724d70 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/setup-ipmid.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/files/setup-ipmid.sh @@ -2,6 +2,22 @@ # # Copyright 2014-present Facebook. All Rights Reserved. # +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + ### BEGIN INIT INFO # Provides: setup-ipmid # Required-Start: diff --git a/meta-facebook/meta-wedge/recipes-wedge/ipmid/ipmid_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/ipmid/ipmid_0.1.bb index 3f9c4a7..7d8fd37 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/ipmid/ipmid_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/ipmid/ipmid_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "IPMI Daemon" DESCRIPTION = "Daemon to handle IPMI Messages." diff --git a/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/lmsensors_%.bbappend b/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/lmsensors_%.bbappend index 35433ae..90a3954 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/lmsensors_%.bbappend +++ b/meta-facebook/meta-wedge/recipes-wedge/lm_sensors/lmsensors_%.bbappend @@ -4,7 +4,11 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:" SRC_URI += "file://wedge.conf \ " -do_install_append() { +do_install_board_config() { install -d ${D}${sysconfdir}/sensors.d install -m 644 ../wedge.conf ${D}${sysconfdir}/sensors.d/wedge.conf } + +do_install_append() { + do_install_board_config +} diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/Makefile b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/Makefile index 0c9f49f..00464e5 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/Makefile +++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/Makefile @@ -1,4 +1,20 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + all: oob-nic i2craw oob-nic: main.o nic.o intf.o ll_map.o libnetlink.o diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/etc/oob-nic.sh b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/etc/oob-nic.sh index 35e1a2a..7eaf581 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/etc/oob-nic.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/etc/oob-nic.sh @@ -40,14 +40,12 @@ DESC="OOB NIC Driver" test -f $DAEMON || exit 0 # enable the isolation buffer -. /usr/local/fbpackages/utils/ast-functions -wedge_iso_buf_enable +. /usr/local/bin/openbmc-utils.sh fix_etc_interfaces() { - local intf_conf rev - intf_conf="/etc/network/interfaces" - rev=$(wedge_board_rev) - if [ $rev -lt 3 ]; then + local intf_conf board_rev board_type enable_oob + if wedge_should_enable_oob; then + intf_conf="/etc/network/interfaces" if ! grep oob $intf_conf > /dev/null 2>&1; then echo >> $intf_conf echo "auto oob" >> $intf_conf diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/i2craw.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/i2craw.c index f9d499b..83f03b7 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/i2craw.c +++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/i2craw.c @@ -27,7 +27,7 @@ #include <stdint.h> #include "facebook/i2c-dev.h" -#include "facebook/log.h" +#include "openbmc/log.h" void usage(const char *prog) { printf("Usage: %s [options] <bus number> <slave address>\n", prog); diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.c index 5bf8480..81834b9 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.c +++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/intf.c @@ -32,7 +32,7 @@ #include <linux/if_tun.h> #include <linux/fib_rules.h> -#include "facebook/log.h" +#include "openbmc/log.h" #include "libnetlink.h" #include "ll_map.h" diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/main.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/main.c index 4312402..2dc1917 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/main.c +++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/main.c @@ -24,7 +24,7 @@ #include "nic.h" #include "intf.h" -#include "facebook/log.h" +#include "openbmc/log.h" #include "facebook/wedge_eeprom.h" #define WAIT4PACKET_TIMEOUT 10000 /* 10ms */ @@ -129,28 +129,40 @@ int main(int argc, const char **argv) { /* read EEPROM for the MAC */ if (wedge_eeprom_parse(NULL, &eeprom) == 0) { - if (eeprom.fbw_mac_size <= 0) { + uint16_t carry; + int pos; + int adj; + /* + * OOB MAC comes from this range. We pick the last MAC from the range to + * use as OOB MAC. + */ + if (eeprom.fbw_mac_size > 128) { + LOG_ERR(EFAULT, "Extended MAC size (%d) is too large.", + eeprom.fbw_mac_size); + carry = 128; + } else { + carry = eeprom.fbw_mac_size; + } + + /* + * Due to various manufacture issues, some FC boards have MAC range overlap + * between LEFT and RIGHT sides. A SW workaround is done below to use the + * 8th (or 7th for right side FC) last MAC from the range for FC. + */ + if (strncmp(eeprom.fbw_location, "LEFT", FBW_EEPROM_F_LOCATION) == 0) { + adj = 8; + } else if (strncmp(eeprom.fbw_location, "RIGHT", FBW_EEPROM_F_LOCATION) + == 0) { + adj = 7; + } else { + adj = 1; + } + + if (carry < adj) { LOG_ERR(EFAULT, "Invalid extended MAC size: %d", eeprom.fbw_mac_size); } else { - uint16_t carry; - int pos; - /* use the last MAC address from the extended MAC range */ + carry -= adj; memcpy(mac, eeprom.fbw_mac_base, sizeof(mac)); - if (eeprom.fbw_mac_size > 128) { - LOG_ERR(EFAULT, "Extended MAC size (%d) is too large.", - eeprom.fbw_mac_size); - carry = 127; - } else { - /* - * hack around bug device which have the same MAC address on - * left and right. - */ - if (strncmp(eeprom.fbw_location, "LEFT", FBW_EEPROM_F_LOCATION) == 0) { - carry = eeprom.fbw_mac_size - 2; - } else { - carry = eeprom.fbw_mac_size - 1; - } - } for (pos = sizeof(mac) - 1; pos >= 0 && carry; pos--) { uint16_t tmp = mac[pos] + carry; mac[pos] = tmp & 0xFF; diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.c b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.c index a4dc071..c5fa422 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.c +++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic.c @@ -17,6 +17,7 @@ */ #include "nic.h" +#include <arpa/inet.h> #include <errno.h> #include <fcntl.h> #include <stdlib.h> @@ -26,7 +27,9 @@ #include <sys/types.h> #include "facebook/i2c-dev.h" -#include "facebook/log.h" +#include "openbmc/log.h" + +#define ETHERTYPE_LLDP 0x88cc struct oob_nic_t { int on_bus; @@ -334,12 +337,25 @@ static int oob_nic_set_force_up(oob_nic *dev, int enable) { static int oob_nic_setup_filters(oob_nic *dev, const uint8_t mac[6]) { int rc; - int i; uint32_t cmd32; uint8_t buf[32]; uint8_t *cmd; /* + * There are 8 filters in total (MDEF0-MDEF7). Any filter that has a + * configuration will be applied. Any packet that matches any filter will + * be passed to OOB by the main NIC. + * + * Each filter has two sets of bits, MDEF and MDEF_EXT. Each bit in the + * filter represents a filter with its logical operation. For example, + * NIC_FILTER_MDEF_MAC_AND_OFFSET(0) represent MAC filter 0 using AND + * operation. So, in order to receive packets matching a specific MAC, MAC0 + * filter (NIC_FILTER_MAC_NUM:NIC_FILTER_MAC_PAIR0) must be programmed + * with the specific MAC. Then set NIC_FILTER_MDEF_MAC_AND_OFFSET (for + * AND) or NIC_FILTER_MDEF_MAC_OR_OFFSET (for OR) in one of the filters. + */ + + /* * Command to set MAC filter * Seven bytes are required to load the MAC address filters. * Data 2—MAC address filters pair number (3:0). @@ -351,9 +367,8 @@ static int oob_nic_setup_filters(oob_nic *dev, const uint8_t mac[6]) { cmd = buf; *cmd++ = NIC_FILTER_MAC_NUM; *cmd++ = NIC_FILTER_MAC_PAIR0; /* pair 0 */ - for (i = 0; i < 6; i++) { - *cmd++ = mac[i]; - } + memcpy(cmd, mac, 6); + cmd += 6; rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD, cmd - buf, buf); if (rc < 0) { @@ -380,17 +395,15 @@ static int oob_nic_setup_filters(oob_nic *dev, const uint8_t mac[6]) { *cmd++ = NIC_FILTER_DECISION_EXT_NUM; *cmd++ = NIC_FILTER_MDEF0; /* enable filter for traffic from network and host */ - cmd32 = NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_NET_EN_OFFSET) - | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET); - for (i = 0; i < sizeof(cmd32); i++) { - *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; - } + cmd32 = htonl(NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_NET_EN_OFFSET) + | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET)); + memcpy(cmd, &cmd32, sizeof(cmd32)); + cmd += sizeof(cmd32); /* enable mac pair 0 */ - cmd32 = NIC_FILTER_MDEF_BIT_VAL(NIC_FILTER_MDEF_MAC_AND_OFFSET, - NIC_FILTER_MAC_PAIR0); - for (i = 0; i < sizeof(cmd32); i++) { - *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; - } + cmd32 = htonl(NIC_FILTER_MDEF_BIT_VAL(NIC_FILTER_MDEF_MAC_AND_OFFSET, + NIC_FILTER_MAC_PAIR0)); + memcpy(cmd, &cmd32, sizeof(cmd32)); + cmd += sizeof(cmd32); rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD, cmd - buf, buf); if (rc < 0) { @@ -398,23 +411,41 @@ static int oob_nic_setup_filters(oob_nic *dev, const uint8_t mac[6]) { LOG_ERR(rc, "Failed to set MAC filter to MDEF 0"); return -rc; } - /* enable ARP and ND on filter 1*/ + + /* Program EtherType0 to match LLDP */ + cmd = buf; + *cmd++ = NIC_FILTER_ETHERTYPE_NUM; + *cmd++ = NIC_FILTER_ETHERTYPE0; + cmd32 = htonl(ETHERTYPE_LLDP); + memcpy(cmd, &cmd32, sizeof(cmd32)); + cmd += sizeof(cmd32); + rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD, + cmd - buf, buf); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to program EtherType0 to match LLDP"); + return -rc; + } + + /* enable ARP, ND, and EtheryType0 (OR) on filter 1 */ cmd = buf; *cmd++ = NIC_FILTER_DECISION_EXT_NUM; *cmd++ = NIC_FILTER_MDEF1; - /* enable filter for traffic from network and host */ - cmd32 = NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_NET_EN_OFFSET) - | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET); - for (i = 0; i < sizeof(cmd32); i++) { - *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; - } + /* enable filter for traffic from network and host, matching ethertype0 */ + cmd32 = htonl(NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_NET_EN_OFFSET) + | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET) + | NIC_FILTER_MDEF_BIT_VAL( + NIC_FILTER_MDEF_EXT_ETHTYPE_OR_OFFSET, + NIC_FILTER_ETHERTYPE0)); + memcpy(cmd, &cmd32, sizeof(cmd32)); + cmd += sizeof(cmd32); + /* enable ARP and ND */ - cmd32 = NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_ARP_REQ_OR_OFFSET) - | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_ARP_RES_OR_OFFSET) - | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_NBG_OR_OFFSET); - for (i = 0; i < sizeof(cmd32); i++) { - *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; - } + cmd32 = htonl(NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_ARP_REQ_OR_OFFSET) + | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_ARP_RES_OR_OFFSET) + | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_NBG_OR_OFFSET)); + memcpy(cmd, &cmd32, sizeof(cmd32)); + cmd += sizeof(cmd32); rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD, cmd - buf, buf); if (rc < 0) { @@ -426,10 +457,9 @@ static int oob_nic_setup_filters(oob_nic *dev, const uint8_t mac[6]) { /* make filter 0, matching MAC, to be mng only */ cmd = buf; *cmd++ = NIC_FILTER_MNG_ONLY_NUM; - cmd32 = NIC_FILTER_MNG_ONLY_FILTER0; - for (i = 0; i < sizeof(cmd32); i++) { - *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; - } + cmd32 = htonl(NIC_FILTER_MNG_ONLY_FILTER0); + memcpy(cmd, &cmd32, sizeof(cmd32)); + cmd += sizeof(cmd32); rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD, cmd - buf, buf); if (rc < 0) { diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic_defs.h b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic_defs.h index 1ae8721..87574f0 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic_defs.h +++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic/src/nic_defs.h @@ -76,12 +76,6 @@ struct oob_nic_status_t { /** Update MNG RCV Filter Parameters */ #define NIC_WRITE_FILTER_CMD 0xCC -#define NIC_FILTER_MAC_NUM 0x66 -#define NIC_FILTER_MAC_PAIR0 0 -#define NIC_FILTER_MAC_PAIR1 1 -#define NIC_FILTER_MAC_PAIR2 2 -#define NIC_FILTER_MAC_PAIR3 3 - #define NIC_FILTER_MNG_ONLY_NUM 0xF #define NIC_FILTER_MNG_ONLY_FILTER0 (0x1) #define NIC_FILTER_MNG_ONLY_FILTER1 (0x1 << 1) @@ -89,6 +83,18 @@ struct oob_nic_status_t { #define NIC_FILTER_MNG_ONLY_FILTER3 (0x1 << 3) #define NIC_FILTER_MNG_ONLY_FILTER4 (0x1 << 4) +#define NIC_FILTER_MAC_NUM 0x66 +#define NIC_FILTER_MAC_PAIR0 0 +#define NIC_FILTER_MAC_PAIR1 1 +#define NIC_FILTER_MAC_PAIR2 2 +#define NIC_FILTER_MAC_PAIR3 3 + +#define NIC_FILTER_ETHERTYPE_NUM 0x67 +#define NIC_FILTER_ETHERTYPE0 0 +#define NIC_FILTER_ETHERTYPE1 1 +#define NIC_FILTER_ETHERTYPE2 2 +#define NIC_FILTER_ETHERTYPE3 3 + #define NIC_FILTER_DECISION_EXT_NUM 0x68 #define NIC_FILTER_MDEF0 0 /* index 0 */ #define NIC_FILTER_MDEF1 1 /* index 1 */ diff --git a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic_0.1.bb index 1df83dc..82a5296 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/oob-nic/oob-nic_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "OOB Shared NIC driver" DESCRIPTION = "The shared-nic driver" @@ -12,7 +27,7 @@ SRC_URI = "file://src \ S = "${WORKDIR}/src" -DEPENDS += "fbutils libwedge-eeprom" +DEPENDS += "openbmc-utils liblog libwedge-eeprom" RDEPENDS_${PN} += "libwedge-eeprom" diff --git a/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/Makefile b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/Makefile index 408de95..0b3fd71 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/Makefile +++ b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/files/Makefile @@ -1,4 +1,20 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + all: po-eeprom po-eeprom: po-eeprom.o diff --git a/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/po-eeprom_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/po-eeprom_0.1.bb index e1d8b32..ad635dc 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/po-eeprom_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/po-eeprom/po-eeprom_0.1.bb @@ -1,4 +1,21 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + SUMMARY = "PowerOne EEPROM Utilities" DESCRIPTION = "Util for PowerOne eeprom" SECTION = "base" diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile index 4a3c25d..926bf52 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/Makefile @@ -1,16 +1,40 @@ # Copyright 2014-present Facebook. All Rights Reserved. -all: modbuscmd gpiowatch modbussim +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +override CFLAGS+=-D_GNU_SOURCE -D_BSD_SOURCE -D_POSIX_C_SOURCE=199309 -Wall -Werror -std=c99 +override LDFLAGS+=-pthread +all: modbuscmd gpiowatch modbussim rackmond rackmondata + +rackmondata: rackmondata.c modbus.c + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +rackmond: rackmond.c modbus.c + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) modbuscmd: modbuscmd.c modbus.c - $(CC) -D_BSD_SOURCE -Wall -Werror -std=c99 -o $@ $^ $(LDFLAGS) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) modbussim: modbussim.c modbus.c - $(CC) -D_BSD_SOURCE -Wall -Werror -std=c99 -o $@ $^ $(LDFLAGS) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) gpiowatch: gpiowatch.c - $(CC) -D_BSD_SOURCE -Wall -Werror -std=c99 -o $@ $^ $(LDFLAGS) + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) .PHONY: clean clean: - rm -rf *.o modbuscmd gpiowatch modbussim + rm -rf *.o modbuscmd gpiowatch modbussim rackmond rackmondata diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/hexfile.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/hexfile.py new file mode 100644 index 0000000..c484fdf --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/hexfile.py @@ -0,0 +1,174 @@ +# The MIT License (MIT) +# ===================== +# +# Copyright (c) 2014 Ryan Sturmer +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# https://github.com/ryansturmer/hexfile/blob/master/hexfile/core.py + +import itertools + +def short(msb,lsb): + return (msb<<8) | lsb + +class HexFile(object): + def __init__(self, segments): + self.segments = segments + + def __getitem__(self, val): + if isinstance(val, slice): + address = val.start + else: + address = val + + for segment in self.segments: + if address in segment: + return segment[val] + + raise IndexError('No segment contains address 0x%x' % address) + + def __len__(self): + return sum(map(len, self.segments)) + + @property + def size(self): + return len(self) + + def __iter__(self): + return itertools.chain(*self.segments) + + @staticmethod + def load(filename): + segments = [Segment(0)] + + with open(filename) as fp: + lines = fp.readlines() + + extended_linear_address = 0 + current_address = 0 + end_of_file = False + + lineno = 0 + for line in lines: + lineno += 1 + line = line.strip(); + if not line.startswith(':'): + continue + + if end_of_file: + raise Exception("Record found after end of file on line %d" % lineno) + + bytes = [int(line[i:i+2], 16) for i in range(1,len(line), 2)] + byte_count = bytes[0] + address = short(*bytes[1:3]) + record_type = bytes[3] + checksum = bytes[-1] + data = bytes[4:-1] + computed_checksum = ((1 << 8)-(sum(bytes[:-1]) & 0xff)) & 0xff + + if(computed_checksum != checksum): + raise Exception("Record checksum doesn't match on line %d" % lineno) + + if record_type == 0: + if byte_count == len(data): + current_address = (address | extended_linear_address) + have_segment = False + for segment in segments: + if segment.end_address == current_address: + segment.data.extend(data) + have_segment = True + break + if not have_segment: + segments.append(Segment(current_address, data)) + else: + raise Exception("Data record reported size does not match actual size on line %d" % lineno) + elif record_type == 1: + end_of_file = True + elif record_type == 4: + if byte_count != 2 or len(data) != 2: + raise Exception("Byte count misreported in extended linear address record on line %d" % lineno) + extended_linear_address = short(*data) << 16 + + else: + raise Exception("Unknown record type: %s" % record_type) + return HexFile(segments) + + def pretty_string(self, stride=16): + retval = [] + for segment in self.segments: + retval.append('Segment @ 0x%08x (%d bytes)' % (segment.start_address, segment.size)) + retval.append(segment.pretty_string(stride=stride)) + retval.append('') + return '\n'.join(retval) + +def load(filename): + return HexFile.load(filename) + +class Segment(object): + def __init__(self, start_address, data = None): + self.start_address = start_address + self.data = data or [] + + def pretty_string(self, stride=16): + retval = [] + addresses = self.addresses + ranges = [addresses[i:i+stride] for i in range(0, self.size, stride)] + for r in ranges: + retval.append('%08x ' % r[0] + ' '.join(['%02x' % self[addr] for addr in r])) + return '\n'.join(retval) + + def __str__(self): + return '<%d byte segment @ 0x%08x>' % (self.size, self.start_address) + def __repr__(self): + return str(self) + + @property + def end_address(self): + return self.start_address + len(self.data) + + @property + def size(self): + return len(self.data) + + def __contains__(self, address): + return address >= self.start_address and address < self.end_address + + def __getitem__(self, address): + if isinstance(address, slice): + if address.start not in self or address.stop-1 not in self: + raise IndexError('Address out of range for this segment') + else: + d = self.data[address.start-self.start_address:address.stop-self.start_address:address.step] + start_address = address.start + self.start_address + return Segment(start_address, d) + else: + if not address in self: + raise IndexError("Address 0x%x is not in this segment" % address) + return self.data[address-self.start_address] + + @property + def addresses(self): + return range(self.start_address, self.end_address) + + def __len__(self): + return len(self.data) + + def __iter__(self): + return iter(self.data) diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c index 46618a9..8fb0835 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.c @@ -16,6 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <time.h> #include "modbus.h" #include <termios.h> #include <unistd.h> @@ -26,9 +27,15 @@ #include <string.h> #include <errno.h> #include <sys/ioctl.h> +#include <sched.h> +#include <pthread.h> -static int loops = 0; -void waitfd(int fd) { +int verbose = 0; + +#define TIOCSERWAITTEMT 0x5499 +int waitfd(int fd) { + int loops = 0; + ioctl(fd, TIOCSERWAITTEMT, DEFAULT_GPIO); while(1) { int lsr; int ret = ioctl(fd, TIOCSERGETLSR, &lsr); @@ -37,8 +44,10 @@ void waitfd(int fd) { break; } if(lsr & TIOCSER_TEMT) break; + // never should hit this with new ioctl loops++; } + return loops; } void gpio_on(int fd) { @@ -60,8 +69,7 @@ void decode_hex_in_place(char* buf, size_t* len) { void append_modbus_crc16(char* buf, size_t* len) { uint16_t crc = modbus_crc16(buf, *len); - if (verbose) - fprintf(stderr, "[*] Append Modbus CRC16 %04x\n", crc); + dbg("[*] Append Modbus CRC16 %04x\n", crc); buf[(*len)++] = crc >> 8; buf[(*len)++] = crc & 0x00FF; } @@ -78,7 +86,7 @@ size_t read_wait(int fd, char* dst, size_t maxlen, int mdelay_us) { size_t read_size = 0; size_t pos = 0; memset(dst, 0, maxlen); - for(;;) { + while(pos < maxlen) { FD_ZERO(&fdset); FD_SET(fd, &fdset); timeout.tv_sec = 0; @@ -95,10 +103,11 @@ size_t read_wait(int fd, char* dst, size_t maxlen, int mdelay_us) { fprintf(stderr, "read error: %s\n", strerror(errno)); exit(1); } - if((pos + read_size) < maxlen) { + if((pos + read_size) <= maxlen) { memcpy(dst + pos, read_buf, read_size); pos += read_size; } else { + return pos; fprintf(stderr, "Response buffer overflowed!\n"); } } @@ -181,3 +190,163 @@ uint16_t modbus_crc16(char* buffer, size_t buffer_length) { return (crc_hi << 8 | crc_lo); } + + +double ts_diff (struct timespec* begin, struct timespec* end) { + return 1000.0 * (end->tv_sec) + (1e-6 * end->tv_nsec) + - (1000.0 * (begin->tv_sec) + (1e-6 * begin->tv_nsec)); +} + +static long success = 0; +static long crcfail = 0; +static long timeout = 0; +static long stat_wait = 0; + +int modbuscmd(modbus_req *req) { + int error = 0; + struct termios tio; + char modbus_cmd[req->cmd_len + 2]; + size_t cmd_len = req->cmd_len; + + if (verbose) + fprintf(stderr, "[*] Setting TTY flags!\n"); + memset(&tio, 0, sizeof(tio)); + // CREAD should be left *off* until we've confirmed THRE + // to avoid catching false character starts + cfsetspeed(&tio,B19200); + tio.c_cflag |= PARENB; + tio.c_cflag |= CLOCAL; + tio.c_cflag |= CS8; + tio.c_iflag |= INPCK; + tio.c_cc[VMIN] = 1; + tio.c_cc[VTIME] = 0; + CHECK(tcsetattr(req->tty_fd,TCSANOW,&tio)); + + memcpy(modbus_cmd, req->modbus_cmd, cmd_len); + append_modbus_crc16(modbus_cmd, &cmd_len); + + // print command as sent + if (verbose) { + fprintf(stderr, "Will send: "); + print_hex(stderr, modbus_cmd, cmd_len); + fprintf(stderr, "\n"); + } + + dbg("[*] Writing!\n"); + + // hoped adding the ioctl to do the switching would have alleviated the + // need to do SCHED_FIFO, but we still get preempted between the write and + // ioctl syscalls w/o it often enough to break f/w updates. + struct sched_param sp; + sp.sched_priority = 50; + int policy = SCHED_FIFO; + CHECKP(sched, pthread_setschedparam(pthread_self(), policy, &sp)); + // gpio on, write, wait, gpio off + gpio_on(req->gpio_fd); + struct timespec write_begin; + struct timespec wait_begin; + struct timespec wait_end; + struct timespec read_end; + clock_gettime(CLOCK_MONOTONIC_RAW, &write_begin); + write(req->tty_fd, modbus_cmd, cmd_len); + clock_gettime(CLOCK_MONOTONIC_RAW, &wait_begin); + int waitloops = waitfd(req->tty_fd); + clock_gettime(CLOCK_MONOTONIC_RAW, &wait_end); + gpio_off(req->gpio_fd); + sp.sched_priority = 0; + // Enable UART read + tio.c_cflag |= CREAD; + CHECK(tcsetattr(req->tty_fd,TCSANOW,&tio)); + policy = SCHED_OTHER; + CHECKP(sched, pthread_setschedparam(pthread_self(), policy, &sp)); + + dbg("[*] waitfd loops: %d\n", waitloops); + dbg("[*] reading any response...\n"); + // Read back response + size_t mb_pos = 0; + memset(req->dest_buf, 0, req->dest_limit); + if(req->expected_len == 0) { + req->expected_len = req->dest_limit; + } + if(req->expected_len > req->dest_limit) { + return -1; + } + mb_pos = read_wait(req->tty_fd, req->dest_buf, req->expected_len, req->timeout); + clock_gettime(CLOCK_MONOTONIC_RAW, &read_end); + req->dest_len = mb_pos; + if(mb_pos >= 4) { + uint16_t crc = modbus_crc16(req->dest_buf, mb_pos - 2); + dbg("Modbus response CRC: %04X\n ", crc); + if((req->dest_buf[mb_pos - 2] == (crc >> 8)) && + (req->dest_buf[mb_pos - 1] == (crc & 0x00FF))) { + dbg("CRC OK!\n"); + } else { + dbg("BAD CRC :(\n"); + fprintf(stderr, "bad crc timings:"); + fprintf(stderr, " write: %.2f ms", ts_diff(&write_begin, &wait_begin)); + fprintf(stderr, " wait: %.2f ms", ts_diff(&wait_begin, &wait_end)); + fprintf(stderr, " read: %.2f ms\n", ts_diff(&wait_end, &read_end)); + if(!req->scan) { + crcfail++; + } + if(verbose) { + print_hex(stderr, req->dest_buf, mb_pos); + } + return MODBUS_BAD_CRC; + } + } else { + fprintf(stderr, "timeout timings:"); + fprintf(stderr, " write: %.2f ms", ts_diff(&write_begin, &wait_begin)); + fprintf(stderr, " wait: %.2f ms", ts_diff(&wait_begin, &wait_end)); + fprintf(stderr, " wait: %d iters", waitloops); + fprintf(stderr, " read: %.2f ms\n", ts_diff(&wait_end, &read_end)); + dbg("No response :(\n"); + if(!req->scan) { + timeout++; + } + return MODBUS_RESPONSE_TIMEOUT; + } + +cleanup: + if(error != 0) { + error = -1; + fprintf(stderr, "%s\n", strerror(errno)); + } else { + //fprintf(stderr, "success, timings:"); + //fprintf(stderr, " write: %.2f ms", ts_diff(&write_begin, &wait_begin)); + //fprintf(stderr, " wait: %.2f ms", ts_diff(&wait_begin, &wait_end)); + //fprintf(stderr, " read: %.2f ms -- ", ts_diff(&wait_end, &read_end)); + if(stat_wait == 0 && !req->scan) { + fprintf(stderr, "success: %.2f%% crcfail %.2f%%, timeout %.2f%%\n", + ((double) 100.0 * success / (success + crcfail + timeout)), + ((double) 100.0 * crcfail / (success + crcfail + timeout)), + ((double) 100.0 * timeout / (success + crcfail + timeout))); + stat_wait = 1000; + fprintf(stderr, "success timings:"); + fprintf(stderr, " write: %.2f ms", ts_diff(&write_begin, &wait_begin)); + fprintf(stderr, " wait: %.2f ms", ts_diff(&wait_begin, &wait_end)); + fprintf(stderr, " wait: %d iters", waitloops); + fprintf(stderr, " read: %.2f ms\n", ts_diff(&wait_end, &read_end)); + } else if (!req->scan) { + stat_wait--; + } + if(!req->scan) { + success++; + } + } + return 0; +} + +const char* modbus_strerror(int mb_err) { + if (mb_err < 0) { + mb_err = -mb_err; + } + switch(mb_err) { + case 4: + return "timed out"; + case 5: + return "crc check failed"; + default: + return "unknown"; + } +} diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h index 435d518..1354feb 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbus.h @@ -26,12 +26,27 @@ uint16_t modbus_crc16(char* buffer, size_t length); #define DEFAULT_TTY "/dev/ttyS3" #define DEFAULT_GPIO 45 -#define CHECK(x) { if((x) < 0) { \ - error = x; \ +extern int verbose; +#define dbg(...) if(verbose) { fprintf(stderr, __VA_ARGS__); } +#define log(...) { fprintf(stderr, __VA_ARGS__); } + +#define CHECK(expr) { int _check = expr; if((_check) < 0) { \ + error = _check; \ + goto cleanup; \ +} } +#define CHECKP(name, expr) { int _check = expr; if((_check) < 0) { \ + error = _check; \ + perror(#name); \ goto cleanup; \ } } +#define BAIL(...) { \ + fprintf(stderr, __VA_ARGS__); \ + fflush(stderr); \ + error = -1; \ + goto cleanup; \ +} -void waitfd(int fd); +int waitfd(int fd); void gpio_on(int fd); void gpio_off(int fd); void decode_hex_in_place(char* buf, size_t* len); @@ -41,6 +56,30 @@ void print_hex(FILE* f, char* buf, size_t len); // Read until maxlen bytes or no bytes in mdelay_us microseconds size_t read_wait(int fd, char* dst, size_t maxlen, int mdelay_us); -extern int verbose; + +typedef struct _modbus_req { + int tty_fd; + int gpio_fd; + const char *modbus_cmd; + size_t cmd_len; + int timeout; + size_t expected_len; + char *dest_buf; + size_t dest_limit; + size_t dest_len; + int scan; +} modbus_req; + +int modbuscmd(modbus_req *req); +// Modbus errors + +#define MODBUS_RESPONSE_TIMEOUT -4 +#define MODBUS_BAD_CRC -5 + +const char* modbus_strerror(int mb_err); + +// Modbus constants +#define MODBUS_READ_HOLDING_REGISTERS 3 + #endif diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c index 2d33039..78f62a1 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbuscmd.c @@ -16,51 +16,54 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <termios.h> -#include <unistd.h> +#include <errno.h> #include <fcntl.h> -#include <stdlib.h> +#include <getopt.h> +#include <sched.h> #include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <errno.h> +#include <unistd.h> #include <sys/ioctl.h> -#include <getopt.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/un.h> #include "modbus.h" - -int verbose; +#include "rackmond.h" void usage() { fprintf(stderr, - "modbuscmd [-v] [-t <tty>] [-g <gpio>] modbus_command\n" - "\ttty defaults to %s\n" - "\tgpio defaults to %d\n" + "modbuscmd [-v] [-t <timeout in ms>] [-x <expected response length>] modbus_command\n" "\tmodbus command should be specified in hex\n" - "\teg:\ta40300000008\n", - DEFAULT_TTY, DEFAULT_GPIO); + "\teg:\ta40300000008\n" + "\tif an expected response length is provided, modbuscmd will stop receving and check crc immediately " + "after receiving that many bytes\n"); exit(1); } + int main(int argc, char **argv) { int error = 0; - int fd; - struct termios tio; - char gpio_filename[255]; - int gpio_fd = 0; - int gpio_n = DEFAULT_GPIO; - char *tty = DEFAULT_TTY; char *modbus_cmd = NULL; size_t cmd_len = 0; + int expected = 0; + uint32_t timeout = 0; verbose = 0; + rackmond_command *cmd = NULL; + char *response = NULL; + int clisock; + uint16_t response_len_actual; + struct sockaddr_un rackmond_addr; int opt; - while((opt = getopt(argc, argv, "t:g:v")) != -1) { + while((opt = getopt(argc, argv, "w:x:t:g:v")) != -1) { switch (opt) { - case 't': - tty = optarg; + case 'x': + expected = atoi(optarg); break; - case 'g': - gpio_n = atoi(optarg); + case 't': + timeout = atol(optarg); break; case 'v': verbose = 1; @@ -77,29 +80,6 @@ int main(int argc, char **argv) { usage(); } - if (verbose) - fprintf(stderr, "[*] Opening TTY\n"); - fd = open(tty, O_RDWR | O_NOCTTY); - CHECK(fd); - - if (verbose) - fprintf(stderr, "[*] Opening GPIO %d\n", gpio_n); - snprintf(gpio_filename, 255, "/sys/class/gpio/gpio%d/value", gpio_n); - gpio_fd = open(gpio_filename, O_WRONLY | O_SYNC); - CHECK(gpio_fd); - - if (verbose) - fprintf(stderr, "[*] Setting TTY flags!\n"); - memset(&tio, 0, sizeof(tio)); - cfsetspeed(&tio,B19200); - tio.c_cflag |= PARENB; - tio.c_cflag |= CLOCAL; - tio.c_cflag |= CS8; - tio.c_iflag |= INPCK; - tio.c_cc[VMIN] = 1; - tio.c_cc[VTIME] = 0; - CHECK(tcsetattr(fd,TCSANOW,&tio)); - //convert hex to bytes cmd_len = strlen(modbus_cmd); if(cmd_len < 4) { @@ -107,57 +87,45 @@ int main(int argc, char **argv) { exit(1); } decode_hex_in_place(modbus_cmd, &cmd_len); - append_modbus_crc16(modbus_cmd, &cmd_len); - // print command as sent - if (verbose) { - fprintf(stderr, "Will send: "); - print_hex(stderr, modbus_cmd, cmd_len); - fprintf(stderr, "\n"); - } - - if (verbose) - fprintf(stderr, "[*] Writing!\n"); - - // gpio on, write, wait, gpio off - gpio_on(gpio_fd); - write(fd, modbus_cmd, cmd_len); - waitfd(fd); - gpio_off(gpio_fd); + cmd = malloc(sizeof(rackmond_command) + cmd_len); + cmd->type = COMMAND_TYPE_RAW_MODBUS; + cmd->raw_modbus.length = cmd_len; + cmd->raw_modbus.custom_timeout = timeout; + memcpy(cmd->raw_modbus.data, modbus_cmd, cmd_len); + cmd->raw_modbus.expected_response_length = expected; + response = malloc(expected ? expected : 1024); + uint16_t wire_cmd_len = sizeof(rackmond_command) + cmd_len; - // Enable UART read - tio.c_cflag |= CREAD; - CHECK(tcsetattr(fd,TCSANOW,&tio)); - - if(verbose) - fprintf(stderr, "[*] reading any response...\n"); - // Read back response - char modbus_buf[255]; - size_t mb_pos = 0; - memset(modbus_buf, 0, sizeof(modbus_buf)); - mb_pos = read_wait(fd, modbus_buf, sizeof(modbus_buf), 90000); - if(mb_pos >= 4) { - uint16_t crc = modbus_crc16(modbus_buf, mb_pos - 2); - if(verbose) - fprintf(stderr, "Modbus response CRC: %04X\n ", crc); - if((modbus_buf[mb_pos - 2] == (crc >> 8)) && - (modbus_buf[mb_pos - 1] == (crc & 0x00FF))) { - if(verbose) - fprintf(stderr, "CRC OK!\n"); - print_hex(stdout, modbus_buf, mb_pos); - printf("\n"); - } else { - fprintf(stderr, "BAD CRC :(\n"); - return 5; - } - } else { - fprintf(stderr, "No response :(\n"); - return 4; + clisock = socket(AF_UNIX, SOCK_STREAM, 0); + CHECKP(socket, clisock); + rackmond_addr.sun_family = AF_UNIX; + strcpy(rackmond_addr.sun_path, "/var/run/rackmond.sock"); + int addr_len = strlen(rackmond_addr.sun_path) + sizeof(rackmond_addr.sun_family); + CHECKP(connect, connect(clisock, (struct sockaddr*) &rackmond_addr, addr_len)); + CHECKP(send, send(clisock, &wire_cmd_len, sizeof(wire_cmd_len), 0)); + CHECKP(send, send(clisock, cmd, wire_cmd_len, 0)); + CHECKP(recv, recv(clisock, &response_len_actual, sizeof(response_len_actual), 0)); + if(response_len_actual == 0) { + uint16_t errcode = 0; + CHECKP(recv, recv(clisock, &errcode, sizeof(errcode), 0)); + fprintf(stderr, "modbus error: %d (%s)\n", errcode, modbus_strerror(errcode)); + error = 1; + goto cleanup; + } + CHECKP(recv, recv(clisock, response, response_len_actual, 0)); + if(error == 0) { + printf("Response: "); + print_hex(stdout, response, response_len_actual); + printf("\n"); } - cleanup: + free(cmd); + free(response); if(error != 0) { + if(errno != 0) { + fprintf(stderr, "errno err: %s\n", strerror(errno)); + } error = 1; - fprintf(stderr, "%s\n", strerror(errno)); } return error; } diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c index bf8c6c8..e276501 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/modbussim.c @@ -28,8 +28,6 @@ #include <getopt.h> #include "modbus.h" -int verbose = 0; - void usage() { fprintf(stderr, "modbussim [-v] [-t <tty>] [-g <gpio>] modbus_request modbus_reply\n" diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py new file mode 100755 index 0000000..a92cf8e --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/psu-update-delta.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python +from __future__ import print_function + +import os.path +import socket +import struct +import sys +import argparse +import traceback + +import hexfile + + +def auto_int(x): + return int(x, 0) + + +parser = argparse.ArgumentParser() +parser.add_argument('--addr', type=auto_int, required=True, + help="PSU Modbus Address") +parser.add_argument('file', help="firmware file") + + +class ModbusTimeout(Exception): + pass + + +class ModbusCRCFail(Exception): + pass + + +class ModbusUnknownError(Exception): + pass + + +class BadMEIResponse(Exception): + pass + + +def rackmon_command(cmd): + srvpath = "/var/run/rackmond.sock" + replydata = [] + if os.path.exists(srvpath): + client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + client.connect(srvpath) + cmdlen = struct.pack("@H", len(cmd)) + client.send(cmdlen) + client.send(cmd) + while True: + data = client.recv(1024) + if not data: + break + replydata.append(data) + client.close() + return ''.join(replydata) + + +def pause_monitoring(): + COMMAND_TYPE_PAUSE_MONITORING = 0x04 + command = struct.pack("@Hxx", COMMAND_TYPE_PAUSE_MONITORING) + result = rackmon_command(command) + (res_n, ) = struct.unpack("@B", result) + if res_n == 1: + print("Monitoring was already paused when tried to pause") + elif res_n == 0: + print("Monitoring paused") + else: + print("Unknown response pausing monitoring: %d" % res_n) + + +def resume_monitoring(): + COMMAND_TYPE_START_MONITORING = 0x05 + command = struct.pack("@Hxx", COMMAND_TYPE_START_MONITORING) + result = rackmon_command(command) + (res_n, ) = struct.unpack("@B", result) + if res_n == 1: + print("Monitoring was already running when tried to resume") + elif res_n == 0: + print("Monitoring resumed") + else: + print("Unknown response resuming monitoring: %d" % res_n) + + +def modbuscmd(raw_cmd, expected=0, timeout=0): + COMMAND_TYPE_RAW_MODBUS = 1 + send_command = struct.pack("@HxxHHL", + COMMAND_TYPE_RAW_MODBUS, + len(raw_cmd), + expected, + timeout) + raw_cmd + result = rackmon_command(send_command) + if len(result) == 0: + raise ModbusUnknownError() + (resp_len,) = struct.unpack("@H", result[:2]) + if resp_len == 0: + (error, ) = struct.unpack("@H", result[2:4]) + if error == 4: + raise ModbusTimeout() + if error == 5: + raise ModbusCRCFail() + print("Unknown modbus error: " + str(error)) + raise ModbusUnknownError() + return result[2:resp_len] + + +def mei_command(addr, func_code, mei_type=0x64, data=None, timeout=0): + i_data = data + if i_data is None: + i_data = ("\xFF" * 7) + if len(i_data) < 7: + i_data = i_data + ("\xFF" * (7 - len(i_data))) + assert len(i_data) == 7 + command = struct.pack("BBBB", addr, 0x2b, mei_type, func_code) + i_data + return modbuscmd(command, expected=13, timeout=timeout) + + +def enter_bootloader(addr): + try: + print("Entering bootloader...") + mei_command(addr, 0xFB, timeout=4000) + except ModbusTimeout: + print("Enter bootloader timed out (expected.)") + pass + + +def mei_expect(response, addr, data_pfx, error, success_mei_type=0x71): + expected = struct.pack("BBB", addr, 0x2B, success_mei_type) + \ + data_pfx + ("\xFF" * (8 - len(data_pfx))) + if response != expected: + print(error + ", response: " + response.encode('hex')) + raise BadMEIResponse() + + +def start_programming(addr): + print("Send start programming...") + response = mei_command(addr, 0x70, timeout=10000) + mei_expect(response, addr, "\xB0", "Start programming failed") + print("Start programming succeeded.") + + +def get_challenge(addr): + print("Send get seed") + response = mei_command(addr, 0x27, timeout=3000) + expected = struct.pack("BBBB", addr, 0x2B, 0x71, 0x67) + if response[:len(expected)] != expected: + print("Bad response to get seed: " + response.encode('hex')) + raise BadMEIResponse() + challenge = response[len(expected):len(expected) + 4] + print("Got seed: " + challenge.encode('hex')) + return challenge + + +def send_key(addr, key): + print("Send key") + response = mei_command(addr, 0x28, data=key, timeout=3000) + mei_expect(response, addr, "\x68", "Start programming failed") + print("Send key successful.") + + +def delta_seccalckey(challenge): + (seed, ) = struct.unpack(">L", challenge) + for i in range(32): + if seed & 1 != 0: + seed = seed ^ 0xc758a5b6 + seed = (seed >> 1) & 0x7fffffff + seed = seed ^ 0x06854137 + return struct.pack(">L", seed) + + +def verify_flash(addr): + print("Verifying program...") + response = mei_command(addr, 0x76, timeout=60000) + mei_expect(response, addr, "\xB6", "Program verification failed") + + +def set_write_address(psu_addr, flash_addr): + # print("Set write address to " + hex(flash_addr)) + data = struct.pack(">LB", flash_addr, 0xEA) + response = mei_command(psu_addr, 0x61, data=data, timeout=3000) + mei_expect(response, psu_addr, "\xA1\xEA", "Set address failed") + + +def write_data(addr, data): + assert(len(data) == 8) + command = struct.pack(">BBB", addr, 0x2b, 0x65) + data + response = modbuscmd(command, expected=13, timeout=3000) + expected = struct.pack(">B", addr) +\ + "\x2b\x73\xf0\xaa\xff\xff\xff\xff\xff\xff" + if response != expected: + print("Bad response to writing data: " + + response.encode('hex')) + raise BadMEIResponse() + + +def send_image(addr, fwimg): + total_chunks = sum([len(s) for s in fwimg.segments]) / 8 + sent_chunks = 0 + for s in fwimg.segments: + if len(s) == 0: + continue + print("Sending " + str(s)) + set_write_address(addr, s.start_address) + for i in xrange(0, len(s), 8): + chunk = s.data[i:i+8] + if len(chunk) < 8: + chunk = chunk + ("\xFF" * (8 - len(chunk))) + sent_chunks += 1 + print("\r[%.2f%%] Sending chunk %d of %d..." % + (sent_chunks * 100.0 / total_chunks, + sent_chunks, total_chunks), end="") + sys.stdout.flush() + write_data(addr, str(bytearray(chunk))) + print("") + + +def reset_psu(addr): + print("Resetting PSU...") + try: + response = mei_command(addr, 0x72, timeout=10000) + except ModbusTimeout: + print("No reply from PSU reset (expected.)") + return + expected = struct.pack(">BBBB", addr, 0x2b, 0x71, 0xb2) +\ + ("\xFF" * 7) + if response != expected: + print("Bad response to unit reset request: " + + response.encode('hex')) + raise BadMEIResponse() + + +def erase_flash(addr): + print("Erasing flash... ") + sys.stdout.flush() + response = mei_command(addr, 0x65, timeout=30000) + expected = struct.pack(">BBBB", addr, 0x2b, 0x71, 0xa5) +\ + ("\xFF" * 7) + if response != expected: + print("Bad response to erasing flash: " + + response.encode('hex')) + raise BadMEIResponse() + + +def update_psu(addr, filename): + pause_monitoring() + fwimg = hexfile.load(filename) + enter_bootloader(addr) + start_programming(addr) + challenge = get_challenge(addr) + send_key(addr, delta_seccalckey(challenge)) + erase_flash(addr) + send_image(addr, fwimg) + verify_flash(addr) + reset_psu(addr) + + +def main(): + args = parser.parse_args() + try: + update_psu(args.addr, args.file) + except: + traceback.print_exc() + print("Firmware update failed") + resume_monitoring() + sys.exit(1) + resume_monitoring() + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py new file mode 100644 index 0000000..e93dfae --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmon-config.py @@ -0,0 +1,93 @@ +from __future__ import print_function +import struct +import socket +import os, os.path + +reglist = [ + {"begin": 0x0, #MFR_MODEL + "length": 8}, + {"begin": 0x10, #MFR_DATE + "length": 8}, + {"begin": 0x20, #FB Part # + "length": 8}, + {"begin": 0x30, #HW Revision + "length": 4}, + {"begin": 0x38, #FW Revision + "length": 4}, + {"begin": 0x40, #MFR Serial # + "length": 16}, + {"begin": 0x60, #Workorder # + "length": 4}, + {"begin": 0x68, #PSU Status + "length": 1, + "keep": 10, # 10-sample ring buffer + "flags": 1}, + {"begin": 0x69, #Battery Status + "length": 1, + "keep": 10, # 10-sample ring buffer + "flags": 1}, + {"begin": 0x80, #Input VAC + "length": 1, + "keep": 10}, + {"begin": 0x82, #Input Current AC + "length": 1, + "keep": 10}, + {"begin": 0x84, #Battery Voltage + "length": 1, + "keep": 10}, + {"begin": 0x86, #Battery Current Output + "length": 1}, + {"begin": 0x88, #Battery Current Input + "length": 1}, + {"begin": 0x8A, #Output Voltage (main converter) + "length": 1, + "keep": 10}, + {"begin": 0x8C, #Output Current (main converter) + "length": 1, + "keep": 10}, + {"begin": 0x8E, #IT Load Voltage Output + "length": 1}, + {"begin": 0x90, #IT Load Current Output + "length": 1}, + {"begin": 0x92, #Bulk Cap Voltage + "length": 1}, + {"begin": 0x94, #Input Power + "length": 1, + "keep": 10}, + {"begin": 0x96, #Output Power + "length": 1, + "keep": 10}, + {"begin": 0x98, #RPM Fan 0 + "length": 1}, + {"begin": 0x9A, #RPM Fan 1 + "length": 1}, + {"begin": 0x9E, #Temp 0 + "length": 1}, + {"begin": 0xA0, #Temp 1 + "length": 1}, +] + +def main(): + COMMAND_TYPE_SET_CONFIG = 2 + config_command = struct.pack("@HxxH", + COMMAND_TYPE_SET_CONFIG, + len(reglist)) + for r in reglist: + keep = 1 + if "keep" in r: + keep = r["keep"] + flags = 0 + if "flags" in r: + flags = r["flags"] + monitor_interval = struct.pack("@HHHH", r["begin"], r["length"], keep, flags) + config_command += monitor_interval + + config_packet = struct.pack("H", len(config_command)) + config_command + srvpath = "/var/run/rackmond.sock" + if os.path.exists(srvpath): + client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + client.connect(srvpath) + client.send(config_packet) + +if __name__ == "__main__": + main() diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.c new file mode 100644 index 0000000..cce3ba4 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.c @@ -0,0 +1,637 @@ +#include "modbus.h" +#include "rackmond.h" +#include <string.h> +#include <pthread.h> +#include <stdio.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include <poll.h> +#include <time.h> +#include <stdarg.h> +#include <syslog.h> +#include <signal.h> + +#define MAX_ACTIVE_ADDRS 12 +#define REGISTER_PSU_STATUS 0x68 + +struct _lock_holder { + pthread_mutex_t *lock; + int held; +}; + +#define lock_holder(holder_name, lock_expr) \ + struct _lock_holder holder_name; \ + holder_name.lock = lock_expr; \ + holder_name.held = 0; + +#define lock_take(holder_name) { \ + pthread_mutex_lock(holder_name.lock); \ + holder_name.held = 1; \ +} + +#define lock_release(holder_name) { \ + if(holder_name.held) { \ + pthread_mutex_unlock(holder_name.lock); \ + holder_name.held = 0; \ + } \ +} + +int scanning = 0; + +typedef struct _rs485_dev { + // hold this for the duration of a command + pthread_mutex_t lock; + int tty_fd; + int gpio_fd; +} rs485_dev; + +typedef struct _register_req { + uint16_t begin; + int num; +} register_req; + +typedef struct register_range_data { + monitor_interval* i; + void* mem_begin; + size_t mem_pos; +} register_range_data; + +typedef struct monitoring_data { + uint8_t addr; + register_range_data range_data[1]; +} monitoring_data; + +typedef struct _rackmond_data { + // global rackmond lock + pthread_mutex_t lock; + // number of register read commands to send to each PSU + int num_reqs; + // register read commands (begin+length) + register_req *reqs; + monitoring_config *config; + + uint8_t num_active_addrs; + uint8_t active_addrs[MAX_ACTIVE_ADDRS]; + monitoring_data* stored_data[MAX_ACTIVE_ADDRS]; + FILE *status_log; + + // timeout in nanosecs + int modbus_timeout; + + int paused; + + rs485_dev rs485; +} rackmond_data; + +rackmond_data world; + +char psu_address(int rack, int shelf, int psu) { + int rack_a = ((rack & 3) << 3); + int shelf_a = ((shelf & 1) << 2); + int psu_a = (psu & 3); + return 0xA0 | rack_a | shelf_a | psu_a; +} + +int modbus_command(rs485_dev* dev, int timeout, char* command, size_t len, char* destbuf, size_t dest_limit, size_t expect) { + int error = 0; + lock_holder(devlock, &dev->lock); + modbus_req req; + req.tty_fd = dev->tty_fd; + req.gpio_fd = dev->gpio_fd; + req.modbus_cmd = command; + req.cmd_len = len; + req.dest_buf = destbuf; + req.dest_limit = dest_limit; + req.timeout = timeout; + req.expected_len = expect != 0 ? expect : dest_limit; + req.scan = scanning; + lock_take(devlock); + int cmd_error = modbuscmd(&req); + CHECK(cmd_error); +cleanup: + lock_release(devlock); + if (error >= 0) { + return req.dest_len; + } + + return error; +} + +int read_registers(rs485_dev *dev, int timeout, uint8_t addr, uint16_t begin, uint16_t num, uint16_t* out) { + int error = 0; + // address, function, begin, length in # of regs + char command[sizeof(addr) + 1 + sizeof(begin) + sizeof(num)]; + // address, function, length (1 byte), data (2 bytes per register), crc + // (VLA) + char response[sizeof(addr) + 1 + 1 + (2 * num) + 2]; + command[0] = addr; + command[1] = MODBUS_READ_HOLDING_REGISTERS; + command[2] = begin << 8; + command[3] = begin & 0xFF; + command[4] = num << 8; + command[5] = num & 0xFF; + + int dest_len = + modbus_command( + dev, timeout, + command, sizeof(addr) + 1 + sizeof(begin) + sizeof(num), + response, sizeof(addr) + 1 + 1 + (2 * num) + 2, 0); + CHECK(dest_len); + + if (dest_len >= 5) { + memcpy(out, response + 3, num * 2); + } else { + log("Unexpected short but CRC correct response!\n"); + error = -1; + goto cleanup; + } + if (response[0] != addr) { + log("Got response for addr %02x when expected %02x\n", response[0], addr); + error = -1; + goto cleanup; + } + if (response[2] != (num * 2)) { + log("Got %d register data bytes when expecting %d\n", response[2], (num * 2)); + error = -1; + goto cleanup; + } +cleanup: + return error; +} + +int sub_uint8s(const void* a, const void* b) { + return (*(uint8_t*)a) - (*(uint8_t*)b); +} + +int check_active_psus() { + int error = 0; + lock_holder(worldlock, &world.lock); + lock_take(worldlock); + if (world.paused == 1) { + usleep(1000); + goto cleanup; + } + if (world.config == NULL) { + lock_release(worldlock); + usleep(5000); + goto cleanup; + } + world.num_active_addrs = 0; + + scanning = 1; + //fprintf(stderr, "Begin presence check: "); + for(int rack = 0; rack < 3; rack++) { + for(int shelf = 0; shelf < 2; shelf++) { + for(int psu = 0; psu < 3; psu++) { + char addr = psu_address(rack, shelf, psu); + uint16_t status = 0; + int err = read_registers(&world.rs485, world.modbus_timeout, addr, REGISTER_PSU_STATUS, 1, &status); + if (err == 0) { + world.active_addrs[world.num_active_addrs] = addr; + world.num_active_addrs++; + //fprintf(stderr, "%02x - active (%04x) ", addr, status); + } else { + dbg("%02x - %d; ", addr, err); + } + } + } + } + //its the only stdlib sort + qsort(world.active_addrs, world.num_active_addrs, + sizeof(uint8_t), sub_uint8s); +cleanup: + scanning = 0; + lock_release(worldlock); + return error; +} + +monitoring_data* alloc_monitoring_data(uint8_t addr) { + size_t size = sizeof(monitoring_data) + + sizeof(register_range_data) * world.config->num_intervals; + for(int i = 0; i < world.config->num_intervals; i++) { + monitor_interval *iv = &world.config->intervals[i]; + int pitch = sizeof(uint32_t) + (sizeof(uint16_t) * iv->len); + int data_size = pitch * iv->keep; + size += data_size; + } + monitoring_data* d = calloc(1, size); + if (d == NULL) { + log("Failed to allocate memory for sensor data.\n"); + return NULL; + } + d->addr = addr; + void* mem = d; + mem = mem + (sizeof(monitoring_data) + + sizeof(register_range_data) * world.config->num_intervals); + for(int i = 0; i < world.config->num_intervals; i++) { + monitor_interval *iv = &world.config->intervals[i]; + int pitch = sizeof(uint32_t) + (sizeof(uint16_t) * iv->len); + int data_size = pitch * iv->keep; + d->range_data[i].i = iv; + d->range_data[i].mem_begin = mem; + d->range_data[i].mem_pos = 0; + mem = mem + data_size; + } + return d; +} + +int sub_storeptrs(const void* va, const void *vb) { + //more *s than i like :/ + monitoring_data* a = *(monitoring_data**)va; + monitoring_data* b = *(monitoring_data**)vb; + //nulls to the end + if (b == NULL && a == NULL) { + return 0; + } + if (b == NULL) { + return -1; + } + if (a == NULL) { + return 1; + } + return a->addr - b->addr; +} + +int alloc_monitoring_datas() { + int error = 0; + if (world.config == NULL) { + goto cleanup; + } + qsort(world.stored_data, MAX_ACTIVE_ADDRS, + sizeof(monitoring_data*), sub_storeptrs); + int data_pos = 0; + for(int i = 0; i < world.num_active_addrs; i++) { + uint8_t addr = world.active_addrs[i]; + while(world.stored_data[data_pos] != NULL && + world.stored_data[data_pos]->addr != addr) { + data_pos++; + } + if (world.stored_data[data_pos] == NULL) { + log("Detected PSU at address 0x%02x\n", addr); + //syslog(LOG_INFO, "Detected PSU at address 0x%02x", addr); + world.stored_data[data_pos] = alloc_monitoring_data(addr); + if (world.stored_data[data_pos] == NULL) { + BAIL("allocation failed\n"); + } + //reset search pos after alloc (post-sorted addrs may already be alloc'd, need to check again) + data_pos = 0; + continue; + } + if (world.stored_data[data_pos]->addr == addr) { + continue; + } + BAIL("shouldn't get here!\n"); + } +cleanup: + return error; +} + +void record_data(register_range_data* rd, uint32_t time, uint16_t* regs) { + int n_regs = (rd->i->len); + int pitch = sizeof(time) + (sizeof(uint16_t) * n_regs); + int mem_size = pitch * rd->i->keep; + + memcpy(rd->mem_begin + rd->mem_pos, &time, sizeof(time)); + rd->mem_pos += sizeof(time); + memcpy(rd->mem_begin + rd->mem_pos, regs, n_regs * sizeof(uint16_t)); + rd->mem_pos += n_regs * sizeof(uint16_t); + rd->mem_pos = rd->mem_pos % mem_size; +} + +int fetch_monitored_data() { + int error = 0; + int data_pos = 0; + lock_holder(worldlock, &world.lock); + lock_take(worldlock); + if (world.paused == 1) { + usleep(1000); + goto cleanup; + } + if (world.config == NULL) { + goto cleanup; + } + lock_release(worldlock); + + usleep(1000); // wait a sec btween PSUs to not overload RT scheduling + // threshold + while(world.stored_data[data_pos] != NULL && data_pos < MAX_ACTIVE_ADDRS) { + uint8_t addr = world.stored_data[data_pos]->addr; + //log("readpsu %02x\n", addr); + for(int r = 0; r < world.config->num_intervals; r++) { + register_range_data* rd = &world.stored_data[data_pos]->range_data[r]; + monitor_interval* i = rd->i; + uint16_t regs[i->len]; + int err = read_registers(&world.rs485, + world.modbus_timeout, addr, i->begin, i->len, regs); + if (err) { + log("Error %d reading %02x registers at %02x from %02x\n", + err, i->len, i->begin, addr); + continue; + } + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + uint32_t timestamp = ts.tv_sec; + if (rd->i->flags & MONITOR_FLAG_ONLY_CHANGES) { + int pitch = sizeof(timestamp) + (sizeof(uint16_t) * i->len); + int lastpos = rd->mem_pos - pitch; + if (lastpos < 0) { + lastpos = (pitch * rd->i->keep) - pitch; + } + if (!memcmp(rd->mem_begin + lastpos + sizeof(timestamp), + regs, sizeof(uint16_t) * i->len) && + memcmp(rd->mem_begin, "\x00\x00\x00\x00", 4)) { + continue; + } + + if (world.status_log) { + time_t rawt; + struct tm* ti; + time(&rawt); + ti = localtime(&rawt); + char timestr[80]; + strftime(timestr, sizeof(timestr), "%b %e %T", ti); + fprintf(world.status_log, + "%s: Change to status register %02x on address %02x. New value: %02x\n", + timestr, i->begin, addr, regs[0]); + fflush(world.status_log); + } + + } + lock_take(worldlock); + record_data(rd, timestamp, regs); + lock_release(worldlock); + } + data_pos++; + } +cleanup: + lock_release(worldlock); + return error; +} + +// check for new psus every N rounds of sensor reads +#define SEARCH_PSUS_EVERY 200 +void* monitoring_loop(void* arg) { + (void) arg; + int until_search = 0; + world.status_log = fopen("/var/log/psu-status.log", "a+"); + while(1) { + if (until_search == 0) { + check_active_psus(); + alloc_monitoring_datas(); + until_search = SEARCH_PSUS_EVERY; + } else { + until_search--; + } + fetch_monitored_data(); + } + return NULL; +} + +int open_rs485_dev(const char* tty_filename, int gpio_num, rs485_dev *dev) { + int error = 0; + int tty_fd, gpio_fd; + char gpio_filename[128]; + dbg("[*] Opening TTY\n"); + tty_fd = open(tty_filename, O_RDWR | O_NOCTTY); + CHECK(tty_fd); + + dbg("[*] Opening GPIO %d\n", gpio_num); + snprintf(gpio_filename, sizeof(gpio_filename), "/sys/class/gpio/gpio%d/value", gpio_num); + gpio_fd = open(gpio_filename, O_WRONLY | O_SYNC); + CHECK(gpio_fd); + + dev->tty_fd = tty_fd; + dev->gpio_fd = gpio_fd; + pthread_mutex_init(&dev->lock, NULL); +cleanup: + return error; +} + +int do_command(int sock, rackmond_command* cmd) { + int error = 0; + lock_holder(worldlock, &world.lock); + switch(cmd->type) { + case COMMAND_TYPE_RAW_MODBUS: + { + uint16_t expected = cmd->raw_modbus.expected_response_length; + int timeout = world.modbus_timeout; + if (cmd->raw_modbus.custom_timeout) { + //ms to us + timeout = cmd->raw_modbus.custom_timeout * 1000; + } + if (expected == 0) { + expected = 1024; + } + char response[expected]; + int response_len = modbus_command( + &world.rs485, timeout, + cmd->raw_modbus.data, cmd->raw_modbus.length, + response, expected, expected); + uint16_t response_len_wire = response_len; + if(response_len < 0) { + uint16_t error = -response_len; + response_len_wire = 0; + send(sock, &response_len_wire, sizeof(uint16_t), 0); + send(sock, &error, sizeof(uint16_t), 0); + break; + } + send(sock, &response_len_wire, sizeof(uint16_t), 0); + send(sock, response, response_len, 0); + break; + } + case COMMAND_TYPE_SET_CONFIG: + { + lock_take(worldlock); + if (world.config != NULL) { + BAIL("rackmond already configured\n"); + } + size_t config_size = sizeof(monitoring_config) + + (sizeof(monitor_interval) * cmd->set_config.config.num_intervals); + world.config = calloc(1, config_size); + memcpy(world.config, &cmd->set_config.config, config_size); + syslog(LOG_INFO, "got configuration"); + lock_release(worldlock); + break; + } + case COMMAND_TYPE_DUMP_DATA_JSON: + { + lock_take(worldlock); + if (world.config == NULL) { + send(sock, "[]", 2, 0); + } else { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + uint32_t now = ts.tv_sec; + send(sock, "[", 1, 0); + int data_pos = 0; + while(world.stored_data[data_pos] != NULL && data_pos < MAX_ACTIVE_ADDRS) { + dprintf(sock, "{\"addr\":%d,\"now\":%d,\"ranges\":[", + world.stored_data[data_pos]->addr, now); + for(int i = 0; i < world.config->num_intervals; i++) { + uint32_t time; + register_range_data *rd = &world.stored_data[data_pos]->range_data[i]; + char* mem_pos = rd->mem_begin; + dprintf(sock,"{\"begin\":%d,\"readings\":[", rd->i->begin); + // want to cut the list off early just before + // the first entry with time == 0 + memcpy(&time, mem_pos, sizeof(time)); + for(int j = 0; j < rd->i->keep && time != 0; j++) { + mem_pos += sizeof(time); + dprintf(sock, "{\"time\":%d,\"data\":\"", time); + for(int c = 0; c < rd->i->len * 2; c++) { + dprintf(sock, "%02x", *mem_pos); + mem_pos++; + } + send(sock, "\"}", 2, 0); + memcpy(&time, mem_pos, sizeof(time)); + if (time == 0) { + break; + } + if ((j+1) < rd->i->keep) { + send(sock, ",", 1, 0); + } + } + send(sock, "]}", 2, 0); + if ((i+1) < world.config->num_intervals) { + send(sock, ",", 1, 0); + } + } + data_pos++; + if (data_pos < MAX_ACTIVE_ADDRS && world.stored_data[data_pos] != NULL) { + send(sock, "]},", 3, 0); + } else { + send(sock, "]}", 2, 0); + } + } + send(sock, "]", 1, 0); + } + lock_release(worldlock); + break; + } + case COMMAND_TYPE_PAUSE_MONITORING: + { + lock_take(worldlock); + uint8_t was_paused = world.paused; + world.paused = 1; + send(sock, &was_paused, sizeof(was_paused), 0); + lock_release(worldlock); + break; + } + case COMMAND_TYPE_START_MONITORING: + { + lock_take(worldlock); + uint8_t was_started = !world.paused; + world.paused = 0; + send(sock, &was_started, sizeof(was_started), 0); + lock_release(worldlock); + break; + } + default: + CHECK(-1); + } +cleanup: + lock_release(worldlock); + return error; +} + +typedef enum { + CONN_WAITING_LENGTH, + CONN_WAITING_BODY +} rackmond_connection_state; + +// receive the command as a length prefixed block +// (uint16_t, followed by data) +// this is all over a local socket, won't be doing +// endian flipping, clients should only be local procs +// compiled for the same arch +int handle_connection(int sock) { + int error = 0; + rackmond_connection_state state = CONN_WAITING_LENGTH; + char bodybuf[1024]; + uint16_t expected_len = 0; + struct pollfd pfd; + int recvret = 0; + pfd.fd = sock; + pfd.events = POLLIN | POLLERR | POLLHUP; + // if you don't do anything for a whole second we bail +next: + CHECKP(poll, poll(&pfd, 1, 1000)); + if (pfd.revents & (POLLERR | POLLHUP)) { + goto cleanup; + } + switch(state) { + case CONN_WAITING_LENGTH: + recvret = recv(sock, &expected_len, 2, MSG_DONTWAIT); + if (recvret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + goto next; + } + if (expected_len == 0 || expected_len > sizeof(bodybuf)) { + // bad length; bail + goto cleanup; + } + state = CONN_WAITING_BODY; + goto next; + break; + case CONN_WAITING_BODY: + recvret = recv(sock, &bodybuf, expected_len, MSG_DONTWAIT); + if (recvret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + goto next; + } + CHECK(do_command(sock, (rackmond_command*) bodybuf)); + } +cleanup: + close(sock); + if (error != 0) { + fprintf(stderr, "Warning: possible error handling user connection (%d)\n", error); + } + return 0; +} + +int main(int argc, char** argv) { + if (getenv("RACKMOND_FOREGROUND") == NULL) { + daemon(0, 0); + } + signal(SIGPIPE, SIG_IGN); + int error = 0; + world.paused = 0; + world.modbus_timeout = 300000; + if (getenv("RACKMOND_TIMEOUT") != NULL) { + world.modbus_timeout = atoll(getenv("RACKMOND_TIMEOUT")); + fprintf(stderr, "Timeout from env: %dms\n", + (world.modbus_timeout / 1000)); + } + world.config = NULL; + pthread_mutex_init(&world.lock, NULL); + verbose = getenv("RACKMOND_VERBOSE") != NULL ? 1 : 0; + openlog("rackmond", 0, LOG_USER); + syslog(LOG_INFO, "rackmon/modbus service starting"); + CHECK(open_rs485_dev(DEFAULT_TTY, DEFAULT_GPIO, &world.rs485)); + pthread_t monitoring_thread; + pthread_create(&monitoring_thread, NULL, monitoring_loop, NULL); + struct sockaddr_un local, client; + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + strcpy(local.sun_path, "/var/run/rackmond.sock"); + local.sun_family = AF_UNIX; + int socknamelen = sizeof(local.sun_family) + strlen(local.sun_path); + unlink(local.sun_path); + CHECKP(bind, bind(sock, (struct sockaddr *)&local, socknamelen)); + CHECKP(listen, listen(sock, 5)); + syslog(LOG_INFO, "rackmon/modbus service listening"); + while(1) { + socklen_t clisocklen = sizeof(struct sockaddr_un); + int clisock = accept(sock, (struct sockaddr*) &client, &clisocklen); + CHECKP(accept, clisock); + CHECK(handle_connection(clisock)); + } + +cleanup: + if (error != 0) { + error = 1; + } + return error; +} diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.h b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.h new file mode 100644 index 0000000..2c0e8a0 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmond.h @@ -0,0 +1,46 @@ +#include <stdint.h> + +//would've been nice to have thrift + +// Raw modbus command +// Response is just the raw response data +typedef struct raw_modbus_command { + uint16_t length; + uint16_t expected_response_length; + uint32_t custom_timeout; // 0 for default + char data[1]; +} raw_modbus_command; + +// only store new value if different from most recent +// (for watching changes to status flags registers) +#define MONITOR_FLAG_ONLY_CHANGES 0x1 + +typedef struct monitor_interval { + uint16_t begin; + uint16_t len; + uint16_t keep; // How long of a history to keep? + uint16_t flags; +} monitor_interval; + +typedef struct monitoring_config { + uint16_t num_intervals; + monitor_interval intervals[1]; +} monitoring_config; + +typedef struct set_config_command { + monitoring_config config; +} set_config_command; + +#define COMMAND_TYPE_RAW_MODBUS 0x01 +#define COMMAND_TYPE_SET_CONFIG 0x02 +#define COMMAND_TYPE_DUMP_DATA_JSON 0x03 +#define COMMAND_TYPE_PAUSE_MONITORING 0x04 +#define COMMAND_TYPE_START_MONITORING 0x05 + +typedef struct rackmond_command { + uint16_t type; + union { + raw_modbus_command raw_modbus; + set_config_command set_config; + }; +} rackmond_command; diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmondata.c b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmondata.c new file mode 100644 index 0000000..391b5be --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/rackmondata.c @@ -0,0 +1,58 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <sys/un.h> +#include "modbus.h" +#include "rackmond.h" + +int main(int argc, char **argv) { + int error = 0; + rackmond_command cmd; + int clisock; + uint16_t wire_cmd_len = sizeof(cmd); + struct sockaddr_un rackmond_addr; + cmd.type = COMMAND_TYPE_DUMP_DATA_JSON; + clisock = socket(AF_UNIX, SOCK_STREAM, 0); + CHECKP(socket, clisock); + rackmond_addr.sun_family = AF_UNIX; + strcpy(rackmond_addr.sun_path, "/var/run/rackmond.sock"); + int addr_len = strlen(rackmond_addr.sun_path) + sizeof(rackmond_addr.sun_family); + CHECKP(connect, connect(clisock, (struct sockaddr*) &rackmond_addr, addr_len)); + CHECKP(send, send(clisock, &wire_cmd_len, sizeof(wire_cmd_len), 0)); + CHECKP(send, send(clisock, &cmd, wire_cmd_len, 0)); + char readbuf[256]; + ssize_t n_read; + while((n_read = read(clisock, readbuf, sizeof(readbuf))) > 0) { + write(1, readbuf, n_read); + } +cleanup: + if(error != 0) { + if(errno != 0) { + fprintf(stderr, "%s\n", strerror(errno)); + } + error = 1; + } + return error; +} diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh new file mode 100644 index 0000000..85a1e22 --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon/setup-rackmond.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +### BEGIN INIT INFO +# Provides: setup-rackmond +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Start Rackmon service +### END INIT INFO + +echo -n "Starting rackmon background service..." +/usr/local/bin/rackmond +echo "done." + +echo -n "Configuring rackmon service..." +python /etc/rackmon-config.py +echo "done." diff --git a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb index d3e79e4..399f7c0 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/rackmon/rackmon_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "Rackmon Functionality" DESCRIPTION = "Rackmon Functionality" SECTION = "base" @@ -6,7 +21,7 @@ PR = "r1" LICENSE = "GPLv2" LIC_FILES_CHKSUM = "file://modbus.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" -#DEPENDS_append = " update-rc.d-native" +DEPENDS_append = " update-rc.d-native" SRC_URI = "file://Makefile \ file://modbuscmd.c \ @@ -14,6 +29,13 @@ SRC_URI = "file://Makefile \ file://modbus.c \ file://modbus.h \ file://gpiowatch.c \ + file://rackmond.c \ + file://rackmond.h \ + file://rackmondata.c \ + file://setup-rackmond.sh \ + file://rackmon-config.py \ + file://psu-update-delta.py \ + file://hexfile.py \ " S = "${WORKDIR}" @@ -21,6 +43,10 @@ S = "${WORKDIR}" binfiles = "modbuscmd \ modbussim \ gpiowatch \ + rackmond \ + rackmondata \ + psu-update-delta.py \ + hexfile.py \ " #otherfiles = "README" @@ -36,6 +62,11 @@ do_install() { install -m 755 $f ${dst}/$f ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f done + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-rackmond.sh ${D}${sysconfdir}/init.d/setup-rackmond.sh + install -m 755 rackmon-config.py ${D}${sysconfdir}/rackmon-config.py + update-rc.d -r ${D} setup-rackmond.sh start 95 2 3 4 5 . } FBPACKAGEDIR = "${prefix}/local/fbpackages" diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py index 6d59fd6..52c98d9 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py +++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest.py @@ -20,14 +20,24 @@ from ctypes import * -from bottle import route, run, template, request, response +from bottle import route, run, template, request, response, ServerAdapter from bottle import abort +from wsgiref.simple_server import make_server, WSGIRequestHandler, WSGIServer import json -from rest_fruid import * -from rest_server import * -from rest_sensors import * -from rest_bmc import * -from rest_gpios import * +import ssl +import socket +import os +import rest_fruid +import rest_server +import rest_sensors +import rest_bmc +import rest_gpios +import rest_modbus +import rest_slotid + +CONSTANTS = { + 'certificate': '/usr/lib/ssl/certs/rest_server.pem', +} # Handler for root resource endpoint @route('/api') @@ -50,7 +60,8 @@ def rest_sys(): "Description": "Wedge System", }, "Actions": [], - "Resources": [ "mb", "bmc", "server", "sensors", "gpios"], + "Resources": [ "mb", "bmc", "server", "sensors", "gpios", + "modbus_registers", "slotid"], } return result @@ -70,33 +81,72 @@ def rest_sys(): # Handler for sys/mb/fruid resource endpoint @route('/api/sys/mb/fruid') -def rest_fruid(): - return get_fruid() +def rest_fruid_hdl(): + return rest_fruid.get_fruid() # Handler for sys/bmc resource endpoint @route('/api/sys/bmc') -def rest_bmc(): - return get_bmc() +def rest_bmc_hdl(): + return rest_bmc.get_bmc() # Handler for sys/server resource endpoint @route('/api/sys/server') -def rest_bmc(): - return get_server() +def rest_server_hdl(): + return rest_server.get_server() # Handler for uServer resource endpoint @route('/api/sys/server', method='POST') -def rest_server(): +def rest_server_act_hdl(): data = json.load(request.body) - return server_action(data) + return rest_server.server_action(data) # Handler for sensors resource endpoint @route('/api/sys/sensors') -def rest_sensors(): - return get_sensors() +def rest_sensors_hdl(): + return rest_sensors.get_sensors() # Handler for sensors resource endpoint @route('/api/sys/gpios') -def rest_gpios(): - return get_gpios() +def rest_gpios_hdl(): + return rest_gpios.get_gpios() + +@route('/api/sys/modbus_registers') +def modbus_registers_hdl(): + return rest_modbus.get_modbus_registers() + +# Handler for sensors resource endpoint +@route('/api/sys/slotid') +def rest_slotid_hdl(): + return rest_slotid.get_slotid() run(host = "::", port = 8080) + +# SSL Wrapper for Rest API +class SSLWSGIRefServer(ServerAdapter): + def run(self, handler): + if self.quiet: + class QuietHandler(WSGIRequestHandler): + def log_request(*args, **kw): pass + self.options['handler_class'] = QuietHandler + + # IPv6 Support + server_cls = self.options.get('server_class', WSGIServer) + + if ':' in self.host: + if getattr(server_cls, 'address_family') == socket.AF_INET: + class server_cls(server_cls): + address_family = socket.AF_INET6 + + srv = make_server(self.host, self.port, handler, + server_class=server_cls, **self.options) + srv.socket = ssl.wrap_socket ( + srv.socket, + certfile=CONSTANTS['certificate'], + server_side=True) + srv.serve_forever() + +# Use SSL if the certificate exists. Otherwise, run without SSL. +if os.access(CONSTANTS['certificate'], os.R_OK): + run(server=SSLWSGIRefServer(host="::", port=8443)) +else: + run(host = "::", port = 8080) diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_bmc.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_bmc.py index d9600ae..c4f661e 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_bmc.py +++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_bmc.py @@ -20,6 +20,7 @@ from subprocess import * +import re # Handler for FRUID resource endpoint def get_bmc(): @@ -51,6 +52,14 @@ def get_bmc(): mem_usage = adata[0] cpu_usage = adata[1] + # Get OpenBMC version + version = "" + data = Popen('cat /etc/issue', \ + shell=True, stdout=PIPE).stdout.read() + ver = re.search(r'v([\w\d._-]*)\s', data) + if ver: + version = ver.group(1) + result = { "Information": { "Description": "Wedge BMC", @@ -58,6 +67,7 @@ def get_bmc(): "Uptime": uptime, "Memory Usage": mem_usage, "CPU Usage": cpu_usage, + "OpenBMC Version": version, }, "Actions": [], "Resources": [], diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_modbus.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_modbus.py new file mode 100644 index 0000000..9d213fc --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_modbus.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +import subprocess +from subprocess import Popen + +# Handler for sensors resource endpoint +def get_modbus_registers(): + p = Popen('/usr/local/bin/rackmondata', stdout=subprocess.PIPE) + out, err = p.communicate() + return out diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py index f4f83d3..fa65372 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py +++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_sensors.py @@ -39,12 +39,10 @@ def get_sensors(): if (len(tdata) < 2): continue sresult[tdata[0].strip()] = tdata[1].strip() - result.append(sresult) - + result.append(sresult) fresult = { "Information": result, "Actions": [], "Resources": [], } - return fresult diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_slotid.py b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_slotid.py new file mode 100644 index 0000000..ee407ac --- /dev/null +++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/rest_slotid.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +import subprocess + +# Handler for sensors resource endpoint +def get_slotid(): + p = subprocess.Popen('source /usr/local/bin/openbmc-utils.sh;' + 'wedge_slot_id $(wedge_board_type)', + shell=True, stdout=subprocess.PIPE) + out, err = p.communicate() + try: + slot = int(out.strip('\n')) + except: + slot = 0 + return { 'slotid' : slot } diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh index fe01c23..bdd79b6 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/files/setup-rest-api.sh @@ -2,6 +2,22 @@ # # Copyright 2014-present Facebook. All Rights Reserved. # +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + ### BEGIN INIT INFO # Provides: setup-rest-api # Required-Start: diff --git a/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb index 2753f30..5dec4bf 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/rest-api/rest-api_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "Rest API Daemon" DESCRIPTION = "Daemon to handle RESTful interface." SECTION = "base" @@ -16,11 +31,13 @@ SRC_URI = "file://setup-rest-api.sh \ file://rest_gpios.py \ file://rest_server.py \ file://rest_sensors.py \ + file://rest_modbus.py \ + file://rest_slotid.py \ " S = "${WORKDIR}" -binfiles = "rest.py rest_bmc.py rest_fruid.py rest_gpios.py rest_server.py rest_sensors.py setup-rest-api.sh" +binfiles = "rest.py rest_bmc.py rest_fruid.py rest_gpios.py rest_server.py rest_sensors.py rest_modbus.py rest_slotid.py setup-rest-api.sh" pkgdir = "rest-api" diff --git a/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/sensor-setup_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/sensor-setup_0.1.bb index ad6bb0c..1b0f937 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/sensor-setup_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/sensor-setup/sensor-setup_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "Configure the sensors" DESCRIPTION = "The script configure sensors" SECTION = "base" diff --git a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/Makefile b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/Makefile index 6425261..dba9dbb 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/Makefile +++ b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/Makefile @@ -1,4 +1,20 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + all: sms-kcsd sms-kcsd: sms-kcsd.c diff --git a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/setup-sms-kcs.sh b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/setup-sms-kcs.sh index d369f5c..b4234a4 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/setup-sms-kcs.sh +++ b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd/setup-sms-kcs.sh @@ -2,6 +2,22 @@ # # Copyright 2014-present Facebook. All Rights Reserved. # +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + ### BEGIN INIT INFO # Provides: setup-sms-kcs # Required-Start: diff --git a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd_0.1.bb index 1f3ea08..812d815 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/sms-kcsd/sms-kcsd_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "SMS KCS Daemon" DESCRIPTION = "Daemon to handle SMS KCS interface." SECTION = "base" diff --git a/meta-facebook/meta-wedge/recipes-wedge/usb-console/usb-console_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/usb-console/usb-console_0.1.bb index f92511c..c934f46 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/usb-console/usb-console_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/usb-console/usb-console_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "Set up a USB serial console" DESCRIPTION = "Sets up a USB serial console" SECTION = "base" diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/Makefile b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/Makefile index 0264efe..8c05686 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/Makefile +++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/Makefile @@ -1,8 +1,24 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + lib: libwedge_eeprom.so libwedge_eeprom.so: wedge_eeprom.c - $(CC) $(CCFLAGS) -fPIC -c -o wedge_eeprom.o wedge_eeprom.c + $(CC) $(CFLAGS) -fPIC -c -o wedge_eeprom.o wedge_eeprom.c $(CC) -shared -o libwedge_eeprom.so wedge_eeprom.o -lc .PHONY: clean diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c index 44f708d..e66941e 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c +++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/lib/wedge_eeprom.c @@ -23,9 +23,11 @@ #include <stdio.h> #include <string.h> -#include <facebook/log.h> +#include <openbmc/log.h> +#ifndef FBW_EEPROM_FILE #define FBW_EEPROM_FILE "/sys/class/i2c-adapter/i2c-6/6-0050/eeprom" +#endif #define FBW_EEPROM_VERSION 0 #define FBW_EEPROM_V0_SIZE 162 diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/Makefile b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/Makefile index 30aac75..f2aeadc 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/Makefile +++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/Makefile @@ -1,4 +1,20 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + utils: weutil weutil: weutil.o diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c index 9e932aa..90aca10 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c +++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/files/utils/weutil.c @@ -20,7 +20,7 @@ #include <stdio.h> #include <facebook/wedge_eeprom.h> -#include <facebook/log.h> +#include <openbmc/log.h> int main(int argc, const char *argv[]) { diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/libwedge-eeprom_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/libwedge-eeprom_0.1.bb index 781cf76..6f62557 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/libwedge-eeprom_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/libwedge-eeprom_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "Wedge EEPROM Library" DESCRIPTION = "library for wedge eeprom" SECTION = "base" @@ -9,7 +24,7 @@ LIC_FILES_CHKSUM = "file://wedge_eeprom.c;beginline=4;endline=16;md5=da35978751a SRC_URI = "file://lib \ " -DEPENDS += "fbutils" +DEPENDS += "liblog" S = "${WORKDIR}/lib" @@ -22,5 +37,4 @@ do_install() { } FILES_${PN} = "${libdir}/libwedge_eeprom.so" -FILES_${PN}-dbg = "${libdir}/.debug" FILES_${PN}-dev = "${includedir}/facebook/wedge_eeprom.h" diff --git a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb index 51bdbb9..3afbed1 100644 --- a/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb +++ b/meta-facebook/meta-wedge/recipes-wedge/wedge-eeprom/wedge-eeprom_0.1.bb @@ -1,4 +1,19 @@ # Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA SUMMARY = "Wedge EEPROM Utilities" DESCRIPTION = "Util for wedge eeprom" SECTION = "base" diff --git a/meta-facebook/meta-yosemite/conf/bblayers.conf.sample b/meta-facebook/meta-yosemite/conf/bblayers.conf.sample new file mode 100644 index 0000000..8827e9d --- /dev/null +++ b/meta-facebook/meta-yosemite/conf/bblayers.conf.sample @@ -0,0 +1,21 @@ +# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf +# changes incompatibly +LCONF_VERSION = "6" + +BBPATH = "${TOPDIR}" +BBFILES ?= "" + +BBLAYERS ?= " \ + ##OEROOT##/meta \ + ##OEROOT##/meta-yocto \ + ##OEROOT##/meta-yocto-bsp \ + ##OEROOT##/meta-openembedded/meta-oe \ + ##OEROOT##/meta-openembedded/meta-networking \ + ##OEROOT##/meta-openbmc \ + ##OEROOT##/meta-openbmc/meta-aspeed \ + ##OEROOT##/meta-openbmc/meta-facebook/meta-yosemite \ + " +BBLAYERS_NON_REMOVABLE ?= " \ + ##OEROOT##/meta \ + ##OEROOT##/meta-yocto \ + " diff --git a/meta-facebook/meta-yosemite/conf/conf-notes.txt b/meta-facebook/meta-yosemite/conf/conf-notes.txt new file mode 100644 index 0000000..87ebd18 --- /dev/null +++ b/meta-facebook/meta-yosemite/conf/conf-notes.txt @@ -0,0 +1,2 @@ +Common targets are: + yosemite-image diff --git a/meta-facebook/meta-yosemite/conf/layer.conf b/meta-facebook/meta-yosemite/conf/layer.conf new file mode 100644 index 0000000..281d2cc --- /dev/null +++ b/meta-facebook/meta-yosemite/conf/layer.conf @@ -0,0 +1,10 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "yosemite" +BBFILE_PATTERN_yosemite = "^${LAYERDIR}/" +BBFILE_PRIORITY_yosemite = "8" diff --git a/meta-facebook/meta-yosemite/conf/local.conf.sample b/meta-facebook/meta-yosemite/conf/local.conf.sample new file mode 100644 index 0000000..9204236 --- /dev/null +++ b/meta-facebook/meta-yosemite/conf/local.conf.sample @@ -0,0 +1,140 @@ +# +# Local configuration file for building the OpenBMC image. +# + +# Always look for packages first in our own local package mirror +SOURCE_MIRROR_URL ?= "file://${TOPDIR}/../meta-openbmc/source_mirror/" +INHERIT += "own-mirrors" + +# Save local tarballs for all packages we download. +# This can be used to update our mirror directory above. +BB_GENERATE_MIRROR_TARBALLS = "1" + +# The following setting will prevent bitbake from downloading anything over the +# network. This can be used to ensure that we get everything from a local +# file:// mirror. +# +# Comment this out if you do need to download new packages from the internet. +# However, once you have downloaded the package you should check them into our +# mirror repository so that other developers will always get it from the mirror +# repo. +BB_NO_NETWORK = "fb-only" + +# Parallelism Options +# +# How many tasks bitbake should run in parallel: +BB_NUMBER_THREADS ?= "${@oe.utils.cpu_count()}" +# How many processes make should run in parallel: +PARALLEL_MAKE ?= "-j ${@oe.utils.cpu_count()}" + +# Machine Selection +MACHINE ??= "yosemite" + +# Build directory locationds. +# +#DL_DIR ?= "${TOPDIR}/downloads" +#SSTATE_DIR ?= "${TOPDIR}/sstate-cache" +#TMPDIR = "${TOPDIR}/tmp" + +# +# Default policy config +# We could eventually create our own distro config if desired, +# but for now we use the standard poky distro settings. +# +DISTRO ?= "poky" + +# Use RPM packages +PACKAGE_CLASSES ?= "package_rpm" + +# Extra image features. +# Currently we do not enable anything extra here. +#EXTRA_IMAGE_FEATURES = "" + +# We build on CentOS 6.3. +# Don't complain about it, even though it isn't in poky's default +# list of supported distros. +SANITY_TESTED_DISTROS_append ?= " CentOS-6.3 \n " + +# +# Additional image features +# +# The following is a list of additional classes to use when building images which +# enable extra features. Some available options which can be included in this variable +# are: +# - 'buildstats' collect build statistics +# - 'image-mklibs' to reduce shared library files size for an image +# - 'image-prelink' in order to prelink the filesystem image +# - 'image-swab' to perform host system intrusion detection +# NOTE: if listing mklibs & prelink both, then make sure mklibs is before prelink +# NOTE: mklibs also needs to be explicitly enabled for a given image, see local.conf.extended +USER_CLASSES ?= "buildstats image-mklibs image-prelink" + +# +# Interactive shell configuration +# +# Under certain circumstances the system may need input from you and to do this it +# can launch an interactive shell. It needs to do this since the build is +# multithreaded and needs to be able to handle the case where more than one parallel +# process may require the user's attention. The default is iterate over the available +# terminal types to find one that works. +# +# Examples of the occasions this may happen are when resolving patches which cannot +# be applied, to use the devshell or the kernel menuconfig +# +# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none +# Note: currently, Konsole support only works for KDE 3.x due to the way +# newer Konsole versions behave +#OE_TERMINAL = "auto" +# By default disable interactive patch resolution (tasks will just fail instead): +PATCHRESOLVE = "noop" + +# +# Disk Space Monitoring during the build +# +# Monitor the disk space during the build. If there is less that 1GB of space or less +# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully +# shutdown the build. If there is less that 100MB or 1K inodes, perform a hard abort +# of the build. The reason for this is that running completely out of space can corrupt +# files and damages the build in ways which may not be easily recoverable. +BB_DISKMON_DIRS = "\ + STOPTASKS,${TMPDIR},1G,100K \ + STOPTASKS,${DL_DIR},1G,100K \ + STOPTASKS,${SSTATE_DIR},1G,100K \ + ABORT,${TMPDIR},100M,1K \ + ABORT,${DL_DIR},100M,1K \ + ABORT,${SSTATE_DIR},100M,1K" + +# +# Shared-state files from other locations +# +# As mentioned above, shared state files are prebuilt cache data objects which can +# used to accelerate build time. This variable can be used to configure the system +# to search other mirror locations for these objects before it builds the data itself. +# +# This can be a filesystem directory, or a remote url such as http or ftp. These +# would contain the sstate-cache results from previous builds (possibly from other +# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the +# cache locations to check for the shared objects. +# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH +# at the end as shown in the examples below. This will be substituted with the +# correct path within the directory structure. +#SSTATE_MIRRORS ?= "\ +#file://.* http://someserver.tld/share/sstate/PATH;downloadfilename=PATH \n \ +#file://.* file:///some/local/dir/sstate/PATH" + + +# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to +# track the version of this file when it was generated. This can safely be ignored if +# this doesn't mean anything to you. +CONF_VERSION = "1" + + +# Update root password to '0penBmc' and change the root shell back to bash. +# This default root password is used at the ODM and system integrator. It will be +# changed during provisioning at the datacenter. +INHERIT += "extrausers" + +EXTRA_USERS_PARAMS = " \ + usermod -s /bin/bash root; \ + usermod -p '\$1\$UGMqyqdG\$FZiylVFmRRfl9Z0Ue8G7e/' root; \ + " diff --git a/meta-facebook/meta-yosemite/conf/machine/yosemite.conf b/meta-facebook/meta-yosemite/conf/machine/yosemite.conf new file mode 100644 index 0000000..cd48ed6 --- /dev/null +++ b/meta-facebook/meta-yosemite/conf/machine/yosemite.conf @@ -0,0 +1,7 @@ +#@TYPE: Machine +#@NAME: Yosemite +#@DESCRIPTION: Machine configuration for Facebook Yosemite + +UBOOT_MACHINE_yosemite = "fbyosemite_config" + +require conf/machine/include/ast1250.inc diff --git a/meta-facebook/meta-yosemite/recipes-core/busybox/busybox/busybox.cfg b/meta-facebook/meta-yosemite/recipes-core/busybox/busybox/busybox.cfg new file mode 100644 index 0000000..66da117 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-core/busybox/busybox/busybox.cfg @@ -0,0 +1,18 @@ +CONFIG_SH_MATH_SUPPORT_64=y +CONFIG_DEVMEM=y +CONFIG_LSUSB=y +CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS=y +CONFIG_RX=y +CONFIG_FLASHCP=y +CONFIG_FLASH_LOCK=y +CONFIG_FLASH_UNLOCK=y +CONFIG_FLASH_ERASEALL=y +CONFIG_TRACEROUTE6=y +CONFIG_VCONFIG=y +# we use the standalone ip util +CONFIG_IP=n +# use dhclient, as udhcpc will flush all v6 link local addresses during renew +CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP=y +CONFIG_UDHCPD=n +CONFIG_UDHCPC=n +CONFIG_UDHCPC6=n diff --git a/meta-facebook/meta-yosemite/recipes-core/busybox/busybox_%.bbappend b/meta-facebook/meta-yosemite/recipes-core/busybox/busybox_%.bbappend new file mode 100644 index 0000000..b8641ee --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-core/busybox/busybox_%.bbappend @@ -0,0 +1,5 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI += " \ + file://busybox.cfg \ + "
\ No newline at end of file diff --git a/meta-facebook/meta-yosemite/recipes-core/images/yosemite-image.bb b/meta-facebook/meta-yosemite/recipes-core/images/yosemite-image.bb new file mode 100644 index 0000000..300f167 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-core/images/yosemite-image.bb @@ -0,0 +1 @@ +include yosemite-image.inc diff --git a/meta-facebook/meta-yosemite/recipes-core/images/yosemite-image.inc b/meta-facebook/meta-yosemite/recipes-core/images/yosemite-image.inc new file mode 100644 index 0000000..5356c20 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-core/images/yosemite-image.inc @@ -0,0 +1,82 @@ +inherit aspeed_uboot_image + +# /dev +require recipes-core/images/aspeed-dev.inc + +# Base this image on core-image-minimal +include recipes-core/images/core-image-minimal.bb + +# Changing the image compression from gz to lzma achieves 30% saving (~3M). +# However, the current u-boot does not have lzma enabled. Stick to gz +# until we generate a new u-boot image. +IMAGE_FSTYPES += "cpio.lzma.u-boot" +UBOOT_IMAGE_ENTRYPOINT = "0x40800000" + +PYTHON_PKGS = " \ + python-core \ + python-io \ + python-json \ + python-shell \ + python-subprocess \ + python-argparse \ + python-ctypes \ + python-datetime \ + python-email \ + python-threading \ + python-mime \ + python-pickle \ + python-misc \ + python-netserver \ + " + +NTP_PKGS = " \ + ntp \ + ntp-utils \ + sntp \ + ntpdate \ + " + +# Include modules in rootfs +IMAGE_INSTALL += " \ + kernel-modules \ + u-boot-fw-utils \ + fbutils \ + fan-ctrl \ + watchdog-ctrl \ + i2c-tools \ + sensor-setup \ + usb-console \ + lmsensors-sensors \ + rest-api \ + bottle \ + ipmid \ + ${PYTHON_PKGS} \ + ${NTP_PKGS} \ + iproute2 \ + dhcp-client \ + fruid \ + ipmbd \ + bic-cached \ + bic-util \ + yosemite-sensors \ + sensor-util \ + sensor-mon \ + gpiod \ + front-paneld \ + power-util \ + consoled \ + cfg-util \ + " + +IMAGE_FEATURES += " \ + ssh-server-openssh \ + tools-debug \ + " + +DISTRO_FEATURES += " \ + ext2 \ + ipv6 \ + nfs \ + usbgadget \ + usbhost \ + " diff --git a/meta-facebook/meta-yosemite/recipes-core/init-ifupdown/files/interfaces b/meta-facebook/meta-yosemite/recipes-core/init-ifupdown/files/interfaces new file mode 100644 index 0000000..36e342e --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-core/init-ifupdown/files/interfaces @@ -0,0 +1,11 @@ +# The loopback interface +auto lo +iface lo inet loopback + +auto eth0 +iface eth0 inet dhcp + +auto usb0 +iface usb0 inet6 static + address fe80::1 + netmask 64 diff --git a/meta-facebook/meta-yosemite/recipes-core/init-ifupdown/init-ifupdown_%.bbappend b/meta-facebook/meta-yosemite/recipes-core/init-ifupdown/init-ifupdown_%.bbappend new file mode 100644 index 0000000..7d74521 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-core/init-ifupdown/init-ifupdown_%.bbappend @@ -0,0 +1,2 @@ + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" diff --git a/meta-facebook/meta-yosemite/recipes-core/sysvinit/sysvinit-inittab_%.bbappend b/meta-facebook/meta-yosemite/recipes-core/sysvinit/sysvinit-inittab_%.bbappend new file mode 100644 index 0000000..9624d65 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-core/sysvinit/sysvinit-inittab_%.bbappend @@ -0,0 +1,2 @@ +# ttyS0 is UART5, BMC's serial port +SERIAL_CONSOLES += "57600;ttyS0" diff --git a/meta-facebook/meta-yosemite/recipes-kernel/linux/linux-aspeed_2.6%.bbappend b/meta-facebook/meta-yosemite/recipes-kernel/linux/linux-aspeed_2.6%.bbappend new file mode 100644 index 0000000..a317986 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-kernel/linux/linux-aspeed_2.6%.bbappend @@ -0,0 +1,5 @@ +LINUX_VERSION_EXTENSION = "-yosemite" + +COMPATIBLE_MACHINE = "yosemite" + +KERNEL_CONFIG_COMMAND = "oe_runmake yosemite_defconfig && oe_runmake oldconfig" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/bic-cached_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/bic-cached_0.1.bb new file mode 100644 index 0000000..ef7a15c --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/bic-cached_0.1.bb @@ -0,0 +1,44 @@ +# Copyright 2015-present Facebook. All Rights Reserved. + +SUMMARY = "Bridge IC Cache Daemon" +DESCRIPTION = "Daemon to provide Bridge IC Cache information." +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://bic-cached.c;beginline=5;endline=17;md5=da35978751a9d71b73679307c4d296ec" + + +DEPENDS_append = "libbic update-rc.d-native" + +SRC_URI = "file://Makefile \ + file://setup-bic-cached.sh \ + file://bic-cached.c \ + " + +S = "${WORKDIR}" + +binfiles = "bic-cached" + +pkgdir = "bic-cached" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + install -m 755 bic-cached ${dst}/bic-cached + ln -snf ../fbpackages/${pkgdir}/bic-cached ${bin}/bic-cached + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-bic-cached.sh ${D}${sysconfdir}/init.d/setup-bic-cached.sh + update-rc.d -r ${D} setup-bic-cached.sh start 66 S . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/bic-cached ${prefix}/local/bin ${sysconfdir} " + +# Inhibit complaints about .debug directories: + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/files/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/files/Makefile new file mode 100644 index 0000000..478b25e --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/files/Makefile @@ -0,0 +1,10 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +all: bic-cached + +bic-cached: bic-cached.c + $(CC) -pthread -lbic -std=c99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o bic-cached diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/files/bic-cached.c b/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/files/bic-cached.c new file mode 100644 index 0000000..3a2dd28 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/files/bic-cached.c @@ -0,0 +1,133 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <openbmc/ipmi.h> +#include <openbmc/ipmb.h> +#include <facebook/bic.h> + +#define LAST_RECORD_ID 0xFFFF +#define MAX_SENSOR_NUM 0xFF +#define BYTES_ENTIRE_RECORD 0xFF + +void +fruid_cache_init(uint8_t slot_id) { + // Initialize Slot0's fruid + int ret; + int i; + char fruid_temp_path[64] = {0}; + char fruid_path[64] = {0}; + + sprintf(fruid_temp_path, "/tmp/tfruid_slot%d.bin", slot_id); + sprintf(fruid_path, "/tmp/fruid_slot%d.bin", slot_id); + + ret = bic_read_fruid(slot_id, 0, fruid_temp_path); + if (ret) { + syslog(LOG_ALERT, "fruid_cache_init: bic_read_fruid returns %d\n", ret); + } + + rename(fruid_temp_path, fruid_path); + + return; +} + +void +sdr_cache_init(uint8_t slot_id) { + int ret; + int fd; + uint8_t rlen; + uint8_t rbuf[MAX_IPMB_RES_LEN] = {0}; + char *path = NULL; + char sdr_temp_path[64] = {0}; + char sdr_path[64] = {0}; + + sprintf(sdr_temp_path, "/tmp/tsdr_slot%d.bin", slot_id); + sprintf(sdr_path, "/tmp/sdr_slot%d.bin", slot_id); + + ipmi_sel_sdr_req_t req; + ipmi_sel_sdr_res_t *res = (ipmi_sel_sdr_res_t *) rbuf; + + req.rsv_id = 0; + req.rec_id = 0; + req.offset = 0; + req.nbytes = BYTES_ENTIRE_RECORD; + + // Read Slot0's SDR records and store + path = sdr_temp_path; + unlink(path); + fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0666); + if (fd < 0) { + syslog(LOG_ALERT, "sdr_cache_init: open fails for path: %s\n", path); + return; + } + + while (1) { + ret = bic_get_sdr(slot_id, &req, res, &rlen); + if (ret) { + syslog(LOG_ALERT, "sdr_cache_init:bic_get_sdr returns %d\n", ret); + continue; + } + + sdr_full_t *sdr = res->data; + + write(fd, sdr, sizeof(sdr_full_t)); + + req.rec_id = res->next_rec_id; + if (req.rec_id == LAST_RECORD_ID) { + // syslog(LOG_INFO, "This record is LAST record\n"); + break; + } + } + + rename(sdr_temp_path, sdr_path); +} + +int +main (int argc, char * const argv[]) +{ + int ret; + ipmi_dev_id_t id = {0}; + uint8_t slot_id; + + if (argc != 2) { + return -1; + } + + slot_id = atoi(argv[1]); + + do { + ret = bic_get_dev_id(slot_id, &id); + sleep(5); + } while (ret != 0); + + fruid_cache_init(slot_id); + sdr_cache_init(slot_id); + + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/files/setup-bic-cached.sh b/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/files/setup-bic-cached.sh new file mode 100644 index 0000000..45eb1e3 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/bic-cached/files/setup-bic-cached.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +### BEGIN INIT INFO +# Provides: setup-bic-cached +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Set Cachcing for Bridge IC info +### END INIT INFO + +. /usr/local/fbpackages/utils/ast-functions + +echo -n "Setup Caching for Bridge IC info.." +if [ $(is_server_prsnt 1) == "1" ]; then + /usr/local/bin/bic-cached 1 > /dev/null 2>&1 & +fi + +if [ $(is_server_prsnt 2) == "1" ]; then +/usr/local/bin/bic-cached 2 > /dev/null 2>&1 & +fi + +if [ $(is_server_prsnt 3) == "1" ]; then +/usr/local/bin/bic-cached 3 > /dev/null 2>&1 & +fi + +if [ $(is_server_prsnt 4) == "1" ]; then +/usr/local/bin/bic-cached 4 > /dev/null 2>&1 & +fi + +echo "done." diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/consoled/consoled_0.1.bbappend b/meta-facebook/meta-yosemite/recipes-yosemite/consoled/consoled_0.1.bbappend new file mode 100644 index 0000000..12a1d17 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/consoled/consoled_0.1.bbappend @@ -0,0 +1,53 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += "file://setup-consoled.sh \ + " + +S = "${WORKDIR}" + + +pkgdir = "consoled" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${dst}/$f + ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f + done + for f in ${otherfiles}; do + install -m 644 $f ${dst}/$f + done + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-consoled.sh ${D}${sysconfdir}/init.d/setup-consoled.sh + update-rc.d -r ${D} setup-consoled.sh start 91 S . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/consoled ${prefix}/local/bin ${sysconfdir} " + +# Inhibit complaints about .debug directories for the sensord binary: + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/consoled/files/setup-consoled.sh b/meta-facebook/meta-yosemite/recipes-yosemite/consoled/files/setup-consoled.sh new file mode 100644 index 0000000..8c50e49 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/consoled/files/setup-consoled.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: setup-consoled +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Setup console history buffering +### END INIT INFO + +. /usr/local/fbpackages/utils/ast-functions + +# TODO: check for the if slot/server is present before starting the daemon +echo -n "Setup console buffering..." + + if [ $(is_server_prsnt 1) == "1" ] ; then + /usr/local/bin/consoled slot1 --buffer + fi + + if [ $(is_server_prsnt 2) == "1" ] ; then + /usr/local/bin/consoled slot2 --buffer + fi + + if [ $(is_server_prsnt 3) == "1" ] ; then + /usr/local/bin/consoled slot3 --buffer + fi + + if [ $(is_server_prsnt 4) == "1" ] ; then + /usr/local/bin/consoled slot4 --buffer + fi + +echo "done." diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/get_fan_speed.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/get_fan_speed.sh new file mode 100755 index 0000000..c77c6f0 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/get_fan_speed.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# +usage() { + echo "Usage: $0 [Fan Unit (0..1)]" >&2 +} + +PWM_DIR=/sys/devices/platform/ast_pwm_tacho.0 +set -e + +# refer to the comments in init_pwn.sh regarding +# the fan unit and tacho mapping +if [ "$#" -eq 0 ]; then + TACHOS="0:0 1:1" +elif [ "$#" -eq 1 ]; then + case "$1" in + "0") + TACHOS="0:0" + ;; + "1") + TACHOS="1:1" + ;; + *) + usage + exit 1 + ;; + esac +else + usage + exit 1 +fi + +for fan_tacho in $TACHOS; do + fan=${fan_tacho%%:*} + tacho=${fan_tacho##*:} + echo "Fan $fan RPM: $(cat $PWM_DIR/tacho${tacho}_rpm)" +done diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/init_pwm.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/init_pwm.sh new file mode 100755 index 0000000..8c8adc6 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/init_pwm.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# +PWM_DIR=/sys/devices/platform/ast_pwm_tacho.0 + +set -e + +# The PWM frequency is + +# clk_source / ((2 ^ division_) * (2 * division_l) * (unit + 1)) +# +# Our clk_source is 24Mhz. 4-pin fans are generally supposed to be driven with +# a 25Khz PWM control signal. Therefore we want the divisor to equal 960. +# +# We also want the unit to be as large as possible, since this controls the +# granularity with which we can modulate the PWM signal. The following +# settings allow us to set the fan from 0 to 100% in increments of 1/96th. +# +# The AST chip supports 3 different PWM clock configurations, but we only use +# type M for now. +echo 0 > $PWM_DIR/pwm_type_m_division_h +echo 5 > $PWM_DIR/pwm_type_m_division_l +echo 95 > $PWM_DIR/pwm_type_m_unit + +# On Yosemite, there are 2 fans connected. +# Each fan uses same PWM input and provide one tacho output. +# Here is the mapping between the fan and PWN/Tacho, +# staring from the one from the edge +# Fan 0: PWM 0, Tacho0 +# Fan 1: PWM 0, Tacho1 + +# For each fan, setting the type, and 100% initially +for pwm in 0 1; do + echo 0 > $PWM_DIR/pwm${pwm}_type + echo 0 > $PWM_DIR/pwm${pwm}_rising + echo 0 > $PWM_DIR/pwm${pwm}_falling + echo 1 > $PWM_DIR/pwm${pwm}_en +done + +# Enable Tach 0..1 +echo 0 > $PWM_DIR/tacho0_source +echo 1 > $PWM_DIR/tacho1_source + +t=0 +while [ $t -le 1 ]; do + echo 1 > $PWM_DIR/tacho${t}_en + t=$((t+1)) +done diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/set_fan_speed.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/set_fan_speed.sh new file mode 100755 index 0000000..49ef55b --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/set_fan_speed.sh @@ -0,0 +1,79 @@ +#!/bin/sh +# +# Copyright 2004-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# +usage() { + echo "Usage: $0 <PERCENT (0..100)> <Fan Unit (0..1)> " >&2 +} + +PWM_DIR=/sys/devices/platform/ast_pwm_tacho.0 + +# The maximum unit setting. +# This should be the value in pwm_type_m_unit plus 1 +PWM_UNIT_MAX=96 + +set -e + +if [ "$#" -ne 2 ] && [ "$#" -ne 1 ]; then + usage + exit 1 +fi + +# refer to the comments in init_pwn.sh regarding +# the fan unit and PWM mapping +if [ "$#" -eq 1 ]; then + PWMS="0:0 1:0" +else + case "$2" in + "0") + PWMS="0:0" + ;; + "1") + PWMS="1:0" + ;; + *) + usage + exit 1 + ;; + esac +fi + +# Convert the percentage to our 1/96th unit. +unit=$(( ( $1 * $PWM_UNIT_MAX ) / 100 )) + +for FAN_PWM in $PWMS; do + FAN_N=${FAN_PWM%%:*} + PWM_N=${FAN_PWM##*:} + if [ "$unit" -eq 0 ]; then + # For 0%, turn off the PWM entirely + echo 0 > $PWM_DIR/pwm${PWM_N}_en + else + if [ "$unit" -eq $PWM_UNIT_MAX ]; then + # For 100%, set falling and rising to the same value + unit=0 + fi + + # always use type M. refer to the comments in init_pwm.sh + echo 0 > $PWM_DIR/pwm${PWM_N}_type + echo 0 > $PWM_DIR/pwm${PWM_N}_rising + echo "$unit" > $PWM_DIR/pwm${PWM_N}_falling + echo 1 > $PWM_DIR/pwm${PWM_N}_en + fi + + echo "Successfully set fan ${FAN_N} (PWM: $PWM_N) speed to $1%" +done diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/setup-fan.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/setup-fan.sh new file mode 100644 index 0000000..72016d0 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl/setup-fan.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: setup-fan +# Required-Start: board-id +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Set fan speed +### END INIT INFO + +. /usr/local/fbpackages/utils/ast-functions + +echo -n "Setup fan speed... " +/usr/local/bin/init_pwm.sh +/usr/local/bin/set_fan_speed.sh 50 +/usr/local/bin/fand +echo "done." diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl_0.1.bbappend b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl_0.1.bbappend new file mode 100644 index 0000000..d5659ae --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fan-ctrl/fan-ctrl_0.1.bbappend @@ -0,0 +1,64 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +DEPENDS_append = "update-rc.d-native libyosemite-sensor" + +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" +SRC_URI += "file://get_fan_speed.sh \ + file://init_pwm.sh \ + file://set_fan_speed.sh \ + file://setup-fan.sh \ + " + +S = "${WORKDIR}" + +binfiles += "get_fan_speed.sh \ + init_pwm.sh \ + set_fan_speed.sh \ + " + +CXXFLAGS_prepend = "-DCONFIG_YOSEMITE " +LDFLAGS_append = " -lyosemite_sensor" + +pkgdir = "fan_ctrl" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${dst}/$f + ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f + done + for f in ${otherfiles}; do + install -m 644 $f ${dst}/$f + done + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-fan.sh ${D}${sysconfdir}/init.d/setup-fan.sh + update-rc.d -r ${D} setup-fan.sh start 91 S . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/fan_ctrl ${prefix}/local/bin ${sysconfdir} " + +# Inhibit complaints about .debug directories for the fand binary: + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/Makefile new file mode 100644 index 0000000..12cb085 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libbic.so + +libbic.so: bic.c + $(CC) $(CFLAGS) -fPIC -c -o bic.o bic.c + $(CC) -lipmb -shared -o libbic.so bic.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libbic.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c new file mode 100644 index 0000000..55cd56b --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.c @@ -0,0 +1,466 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdint.h> +#include <fcntl.h> +#include "bic.h" + +#define FRUID_READ_COUNT_MAX 0x30 +#define SDR_READ_COUNT_MAX 0x1A + +enum { + IPMB_BUS_SLOT1 = 3, + IPMB_BUS_SLOT2 = 1, + IPMB_BUS_SLOT3 = 7, + IPMB_BUS_SLOT4 = 5, +}; + +#pragma pack(push, 1) +typedef struct _sdr_rec_hdr_t { + uint16_t rec_id; + uint8_t ver; + uint8_t type; + uint8_t len; +} sdr_rec_hdr_t; +#pragma pack(pop) + +// Common IPMB Wrapper function + +static int +get_ipmb_bus_id(uint8_t slot_id) { + int bus_id; + + switch(slot_id) { + case 1: + bus_id = IPMB_BUS_SLOT1; + break; + case 2: + bus_id = IPMB_BUS_SLOT2; + break; + case 3: + bus_id = IPMB_BUS_SLOT3; + break; + case 4: + bus_id = IPMB_BUS_SLOT4; + break; + default: + bus_id = -1; + break; + } + + return bus_id; +} + +static int +bic_ipmb_wrapper(uint8_t slot_id, uint8_t netfn, uint8_t cmd, + uint8_t *txbuf, uint8_t txlen, + uint8_t *rxbuf, uint8_t *rxlen) { + ipmb_req_t *req; + ipmb_res_t *res; + uint8_t rbuf[MAX_IPMB_RES_LEN] = {0}; + uint8_t tbuf[MAX_IPMB_RES_LEN] = {0}; + uint8_t tlen = 0; + uint8_t rlen = 0; + int count = 0; + int i = 0; + int ret; + uint8_t bus_id; + + ret = get_ipmb_bus_id(slot_id); + if (ret < 0) { + printf("bic_ipmb_wrapper: Wrong Slot ID %d\n", slot_id); + return ret; + } + + bus_id = (uint8_t) ret; + + req = (ipmb_req_t*)tbuf; + + req->res_slave_addr = BRIDGE_SLAVE_ADDR << 1; + req->netfn_lun = netfn << LUN_OFFSET; + req->hdr_cksum = req->res_slave_addr + + req->netfn_lun; + req->hdr_cksum = ZERO_CKSUM_CONST - req->hdr_cksum; + + req->req_slave_addr = BMC_SLAVE_ADDR << 1; + req->seq_lun = 0x00; + req->cmd = cmd; + + //copy the data to be send + if (txlen) { + memcpy(req->data, txbuf, txlen); + } + + tlen = IPMB_HDR_SIZE + IPMI_REQ_HDR_SIZE + txlen; + + // Invoke IPMB library handler + lib_ipmb_handle(bus_id, tbuf, tlen, &rbuf, &rlen); + if (rlen == 0) { + printf("bic_ipmb_wrapper: Zero bytes received\n"); + return -1; + } + + // Handle IPMB response + res = (ipmb_res_t*) rbuf; + + if (res->cc) { + printf("bic_ipmb_wrapper: Completion Code: 0x%X\n", res->cc); + return -1; + } + + // copy the received data back to caller + *rxlen = rlen - IPMB_HDR_SIZE - IPMI_RESP_HDR_SIZE; + memcpy(rxbuf, res->data, *rxlen); + + return 0; +} + +// Get Device ID +int +bic_get_dev_id(uint8_t slot_id, ipmi_dev_id_t *dev_id) { + uint8_t rlen = 0; + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_APP_REQ, CMD_APP_GET_DEVICE_ID, NULL, 0, (uint8_t *) dev_id, &rlen); + + return ret; +} + +// Get GPIO value and configuration +int +bic_get_gpio(uint8_t slot_id, bic_gpio_t *gpio) { + uint8_t rlen = 0; + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_GPIO, NULL, 0, (uint8_t*) gpio, &rlen); + + return ret; +} + +int +bic_get_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config) { + uint8_t tbuf[4] = {0}; + uint8_t rlen = 0; + uint8_t tlen = 0; + uint32_t pin; + int ret; + + pin = 1 << gpio; + + tbuf[0] = pin & 0xFF; + tbuf[1] = (pin >> 8) & 0xFF; + tbuf[2] = (pin >> 16) & 0xFF; + tbuf[3] = (pin >> 24) & 0xFF; + + tlen = 4; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_GPIO_CONFIG, tbuf, tlen, (uint8_t *) gpio_config, &rlen); + + return ret; +} + +int +bic_set_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config) { + uint8_t tbuf[5] = {0}; + uint8_t rlen = 0; + uint8_t tlen = 0; + uint32_t pin; + uint8_t res; + int ret; + + pin = 1 << gpio; + + tbuf[0] = pin & 0xFF; + tbuf[1] = (pin >> 8) & 0xFF; + tbuf[2] = (pin >> 16) & 0xFF; + tbuf[3] = (pin >> 24) & 0xFF; + tbuf[4] = (*(uint8_t *) gpio_config) & 0x1F; + + tlen = 5; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_SET_GPIO_CONFIG, + tbuf, tlen, &res, &rlen); + return ret; +} + +// Get BIC Configuration +int +bic_get_config(uint8_t slot_id, bic_config_t *cfg) { + uint8_t rlen = 0; + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_CONFIG, + NULL, 0x00, (uint8_t *) cfg, &rlen); + return ret; +} + +// Set BIC Configuration +int +bic_set_config(uint8_t slot_id, bic_config_t *cfg) { + uint8_t rlen = 0; + uint8_t rbuf[4] = {0}; + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_SET_CONFIG, + (uint8_t *) cfg, 1, rbuf, &rlen); + return ret; +} + +// Read POST Buffer +int +bic_get_post_buf(uint8_t slot_id, uint8_t *buf, uint8_t *len) { + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_OEM_1S_REQ, CMD_OEM_1S_GET_POST_BUF, NULL, 0, buf, len); + + return ret; +} + +// Read 1S server's FRUID +int +bic_get_fruid_info(uint8_t slot_id, uint8_t fru_id, ipmi_fruid_info_t *info) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_FRUID_INFO, &fru_id, 1, (uint8_t *) info, &rlen); + + return ret; +} + +static int +_read_fruid(uint8_t slot_id, uint8_t fru_id, uint32_t offset, uint8_t count, uint8_t *rbuf, uint8_t *rlen) { + int ret; + uint8_t tbuf[4] = {0}; + uint8_t tlen = 0; + + tbuf[0] = fru_id; + tbuf[1] = offset & 0xFF; + tbuf[2] = (offset >> 8) & 0xFF; + tbuf[3] = count; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_READ_FRUID_DATA, tbuf, 4, rbuf, rlen); + + return ret; +} + +int +bic_read_fruid(uint8_t slot_id, uint8_t fru_id, const char *path) { + int ret; + uint32_t nread; + uint32_t offset; + uint8_t count; + uint8_t rbuf[256] = {0}; + uint8_t rlen = 0; + int fd; + ipmi_fruid_info_t info; + + // Remove the file if exists already + unlink(path); + + // Open the file exclusively for write + fd = open(path, O_WRONLY | O_CREAT | O_EXCL, 0666); + if (fd < 0) { + printf("bic_read_fruid: open fails for path: %s\n", path); + goto error_exit; + } + + // Read the FRUID information + ret = bic_get_fruid_info(slot_id, fru_id, &info); + if (ret) { + printf("bic_read_fruid: bic_read_fruid_info returns %d\n", ret); + goto error_exit; + } + + // Indicates the size of the FRUID + nread = (info.size_msb << 8) + (info.size_lsb); + + // Read chunks of FRUID binary data in a loop + offset = 0; + while (nread > 0) { + if (nread > FRUID_READ_COUNT_MAX) { + count = FRUID_READ_COUNT_MAX; + } else { + count = nread; + } + + ret = _read_fruid(slot_id, fru_id, offset, count, rbuf, &rlen); + if (ret) { + printf("bic_read_fruid: ipmb_wrapper fails\n"); + goto error_exit; + } + + // Ignore the first byte as it indicates length of response + write(fd, &rbuf[1], rlen-1); + + // Update offset + offset += (rlen-1); + nread -= (rlen-1); + } + +error_exit: + if (fd > 0 ) { + close(fd); + } + + return ret; +} + +// Read System Event Log (SEL) +int +bic_get_sel_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SEL_INFO, NULL, 0, (uint8_t *)info, &rlen); + + return ret; +} + +static int +_get_sel_rsv(uint8_t slot_id, uint16_t *rsv) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_RSV_SEL, NULL, 0, (uint8_t *) rsv, &rlen); + return ret; +} + +int +bic_get_sel(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen) { + + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SEL, (uint8_t *)req, sizeof(ipmi_sel_sdr_req_t), (uint8_t*)res, rlen); + + return ret; +} + +// Read Sensor Data Records (SDR) +int +bic_get_sdr_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SDR_INFO, NULL, 0, (uint8_t *) info, &rlen); + + return ret; +} + +static int +_get_sdr_rsv(uint8_t slot_id, uint16_t *rsv) { + int ret; + uint8_t rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_RSV_SDR, NULL, 0, (uint8_t *) rsv, &rlen); + + return ret; +} + +static int +_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen) { + int ret; + + ret = bic_ipmb_wrapper(slot_id, NETFN_STORAGE_REQ, CMD_STORAGE_GET_SDR, (uint8_t *)req, sizeof(ipmi_sel_sdr_req_t), (uint8_t*)res, rlen); + + return ret; +} + +int +bic_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen) { + int ret; + uint8_t tbuf[MAX_IPMB_RES_LEN] = {0}; + uint8_t tlen; + uint8_t len; + ipmi_sel_sdr_res_t *tres; + sdr_rec_hdr_t *hdr; + + tres = (ipmi_sel_sdr_res_t *) tbuf; + + // Get SDR reservation ID for the given record + ret = _get_sdr_rsv(slot_id, &req->rsv_id); + if (ret) { + printf("bic_read_sdr: _get_sdr_rsv returns %d\n", ret); + return ret; + } + + // Initialize the response length to zero + *rlen = 0; + + // Read SDR Record Header + req->offset = 0; + req->nbytes = sizeof(sdr_rec_hdr_t); + + ret = _get_sdr(slot_id, req, tbuf, &tlen); + if (ret) { + printf("bic_read_sdr: _get_sdr returns %d\n", ret); + return ret; + } + + // Copy the next record id to response + res->next_rec_id = tres->next_rec_id; + + // Copy the header excluding first two bytes(next_rec_id) + memcpy(res->data, tres->data, tlen-2); + + // Update response length and offset for next request + *rlen += tlen-2; + req->offset = tlen-2; + + // Find length of data from header info + hdr = (sdr_rec_hdr_t *) tres->data; + len = hdr->len; + + // Keep reading chunks of SDR record in a loop + while (len > 0) { + if (len > SDR_READ_COUNT_MAX) { + req->nbytes = SDR_READ_COUNT_MAX; + } else { + req->nbytes = len; + } + + ret = _get_sdr(slot_id, req, tbuf, &tlen); + if (ret) { + printf("bic_read_sdr: _get_sdr returns %d\n", ret); + return ret; + } + + // Copy the data excluding the first two bytes(next_rec_id) + memcpy(&res->data[req->offset], tres->data, tlen-2); + + // Update response length, offset for next request, and remaining length + *rlen += tlen-2; + req->offset += tlen-2; + len -= tlen-2; + } + + return 0; +} + +int +bic_read_sensor(uint8_t slot_id, uint8_t sensor_num, ipmi_sensor_reading_t *sensor) { + int ret; + int rlen = 0; + + ret = bic_ipmb_wrapper(slot_id, NETFN_SENSOR_REQ, CMD_SENSOR_GET_SENSOR_READING, (uint8_t *)&sensor_num, 1, (uint8_t *)sensor, &rlen); + + return ret; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.h new file mode 100644 index 0000000..47b0baa --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/bic/bic.h @@ -0,0 +1,156 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __BIC_H__ +#define __BIC_H__ + +#include <openbmc/ipmi.h> +#include <openbmc/ipmb.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_GPIO_PINS 32 + +// GPIO PINS +enum { + PWRGOOD_CPU = 0x0, + PWRGD_PCH_PWROK, + PVDDR_VRHOT_N, + PVCCIN_VRHOT_N, + FM_FAST_PROCHOT_N, + PCHHOT_CPU_N, + FM_CPLD_CPU_DIMM_EVENT_CO_N, + FM_CPLD_BDXDE_THERMTRIP_N, + THERMTRIP_PCH_N, + FM_CPLD_FIVR_FAULT, + FM_BDXDE_CATERR_LVT3_N, + FM_BDXDE_ERR2_LVT3_N, + FM_BDXDE_ERR1_LVT3_N, + FM_BDXDE_ERR0_LVT3_N, + SLP_S4_N, + FM_NMI_EVENT_BMC_N, + FM_SMI_BMC_N, + RST_PLTRST_BMC_N, + FP_RST_BTN_BUF_N, + BMC_RST_BTN_OUT_N, + FM_BDE_POST_CMPLT_N, + FM_BDXDE_SLP3_N, + FM_PWR_LED_N, + PWRGD_PVCCIN, + SVR_ID0, + SVR_ID1, + SVR_ID2, + SVR_ID3, + BMC_READY_N, + RESERVED_29, + RESERVED_30, + RESERVED_31, +}; + +// Bridge IC Spec +typedef struct _bic_gpio_t { + uint32_t pwrgood_cpu:1; + uint32_t pwrgd_pch_pwrok:1; + uint32_t pvddr_vrhot_n:1; + uint32_t pvccin_vrhot_n:1; + uint32_t fm_fast_prochot_n:1; + uint32_t pchhot_cpu_n:1; + uint32_t fm_cpld_cpu_dimm_event_c0_n:1; + uint32_t fm_cpld_bdxde_thermtrip_n:1; + uint32_t thermtrip_pch_n:1; + uint32_t fm_cpld_fivr_fault:1; + uint32_t fm_bdxde_caterr_lvt3_n:1; + uint32_t fm_bdxde_err_lvt3_n:3; + uint32_t slp_s4_n:1; + uint32_t fm_nmi_event_bmc_n:1; + uint32_t fm_smi_bmc_n:1; + uint32_t rst_pltrst_bmc_n:1; + uint32_t fp_rst_btn_buf_n:1; + uint32_t bmc_rst_btn_out_n:1; + uint32_t fm_bde_post_cmplt_n:1; + uint32_t fm_bdxde_slp3_n:1; + uint32_t fm_pwr_led_n:1; + uint32_t pwrgd_pvccin:1; + uint32_t svr_id:4; + uint32_t bmc_ready_n:1; + uint32_t bmc_com_sw_n:1; + uint32_t rsvd:2; +} bic_gpio_t; + +typedef union _bic_gpio_u { + uint8_t gpio[4]; + bic_gpio_t bits; +} bic_gpio_u; + +typedef struct _bic_gpio_config_t { + uint8_t dir:1; + uint8_t ie:1; + uint8_t edge:1; + uint8_t trig:2; +} bic_gpio_config_t; + +typedef union _bic_gpio_config_u { + uint8_t config; + bic_gpio_config_t bits; +} bic_gpio_config_u; + +typedef struct _bic_config_t { + uint8_t sol:1; + uint8_t post:1; + uint8_t kcs:1; + uint8_t ipmb:1; + uint8_t rsvd:4; +} bic_config_t; + +typedef union _bic_config_u { + uint8_t config; + bic_config_t bits; +} bic_config_u; + +int bic_get_dev_id(uint8_t slot_id, ipmi_dev_id_t *id); + +int bic_get_bic_config(uint8_t slot_id, bic_config_t *cfg); +int bic_set_bic_config(uint8_t slot_id, bic_config_t *cfg); + +int bic_get_gpio(uint8_t slot_id, bic_gpio_t *gpio); +int bic_get_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config); +int bic_set_gpio_config(uint8_t slot_id, uint8_t gpio, bic_gpio_config_t *gpio_config); +int bic_get_post_buf(uint8_t slot_id, uint8_t *buf, uint8_t *len); + +int bic_get_fruid_info(uint8_t slot_id, uint8_t fru_id, ipmi_fruid_info_t *info); +int bic_read_fruid(uint8_t slot_id, uint8_t fru_id, const char *path); + +int bic_get_sel_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info); +int bic_get_sel_rsv(uint8_t slot_id, uint16_t *rsv); +int bic_get_sel(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen); + +int bic_get_sdr_info(uint8_t slot_id, ipmi_sel_sdr_info_t *info); +int bic_get_sdr_rsv(uint8_t slot_id, uint16_t *rsv); +int bic_get_sdr(uint8_t slot_id, ipmi_sel_sdr_req_t *req, ipmi_sel_sdr_res_t *res, uint8_t *rlen); + +int bic_read_sensor(uint8_t slot_id, uint8_t sensor_num, ipmi_sensor_reading_t *sensor); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __BIC_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/Makefile new file mode 100644 index 0000000..bab4007 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libpal.so + +libpal.so: pal.c + $(CC) $(CFLAGS) -fPIC -c -o pal.o pal.c + $(CC) -lbic -lyosemite_common -lyosemite_fruid -lyosemite_sensor -shared -o libpal.so pal.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libpal.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.c new file mode 100644 index 0000000..93a5fbf --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.c @@ -0,0 +1,1151 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdint.h> +#include <stdbool.h> +#include <fcntl.h> +#include <errno.h> +#include <syslog.h> +#include <sys/mman.h> +#include <string.h> +#include "pal.h" + +#define BIT(value, index) ((value >> index) & 1) + +#define YOSEMITE_PLATFORM_NAME "Yosemite" +#define LAST_KEY "last_key" +#define YOSEMITE_MAX_NUM_SLOTS 4 +#define GPIO_VAL "/sys/class/gpio/gpio%d/value" +#define GPIO_DIR "/sys/class/gpio/gpio%d/direction" + +#define GPIO_HAND_SW_ID1 138 +#define GPIO_HAND_SW_ID2 139 +#define GPIO_HAND_SW_ID4 140 +#define GPIO_HAND_SW_ID8 141 + +#define GPIO_RST_BTN 144 +#define GPIO_PWR_BTN 24 + +#define GPIO_USB_SW0 36 +#define GPIO_USB_SW1 37 + +#define GPIO_UART_SEL0 32 +#define GPIO_UART_SEL1 33 +#define GPIO_UART_SEL2 34 +#define GPIO_UART_RX 35 + +#define GPIO_POSTCODE_0 48 +#define GPIO_POSTCODE_1 49 +#define GPIO_POSTCODE_2 50 +#define GPIO_POSTCODE_3 51 +#define GPIO_POSTCODE_4 124 +#define GPIO_POSTCODE_5 125 +#define GPIO_POSTCODE_6 126 +#define GPIO_POSTCODE_7 127 + +#define GPIO_DBG_CARD_PRSNT 137 + +#define PAGE_SIZE 0x1000 +#define AST_SCU_BASE 0x1e6e2000 +#define PIN_CTRL1_OFFSET 0x80 +#define PIN_CTRL2_OFFSET 0x84 + +#define UART1_TXD (1 << 22) +#define UART2_TXD (1 << 30) +#define UART3_TXD (1 << 22) +#define UART4_TXD (1 << 30) + +#define BIT(v, i) ((v >> i) & 1) +#define DELAY_GRACEFUL_SHUTDOWN 1 +#define DELAY_POWER_OFF 5 + +static uint8_t gpio_rst_btn[5] = { 0, 57, 56, 59, 58 }; +static uint8_t gpio_led[5] = { 0, 97, 96, 99, 98 }; +static uint8_t gpio_prsnt[5] = { 0, 61, 60, 63, 62 }; +static uint8_t gpio_power[5] = { 0, 27, 25, 31, 29 }; +const char pal_fru_list[] = "all, slot1, slot2, slot3, slot4, spb, nic"; +const char pal_server_list[] = "slot1, slot2, slot3, slot4"; + +char * key_list[] = { +"pwr_server1_last_state", +"pwr_server2_last_state", +"pwr_server3_last_state", +"pwr_server4_last_state", +"slot1_por_cfg", +"slot2_por_cfg", +"slot3_por_cfg", +"slot4_por_cfg", +/* Add more Keys here */ +LAST_KEY /* This is the last key of the list */ +}; + +// Helper Functions +static int +read_device(const char *device, int *value) { + FILE *fp; + int rc; + + fp = fopen(device, "r"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device %s", device); + return err; + } + + rc = fscanf(fp, "%d", value); + fclose(fp); + if (rc != 1) { + syslog(LOG_INFO, "failed to read device %s", device); + return ENOENT; + } else { + return 0; + } +} + +static int +write_device(const char *device, const char *value) { + FILE *fp; + int rc; + + fp = fopen(device, "w"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device for write %s", device); + return err; + } + + rc = fputs(value, fp); + fclose(fp); + + if (rc < 0) { + syslog(LOG_INFO, "failed to write device %s", device); + return ENOENT; + } else { + return 0; + } +} + +// Power On the server in a given slot +static int +server_power_on(uint8_t slot_id) { + char vpath[64] = {0}; + + sprintf(vpath, GPIO_VAL, gpio_power[slot_id]); + + if (write_device(vpath, "1")) { + return -1; + } + + if (write_device(vpath, "0")) { + return -1; + } + + sleep(1); + + if (write_device(vpath, "1")) { + return -1; + } + + return 0; +} + +// Power Off the server in given slot +static int +server_power_off(uint8_t slot_id, bool gs_flag) { + char vpath[64] = {0}; + + if (slot_id < 1 || slot_id > 4) { + return -1; + } + + sprintf(vpath, GPIO_VAL, gpio_power[slot_id]); + + if (write_device(vpath, "1")) { + return -1; + } + + sleep(1); + + if (write_device(vpath, "0")) { + return -1; + } + + if (gs_flag) { + sleep(DELAY_GRACEFUL_SHUTDOWN); + } else { + sleep(DELAY_POWER_OFF); + } + + if (write_device(vpath, "1")) { + return -1; + } + + return 0; +} + +// Debug Card's UART and BMC/SoL port share UART port and need to enable only +// one TXD i.e. either BMC's TXD or Debug Port's TXD. +static int +control_sol_txd(uint8_t slot) { + uint32_t scu_fd; + uint32_t ctrl; + void *scu_reg; + void *scu_pin_ctrl1; + void *scu_pin_ctrl2; + + scu_fd = open("/dev/mem", O_RDWR | O_SYNC ); + if (scu_fd < 0) { + syslog(LOG_ALERT, "control_sol_txd: open fails\n"); + return -1; + } + + scu_reg = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, scu_fd, + AST_SCU_BASE); + scu_pin_ctrl1 = (char*)scu_reg + PIN_CTRL1_OFFSET; + scu_pin_ctrl2 = (char*)scu_reg + PIN_CTRL2_OFFSET; + + switch(slot) { + case 1: + // Disable UART2's TXD and enable others + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl |= UART1_TXD; + ctrl &= (~UART2_TXD); //Disable + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl |= UART3_TXD | UART4_TXD; + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + case 2: + // Disable UART1's TXD and enable others + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl &= (~UART1_TXD); // Disable + ctrl |= UART2_TXD; + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl |= UART3_TXD | UART4_TXD; + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + case 3: + // Disable UART4's TXD and enable others + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl |= UART1_TXD | UART2_TXD; + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl |= UART3_TXD; + ctrl &= (~UART4_TXD); // Disable + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + case 4: + // Disable UART3's TXD and enable others + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl |= UART1_TXD | UART2_TXD; + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl &= (~UART3_TXD); // Disable + ctrl |= UART4_TXD; + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + default: + // Any other slots we need to enable all TXDs + ctrl = *(volatile uint32_t*) scu_pin_ctrl2; + ctrl |= UART1_TXD | UART2_TXD; + *(volatile uint32_t*) scu_pin_ctrl2 = ctrl; + + ctrl = *(volatile uint32_t*) scu_pin_ctrl1; + ctrl |= UART3_TXD | UART4_TXD; + *(volatile uint32_t*) scu_pin_ctrl1 = ctrl; + break; + } + + munmap(scu_reg, PAGE_SIZE); + close(scu_fd); + + return 0; +} + +// Display the given POST code using GPIO port +static int +pal_post_display(uint8_t status) { + char path[64] = {0}; + int ret; + char *val; + + syslog(LOG_ALERT, "pal_post_display: status is %d\n", status); + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_0); + + if (BIT(status, 0)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_1); + if (BIT(status, 1)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_2); + if (BIT(status, 2)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_3); + if (BIT(status, 3)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_4); + if (BIT(status, 4)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_5); + if (BIT(status, 5)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_6); + if (BIT(status, 6)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + + sprintf(path, GPIO_VAL, GPIO_POSTCODE_7); + if (BIT(status, 7)) { + val = "1"; + } else { + val = "0"; + } + + ret = write_device(path, val); + if (ret) { + goto post_exit; + } + +post_exit: + if (ret) { + syslog(LOG_ALERT, "write_device failed for %s\n", path); + return -1; + } else { + return 0; + } +} + +// Platform Abstraction Layer (PAL) Functions +int +pal_get_platform_name(char *name) { + strcpy(name, YOSEMITE_PLATFORM_NAME); + + return 0; +} + +int +pal_get_num_slots(uint8_t *num) { + *num = YOSEMITE_MAX_NUM_SLOTS; + + return 0; +} + +int +pal_is_server_prsnt(uint8_t slot_id, uint8_t *status) { + int val; + char path[64] = {0}; + + if (slot_id < 1 || slot_id > 4) { + return -1; + } + + sprintf(path, GPIO_VAL, gpio_prsnt[slot_id]); + + if (read_device(path, &val)) { + return -1; + } + + if (val == 0x0) { + *status = 1; + } else { + *status = 0; + } + + return 0; +} + +int +pal_is_debug_card_prsnt(uint8_t *status) { + int val; + char path[64] = {0}; + + sprintf(path, GPIO_VAL, GPIO_DBG_CARD_PRSNT); + + if (read_device(path, &val)) { + return -1; + } + + // TODO: Logic is reversed until DVT board with h/w fix + if (val == 0x0) { + *status = 0; + } else { + *status = 1; + } + + return 0; +} + +int +pal_get_server_power(uint8_t slot_id, uint8_t *status) { + int ret; + bic_gpio_t gpio; + + ret = bic_get_gpio(slot_id, &gpio); + if (ret) { + return ret; + } + + if (gpio.pwrgood_cpu) { + *status = SERVER_POWER_ON; + } else { + *status = SERVER_POWER_OFF; + } + + return 0; +} + +// Power Off, Power On, or Power Reset the server in given slot +int +pal_set_server_power(uint8_t slot_id, uint8_t cmd) { + uint8_t status; + bool gs_flag = false; + + if (slot_id < 1 || slot_id > 4) { + return -1; + } + + if (pal_get_server_power(slot_id, &status) < 0) { + return -1; + } + + switch(cmd) { + case SERVER_POWER_ON: + if (status == SERVER_POWER_ON) + return 1; + else + return server_power_on(slot_id); + break; + + case SERVER_POWER_OFF: + if (status == SERVER_POWER_OFF) + return 1; + else + return server_power_off(slot_id, gs_flag); + break; + + case SERVER_POWER_CYCLE: + if (status == SERVER_POWER_ON) + return (server_power_off(slot_id, gs_flag) || server_power_on(slot_id)); + else if (status == SERVER_POWER_OFF) + return (server_power_on(slot_id)); + break; + + case SERVER_GRACEFUL_SHUTDOWN: + if (status == SERVER_POWER_OFF) + return 1; + else + gs_flag = true; + return server_power_off(slot_id, gs_flag); + break; + default: + return -1; + } + + return 0; +} + +int +pal_sled_cycle(void) { + // Remove the adm1275 module as the HSC device is busy + system("rmmod adm1275"); + + // Send command to HSC power cycle + system("i2cset -y 10 0x40 0xd9 c"); + + return 0; +} + +// Read the Front Panel Hand Switch and return the position +int +pal_get_hand_sw(uint8_t *pos) { + char path[64] = {0}; + int id1, id2, id4, id8; + uint8_t loc; + // Read 4 GPIOs to read the current position + // id1: GPIOR2(138) + // id2: GPIOR3(139) + // id4: GPIOR4(140) + // id8: GPIOR5(141) + + // Read ID1 + sprintf(path, GPIO_VAL, GPIO_HAND_SW_ID1); + if (read_device(path, &id1)) { + return -1; + } + + // Read ID2 + sprintf(path, GPIO_VAL, GPIO_HAND_SW_ID2); + if (read_device(path, &id2)) { + return -1; + } + + // Read ID4 + sprintf(path, GPIO_VAL, GPIO_HAND_SW_ID4); + if (read_device(path, &id4)) { + return -1; + } + + // Read ID8 + sprintf(path, GPIO_VAL, GPIO_HAND_SW_ID8); + if (read_device(path, &id8)) { + return -1; + } + + loc = ((id8 << 3) | (id4 << 2) | (id2 << 1) | (id1)); + + switch(loc) { + case 1: + case 6: + *pos = HAND_SW_SERVER1; + break; + case 2: + case 7: + *pos = HAND_SW_SERVER2; + break; + case 3: + case 8: + *pos = HAND_SW_SERVER3; + break; + case 4: + case 9: + *pos = HAND_SW_SERVER4; + break; + default: + *pos = HAND_SW_BMC; + break; + } + + return 0; +} + +// Return the Front panel Power Button +int +pal_get_pwr_btn(uint8_t *status) { + char path[64] = {0}; + int val; + + sprintf(path, GPIO_VAL, GPIO_PWR_BTN); + if (read_device(path, &val)) { + return -1; + } + + if (val) { + *status = 0x0; + } else { + *status = 0x1; + } + + return 0; +} + +// Return the front panel's Reset Button status +int +pal_get_rst_btn(uint8_t *status) { + char path[64] = {0}; + int val; + + sprintf(path, GPIO_VAL, GPIO_RST_BTN); + if (read_device(path, &val)) { + return -1; + } + + if (val) { + *status = 0x0; + } else { + *status = 0x1; + } + + return 0; +} + +// Update the Reset button input to the server at given slot +int +pal_set_rst_btn(uint8_t slot, uint8_t status) { + char path[64] = {0}; + char *val; + + if (slot < 1 || slot > 4) { + return -1; + } + + if (status) { + val = "0"; + } else { + val = "1"; + } + + sprintf(path, GPIO_VAL, gpio_rst_btn[slot]); + if (write_device(path, val)) { + return -1; + } + + return 0; +} + +// Update the LED for the given slot with the status +int +pal_set_led(uint8_t slot, uint8_t status) { + char path[64] = {0}; + char *val; + + if (slot < 1 || slot > 4) { + return -1; + } + + if (status) { + val = "1"; + } else { + val = "0"; + } + + sprintf(path, GPIO_VAL, gpio_led[slot]); + if (write_device(path, val)) { + return -1; + } + + return 0; +} + +// Update the USB Mux to the server at given slot +int +pal_switch_usb_mux(uint8_t slot) { + char *gpio_sw0, *gpio_sw1; + char path[64] = {0}; + + // Based on the USB mux table in Schematics + switch(slot) { + case 1: + gpio_sw0 = "1"; + gpio_sw1 = "0"; + break; + case 2: + gpio_sw0 = "0"; + gpio_sw1 = "0"; + break; + case 3: + gpio_sw0 = "1"; + gpio_sw1 = "1"; + break; + case 4: + gpio_sw0 = "0"; + gpio_sw1 = "1"; + break; + default: + // Default is for BMC itself + return 0; + } + + sprintf(path, GPIO_VAL, GPIO_USB_SW0); + if (write_device(path, gpio_sw0) < 0) { + syslog(LOG_ALERT, "write_device failed for %s\n", path); + return -1; + } + + sprintf(path, GPIO_VAL, GPIO_USB_SW1); + if (write_device(path, gpio_sw1) < 0) { + syslog(LOG_ALERT, "write_device failed for %s\n", path); + return -1; + } + + return 0; +} + +// Switch the UART mux to the given slot +int +pal_switch_uart_mux(uint8_t slot) { + char * gpio_uart_sel0; + char * gpio_uart_sel1; + char * gpio_uart_sel2; + char * gpio_uart_rx; + char path[64] = {0}; + int ret; + + // Refer the UART select table in schematic + switch(slot) { + case 1: + gpio_uart_sel2 = "0"; + gpio_uart_sel1 = "0"; + gpio_uart_sel0 = "1"; + gpio_uart_rx = "0"; + break; + case 2: + gpio_uart_sel2 = "0"; + gpio_uart_sel1 = "0"; + gpio_uart_sel0 = "0"; + gpio_uart_rx = "0"; + break; + case 3: + gpio_uart_sel2 = "0"; + gpio_uart_sel1 = "1"; + gpio_uart_sel0 = "1"; + gpio_uart_rx = "0"; + break; + case 4: + gpio_uart_sel2 = "0"; + gpio_uart_sel1 = "1"; + gpio_uart_sel0 = "0"; + gpio_uart_rx = "0"; + break; + default: + // for all other cases, assume BMC + gpio_uart_sel2 = "1"; + gpio_uart_sel1 = "0"; + gpio_uart_sel0 = "0"; + gpio_uart_rx = "1"; + break; + } + + // Diable TXD path from BMC to avoid conflict with SoL + ret = control_sol_txd(slot); + if (ret) { + goto uart_exit; + } + + // Enable Debug card path + sprintf(path, GPIO_VAL, GPIO_UART_SEL2); + ret = write_device(path, gpio_uart_sel2); + if (ret) { + goto uart_exit; + } + + sprintf(path, GPIO_VAL, GPIO_UART_SEL1); + ret = write_device(path, gpio_uart_sel1); + if (ret) { + goto uart_exit; + } + + sprintf(path, GPIO_VAL, GPIO_UART_SEL0); + ret = write_device(path, gpio_uart_sel0); + if (ret) { + goto uart_exit; + } + + sprintf(path, GPIO_VAL, GPIO_UART_RX); + ret = write_device(path, gpio_uart_rx); + if (ret) { + goto uart_exit; + } + +uart_exit: + if (ret) { + syslog(LOG_ALERT, "pal_switch_uart_mux: write_device failed: %s\n", path); + return ret; + } else { + return 0; + } +} + +// Enable POST buffer for the server in given slot +int +pal_post_enable(uint8_t slot) { + int ret; + int i; + bic_config_t config = {0}; + bic_config_u *t = (bic_config_u *) &config; + + ret = bic_get_config(slot, &config); + if (ret) { + syslog(LOG_ALERT, "post_enable: bic_get_config failed\n"); + return ret; + } + + t->bits.post = 1; + + ret = bic_set_config(slot, &config); + if (ret) { + syslog(LOG_ALERT, "post_enable: bic_set_config failed\n"); + return ret; + } + + return 0; +} + +// Disable POST buffer for the server in given slot +int +pal_post_disable(uint8_t slot) { + int ret; + int i; + bic_config_t config = {0}; + bic_config_u *t = (bic_config_u *) &config; + + ret = bic_get_config(slot, &config); + if (ret) { + return ret; + } + + t->bits.post = 0; + + ret = bic_set_config(slot, &config); + if (ret) { + return ret; + } + + return 0; +} + +// Get the last post code of the given slot +int +pal_post_get_last(uint8_t slot, uint8_t *status) { + int ret; + uint8_t buf[MAX_IPMB_RES_LEN] = {0x0}; + uint8_t len; + int i; + + ret = bic_get_post_buf(slot, buf, &len); + if (ret) { + return ret; + } + + // The post buffer is LIFO and the first byte gives the latest post code + *status = buf[0]; + + return 0; +} + +// Handle the received post code, for now display it on debug card +int +pal_post_handle(uint8_t slot, uint8_t status) { + uint8_t prsnt, pos; + int ret; + + // Check for debug card presence + ret = pal_is_debug_card_prsnt(&prsnt); + if (ret) { + return ret; + } + + // No debug card present, return + if (!prsnt) { + return 0; + } + + // Get the hand switch position + ret = pal_get_hand_sw(&pos); + if (ret) { + return ret; + } + + // If the give server is not selected, return + if (pos != slot) { + return 0; + } + + // Display the post code in the debug card + ret = pal_post_display(status); + if (ret) { + return ret; + } + + return 0; +} + + +static int +read_kv(char *key, char *value) { + + FILE *fp; + int rc; + + fp = fopen(key, "r"); + if (!fp) { + int err = errno; + syslog(LOG_ALERT, "read_kv: failed to open %s", key); + return err; + } + + rc = (int) fread(value, 1, MAX_VALUE_LEN, fp); + fclose(fp); + if (rc <= 0) { + syslog(LOG_INFO, "read_kv: failed to read %s", key); + return ENOENT; + } else { + return 0; + } +} + +static int +write_kv(char *key, char *value) { + + FILE *fp; + int rc; + + fp = fopen(key, "w"); + if (!fp) { + int err = errno; + syslog(LOG_ALERT, "write_kv: failed to open %s", key); + return err; + } + + rc = fwrite(value, 1, strlen(value), fp); + fclose(fp); + + if (rc < 0) { + syslog(LOG_ALERT, "write_kv: failed to write to %s", key); + return ENOENT; + } else { + return 0; + } +} + +int +pal_get_fru_id(char *str, uint8_t *fru) { + + return yosemite_common_fru_id(str, fru); +} + +int +pal_get_fru_sensor_list(uint8_t fru, uint8_t **sensor_list, int *cnt) { + + switch(fru) { + case FRU_SLOT1: + case FRU_SLOT2: + case FRU_SLOT3: + case FRU_SLOT4: + *sensor_list = (uint8_t *) bic_sensor_list; + *cnt = bic_sensor_cnt; + break; + case FRU_SPB: + *sensor_list = (uint8_t *) spb_sensor_list; + *cnt = spb_sensor_cnt; + break; + case FRU_NIC: + *sensor_list = NULL; // (uint8_t *) nic_sensor_list; + *cnt = 0; //nic_sensor_cnt; + break; + default: + syslog(LOG_ALERT, "pal_get_fru_sensor_list: Wrong fru id %u", fru); + return -1; + } + return 0; +} + +int +pal_sensor_read(uint8_t fru, uint8_t sensor_num, void *value) { + return yosemite_sensor_read(fru, sensor_num, value); +} + +int +pal_get_sensor_name(uint8_t fru, uint8_t sensor_num, char *name) { + return yosemite_sensor_name(fru, sensor_num, name); +} + +int +pal_get_sensor_units(uint8_t fru, uint8_t sensor_num, char *units) { + return yosemite_sensor_units(fru, sensor_num, units); +} + +int +pal_get_fruid_path(uint8_t fru, char *path) { + return yosemite_get_fruid_path(fru, path); +} + +int +pal_get_fruid_name(uint8_t fru, char *name) { + return yosemite_get_fruid_name(fru, name); +} + + +static int +get_key_value(char* key, char *value) { + + char kpath[64] = {0}; + + sprintf(kpath, KV_STORE, key); + + if (access(KV_STORE_PATH, F_OK) == -1) { + mkdir(KV_STORE_PATH, 0777); + } + + return read_kv(kpath, value); +} + +static int +set_key_value(char *key, char *value) { + + char kpath[64] = {0}; + + sprintf(kpath, KV_STORE, key); + + if (access(KV_STORE_PATH, F_OK) == -1) { + mkdir(KV_STORE_PATH, 0777); + } + + return write_kv(kpath, value); +} + +int +pal_get_key_value(char *key, char *value) { + + int ret; + int i; + + i = 0; + while(strcmp(key_list[i], LAST_KEY)) { + + if (!strcmp(key, key_list[i])) { + // Key is valid + if ((ret = get_key_value(key, value)) < 0 ) { + syslog(LOG_ALERT, "pal_get_key_value: get_key_value failed. %d", ret); + return ret; + } + return ret; + } + i++; + } + + return -1; +} + +int +pal_set_key_value(char *key, char *value) { + + int ret; + int i; + + i = 0; + while(strcmp(key_list[i], LAST_KEY)) { + + if (!strcmp(key, key_list[i])) { + // Key is valid + if ((ret = set_key_value(key, value)) < 0) { + syslog(LOG_ALERT, "pal_set_key_value: set_key_value failed. %d", ret); + printf("pal_set_key_value: ret = %d\n", ret); + return ret; + } + return ret; + } + i++; + } + + return -1; +} + +int +pal_get_fru_devtty(uint8_t fru, char *devtty) { + + switch(fru) { + case FRU_SLOT1: + sprintf(devtty, "/dev/ttyS2"); + break; + case FRU_SLOT2: + sprintf(devtty, "/dev/ttyS1"); + break; + case FRU_SLOT3: + sprintf(devtty, "/dev/ttyS4"); + break; + case FRU_SLOT4: + sprintf(devtty, "/dev/ttyS3"); + break; + default: + syslog(LOG_ALERT, "pal_get_fru_devtty: Wrong fru id %u", fru); + return -1; + } + return 0; +} + +void +pal_dump_key_value(void) { + int i; + int ret; + + char value[MAX_VALUE_LEN] = {0x0}; + + while (strcmp(key_list[i], LAST_KEY)) { + printf("%s:", key_list[i]); + if (ret = get_key_value(key_list[i], value) < 0) { + printf("\n"); + } else { + printf("%s\n", value); + } + i++; + memset(value, 0, MAX_VALUE_LEN); + } +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.h new file mode 100644 index 0000000..1d9f3b9 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/pal/pal.h @@ -0,0 +1,98 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __PAL_H__ +#define __PAL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <facebook/bic.h> +#include <facebook/yosemite_common.h> +#include <facebook/yosemite_fruid.h> +#include <facebook/yosemite_sensor.h> + +#define MAX_NUM_FRUS 6 +#define MAX_KEY_LEN 64 +#define MAX_VALUE_LEN 64 + +#define KV_STORE "/mnt/data/kv_store/%s" +#define KV_STORE_PATH "/mnt/data/kv_store" + +extern char * key_list[]; +extern const char pal_fru_list[]; +extern const char pal_server_list[]; + +enum { + LED_STATE_OFF, + LED_STATE_ON, +}; + +enum { + SERVER_POWER_OFF, + SERVER_POWER_ON, + SERVER_POWER_CYCLE, + SERVER_GRACEFUL_SHUTDOWN, +}; + +enum { + HAND_SW_SERVER1 = 1, + HAND_SW_SERVER2, + HAND_SW_SERVER3, + HAND_SW_SERVER4, + HAND_SW_BMC +}; + +int pal_get_platform_name(char *name); +int pal_get_num_slots(uint8_t *num); +int pal_is_server_prsnt(uint8_t slot_id, uint8_t *status); +int pal_get_server_power(uint8_t slot_id, uint8_t *status); +int pal_set_server_power(uint8_t slot_id, uint8_t cmd); +int pal_sled_cycle(void); +int pal_is_debug_card_prsnt(uint8_t *status); +int pal_get_hand_sw(uint8_t *pos); +int pal_switch_usb_mux(uint8_t slot); +int pal_switch_uart_mux(uint8_t slot); +int pal_post_enable(uint8_t slot); +int pal_post_disable(uint8_t slot); +int pal_post_get_last(uint8_t slot, uint8_t *post); +int pal_post_handle(uint8_t slot, uint8_t status); +int pal_get_pwr_btn(uint8_t *status); +int pal_get_rst_btn(uint8_t *status); +int pal_set_rst_btn(uint8_t slot, uint8_t status); +int pal_set_led(uint8_t slot, uint8_t status); +int pal_get_fru_id(char *fru_str, uint8_t *fru); +int pal_get_fruid_path(uint8_t fru, char *path); +int pal_get_fruid_name(uint8_t fru, char *name); +int pal_get_sensor_units(uint8_t fru, uint8_t sensor_num, char *units); +int pal_get_fru_sensor_list(uint8_t fru, uint8_t **sensor_list, int *cnt); +int pal_sensor_read(uint8_t fru, uint8_t sensor_num, void *value); +int pal_get_sensor_name(uint8_t fru, uint8_t sensor_num, char *name); +int pal_get_key_value(char *key, char *value); +int pal_set_key_value(char *key, char *value); +void pal_dump_key_value(void); +int pal_get_fru_devtty(uint8_t fru, char *devtty); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __PAL_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/Makefile new file mode 100644 index 0000000..76bf61f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libyosemite_common.so + +libyosemite_common.so: yosemite_common.c + $(CC) $(CFLAGS) -fPIC -c -o yosemite_common.o yosemite_common.c + $(CC) -shared -o libyosemite_common.so yosemite_common.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libyosemite_common.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.c new file mode 100644 index 0000000..e41690f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.c @@ -0,0 +1,55 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <math.h> +#include <fcntl.h> +#include <errno.h> +#include <syslog.h> +#include "yosemite_common.h" + +int +yosemite_common_fru_id(char *str, uint8_t *fru) { + + if (!strcmp(str, "all")) { + *fru = FRU_ALL; + } else if (!strcmp(str, "slot1")) { + *fru = FRU_SLOT1; + } else if (!strcmp(str, "slot2")) { + *fru = FRU_SLOT2; + } else if (!strcmp(str, "slot3")) { + *fru = FRU_SLOT3; + } else if (!strcmp(str, "slot4")) { + *fru = FRU_SLOT4; + } else if (!strcmp(str, "spb")) { + *fru = FRU_SPB; + } else if (!strcmp(str, "nic")) { + *fru = FRU_NIC; + } else { + syslog(LOG_ALERT, "yosemite_common_fru_id: Wrong fru id"); + return -1; + } + + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.h new file mode 100644 index 0000000..85d8638 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_common/yosemite_common.h @@ -0,0 +1,44 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __YOSEMITE_COMMON_H__ +#define __YOSEMITE_COMMON_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + FRU_ALL = 0, + FRU_SLOT1 = 1, + FRU_SLOT2 = 2, + FRU_SLOT3 = 3, + FRU_SLOT4 = 4, + FRU_SPB = 5, + FRU_NIC = 6, +}; + +int yosemite_common_fru_id(char *str, uint8_t *fru); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __YOSEMITE_COMMON_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/Makefile new file mode 100644 index 0000000..eda01dc --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/Makefile @@ -0,0 +1,27 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +lib: libyosemite_fruid.so + +libyosemite_fruid.so: yosemite_fruid.c + $(CC) $(CFLAGS) -fPIC -c -o yosemite_fruid.o yosemite_fruid.c + $(CC) -lyosemite_common -shared -o libyosemite_fruid.so yosemite_fruid.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libyosemite_fruid.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.c new file mode 100644 index 0000000..226f2f8 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.c @@ -0,0 +1,86 @@ +/* Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <syslog.h> +#include "yosemite_fruid.h" + +/* Populate char path[] with the path to the fru's fruid binary dump */ +int +yosemite_get_fruid_path(uint8_t fru, char *path) { + char fname[16] = {0}; + + switch(fru) { + case FRU_SLOT1: + sprintf(fname, "slot1"); + break; + case FRU_SLOT2: + sprintf(fname, "slot2"); + break; + case FRU_SLOT3: + sprintf(fname, "slot3"); + break; + case FRU_SLOT4: + sprintf(fname, "slot4"); + break; + case FRU_SPB: + sprintf(fname, "spb"); + break; + case FRU_NIC: + sprintf(fname, "nic"); + break; + default: + syslog(LOG_ALERT, "yosemite_get_fruid_path: wrong fruid"); + return -1; + } + + sprintf(path, YOSEMITE_FRU_PATH, fname); + return 0; +} +/* Populate char name[] with the path to the fru's name */ +int +yosemite_get_fruid_name(uint8_t fru, char *name) { + + switch(fru) { + case FRU_SLOT1: + sprintf(name, "MonoLake Board 1"); + break; + case FRU_SLOT2: + sprintf(name, "MonoLake Board 2"); + break; + case FRU_SLOT3: + sprintf(name, "MonoLake Board 3"); + break; + case FRU_SLOT4: + sprintf(name, "MonoLake Board 4"); + break; + case FRU_SPB: + sprintf(name, "Side Plane Board"); + break; + case FRU_NIC: + sprintf(name, "CX4 NIC"); + break; + default: + syslog(LOG_ALERT, "yosemite_get_fruid_name: wrong fruid"); + return -1; + } + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.h new file mode 100644 index 0000000..5c01267 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_fruid/yosemite_fruid.h @@ -0,0 +1,37 @@ +/* Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __YOSEMITE_FRUID_H__ +#define __YOSEMITE_FRUID_H__ + +#include <facebook/yosemite_common.h> + +#define YOSEMITE_FRU_PATH "/tmp/fruid_%s.bin" + +#ifdef __cplusplus +extern "C" { +#endif + +int yosemite_get_fruid_path(uint8_t fru, char *path); +int yosemite_get_fruid_name(uint8_t fru, char *name); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __YOSEMITE_FRUID_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/Makefile new file mode 100644 index 0000000..66c0005 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/Makefile @@ -0,0 +1,27 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +lib: libyosemite_gpio.so + +libyosemite_gpio.so: yosemite_gpio.c + $(CC) $(CFLAGS) -fPIC -c -o yosemite_gpio.o yosemite_gpio.c + $(CC) -shared -o libyosemite_gpio.so yosemite_gpio.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libyosemite_gpio.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.c new file mode 100644 index 0000000..ac2c820 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.c @@ -0,0 +1,116 @@ +/* Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <syslog.h> +#include "yosemite_gpio.h" + +// List of GPIO pins to be monitored +const uint8_t gpio_pin_list[] = { + PWRGOOD_CPU, + PWRGD_PCH_PWROK, + PVDDR_VRHOT_N, + PVCCIN_VRHOT_N, + FM_FAST_PROCHOT_N, + PCHHOT_CPU_N, + FM_CPLD_CPU_DIMM_EVENT_CO_N, + FM_CPLD_BDXDE_THERMTRIP_N, + THERMTRIP_PCH_N, + FM_CPLD_FIVR_FAULT, + FM_BDXDE_CATERR_LVT3_N, + FM_BDXDE_ERR2_LVT3_N, + FM_BDXDE_ERR1_LVT3_N, + FM_BDXDE_ERR0_LVT3_N, + //SLP_S4_N, + FM_NMI_EVENT_BMC_N, + FM_SMI_BMC_N, + RST_PLTRST_BMC_N, + FP_RST_BTN_BUF_N, + BMC_RST_BTN_OUT_N, + FM_BDE_POST_CMPLT_N, + //FM_BDXDE_SLP3_N, + //FM_PWR_LED_N, + PWRGD_PVCCIN, + //SVR_ID0, + //SVR_ID1, + //SVR_ID2, + //SVR_ID3, + //BMC_READY_N, + //RESERVED_29, + //RESERVED_30, + //RESERVED_31, +}; + +size_t gpio_pin_cnt = sizeof(gpio_pin_list)/sizeof(uint8_t); +const uint32_t gpio_ass_val = 0x0 | (1 << FM_CPLD_FIVR_FAULT); + +const char *gpio_pin_name[] = { + "PWRGOOD_CPU", + "PWRGD_PCH_PWROK", + "PVDDR_VRHOT_N", + "PVCCIN_VRHOT_N", + "FM_FAST_PROCHOT_N", + "PCHHOT_CPU_N", + "FM_CPLD_CPU_DIMM_EVENT_CO_N", + "FM_CPLD_BDXDE_THERMTRIP_N", + "THERMTRIP_PCH_N", + "FM_CPLD_FIVR_FAULT", + "FM_BDXDE_CATERR_LVT3_N", + "FM_BDXDE_ERR2_LVT3_N", + "FM_BDXDE_ERR1_LVT3_N", + "FM_BDXDE_ERR0_LVT3_N", + "SLP_S4_N", + "FM_NMI_EVENT_BMC_N", + "FM_SMI_BMC_N", + "RST_PLTRST_BMC_N", + "FP_RST_BTN_BUF_N", + "BMC_RST_BTN_OUT_N", + "FM_BDE_POST_CMPLT_N", + "FM_BDXDE_SLP3_N", + "FM_PWR_LED_N", + "PWRGD_PVCCIN", + "SVR_ID0", + "SVR_ID1", + "SVR_ID2", + "SVR_ID3", + "BMC_READY_N", + "RESERVED_29", + "RESERVED_30", + "RESERVED_31" +}; + +int +yosemite_get_gpio_name(uint8_t fru, uint8_t gpio, char *name) { + + //TODO: Add support for BMC GPIO pins + if (fru < 1 || fru > 4) { + syslog(LOG_ALERT, "yosemite_get_gpio_name: Wrong fru %u", fru); + return -1; + } + + if (gpio < 0 || gpio > MAX_GPIO_PINS) { + syslog(LOG_ALERT, "yosemite_get_gpio_name: Wrong gpio pin %u", gpio); + return -1; + } + + sprintf(name, "%s", gpio_pin_name[gpio]); + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.h new file mode 100644 index 0000000..77808a8 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_gpio/yosemite_gpio.h @@ -0,0 +1,39 @@ +/* Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __YOSEMITE_GPIO_H__ +#define __YOSEMITE_GPIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <facebook/bic.h> + +extern const uint8_t gpio_pin_list[]; +extern const char *gpio_pin_name[]; +extern const uint32_t gpio_ass_val; +extern size_t gpio_pin_cnt; + +int yosemite_get_gpio_name(uint8_t fru, uint8_t gpio, char *name); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __YOSEMITE_GPIO_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/Makefile new file mode 100644 index 0000000..63b334c --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/Makefile @@ -0,0 +1,11 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +lib: libyosemite_sensor.so + +libyosemite_sensor.so: yosemite_sensor.c + $(CC) $(CFLAGS) -fPIC -c -o yosemite_sensor.o yosemite_sensor.c + $(CC) -lm -lbic -lsdr -lipmi -lipmb -lyosemite_common -shared -o libyosemite_sensor.so yosemite_sensor.o -lc + +.PHONY: clean + +clean: + rm -rf *.o libyosemite_sensor.so diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.c b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.c new file mode 100644 index 0000000..0f25e54 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.c @@ -0,0 +1,778 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <math.h> +#include <fcntl.h> +#include <errno.h> +#include <syslog.h> +#include "yosemite_sensor.h" + +#define LARGEST_DEVICE_NAME 120 + +#define GPIO_VAL "/sys/class/gpio/gpio%d/value" + +#define I2C_BUS_9_DIR "/sys/class/i2c-adapter/i2c-9/" +#define I2C_BUS_10_DIR "/sys/class/i2c-adapter/i2c-10/" + +#define TACH_DIR "/sys/devices/platform/ast_pwm_tacho.0" +#define ADC_DIR "/sys/devices/platform/ast_adc.0" + +#define SP_INLET_TEMP_DEVICE I2C_BUS_9_DIR "9-004e" +#define SP_OUTLET_TEMP_DEVICE I2C_BUS_9_DIR "9-004f" +#define HSC_DEVICE I2C_BUS_10_DIR "10-0040" + +#define FAN_TACH_RPM "tacho%d_rpm" +#define ADC_VALUE "adc%d_value" +#define HSC_IN_VOLT "in1_input" +#define HSC_OUT_CURR "curr1_input" +#define HSC_TEMP "temp1_input" + +#define UNIT_DIV 1000 + +#define BIC_SENSOR_READ_NA 0x20 + +#define MAX_SENSOR_NUM 0xFF +#define ALL_BYTES 0xFF +#define LAST_REC_ID 0xFFFF + +#define YOSEMITE_SDR_PATH "/tmp/sdr_%s.bin" + +// List of BIC sensors to be monitored +const uint8_t bic_sensor_list[] = { + /* Threshold sensors */ + BIC_SENSOR_MB_OUTLET_TEMP, + BIC_SENSOR_VCCIN_VR_TEMP, + BIC_SENSOR_VCC_GBE_VR_TEMP, + BIC_SENSOR_1V05PCH_VR_TEMP, + BIC_SENSOR_SOC_TEMP, + BIC_SENSOR_MB_INLET_TEMP, + BIC_SENSOR_PCH_TEMP, + BIC_SENSOR_SOC_THERM_MARGIN, + BIC_SENSOR_VDDR_VR_TEMP, + BIC_SENSOR_VCC_GBE_VR_CURR, + BIC_SENSOR_1V05_PCH_VR_CURR, + BIC_SENSOR_VCCIN_VR_POUT, + BIC_SENSOR_VCCIN_VR_CURR, + BIC_SENSOR_VCCIN_VR_VOL, + BIC_SENSOR_INA230_POWER, + BIC_SENSOR_SOC_PACKAGE_PWR, + BIC_SENSOR_SOC_TJMAX, + BIC_SENSOR_VDDR_VR_POUT, + BIC_SENSOR_VDDR_VR_CURR, + BIC_SENSOR_VDDR_VR_VOL, + BIC_SENSOR_VCC_SCSUS_VR_CURR, + BIC_SENSOR_VCC_SCSUS_VR_VOL, + BIC_SENSOR_VCC_SCSUS_VR_TEMP, + BIC_SENSOR_VCC_SCSUS_VR_POUT, + BIC_SENSOR_VCC_GBE_VR_POUT, + BIC_SENSOR_VCC_GBE_VR_VOL, + BIC_SENSOR_1V05_PCH_VR_VOL, + BIC_SENSOR_SOC_DIMMA0_TEMP, + BIC_SENSOR_SOC_DIMMA1_TEMP, + BIC_SENSOR_SOC_DIMMB0_TEMP, + BIC_SENSOR_SOC_DIMMB1_TEMP, + BIC_SENSOR_P3V3_MB, + BIC_SENSOR_P12V_MB, + BIC_SENSOR_P1V05_PCH, + BIC_SENSOR_P3V3_STBY_MB, + BIC_SENSOR_P5V_STBY_MB, + BIC_SENSOR_PV_BAT, + BIC_SENSOR_PVDDR, + BIC_SENSOR_PVCC_GBE, + /* Discrete sensors */ + //BIC_SENSOR_SYSTEM_STATUS, + //BIC_SENSOR_SYS_BOOT_STAT, + //BIC_SENSOR_CPU_DIMM_HOT, + //BIC_SENSOR_PROC_FAIL, + //BIC_SENSOR_VR_HOT, + /* Event-only sensors */ + //BIC_SENSOR_POST_ERR, + //BIC_SENSOR_SPS_FW_HLTH, + //BIC_SENSOR_POWER_THRESH_EVENT, + //BIC_SENSOR_MACHINE_CHK_ERR, + //BIC_SENSOR_PCIE_ERR, + //BIC_SENSOR_OTHER_IIO_ERR, + //BIC_SENSOR_PROC_HOT_EXT, + //BIC_SENSOR_POWER_ERR, + //BIC_SENSOR_CAT_ERR, +}; + +// List of SPB sensors to be monitored +const uint8_t spb_sensor_list[] = { + SP_SENSOR_INLET_TEMP, + SP_SENSOR_OUTLET_TEMP, + //SP_SENSOR_MEZZ_TEMP + SP_SENSOR_FAN0_TACH, + SP_SENSOR_FAN1_TACH, + //SP_SENSOR_AIR_FLOW, + SP_SENSOR_P5V, + SP_SENSOR_P12V, + SP_SENSOR_P3V3_STBY, + SP_SENSOR_P12V_SLOT0, + SP_SENSOR_P12V_SLOT1, + SP_SENSOR_P12V_SLOT2, + SP_SENSOR_P12V_SLOT3, + SP_SENSOR_P3V3, + SP_SENSOR_HSC_IN_VOLT, + SP_SENSOR_HSC_OUT_CURR, + SP_SENSOR_HSC_TEMP, + SP_SENSOR_HSC_IN_POWER, +}; + +size_t bic_sensor_cnt = sizeof(bic_sensor_list)/sizeof(uint8_t); + +size_t spb_sensor_cnt = sizeof(spb_sensor_list)/sizeof(uint8_t); + +enum { + FAN0 = 0, + FAN1, +}; + +enum { + ADC_PIN0 = 0, + ADC_PIN1, + ADC_PIN2, + ADC_PIN3, + ADC_PIN4, + ADC_PIN5, + ADC_PIN6, + ADC_PIN7, +}; + +static sensor_info_t g_sinfo1[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo2[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo3[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo4[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo_spb[MAX_SENSOR_NUM] = {0}; +static sensor_info_t g_sinfo_nic[MAX_SENSOR_NUM] = {0}; + +static int +read_device(const char *device, int *value) { + FILE *fp; + int rc; + + fp = fopen(device, "r"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device %s", device); + return err; + } + + rc = fscanf(fp, "%d", value); + fclose(fp); + + if (rc != 1) { + syslog(LOG_INFO, "failed to read device %s", device); + return ENOENT; + } else { + return 0; + } +} + +static int +read_device_float(const char *device, float *value) { + FILE *fp; + int rc; + char tmp[10]; + + fp = fopen(device, "r"); + if (!fp) { + int err = errno; + + syslog(LOG_INFO, "failed to open device %s", device); + return err; + } + + rc = fscanf(fp, "%s", tmp); + fclose(fp); + + if (rc != 1) { + syslog(LOG_INFO, "failed to read device %s", device); + return ENOENT; + } + + *value = atof(tmp); + + return 0; +} + +static int +read_temp(const char *device, float *value) { + char full_name[LARGEST_DEVICE_NAME + 1]; + int tmp; + + snprintf( + full_name, LARGEST_DEVICE_NAME, "%s/temp1_input", device); + if (read_device(full_name, &tmp)) { + return -1; + } + + *value = ((float)tmp)/UNIT_DIV; + + return 0; +} + +static int +read_fan_value(const int fan, const char *device, float *value) { + char device_name[LARGEST_DEVICE_NAME]; + char full_name[LARGEST_DEVICE_NAME]; + + snprintf(device_name, LARGEST_DEVICE_NAME, device, fan); + snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", TACH_DIR, device_name); + return read_device_float(full_name, value); +} + +static int +read_adc_value(const int pin, const char *device, float *value) { + char device_name[LARGEST_DEVICE_NAME]; + char full_name[LARGEST_DEVICE_NAME]; + + snprintf(device_name, LARGEST_DEVICE_NAME, device, pin); + snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", ADC_DIR, device_name); + return read_device_float(full_name, value); +} + +static int +read_hsc_value(const char *device, float *value) { + char full_name[LARGEST_DEVICE_NAME]; + int tmp; + + snprintf(full_name, LARGEST_DEVICE_NAME, "%s/%s", HSC_DEVICE, device); + if(read_device(full_name, &tmp)) { + return -1; + } + + *value = ((float) tmp)/UNIT_DIV; + + return 0; +} + +static int +bic_read_sensor_wrapper(uint8_t slot_id, uint8_t sensor_num, void *value) { + int ret; + ipmi_sensor_reading_t sensor; + + ret = bic_read_sensor(slot_id, sensor_num, &sensor); + if (ret) { + return ret; + } + + if (sensor.flags & BIC_SENSOR_READ_NA) { + syslog(LOG_ERR, "bic_read_sensor_wrapper: Reading Not Available"); + syslog(LOG_ERR, "bic_read_sensor_wrapper: sensor_num: 0x%X, flag: 0x%X", + sensor_num, sensor.flags); + return -1; + } + + if (sensor.status) { + //printf("bic_read_sensor_wrapper: Status Asserted: 0x%X\n", sensor.status); + } + + // Check SDR to convert raw value to actual + sdr_full_t *sdr; + + switch (slot_id) { + case 1: + sdr = &g_sinfo1[sensor_num].sdr; + break; + case 2: + sdr = &g_sinfo2[sensor_num].sdr; + break; + case 3: + sdr = &g_sinfo3[sensor_num].sdr; + break; + case 4: + sdr = &g_sinfo4[sensor_num].sdr; + break; + default: + syslog(LOG_ALERT, "bic_read_sensor_wrapper: Wrong Slot ID\n"); + return -1; + } + + // If the SDR is not type1, no need for conversion + if (sdr->type !=1) { + *(float *) value = sensor.value; + return 0; + } + + // y = (mx + b * 10^b_exp) * 10^r_exp + uint8_t x; + uint8_t m_lsb, m_msb, m; + uint8_t b_lsb, b_msb, b; + int8_t b_exp, r_exp; + + x = sensor.value; + + m_lsb = sdr->m_val; + m_msb = sdr->m_tolerance >> 6; + m = (m_msb << 8) | m_lsb; + + b_lsb = sdr->b_val; + b_msb = sdr->b_accuracy >> 6; + b = (b_msb << 8) | b_lsb; + + // exponents are 2's complement 4-bit number + b_exp = sdr->rb_exp & 0xF; + if (b_exp > 7) { + b_exp = (~b_exp + 1) & 0xF; + b_exp = -b_exp; + } + r_exp = (sdr->rb_exp >> 4) & 0xF; + if (r_exp > 7) { + r_exp = (~r_exp + 1) & 0xF; + r_exp = -r_exp; + } + + //printf("m:%d, x:%d, b:%d, b_exp:%d, r_exp:%d\n", m, x, b, b_exp, r_exp); + + * (float *) value = ((m * x) + (b * pow(10, b_exp))) * (pow(10, r_exp)); + + return 0; +} + +/* Returns the all the SDRs for the particular fru# */ +static sensor_info_t * +get_struct_sensor_info(uint8_t fru) { + sensor_info_t *sinfo; + switch(fru) { + case FRU_SLOT1: + sinfo = g_sinfo1; + break; + case FRU_SLOT2: + sinfo = g_sinfo2; + break; + case FRU_SLOT3: + sinfo = g_sinfo3; + break; + case FRU_SLOT4: + sinfo = g_sinfo4; + break; + case FRU_SPB: + sinfo = g_sinfo_spb; + break; + case FRU_NIC: + sinfo = g_sinfo_nic; + break; + default: + syslog(LOG_ALERT, "yosemite_sdr_init: Wrong Slot ID\n"); + return NULL; + } + return sinfo; +} + +int +get_fru_sdr_path(uint8_t fru, char *path) { + + char fru_name[16] = {0}; + + switch(fru) { + case FRU_SLOT1: + sprintf(fru_name, "%s", "slot1"); + break; + case FRU_SLOT2: + sprintf(fru_name, "%s", "slot2"); + break; + case FRU_SLOT3: + sprintf(fru_name, "%s", "slot3"); + break; + case FRU_SLOT4: + sprintf(fru_name, "%s", "slot4"); + break; + case FRU_SPB: + sprintf(fru_name, "%s", "spb"); + break; + case FRU_NIC: + sprintf(fru_name, "%s", "nic"); + break; + default: + syslog(LOG_ALERT, "yosemite_sdr_init: Wrong Slot ID\n"); + return -1; + } + + sprintf(path, YOSEMITE_SDR_PATH, fru_name); + + return 0; +} + +static int +yosemite_sdr_init(uint8_t fru) { + int fd; + uint8_t buf[MAX_SDR_LEN] = {0}; + uint8_t bytes_rd = 0; + uint8_t sn = 0; + char path[64] = {0}; + sensor_info_t *sinfo; + + if (get_fru_sdr_path(fru, path) < 0) { + syslog(LOG_ALERT, "yosemite_sdr_init: get_fru_sdr_path failed\n"); + return -1; + } + sinfo = get_struct_sensor_info(fru); + if (sinfo == NULL) { + syslog(LOG_ALERT, "yosemite_sdr_init: get_struct_sensor_info failed\n"); + return -1; + } + + if (sdr_init(path, sinfo) < 0) { + syslog(LOG_ERR, "yosemite_sdr_init: sdr_init failed for FRU %d", fru); + } + + return 0; +} + +static bool +is_server_prsnt(uint8_t slot_id) { + uint8_t gpio; + int val; + char path[64] = {0}; + + switch(slot_id) { + case 1: + gpio = 61; + break; + case 2: + gpio = 60; + break; + case 3: + gpio = 63; + break; + case 4: + gpio = 62; + break; + default: + return 0; + } + + sprintf(path, GPIO_VAL, gpio); + + if (read_device(path, &val)) { + return -1; + } + + if (val == 0x0) { + return 1; + } else { + return 0; + } +} + +/* Get the units for the sensor */ +int +yosemite_sensor_units(uint8_t fru, uint8_t sensor_num, char *units) { + static bool init_done = false; + uint8_t op, modifier; + sensor_info_t *sinfo; + + if (!init_done) { + + if (is_server_prsnt(1) && (yosemite_sdr_init(FRU_SLOT1) != 0)) { + return -1; + } + if (is_server_prsnt(2) && (yosemite_sdr_init(FRU_SLOT2) != 0)) { + return -1; + } + if (is_server_prsnt(3) && (yosemite_sdr_init(FRU_SLOT3) != 0)) { + return -1; + } + if (is_server_prsnt(4) && (yosemite_sdr_init(FRU_SLOT4) != 0)) { + return -1; + } + init_done = true; + } + + switch(fru) { + case FRU_SLOT1: + case FRU_SLOT2: + case FRU_SLOT3: + case FRU_SLOT4: + sinfo = get_struct_sensor_info(fru); + if (sinfo == NULL) { + syslog(LOG_ALERT, "yosemite_sensor_units: get_struct_sensor_info failed\n"); + return -1; + } + + if (sdr_get_sensor_units(&sinfo[sensor_num].sdr, &op, &modifier, units)) { + syslog(LOG_ALERT, "yosemite_sensor_units: FRU %d: num 0x%2X: reading units" + " from SDR failed.", fru, sensor_num); + return -1; + } + break; + case FRU_SPB: + switch(sensor_num) { + case SP_SENSOR_INLET_TEMP: + sprintf(units, "C"); + break; + case SP_SENSOR_OUTLET_TEMP: + sprintf(units, "C"); + break; + case SP_SENSOR_MEZZ_TEMP: + sprintf(units, "C"); + break; + case SP_SENSOR_FAN0_TACH: + sprintf(units, "RPM"); + break; + case SP_SENSOR_FAN1_TACH: + sprintf(units, "RPM"); + break; + case SP_SENSOR_AIR_FLOW: + sprintf(units, ""); + break; + case SP_SENSOR_P5V: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P3V3_STBY: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V_SLOT0: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V_SLOT1: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V_SLOT2: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P12V_SLOT3: + sprintf(units, "Volts"); + break; + case SP_SENSOR_P3V3: + sprintf(units, "Volts"); + break; + case SP_SENSOR_HSC_IN_VOLT: + sprintf(units, "Volts"); + break; + case SP_SENSOR_HSC_OUT_CURR: + sprintf(units, "Amps"); + break; + case SP_SENSOR_HSC_TEMP: + sprintf(units, "C"); + break; + case SP_SENSOR_HSC_IN_POWER: + sprintf(units, "Watts"); + break; + } + break; + case FRU_NIC: + sprintf(units, ""); + break; + } + return 0; +} + +/* Get the name for the sensor */ +int +yosemite_sensor_name(uint8_t fru, uint8_t sensor_num, char *name) { + static bool init_done = false; + uint8_t op, modifier; + sensor_info_t *sinfo; + + if (!init_done) { + + if (is_server_prsnt(1) && (yosemite_sdr_init(FRU_SLOT1) != 0)) { + return -1; + } + if (is_server_prsnt(2) && (yosemite_sdr_init(FRU_SLOT2) != 0)) { + return -1; + } + if (is_server_prsnt(3) && (yosemite_sdr_init(FRU_SLOT3) != 0)) { + return -1; + } + if (is_server_prsnt(4) && (yosemite_sdr_init(FRU_SLOT4) != 0)) { + return -1; + } + init_done = true; + } + + switch(fru) { + case FRU_SLOT1: + case FRU_SLOT2: + case FRU_SLOT3: + case FRU_SLOT4: + sinfo = get_struct_sensor_info(fru); + if (sinfo == NULL) { + syslog(LOG_ALERT, "yosemite_sensor_name: get_struct_sensor_info failed\n"); + return -1; + } + + if (sdr_get_sensor_name(&sinfo[sensor_num].sdr, name)) { + syslog(LOG_ALERT, "yosemite_sensor_name: FRU %d: num 0x%2X: reading units" + " from SDR failed.", fru, sensor_num); + return -1; + } + + break; + case FRU_SPB: + switch(sensor_num) { + case SP_SENSOR_INLET_TEMP: + sprintf(name, "SP_SENSOR_INLET_TEMP"); + break; + case SP_SENSOR_OUTLET_TEMP: + sprintf(name, "SP_SENSOR_OUTLET_TEMP"); + break; + case SP_SENSOR_MEZZ_TEMP: + sprintf(name, "SP_SENSOR_MEZZ_TEMP"); + break; + case SP_SENSOR_FAN0_TACH: + sprintf(name, "SP_SENSOR_FAN0_TACH"); + break; + case SP_SENSOR_FAN1_TACH: + sprintf(name, "SP_SENSOR_FAN1_TACH"); + break; + case SP_SENSOR_AIR_FLOW: + sprintf(name, "SP_SENSOR_AIR_FLOW"); + break; + case SP_SENSOR_P5V: + sprintf(name, "SP_SENSOR_P5V"); + break; + case SP_SENSOR_P12V: + sprintf(name, "SP_SENSOR_P12V"); + break; + case SP_SENSOR_P3V3_STBY: + sprintf(name, "SP_SENSOR_P3V3_STBY"); + break; + case SP_SENSOR_P12V_SLOT0: + sprintf(name, "SP_SENSOR_P12V_SLOT0"); + break; + case SP_SENSOR_P12V_SLOT1: + sprintf(name, "SP_SENSOR_P12V_SLOT1"); + break; + case SP_SENSOR_P12V_SLOT2: + sprintf(name, "SP_SENSOR_P12V_SLOT2"); + break; + case SP_SENSOR_P12V_SLOT3: + sprintf(name, "SP_SENSOR_P12V_SLOT3"); + break; + case SP_SENSOR_P3V3: + sprintf(name, "SP_SENSOR_P3V3"); + break; + case SP_SENSOR_HSC_IN_VOLT: + sprintf(name, "SP_SENSOR_HSC_IN_VOLT"); + break; + case SP_SENSOR_HSC_OUT_CURR: + sprintf(name, "SP_SENSOR_HSC_OUT_CURR"); + break; + case SP_SENSOR_HSC_TEMP: + sprintf(name, "SP_SENSOR_HSC_TEMP"); + break; + case SP_SENSOR_HSC_IN_POWER: + sprintf(name, "SP_SENSOR_HSC_IN_POWER"); + break; + } + break; + case FRU_NIC: + sprintf(name, ""); + break; + } + return 0; +} + + +int +yosemite_sensor_read(uint8_t slot_id, uint8_t sensor_num, void *value) { + static bool init_done = false; + float volt; + float curr; + + if (!init_done) { + + if (is_server_prsnt(1) && (yosemite_sdr_init(FRU_SLOT1) != 0)) { + return -1; + } + + if (is_server_prsnt(2) && (yosemite_sdr_init(FRU_SLOT2) != 0)) { + return -1; + } + + if (is_server_prsnt(3) && (yosemite_sdr_init(FRU_SLOT3) != 0)) { + return -1; + } + + if (is_server_prsnt(4) && (yosemite_sdr_init(FRU_SLOT4) != 0)) { + return -1; + } + + init_done = true; + } + + switch(sensor_num) { + // Inlet, Outlet Temp + + case SP_SENSOR_INLET_TEMP: + return read_temp(SP_INLET_TEMP_DEVICE, (float*) value); + case SP_SENSOR_OUTLET_TEMP: + return read_temp(SP_OUTLET_TEMP_DEVICE, (float*) value); + + // Fan Tach Values + case SP_SENSOR_FAN0_TACH: + return read_fan_value(FAN0, FAN_TACH_RPM, (float*) value); + case SP_SENSOR_FAN1_TACH: + return read_fan_value(FAN1, FAN_TACH_RPM, (float*) value); + + // Various Voltages + case SP_SENSOR_P5V: + return read_adc_value(ADC_PIN0, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V: + return read_adc_value(ADC_PIN1, ADC_VALUE, (float*) value); + case SP_SENSOR_P3V3_STBY: + return read_adc_value(ADC_PIN2, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V_SLOT0: + return read_adc_value(ADC_PIN3, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V_SLOT1: + return read_adc_value(ADC_PIN4, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V_SLOT2: + return read_adc_value(ADC_PIN5, ADC_VALUE, (float*) value); + case SP_SENSOR_P12V_SLOT3: + return read_adc_value(ADC_PIN6, ADC_VALUE, (float*) value); + case SP_SENSOR_P3V3: + return read_adc_value(ADC_PIN7, ADC_VALUE, (float*) value); + + // Hot Swap Controller + case SP_SENSOR_HSC_IN_VOLT: + return read_hsc_value(HSC_IN_VOLT, (float*) value); + case SP_SENSOR_HSC_OUT_CURR: + return read_hsc_value(HSC_OUT_CURR, (float*) value); + case SP_SENSOR_HSC_TEMP: + return read_hsc_value(HSC_TEMP, (float*) value); + case SP_SENSOR_HSC_IN_POWER: + if (read_hsc_value(HSC_IN_VOLT, &volt)) { + return -1; + } + + if (read_hsc_value(HSC_OUT_CURR, &curr)) { + return -1; + } + + * (float*) value = volt * curr; + return 0; + default: + // For all others we assume the sensors are on Monolake + return bic_read_sensor_wrapper(slot_id, sensor_num, value); + } +} + diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.h b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.h new file mode 100644 index 0000000..0a33173 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/files/yosemite_sensor/yosemite_sensor.h @@ -0,0 +1,133 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __YOSEMITE_SENSOR_H__ +#define __YOSEMITE_SENSOR_H__ + +#include <stdbool.h> +#include <openbmc/ipmi.h> +#include <openbmc/ipmb.h> +#include <openbmc/sdr.h> +#include <facebook/bic.h> +#include <facebook/yosemite_common.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// Sensors under Bridge IC +enum { + BIC_SENSOR_MB_OUTLET_TEMP = 0x01, + BIC_SENSOR_VCCIN_VR_TEMP = 0x02, + BIC_SENSOR_VCC_GBE_VR_TEMP = 0x03, + BIC_SENSOR_1V05PCH_VR_TEMP = 0x04, + BIC_SENSOR_SOC_TEMP = 0x05, + BIC_SENSOR_MB_INLET_TEMP = 0x07, + BIC_SENSOR_PCH_TEMP = 0x08, + BIC_SENSOR_SOC_THERM_MARGIN = 0x09, + BIC_SENSOR_VDDR_VR_TEMP = 0x0B, + BIC_SENSOR_SYSTEM_STATUS = 0x10, //Discrete + BIC_SENSOR_SPS_FW_HLTH = 0x17, //Event-only + BIC_SENSOR_VCC_GBE_VR_CURR = 0x20, + BIC_SENSOR_1V05_PCH_VR_CURR = 0x21, + BIC_SENSOR_VCCIN_VR_POUT = 0x22, + BIC_SENSOR_VCCIN_VR_CURR = 0x23, + BIC_SENSOR_VCCIN_VR_VOL = 0x24, + BIC_SENSOR_INA230_POWER = 0x29, + BIC_SENSOR_POST_ERR = 0x2B, //Event-only + BIC_SENSOR_SOC_PACKAGE_PWR = 0x2C, + BIC_SENSOR_SOC_TJMAX = 0x30, + BIC_SENSOR_VDDR_VR_POUT = 0x32, + BIC_SENSOR_VDDR_VR_CURR = 0x33, + BIC_SENSOR_VDDR_VR_VOL = 0x34, + BIC_SENSOR_VCC_SCSUS_VR_CURR = 0x35, + BIC_SENSOR_VCC_SCSUS_VR_VOL = 0x36, + BIC_SENSOR_VCC_SCSUS_VR_TEMP = 0x37, + BIC_SENSOR_VCC_SCSUS_VR_POUT = 0x38, + BIC_SENSOR_VCC_GBE_VR_POUT = 0x39, + BIC_SENSOR_POWER_THRESH_EVENT = 0x3B, //Event-only + //BIC_SENSOR_1V05_PCH_VR_POUT = 0x40, + BIC_SENSOR_MACHINE_CHK_ERR = 0x40, //Event-only + BIC_SENSOR_PCIE_ERR = 0x41, //Event-only + BIC_SENSOR_OTHER_IIO_ERR = 0x43, //Event-only + BIC_SENSOR_PROC_HOT_EXT = 0x51, //Event-only + BIC_SENSOR_VCC_GBE_VR_VOL = 0x54, + BIC_SENSOR_1V05_PCH_VR_VOL = 0x55, + BIC_SENSOR_POWER_ERR = 0x56, //Event-only + BIC_SENSOR_MEM_ECC_ERR = 0x63, //Event-only + BIC_SENSOR_PROC_FAIL = 0x65, //Discrete + BIC_SENSOR_SYS_BOOT_STAT = 0x7E, //Discrete + BIC_SENSOR_VR_HOT = 0xB2, //Discrete + BIC_SENSOR_CPU_DIMM_HOT = 0xB3, //Discrete + BIC_SENSOR_SOC_DIMMA0_TEMP = 0xB4, + BIC_SENSOR_SOC_DIMMA1_TEMP = 0xB5, + BIC_SENSOR_SOC_DIMMB0_TEMP = 0xB6, + BIC_SENSOR_SOC_DIMMB1_TEMP = 0xB7, + BIC_SENSOR_P3V3_MB = 0xD0, + BIC_SENSOR_P12V_MB = 0xD2, + BIC_SENSOR_P1V05_PCH = 0xD3, + BIC_SENSOR_P3V3_STBY_MB = 0xD5, + BIC_SENSOR_P5V_STBY_MB = 0xD6, + BIC_SENSOR_PV_BAT = 0xD7, + BIC_SENSOR_PVDDR = 0xD8, + BIC_SENSOR_PVCC_GBE = 0xD9, + BIC_SENSOR_CAT_ERR = 0xEB, //Event-only +}; + +// Sensors Under Side Plane +enum { + SP_SENSOR_INLET_TEMP = 0x81, + SP_SENSOR_OUTLET_TEMP = 0x80, + SP_SENSOR_MEZZ_TEMP = 0x82, + SP_SENSOR_FAN0_TACH = 0x46, + SP_SENSOR_FAN1_TACH = 0x47, + SP_SENSOR_AIR_FLOW = 0x4A, + SP_SENSOR_P5V = 0xE0, + SP_SENSOR_P12V = 0xE1, + SP_SENSOR_P3V3_STBY = 0xE2, + SP_SENSOR_P12V_SLOT0 = 0xE3, + SP_SENSOR_P12V_SLOT1 = 0xE4, + SP_SENSOR_P12V_SLOT2 = 0xE5, + SP_SENSOR_P12V_SLOT3 = 0xE6, + SP_SENSOR_P3V3 = 0xE7, + SP_SENSOR_HSC_IN_VOLT = 0xC0, + SP_SENSOR_HSC_OUT_CURR = 0xC1, + SP_SENSOR_HSC_TEMP = 0xC2, + SP_SENSOR_HSC_IN_POWER = 0xC3, +}; + +extern const uint8_t bic_sensor_list[]; + +extern const uint8_t spb_sensor_list[]; + +extern size_t bic_sensor_cnt; + +extern size_t spb_sensor_cnt; + +int yosemite_sensor_read(uint8_t slot_id, uint8_t sensor_num, void *value); +int yosemite_sensor_name(uint8_t fru, uint8_t sensor_num, char *name); +int yosemite_sensor_units(uint8_t fru, uint8_t sensor_num, char *units); +int get_fru_sdr_path(uint8_t fru, char *path); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* __YOSEMITE_SENSOR_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libbic_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libbic_0.1.bb new file mode 100644 index 0000000..6b22366 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libbic_0.1.bb @@ -0,0 +1,25 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Bridge IC Library" +DESCRIPTION = "library for communicating with Bridge IC" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://bic.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://bic \ + " +DEPENDS += "libipmi libipmb" + +S = "${WORKDIR}/bic" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libbic.so ${D}${libdir}/libbic.so + + install -d ${D}${includedir}/facebook + install -m 0644 bic.h ${D}${includedir}/facebook/bic.h +} + +FILES_${PN} = "${libdir}/libbic.so" +FILES_${PN}-dev = "${includedir}/facebook/bic.h" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libpal_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libpal_0.1.bb new file mode 100644 index 0000000..bcdd420 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libpal_0.1.bb @@ -0,0 +1,28 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Platform Abstraction Library" +DESCRIPTION = "library for communicating with Platform" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://pal.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://pal \ + " + +DEPENDS += "libbic libyosemite-common libyosemite-fruid libyosemite-sensor " + +S = "${WORKDIR}/pal" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libpal.so ${D}${libdir}/libpal.so + + install -d ${D}${includedir}/openbmc + install -m 0644 pal.h ${D}${includedir}/openbmc/pal.h +} + +FILES_${PN} = "${libdir}/libpal.so" +FILES_${PN}-dev = "${includedir}/openbmc/pal.h" + +RDEPENDS_${PN} += " libyosemite-common" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-common_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-common_0.1.bb new file mode 100644 index 0000000..bdf8192 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-common_0.1.bb @@ -0,0 +1,25 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Yosemite Common Library" +DESCRIPTION = "library for common Yosemite information" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://yosemite_common.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://yosemite_common \ + " + +S = "${WORKDIR}/yosemite_common" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libyosemite_common.so ${D}${libdir}/libyosemite_common.so + + install -d ${D}${includedir} + install -d ${D}${includedir}/facebook + install -m 0644 yosemite_common.h ${D}${includedir}/facebook/yosemite_common.h +} + +FILES_${PN} = "${libdir}/libyosemite_common.so" +FILES_${PN}-dev = "${includedir}/facebook/yosemite_common.h" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-fruid_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-fruid_0.1.bb new file mode 100644 index 0000000..ce9fe7f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-fruid_0.1.bb @@ -0,0 +1,43 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "Yosemite Fruid Library" +DESCRIPTION = "library for reading all yosemite fruids" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://yosemite_fruid.c;beginline=6;endline=18;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://yosemite_fruid \ + " + +DEPENDS += " libyosemite-common " + +S = "${WORKDIR}/yosemite_fruid" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libyosemite_fruid.so ${D}${libdir}/libyosemite_fruid.so + + install -d ${D}${includedir} + install -d ${D}${includedir}/facebook + install -m 0644 yosemite_fruid.h ${D}${includedir}/facebook/yosemite_fruid.h +} + +FILES_${PN} = "${libdir}/libyosemite_fruid.so" +FILES_${PN}-dev = "${includedir}/facebook/yosemite_fruid.h" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-gpio_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-gpio_0.1.bb new file mode 100644 index 0000000..39993d0 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-gpio_0.1.bb @@ -0,0 +1,43 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "Yosemite GPIO Pin Library" +DESCRIPTION = "library for all gpio pins in yosemite" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://yosemite_gpio.c;beginline=6;endline=18;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://yosemite_gpio \ + " + +DEPENDS += "libbic " + +S = "${WORKDIR}/yosemite_gpio" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libyosemite_gpio.so ${D}${libdir}/libyosemite_gpio.so + + install -d ${D}${includedir} + install -d ${D}${includedir}/facebook + install -m 0644 yosemite_gpio.h ${D}${includedir}/facebook/yosemite_gpio.h +} + +FILES_${PN} = "${libdir}/libyosemite_gpio.so" +FILES_${PN}-dev = "${includedir}/facebook/yosemite_gpio.h" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-sensor_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-sensor_0.1.bb new file mode 100644 index 0000000..fbb4a15 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fblibs/libyosemite-sensor_0.1.bb @@ -0,0 +1,25 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Yosemite Sensor Library" +DESCRIPTION = "library for reading various sensors" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://yosemite_sensor.c;beginline=8;endline=20;md5=da35978751a9d71b73679307c4d296ec" + + +SRC_URI = "file://yosemite_sensor \ + " +DEPENDS =+ " libipmi libipmb libbic libsdr libyosemite-common " + +S = "${WORKDIR}/yosemite_sensor" + +do_install() { + install -d ${D}${libdir} + install -m 0644 libyosemite_sensor.so ${D}${libdir}/libyosemite_sensor.so + + install -d ${D}${includedir}/facebook + install -m 0644 yosemite_sensor.h ${D}${includedir}/facebook/yosemite_sensor.h +} + +FILES_${PN} = "${libdir}/libyosemite_sensor.so" +FILES_${PN}-dev = "${includedir}/facebook/yosemite_sensor.h" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/bic-util_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/bic-util_0.1.bb new file mode 100644 index 0000000..86679d6 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/bic-util_0.1.bb @@ -0,0 +1,21 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Bridge IC Utility" +DESCRIPTION = "Util for checking with Bridge IC on Yosemite" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://bic-util.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238" + +SRC_URI = "file://bic-util \ + " + +S = "${WORKDIR}/bic-util" + +do_install() { + install -d ${D}${bindir} + install -m 0755 bic-util ${D}${bindir}/bic-util +} + +DEPENDS += "libbic" + +FILES_${PN} = "${bindir}" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/fbutils_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/fbutils_0.1.bb new file mode 100644 index 0000000..9a9f5fe --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/fbutils_0.1.bb @@ -0,0 +1,102 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "Utilities" +DESCRIPTION = "Various utilities" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=eb723b61539feef013de476e68b5c50a" + +SRC_URI = "file://ast-functions \ + file://us_console.sh \ + file://sol-util \ + file://power_led.sh \ + file://power_util.py \ + file://post_led.sh \ + file://reset_usb.sh \ + file://setup-gpio.sh \ + file://setup_rov.sh \ + file://mdio.py \ + file://bcm5396.py \ + file://bcm5396_util.py \ + file://mount_data0.sh \ + file://eth0_mac_fixup.sh \ + file://yosemite_power.sh \ + file://power-on.sh \ + file://wedge_us_mac.sh \ + file://setup_switch.py \ + file://create_vlan_intf \ + file://watch-fc.sh \ + file://fcswitcher.sh \ + file://rc.early \ + file://rc.local \ + file://src \ + file://COPYING \ + " + +pkgdir = "utils" + +S = "${WORKDIR}" + +binfiles = "us_console.sh sol-util power_led.sh post_led.sh \ + reset_usb.sh mdio.py setup_rov.sh yosemite_power.sh wedge_us_mac.sh \ + bcm5396.py bcm5396_util.py setup_switch.py watch-fc.sh power_util.py" + +DEPENDS_append = "update-rc.d-native" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + install -d $dst + install -m 644 ast-functions ${dst}/ast-functions + localbindir="${D}/usr/local/bin" + install -d ${localbindir} + for f in ${binfiles}; do + install -m 755 $f ${dst}/${f} + ln -s ../fbpackages/${pkgdir}/${f} ${localbindir}/${f} + done + + # common lib and include files + install -d ${D}${includedir}/facebook + install -m 0644 src/include/log.h ${D}${includedir}/facebook/log.h + install -m 0644 src/include/i2c-dev.h ${D}${includedir}/facebook/i2c-dev.h + + # init + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + # the script to mount /mnt/data + install -m 0755 ${WORKDIR}/mount_data0.sh ${D}${sysconfdir}/init.d/mount_data0.sh + update-rc.d -r ${D} mount_data0.sh start 03 S . + install -m 0755 ${WORKDIR}/rc.early ${D}${sysconfdir}/init.d/rc.early + update-rc.d -r ${D} rc.early start 04 S . + install -m 755 setup-gpio.sh ${D}${sysconfdir}/init.d/setup-gpio.sh + update-rc.d -r ${D} setup-gpio.sh start 59 S . + # create VLAN intf automatically + #install -d ${D}/${sysconfdir}/network/if-up.d + #install -m 755 create_vlan_intf ${D}${sysconfdir}/network/if-up.d/create_vlan_intf + # networking is done after rcS, any start level within rcS + # for mac fixup should work + #install -m 755 eth0_mac_fixup.sh ${D}${sysconfdir}/init.d/eth0_mac_fixup.sh + #update-rc.d -r ${D} eth0_mac_fixup.sh start 70 S . + install -m 755 power-on.sh ${D}${sysconfdir}/init.d/power-on.sh + update-rc.d -r ${D} power-on.sh start 85 S . + #install -m 755 fcswitcher.sh ${D}${sysconfdir}/init.d/fcswitcher.sh + #update-rc.d -r ${D} fcswitcher.sh start 90 S . + install -m 0755 ${WORKDIR}/rc.local ${D}${sysconfdir}/init.d/rc.local + update-rc.d -r ${D} rc.local start 99 2 3 4 5 . +} + +FILES_${PN} += "/usr/local ${sysconfdir}" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/COPYING b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/COPYING new file mode 100644 index 0000000..3912109 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/ast-functions b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/ast-functions new file mode 100644 index 0000000..f29514f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/ast-functions @@ -0,0 +1,147 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +DEVMEM=/sbin/devmem + +devmem_set_bit() { + local addr + local val + addr=$1 + val=$($DEVMEM $addr) + val=$((val | (0x1 << $2))) + $DEVMEM $addr 32 $val +} + +devmem_clear_bit() { + local addr + local val + addr=$1 + val=$($DEVMEM $addr) + val=$((val & ~(0x1 << $2))) + $DEVMEM $addr 32 $val +} + +scu_addr() { + echo $((0x1E6E2000 + 0x$1)) +} + +GPIODIR="/sys/class/gpio" +GPIOEXPORT="$GPIODIR/export" + +gpio_dir() { + echo "$GPIODIR/gpio$1" +} + +gpio_name2value() { + local first remaining base val + remaining=$1 + val=0 + while [ -n "$remaining" ]; do + first=${remaining:0:1} + case "$first" in + [[:lower:]]) + base=$(printf "%d" "'$first'") + base=$((base - 96)) + val=$((val * 26 + base)) + ;; + [[:upper:]]) + base=$(printf "%d" "'$first'") + base=$((base - 64)) + val=$((val * 26 + base)) + ;; + *) + if [ $val -gt 0 ]; then + val=$((val-1)) + fi + val=$((val * 8 + $remaining)) + break + ;; + esac + remaining=${remaining:1} + done + echo "$val" +} + +gpio_export() { + local gpio + gpio=$(gpio_name2value $1) + dir=$(gpio_dir $gpio) + if [ ! -d ${dir} ]; then + echo $gpio > $GPIOEXPORT + fi +} + +gpio_set() { + local gpio + local val + gpio=$(gpio_name2value $1) + val=$2 + dir=$(gpio_dir $gpio) + if [ ! -d ${dir} ]; then + echo $gpio > $GPIOEXPORT + fi + echo out > ${dir}/direction + echo $val > ${dir}/value +} + +gpio_get() { + local gpio + local val + gpio=$(gpio_name2value $1) + dir=$(gpio_dir $gpio) + if [ ! -d ${dir} ]; then + echo $gpio > $GPIOEXPORT + fi + echo in > ${dir}/direction + cat ${dir}/value +} + +# Check to see if BMC power-on-reset +is_bmc_por() { + local val + # Read the Watch Dog Counter + val=$(devmem 0x1e785010 2>/dev/null) + if [ "$((val & 0xff00))" == "0" ]; then + # Power ON Reset + echo 1 + else + echo 0 + fi +} + +# Check to see if server is present in given slot or not +is_server_prsnt() { + local prsnt + + case $1 in + 1) + prsnt=$(gpio_get H5) + ;; + 2) + prsnt=$(gpio_get H4) + ;; + 3) + prsnt=$(gpio_get H7) + ;; + 4) + prsnt=$(gpio_get H6) + ;; + *) + prsnt=$(gpio_get H4) + ;; + esac + + if [ $prsnt == "0" ]; then + echo 1 + else + echo 0 + fi +} + +yosemite_is_server_on() { + local curr_pwr_cpu + curr_pwr_cpu=$(python -c 'import sys; sys.path.append("/usr/local/fbpackages/utils"); import power_util; print power_util.get_pwr_cpu()') + if [ $curr_pwr_cpu == "1" ]; then + echo 1 + else + echo 0 + fi +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/at93c46.py b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/at93c46.py new file mode 100644 index 0000000..9fa9f05 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/at93c46.py @@ -0,0 +1,276 @@ +# Copyright 2004-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +import subprocess +import struct +import sys + +class VerboseLogger: + def __init__(self, verbose=False): + self.verbose = verbose + + def _verbose_print(self, caption, bytestream=None): + ''' + Print a bytestream to stdout if verbose is enabled. + ''' + if self.verbose: + if bytestream is not None: + sys.stderr.write("{}: {}\n".format(caption, " ".join(['{:02X}'.format(ord(x)) for x in bytestream]))) + else: + sys.stderr.write("{}\n".format(caption)) + +class AT93C46SPI(VerboseLogger): + '''The class to access AT93C46 through SPI intf''' + SPI_CMD = 'spi-bb' + + def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di, + verbose=False): + if bus_width != 8 and bus_width != 16: + raise Exception("Invalid bus width for AT93C46!") + + self.bus_width = bus_width + self.gpio_cs = gpio_cs + self.gpio_ck = gpio_ck + self.gpio_do = gpio_do + self.gpio_di = gpio_di + self.verbose = verbose + + self.addr_bits = 6 if self.bus_width == 16 else 7 + self.addr_mask = 0x3F if self.bus_width == 16 else 0x7F + + def __shift(self, bytestream, value): + ''' + Shift an entire byte stream by value bits. + ''' + binary = "".join(['{:08b}'.format(ord(x)) for x in bytestream]) + if value > 0: + binary = binary[value:] + '0' * value + else: + binary = '0' * (-value) + binary[:value] + return "".join([chr(int(binary[x:x+8],2)) for x in range(0, len(binary), 8)]) + + def __io(self, op, addr, data=None): + ''' + Perform an IO operation against the EEPROM + ''' + write_bits = self.addr_bits + 3 + if data is not None: + # If giving data, we are doing a write command so + # no need to read any data. + write_bits = write_bits + self.bus_width + read_bits = 0 + else: + # If not giving data, we are doing either a read + # command or a set command, so read the result. + # We pad with an extra bit due to a dummy bit introduced + # by a delay for address decoding on chip. + read_bits = self.addr_bits + 4 + self.bus_width + + # Format the command itself + cmd_loc = 6 if self.bus_width == 16 else 7 + instruction = addr & self.addr_mask + instruction = instruction | ((0x4 | (op & 0x3)) << cmd_loc) + if data is not None: + if self.bus_width == 16: + write_data = struct.pack(">HH", instruction, data & 0xFFFF) + else: + write_data = struct.pack(">HB", instruction, data & 0xFF) + else: + write_data = struct.pack(">H", instruction) + write_data = self.__shift(write_data, 16 - (cmd_loc + 3)) + + self._verbose_print("Write data", write_data) + + # Run the command with the bitbang driver + if read_bits > 0: + data_portion = "-r {} -w {}".format(read_bits, write_bits) + else: + data_portion = "-w {}".format(write_bits) + + cmd = "{} -s {} -c {} -o {} -i {} -b {}".format( + self.SPI_CMD, self.gpio_cs, self.gpio_ck, self.gpio_do, + self.gpio_di, data_portion + ) + + self._verbose_print("Command: {}".format(cmd)) + + out = subprocess.Popen(cmd.split(), + stdout=subprocess.PIPE, + stdin = subprocess.PIPE)\ + .communicate(input=write_data) + + # Format the response + read_data = self.__shift(out[0], cmd_loc + 4) + if self.bus_width == 16: + read_data = read_data[:2] + self._verbose_print("Read data", read_data) + return struct.unpack(">H", read_data)[0] + else: + read_data = read_data[:1] + self._verbose_print("Read data", read_data) + return struct.unpack(">B", read_data)[0] + + def read(self, addr): + return self.__io(0x2, addr) + + def ewen(self): + self.__io(0x0, 0x3 << (self.addr_bits - 2)) + + def erase(self, addr): + self.__io(0x3, addr) + + def write(self, addr, data): + self.__io(0x1, addr, data) + + def eral(self): + self.__io(0x0, 0x2 << (self.addr_bits - 2)) + + def wral(self, data): + self.__io(0x0, 0x1 << (self.addr_bits - 2), data) + + def ewds(self): + self.__io(0x0, 0x0) + +class AT93C46(VerboseLogger): + ''' + The class which handles accessing memory on the AT93C46 chip. + ''' + AT93C46_MEMORY_SIZE = 128 + + def __init__(self, bus_width, gpio_cs, gpio_ck, gpio_do, gpio_di, + byte_swap, verbose=False): + self.bus_width = bus_width + self.verbose = verbose + self.byte_swap = byte_swap + + self.spi = AT93C46SPI(bus_width=bus_width, gpio_cs=gpio_cs, + gpio_ck=gpio_ck, gpio_do=gpio_do, + gpio_di=gpio_di, verbose=verbose) + + def __swap(self, value): + ''' + Swap bytes for a 16-bit integer if instructed to do so. + ''' + if self.bus_width == 16: + if self.byte_swap: + return ((value >> 8) & 0xFF) | ((value << 8) & 0xFF00) + else: + return value + else: + return value + + def erase(self, offset=None, limit=None): + ''' + Erase the chip. + ''' + if offset is None: + offset = 0 + if limit is None: + limit = self.AT93C46_MEMORY_SIZE + + if offset < 0 or offset + limit > self.AT93C46_MEMORY_SIZE: + raise Exception("Erase would be out of bounds!") + if self.bus_width == 16 and \ + ((offset & 1) != 0 or ((offset + limit) & 1) != 0): + raise Exception("Erase can't start or end on odd boundary in 16-bit mode!") + + if offset == 0 and limit == self.AT93C46_MEMORY_SIZE: + # Special case when we are erasing the entire chip + self.spi.ewen() + self.spi.eral() + self.spi.ewds() + + self._verbose_print("Erased entire chip") + else: + # Regular case + if self.bus_width == 16: + real_offset = offset / 2 + real_limit = limit / 2 + else: + real_offset = offset + real_limit = limit + + self.spi.ewen() + for addr in range(real_offset, real_offset + real_limit): + self.spi.erase(addr) + self.spi.ewds() + + self._verbose_print("Erased {} bytes from offset {}".format(limit, offset)) + + def read(self, offset=None, limit=None): + ''' + Read the chip into a memory buffer. + ''' + if offset is None: + offset = 0 + if limit is None: + limit = self.AT93C46_MEMORY_SIZE + + if offset < 0 or offset + limit > self.AT93C46_MEMORY_SIZE: + raise Exception("Read would be out of bounds!") + if self.bus_width == 16 and \ + ((offset & 1) != 0 or ((offset + limit) & 1) != 0): + raise Exception("Read can't start or end on odd boundary in 16-bit mode!") + + output = "" + if self.bus_width == 16: + real_offset = offset / 2 + real_limit = limit / 2 + pack_instruction = "=H" + else: + real_offset = offset + real_offset + pack_instruction = "=B" + + for addr in range(real_offset, real_offset + real_limit): + output = output + struct.pack(pack_instruction, self.__swap(self.spi.read(addr))) + + self._verbose_print("Read {} bytes from offset {}".format(limit, offset), output) + + return output + + def write(self, data, offset=None): + ''' + Write a memory buffer to the chip. + ''' + if offset is None: + offset = 0 + + if offset < 0 or offset + len(data) > self.AT93C46_MEMORY_SIZE: + raise Exception("Write would be out of bounds!") + if self.bus_width == 16 and \ + ((offset & 1) != 0 or ((offset + len(data)) & 1) != 0): + raise Exception("Write can't start or end on odd boundary in 16-bit mode!") + + if self.bus_width == 16: + offset_divisor = 2 + pack_instruction = "=H" + else: + offset_divisor = 1 + pack_instruction = "=B" + + self.spi.ewen() + for addr in range(offset, offset + len(data), offset_divisor): + actual_addr = addr / offset_divisor + value = self.__swap(struct.unpack(pack_instruction, data[(addr - offset):(addr - offset) + offset_divisor])[0]) + + self.spi.erase(actual_addr) + self.spi.write(actual_addr, value) + self.spi.ewds() + + self._verbose_print("Wrote {} bytes from offset {}".format(len(data), offset), data) diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/at93c46_util.py b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/at93c46_util.py new file mode 100755 index 0000000..c10f879 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/at93c46_util.py @@ -0,0 +1,194 @@ +#!/usr/bin/python -S +# Copyright 2004-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +from argparse import ArgumentParser +from at93c46 import AT93C46, AT93C46SPI +import sys + +def get_raw(args): + return AT93C46SPI(args.bus_width, args.cs, args.clk, args.mosi, args.miso, + args.verbose) + +def get_chip(args): + return AT93C46(args.bus_width, args.cs, args.clk, args.mosi, args.miso, + args.byte_swap, args.verbose) + +def access_parser(ap): + # Default, based on currenct HW configuration + SPI_CS_DEFAULT = 68 + SPI_CLK_DEFAULT = 69 + SPI_MOSI_DEFAULT = 70 + SPI_MISO_DEFAULT = 71 + + spi_group = ap.add_argument_group('SPI Access') + spi_group.add_argument('--cs', type=int, default=SPI_CS_DEFAULT, + help='The GPIO number for SPI CS pin (default: %s)' + % SPI_CS_DEFAULT) + spi_group.add_argument('--clk', type=int, default=SPI_CLK_DEFAULT, + help='The GPIO number for SPI CLK pin (default: %s)' + % SPI_CLK_DEFAULT) + spi_group.add_argument('--mosi', type=int, default=SPI_MOSI_DEFAULT, + help='The GPIO number for SPI MOSI pin (default: %s)' + % SPI_MOSI_DEFAULT) + spi_group.add_argument('--miso', type=int, default=SPI_MISO_DEFAULT, + help='The GPIO number for SPI MISO pin (default: %s)' + % SPI_MISO_DEFAULT) + +def bus_width_parser(ap): + # Default, based on currenct HW configuration + AT83C46_BUS_WIDTH = 16 + + bus_group = ap.add_argument_group('Bus Width') + bus_group.add_argument('--bus-width', type=int, default=AT83C46_BUS_WIDTH, + help='The configured bus width (default: %s)' + % AT83C46_BUS_WIDTH) + +def read_raw(args): + raw = get_raw(args) + val = raw.read(args.address) + + if args.int: + print "{}".format(val) + else: + if args.bus_width == 16: + print "0x{:04X}".format(val) + else: + print "0x{:02X}".format(val) + +def write_raw(args): + if args.value[:2] == "0x": + value = int(args.value, 16) + else: + value = int(args.value) + + raw = get_raw(args) + raw.ewen() + raw.erase(args.address) + raw.write(args.address, value) + raw.ewds() + +def erase_raw(args): + raw = get_raw(args) + raw.ewen() + raw.erase(args.address) + raw.ewds() + +def raw_subparser(subparsers): + raw_parser = subparsers.add_parser('raw', help='Raw memory access') + raw_sub = raw_parser.add_subparsers() + + read_parser = raw_sub.add_parser('read', help='Read a single memory address') + read_parser.add_argument('address', type=int, help='The memory address') + read_parser.add_argument('--int', action='store_true', + help='Display output as an integer') + read_parser.set_defaults(func=read_raw) + + write_parser = raw_sub.add_parser('write', help='Write a single memory address') + write_parser.add_argument('address', type=int, help='The memory address') + write_parser.add_argument('value', type=str, help='The value to write, either integer or hex') + write_parser.set_defaults(func=write_raw) + + erase_parser = raw_sub.add_parser('erase', help='Erase a single memory address') + erase_parser.add_argument('address', type=int, help='The memory address') + erase_parser.set_defaults(func=erase_raw) + +def read_chip(args): + chip = get_chip(args) + data = chip.read(args.start, args.length) + + if args.file is None: + sys.stdout.write(data) + else: + fp = open(args.file, "wb") + fp.write(data) + +def write_chip(args): + chip = get_chip(args) + + # Either way, limit reads to the size of the chip + if args.file is None: + data = sys.stdin.read(AT93C46.AT93C46_MEMORY_SIZE) + else: + fp = open(args.file, "rb") + data = fp.read(AT93C46.AT93C46_MEMORY_SIZE) + + if args.length is not None: + # Make sure length is correct + if len(data) < args.length: + data = data + '\x00' * (args.length - len(data)) + if len(data) > args.length: + data = data[:args.length] + + chip.write(data, args.start) + +def erase_chip(args): + chip = get_chip(args) + chip.erase(args.start, args.length) + +def chip_subparser(subparsers): + chip_parser = subparsers.add_parser('chip', help='Chip-level access') + chip_sub = chip_parser.add_subparsers() + + read_parser = chip_sub.add_parser('read', help='Read from the chip') + read_parser.add_argument('--start', type=int, + help='The memory address to start at (default: 0)') + read_parser.add_argument('--length', type=int, + help='The number of bytes to read (default: whole chip)') + read_parser.add_argument('--file', type=str, + help='File to operate on (default: stdout)') + read_parser.add_argument('--byte-swap', action='store_true', + help='Byte swap values for 16-bit reads/writes') + read_parser.set_defaults(func=read_chip) + + write_parser = chip_sub.add_parser('write', help='Write to the chip') + write_parser.add_argument('--start', type=int, + help='The memory address to start at (default: 0)') + write_parser.add_argument('--length', type=int, + help='The number of bytes to write (default: file length)') + write_parser.add_argument('--file', type=str, + help='File to operate on (default: stdin)') + write_parser.add_argument('--byte-swap', action='store_true', + help='Byte swap values for 16-bit reads/writes') + write_parser.set_defaults(func=write_chip) + + erase_parser = chip_sub.add_parser('erase', help='Erase the chip') + erase_parser.add_argument('--start', type=int, + help='The memory address to start at (default: 0)') + erase_parser.add_argument('--length', type=int, + help='The number of bytes to erase (default: whole chip)') + erase_parser.set_defaults(func=erase_chip) + +if __name__ == "__main__": + # General arguments + ap = ArgumentParser() + ap.add_argument('--verbose', action='store_true', + help='Print verbose debugging information') + + # SPI and bus width arguments + access_parser(ap) + bus_width_parser(ap) + + # Functionality + subparsers = ap.add_subparsers() + raw_subparser(subparsers) + chip_subparser(subparsers) + + # Command runner + args = ap.parse_args() + args.func(args) diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bcm5396.py b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bcm5396.py new file mode 100644 index 0000000..e1aba47 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bcm5396.py @@ -0,0 +1,452 @@ +# +# Copyright 2004-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +import subprocess +import time + +class Bcm5396MDIO: + '''The class to access BCM5396 through MDIO intf''' + MDIO_CMD = 'mdio-bb' + + PHYADDR = 0x1E + + ACCESS_CTRL_REG = 16 + IO_CTRL_REG = 17 + STATUS_REG = 18 + DATA0_REG = 24 + DATA1_REG = 25 + DATA2_REG = 26 + DATA3_REG = 27 + + def __init__(self, mdc, mdio): + self.mdc = mdc + self.mdio = mdio + self.page = -1 + + def __io(self, op, reg, val=0): + cmd = '%s -p -c %s -d %s %s %s %s' \ + % (self.MDIO_CMD, self.mdc, self.mdio, op, str(self.PHYADDR), + str(reg)) + if op == 'write': + cmd += ' %s' % val + out = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)\ + .communicate()[0] + if op == 'write': + return val + # need to parse the result for read + rc = 0 + for line in out.split('\n'): + if not line.startswith('Read:'): + continue + rc = int(line.split(':')[1], 0) + return rc + + def __read_mdio(self, reg): + return self.__io('read', reg) + + def __write_mdio(self, reg, val): + return self.__io('write', reg, val) + + def __set_page(self, page): + if self.page == page: + return + # Write MII register ACCESS_CTRL_REG: + # set bit 0 as "1" to enable MDIO access + # set "page number to bit 15:8 + val = 0x1 | ((page & 0xff) << 8) + self.__write_mdio(self.ACCESS_CTRL_REG, val) + self.page = page + + def __wait_for_done(self): + # Read MII register IO_CTRL_REG: + # Check op_code = "00" + while (self.__read_mdio(self.IO_CTRL_REG) & 0x3): + time.sleep(0.010) # 10ms + + def read(self, page, reg, n_bytes): + self.__set_page(page) + # Write MII register IO_CTRL_REG: + # set "Operation Code as "00" + # set "Register Address" to bit 15:8 + val = 0x00 | ((reg & 0xff) << 8) + self.__write_mdio(self.IO_CTRL_REG, val) + # Write MII register IO_CTRL_REG: + # set "Operation Code as "10" + # set "Register Address" to bit 15:8 + val = 0x2 | ((reg & 0xff) << 8) + self.__write_mdio(self.IO_CTRL_REG, val) + self.__wait_for_done() + # Read MII register DATA0_REG for bit 15:0 + val = long(self.__read_mdio(self.DATA0_REG)) + # Read MII register DATA1_REG for bit 31:16 + val |= self.__read_mdio(self.DATA1_REG) << 16 + # Read MII register DATA2_REG for bit 47:32 + val |= self.__read_mdio(self.DATA2_REG) << 32 + # Read MII register DATA3_REG for bit 63:48 + val |= self.__read_mdio(self.DATA3_REG) << 48 + return val + + def write(self, page, reg, val, n_bytes): + self.__set_page(page) + # Write MII register DATA0_REG for bit 15:0 + self.__write_mdio(self.DATA0_REG, val & 0xFFFF) + # Write MII register DATA1_REG for bit 31:16 + self.__write_mdio(self.DATA1_REG, (val >> 16) & 0xFFFF) + # Write MII register DATA2_REG for bit 47:32 + self.__write_mdio(self.DATA2_REG, (val >> 32) & 0xFFFF) + # Write MII register DATA3_REG for bit 63:48 + self.__write_mdio(self.DATA3_REG, (val >> 48) & 0xFFFF) + # Write MII register IO_CTRL_REG: + # set "Operation Code as "00" + # set "Register Address" to bit 15:8 + val = 0x00 | ((reg & 0xff) << 8) + self.__write_mdio(self.IO_CTRL_REG, val) + # Write MII register IO_CTRL_REG: + # set "Operation Code as "01" + # set "Register Address" to bit 15:8 + val = 0x1 | ((reg & 0xff) << 8) + self.__write_mdio(self.IO_CTRL_REG, val) + self.__wait_for_done() + + +class Bcm5396SPI: + '''The class to access BCM5396 through SPI interface''' + SPI_CMD = 'spi-bb' + + READ_CMD = 0x60 + WRITE_CMD = 0x61 + + SPI_STS_DIO = 0xF0 + SPI_STS_REG = 0xFE + SPI_STS_REG_RACK = 0x1 << 5 + SPI_STS_REG_SPIF = 0x1 << 7 + PAGE_REG = 0xFF + + def __init__(self, cs, clk, mosi, miso): + self.cs = cs + self.clk = clk + self.mosi = mosi + self.miso = miso + self.page = -1 + + def __bytes2val(self, values): + # LSB first, MSB last + pos = 0 + result = 0L + for byte in values: + if type(byte) is str: + byte = int(byte, 16) + if byte > 255: + raise Exception('%s is not a byte in the list %s'\ + % (byte, values)) + result |= byte << pos + pos += 8 + return result + + def __val2bytes(self, value, n): + result = [] + for _ in range(n): + result.append(value & 0xFF) + value >>= 8 + if value > 0: + raise Exception('Value, %s, is too large for %s bytes' + % (value, n)) + return result + + def __io(self, bytes_to_write, to_read=0): + # TODO: check parameters + cmd = '%s -s %s -S low -c %s -o %s -i %s '\ + % (self.SPI_CMD, self.cs, self.clk, self.mosi, self.miso) + if len(bytes_to_write): + write_cmd = '-w %s %s '\ + % (len(bytes_to_write) * 8, + ' '.join([str(byte) for byte in bytes_to_write])) + else: + write_cmd = '' + if to_read: + # spi-bb will first return the exact number of bits used for + # writing. So, total number of bits to read should also include + # the number of bits written. + cmd += '-r %s ' % str((len(bytes_to_write) + to_read) * 8) + cmd += write_cmd + rc = 0L + out = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)\ + .communicate()[0] + if to_read: + # need to parse the result + for line in out.split('\n'): + if not line.startswith('Read'): + continue + res = line.split(':')[1] + rc = self.__bytes2val(res.split()[len(bytes_to_write):]) + break + return rc + + def __set_page(self, page): + page &= 0xff + if self.page == page: + return + self.__io([self.WRITE_CMD, self.PAGE_REG, page]) + self.page = page + + def __read_spi_reg(self, reg): + reg &= 0xFF + return self.__io([self.READ_CMD, reg], 1) + + def __read_spi_sts(self): + return self.__read_spi_reg(self.SPI_STS_REG) + + def __read_spi_dio(self): + return self.__read_spi_reg(self.SPI_STS_DIO) + + def read(self, page, reg, n_bytes): + '''Read a register value from a page.''' + if n_bytes > 8: + print('TODO to support reading more than 8 bytes') + return 0 + if page > 0xff or reg > 0xff: + print('Page and register must be <= 255') + return 0 + try: + self.__set_page(page) + self.__io([self.READ_CMD, reg], 1) + while True: + # check sts + sts = self.__read_spi_sts() + if sts & self.SPI_STS_REG_RACK: + break + bytes = [] + for _ in range(n_bytes): + bytes.append(self.__read_spi_dio()) + except Exception as e: + print(e) + return self.__bytes2val(bytes) + + def write(self, page, reg, val, n_bytes): + '''Write a value as n bytes to a register on a page.''' + if page > 0xff or reg > 0xff: + print('Page and register must be <= 255') + return + bytes = self.__val2bytes(val, n_bytes) + if len(bytes) > 8: + print('TODO to support writing more than 8 bytes') + return + bytes = [self.WRITE_CMD, reg] + bytes + try: + self.__set_page(page) + self.__io(bytes) + except Exception as e: + print(e) + +class Bcm5396: + '''The class for BCM5396 Switch''' + + MDIO_ACCESS = 0 + SPI_ACCESS = 1 + + def __init__(self, access, **kwargs): + if access == self.MDIO_ACCESS: + self.access = Bcm5396MDIO(**kwargs) + else: + self.access = Bcm5396SPI(**kwargs) + + def write(self, page, reg, value, n_bytes): + return self.access.write(page, reg, value, n_bytes) + + def read(self, page, reg, n_bytes): + return self.access.read(page, reg, n_bytes) + + def __add_remove_vlan(self, add, vid, untag, fwd, spt): + VLAN_PAGE = 0x5 + CTRL_ADDR = 0x60 + CTRL_START_DONE = (0x1 << 7) + VID_ADDR = 0x61 + ENTRY_ADDR = 0x63 + + fwd_map = self.__ports2portmap(fwd) + untag_map = self.__ports2portmap(untag) + + # mark it as write and stop the previous action + ctrl = 0 + self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1) + # write entry + if (add): + entry = 0x1L | ((spt & 0x1F) << 1) \ + | (fwd_map << 6) | (untag_map << 23) + else: + entry = 0x0L + self.write(VLAN_PAGE, ENTRY_ADDR, entry, 8) + # write vid as the index + self.write(VLAN_PAGE, VID_ADDR, vid & 0xFFF, 2) + # start the write + ctrl = CTRL_START_DONE + self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1) + while True: + ctrl = self.read(VLAN_PAGE, CTRL_ADDR, 1) + if not (ctrl & CTRL_START_DONE): + # done + break + time.sleep(0.010) # 10ms + + def add_vlan(self, vid, untag, fwd, spt=0): + return self.__add_remove_vlan(True, vid, untag, fwd, spt) + + def remove_vlan(self, vid): + return self.__add_remove_vlan(False, vid, [], [], 0) + + def get_vlan(self, vid): + VLAN_PAGE = 0x5 + CTRL_ADDR = 0x60 + CTRL_START_DONE = (0x1 << 7) + CTRL_READ = 0x1 + VID_ADDR = 0x61 + ENTRY_ADDR = 0x63 + + # mark it as read and stop the previous action + ctrl = CTRL_READ + self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1) + # write the vid as the index + self.write(VLAN_PAGE, VID_ADDR, vid & 0xFFF, 2) + # start the read + ctrl = CTRL_READ|CTRL_START_DONE + self.write(VLAN_PAGE, CTRL_ADDR, ctrl, 1) + while True: + ctrl = self.read(VLAN_PAGE, CTRL_ADDR, 1) + if not (ctrl & CTRL_START_DONE): + # done + break + time.sleep(0.010) # 10ms + entry = self.read(VLAN_PAGE, ENTRY_ADDR, 8) + res = {} + res['valid'] = True if entry & 0x1 else False + res['spt'] = (entry >> 1) & 0x1f + res['fwd'] = self.__portmap2ports((entry >> 6) & 0x1ffff) + res['untag'] = self.__portmap2ports((entry >> 23) & 0x1ffff) + return res + + def __portmap2ports(self, port_map): + return list(set([port if port_map & (0x1 << port) else None + for port in range (0, 17)]) + - set([None])) + + def __ports2portmap(self, ports): + port_map = 0 + for port in ports: + port_map |= (0x1 << port) + return port_map & 0x1FFFF + + def __parse_arl_result(self, vid, result): + is_bitset = lambda bit: True if result & (0x1 << bit) else False + if not is_bitset(3): + return None + res = {} + # parse vid first + res['vid'] = (vid >> 48) & 0xfff + mac_val = vid & 0xffffffffffffL + mac_list = [] + for pos in range(5, -1, -1): + mac_list.append('{:02x}'.format((mac_val >> (pos * 8)) & 0xff)) + res['mac'] = ':'.join(mac_list) + if mac_val & (0x1 << 40): + res['ports'] = self.__portmap2ports((result >> 6) & 0xffff) + else: + res['ports'] = [(result >> 6) & 0xf] + res['static'] = is_bitset(5) + res['age'] = is_bitset(4) + res['valid'] = is_bitset(3) + res['priority'] = result & 0x7 + return res + + def get_all_arls(self): + ARL_PAGE = 0x5 + SEARCH_CTRL_ADDR = 0x30 + SEARCH_CTRL_START_DONE = (0x1 << 7) + SEARCH_CTRL_SR_VALID = (0x1) + + VID0_ADDR = 0x33 + RESULT0_ADDR = 0x3B + VID1_ADDR = 0x40 + RESULT1_ADDR = 0x48 + + all = [] + # write START to search control + ctrl = SEARCH_CTRL_START_DONE + self.write(ARL_PAGE, SEARCH_CTRL_ADDR, ctrl, 1) + while True: + ctrl = self.read(ARL_PAGE, SEARCH_CTRL_ADDR, 1) + if not (ctrl & SEARCH_CTRL_START_DONE): + # Done + break + if not (ctrl & SEARCH_CTRL_SR_VALID): + # result is not ready, sleep and retry + time.sleep(0.010) # 10ms + continue + for vid_addr, result_addr in [[VID1_ADDR, RESULT1_ADDR], + [VID0_ADDR, RESULT0_ADDR]]: + vid = self.read(ARL_PAGE, vid_addr, 8) + result = self.read(ARL_PAGE, result_addr, 4) + one = self.__parse_arl_result(vid, result) + if one: + all.append(one) + return all + + def vlan_ctrl(self, enable): + VLAN_CTRL_PAGE = 0x34 + VLAN_CTRL0_REG = 0x0 + VLAN_CTRL0_B_EN_1QVLAN = 0x1 << 7 + + ctrl = self.read(VLAN_CTRL_PAGE, VLAN_CTRL0_REG, 1) + need_write = False + if enable: + if not ctrl & VLAN_CTRL0_B_EN_1QVLAN: + need_write = True; + ctrl |= VLAN_CTRL0_B_EN_1QVLAN + else: + if ctrl & VLAN_CTRL0_B_EN_1QVLAN: + need_write = True; + ctrl &= (~VLAN_CTRL0_B_EN_1QVLAN) & 0xFF + if need_write: + self.write(VLAN_CTRL_PAGE, VLAN_CTRL0_REG, ctrl, 1) + + def vlan_set_port_default(self, port, vid, pri=0): + VLAN_PORT_PAGE = 0x34 + VLAN_PORT_REG_BASE = 0x10 + + if port < 0 or port > 16: + raise Exception('Invalid port number %s' % port) + if pri < 0 or pri > 7: + raise Exception('Invalid priority %s' % pri) + if vid < 0 or vid > 0xFFF: + raise Exception('Invalid VLAN %s' % vid) + reg = VLAN_PORT_REG_BASE + port * 2 + ctrl = (pri << 13) | vid + self.write(VLAN_PORT_PAGE, reg, ctrl, 2) + + def vlan_get_port_default(self, port): + VLAN_PORT_PAGE = 0x34 + VLAN_PORT_REG_BASE = 0x10 + + if port < 0 or port > 16: + raise Exception('Invalid port number %s' % port) + reg = VLAN_PORT_REG_BASE + port * 2 + val = self.read(VLAN_PORT_PAGE, reg, 2) + res = {} + res['priority'] = (val >> 13) & 0x7 + res['vid'] = val & 0xFFF + return res diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bcm5396_util.py b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bcm5396_util.py new file mode 100644 index 0000000..1496412 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bcm5396_util.py @@ -0,0 +1,260 @@ +#!/usr/bin/python +# Copyright 2004-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +from argparse import ArgumentParser +from bcm5396 import Bcm5396 + +def auto_long(x): + return long(x, 0) + +def auto_int(x): + return int(x, 0) + +def get_bcm(args): + if args.spi: + return Bcm5396(Bcm5396.SPI_ACCESS, cs=args.cs, clk=args.clk, + mosi=args.mosi, miso=args.miso) + else: + return Bcm5396(Bcm5396.MDIO_ACCESS, mdc=args.mdc, mdio=args.mdio) + + +def read_register(args): + bcm = get_bcm(args) + val = bcm.read(args.page, args.register, args.size) + print('Read from BCM5396 ({}:{}.{}): {}' + .format(hex(args.page), hex(args.register), args.size, hex(val))) + +def write_register(args): + bcm = get_bcm(args) + val = bcm.write(args.page, args.register, args.value, args.size) + print('Write to BCM5396 ({}.{}): {}' + .format(hex(args.page), hex(args.register), hex(args.value))) + +def register_parser(subparser): + reg_parser = subparser.add_parser('register', help='Register IO') + reg_sub = reg_parser.add_subparsers() + + read_parser = reg_sub.add_parser('read', help='read switch register') + read_parser.set_defaults(func=read_register) + read_parser.add_argument('page', type=auto_int, + help='The page of the register') + read_parser.add_argument('register', type=auto_int, + help='The register to read from') + read_parser.add_argument('size', type=auto_int, + help='Number of bytes', + choices=range(1, 9)) + + write_parser = reg_sub.add_parser('write', help='write switch register') + write_parser.set_defaults(func=write_register) + write_parser.add_argument('page', type=auto_int, + help='The page oof the register') + write_parser.add_argument('register', type=auto_int, + help='The register to write to') + write_parser.add_argument('value', type=auto_long, + help='The value to write') + write_parser.add_argument('size', type=auto_int, + help='Number of bytes', + choices=range(1, 9)) + + +def dump_arl(args): + bcm = get_bcm(args) + arls = bcm.get_all_arls() + print('All ARLs are:') + for entry in arls: + print(entry) + +def arl_parser(subparser): + dump_parser = subparser.add_parser('arl', help='dump all ARL entries') + dump_parser.set_defaults(func=dump_arl) + + +def __parse_port_list(parm): + '''Parse the port numbers to a list''' + if len(parm) == 0: + return [] + ports=[] + for port in parm.split(','): + idx = port.find('-') + if idx == -1: + p = int(port) + if p < 0 or p > 15: + raise Exception('Invalid port number %s' % p) + # just one port + ports.append(p) + else: + start = int(port[:idx]) + end = int(port[idx+1:]) + if start > end or start < 0 or end > 15: + raise Exception('Invalid port range %s-%s' % (start, end)) + ports.extend(range(start, end + 1)) + return ports + +def enable_vlan(args): + bcm = get_bcm(args) + bcm.vlan_ctrl(True) + print('VLAN function is enabled.') + +def disable_vlan(args): + bcm = get_bcm(args) + bcm.vlan_ctrl(False) + print('VLAN function is disabled.') + +def add_vlan(args): + bcm = get_bcm(args) + vid = args.vid + fwd = sorted(__parse_port_list(args.fwd)) + untag = sorted(__parse_port_list(args.untag)) + spt = args.spt + # make sure untag is subset of fwd + if not set(untag).issubset(set(fwd)): + raise Exception('Some untagged ports, %s, are not part of forward ports' + % (set(untag) - set(fwd))) + bcm.add_vlan(vid, untag, fwd, spt) + print('Added VLAN: %s' % vid) + print('Ports in VLAN: %s' % sorted(fwd)) + print('Ports without VLAN tag: %s' % sorted(untag)) + +def remove_vlan(args): + bcm = get_bcm(args) + vid = args.vid + bcm.remove_vlan(vid) + print('Removed VLAN: %s' % vid) + +def show_vlan(args): + bcm = get_bcm(args) + vid = args.vid + vlan = bcm.get_vlan(vid) + if not vlan['valid']: + print('VLAN %s does not exist' % vid) + else: + print('VLAN: %s' % vid) + print('Spanning tree index: %s' % vlan['spt']) + print('Ports in VLAN: %s' % sorted(vlan['fwd'])) + print('Untagged ports in VLAN: %s' % sorted(vlan['untag'])) + +def set_port_vlan(args): + bcm = get_bcm(args) + bcm.vlan_set_port_default(args.port, args.vid, args.pri) + print('Set VLAN default for port: %s' % args.port) + print('Default VLAN: %s' % args.vid) + print('Default priority %s' % args.pri) + +def get_port_vlan(args): + bcm = get_bcm(args) + port = bcm.vlan_get_port_default(args.port) + print('Get VLAN default for port: %s' % args.port) + print('Default VLAN: %s' % port['vid']) + print('Default priority: %s' % port['priority']) + +def vlan_parser(subparser): + UNTAG_DEFAULT = '' + SPT_DEFAULT = 0 + PRI_DEFAULT = 0 + + vlan_parser = subparser.add_parser('vlan', help='Manage vlan function') + vlan_sub = vlan_parser.add_subparsers() + + add_parser = vlan_sub.add_parser('add', help='Add or modify a VLAN entry') + add_parser.add_argument('vid', type=int, help='The VLAN ID') + add_parser.add_argument('fwd', type=str, + help='Ports belonging to this VLAN. i.e. 1,4,5-8') + add_parser.add_argument('untag', type=str, default=UNTAG_DEFAULT, nargs='?', + help='Ports that do not add VLAN tag. i.e. 1,4,5-8' + ' (default: all ports are tagged)') + add_parser.add_argument('spt', type=int, default=SPT_DEFAULT, nargs='?', + help='Spanning tree index (default: %s)' + % SPT_DEFAULT) + add_parser.set_defaults(func=add_vlan) + + remove_parser = vlan_sub.add_parser('remove', help='Remove a VLAN entry') + remove_parser.add_argument('vid', type=int, help='The VLAN ID') + remove_parser.set_defaults(func=remove_vlan) + + show_parser = vlan_sub.add_parser('show', help='Show a VLAN entry') + show_parser.add_argument('vid', type=int, help='The VLAN ID') + show_parser.set_defaults(func=show_vlan) + + enable_parser = vlan_sub.add_parser('enable', help='Enable VLAN function') + enable_parser.set_defaults(func=enable_vlan) + + disable_parser = vlan_sub.add_parser('disable', help='Enable VLAN function') + disable_parser.set_defaults(func=disable_vlan) + + port_parser = vlan_sub.add_parser('port', + help='Set/Get VLAN default for a port') + port_sub = port_parser.add_subparsers() + set_port = port_sub.add_parser('set', help='Set VLAN default for a port') + set_port.add_argument('port', type=int, help='The port number (0..16)') + set_port.add_argument('vid', type=int, + help='The default VLAN for this port') + set_port.add_argument('pri', type=int, default=PRI_DEFAULT, nargs='?', + help='The default priority for this port ' + '(default: %s)' % PRI_DEFAULT) + set_port.set_defaults(func=set_port_vlan) + + get_port = port_sub.add_parser('get', help='Get VLAN default for a port') + get_port.add_argument('port', type=int, help='The port number (0..16)') + get_port.set_defaults(func=get_port_vlan) + +def access_parser(ap): + SPI_CS_DEFAULT = 68 + SPI_CLK_DEFAULT = 69 + SPI_MOSI_DEFAULT = 70 + SPI_MISO_DEFAULT = 71 + + MDIO_MDC_DEFAULT = 6 + MDIO_MDIO_DEFAULT = 7 + + spi_group = ap.add_argument_group('SPI Access') + spi_group.add_argument('--spi', action='store_true', + help='Access through SPI.') + spi_group.add_argument('--cs', type=int, default=SPI_CS_DEFAULT, + help='The GPIO number for SPI CS pin (default: %s)' + % SPI_CS_DEFAULT) + spi_group.add_argument('--clk', type=int, default=SPI_CLK_DEFAULT, + help='The GPIO number for SPI CLK pin (default: %s)' + % SPI_CLK_DEFAULT) + spi_group.add_argument('--mosi', type=int, default=SPI_MOSI_DEFAULT, + help='The GPIO number for SPI MOSI pin (default: %s)' + % SPI_MOSI_DEFAULT) + spi_group.add_argument('--miso', type=int, default=SPI_MISO_DEFAULT, + help='The GPIO number for SPI MISO pin (default: %s)' + % SPI_MISO_DEFAULT) + mdio_group = ap.add_argument_group('MDIO Access (default)') + mdio_group.add_argument('--mdc', type=int, default=MDIO_MDC_DEFAULT, + help='The GPIO number for MDC pin (default: %s)' + % MDIO_MDC_DEFAULT) + mdio_group.add_argument('--mdio', type=int, default=MDIO_MDIO_DEFAULT, + help='The GPIO number for MDIO pin (default: %s)' + % MDIO_MDIO_DEFAULT) + return ap + + +if __name__ == '__main__': + ap = ArgumentParser() + access_parser(ap) + + subparsers = ap.add_subparsers() + register_parser(subparsers) + arl_parser(subparsers) + vlan_parser(subparsers) + args = ap.parse_args() + + args.func(args) diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bic-util/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bic-util/Makefile new file mode 100644 index 0000000..9c046be --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bic-util/Makefile @@ -0,0 +1,10 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +all: bic-util + +bic-util: bic-util.c + $(CC) -pthread -lipmi -lipmb -lbic -std=c99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o bic-util diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bic-util/bic-util.c b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bic-util/bic-util.c new file mode 100644 index 0000000..4a8966d --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/bic-util/bic-util.c @@ -0,0 +1,384 @@ +/* + * bic-util + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <stdint.h> +#include <pthread.h> +#include <facebook/bic.h> +#include <openbmc/ipmi.h> + +#define LAST_RECORD_ID 0xFFFF +#define MAX_SENSOR_NUM 0xFF +#define BYTES_ENTIRE_RECORD 0xFF + +// Test to Get device ID +static void +util_get_device_id(uint8_t slot_id) { + int ret; + ipmi_dev_id_t id = {0}; + + ret = bic_get_dev_id(slot_id, &id); + if (ret) { + printf("util_get_device_id: bic_get_dev_id returns %d\n", ret); + return; + } + + // Print response + printf("Device ID: 0x%X\n", id.dev_id); + printf("Device Revision: 0x%X\n", id.dev_rev); + printf("Firmware Revision: 0x%X:0x%X\n", id.fw_rev1, id.fw_rev2); + printf("IPMI Version: 0x%X\n", id.ipmi_ver); + printf("Device Support: 0x%X\n", id.dev_support); + printf("Manufacturer ID: 0x%X:0x%X:0x%X\n", id.mfg_id[2], id.mfg_id[1], id.mfg_id[0]); + printf("Product ID: 0x%X:0x%X\n", id.prod_id[1], id.prod_id[0]); + printf("Aux. FW Rev: 0x%X:0x%X:0x%X:0x%X\n", id.aux_fw_rev[0], id.aux_fw_rev[1],id.aux_fw_rev[2],id.aux_fw_rev[3]); +} + +// Tests for reading GPIO values and configuration +static void +util_get_gpio(uint8_t slot_id) { + int ret; + bic_gpio_t gpio = {0}; + + ret = bic_get_gpio(slot_id, &gpio); + if (ret) { + printf("util_get_gpio: bic_get_gpio returns %d\n", ret); + return; + } + + bic_gpio_u *t = (bic_gpio_u*) &gpio; + + // Print response + printf("PWRGOOD_CPU: %d\n", t->bits.pwrgood_cpu); + printf("PWRGOOD_PCH_PWROK: %d\n", t->bits.pwrgd_pch_pwrok); + printf("PVDDR_VRHOT_N: %d\n", t->bits.pvddr_vrhot_n); + printf("PVCCIN_VRHOT_N: %d\n", t->bits.pvccin_vrhot_n); + printf("FM_FAST_PROCHOT_N: %d\n", t->bits.fm_fast_prochot_n); + printf("PCHHOT_CPU_N: %d\n", t->bits.pchhot_cpu_n); + printf("FM_CPLD_CPU_DIMM_EVENT_C0_N: %d\n", t->bits.fm_cpld_cpu_dimm_event_c0_n); + printf("FM_CPLD_BDXDE_THERMTRIP_N: %d\n", t->bits.fm_cpld_bdxde_thermtrip_n); + printf("THERMTRIP_PCH_N: %d\n", t->bits.thermtrip_pch_n); + printf("FM_CPLD_FIVR_FAULT: %d\n", t->bits.fm_cpld_fivr_fault); + printf("FM_BDXDE_CATERR_LVT3_N: %d\n", t->bits.fm_bdxde_caterr_lvt3_n); + printf("FM_BDXDE_ERR_LVT3_N: %d\n", t->bits.fm_bdxde_err_lvt3_n); + printf("SLP_S4_N: %d\n", t->bits.slp_s4_n); + printf("FM_NMI_EVENT_BMC_N: %d\n", t->bits.fm_nmi_event_bmc_n); + printf("FM_SMI_BMC_N: %d\n", t->bits.fm_smi_bmc_n); + printf("RST_PLTRST_BMC_N: %d\n", t->bits.rst_pltrst_bmc_n); + printf("FP_RST_BTN_BUF_N: %d\n", t->bits.fp_rst_btn_buf_n); + printf("BMC_RST_BTN_OUT_N: %d\n", t->bits.bmc_rst_btn_out_n); + printf("FM_BDE_POST_CMPLT_N: %d\n", t->bits.fm_bde_post_cmplt_n); + printf("FM_BDXDE_SLP3_N: %d\n", t->bits.fm_bdxde_slp3_n); + printf("FM_PWR_LED_N: %d\n", t->bits.fm_pwr_led_n); + printf("PWRGD_PVCCIN: %d\n", t->bits.pwrgd_pvccin); + printf("SVR_ID: %d\n", t->bits.svr_id); + printf("BMC_READY_N: %d\n", t->bits.bmc_ready_n); + printf("BMC_COM_SW_N: %d\n", t->bits.bmc_com_sw_n); + printf("rsvd: %d\n", t->bits.rsvd); +} + +static void +util_get_gpio_config(uint8_t slot_id) { + int ret; + int i; + bic_gpio_config_t gpio_config = {0}; + bic_gpio_config_u *t = (bic_gpio_config_u *) &gpio_config; + + // Read configuration of all bits + for (i = 0; i < MAX_GPIO_PINS; i++) { + ret = bic_get_gpio_config(slot_id, i, &gpio_config); + if (ret == -1) { + continue; + } + + printf("gpio_config for pin#%d:\n", i); + printf("Direction: %s", t->bits.dir?"Output":"Input"); + printf("Interrupt Enabled?: %s", t->bits.ie?"Enabled":"Disabled"); + printf("Trigger Type: %s", t->bits.edge?"Level":"Edge"); + if (t->bits.trig == 0x0) { + printf("Trigger Edge: %s\n", "Falling Edge"); + } else if (t->bits.trig == 0x1) { + printf("Trigger Edge: %s\n", "Falling Edge"); + } else if (t->bits.trig == 0x2) { + printf("Trigger Edge: %s\n", "Both Edges"); + } else { + printf("Trigger Edge: %s\n", "Reserved"); + } + } +} + +static void +util_get_config(uint8_t slot_id) { + int ret; + int i; + bic_config_t config = {0}; + bic_config_u *t = (bic_config_u *) &config; + + ret = bic_get_config(slot_id, &config); + if (ret) { + printf("util_get_config: bic_get_config failed\n"); + return; + } + + printf("SoL Enabled?: %s", t->bits.sol? "Enabled" : "Disabled"); + printf("POST Enabled?: %s", t->bits.post? "Enabled" : "Disabled"); + printf("KCS Enabled?: %s", t->bits.kcs? "Enabled" : "Disabled"); + printf("IPMB Enabled?: %s", t->bits.ipmb? "Enabled" : "Disabled"); +} + +static void +util_set_config(uint8_t slot_id, uint8_t status) { + +} + +// Test to get the POST buffer +static void +util_get_post_buf(uint8_t slot_id) { + int ret; + uint8_t buf[MAX_IPMB_RES_LEN] = {0x0}; + uint8_t len; + int i; + + ret = bic_get_post_buf(slot_id, buf, &len); + if (ret) { + printf("util_get_post_buf: bic_get_post_buf returns %d\n", ret); + return; + } + + printf("util_get_post_buf: returns %d bytes\n", len); + for (i = 0; i < len; i++) { + printf("0x%X:", buf[i]); + } + printf("\n"); +} + +// Tests to read FRUID of Monolake Server +static void +util_get_fruid_info(uint8_t slot_id) { + int ret; + int i; + + ipmi_fruid_info_t info = {0}; + + ret = bic_get_fruid_info(slot_id, 0, &info); + if (ret) { + printf("util_get_fruid_info: bic_get_fruid_info returns %d\n", ret); + return; + } + + printf("FRUID info for 1S Slot..\n"); + + printf("FRUID Size: %d\n", (info.size_msb << 8) + (info.size_lsb)); + printf("Accessed as : %s\n", (info.bytes_words)?"Words":"Bytes"); +} + +static void +util_read_fruid(uint8_t slot_id) { + int ret; + int i; + + char path[64] = {0}; + sprintf(path, "/tmp/fruid_slot%d.bin", slot_id); + + ret = bic_read_fruid(slot_id, 0, path); + if (ret) { + printf("util_read_fruid: bic_read_fruid returns %d\n", ret); + return; + } +} + +// Tests to read SEL from Monolake Server +static void +util_get_sel_info(uint8_t slot_id) { + int ret; + + ipmi_sel_sdr_info_t info; + + ret = bic_get_sel_info(slot_id, &info); + if (ret) { + printf("util_get_sel_info:bic_get_sel_info returns %d\n", ret); + return; + } + + printf("SEL info for 1S Slot is..\n"); + + printf("version: 0x%X\n", info.ver); + printf("Record Count: 0x%X\n", info.rec_count); + printf("Free Space: 0x%X\n", info.free_space); + printf("Recent Add TS: 0x%X:0x%X:0x%X:0x%X\n", info.add_ts[3], info.add_ts[2], info.add_ts[1], info.add_ts[0]); + printf("Recent Erase TS: 0x%X:0x%X:0x%X:0x%X\n", info.erase_ts[3], info.erase_ts[2], info.erase_ts[1], info.erase_ts[0]); + printf("Operation Support: 0x%X\n", info.oper); +} + +static void +util_get_sel(uint8_t slot_id) { + int ret; + int i; + uint16_t rsv; + uint8_t rlen; + uint8_t rbuf[MAX_IPMB_RES_LEN] = {0}; + + ipmi_sel_sdr_req_t req; + ipmi_sel_sdr_res_t *res = (ipmi_sel_sdr_res_t *) rbuf; + + req.rsv_id = 0; + req.rec_id = 0; + req.offset = 0; + req.nbytes = BYTES_ENTIRE_RECORD; + + while (1) { + ret = bic_get_sel(slot_id, &req, res, &rlen); + if (ret) { + printf("util_get_sel:bic_get_sel returns %d\n", ret); + continue; + } + + printf("SEL for rec_id %d\n", req.rec_id); + printf("Next Record ID is %d\n", res->next_rec_id); + printf("Record contents are..\n"); + for (i = 0; i < rlen-2; i++) { // First 2 bytes are next_rec_id + printf("0x%X:", res->data[i]); + } + printf("\n"); + + req.rec_id = res->next_rec_id; + if (req.rec_id == LAST_RECORD_ID) { + printf("This record is LAST record\n"); + break; + } + } +} + +// Tests to read SDR records from Monolake Servers +static void +util_get_sdr_info(uint8_t slot_id) { + int ret; + + ipmi_sel_sdr_info_t info; + + ret = bic_get_sdr_info(slot_id, &info); + if (ret) { + printf("util_get_sdr_info:bic_get_sdr_info returns %d\n", ret); + return; + } + + printf("SDR info for 1S Slot is..\n"); + + printf("version: 0x%X\n", info.ver); + printf("Record Count: 0x%X\n", info.rec_count); + printf("Free Space: 0x%X\n", info.free_space); + printf("Recent Add TS: 0x%X:0x%X:0x%X:0x%X\n", info.add_ts[3], info.add_ts[2], info.add_ts[1], info.add_ts[0]); + printf("Recent Erase TS: 0x%X:0x%X:0x%X:0x%X\n", info.erase_ts[3], info.erase_ts[2], info.erase_ts[1], info.erase_ts[0]); + printf("Operation Support: 0x%X\n", info.oper); +} + +static void +util_get_sdr(uint8_t slot_id) { + int ret; + int i; + uint16_t rsv; + uint8_t rlen; + uint8_t rbuf[MAX_IPMB_RES_LEN] = {0}; + + ipmi_sel_sdr_req_t req; + ipmi_sel_sdr_res_t *res = (ipmi_sel_sdr_res_t *) rbuf; + + req.rsv_id = 0; + req.rec_id = 0; + req.offset = 0; + req.nbytes = BYTES_ENTIRE_RECORD; + + while (1) { + ret = bic_get_sdr(slot_id, &req, res, &rlen); + if (ret) { + printf("util_get_sdr:bic_get_sdr returns %d\n", ret); + continue; + } + + sdr_full_t *sdr = res->data; + + printf("type: %d, ", sdr->type); + printf("sensor_num: %d, ", sdr->sensor_num); + printf("sensor_type: %d, ", sdr->sensor_type); + printf("evt_read_type: %d, ", sdr->evt_read_type); + printf("m_val: %d, ", sdr->m_val); + printf("m_tolerance: %d, ", sdr->m_tolerance); + printf("b_val: %d, ", sdr->b_val); + printf("b_accuracy: %d, ", sdr->b_accuracy); + printf("accuracy_dir: %d, ", sdr->accuracy_dir); + printf("rb_exp: %d,\n", sdr->rb_exp); + + req.rec_id = res->next_rec_id; + if (req.rec_id == LAST_RECORD_ID) { + printf("This record is LAST record\n"); + break; + } + } +} + +// Test to read all Sensors from Monolake Server +static void +util_read_sensor(uint8_t slot_id) { + int ret; + int i; + ipmi_sensor_reading_t sensor; + + for (i = 0; i < MAX_SENSOR_NUM; i++) { + ret = bic_read_sensor(slot_id, i, &sensor); + if (ret) { + continue; + } + + printf("sensor#%d: value: 0x%X, flags: 0x%X, status: 0x%X, ext_status: 0x%X\n", + i, sensor.value, sensor.flags, sensor.status, sensor.ext_status); + } +} + +// TODO: Make it as User selectable tests to run +int +main(int argc, char **argv) { + + uint8_t slot_id; + + slot_id = atoi(argv[1]); + + util_get_device_id(slot_id); + + util_get_gpio(slot_id); + util_get_gpio_config(slot_id); + + util_get_config(slot_id); + + util_get_post_buf(slot_id); + + util_get_fruid_info(slot_id); + util_read_fruid(slot_id); + + util_get_sel_info(slot_id); + util_get_sel(slot_id); + + util_get_sdr_info(slot_id); + util_get_sdr(slot_id); + util_read_sensor(slot_id); +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/create_vlan_intf b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/create_vlan_intf new file mode 100644 index 0000000..2cf7a9a --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/create_vlan_intf @@ -0,0 +1,37 @@ +#!/bin/bash +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +# only care about 'eth0' and 'oob' intf +[ "$IFACE" != "eth0" ] && [ "$IFACE" != "oob" ] && exit 0 + +. /usr/local/fbpackages/utils/ast-functions + +board=$(wedge_board_type) + +[ "$board" = "WEDGE" ] && exit 0 + +vlan=4088 +intf="${IFACE}.${vlan}" +slot=$(wedge_slot_id $board) + +vconfig add $IFACE $vlan +ifconfig $intf up "fe80::$(printf "%x" $slot):1/64" + +exit 0 diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/eth0_mac_fixup.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/eth0_mac_fixup.sh new file mode 100644 index 0000000..1cdbcb6 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/eth0_mac_fixup.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: eth0_mac_fixup.sh +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Fixup the MAC address for eth0 based on wedge EEPROM +### END INIT INFO + +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + +mac=$(weutil 2>/dev/null | grep '^Local MAC' 2>/dev/null | cut -d' ' -f3 2>/dev/null) + +if [ -n "$mac" ]; then + ifconfig eth0 hw ether $mac + # compare the 'ethaddr' from u-boot env + ethaddr=$(fw_printenv ethaddr 2>/dev/null | cut -d'=' -f2 2>/dev/null) + if [ "$ethaddr" != "$mac" ]; then + fw_setenv "ethaddr" "$mac" + fi +fi diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/fcswitcher.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/fcswitcher.sh new file mode 100755 index 0000000..53e24f3 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/fcswitcher.sh @@ -0,0 +1,83 @@ +#! /bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: usbcons +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Creates a virtual USB serial device and starts a console +# on it. +# +### END INIT INFO + +PATH=/sbin:/bin:/usr/sbin:/usr/bin +NAME="FC Switcher" +DESC="FC Failover Daemon" + +# source function library +. /etc/init.d/functions + +. /usr/local/fbpackages/utils/ast-functions + +STOPPER= +ACTION="$1" + +case "$ACTION" in + start) + if [ "$(wedge_board_type)" = "LC" ]; then + # Ability to prevent this from starting by editing cmdline in u-boot. + # Keeping this here until I get gadget switching working properly. (t4906522) + /usr/local/bin/watch-fc.sh > /dev/null 2>&1 & + echo "$NAME." + else + echo 'skipping watch-fc.sh: only necessary on six-pack line cards.' + fi + ;; + stop) + echo -n "Stopping $DESC: " + killall watch-fc.sh + echo "$NAME." + ;; + restart|force-reload) + echo -n "Restarting $DESC: " + killall watch-fc.sh + if [ "$(wedge_board_type)" = "LC" ]; then + sleep 1 + /usr/local/bin/watch-fc.sh > /dev/null 2>&1 & + echo "$NAME." + else + echo 'skipping watch-fc.sh: only necessary on six-pack line cards.' + fi + ;; + status) + status watch-fc.sh + exit $? + ;; + *) + N=${0##*/} + N=${N#[SK]??} + echo "Usage: $N {start|stop|status|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/mdio.py b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/mdio.py new file mode 100755 index 0000000..aa7d4bf --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/mdio.py @@ -0,0 +1,124 @@ +#!/usr/bin/python +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +from argparse import ArgumentParser +import subprocess +import time + +IO_BASE = [ 0x1e660000, 0x1e680000 ] +PHYCR_REG_OFFSET = 0x60 +PHYCR_READ_BIT = 0x1 << 26 +PHYCR_WRITE_BIT = 0x1 << 27 +phycr_reg = lambda mac: IO_BASE[mac - 1] + PHYCR_REG_OFFSET +PHYDATA_REG_OFFSET = 0x64 +phydata_reg = lambda mac: IO_BASE[mac - 1] + PHYDATA_REG_OFFSET + + +devmem_read_cmd = lambda reg: [ 'devmem', hex(reg) ] +devmem_write_cmd = lambda reg, val: [ 'devmem', hex(reg), '32', hex(val)] + + +def devmem_read(reg): + cmd = devmem_read_cmd(reg) + #print('Cmd: {}'.format(cmd)) + out = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] + return int(out, 0) + + +def devmem_write(reg, val): + cmd = devmem_write_cmd(reg, val) + #print('Cmd: {}'.format(cmd)) + subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] + + +def wait_for_mdio_done(args): + reg = phycr_reg(args.mac) + while devmem_read(reg) & (PHYCR_READ_BIT|PHYCR_WRITE_BIT): + time.sleep(0.010) # 10ms + + +def read_mdio(args): + reg = phycr_reg(args.mac) + ctrl = devmem_read(reg) + ctrl &= 0x3000003f + ctrl |= (args.phy & 0x1F) << 16 + ctrl |= (args.register & 0x1F) << 21 + ctrl |= PHYCR_READ_BIT + devmem_write(reg, ctrl) + wait_for_mdio_done(args) + val = devmem_read(phydata_reg(args.mac)) >> 16 + print('Read from PHY ({}.{}): {}' + .format(hex(args.phy), hex(args.register), hex(val))) + + +def write_mdio(args): + ctrl_reg = phycr_reg(args.mac) + ctrl = devmem_read(ctrl_reg) + ctrl &= 0x3000003f + ctrl |= (args.phy & 0x1F) << 16 + ctrl |= (args.register & 0x1F) << 21 + ctrl |= PHYCR_WRITE_BIT + data_reg = phydata_reg(args.mac) + # write data first + devmem_write(data_reg, args.value) + # then ctrl + devmem_write(ctrl_reg, ctrl) + wait_for_mdio_done(args) + print('Write to PHY ({}.{}): {}' + .format(hex(args.phy), hex(args.register), hex(args.value))) + + +def auto_int(x): + return int(x, 0) + +if __name__ == '__main__': + ap = ArgumentParser() + ap.add_argument('--mac', '-m', type=int, default=2, + help='The MAC') + ap.add_argument('--phy', '-p', type=auto_int, default=0x1f, + help='The PHY address') + + subparsers = ap.add_subparsers() + + read_parser = subparsers.add_parser('read', + help='read MDIO') + read_parser.set_defaults(func=read_mdio) + read_parser.add_argument('register', type=auto_int, + help='The register to read from') + + write_parser = subparsers.add_parser('write', + help='write MDIO') + write_parser.set_defaults(func=write_mdio) + write_parser.add_argument('register', type=auto_int, + help='The register to write to') + write_parser.add_argument('value', type=auto_int, + help='The value to write to') + + args = ap.parse_args() + + if args.mac != 2 and args.mac != 1: + print("MAC can only be either 1 or 2.") + exit(-1) + + if args.phy > 0x1f: + printf("PHY address must be smaller than 0x1f.") + exit(-2) + + args.func(args) diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/mount_data0.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/mount_data0.sh new file mode 100755 index 0000000..6986be5 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/mount_data0.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: mount_data0 +# Required-Start: mountvirtfs +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Mount data0 partition from flash chip. +# Description: +### END INIT INFO + +. /etc/default/rcS + +# Find out which device maps to 'data0' on mtd +# Note: /proc/mtd lists partitions using mtdX, where X is a number, +# but we mount using /dev/mtdblockX. We'll do some magic here +# to get the mtdX (char device) and mtdblockX (block device) +# names. +MOUNT_POINT="/mnt/data" +DATA_CHAR_DEV=$(cat /proc/mtd | awk '{ if ($4 == "\"data0\"") print $1 }' | + cut -d ':' -f 1 | awk '{ print "/dev/" $1 }') +if [ -z "$DATA_CHAR_DEV" ] +then + echo "No data0 partition found. Not mounting anything to $MOUNT_POINT." +else + DEVICE_ID=$(echo $DATA_CHAR_DEV | tail -c 2) + DATA_BLOCK_DEV=${DATA_CHAR_DEV/mtd/mtdblock} + + echo "data0 partition found on $DATA_BLOCK_DEV; mounting to $MOUNT_POINT." + mount -t jffs2 $DATA_BLOCK_DEV $MOUNT_POINT + + # if the mount failed, format the partition and remount + if [ $? -ne 0 ] + then + echo "Mount failed; formatting $DATA_BLOCK_DEV and remounting." + flash_eraseall $DATA_CHAR_DEV + mount -t jffs2 $DATA_BLOCK_DEV $MOUNT_POINT + fi +fi + +: exit 0 + diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/post_led.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/post_led.sh new file mode 100644 index 0000000..c23349f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/post_led.sh @@ -0,0 +1,105 @@ +#!/bin/sh +# +# Copyright 2004-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +usage() { + echo "Displays values onto the debug header LEDs." + echo "Hex and decimal accepted." + echo "Usage: $0 <value>" +} + +. /usr/local/fbpackages/utils/ast-functions + +# Function to set the less significant hex digit +display_lower() { + local bit0=$(expr $1 % 2) + local bit1=$(expr $1 / 2 % 2) + local bit2=$(expr $1 / 4 % 2) + local bit3=$(expr $1 / 8 % 2) + + # Set the pins to the correct operating mode. + # The relevant pins are GPIOG[0...3]. + # For GPIO bank G, SCU84[0..3] must be 0. + devmem_clear_bit $(scu_addr 84) 0 + devmem_clear_bit $(scu_addr 84) 1 + devmem_clear_bit $(scu_addr 84) 2 + devmem_clear_bit $(scu_addr 84) 3 + + # Now set the GPIOs to the right binary values + gpio_set 48 $bit0 + gpio_set 49 $bit1 + gpio_set 50 $bit2 + gpio_set 51 $bit3 +} + +# Function to set the more significant hex digit +display_upper() { + local bit0=$(expr $1 % 2) + local bit1=$(expr $1 / 2 % 2) + local bit2=$(expr $1 / 4 % 2) + local bit3=$(expr $1 / 8 % 2) + + # Set the pins to the correct operating mode. + # The relevant pins are GPIOB[4...7]. + # GPIOB4: SCU80[12] = 0 and Strap[14] = 0 + # GPIOB5: SCU80[13] = 0 + # GPIOB6: SCU80[14] = 0 + # GPIOB7: SCU80[15] = 0 + devmem_clear_bit $(scu_addr 70) 14 + devmem_clear_bit $(scu_addr 80) 12 + devmem_clear_bit $(scu_addr 80) 13 + devmem_clear_bit $(scu_addr 80) 14 + devmem_clear_bit $(scu_addr 80) 15 + + gpio_set 12 $bit0 + gpio_set 13 $bit1 + gpio_set 14 $bit2 + gpio_set 15 $bit3 +} + +# Check number of parameters +if [ $# -ne 1 ] +then + usage + exit 1 +fi + +# Make sure input is actually numeric +DEC_VALUE=$(printf "%d" $1 2>/dev/null) +if [ $? -eq 1 ] +then + echo "Unable to parse input as numeric value." + exit 1 +fi + +# Make sure input is within proper range +if [ $DEC_VALUE -lt 0 ] || [ $DEC_VALUE -gt 255 ] +then + echo "Value $DEC_VALUE is outside of displayable range 0 - 0xff (255)." + exit 1 +fi + +# Get upper/lower decimal values +LOWER_DEC_VALUE=$(expr $DEC_VALUE % 16) +UPPER_DEC_VALUE=$(expr $DEC_VALUE / 16) + +# Display the results +display_lower $LOWER_DEC_VALUE +display_upper $UPPER_DEC_VALUE + diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/power-on.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/power-on.sh new file mode 100644 index 0000000..3a9ce06 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/power-on.sh @@ -0,0 +1,99 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +### BEGIN INIT INFO +# Provides: power-on +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Power on Server +### END INIT INFO +. /usr/local/fbpackages/utils/ast-functions + +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + +# Disable Watch Dog Timer +/usr/local/bin/watchdog_ctrl.sh off + + +KEYDIR=/mnt/data/kv_store +DEF_PWR_ON=1 +TO_PWR_ON= + +check_por_config() +{ + + TO_PWR_ON=-1 + + # Check if the file/key doesn't exist + if [ ! -f "${KEYDIR}/slot${1}_por_cfg" ]; then + TO_PWR_ON=$DEF_PWR_ON + else + POR=`cat ${KEYDIR}/slot${1}_por_cfg` + + # Case ON + if [ $POR == "on" ]; then + TO_PWR_ON=1; + + # Case OFF + elif [ $POR == "off" ]; then + TO_PWR_ON=0; + + # Case LPS + elif [ $POR == "lps" ]; then + + # Check if the file/key doesn't exist + if [ ! -f "${KEYDIR}/pwr_server${1}_last_state" ]; then + TO_PWR_ON=$DEF_PWR_ON + else + LS=`cat ${KEYDIR}/pwr_server${1}_last_state` + if [ $LS == "on" ]; then + TO_PWR_ON=1; + elif [ $LS == "off" ]; then + TO_PWR_ON=0; + fi + fi + fi + fi +} + +# Check whether it is fresh power on reset +if [ $(is_bmc_por) -eq 1 ]; then + + check_por_config 1 + if [ $TO_PWR_ON -eq 1 ] && [ $(is_server_prsnt 1) == "1" ] ; then + power-util slot1 on + fi + + check_por_config 2 + if [ $TO_PWR_ON -eq 1 ] && [ $(is_server_prsnt 2) == "1" ] ; then + power-util slot2 on + fi + + check_por_config 3 + if [ $TO_PWR_ON -eq 1 ] && [ $(is_server_prsnt 3) == "1" ] ; then + power-util slot3 on + fi + + check_por_config 4 + if [ $TO_PWR_ON -eq 1 ] && [ $(is_server_prsnt 4) == "1" ] ; then + power-util slot4 on + fi +fi diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/power_led.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/power_led.sh new file mode 100755 index 0000000..2f9bb6a --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/power_led.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +usage() { + echo "Usage: $1 <slot#> <on | off>" + exit -1 +} + +. /usr/local/fbpackages/utils/ast-functions + +PATH=/sbin:/bin:/usr/sbin:/usr/bin + +set -e + +if [ $# != 2 ]; then + usage $0 +fi + +# Slot#1: GPIOM1(97),Slot#2: GPIOM0(96),Slot#3: GPIOM3(99),Slot#4: GPIOM2(98) +if [ $1 = "1" ]; then + gpio=M1 +elif [ $1 = "2" ]; then + gpio=M0 +elif [ $1 = "3" ]; then + gpio=M3 +elif [ $1 = "4" ]; then + gpio=M2 +else + usage $0 +fi + + +if [ $2 = "on" ]; then + val=1 +elif [ $2 = "off" ]; then + val=0 +else + usage $0 +fi + +gpio_set $gpio $val diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/power_util.py b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/power_util.py new file mode 100644 index 0000000..d1cc60e --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/power_util.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +import os +import re +import time +import logging +from ctypes import * + +POR_DIR = '/mnt/data/power/por' +POR_CONFIG = '%s/config' % POR_DIR +POR_LPS = '%s/last_state' % POR_DIR + +logging.basicConfig(level=logging.INFO) +log = logging.getLogger(__name__) + +class PORConfig(): + on = "1" # Default ON + off = "2" # Default OFF + lps = "3" # Default is to use the Last Power State + +# Handler for Bridge IC libraries +bic = CDLL("libbic.so") + +class BIC_GPIO(Structure): + _fields_ = [ ("bic_gpio_data", c_char * 4) ] + +# Get 32-bit GPIO data +def get_bic_gpio(): + gpio = BIC_GPIO() + p_gpio = pointer(gpio) + bic.bic_get_gpio(p_gpio) + return gpio + +# Get the CPU power status +def get_pwr_cpu(): + gpio = get_bic_gpio() + pwrgood_cpu = (ord(gpio.bic_gpio_data[0]) & 0x01) + return pwrgood_cpu + +# Initilize the POR configuration files in /mnt/data +def init_por(): + + por = PORConfig() + + # For the Power On Reset Config + if not os.path.isfile(POR_CONFIG): + try: + os.makedirs(POR_DIR) + except OSERROR as err: + pass + + por_cnfg = open(POR_CONFIG, 'w') + por_cnfg.write('%s\n' % por.on) + por_cnfg.close() + + # For the Last Power State info + if not os.path.isfile(POR_LPS): + curr_time = int(time.time()) + lps = 'on %s' % str(curr_time) + + f_lps = open(POR_LPS, 'w') + f_lps.write('%s\n' % lps) + f_lps.close() + +# Get the POR config [ ON | OFF | LPS ] +def get_por_config(): + + por = PORConfig() + + if os.path.isfile(POR_CONFIG): + por_cnfg = open(POR_CONFIG, 'r') + cnfg = por_cnfg.read(1) + + if cnfg in [por.on, por.off, por.lps]: + return cnfg + else: + return 0 + else: + return -1 + +# To check whether the last power state was on or off +def get_por_lps(): + + if os.path.isfile(POR_LPS): + f_lps = open(POR_LPS, 'r') + lps = f_lps.readline() + if re.search(r'on', lps): + return 1 + elif re.search(r'off', lps): + return 0 + else: + return -1 + +# This tells whether to Power ON or not on POR +# 1 - Power ON +# 0 - Do not Power ON +def por_policy(): + + por = PORConfig() + cnfg = get_por_config() + if cnfg < 1: + log.error("power_util: Error getting the POR config.") + exit(-1) + + if (cnfg == por.on): + # cpu power ON + log.debug('ON: Powering ON') + return 1 + + elif (cnfg == por.off): + # cpu power OFF + log.debug('OFF: Powering OFF') + return 0 + + elif (cnfg == por.lps): + lps = get_por_lps() + if lps < 0: + log.error("power_util: Error getting the POR Last State.") + exit(-1) + + if lps == 1: + # cpu power ON + log.debug('LPS: Powering ON') + return 1 + + elif lps == 0: + # cpu power OFF + log.debug('LPS: Powering OFF') + return 0 + + +if __name__ == "__main__": + main() diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/rc.early b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/rc.early new file mode 100644 index 0000000..0f47c72 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/rc.early @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# +# This script will be executed at rcS S04 level, which is right after mount /mnt/data +# and before almost anything else. + +if [ -x /mnt/data/etc/rc.early ]; then + /mnt/data/etc/rc.early +fi diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/rc.local b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/rc.local new file mode 100644 index 0000000..36fa0f1 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/rc.local @@ -0,0 +1,26 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +# +# This script will be executed *after* all the other init scripts. + +if [ -x /mnt/data/etc/rc.local ]; then + /mnt/data/etc/rc.local +fi diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/reset_usb.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/reset_usb.sh new file mode 100644 index 0000000..a7936b1 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/reset_usb.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +. /usr/local/fbpackages/utils/ast-functions + +#TODO: Add logic to control mux based on front panel switch +echo -n "Set USB Mux to given slot ... " + +# USB_MUX_SEL signals: GPIOE4(36), GPIOE5(37) +slot=$1 + +case $slot in + 1) + gpio_set E4 1 + gpio_set E5 0 + ;; + 2) + gpio_set E4 0 + gpio_set E5 0 + ;; + 3) + gpio_set E4 1 + gpio_set E5 1 + ;; + 4) + gpio_set E4 0 + gpio_set E5 1 + ;; + *) + gpio_set E4 0 + gpio_set E5 0 + ;; +esac + +# Enable the USB MUX GPIOS3(147) +gpio_set S3 0 + +echo "Done" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/setup-gpio.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/setup-gpio.sh new file mode 100755 index 0000000..91797c5 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/setup-gpio.sh @@ -0,0 +1,307 @@ +#!/bin/bash +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: gpio-setup +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Set up GPIO pins as appropriate +### END INIT INFO + +# This file contains definitions for the GPIO pins that were not otherwise +# defined in other files. We should probably move some more of the +# definitions to this file at some point. + +# The commented-out sections are generally already defined elsewhere, +# and defining them twice generates errors. + +# The exception to this is the definition of the GPIO H0, H1, and H2 +# pins, which seem to adversely affect the rebooting of the system. +# When defined, the system doesn't reboot cleanly. We're still +# investigating this. + +. /usr/local/fbpackages/utils/ast-functions + +# Set up to read the board revision pins, Y0, Y1, Y2 +devmem_set_bit $(scu_addr 70) 19 +devmem_clear_bit $(scu_addr a4) 8 +devmem_clear_bit $(scu_addr a4) 9 +devmem_clear_bit $(scu_addr a4) 10 + +gpio_export Y0 +gpio_export Y1 +gpio_export Y2 + +# SLOT1_PRSNT_N, GPIOH5 (61) +# GPIOH5(61): SCU90[6], SCU90[7] shall be 0 +devmem_clear_bit $(scu_addr 90) 6 +devmem_clear_bit $(scu_addr 90) 7 + +gpio_export H5 + +# SLOT2_PRSNT_N, GPIOH4 (60) +# GPIOH4(60): SCU90[6], SCU90[7] shall be 0 +gpio_export H4 + +# SLOT3_PRSNT_N, GPIOH7 (63) +# GPIOH7(63): SCU90[6], SCU90[7] shall be 0 +gpio_export H7 + +# SLOT4_PRSNT_N, GPIOH6 (62) +# GPIOH6(62): SCU90[6], SCU90[7] shall be 0 +gpio_export H6 + +# BMC_PWR_BTN_IN_N, uServer power button in, on GPIO D0(24) +gpio_export D0 + +# PWR_SLOT1_BTN_N, 1S Server power out, on GPIO D3 +# GPIOD3(27): SCU90[1], SCU8C[9], and SCU70[21] shall be 0 +devmem_clear_bit $(scu_addr 90) 1 +devmem_clear_bit $(scu_addr 8c) 9 +devmem_clear_bit $(scu_addr 70) 21 + +gpio_set D3 1 + +# PWR_SLOT2_BTN_N, 1S Server power out, on GPIO D1 +# Make sure the Power Control Pin is Set properly +# GPIOD1(25): SCU90[1], SCU8C[8], and SCU70[21] shall be 0 + +devmem_clear_bit $(scu_addr 8c) 8 + +gpio_set D1 1 + +# PWR_SLOT3_BTN_N, 1S Server power out, on GPIO D7 +# GPIOD7(31): SCU90[1], SCU8C[11], and SCU70[21] shall be 0 +devmem_clear_bit $(scu_addr 8c) 11 + +gpio_set D7 1 + +# PWR_SLOT4_BTN_N, 1S Server power out, on GPIO D5 +# GPIOD5(29): SCU90[1], SCU8C[10], and SCU70[21] shall be 0 +devmem_clear_bit $(scu_addr 8c) 10 + +gpio_set D5 1 + +# SMB_SLOT0_NIC_ALERT_N, alert for 1S Server NIC I2C, GPIO B0 +devmem_clear_bit $(scu_addr 80) 8 + +gpio_export B0 + +# Setup GPIOs to Mux Enable: GPIOS3(147), Channel Select: GPIOE4(36), GPIOE5(37) + +# To use GPIOS3 (147), SCU8C[3], SCU94[0], and SCU94[1] must be 0 +devmem_clear_bit $(scu_addr 8C) 3 +devmem_clear_bit $(scu_addr 94) 0 +devmem_clear_bit $(scu_addr 94) 1 + +# To use GPIOE4 (36), SCU80[20], SCU8C[14], and SCU70[22] must be 0 +devmem_clear_bit $(scu_addr 80) 20 +devmem_clear_bit $(scu_addr 8C) 14 +devmem_clear_bit $(scu_addr 70) 22 + +# To use GPIOE5 (37), SCU80[21], SCU8C[14], and SCU70[22] must be 0 +devmem_clear_bit $(scu_addr 80) 21 +devmem_clear_bit $(scu_addr 8C) 14 +devmem_clear_bit $(scu_addr 70) 22 + +gpio_export S3 +gpio_export E4 +gpio_export E5 + +# BMC_HEARTBEAT_N, heartbeat LED, GPIO Q7 +devmem_clear_bit $(scu_addr 90) 28 + +gpio_export Q7 + +# USB_OC_N, resettable fuse tripped, GPIO Q6 +devmem_clear_bit $(scu_addr 90) 28 + +gpio_export Q6 + +# System SPI +# Strap 12 must be 0 and Strape 13 must be 1 +devmem_clear_bit $(scu_addr 70) 12 +devmem_set_bit $(scu_addr 70) 13 + +# DEBUG_PORT_UART_SEL_BMC_N: GPIOR1(137) +# To use GPIOR1, SCU88[25] must be 0 +devmem_clear_bit $(scu_addr 88) 25 + +gpio_export R1 + +# DEBUG UART Controls +# 4 signals: DEBUG_UART_SEL_0/1/2 and DEBUG_UART_RX_SEL_N +# GPIOE0 (32), GPIOE1 (33), GPIOE2 (34) and GPIOE3 (35) + +# To enable GPIOE0, SCU80[16], SCU8C[12], and SCU70[22] must be 0 +devmem_clear_bit $(scu_addr 80) 16 +devmem_clear_bit $(scu_addr 8C) 12 +devmem_clear_bit $(scu_addr 70) 22 + +gpio_set E0 0 + +# To enable GPIOE1, SCU80[17], SCU8C[12], and SCU70[22] must be 0 +devmem_clear_bit $(scu_addr 80) 17 + +gpio_set E1 0 + +# To enable GPIOE2, SCU80[18], SCU8C[13], and SCU70[22] must be 0 +devmem_clear_bit $(scu_addr 80) 18 +devmem_clear_bit $(scu_addr 8C) 13 + +gpio_set E2 1 + +# To enable GPIOE3, SCU80[19], SCU8C[13], and SCU70[22] must be 0 +devmem_clear_bit $(scu_addr 80) 19 + +gpio_set E3 1 + +# Enable GPIOY3: BoardId(Yosemite or Test system) +devmem_clear_bit $(scu_addr a4) 11 + +# Power LED for Slot#2: +# To use GPIOM0 (96), SCU90[4], SCU90[5], and SCU84[24] must be 0 +devmem_clear_bit $(scu_addr 90) 4 +devmem_clear_bit $(scu_addr 90) 5 +devmem_clear_bit $(scu_addr 84) 24 + +gpio_set M0 1 + +# Power LED for Slot#1: +# To use GPIOM1 (97), SCU90[4], SCU90[5], and SCU84[25] must be 0 +devmem_clear_bit $(scu_addr 84) 25 + +gpio_set M1 1 + +# Power LED for Slot#4: +# To use GPIOM2 (98), SCU90[4], SCU90[5], and SCU84[26] must be 0 +devmem_clear_bit $(scu_addr 84) 26 + +gpio_set M2 1 + +# Power LED for Slot#3: +# To use GPIOM3 (99), SCU90[4], SCU90[5], and SCU84[27] must be 0 +devmem_clear_bit $(scu_addr 84) 27 + +gpio_set M3 1 + +# Front Panel Hand Switch GPIO setup +# HAND_SW_ID1: GPIOR2(138) +# To use GPIOR2, SCU88[26] must be 0 +devmem_clear_bit $(scu_addr 88) 26 + +gpio_export R2 + +# HAND_SW_ID2: GPIOR3(139) +# To use GPIOR3, SCU88[27] must be 0 +devmem_clear_bit $(scu_addr 88) 27 + +gpio_export R3 + +# HAND_SW_ID4: GPIOR4(140) +# To use GPIOR4, SCU88[28] must be 0 +devmem_clear_bit $(scu_addr 88) 28 + +gpio_export R4 + + +# HAND_SW_ID8: GPIOR5(141) +# To use GPIOR5, SCU88[29] must be 0 +devmem_clear_bit $(scu_addr 88) 29 + +gpio_export R5 + +# LED POST CODES: 8 GPIO signals + +# LED_POSTCODE_0: GPIOG0 (48) +# To use GPIOG0, SCU84[0] must be 0 +devmem_clear_bit $(scu_addr 84) 0 + +gpio_set G0 0 + +# LED_POSTCODE_1: GPIOG1 (49) +# To use GPIOG1, SCU84[1] must be 0 +devmem_clear_bit $(scu_addr 84) 1 + +gpio_set G1 0 + +# LED_POSTCODE_2: GPIOG2 (50) +# To use GPIOG2, SCU84[2] must be 0 +devmem_clear_bit $(scu_addr 84) 2 + +gpio_set G2 0 + +# LED_POSTCODE_3: GPIOG3 (51) +# To use GPIOG3, SCU84[3] must be 0 +devmem_clear_bit $(scu_addr 84) 3 + +gpio_set G3 0 + +# LED_POSTCODE_4: GPIOP4 (124) +gpio_set P4 0 + +# LED_POSTCODE_5: GPIOP5 (125) +gpio_set P5 0 + +# LED_POSTCODE_6: GPIOP6 (126) +# To use GPIOP6, SCU88[22] must be 0 +devmem_clear_bit $(scu_addr 88) 22 + +gpio_set P6 0 + +# LED_POSTCODE_7: GPIOP7 (127) +# To use GPIOP7, SCU88[23] must be 0 +devmem_clear_bit $(scu_addr 88) 23 + +gpio_set P7 0 + +# BMC_READY_N: GPIOG6 (54) +# To use GPIOG6, SCU84[6] must be 0 +devmem_clear_bit $(scu_addr 84) 6 + +gpio_set G6 0 + +# BMC_RST_BTN_IN_N: GPIOS0 (144) +# To use GPIOS0, SCU8C[0] +devmem_clear_bit $(scu_addr 8c) 0 + +gpio_export S0 + +# RESET for all Slots +# RST_SLOT1_SYS_RESET_N: GPIOH1 (57) +# To use GPIOH1, SCU90[6], SCU90[7] must be 0 +devmem_clear_bit $(scu_addr 90) 6 +devmem_clear_bit $(scu_addr 90) 7 + +gpio_set H1 1 + +# RST_SLOT2_SYS_RESET_N: GPIOH0 (56) +# To use GPIOH0, SCU90[6], SCU90[7] must be 0 +gpio_set H0 1 + +# RST_SLOT3_SYS_RESET_N: GPIOH3 (59) +# To use GPIOH3, SCU90[6], SCU90[7] must be 0 +gpio_set H3 1 + +# RST_SLOT4_SYS_RESET_N: GPIOH2 (58) +# To use GPIOH2, SCU90[6], SCU90[7] must be 0 +gpio_set H2 1 diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/setup_rov.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/setup_rov.sh new file mode 100755 index 0000000..749fe65 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/setup_rov.sh @@ -0,0 +1,99 @@ +#!/bin/bash +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +# The T2 chip can prefer different input voltages, depending, presumably +# of manufacturing variations. We need to determine whether it wants +# 0.95V or 1.025V, reset the T2 to reduce total power usage, set the +# outgoing voltage on the first buck converter, and bring T2 up out of +# reset. + +. /usr/local/fbpackages/utils/ast-functions + +# read the T2 ROV after the GPIOs are enabled +t2_rov() { + local val0 val1 val2 + # Note that the values are *not* read in order. + val0=$(cat /sys/class/gpio/gpio58/value 2>/dev/null) + val1=$(cat /sys/class/gpio/gpio56/value 2>/dev/null) + val2=$(cat /sys/class/gpio/gpio57/value 2>/dev/null) + echo $((val0 | (val1 << 1) | (val2 << 2))) +} + +rov=$(t2_rov) + +# target_volts come from the data sheet and 18mV of loss and +# some fudging based on actual measurements to get either 1.025V +# or 0.95V at T2 +if [ $rov -eq 1 ]; then + target_volts=0x5a +elif [ $rov -eq 2 ]; then + target_volts=0x65 +else + echo "Unrecognized T2 ROV value $rov, setting failed." + exit 1 +fi +target_volts=$(( $target_volts * 1 )) # normalize to decimal + +# We shouldn't have to rmmod pmbus, because it hasn't been loaded yet, +# but if the script is rerun after the system is up, it may be necessary. +rmmod pmbus +reload=$? + +# Get current voltage value +cur_volts=$(i2cget -y 1 0x60 0x8b w) +cur_volts=$(( $cur_volts * 1 )) # normalize to decimal + +# Only bounce the T2 if we actually need to modify the voltage +if [ $cur_volts -ne $target_volts ]; then + # Set values before turning out output; we're using "PCIE, then MCS" + echo 1 > /sys/class/gpio/gpio42/value + echo 1 > /sys/class/gpio/gpio43/value + echo out > /sys/class/gpio/gpio42/direction + echo out > /sys/class/gpio/gpio43/direction + echo 0 > /sys/class/gpio/gpio16/value + echo out > /sys/class/gpio/gpio16/direction + # T2 is in reset; note that this may cause NMI messages on the uServer, + # which shouldn't be up anyway when this is first run. + + # Set the requested value to the current value to avoid rapid shifts + i2cset -y 1 0x60 0x21 $cur_volts w + # Enable the requested voltage + i2cset -y 1 0x60 0xd2 0x5a + i2cset -y 1 0x60 0xd3 0x5a + sleep 1 + + # Set the target voltage + i2cset -y 1 0x60 0x21 $target_volts w + + sleep 1 + + # Let T2 come out of reset + echo 1 > /sys/class/gpio/gpio16/value + echo "T2 ROV value set based on $rov." + sleep 2 + echo 0 > /sys/class/gpio/gpio42/value + echo 0 > /sys/class/gpio/gpio43/value +else + echo "T2 ROV already correctly set." +fi +# Bring back pmbus if necessary +if [ $reload -eq 0 ]; then + modprobe pmbus +fi diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/setup_switch.py b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/setup_switch.py new file mode 100644 index 0000000..995cec8 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/setup_switch.py @@ -0,0 +1,49 @@ +#!/usr/bin/python +# +# Copyright 2004-present Facebook. All rights reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# +# This script combines multiple switch configuration into one python script. +# All such configuration can be done directly through bcm5396_util.py. +# But, it turns out it took several seconds to just start the python script. +# Involking the script 16 times (2 to create vlan, 13 to set port vlan default, +# and 1 to enable vlan function) contributes 1 minute delay. + +from bcm5396 import Bcm5396 + +MDC_GPIO = 6 +MDIO_GPIO = 7 + +INTERNAL_VLAN = 4088 +DEFAULT_VLAN=4090 + +INTERNAL_PORTS = [3, 10, 1, 11, 0, 8, 2, 9, 4, 12, 14, 13] +FRONT_PORT=5 + +if __name__ == '__main__': + bcm = Bcm5396(Bcm5396.MDIO_ACCESS, mdc=MDC_GPIO, mdio=MDIO_GPIO) + # create default VLAN including internal ports and front panel + # port (un-tagged) + bcm.add_vlan(DEFAULT_VLAN, INTERNAL_PORTS + [FRONT_PORT], + INTERNAL_PORTS + [FRONT_PORT], 0) + # set ingress vlan for internal ports and front panel port to default vlan + for port in INTERNAL_PORTS + [FRONT_PORT]: + bcm.vlan_set_port_default(port, DEFAULT_VLAN, 0) + # create internal vlan including internal ports only (tagged) + bcm.add_vlan(INTERNAL_VLAN, [], INTERNAL_PORTS, 0) + # enable vlan + bcm.vlan_ctrl(True) diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/sol-util b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/sol-util new file mode 100755 index 0000000..3769a5b --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/sol-util @@ -0,0 +1,74 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +BIN_CONSOLED="/usr/local/bin/consoled" +LOGFILE1="/tmp/consoled_$1_log-old" +LOGFILE2="/tmp/consoled_$1_log" + + +if [ "$1" == "slot1" ] || [ "$1" == "slot2" ] || [ "$1" == "slot3" ] || [ "$1" == "slot4" ] +then + SLOT=$1 +else + echo "Usage: sol-util [ slot1 | slot2 | slot3 | slot4 ]" + echo " sol-util [ slot1 | slot2 | slot3 | slot4 ] --force" + echo " sol-util [ slot1 | slot2 | slot3 | slot4 ] --history" + exit -1 +fi + +if [ $# -gt 1 ]; then + if [[ "$2" == "--history" ]]; then + cat $LOGFILE1 2>/dev/null + cat $LOGFILE2 2>/dev/null + exit 0 + fi +fi + +PS=$(ps | grep -e $BIN_CONSOLED | grep -e $SLOT) + +PID=$(ps | grep -e $BIN_CONSOLED | grep -e $SLOT | awk '{print $1}') + + +if [[ $PS =~ "term" ]] && [[ "$2" != "--force" ]]; then + echo "Another SOL session is running." + echo "Please use the \"--force\" option" + exit -1 +fi + +echo "You are in SOL session." +echo "Use ctrl-x to quit." +echo "-----------------------" +echo + +kill -9 -s TERM $PID 2>/dev/null + +if [[ "$2" == "--force" ]]; then + PID=$(ps | grep -e $BIN_CONSOLED | grep -e $SLOT | awk '{print $1}') + kill -9 -s TERM $PID 2>/dev/null +fi + +$BIN_CONSOLED $SLOT --term + +$BIN_CONSOLED $SLOT --buffer + +echo +echo +echo "-----------------------" +echo "Exit from SOL session." diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/src/include/i2c-dev.h b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/src/include/i2c-dev.h new file mode 100644 index 0000000..3b67afc --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/src/include/i2c-dev.h @@ -0,0 +1,364 @@ +/* + i2c-dev.h - i2c-bus driver, char device interface + + Copyright (C) 1995-97 Simon G. Vogl + Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl> + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef _LINUX_I2C_DEV_H +#define _LINUX_I2C_DEV_H + +#include <linux/types.h> +#include <sys/ioctl.h> +#include <stddef.h> +#include <string.h> + + +/* -- i2c.h -- */ + +#define _I2C_MIN(a, b) (((a) <= (b)) ? (a) : (b)) + +/* + * I2C Message - used for pure i2c transaction, also from /dev interface + */ +struct i2c_msg { + __u16 addr; /* slave address */ + unsigned short flags; +#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */ +#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ +#define I2C_M_RD 0x0001 /* read data, from slave to master */ +#define I2C_S_EN 0x0002 /* read data, from slave to master */ +#define I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ + short len; /* msg length */ + char *buf; /* pointer to msg data */ +}; + +/* To determine what functionality is present */ + +#define I2C_FUNC_I2C 0x00000001 +#define I2C_FUNC_10BIT_ADDR 0x00000002 +#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART,..} */ +#define I2C_FUNC_SMBUS_PEC 0x00000008 +#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */ +#define I2C_FUNC_SMBUS_QUICK 0x00010000 +#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 +#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 +#define I2C_FUNC_SMBUS_READ_BYTE_DATA 0x00080000 +#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA 0x00100000 +#define I2C_FUNC_SMBUS_READ_WORD_DATA 0x00200000 +#define I2C_FUNC_SMBUS_WRITE_WORD_DATA 0x00400000 +#define I2C_FUNC_SMBUS_PROC_CALL 0x00800000 +#define I2C_FUNC_SMBUS_READ_BLOCK_DATA 0x01000000 +#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA 0x02000000 +#define I2C_FUNC_SMBUS_READ_I2C_BLOCK 0x04000000 /* I2C-like block xfer */ +#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ + +#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \ + I2C_FUNC_SMBUS_WRITE_BYTE) +#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \ + I2C_FUNC_SMBUS_WRITE_BYTE_DATA) +#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \ + I2C_FUNC_SMBUS_WRITE_WORD_DATA) +#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) +#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ + I2C_FUNC_SMBUS_WRITE_I2C_BLOCK) + +/* Old name, for compatibility */ +#define I2C_FUNC_SMBUS_HWPEC_CALC I2C_FUNC_SMBUS_PEC + +/* + * Data for SMBus Messages + */ +#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ +#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */ +union i2c_smbus_data { + __u8 byte; + __u16 word; + __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ + /* and one more for PEC */ +}; + +#define I2C_SMBUS_BLOCK_LARGE_MAX 240 +union i2c_smbus_large_data { + union i2c_smbus_data data; + __u8 block[I2C_SMBUS_BLOCK_LARGE_MAX + 2]; /* block[0] is used for length */ + /* and one more for PEC */ +}; + +/* smbus_access read or write markers */ +#define I2C_SMBUS_READ 1 +#define I2C_SMBUS_WRITE 0 + +/* SMBus transaction types (size parameter in the above functions) + Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */ +#define I2C_SMBUS_QUICK 0 +#define I2C_SMBUS_BYTE 1 +#define I2C_SMBUS_BYTE_DATA 2 +#define I2C_SMBUS_WORD_DATA 3 +#define I2C_SMBUS_PROC_CALL 4 +#define I2C_SMBUS_BLOCK_DATA 5 +#define I2C_SMBUS_I2C_BLOCK_BROKEN 6 +#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */ +#define I2C_SMBUS_I2C_BLOCK_DATA 8 +#define I2C_SMBUS_BLOCK_LARGE_DATA 9 + + +/* /dev/i2c-X ioctl commands. The ioctl's parameter is always an + * unsigned long, except for: + * - I2C_FUNCS, takes pointer to an unsigned long + * - I2C_RDWR, takes pointer to struct i2c_rdwr_ioctl_data + * - I2C_SMBUS, takes pointer to struct i2c_smbus_ioctl_data + */ +#define I2C_RETRIES 0x0701 /* number of times a device address should + be polled when not acknowledging */ +#define I2C_TIMEOUT 0x0702 /* set timeout in units of 10 ms */ + +/* NOTE: Slave address is 7 or 10 bits, but 10-bit addresses + * are NOT supported! (due to code brokenness) + */ +#define I2C_SLAVE 0x0703 /* Use this slave address */ +#define I2C_SLAVE_FORCE 0x0706 /* Use this slave address, even if it + is already in use by a driver! */ +#define I2C_TENBIT 0x0704 /* 0 for 7 bit addrs, != 0 for 10 bit */ + +#define I2C_FUNCS 0x0705 /* Get the adapter functionality mask */ + +#define I2C_RDWR 0x0707 /* Combined R/W transfer (one STOP only) */ +#define I2C_SLAVE_RDWR 0x0709 /* Slave Read/Write */ + +#define I2C_PEC 0x0708 /* != 0 to use PEC with SMBus */ +#define I2C_SMBUS 0x0720 /* SMBus transfer */ + + +/* This is the structure as used in the I2C_SMBUS ioctl call */ +struct i2c_smbus_ioctl_data { + __u8 read_write; + __u8 command; + __u32 size; + union i2c_smbus_data *data; +}; + +/* This is the structure as used in the I2C_RDWR ioctl call */ +struct i2c_rdwr_ioctl_data { + struct i2c_msg *msgs; /* pointers to i2c_msgs */ + __u32 nmsgs; /* number of i2c_msgs */ +}; + +#define I2C_RDRW_IOCTL_MAX_MSGS 42 + + +static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command, + int size, union i2c_smbus_data *data) +{ + struct i2c_smbus_ioctl_data args; + + args.read_write = read_write; + args.command = command; + args.size = size; + args.data = data; + return ioctl(file,I2C_SMBUS,&args); +} + + +static inline __s32 i2c_smbus_write_quick(int file, __u8 value) +{ + return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL); +} + +static inline __s32 i2c_smbus_read_byte(int file) +{ + union i2c_smbus_data data; + if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data)) + return -1; + else + return 0x0FF & data.byte; +} + +static inline __s32 i2c_smbus_write_byte(int file, __u8 value) +{ + return i2c_smbus_access(file,I2C_SMBUS_WRITE,value, + I2C_SMBUS_BYTE,NULL); +} + +static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command) +{ + union i2c_smbus_data data; + if (i2c_smbus_access(file,I2C_SMBUS_READ,command, + I2C_SMBUS_BYTE_DATA,&data)) + return -1; + else + return 0x0FF & data.byte; +} + +static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command, + __u8 value) +{ + union i2c_smbus_data data; + data.byte = value; + return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_BYTE_DATA, &data); +} + +static inline __s32 i2c_smbus_read_word_data(int file, __u8 command) +{ + union i2c_smbus_data data; + if (i2c_smbus_access(file,I2C_SMBUS_READ,command, + I2C_SMBUS_WORD_DATA,&data)) + return -1; + else + return 0x0FFFF & data.word; +} + +static inline __s32 i2c_smbus_write_word_data(int file, __u8 command, + __u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_WORD_DATA, &data); +} + +static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value) +{ + union i2c_smbus_data data; + data.word = value; + if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_PROC_CALL,&data)) + return -1; + else + return 0x0FFFF & data.word; +} + + +/* Returns the number of read bytes */ +static inline __s32 i2c_smbus_read_block_data(int file, __u8 command, + __u8 *values) +{ + union i2c_smbus_data data; + if (i2c_smbus_access(file,I2C_SMBUS_READ,command, + I2C_SMBUS_BLOCK_DATA,&data)) + return -1; + else { + memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_MAX)); + return data.block[0]; + } +} + +static inline __s32 i2c_smbus_write_block_data(int file, __u8 command, + __u8 length, const __u8 *values) +{ + union i2c_smbus_data data; + if (length > 32) + length = 32; + memcpy(&data.block[1], values, length); + data.block[0] = length; + return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_BLOCK_DATA, &data); +} + +static inline __s32 i2c_smbus_read_block_large_data(int file, __u8 command, + __u8 *values) +{ + union i2c_smbus_large_data data; + if (i2c_smbus_access(file, I2C_SMBUS_READ, command, + I2C_SMBUS_BLOCK_LARGE_DATA, + (union i2c_smbus_data *)&data)) { + return -1; + } else { + /* the first byte is the length which is not copied */ + memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_LARGE_MAX)); + return data.block[0]; + } +} + +static inline __s32 i2c_smbus_write_block_large_data(int file, __u8 command, + __u8 length, + const __u8 *values) +{ + union i2c_smbus_large_data data; + if (length > I2C_SMBUS_BLOCK_LARGE_MAX) { + length = I2C_SMBUS_BLOCK_LARGE_MAX; + } + data.block[0] = length; + memcpy(&data.block[1], values, length); + return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BLOCK_LARGE_DATA, + (union i2c_smbus_data *)&data); +} + +/* Returns the number of read bytes */ +/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you + ask for less than 32 bytes, your code will only work with kernels + 2.6.23 and later. */ +static inline __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, + __u8 length, __u8 *values) +{ + union i2c_smbus_data data; + + if (length > 32) + length = 32; + data.block[0] = length; + if (i2c_smbus_access(file,I2C_SMBUS_READ,command, + length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN : + I2C_SMBUS_I2C_BLOCK_DATA,&data)) + return -1; + else { + memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_MAX)); + return data.block[0]; + } +} + +static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, + __u8 length, + const __u8 *values) +{ + union i2c_smbus_data data; + if (length > 32) + length = 32; + memcpy(&data.block[1], values, length); + data.block[0] = length; + return i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_I2C_BLOCK_BROKEN, &data); +} + +/* Returns the number of read bytes */ +static inline __s32 i2c_smbus_block_process_call(int file, __u8 command, + __u8 length, __u8 *values) +{ + union i2c_smbus_data data; + if (length > 32) + length = 32; + memcpy(&data.block[1], values, length); + data.block[0] = length; + if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command, + I2C_SMBUS_BLOCK_PROC_CALL,&data)) + return -1; + else { + memcpy(values, &data.block[1], _I2C_MIN(data.block[0], I2C_SMBUS_BLOCK_MAX)); + return data.block[0]; + } +} + +#undef _I2C_MIN + +#endif /* _LINUX_I2C_DEV_H */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/src/include/log.h b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/src/include/log.h new file mode 100644 index 0000000..a69d69e --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/src/include/log.h @@ -0,0 +1,59 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef LOG_H +#define LOG_H + +#include <stdio.h> +#include <string.h> + +//#define DEBUG +//#define VERBOSE + +#define _LOG(dst, fmt, ...) do { \ + fprintf(dst, "%s:%d " fmt "\n", \ + __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + fflush(dst); \ +} while(0) + +#define LOG_ERR(err, fmt, ...) do { \ + char buf[128]; \ + strerror_r(err, buf, sizeof(buf)); \ + _LOG(stderr, "ERROR " fmt ": %s", ##__VA_ARGS__, buf); \ +} while(0) + +#define LOG_INFO(fmt, ...) do { \ + _LOG(stdout, fmt, ##__VA_ARGS__); \ +} while(0) + +#ifdef DEBUG +#define LOG_DBG(fmt, ...) do { \ + _LOG(stdout, fmt, ##__VA_ARGS__); \ +} while(0) +#else +#define LOG_DBG(fmt, ...) +#endif + +#ifdef VERBOSE +#define LOG_VER(fmt, ...) do { \ + _LOG(stdout, fmt, ##__VA_ARGS__); \ +} while(0) +#else +#define LOG_VER(fmt, ...) +#endif + +#endif diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/us_console.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/us_console.sh new file mode 100755 index 0000000..1672acd --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/us_console.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +usage() { + echo "$0 <connect | disconnect>" +} + +. /usr/local/fbpackages/utils/ast-functions + +if [ $# -ne 1 ]; then + usage + exit 1 +fi + +if [ "$1" == "connect" ]; then + VALUE=1 +elif [ "$1" == "disconnect" ]; then + VALUE=0 +else + usage + exit 1 +fi + +gpio_set 32 $VALUE diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/watch-fc.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/watch-fc.sh new file mode 100755 index 0000000..d04b7cd --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/watch-fc.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +. /usr/local/fbpackages/utils/ast-functions + +MAC1LINK=0 # GPIOA0 +FAB0_PRES=20 # GPIOC4 +FAB1_PRES=21 # GPIOC5 +while true; do + # fabN_pres: active low. + if [ $(gpio_get $FAB0_PRES) = 0 ]; then + gpio_set $MAC1LINK 0 + elif [ $(gpio_get $FAB1_PRES) = 0 ]; then + gpio_set $MAC1LINK 1 + fi + sleep 1 +done diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/wedge_us_mac.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/wedge_us_mac.sh new file mode 100644 index 0000000..34b8e59 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/wedge_us_mac.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + +mac=$(i2cdump -y 0x0 0x49 s 0xd4 | grep '^00: d4'| awk '{ print $3":"$4":"$5":"$6":"$7":"$8 }') 2>/dev/null + +if [ -n "$mac" ]; then + echo $mac +else + echo "Cannot find out the microserver MAC" 1>&2 +fi diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/yosemite-sensors/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/yosemite-sensors/Makefile new file mode 100644 index 0000000..2bc9721 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/yosemite-sensors/Makefile @@ -0,0 +1,10 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +all: yosemite-sensors + +yosemite-sensors: yosemite-sensors.c + $(CC) -lyosemite_sensor -std=c99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o yosemite-sensors diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/yosemite-sensors/yosemite-sensors.c b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/yosemite-sensors/yosemite-sensors.c new file mode 100644 index 0000000..aa921db --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/yosemite-sensors/yosemite-sensors.c @@ -0,0 +1,405 @@ +/* + * yosemite-sensors + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <stdint.h> +#include <pthread.h> +#include <facebook/bic.h> +#include <openbmc/ipmi.h> +#include <facebook/yosemite_sensor.h> + +int +main(int argc, char **argv) { + int value; + float fvalue; + uint8_t slot_id; + + slot_id = atoi(argv[1]); + + if (yosemite_sensor_read(slot_id, SP_SENSOR_INLET_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_INLET_TEMP\n"); + } else { + printf("SP_SENSOR_INLET_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_OUTLET_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_OUTLET_TEMP\n"); + } else { + printf("SP_SENSOR_OUTLET_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_FAN0_TACH, &value)) { + printf("yosemite_sensor_read failed: SP_SENSOR_FAN0_TACH\n"); + } else { + printf("SP_SENSOR_FAN0_TACH: %d rpm\n", value); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_FAN1_TACH, &value)) { + printf("yosemite_sensor_read failed: SP_SENSOR_FAN1_TACH\n"); + } else { + printf("SP_SENSOR_FAN1_TACH: %d rpm\n", value); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_P5V, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_P5V\n"); + } else { + printf("SP_SENSOR_P5V: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_P12V, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_P12V\n"); + } else { + printf("SP_SENSOR_P12V: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_P3V3_STBY, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_P3V3_STBY\n"); + } else { + printf("SP_SENSOR_P3V3_STBY: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_P12V_SLOT0, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_P12V_SLOT0\n"); + } else { + printf("SP_SENSOR_P12V_SLOT0: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_P12V_SLOT1, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_P12V_SLOT1\n"); + } else { + printf("SP_SENSOR_P12V_SLOT1: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_P12V_SLOT2, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_P12V_SLOT2\n"); + } else { + printf("SP_SENSOR_P12V_SLOT2: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_P12V_SLOT3, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_P12V_SLOT3\n"); + } else { + printf("SP_SENSOR_P12V_SLOT3: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_P3V3, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_P3V3\n"); + } else { + printf("SP_SENSOR_P3V3: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_HSC_IN_VOLT, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_HSC_IN_VOLT\n"); + } else { + printf("SP_SENSOR_HSC_IN_VOLT: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_HSC_OUT_CURR, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_HSC_OUT_CURR\n"); + } else { + printf("SP_SENSOR_HSC_OUT_CURR: %.2f Amps\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_HSC_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_HSC_TEMP\n"); + } else { + printf("SP_SENSOR_P3V3: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, SP_SENSOR_HSC_IN_POWER, &fvalue)) { + printf("yosemite_sensor_read failed: SP_SENSOR_HSC_IN_POWER\n"); + } else { + printf("SP_SENSOR_HSC_IN_POWER: %.2f Watts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_MB_OUTLET_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_MB_OUTLET_TEMP\n"); + } else { + printf("BIC_SENSOR_MB_OUTLET_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCCIN_VR_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCCIN_VR_TEMP\n"); + } else { + printf("BIC_SENSOR_VCCIN_VR_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCC_GBE_VR_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCC_GBE_VR_TEMP\n"); + } else { + printf("BIC_SENSOR_VCC_GBE_VR_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_1V05PCH_VR_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_1V05PCH_VR_TEMP\n"); + } else { + printf("BIC_SENSOR_1V05PCH_VR_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SOC_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SOC_TEMP\n"); + } else { + printf("BIC_SENSOR_SOC_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_MB_INLET_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_MB_INLET_TEMP\n"); + } else { + printf("BIC_SENSOR_MB_INLET_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_PCH_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_PCH_TEMP\n"); + } else { + printf("BIC_SENSOR_PCH_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SOC_THERM_MARGIN, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SOC_THERM_MARGIN\n"); + } else { + printf("BIC_SENSOR_SOC_THERM_MARGIN: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VDDR_VR_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VDDR_VR_TEMP\n"); + } else { + printf("BIC_SENSOR_VDDR_VR_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SOC_TJMAX, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SOC_TJMAX\n"); + } else { + printf("BIC_SENSOR_SOC_TJMAX: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCC_SCSUS_VR_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCC_SCSUS_VR_TEMP\n"); + } else { + printf("BIC_SENSOR_VCC_SCSUS_VR_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SOC_DIMMA0_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SOC_DIMMA0_TEMP\n"); + } else { + printf("BIC_SENSOR_SOC_DIMMA0_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SOC_DIMMA1_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SOC_DIMMA1_TEMP\n"); + } else { + printf("BIC_SENSOR_SOC_DIMMA1_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SOC_DIMMB0_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SOC_DIMMB0_TEMP\n"); + } else { + printf("BIC_SENSOR_SOC_DIMMB0_TEMP: %.2f C\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SOC_DIMMB1_TEMP, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SOC_DIMMB1_TEMP\n"); + } else { + printf("BIC_SENSOR_SOC_DIMMB1_TEMP: %.2f C\n", fvalue); + } + + // Monolake Current Sensors + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCC_GBE_VR_CURR, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCC_GBE_VR_CURR\n"); + } else { + printf("BIC_SENSOR_VCC_GBE_VR_CURR: %.2f Amps\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_1V05_PCH_VR_CURR, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_1V05_PCH_VR_CURR\n"); + } else { + printf("BIC_SENSOR_1V05_PCH_VR_CURR: %.2f Amps\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCCIN_VR_CURR, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCCIN_VR_CURR\n"); + } else { + printf("BIC_SENSOR_VCCIN_VR_CURR: %.2f Amps\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VDDR_VR_CURR, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VDDR_VR_CURR\n"); + } else { + printf("BIC_SENSOR_VDDR_VR_CURR: %.2f Amps\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCC_SCSUS_VR_CURR, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCC_SCSUS_VR_CURR\n"); + } else { + printf("BIC_SENSOR_VCC_SCSUS_VR_CURR: %.2f Amps\n", fvalue); + } + + // Monolake Voltage Sensors + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCCIN_VR_VOL, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCCIN_VR_VOL\n"); + } else { + printf("BIC_SENSOR_VCCIN_VR_VOL: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VDDR_VR_VOL, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VDDR_VR_VOL\n"); + } else { + printf("BIC_SENSOR_VDDR_VR_VOL: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCC_SCSUS_VR_VOL, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCC_SCSUS_VR_VOL\n"); + } else { + printf("BIC_SENSOR_VCC_SCSUS_VR_VOL: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCC_GBE_VR_VOL, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCC_GBE_VR_VOL\n"); + } else { + printf("BIC_SENSOR_VCC_GBE_VR_VOL: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_1V05_PCH_VR_VOL, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_1V05_PCH_VR_VOL\n"); + } else { + printf("BIC_SENSOR_1V05_PCH_VR_VOL: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_P3V3_MB, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_P3V3_MB\n"); + } else { + printf("BIC_SENSOR_P3V3_MB: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_P12V_MB, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_P12V_MB\n"); + } else { + printf("BIC_SENSOR_P12V_MB: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_P1V05_PCH, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_P1V05_PCH\n"); + } else { + printf("BIC_SENSOR_P1V05_PCH: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_P3V3_STBY_MB, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_P3V3_STBY_MB\n"); + } else { + printf("BIC_SENSOR_P3V3_STBY_MB: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_P5V_STBY_MB, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_P5V_STBY_MB\n"); + } else { + printf("BIC_SENSOR_P5V_STBY_MB: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_PV_BAT, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_PV_BAT\n"); + } else { + printf("BIC_SENSOR_PV_BAT: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_PVDDR, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_PVDDR\n"); + } else { + printf("BIC_SENSOR_PVDDR: %.2f Volts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_PVCC_GBE, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_PVCC_GBE\n"); + } else { + printf("BIC_SENSOR_PVCC_GBE: %.2f Volts\n", fvalue); + } + + // Monolake Power Sensors + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCCIN_VR_POUT, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCCIN_VR_POUT\n"); + } else { + printf("BIC_SENSOR_VCCIN_VR_POUT: %.2f Watts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_INA230_POWER, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_INA230_POWER\n"); + } else { + printf("BIC_SENSOR_INA230_POWER: %.2f Watts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SOC_PACKAGE_PWR, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SOC_PACKAGE_PWR\n"); + } else { + printf("BIC_SENSOR_SOC_PACKAGE_PWR: %.2f Watts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VDDR_VR_POUT, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VDDR_VR_POUT\n"); + } else { + printf("BIC_SENSOR_VDDR_VR_POUT: %.2f Watts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCC_SCSUS_VR_POUT, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCC_SCSUS_VR_POUT\n"); + } else { + printf("BIC_SENSOR_VCC_SCSUS_VR_POUT: %.2f Watts\n", fvalue); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VCC_GBE_VR_POUT, &fvalue)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VCC_GBE_VR_POUT\n"); + } else { + printf("BIC_SENSOR_VCC_GBE_VR_POUT: %.2f Watts\n", fvalue); + } + + // Discrete Sensors + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SYSTEM_STATUS, &value)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SYSTEM_STATUS\n"); + } else { + printf("BIC_SENSOR_SYSTEM_STATUS: 0x%X\n", value); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_PROC_FAIL, &value)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_PROC_FAIL\n"); + } else { + printf("BIC_SENSOR_PROC_FAIL: 0x%X\n", value); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_SYS_BOOT_STAT, &value)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_SYS_BOOT_STAT\n"); + } else { + printf("BIC_SENSOR_SYS_BOOT_STAT: 0x%X\n", value); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_VR_HOT, &value)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_VR_HOT\n"); + } else { + printf("BIC_SENSOR_VR_HOT: 0x%X\n", value); + } + + if (yosemite_sensor_read(slot_id, BIC_SENSOR_CPU_DIMM_HOT, &value)) { + printf("yosemite_sensor_read failed: BIC_SENSOR_CPU_DIMM_HOT\n"); + } else { + printf("BIC_SENSOR_CPU_DIMM_HOT: 0x%X\n", value); + } + + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/yosemite_power.sh b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/yosemite_power.sh new file mode 100644 index 0000000..3a2aaf7 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/files/yosemite_power.sh @@ -0,0 +1,169 @@ +#!/bin/bash +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +. /usr/local/fbpackages/utils/ast-functions + +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin + +LPS_PATH=/mnt/data/power/por/last_state + +prog="$0" + +usage() { + echo "Usage: $prog <slot#> <command> [command options]" + echo + echo "Commands:" + echo " status: Get the current 1S server power status" + echo + echo " on: Power on 1S server if not powered on already" + echo " options:" + echo " -f: Re-do power on sequence no matter if 1S server has " + echo " been powered on or not." + echo + echo " off: Power off 1S server ungracefully" + echo + echo +} + +do_status() { + if [ $(is_server_prsnt $slot) == "0" ]; then + echo "The given slot is Empty" + return 0 + fi + + echo -n "1S Server power for slot#$slot is " + if [ $(yosemite_is_server_on $slot) -eq 1 ] ; then + echo "on" + else + echo "off" + fi + return 0 +} + +do_on() { + + if [ $(is_server_prsnt $slot) == "0" ]; then + echo "The given slot is Empty" + return 0 + fi + + local force opt + force=0 + while getopts "f" opt; do + case $opt in + f) + force=1 + ;; + *) + usage + exit -1 + ;; + + esac + done + echo -n "Power on slot#$slot server ..." + if [ $force -eq 0 ]; then + # need to check if 1S Server is on or not + if [ $(yosemite_is_server_on $slot) -eq 1 ]; then + echo " Already on. Skip!" + return 1 + fi + fi + + # TODO: State the power state change + echo "on $(date +%s)" > $LPS_PATH + + # first make sure, GPIO is high + gpio_set $gpio 1 + # generate the power on pulse + gpio_set $gpio 0 + sleep 1 + gpio_set $gpio 1 + sleep 1 + # Turn on the power LED + /usr/local/bin/power_led.sh $slot on + echo " Done" + return 0 +} + +do_off() { + if [ $(is_server_prsnt $slot) == "0" ]; then + echo "The given slot is Empty" + return 0 + fi + echo -n "Power off slot#$slot server ..." + + #TODO: State the power state change + echo "off $(date +%s)" > $LPS_PATH + + # first make sure, GPIO is high + gpio_set $gpio 1 + sleep 1 + gpio_set $gpio 0 + sleep 5 + gpio_set $gpio 1 + # Turn off the power LED + /usr/local/bin/power_led.sh $slot off + echo " Done" + return 0 +} + +# Slot1: GPIOD3(27), Slot2: GPIOD1(25), Slot3: GPIOD7(31), Slot4: GPIOD5(29) +slot=$1 + +case $slot in + 1) + gpio=D3 + ;; + 2) + gpio=D1 + ;; + 3) + gpio=D7 + ;; + 4) + gpio=D5 + ;; + *) + gpio=D3 + ;; +esac + +command="$2" +shift +shift + +case "$command" in + status) + do_status $@ + ;; + on) + do_on $@ + ;; + off) + do_off $@ + ;; + *) + usage + exit -1 + ;; +esac + +exit $? diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/yosemite-sensors_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/yosemite-sensors_0.1.bb new file mode 100644 index 0000000..245f05d --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fbutils/yosemite-sensors_0.1.bb @@ -0,0 +1,21 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +SUMMARY = "Yosemite Sensor Utility" +DESCRIPTION = "Util for reading various sensors on Yosemite" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://yosemite-sensors.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238" + +SRC_URI = "file://yosemite-sensors \ + " + +S = "${WORKDIR}/yosemite-sensors" + +do_install() { + install -d ${D}${bindir} + install -m 0755 yosemite-sensors ${D}${bindir}/yosemite-sensors +} + +DEPENDS += "libyosemite-sensor" + +FILES_${PN} = "${bindir}" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/files/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/files/Makefile new file mode 100644 index 0000000..c542230 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/files/Makefile @@ -0,0 +1,10 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +all: front-paneld + +front-paneld: front-paneld.c + $(CC) -pthread -lpal -lbic -std=c99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o front-paneld diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/files/front-paneld.c b/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/files/front-paneld.c new file mode 100644 index 0000000..03849cd --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/files/front-paneld.c @@ -0,0 +1,460 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +#include <pthread.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <time.h> +#include <openbmc/ipmi.h> +#include <openbmc/ipmb.h> +#include <openbmc/pal.h> + +#define BTN_MAX_SAMPLES 200 +#define MAX_NUM_SLOTS 4 + +// Helper function for msleep +void +msleep(int msec) { + struct timespec req; + + req.tv_sec = 0; + req.tv_nsec = msec * 1000 * 1000; + + while(nanosleep(&req, &req) == -1 && errno == EINTR) { + continue; + } +} + +// Thread for monitoring debug card hotswap +static void * +debug_card_handler() { + int curr = -1; + int prev = -1; + uint8_t prsnt; + uint8_t pos; + uint8_t lpc; + int i, ret; + + while (1) { + // Check if debug card present or not + ret = pal_is_debug_card_prsnt(&prsnt); + if (ret) { + goto debug_card_out; + } + + curr = prsnt; + if (curr == prev) { + // No state change, continue + goto debug_card_out; + } + + if (curr) { + syslog(LOG_ALERT, "Debug Card Insertion\n"); + // Get current position of hand switch + ret = pal_get_hand_sw(&pos); + if (ret) { + goto debug_card_out; + } + + // Switch USB mux based on hand switch + ret = pal_switch_usb_mux(pos); + if (ret) { + goto debug_card_out; + } + // Switch UART mux based on hand switch + ret = pal_switch_uart_mux(pos); + if (ret) { + goto debug_card_out; + } + + // Enable POST code based on hand switch + if (pos == HAND_SW_BMC) { + // For BMC, there is no need to have POST specific code + goto debug_card_done; + } + + // Make sure the server at selected position is present + ret = pal_is_server_prsnt(pos, &prsnt); + if (ret || !prsnt) { + goto debug_card_done; + } + + // Enable POST codes for all slots + ret = pal_post_enable(pos); + if (ret) { + goto debug_card_out; + } + + // Get last post code and display it + ret = pal_post_get_last(pos, &lpc); + if (ret) { + goto debug_card_out; + } + + ret = pal_post_handle(pos, lpc); + if (ret) { + goto debug_card_out; + } + } else { + syslog(LOG_ALERT, "Debug Card Extraction\n"); + // Switch UART mux to BMC + ret = pal_switch_uart_mux(HAND_SW_BMC); + if (ret) { + goto debug_card_out; + } + } +debug_card_done: + prev = curr; +debug_card_out: + sleep(1); + } +} + +// Thread to monitor the hand switch +static void * +hand_sw_handler() { + int curr = -1; + int prev = -1; + int ret; + uint8_t pos; + uint8_t prsnt; + uint8_t lpc; + + while (1) { + // Get the current hand switch position + ret = pal_get_hand_sw(&pos); + if (ret) { + goto hand_sw_out; + } + curr = pos; + if (curr == prev) { + // No state change, continue; + goto hand_sw_out; + } + + // Switch USB Mux to selected server + ret = pal_switch_usb_mux(pos); + if (ret) { + goto hand_sw_out; + } + + // If Debug Card is present, update UART MUX + ret = pal_is_debug_card_prsnt(&prsnt); + if (ret) { + goto hand_sw_out; + } + + if (prsnt) { + // Switch UART mux based on position + ret = pal_switch_uart_mux(pos); + if (ret) { + goto hand_sw_out; + } + + if (pos == HAND_SW_BMC) { + // For BMC, there is no need for POST enable/disable code + goto hand_sw_done; + } + + ret = pal_is_server_prsnt(pos, &prsnt); + if (ret || !prsnt) { + // Server at chosen position is not present + goto hand_sw_done; + } + + // Enable post for the chosen server + ret = pal_post_enable(pos); + if (ret) { + goto hand_sw_out; + } + + // Get last post code and display it + ret = pal_post_get_last(pos, &lpc); + if (ret) { + goto hand_sw_out; + } + + ret = pal_post_handle(pos, lpc); + if (ret) { + goto hand_sw_out; + } + } +hand_sw_done: + prev = curr; +hand_sw_out: + sleep(1); + continue; + } +} + +// Thread to monitor Reset Button and propagate to selected server +static void * +rst_btn_handler() { + int ret; + uint8_t pos; + int i; + uint8_t btn; + + while (1) { + // Check the position of hand switch + ret = pal_get_hand_sw(&pos); + if (ret || pos == HAND_SW_BMC) { + // For BMC, no need to handle Reset Button + sleep (1); + continue; + } + + // Check if reset button is pressed + ret = pal_get_rst_btn(&btn); + if (ret || !btn) { + goto rst_btn_out; + } + + // Pass the reset button to the selected slot + syslog(LOG_ALERT, "reset button pressed\n"); + ret = pal_set_rst_btn(pos, 0); + if (ret) { + goto rst_btn_out; + } + + // Wait for the button to be released + for (i = 0; i < BTN_MAX_SAMPLES; i++) { + ret = pal_get_rst_btn(&btn); + if (ret || btn) { + msleep(100); + continue; + } + syslog(LOG_ALERT, "Reset button released\n"); + ret = pal_set_rst_btn(pos, 1); + goto rst_btn_out; + } + + // handle error case + if (i == BTN_MAX_SAMPLES) { + syslog(LOG_ALERT, "Reset button seems to stuck for long time\n"); + goto rst_btn_out; + } +rst_btn_out: + msleep(100); + } +} + +// Thread to handle Power Button and power on/off the selected server +static void * +pwr_btn_handler() { + int ret; + uint8_t pos, btn; + int i; + uint8_t power; + + while (1) { + // Check the position of hand switch + ret = pal_get_hand_sw(&pos); + if (ret || pos == HAND_SW_BMC) { + sleep(1); + continue; + } + + // Check if power button is pressed + ret = pal_get_pwr_btn(&btn); + if (ret || !btn) { + goto pwr_btn_out; + } + + syslog(LOG_ALERT, "power button pressed\n"); + + // Wait for the button to be released + for (i = 0; i < BTN_MAX_SAMPLES; i++) { + ret = pal_get_pwr_btn(&btn); + if (ret || btn ) { + msleep(100); + continue; + } + syslog(LOG_ALERT, "power button released\n"); + break; + } + + // handle error case + if (i == BTN_MAX_SAMPLES) { + syslog(LOG_ALERT, "Power button seems to stuck for long time\n"); + goto pwr_btn_out; + } + + // Get the current power state (power on vs. power off) + ret = pal_get_server_power(pos, &power); + if (ret) { + goto pwr_btn_out; + } + + // Reverse the power state of the given server + ret = pal_set_server_power(pos, !power); +pwr_btn_out: + msleep(100); + } +} + +// Thread to handle LED state of the server at given slot +static void * +led_handler(void *num) { + int ret; + uint8_t prsnt; + uint8_t power; + uint8_t pos; + uint8_t ident; + uint8_t led_blink; + int led_on_time, led_off_time; + + uint8_t slot = (*(int*) num) + 1; + + syslog(LOG_INFO, "led_handler for slot %d\n", slot); + + ret = pal_is_server_prsnt(slot, &prsnt); + if (ret || !prsnt) { + // Turn off led and exit + ret = pal_set_led(slot, 0); + goto led_handler_exit; + } + + while (1) { + // Get power status for this slot + ret = pal_get_server_power(slot, &power); + if (ret) { + sleep(1); + continue; + } + + // Get hand switch position to see if this is selected server + ret = pal_get_hand_sw(&pos); + if (ret) { + sleep(1); + continue; + } + + if (pos == slot) { + // This server is selcted one, set ident flag + ident = 1; + } else { + ident = 0; + } + + // Update LED based on current state + if (ident) { + // If this is selected server the blink flag is one + led_blink = 1; + // update the blink rate based on power state + if (power) { + led_on_time = 900; + led_off_time = 100; + } else { + led_on_time = 100; + led_off_time = 900; + } + } else { + // This server is not selected one + led_blink = 0; + } + + if (!led_blink) { + // Set the led state based on power state + ret = pal_set_led(slot, power); + goto led_handler_out; + } + + // Since this is selected slot, start blinking the LED + ret = pal_set_led(slot, 1); + if (ret) { + goto led_handler_out; + } + + msleep(led_on_time); + + ret = pal_set_led(slot, 0); + if (ret) { + goto led_handler_out; + } + + msleep(led_off_time); +led_handler_out: + msleep(100); + } + +led_handler_exit: + free(num); +} + +int +main (int argc, char * const argv[]) { + pthread_t tid_hand_sw; + pthread_t tid_debug_card; + pthread_t tid_rst_btn; + pthread_t tid_pwr_btn; + pthread_t tid_leds[MAX_NUM_SLOTS]; + int i; + int *ip; + + daemon(1, 0); + openlog("front-paneld", LOG_CONS, LOG_DAEMON); + + if (pthread_create(&tid_debug_card, NULL, debug_card_handler, NULL) < 0) { + syslog(LOG_ALERT, "pthread_create for debug card error\n"); + exit(1); + } + + if (pthread_create(&tid_hand_sw, NULL, hand_sw_handler, NULL) < 0) { + syslog(LOG_ALERT, "pthread_create for hand switch error\n"); + exit(1); + } + + if (pthread_create(&tid_rst_btn, NULL, rst_btn_handler, NULL) < 0) { + syslog(LOG_ALERT, "pthread_create for reset button error\n"); + exit(1); + } + + if (pthread_create(&tid_pwr_btn, NULL, pwr_btn_handler, NULL) < 0) { + syslog(LOG_ALERT, "pthread_create for power button error\n"); + exit(1); + } + + for (i = 0; i < MAX_NUM_SLOTS; i++) { + ip = malloc(sizeof(int)); + *ip = i; + if (pthread_create(&tid_leds[i], NULL, led_handler, (void*)ip) < 0) { + syslog(LOG_ALERT, "pthread_create for hand switch error\n"); + exit(1); + } + } + + pthread_join(tid_debug_card, NULL); + pthread_join(tid_hand_sw, NULL); + pthread_join(tid_rst_btn, NULL); + pthread_join(tid_pwr_btn, NULL); + for (i = 0; i < MAX_NUM_SLOTS; i++) { + pthread_join(tid_leds[i], NULL); + } + + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/files/setup-front-paneld.sh b/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/files/setup-front-paneld.sh new file mode 100644 index 0000000..7055cc0 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/files/setup-front-paneld.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +### BEGIN INIT INFO +# Provides: setup-front-paneld +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Start front panel control daemon +### END INIT INFO + +echo -n "Setup Front Panel Daemon.." + /usr/local/bin/front-paneld > /dev/null 2>&1 & +echo "done." diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/front-paneld_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/front-paneld_0.1.bb new file mode 100644 index 0000000..26db659 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/front-paneld/front-paneld_0.1.bb @@ -0,0 +1,44 @@ +# Copyright 2015-present Facebook. All Rights Reserved. + +SUMMARY = "Front Panel Control Daemon" +DESCRIPTION = "Daemon to monitor and control the front panel " +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://front-paneld.c;beginline=5;endline=17;md5=da35978751a9d71b73679307c4d296ec" + + +DEPENDS_append = "libpal libbic update-rc.d-native" + +SRC_URI = "file://Makefile \ + file://setup-front-paneld.sh \ + file://front-paneld.c \ + " + +S = "${WORKDIR}" + +binfiles = "front-paneld" + +pkgdir = "front-paneld" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + install -m 755 front-paneld ${dst}/front-paneld + ln -snf ../fbpackages/${pkgdir}/front-paneld ${bin}/front-paneld + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-front-paneld.sh ${D}${sysconfdir}/init.d/setup-front-paneld.sh + update-rc.d -r ${D} setup-front-paneld.sh start 67 S . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/front-paneld ${prefix}/local/bin ${sysconfdir} " + +# Inhibit complaints about .debug directories: + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/fruid/fruid_0.1.bbappend b/meta-facebook/meta-yosemite/recipes-yosemite/fruid/fruid_0.1.bbappend new file mode 100644 index 0000000..c87f2a7 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/fruid/fruid_0.1.bbappend @@ -0,0 +1,24 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + + +S = "${WORKDIR}" + +CFLAGS_prepend = " -DCONFIG_YOSEMITE" +LDFLAGS_append = " -lyosemite_fruid" + +DEPENDS_prepend = "libyosemite-fruid" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/files/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/files/Makefile new file mode 100644 index 0000000..68e9453 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/files/Makefile @@ -0,0 +1,26 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +all: gpiod + +sensord: gpiod.c + $(CC) $(CFLAGS) -D _XOPEN_SOURCE -pthread -lm -std=c99 -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o gpiod diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/files/gpiod.c b/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/files/gpiod.c new file mode 100644 index 0000000..9282e00 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/files/gpiod.c @@ -0,0 +1,353 @@ +/* + * sensord + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <stdint.h> +#include <math.h> +#include <string.h> +#include <pthread.h> +#include <sys/un.h> +#include <sys/file.h> +#include <openbmc/ipmi.h> +#include <openbmc/pal.h> +#include <facebook/bic.h> +#include <facebook/yosemite_gpio.h> + +#define SETBIT(x, y) (x | (1 << y)) +#define GETBIT(x, y) ((x & (1 << y)) > y) +#define CLEARBIT(x, y) (x & (~(1 << y))) +#define GETMASK(y) (1 << y) + +#define MAX_NUM_SLOTS 4 +#define GPIOD_READ_DELAY 1 +#define SOCK_PATH_GPIO "/tmp/gpio_socket" + +/* To hold the gpio info and status */ +typedef struct { + uint8_t flag; + uint8_t status; + uint8_t ass_val; + char name[32]; +} gpio_pin_t; + +static gpio_pin_t gpio_slot1[MAX_GPIO_PINS] = {0}; +static gpio_pin_t gpio_slot2[MAX_GPIO_PINS] = {0}; +static gpio_pin_t gpio_slot3[MAX_GPIO_PINS] = {0}; +static gpio_pin_t gpio_slot4[MAX_GPIO_PINS] = {0}; + +/* Returns the pointer to the struct holding all gpio info for the fru#. */ +static gpio_pin_t * +get_struct_gpio_pin(uint8_t fru) { + + gpio_pin_t *gpios; + + switch (fru) { + case FRU_SLOT1: + gpios = gpio_slot1; + break; + case FRU_SLOT2: + gpios = gpio_slot2; + break; + case FRU_SLOT3: + gpios = gpio_slot3; + break; + case FRU_SLOT4: + gpios = gpio_slot4; + break; + default: + syslog(LOG_ALERT, "get_struct_gpio_pin: Wrong SLOT ID %d\n", fru); + return NULL; + } + + return gpios; +} + +int +enable_gpio_intr_config(uint8_t fru, uint8_t gpio) { + int ret; + + bic_gpio_config_t cfg = {0}; + bic_gpio_config_t verify_cfg = {0}; + + + ret = bic_get_gpio_config(fru, gpio, &cfg); + if (ret < 0) { + syslog(LOG_ERR, "enable_gpio_intr_config: bic_get_gpio_config failed" + "for slot_id: %u, gpio pin: %u", fru, gpio); + return -1; + } + + cfg.ie = 1; + + ret = bic_set_gpio_config(fru, gpio, &cfg); + if (ret < 0) { + syslog(LOG_ERR, "enable_gpio_intr_config: bic_set_gpio_config failed" + "for slot_id: %u, gpio pin: %u", fru, gpio); + return -1; + } + + ret = bic_get_gpio_config(fru, gpio, &verify_cfg); + if (ret < 0) { + syslog(LOG_ERR, "enable_gpio_intr_config: verification bic_get_gpio_config" + "for slot_id: %u, gpio pin: %u", fru, gpio); + return -1; + } + + if (verify_cfg.ie != cfg.ie) { + syslog(LOG_ALERT, "Slot_id: %u,Interrupt enabling FAILED for GPIO pin# %d", + fru, gpio); + return -1; + } + + return 0; +} + +/* Enable the interrupt mode for all the gpio sensors */ +static void +enable_gpio_intr(uint8_t fru) { + + int i, ret; + gpio_pin_t *gpios; + + gpios = get_struct_gpio_pin(fru); + if (gpios == NULL) { + syslog(LOG_ALERT, "enable_gpio_intr: get_struct_gpio_pin failed."); + return; + } + + for (i = 0; i < gpio_pin_cnt; i++) { + ret = enable_gpio_intr_config(fru, gpio_pin_list[i]); + if (ret < 0) { + gpios[i].flag = 0; + syslog(LOG_ALERT, "enable_gpio_intr: Slot: %d, Pin %d interrupt enabling" + " failed", fru, gpio_pin_list[i]); + syslog(LOG_ALERT, "enable_gpio_intr: Disable check for Slot %d, Pin %d", + fru, gpio_pin_list[i]); + } else { + gpios[i].flag = 1; +#ifdef DEBUG + syslog(LOG_ALERT, "enable_gpio_intr: Enabled check for Slot: %d, Pin %d", + fru, gpio_pin_list[i]); +#endif /* DEBUG */ + } + } +} + +static void +populate_gpio_pins(uint8_t fru) { + + int i, ret; + + gpio_pin_t *gpios; + + gpios = get_struct_gpio_pin(fru); + if (gpios == NULL) { + syslog(LOG_ALERT, "populate_gpio_pins: get_struct_gpio_pin failed."); + return; + } + + for(i = 0; i < gpio_pin_cnt; i++) { + gpios[gpio_pin_list[i]].flag = 1; + } + + + for(i = 0; i < MAX_GPIO_PINS; i++) { + if (gpios[i].flag) { + gpios[i].ass_val = GETBIT(gpio_ass_val, i); + ret = yosemite_get_gpio_name(fru, i, gpios[i].name); + if (ret < 0) + continue; + } + } +} + +/* Wrapper function to configure and get all gpio info */ +static void +init_gpio_pins() { + int fru; + + for (fru = FRU_SLOT1; fru < (FRU_SLOT1 + MAX_NUM_SLOTS); fru++) { + populate_gpio_pins(fru); + } +} + +/* Monitor the gpio pins */ +static int +gpio_monitor_poll(uint8_t fru_flag) { + int i, ret; + uint8_t fru; + uint32_t revised_pins, n_pin_val, o_pin_val[MAX_NUM_SLOTS + 1] = {0}; + gpio_pin_t *gpios; + + uint32_t status; + bic_gpio_t gpio = {0}; + + /* Check for initial Asserts */ + for (fru = 1; fru <= MAX_NUM_SLOTS; fru++) { + if (GETBIT(fru_flag, fru) == 0) + continue; + + ret = bic_get_gpio(fru, &gpio); + if (ret) { + syslog(LOG_ALERT, "populate_gpio_pins: bic_get_gpio failed for " + " fru %u", fru); + continue; + } + + gpios = get_struct_gpio_pin(fru); + if (gpios == NULL) { + syslog(LOG_ALERT, "gpio_monitor_poll: get_struct_gpio_pin failed for" + " fru %u", fru); + continue; + } + + memcpy(&status, (uint8_t *) &gpio, sizeof(status)); + + o_pin_val[fru] = 0; + + for (i = 0; i <= MAX_GPIO_PINS; i++) { + + if (gpios[i].flag == 0) + continue; + + gpios[i].status = GETBIT(status, i); + + if (gpios[i].status) + o_pin_val[fru] = SETBIT(o_pin_val[fru], i); + + if (gpios[i].status == gpios[i].ass_val) { + syslog(LOG_CRIT, "ASSERT: fru: %u, gpio pin: %-20s, num: %d", + fru, gpios[i].name, i); + } + } + } + + /* Keep monitoring each fru's gpio pins every 4 * GPIOD_READ_DELAY seconds */ + while(1) { + for (fru = 1; fru <= MAX_NUM_SLOTS; fru++) { + if (!(GETBIT(fru_flag, fru))) { + sleep(GPIOD_READ_DELAY); + continue; + } + + gpios = get_struct_gpio_pin(fru); + if (gpios == NULL) { + syslog(LOG_ALERT, "gpio_monitor_poll: get_struct_gpio_pin failed for" + " fru %u", fru); + continue; + } + + if ((ret = bic_get_gpio(fru, (bic_gpio_t *) &n_pin_val)) < 0) { + syslog(LOG_ALERT, "gpio_monitor_poll: bic_get_gpio failed for " + " fru %u", fru); + continue; + } + + if (o_pin_val[fru] == n_pin_val) { + o_pin_val[fru] = n_pin_val; + sleep(GPIOD_READ_DELAY); + continue; + } + + revised_pins = (n_pin_val ^ o_pin_val[fru]); + + for (i = 0; i < MAX_GPIO_PINS; i++) { + if (GETBIT(revised_pins, i) & gpios[i].flag) { + gpios[i].status = GETBIT(n_pin_val, i); + + // Check if the new GPIO val is ASSERT + if (gpios[i].status == gpios[i].ass_val) { + syslog(LOG_CRIT, "ASSERT: fru: %u, gpio pin: %-20s, num: %d", + fru, gpios[i].name, i); + } else { + syslog(LOG_CRIT, "DEASSERT: fru: %u, gpio pin: %-20s, num: %d", + fru, gpios[i].name, i); + } + } + } + + o_pin_val[fru] = n_pin_val; + sleep(GPIOD_READ_DELAY); + + } /* For Loop for each fru */ + } /* while loop */ +} /* function definition*/ + +static void +print_usage() { + printf("Usage: gpiod [ %s ]\n", "slot1, slot2, slot3, slot4"); +} + +/* Spawns a pthread for each fru to monitor all the sensors on it */ +static void +run_gpiod(int argc, void **argv) { + + //gpio_monitor(); + + int i, ret; + uint8_t fru_flag, fru; + + /* Check for which fru do we need to monitor the gpio pins */ + fru_flag = 0; + for (i = 1; i < argc; i++) { + ret = pal_get_fru_id(argv[i], &fru); + if (ret < 0) { + print_usage(); + exit(-1); + } + fru_flag = SETBIT(fru_flag, fru); + } + + gpio_monitor_poll(fru_flag); +} + +int +main(int argc, void **argv) { + int dev, rc, pid_file; + + if (argc < 2) { + print_usage(); + exit(-1); + } + + pid_file = open("/var/run/gpiod.pid", O_CREAT | O_RDWR, 0666); + rc = flock(pid_file, LOCK_EX | LOCK_NB); + if(rc) { + if(EWOULDBLOCK == errno) { + printf("Another gpiod instance is running...\n"); + exit(-1); + } + } else { + + init_gpio_pins(); + + daemon(0,1); + openlog("gpiod", LOG_CONS, LOG_DAEMON); + syslog(LOG_INFO, "gpiod: daemon started"); + run_gpiod(argc, argv); + } + + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/files/setup-gpiod.sh b/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/files/setup-gpiod.sh new file mode 100644 index 0000000..9e532f2 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/files/setup-gpiod.sh @@ -0,0 +1,33 @@ +#!/bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: setup-sensord +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Setup sensor monitoring +### END INIT INFO + +# TODO: check for the if slot/server is present before starting the daemon +echo -n "Setup gpio monitoring for yosemite... " +/usr/local/bin/gpiod slot1 slot2 slot3 slot4 +echo "done." diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/gpiod_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/gpiod_0.1.bb new file mode 100644 index 0000000..2193a92 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/gpiod/gpiod_0.1.bb @@ -0,0 +1,62 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "GPIO Sensor Monitoring Daemon" +DESCRIPTION = "Daemon for monitoring the gpio sensors" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://gpiod.c;beginline=4;endline=16;md5=b395943ba8a0717a83e62ca123a8d238" + +SRC_URI = "file://Makefile \ + file://gpiod.c \ + file://setup-gpiod.sh \ + " + +S = "${WORKDIR}" + +binfiles = "gpiod \ + " + +CFLAGS += " -lbic -lyosemite_gpio -lpal " + +DEPENDS += " libbic libyosemite-gpio libpal " + +pkgdir = "gpiod" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${dst}/$f + ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f + done + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-gpiod.sh ${D}${sysconfdir}/init.d/setup-gpiod.sh + update-rc.d -r ${D} setup-gpiod.sh start 91 S . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/gpiod ${prefix}/local/bin ${sysconfdir} " + + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/ipmbd/files/setup-ipmbd.sh b/meta-facebook/meta-yosemite/recipes-yosemite/ipmbd/files/setup-ipmbd.sh new file mode 100644 index 0000000..b37d8fa --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/ipmbd/files/setup-ipmbd.sh @@ -0,0 +1,104 @@ +#! /bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: ipmbd +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Provides ipmb message tx/rx service +# +### END INIT INFO + +. /usr/local/fbpackages/utils/ast-functions + +PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin +DAEMON=/usr/local/bin/ipmbd +NAME=ipmbd +DESC="IPMB Rx/Tx Daemon" + +test -f $DAEMON || exit 0 + +STOPPER= +ACTION="$1" + +case "$ACTION" in + start) + echo -n "Starting $DESC: " + + if [ $(is_server_prsnt 1) == "1" ]; then + $DAEMON 3 > /dev/null 2>&1 & + fi + + if [ $(is_server_prsnt 2) == "1" ]; then + $DAEMON 1 > /dev/null 2>&1 & + fi + + if [ $(is_server_prsnt 3) == "1" ]; then + $DAEMON 7 > /dev/null 2>&1 & + fi + + if [ $(is_server_prsnt 4) == "1" ]; then + $DAEMON 5 > /dev/null 2>&1 & + fi + + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --exec $DAEMON + echo "$NAME." + ;; + restart|force-reload) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --exec $DAEMON + sleep 1 + if [ $(is_server_prsnt 1) == "1" ]; then + $DAEMON 3 > /dev/null 2>&1 & + fi + + if [ $(is_server_prsnt 2) == "1" ]; then + $DAEMON 1 > /dev/null 2>&1 & + fi + + if [ $(is_server_prsnt 3) == "1" ]; then + $DAEMON 7 > /dev/null 2>&1 & + fi + + if [ $(is_server_prsnt 4) == "1" ]; then + $DAEMON 5 > /dev/null 2>&1 & + fi + + echo "$NAME." + ;; + status) + status $DAEMON + exit $? + ;; + *) + N=${0##*/} + N=${N#[SK]??} + echo "Usage: $N {start|stop|status|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/ipmbd/ipmbd_0.1.bbappend b/meta-facebook/meta-yosemite/recipes-yosemite/ipmbd/ipmbd_0.1.bbappend new file mode 100644 index 0000000..bf2af1e --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/ipmbd/ipmbd_0.1.bbappend @@ -0,0 +1,27 @@ +# Copyright 2015-present Facebook. All Rights Reserved. + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" +SRC_URI += " file://setup-ipmbd.sh \ + " + +CFLAGS_prepend = " -DCONFIG_YOSEMITE" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + install -m 755 ipmbd ${dst}/ipmbd + ln -snf ../fbpackages/${pkgdir}/ipmbd ${bin}/ipmbd + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-ipmbd.sh ${D}${sysconfdir}/init.d/setup-ipmbd.sh + update-rc.d -r ${D} setup-ipmbd.sh start 65 S . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/ipmbd ${prefix}/local/bin ${sysconfdir} " + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/bic.c b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/bic.c new file mode 100644 index 0000000..5af03ce --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/bic.c @@ -0,0 +1,78 @@ +/* Copyright 2015-present Facebook. All Rights Reserved. + * + * This file contains code to support IPMI2.0 Specificaton available @ + * http://www.intel.com/content/www/us/en/servers/ipmi/ipmi-specifications.html + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> +#include <syslog.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <openbmc/ipmi.h> + +#define MAX_IPMI_RES_LEN 100 + +/* + * Function to handle GPIO interrupt + */ +void +lib_gpio_intr_handle(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len) { + + int sockfd, t, len; + struct sockaddr_un remote; + + // TODO: Need to update to reuse the socket instead of creating new + if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + syslog(LOG_ALERT, "lib_gpio_intr_handle: socket() failed\n"); + return; + } + + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, SOCK_PATH_GPIO); + len = strlen(remote.sun_path) + sizeof(remote.sun_family); + + if (connect(sockfd, (struct sockaddr *)&remote, len) == -1) { + syslog(LOG_ALERT, "lib_gpio_intr_handle: connect() failed\n"); + return; + } + + if (send(sockfd, request, req_len, 0) == -1) { + syslog(LOG_ALERT, "lib_gpio_intr_handle: send() failed\n"); + return; + } + + if ((t=recv(sockfd, response, MAX_IPMI_RES_LEN, 0)) > 0) { + *res_len = t; + } else { + if (t < 0) { + syslog(LOG_ALERT, "lib_gpio_intr_handle: recv() failed\n"); + } else { + printf("Server closed connection"); + } + + return; + } + + close(sockfd); + + return; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/bic.h b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/bic.h new file mode 100644 index 0000000..c0fcfbb --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/bic.h @@ -0,0 +1,29 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __BIC_H__ +#define __BIC_H__ + +#define SOCK_PATH_GPIO "/tmp/gpio_socket" + +void lib_gpio_intr_handle(unsigned char *request, unsigned char req_len, + unsigned char *response, unsigned char *res_len); + +#endif /* __BIC_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/fruid.c b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/fruid.c new file mode 100644 index 0000000..04772d7 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/fruid.c @@ -0,0 +1,111 @@ +/* + * + * Copyright 2015-present Facebook. All Rights Reserved. + * + * This file provides platform specific implementation of FRUID information + * + * FRUID specification can be found at + * www.intel.com/content/dam/www/public/us/en/documents/product-briefs/platform-management-fru-document-rev-1-2-feb-2013.pdf + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> +#include <stdint.h> +#include "fruid.h" + +#define EEPROM_SPB "/sys/class/i2c-adapter/i2c-8/8-0051/eeprom" + +#define BIN_SPB "/tmp/fruid_spb.bin" + +#define NAME_SPB "Side Plane Board" + +#define BUF_SIZE 1024 + +/* + * copy_eeprom_to_bin - copy the eeprom to binary file im /tmp directory + * + * @eeprom_file : path for the eeprom of the device + * @bin_file : path for the binary file + * + * returns 0 on successful copy + * returns non-zero on file operation errors + */ +int copy_eeprom_to_bin(const char * eeprom_file, const char * bin_file) { + + int eeprom; + int bin; + uint64_t tmp[BUF_SIZE]; + ssize_t bytes_rd, bytes_wr; + + errno = 0; + + if (access(eeprom_file, F_OK) != -1) { + + eeprom = open(eeprom_file, O_RDONLY); + if (eeprom == -1) { + syslog(LOG_ERR, "copy_eeprom_to_bin: unable to open the %s file: %s", + eeprom_file, strerror(errno)); + return errno; + } + + bin = open(bin_file, O_WRONLY | O_CREAT, 0644); + if (bin == -1) { + syslog(LOG_ERR, "copy_eeprom_to_bin: unable to create %s file: %s", + bin_file, strerror(errno)); + return errno; + } + + while ((bytes_rd = read(eeprom, tmp, BUF_SIZE)) > 0) { + bytes_wr = write(bin, tmp, bytes_rd); + if (bytes_wr != bytes_rd) { + syslog(LOG_ERR, "copy_eeprom_to_bin: write to %s file failed: %s", + bin_file, strerror(errno)); + return errno; + } + } + + close(bin); + close(eeprom); + } + + return 0; +} + +/* Populate the platform specific eeprom for fruid info */ +int plat_fruid_init(void) { + + int ret; + + ret = copy_eeprom_to_bin(EEPROM_SPB, BIN_SPB); + + return ret; +} + +int plat_fruid_size(void) { + /* TODO: Not supported yet */ + return 0; +} +int plat_fruid_data(int offset, int count, unsigned char *data) { + /* TODO: Not supported yet */ + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/sensor.c b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/sensor.c new file mode 100644 index 0000000..16cf98e --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/sensor.c @@ -0,0 +1,371 @@ +/* + * + * Copyright 2014-present Facebook. All Rights Reserved. + * + * This file provides platform specific implementation of sensor information + * + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "sensor.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <syslog.h> +#include <string.h> + +#define SENSOR_MGMT_MAX 1 +#define SENSOR_DISC_MAX 8 +#define SENSOR_THRESH_MAX 1 +#define SENSOR_OEM_MAX 1 + +#define BMC_SLAVE_ADDR 0x20 + +typedef struct { + unsigned char num; + sensor_mgmt_t sensor[SENSOR_MGMT_MAX]; +} sensor_mgmt_info_t; + +typedef struct { + unsigned char num; + sensor_disc_t sensor[SENSOR_DISC_MAX]; +} sensor_disc_info_t; + +typedef struct { + unsigned char num; + sensor_thresh_t sensor[SENSOR_THRESH_MAX]; +} sensor_thresh_info_t; + +typedef struct { + unsigned char num; + sensor_oem_t sensor[SENSOR_OEM_MAX]; +} sensor_oem_info_t; + +// Global structures +static sensor_mgmt_info_t g_sensor_mgmt = {0}; +static sensor_disc_info_t g_sensor_disc = {0}; +static sensor_thresh_info_t g_sensor_thresh = {0}; +static sensor_oem_info_t g_sensor_oem = {0}; + +static void +populate_mgmt_sensors(void) { + sensor_mgmt_t sensor = {0}; + + // Add record for the AST2100 BMC + sensor.slave_addr = BMC_SLAVE_ADDR; + sensor.chan_no = 0x0; // Primary BMC controller + + // Init Agent = false + sensor.pwr_state_init = 0x00; + + // FRUID = true, SEL = true, SDR = true, Sensor = true + sensor.dev_caps = 0x0F; + + // Device ID string + // Type - 0xC0: ASCII, Length - 0x09 + sensor.str_type_len = 0xC0 + 0x09; + strncpy(sensor.str, "Yosemite-BMC", 0x09); + + // Add this sensor to the global table + if (g_sensor_mgmt.num >= SENSOR_MGMT_MAX) { + syslog(LOG_ALERT, "populate_mgmt_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_mgmt.sensor[g_sensor_mgmt.num], &sensor, sizeof(sensor_mgmt_t)); + + g_sensor_mgmt.num++; + + return; +} + +static void +populate_disc_sensors(void) { + + sensor_disc_t sensor = {0}; + + // Sensor uS Status + // Sensor# 0x10 + // EntitiyId# 0xD0, EntityInst# 0x00 + // Sensor Type# Chassis 0x18 + // Event Read/Type# OEM 0x70 + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0x10; + + sensor.ent_id = 0xD0; + sensor.ent_inst = 0x00; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0x18; + sensor.evt_read_type = 0x70; + // 1-bit for CPU0 Thermal Trip + sensor.assert_evt_mask[0] = 0x04; + sensor.deassert_evt_mask[0] = 0x00; + sensor.read_evt_mask[0] = 0x04; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 9; + strncpy(sensor.str, "uS-Status", 9); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + // Sensor SEL Status + // Sensor# 0x5F + // EntitiyId# 0xD0, EntityInst# 0x02 + // Sensor Type# OEM: 0xC0 + // Event Read/Type# Sensor Specific: 0x6F + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0x5F; + + sensor.ent_id = 0xD0; + sensor.ent_inst = 0x02; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0xC0; + sensor.evt_read_type = 0x6F; + // SEL Clear(bit1), SEL Rollover(bit8) + sensor.assert_evt_mask[0] = 0x02; + sensor.assert_evt_mask[1] = 0x01; + sensor.deassert_evt_mask[0] = 0x00; + sensor.deassert_evt_mask[1] = 0x00; + sensor.read_evt_mask[0] = 0x02; + sensor.read_evt_mask[1] = 0x01; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 10; + strncpy(sensor.str, "SEL-Status", 10); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + + // Sensor WDT + // Sensor# 0x60 + // EntitiyId# 0xD0, EntityInst# 0x03 + // Sensor Type# WDT2: 0x23 + // Event Read/Type# Sensor Specific: 0x6F + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0x60; + + sensor.ent_id = 0xD0; + sensor.ent_inst = 0x03; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0x23; + sensor.evt_read_type = 0x6F; + // 5 bits for expiry, reset, pwrdown, pwrcycle, timer + sensor.assert_evt_mask[0] = 0x0F; + sensor.assert_evt_mask[1] = 0x01; + sensor.deassert_evt_mask[0] = 0x00; + sensor.deassert_evt_mask[1] = 0x00; + sensor.read_evt_mask[0] = 0x0F; + sensor.read_evt_mask[1] = 0x01; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 3; + strncpy(sensor.str, "WDT", 3); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + + // Sensor Chassis Pwr Sts + // Sensor# 0x70 + // EntitiyId# 0x15, EntityInst# 0x00 + // Sensor Type# OEM: 0xC8 + // Event Read/Type# Sensor Specific: 0x6F + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0x70; + + sensor.ent_id = 0x15; + sensor.ent_inst = 0x00; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0xC8; + sensor.evt_read_type = 0x6F; + // 6 bits for pwroff, pwrcycle, pwron, softdown, ac-lost, hard-reset + sensor.assert_evt_mask[0] = 0x3F; + sensor.deassert_evt_mask[0] = 0x00; + sensor.read_evt_mask[0] = 0x3F; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 13; + strncpy(sensor.str, "CH-Pwr-Status", 13); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + // Sensor CPU DIMM Hot + // Sensor# 0xB3 + // EntitiyId# 0xD0, EntityInst# 0x05 + // Sensor Type# OEM 0xC6 + // Event Read/Type# Sensor Specific 6Fh + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0xB3; + + sensor.ent_id = 0xD0; + sensor.ent_inst = 0x05; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0xC6; + sensor.evt_read_type = 0x6F; + // Two bits for CPU Hot, DIMM Hot + sensor.assert_evt_mask[0] = 0x05; + sensor.deassert_evt_mask[0] = 0x05; + sensor.read_evt_mask[0] = 0x05; + + // Device ID string + // Type - 0xC0: ASCII, Length - 12 + sensor.str_type_len = 0xC0 + 12; + strncpy(sensor.str, "CPU_DIMM_HOT", 12); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + // Sensor PMBus Status Word Low + // Sensor PMBus Status Word High + // Sensor PMBus Status MFR + // Sensor PMBus Status Input + // Sensor NTP Status + // Sensor# 0xED + // EntitiyId# 0x35, EntityInst# 0x00 + // Sensor Type# OEM 0xC7 + // Event Read/Type# Sensor Specific 6Fh + sensor.owner= BMC_SLAVE_ADDR; + sensor.lun = 0x00; + sensor.sensor_num = 0xED; + + sensor.ent_id = 0x35; + sensor.ent_inst = 0x00; + // Enable Scanning, Enable Events + sensor.sensor_init = 0x63; + // Supports Auto Re-Arm + sensor.sensor_caps = 0x40; + sensor.sensor_type = 0xC7; + sensor.evt_read_type = 0x6F; + // 1-bit for date/time sync failed + sensor.assert_evt_mask[0] = 0x01; + sensor.deassert_evt_mask[0] = 0x00; + sensor.read_evt_mask[0] = 0x01; + + // Device ID string + // Type - 0xC0: ASCII, Length - 10 + sensor.str_type_len = 0xC0 + 12; + strncpy(sensor.str, "NTP-Status", 10); + + // Add this sensor to the global table + if (g_sensor_disc.num >= SENSOR_DISC_MAX) { + syslog(LOG_ALERT, "populate_disc_sensors: num exceeded\n"); + return; + } + + memcpy(&g_sensor_disc.sensor[g_sensor_disc.num], &sensor, sizeof(sensor_disc_t)); + + g_sensor_disc.num++; + + return; +} + +// Access functions for Sensor Table +void +plat_sensor_mgmt_info(int *p_num, sensor_mgmt_t **p_sensor) { + *p_num = g_sensor_mgmt.num; + *p_sensor = g_sensor_mgmt.sensor; +} + +void +plat_sensor_disc_info(int *p_num, sensor_disc_t **p_sensor) { + *p_num = g_sensor_disc.num; + *p_sensor = g_sensor_disc.sensor; +} + +void +plat_sensor_thresh_info(int *p_num, sensor_thresh_t **p_sensor) { + *p_num = g_sensor_thresh.num; + *p_sensor = g_sensor_thresh.sensor; +} + +void +plat_sensor_oem_info(int *p_num, sensor_oem_t **p_sensor) { + *p_num = g_sensor_oem.num; + *p_sensor = g_sensor_oem.sensor; +} + +// Initialize Sensor Table +int +plat_sensor_init(void) { + + // Populate all Sensors + populate_mgmt_sensors(); + populate_disc_sensors(); + + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/setup-ipmid.sh b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/setup-ipmid.sh new file mode 100644 index 0000000..b724d70 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/files/setup-ipmid.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: setup-ipmid +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Set IPMI Message handler +### END INIT INFO + +echo -n "Setup IPMI message handler... " +/usr/local/bin/ipmid +echo "done." diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/ipmid_0.2.bbappend b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/ipmid_0.2.bbappend new file mode 100644 index 0000000..4a92e78 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/ipmid/ipmid_0.2.bbappend @@ -0,0 +1,46 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +DEPENDS_append = "libipmi libfruid update-rc.d-native" + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" +SRC_URI += "file://setup-ipmid.sh \ + file://sensor.c \ + file://fruid.c \ + " + +S = "${WORKDIR}" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + install -m 755 ipmid ${dst}/ipmid + ln -snf ../fbpackages/${pkgdir}/ipmid ${bin}/ipmid + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-ipmid.sh ${D}${sysconfdir}/init.d/setup-ipmid.sh + update-rc.d -r ${D} setup-ipmid.sh start 64 S . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/ipmid ${prefix}/local/bin ${sysconfdir} " + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/lm_sensors/files/yosemite.conf b/meta-facebook/meta-yosemite/recipes-yosemite/lm_sensors/files/yosemite.conf new file mode 100644 index 0000000..b05ec3a --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/lm_sensors/files/yosemite.conf @@ -0,0 +1,44 @@ + +bus "i2c-9" "ast_i2c.9" + +chip "tmp75-i2c-9-4e" + label temp1 "Inlet Temp" + +chip "tmp75-i2c-9-4f" + label temp1 "Outlet Temp" + +chip "ast_pwm-*" + label fan1 "Fan 1" + label fan2 "Fan 2" + ignore fan3 + ignore fan4 + ignore fan5 + ignore fan6 + ignore fan7 + ignore fan8 + ignore fan9 + ignore fan10 + ignore fan11 + ignore fan12 + ignore fan13 + ignore fan14 + ignore fan15 + ignore fan16 + +chip "ast_adc-isa-0000" + label in0 "P5V_STBY Voltage" + label in1 "P12V_STBY Voltage" + label in2 "P3V3_STBY Voltage" + label in3 "P12V_STBY_SLOT0 Voltage" + label in4 "P12V_STBY_SLOT1 Voltage" + label in5 "P12V_STBY_SLOT2 Voltage" + label in6 "P12V_STBY_SLOT3 Voltage" + label in7 "P3V3 Voltage" + ignore in8 + ignore in9 + ignore in10 + ignore in11 + ignore in12 + ignore in13 + ignore in14 + ignore in15 diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/lm_sensors/lmsensors_%.bbappend b/meta-facebook/meta-yosemite/recipes-yosemite/lm_sensors/lmsensors_%.bbappend new file mode 100644 index 0000000..c33761e --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/lm_sensors/lmsensors_%.bbappend @@ -0,0 +1,10 @@ + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += "file://yosemite.conf \ + " + +do_install_append() { + install -d ${D}${sysconfdir}/sensors.d + install -m 644 ../yosemite.conf ${D}${sysconfdir}/sensors.d/yosemite.conf +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/Makefile b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/Makefile new file mode 100644 index 0000000..00464e5 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/Makefile @@ -0,0 +1,29 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +all: oob-nic i2craw + +oob-nic: main.o nic.o intf.o ll_map.o libnetlink.o + $(CC) -o $@ $^ $(LDFLAGS) -lwedge_eeprom + +i2craw: i2craw.o + $(CC) -o $@ $^ $(LDFLAGS) + +.PHONY: clean + +clean: + rm -rf *.o oob-nic i2craw diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/README b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/README new file mode 100644 index 0000000..f46971f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/README @@ -0,0 +1,10 @@ + +TODO: + +1. Currently, we poll the SMbus instead of rely on the ALERT. The kernel does not handle the ALERT either other than just a print out. + +2. Maximum fragment is 32 + +3. We use libnetlink for bring interface up and setting MAC. That increases the binary by about 50k and also we copied about 5 files from iproute2 here for that. We might be able to get away this by using some non-iproute2 API + +4. The dependency in the Makefile does not consider .h diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/etc/oob-nic.sh b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/etc/oob-nic.sh new file mode 100644 index 0000000..71ee0fa --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/etc/oob-nic.sh @@ -0,0 +1,93 @@ +#! /bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: oob-nic +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: One of the first scripts to be executed. Starts or stops +# the OOB NIC. +# +### END INIT INFO + +PATH=/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/sbin/oob-nic +NAME=oob-nic +DESC="OOB NIC Driver" + +# source function library +. /etc/init.d/functions + +test -f $DAEMON || exit 0 + +. /usr/local/fbpackages/utils/ast-functions + +fix_etc_interfaces() { + local intf_conf rev + intf_conf="/etc/network/interfaces" +} + +STOPPER= +ACTION="$1" + +case "$ACTION" in + start) + echo -n "Starting $DESC: " + if [ ! -d /dev/net ] + then + mkdir /dev/net + fi + if [ ! -f /dev/net/tun ] + then + mknod /dev/net/tun c 10 200 + chmod 666 /dev/net/tun + fi + fix_etc_interfaces + $DAEMON > /dev/null 2>&1 & + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --quiet --exec $DAEMON + echo "$NAME." + ;; + restart|force-reload) + echo -n "Restarting $DESC: " + start-stop-daemon --stop --quiet --exec $DAEMON + sleep 1 + fix_etc_interfaces + $DAEMON > /dev/null 2>&1 & + echo "$NAME." + ;; + status) + status $DAEMON + exit $? + ;; + *) + N=${0##*/} + N=${N#[SK]??} + echo "Usage: $N {start|stop|status|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/hlist.h b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/hlist.h new file mode 100644 index 0000000..5e89765 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/hlist.h @@ -0,0 +1,73 @@ +/* + * Note: Original file from iproute2 package + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __HLIST_H__ +#define __HLIST_H__ 1 +/* Hash list stuff from kernel */ + +#include <stddef.h> + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +static inline void hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos ; pos = pos->next) + + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +#define hlist_entry_safe(ptr, type, member) \ + ({ typeof(ptr) ____ptr = (ptr); \ + ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ + }) + +#define hlist_for_each_entry(pos, head, member) \ + for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\ + pos; \ + pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) + +#endif /* __HLIST_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/i2craw.c b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/i2craw.c new file mode 100644 index 0000000..f9d499b --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/i2craw.c @@ -0,0 +1,245 @@ +/* + * Copyright 2004-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdint.h> + +#include "facebook/i2c-dev.h" +#include "facebook/log.h" + +void usage(const char *prog) { + printf("Usage: %s [options] <bus number> <slave address>\n", prog); + printf("\n Options:\n" + "\n\t-w 'bytes to write':\n" + "\t\t i2c write\n" + "\n\t-r <number of bytes to read>:\n" + "\t\t if 0 is provided, the first byte of read is used to determine\n" + "\t\t how many bytes more to read\n" + "\n\t-p:\n" + "\t\t Use PEC\n" + "\n\t-h:\n" + "\t\t Print this help\n" + "\n Note: if both '-w' and '-r' are specified, write will be" + "\n performed first, followed by read\n"); +} + +#define MAX_BYTES 255 + +int g_use_pec = 0; +int g_has_write = 0; +int g_n_write = 0; +uint8_t g_write_bytes[MAX_BYTES]; +int g_has_read = 0; +int g_n_read = -1; +uint8_t g_read_bytes[MAX_BYTES]; +uint8_t g_bus = -1; +uint8_t g_slave_addr = 0xff; + +static int parse_byte_string(const char *str) { + const char *startptr = str; + char *endptr; + int total = 0; + unsigned long val; + + do { + val = strtoul(startptr, &endptr, 0); + if (startptr == endptr) { + printf("'%s' is invalid\n", str); + return -1; + } + if (val > MAX_BYTES) { + printf("'%s' is invalid\n", str); + return -1; + } + g_write_bytes[total++] = val; + if (*endptr == '\0') { + break; + } + if (total >= MAX_BYTES) { + printf("'%s' is invalid\n", str); + return -1; + } + startptr = endptr; + } while(1); + + return total; +} + +static int i2c_open() { + int fd; + char fn[32]; + int rc; + + snprintf(fn, sizeof(fn), "/dev/i2c-%d", g_bus); + fd = open(fn, O_RDWR); + if (fd == -1) { + LOG_ERR(errno, "Failed to open i2c device %s", fn); + return -1; + } + + rc = ioctl(fd, I2C_SLAVE, g_slave_addr); + if (rc < 0) { + LOG_ERR(errno, "Failed to open slave @ address 0x%x", g_slave_addr); + close(fd); + } + + return fd; +} + +static int i2c_io(int fd) { + struct i2c_rdwr_ioctl_data data; + struct i2c_msg msg[2]; + int n_msg = 0; + int rc; + + memset(&msg, 0, sizeof(msg)); + + if (g_has_write) { + msg[n_msg].addr = g_slave_addr; + msg[n_msg].flags = (g_use_pec) ? I2C_CLIENT_PEC : 0; + msg[n_msg].len = g_n_write; + msg[n_msg].buf = g_write_bytes; + n_msg++; + } + + if (g_has_read) { + msg[n_msg].addr = g_slave_addr; + msg[n_msg].flags = I2C_M_RD + | ((g_use_pec) ? I2C_CLIENT_PEC : 0) + | ((g_n_read == 0) ? I2C_M_RECV_LEN : 0); + /* + * In case of g_n_read is 0, block length will be added by + * the underlying bus driver. + */ + msg[n_msg].len = (g_n_read) ? g_n_read : 256; + msg[n_msg].buf = g_read_bytes; + if (g_n_read == 0) { + /* If we're using variable length block reads, we have to set the + * first byte of the buffer to at least one or the kernel complains. + */ + g_read_bytes[0] = 1; + } + n_msg++; + } + + data.msgs = msg; + data.nmsgs = n_msg; + + rc = ioctl(fd, I2C_RDWR, &data); + if (rc < 0) { + LOG_ERR(errno, "Failed to do raw io"); + return -1; + } + + return 0; +} + +int main(int argc, char * const argv[]) { + int i; + int fd; + int opt; + while ((opt = getopt(argc, argv, "hpw:r:")) != -1) { + switch (opt) { + case 'h': + usage(argv[0]); + return 0; + case 'p': + g_use_pec = 1; + break; + case 'w': + g_has_write = 1; + if ((g_n_write = parse_byte_string(optarg)) <= 0) { + usage(argv[0]); + return -1; + } + break; + case 'r': + g_has_read = 1; + g_n_read = atoi(optarg); + break; + default: + usage(argv[0]); + return -1; + } + } + + /* make sure we still have arguments for bus and slave address */ + if (optind + 2 != argc) { + printf("Bus or slave address is missing\n"); + usage(argv[0]); + return -1; + } + + g_bus = atoi(argv[optind]); + g_slave_addr = strtoul(argv[optind + 1], NULL, 0); + if ((g_slave_addr & 0x80)) { + printf("Slave address must be 7-bit\n"); + return -1; + } + + if (!g_has_write && !g_has_read) { + /* by default, read, first byte read is the length */ + g_has_read = 1; + g_n_read = 0; + } + + printf("Bus: %d\nDevice address: 0x%x\n", g_bus, g_slave_addr); + if (g_has_write) { + printf("To write %d bytes:", g_n_write); + for (i = 0; i < g_n_write; i++) { + printf(" 0x%x", g_write_bytes[i]); + } + printf("\n"); + } + if (g_has_read) { + if (g_n_read) { + printf("To read %d bytes.\n", g_n_read); + } else { + printf("To read data.\n"); + } + } + + fd = i2c_open(); + if (fd < 0) { + return -1; + } + + if (i2c_io(fd) < 0) { + return -1; + } + + if (g_has_read) { + printf("Received:\n "); + if (g_n_read == 0) { + g_n_read = g_read_bytes[0] + 1; + } + for (i = 0; i < g_n_read; i++) { + printf(" 0x%x", g_read_bytes[i]); + } + printf("\n"); + } + + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/intf.c b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/intf.c new file mode 100644 index 0000000..5bf8480 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/intf.c @@ -0,0 +1,254 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "intf.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <linux/rtnetlink.h> +#include <linux/if.h> +#include <linux/if_tun.h> +#include <linux/fib_rules.h> + +#include "facebook/log.h" +#include "libnetlink.h" +#include "ll_map.h" + +struct oob_intf_t { + char oi_name[32]; + int oi_fd; + int oi_ifidx; + uint8_t oi_mac[6]; + struct rtnl_handle oi_rth; +}; + +#define TUN_DEVICE "/dev/net/tun" + +static int oob_intf_set_mac(oob_intf *intf, const uint8_t mac[6]) { + int rc; + struct { + struct nlmsghdr n; + struct ifinfomsg ifi; + char buf[256]; + } req; + + memset(&req, 0, sizeof(req)); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_type = RTM_NEWLINK; + req.n.nlmsg_flags = NLM_F_REQUEST; + req.ifi.ifi_family = AF_UNSPEC; + req.ifi.ifi_index = intf->oi_ifidx; + memcpy(intf->oi_mac, mac, sizeof(intf->oi_mac)); + addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, + intf->oi_mac, sizeof(intf->oi_mac)); + rc = rtnl_talk(&intf->oi_rth, &req.n, 0, 0, NULL); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to set mac to interface %s @ index %d", + intf->oi_name, intf->oi_ifidx); + return -rc; + } + + LOG_INFO("Set interface %s @ index %d mac to %x:%x:%x:%x:%x:%x", + intf->oi_name, intf->oi_ifidx, + intf->oi_mac[0], intf->oi_mac[1], intf->oi_mac[2], + intf->oi_mac[3], intf->oi_mac[4], intf->oi_mac[5]); + + return 0; +} + +static int oob_intf_bring_up(oob_intf *intf) { + int rc; + struct { + struct nlmsghdr n; + struct ifinfomsg ifi; + char buf[256]; + } req; + + memset(&req, 0, sizeof(req)); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.n.nlmsg_type = RTM_NEWLINK; + req.n.nlmsg_flags = NLM_F_REQUEST; + req.ifi.ifi_family = AF_UNSPEC; + req.ifi.ifi_change |= IFF_UP; + req.ifi.ifi_flags |= IFF_UP; + req.ifi.ifi_index = intf->oi_ifidx; + rc = rtnl_talk(&intf->oi_rth, &req.n, 0, 0, NULL); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to bring up interface %s @ index %d", + intf->oi_name, intf->oi_ifidx); + return -rc; + } + + LOG_INFO("Brought up interface %s @ index %d", intf->oi_name, intf->oi_ifidx); + + return 0; +} + +oob_intf* oob_intf_create(const char *name, const uint8_t mac[6]) { + + int rc; + int flags; + struct ifreq ifr; + oob_intf *intf = NULL; + +#define _CHECK_RC(fmt, ...) do { \ + if (rc < 0) { \ + rc = errno; \ + LOG_ERR(rc, fmt, ##__VA_ARGS__); \ + goto err_out; \ + } \ +} while(0) + + intf = malloc(sizeof(*intf)); + if (!intf) { + rc = ENOMEM; + LOG_ERR(rc, "Failed to allocate memory for interface"); + goto err_out; + } + memset(intf, 0, sizeof(*intf)); + strncpy(intf->oi_name, name, sizeof(intf->oi_name)); + intf->oi_name[sizeof(intf->oi_name) - 1] = '\0'; + intf->oi_fd = -1; + + rc = rtnl_open(&intf->oi_rth, 0); + _CHECK_RC("Failed to open rth_handler"); + + rc = open(TUN_DEVICE, O_RDWR); + _CHECK_RC("Failed to open %s", TUN_DEVICE); + intf->oi_fd = rc; + + memset(&ifr, 0, sizeof(ifr)); + /* + * IFF_TAP: TAP interface + * IFF_NO_PI: Do not provide pracket information + */ + ifr.ifr_flags = IFF_TAP|IFF_NO_PI; + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; + + rc = ioctl(intf->oi_fd, TUNSETIFF, (void *) &ifr); + _CHECK_RC("Failed to create tap interface %s", ifr.ifr_name); + + /* make fd non-blocking */ + rc = fcntl(intf->oi_fd, F_GETFL); + _CHECK_RC("Failed to get flags from fd ", intf->oi_fd); + flags = rc | O_NONBLOCK; + rc = fcntl(intf->oi_fd, F_SETFL, rc); + _CHECK_RC("Failed to set non-blocking flags ", flags, + " to fd ", intf->oi_fd); + + /* set CLOEXEC */ + rc = fcntl(intf->oi_fd, F_GETFD); + _CHECK_RC("Failed to get flags from fd ", intf->oi_fd); + flags = rc | FD_CLOEXEC; + rc = fcntl(intf->oi_fd, F_SETFD, flags); + _CHECK_RC("Failed to set close-on-exec flags ", flags, + " to fd ", intf->oi_fd); + + // TODO: if needed, we can adjust send buffer size, TUNSETSNDBUF + intf->oi_ifidx = ll_name_to_index(intf->oi_name); + + /* now set the mac address */ + oob_intf_set_mac(intf, mac); + +#if 0 + /* make it persistent */ + rc = ioctl(intf->oi_fd, TUNSETPERSIST, 0); + _CHECK_RC("Failed to make the tap interface %s persistent", intf->oi_name); +#endif + + LOG_INFO("Create/attach to tap interface %s @ fd %d, index %d", + intf->oi_name, intf->oi_fd, intf->oi_ifidx); + + //oob_intf_bring_up(intf); + + return intf; + + err_out: + if (intf) { + rtnl_close(&intf->oi_rth); + if (intf->oi_fd != -1) { + close(intf->oi_fd); + } + free(intf); + } + + return NULL; +} + +int oob_intf_get_fd(const oob_intf *intf) { + return intf->oi_fd; +} + +int oob_intf_receive(const oob_intf *intf, char *buf, int len) { + int rc; + do { + rc = read(intf->oi_fd, buf, len); + } while (rc == -1 && errno == EINTR); + if (rc < 0) { + rc = errno; + if (rc != EAGAIN) { + LOG_ERR(rc, "Failed to read on interface fd %d", intf->oi_fd); + return -rc; + } else { + /* nothing is available */ + return 0; + } + } else if (rc == 0) { + // Nothing to read. It shall not happen as the fd is non-blocking. + // Just add this case to be safe. + return 0; + } else if (rc > len) { + // The pkt is larger than the buffer. We don't have complete packet. + // It shall not happen unless the MTU is mis-match. Drop the packet. + LOG_ERR(ENOSPC, "Received a too large packet (%d bytes > %d) from the " + "tap interface. Drop it...", rc, len); + return -ENOSPC; + } else { + LOG_VER("Recv a packet of %d bytes from %s", rc, intf->oi_name); + return rc; + } +} + +int oob_intf_send(const oob_intf *intf, const char *buf, int len) { + int rc; + do { + rc = write(intf->oi_fd, buf, len); + } while (rc == -1 && errno == EINTR); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to send on interface fd %d", intf->oi_fd); + return -rc; + } else if (rc < len) { + LOG_ERR(EIO, "Failed to send the full packet (%d bytes > %d) for fd %d", + len, rc, intf->oi_fd); + return -EIO; + } else { + LOG_VER("Sent a packet of %d bytes to %s", rc, intf->oi_name); + return rc; + } +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/intf.h b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/intf.h new file mode 100644 index 0000000..6ea7af1 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/intf.h @@ -0,0 +1,31 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef INTF_H +#define INTF_H + +#include <stdint.h> + +typedef struct oob_intf_t oob_intf; + +oob_intf* oob_intf_create(const char *name, const uint8_t mac[6]); +int oob_intf_get_fd(const oob_intf *intf); + +int oob_intf_receive(const oob_intf *intf, char *buf, int len); +int oob_intf_send(const oob_intf *intf, const char *buf, int len); + +#endif diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/libnetlink.c b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/libnetlink.c new file mode 100644 index 0000000..019e2c8 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/libnetlink.c @@ -0,0 +1,717 @@ +/* + * Note: Original file from iproute2 package + * + * libnetlink.c RTnetlink service routines. + * + * 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. + * + * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <syslog.h> +#include <fcntl.h> +#include <net/if_arp.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <string.h> +#include <errno.h> +#include <time.h> +#include <sys/uio.h> + +#include "libnetlink.h" + +int rcvbuf = 1024 * 1024; + +void rtnl_close(struct rtnl_handle *rth) +{ + if (rth->fd >= 0) { + close(rth->fd); + rth->fd = -1; + } +} + +int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, + int protocol) +{ + socklen_t addr_len; + int sndbuf = 32768; + + memset(rth, 0, sizeof(*rth)); + + rth->fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol); + if (rth->fd < 0) { + perror("Cannot open netlink socket"); + return -1; + } + + if (setsockopt(rth->fd,SOL_SOCKET,SO_SNDBUF,&sndbuf,sizeof(sndbuf)) < 0) { + perror("SO_SNDBUF"); + return -1; + } + + if (setsockopt(rth->fd,SOL_SOCKET,SO_RCVBUF,&rcvbuf,sizeof(rcvbuf)) < 0) { + perror("SO_RCVBUF"); + return -1; + } + + memset(&rth->local, 0, sizeof(rth->local)); + rth->local.nl_family = AF_NETLINK; + rth->local.nl_groups = subscriptions; + + if (bind(rth->fd, (struct sockaddr*)&rth->local, sizeof(rth->local)) < 0) { + perror("Cannot bind netlink socket"); + return -1; + } + addr_len = sizeof(rth->local); + if (getsockname(rth->fd, (struct sockaddr*)&rth->local, &addr_len) < 0) { + perror("Cannot getsockname"); + return -1; + } + if (addr_len != sizeof(rth->local)) { + fprintf(stderr, "Wrong address length %d\n", addr_len); + return -1; + } + if (rth->local.nl_family != AF_NETLINK) { + fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family); + return -1; + } + rth->seq = time(NULL); + return 0; +} + +int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions) +{ + return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE); +} + +int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type) +{ + return rtnl_wilddump_req_filter(rth, family, type, RTEXT_FILTER_VF); +} + +int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int family, int type, + __u32 filt_mask) +{ + struct { + struct nlmsghdr nlh; + struct ifinfomsg ifm; + /* attribute has to be NLMSG aligned */ + struct rtattr ext_req __attribute__ ((aligned(NLMSG_ALIGNTO))); + __u32 ext_filter_mask; + } req; + + memset(&req, 0, sizeof(req)); + req.nlh.nlmsg_len = sizeof(req); + req.nlh.nlmsg_type = type; + req.nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = rth->dump = ++rth->seq; + req.ifm.ifi_family = family; + + req.ext_req.rta_type = IFLA_EXT_MASK; + req.ext_req.rta_len = RTA_LENGTH(sizeof(__u32)); + req.ext_filter_mask = filt_mask; + + return send(rth->fd, (void*)&req, sizeof(req), 0); +} + +int rtnl_send(struct rtnl_handle *rth, const void *buf, int len) +{ + return send(rth->fd, buf, len, 0); +} + +int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int len) +{ + struct nlmsghdr *h; + int status; + char resp[1024]; + + status = send(rth->fd, buf, len, 0); + if (status < 0) + return status; + + /* Check for immediate errors */ + status = recv(rth->fd, resp, sizeof(resp), MSG_DONTWAIT|MSG_PEEK); + if (status < 0) { + if (errno == EAGAIN) + return 0; + return -1; + } + + for (h = (struct nlmsghdr *)resp; NLMSG_OK(h, status); + h = NLMSG_NEXT(h, status)) { + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); + if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) + fprintf(stderr, "ERROR truncated\n"); + else + errno = -err->error; + return -1; + } + } + + return 0; +} + +int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) +{ + struct nlmsghdr nlh; + struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK }; + struct iovec iov[2] = { + { .iov_base = &nlh, .iov_len = sizeof(nlh) }, + { .iov_base = req, .iov_len = len } + }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = iov, + .msg_iovlen = 2, + }; + + nlh.nlmsg_len = NLMSG_LENGTH(len); + nlh.nlmsg_type = type; + nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST; + nlh.nlmsg_pid = 0; + nlh.nlmsg_seq = rth->dump = ++rth->seq; + + return sendmsg(rth->fd, &msg, 0); +} + +int rtnl_dump_filter_l(struct rtnl_handle *rth, + const struct rtnl_dump_filter_arg *arg) +{ + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char buf[16384]; + int dump_intr = 0; + + iov.iov_base = buf; + while (1) { + int status; + const struct rtnl_dump_filter_arg *a; + int found_done = 0; + int msglen = 0; + + iov.iov_len = sizeof(buf); + status = recvmsg(rth->fd, &msg, 0); + + if (status < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + fprintf(stderr, "netlink receive error %s (%d)\n", + strerror(errno), errno); + return -1; + } + + if (status == 0) { + fprintf(stderr, "EOF on netlink\n"); + return -1; + } + + for (a = arg; a->filter; a++) { + struct nlmsghdr *h = (struct nlmsghdr*)buf; + msglen = status; + + while (NLMSG_OK(h, msglen)) { + int err; + + if (nladdr.nl_pid != 0 || + h->nlmsg_pid != rth->local.nl_pid || + h->nlmsg_seq != rth->dump) + goto skip_it; + + if (h->nlmsg_flags & NLM_F_DUMP_INTR) + dump_intr = 1; + + if (h->nlmsg_type == NLMSG_DONE) { + found_done = 1; + break; /* process next filter */ + } + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); + if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr))) { + fprintf(stderr, + "ERROR truncated\n"); + } else { + errno = -err->error; + perror("RTNETLINK answers"); + } + return -1; + } + err = a->filter(&nladdr, h, a->arg1); + if (err < 0) + return err; + +skip_it: + h = NLMSG_NEXT(h, msglen); + } + } + + if (found_done) { + if (dump_intr) + fprintf(stderr, + "Dump was interrupted and may be inconsistent.\n"); + return 0; + } + + if (msg.msg_flags & MSG_TRUNC) { + fprintf(stderr, "Message truncated\n"); + continue; + } + if (msglen) { + fprintf(stderr, "!!!Remnant of size %d\n", msglen); + exit(1); + } + } +} + +int rtnl_dump_filter(struct rtnl_handle *rth, + rtnl_filter_t filter, + void *arg1) +{ + const struct rtnl_dump_filter_arg a[2] = { + { .filter = filter, .arg1 = arg1, }, + { .filter = NULL, .arg1 = NULL, }, + }; + + return rtnl_dump_filter_l(rth, a); +} + +int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + unsigned groups, struct nlmsghdr *answer) +{ + int status; + unsigned seq; + struct nlmsghdr *h; + struct sockaddr_nl nladdr; + struct iovec iov = { + .iov_base = (void*) n, + .iov_len = n->nlmsg_len + }; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char buf[16384]; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + nladdr.nl_pid = peer; + nladdr.nl_groups = groups; + + n->nlmsg_seq = seq = ++rtnl->seq; + + if (answer == NULL) + n->nlmsg_flags |= NLM_F_ACK; + + status = sendmsg(rtnl->fd, &msg, 0); + + if (status < 0) { + perror("Cannot talk to rtnetlink"); + return -1; + } + + memset(buf,0,sizeof(buf)); + + iov.iov_base = buf; + + while (1) { + iov.iov_len = sizeof(buf); + status = recvmsg(rtnl->fd, &msg, 0); + + if (status < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + fprintf(stderr, "netlink receive error %s (%d)\n", + strerror(errno), errno); + return -1; + } + if (status == 0) { + fprintf(stderr, "EOF on netlink\n"); + return -1; + } + if (msg.msg_namelen != sizeof(nladdr)) { + fprintf(stderr, "sender address length == %d\n", msg.msg_namelen); + exit(1); + } + for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { + int len = h->nlmsg_len; + int l = len - sizeof(*h); + + if (l < 0 || len>status) { + if (msg.msg_flags & MSG_TRUNC) { + fprintf(stderr, "Truncated message\n"); + return -1; + } + fprintf(stderr, "!!!malformed message: len=%d\n", len); + exit(1); + } + + if (nladdr.nl_pid != peer || + h->nlmsg_pid != rtnl->local.nl_pid || + h->nlmsg_seq != seq) { + /* Don't forget to skip that message. */ + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + continue; + } + + if (h->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(h); + if (l < sizeof(struct nlmsgerr)) { + fprintf(stderr, "ERROR truncated\n"); + } else { + if (!err->error) { + if (answer) + memcpy(answer, h, h->nlmsg_len); + return 0; + } + + fprintf(stderr, "RTNETLINK answers: %s\n", strerror(-err->error)); + errno = -err->error; + } + return -1; + } + if (answer) { + memcpy(answer, h, h->nlmsg_len); + return 0; + } + + fprintf(stderr, "Unexpected reply!!!\n"); + + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + } + if (msg.msg_flags & MSG_TRUNC) { + fprintf(stderr, "Message truncated\n"); + continue; + } + if (status) { + fprintf(stderr, "!!!Remnant of size %d\n", status); + exit(1); + } + } +} + +int rtnl_listen(struct rtnl_handle *rtnl, + rtnl_filter_t handler, + void *jarg) +{ + int status; + struct nlmsghdr *h; + struct sockaddr_nl nladdr; + struct iovec iov; + struct msghdr msg = { + .msg_name = &nladdr, + .msg_namelen = sizeof(nladdr), + .msg_iov = &iov, + .msg_iovlen = 1, + }; + char buf[8192]; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + nladdr.nl_pid = 0; + nladdr.nl_groups = 0; + + iov.iov_base = buf; + while (1) { + iov.iov_len = sizeof(buf); + status = recvmsg(rtnl->fd, &msg, 0); + + if (status < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + fprintf(stderr, "netlink receive error %s (%d)\n", + strerror(errno), errno); + if (errno == ENOBUFS) + continue; + return -1; + } + if (status == 0) { + fprintf(stderr, "EOF on netlink\n"); + return -1; + } + if (msg.msg_namelen != sizeof(nladdr)) { + fprintf(stderr, "Sender address length == %d\n", msg.msg_namelen); + exit(1); + } + for (h = (struct nlmsghdr*)buf; status >= sizeof(*h); ) { + int err; + int len = h->nlmsg_len; + int l = len - sizeof(*h); + + if (l<0 || len>status) { + if (msg.msg_flags & MSG_TRUNC) { + fprintf(stderr, "Truncated message\n"); + return -1; + } + fprintf(stderr, "!!!malformed message: len=%d\n", len); + exit(1); + } + + err = handler(&nladdr, h, jarg); + if (err < 0) + return err; + + status -= NLMSG_ALIGN(len); + h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); + } + if (msg.msg_flags & MSG_TRUNC) { + fprintf(stderr, "Message truncated\n"); + continue; + } + if (status) { + fprintf(stderr, "!!!Remnant of size %d\n", status); + exit(1); + } + } +} + +int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, + void *jarg) +{ + int status; + struct sockaddr_nl nladdr; + char buf[8192]; + struct nlmsghdr *h = (void*)buf; + + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + nladdr.nl_pid = 0; + nladdr.nl_groups = 0; + + while (1) { + int err, len; + int l; + + status = fread(&buf, 1, sizeof(*h), rtnl); + + if (status < 0) { + if (errno == EINTR) + continue; + perror("rtnl_from_file: fread"); + return -1; + } + if (status == 0) + return 0; + + len = h->nlmsg_len; + l = len - sizeof(*h); + + if (l<0 || len>sizeof(buf)) { + fprintf(stderr, "!!!malformed message: len=%d @%lu\n", + len, ftell(rtnl)); + return -1; + } + + status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl); + + if (status < 0) { + perror("rtnl_from_file: fread"); + return -1; + } + if (status < l) { + fprintf(stderr, "rtnl-from_file: truncated message\n"); + return -1; + } + + err = handler(&nladdr, h, jarg); + if (err < 0) + return err; + } +} + +int addattr(struct nlmsghdr *n, int maxlen, int type) +{ + return addattr_l(n, maxlen, type, NULL, 0); +} + +int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data) +{ + return addattr_l(n, maxlen, type, &data, sizeof(__u8)); +} + +int addattr16(struct nlmsghdr *n, int maxlen, int type, __u16 data) +{ + return addattr_l(n, maxlen, type, &data, sizeof(__u16)); +} + +int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data) +{ + return addattr_l(n, maxlen, type, &data, sizeof(__u32)); +} + +int addattr64(struct nlmsghdr *n, int maxlen, int type, __u64 data) +{ + return addattr_l(n, maxlen, type, &data, sizeof(__u64)); +} + +int addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *str) +{ + return addattr_l(n, maxlen, type, str, strlen(str)+1); +} + +int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, + int alen) +{ + int len = RTA_LENGTH(alen); + struct rtattr *rta; + + if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { + fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",maxlen); + return -1; + } + rta = NLMSG_TAIL(n); + rta->rta_type = type; + rta->rta_len = len; + memcpy(RTA_DATA(rta), data, alen); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); + return 0; +} + +int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) +{ + if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { + fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); + return -1; + } + + memcpy(NLMSG_TAIL(n), data, len); + memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); + return 0; +} + +struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type) +{ + struct rtattr *nest = NLMSG_TAIL(n); + + addattr_l(n, maxlen, type, NULL, 0); + return nest; +} + +int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest) +{ + nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest; + return n->nlmsg_len; +} + +struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, + const void *data, int len) +{ + struct rtattr *start = NLMSG_TAIL(n); + + addattr_l(n, maxlen, type, data, len); + addattr_nest(n, maxlen, type); + return start; +} + +int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *start) +{ + struct rtattr *nest = (void *)start + NLMSG_ALIGN(start->rta_len); + + start->rta_len = (void *)NLMSG_TAIL(n) - (void *)start; + addattr_nest_end(n, nest); + return n->nlmsg_len; +} + +int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) +{ + int len = RTA_LENGTH(4); + struct rtattr *subrta; + + if (RTA_ALIGN(rta->rta_len) + len > maxlen) { + fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",maxlen); + return -1; + } + subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); + subrta->rta_type = type; + subrta->rta_len = len; + memcpy(RTA_DATA(subrta), &data, 4); + rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; + return 0; +} + +int rta_addattr_l(struct rtattr *rta, int maxlen, int type, + const void *data, int alen) +{ + struct rtattr *subrta; + int len = RTA_LENGTH(alen); + + if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { + fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",maxlen); + return -1; + } + subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); + subrta->rta_type = type; + subrta->rta_len = len; + memcpy(RTA_DATA(subrta), data, alen); + rta->rta_len = NLMSG_ALIGN(rta->rta_len) + RTA_ALIGN(len); + return 0; +} + +int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) +{ + return parse_rtattr_flags(tb, max, rta, len, 0); +} + +int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, + int len, unsigned short flags) +{ + unsigned short type; + + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + while (RTA_OK(rta, len)) { + type = rta->rta_type & ~flags; + if ((type <= max) && (!tb[type])) + tb[type] = rta; + rta = RTA_NEXT(rta,len); + } + if (len) + fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); + return 0; +} + +int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len) +{ + int i = 0; + + memset(tb, 0, sizeof(struct rtattr *) * max); + while (RTA_OK(rta, len)) { + if (rta->rta_type <= max && i < max) + tb[i++] = rta; + rta = RTA_NEXT(rta,len); + } + if (len) + fprintf(stderr, "!!!Deficit %d, rta_len=%d\n", len, rta->rta_len); + return i; +} + +int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, + int len) +{ + if (RTA_PAYLOAD(rta) < len) + return -1; + if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) { + rta = RTA_DATA(rta) + RTA_ALIGN(len); + return parse_rtattr_nested(tb, max, rta); + } + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/libnetlink.h b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/libnetlink.h new file mode 100644 index 0000000..9e72692 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/libnetlink.h @@ -0,0 +1,161 @@ +/* + * Note: Original file from iproute2 package + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __LIBNETLINK_H__ +#define __LIBNETLINK_H__ 1 + +#include <stdio.h> +#include <string.h> +#include <asm/types.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> +#include <linux/if_link.h> +#include <linux/if_addr.h> +#include <linux/neighbour.h> +#include <linux/netconf.h> + +struct rtnl_handle +{ + int fd; + struct sockaddr_nl local; + struct sockaddr_nl peer; + __u32 seq; + __u32 dump; +}; + +extern int rcvbuf; + +extern int rtnl_open(struct rtnl_handle *rth, unsigned subscriptions); +extern int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions, int protocol); +extern void rtnl_close(struct rtnl_handle *rth); +extern int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type); +extern int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int fam, int type, + __u32 filt_mask); +extern int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len); + +typedef int (*rtnl_filter_t)(const struct sockaddr_nl *, + struct nlmsghdr *n, void *); + +struct rtnl_dump_filter_arg +{ + rtnl_filter_t filter; + void *arg1; +}; + +extern int rtnl_dump_filter_l(struct rtnl_handle *rth, + const struct rtnl_dump_filter_arg *arg); +extern int rtnl_dump_filter(struct rtnl_handle *rth, rtnl_filter_t filter, + void *arg); +extern int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, pid_t peer, + unsigned groups, struct nlmsghdr *answer); +extern int rtnl_send(struct rtnl_handle *rth, const void *buf, int); +extern int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int); + +extern int addattr(struct nlmsghdr *n, int maxlen, int type); +extern int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data); +extern int addattr16(struct nlmsghdr *n, int maxlen, int type, __u16 data); +extern int addattr32(struct nlmsghdr *n, int maxlen, int type, __u32 data); +extern int addattr64(struct nlmsghdr *n, int maxlen, int type, __u64 data); +extern int addattrstrz(struct nlmsghdr *n, int maxlen, int type, const char *data); + +extern int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen); +extern int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len); +extern struct rtattr *addattr_nest(struct nlmsghdr *n, int maxlen, int type); +extern int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest); +extern struct rtattr *addattr_nest_compat(struct nlmsghdr *n, int maxlen, int type, const void *data, int len); +extern int addattr_nest_compat_end(struct nlmsghdr *n, struct rtattr *nest); +extern int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data); +extern int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen); + +extern int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len); +extern int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, + int len, unsigned short flags); +extern int parse_rtattr_byindex(struct rtattr *tb[], int max, struct rtattr *rta, int len); +extern int __parse_rtattr_nested_compat(struct rtattr *tb[], int max, struct rtattr *rta, int len); + +#define parse_rtattr_nested(tb, max, rta) \ + (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta))) + +#define parse_rtattr_nested_compat(tb, max, rta, data, len) \ + ({ data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \ + __parse_rtattr_nested_compat(tb, max, rta, len); }) + +static inline __u8 rta_getattr_u8(const struct rtattr *rta) +{ + return *(__u8 *)RTA_DATA(rta); +} +static inline __u16 rta_getattr_u16(const struct rtattr *rta) +{ + return *(__u16 *)RTA_DATA(rta); +} +static inline __u32 rta_getattr_u32(const struct rtattr *rta) +{ + return *(__u32 *)RTA_DATA(rta); +} +static inline __u64 rta_getattr_u64(const struct rtattr *rta) +{ + __u64 tmp; + memcpy(&tmp, RTA_DATA(rta), sizeof(__u64)); + return tmp; +} +static inline const char *rta_getattr_str(const struct rtattr *rta) +{ + return (const char *)RTA_DATA(rta); +} + +extern int rtnl_listen(struct rtnl_handle *, rtnl_filter_t handler, + void *jarg); +extern int rtnl_from_file(FILE *, rtnl_filter_t handler, + void *jarg); + +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) + +#ifndef IFA_RTA +#define IFA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) +#endif +#ifndef IFA_PAYLOAD +#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) +#endif + +#ifndef IFLA_RTA +#define IFLA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) +#endif +#ifndef IFLA_PAYLOAD +#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) +#endif + +#ifndef NDA_RTA +#define NDA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#endif +#ifndef NDA_PAYLOAD +#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg)) +#endif + +#ifndef NDTA_RTA +#define NDTA_RTA(r) \ + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndtmsg)))) +#endif +#ifndef NDTA_PAYLOAD +#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg)) +#endif + +#endif /* __LIBNETLINK_H__ */ + diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/ll_map.c b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/ll_map.c new file mode 100644 index 0000000..64e5069 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/ll_map.c @@ -0,0 +1,225 @@ +/* + * Note: Original file from iproute2 package + * + * ll_map.c + * + * 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. + * + * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <syslog.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <string.h> +#include <net/if.h> + +#include "libnetlink.h" +#include "ll_map.h" +#include "hlist.h" + +struct ll_cache { + struct hlist_node idx_hash; + struct hlist_node name_hash; + unsigned flags; + int index; + unsigned short type; + char name[IFNAMSIZ]; +}; + +#define IDXMAP_SIZE 1024 +static struct hlist_head idx_head[IDXMAP_SIZE]; +static struct hlist_head name_head[IDXMAP_SIZE]; + +static struct ll_cache *ll_get_by_index(unsigned index) +{ + struct hlist_node *n; + unsigned h = index & (IDXMAP_SIZE - 1); + + hlist_for_each(n, &idx_head[h]) { + struct ll_cache *im + = container_of(n, struct ll_cache, idx_hash); + if (im->index == index) + return im; + } + + return NULL; +} + +static unsigned namehash(const char *str) +{ + unsigned hash = 5381; + + while (*str) + hash = ((hash << 5) + hash) + *str++; /* hash * 33 + c */ + + return hash; +} + +static struct ll_cache *ll_get_by_name(const char *name) +{ + struct hlist_node *n; + unsigned h = namehash(name) & (IDXMAP_SIZE - 1); + + hlist_for_each(n, &name_head[h]) { + struct ll_cache *im + = container_of(n, struct ll_cache, name_hash); + + if (strncmp(im->name, name, IFNAMSIZ) == 0) + return im; + } + + return NULL; +} + +int ll_remember_index(const struct sockaddr_nl *who, + struct nlmsghdr *n, void *arg) +{ + unsigned int h; + const char *ifname; + struct ifinfomsg *ifi = NLMSG_DATA(n); + struct ll_cache *im; + struct rtattr *tb[IFLA_MAX+1]; + + if (n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) + return 0; + + if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi))) + return -1; + + im = ll_get_by_index(ifi->ifi_index); + if (n->nlmsg_type == RTM_DELLINK) { + if (im) { + hlist_del(&im->name_hash); + hlist_del(&im->idx_hash); + free(im); + } + return 0; + } + + memset(tb, 0, sizeof(tb)); + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n)); + ifname = rta_getattr_str(tb[IFLA_IFNAME]); + if (ifname == NULL) + return 0; + + if (im) { + /* change to existing entry */ + if (strcmp(im->name, ifname) != 0) { + hlist_del(&im->name_hash); + h = namehash(ifname) & (IDXMAP_SIZE - 1); + hlist_add_head(&im->name_hash, &name_head[h]); + } + + im->flags = ifi->ifi_flags; + return 0; + } + + im = malloc(sizeof(*im)); + if (im == NULL) + return 0; + im->index = ifi->ifi_index; + strcpy(im->name, ifname); + im->type = ifi->ifi_type; + im->flags = ifi->ifi_flags; + + h = ifi->ifi_index & (IDXMAP_SIZE - 1); + hlist_add_head(&im->idx_hash, &idx_head[h]); + + h = namehash(ifname) & (IDXMAP_SIZE - 1); + hlist_add_head(&im->name_hash, &name_head[h]); + + return 0; +} + +const char *ll_idx_n2a(unsigned idx, char *buf) +{ + const struct ll_cache *im; + + if (idx == 0) + return "*"; + + im = ll_get_by_index(idx); + if (im) + return im->name; + + if (if_indextoname(idx, buf) == NULL) + snprintf(buf, IFNAMSIZ, "if%d", idx); + + return buf; +} + +const char *ll_index_to_name(unsigned idx) +{ + static char nbuf[IFNAMSIZ]; + + return ll_idx_n2a(idx, nbuf); +} + +int ll_index_to_type(unsigned idx) +{ + const struct ll_cache *im; + + if (idx == 0) + return -1; + + im = ll_get_by_index(idx); + return im ? im->type : -1; +} + +unsigned ll_index_to_flags(unsigned idx) +{ + const struct ll_cache *im; + + if (idx == 0) + return 0; + + im = ll_get_by_index(idx); + return im ? im->flags : -1; +} + +unsigned ll_name_to_index(const char *name) +{ + const struct ll_cache *im; + unsigned idx; + + if (name == NULL) + return 0; + + im = ll_get_by_name(name); + if (im) + return im->index; + + idx = if_nametoindex(name); + if (idx == 0) + sscanf(name, "if%u", &idx); + return idx; +} + +void ll_init_map(struct rtnl_handle *rth) +{ + static int initialized; + + if (initialized) + return; + + if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) { + perror("Cannot send dump request"); + exit(1); + } + + if (rtnl_dump_filter(rth, ll_remember_index, NULL) < 0) { + fprintf(stderr, "Dump terminated\n"); + exit(1); + } + + initialized = 1; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/ll_map.h b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/ll_map.h new file mode 100644 index 0000000..d74a46f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/ll_map.h @@ -0,0 +1,32 @@ +/* + * Note: Original file from iproute2 package + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __LL_MAP_H__ +#define __LL_MAP_H__ 1 + +extern int ll_remember_index(const struct sockaddr_nl *who, + struct nlmsghdr *n, void *arg); + +extern void ll_init_map(struct rtnl_handle *rth); +extern unsigned ll_name_to_index(const char *name); +extern const char *ll_index_to_name(unsigned idx); +extern const char *ll_idx_n2a(unsigned idx, char *buf); +extern int ll_index_to_type(unsigned idx); +extern unsigned ll_index_to_flags(unsigned idx); + +#endif /* __LL_MAP_H__ */ diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/main.c b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/main.c new file mode 100644 index 0000000..4312402 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/main.c @@ -0,0 +1,192 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include <stdio.h> +#include <unistd.h> +#include <sys/select.h> +#include <sys/time.h> +#include <sys/errno.h> + +#include "nic.h" +#include "intf.h" + +#include "facebook/log.h" +#include "facebook/wedge_eeprom.h" + +#define WAIT4PACKET_TIMEOUT 10000 /* 10ms */ +#define NO_RCV_CHECK_THRESHOLD 100 /* if not receiving pkt for 100 times (1s), + * check the NIC status + */ + +static void io_loop(oob_nic *nic, oob_intf *intf, const uint8_t mac[6]) { + + fd_set rfds; + int fd = oob_intf_get_fd(intf); + struct timeval timeout; + int rc; + int n_fds; + int n_io; + char buf[NIC_PKT_SIZE_MAX]; + int no_rcv = 0; + struct oob_nic_status_t sts; + + while (1) { + memset(&timeout, 0, sizeof(timeout)); + timeout.tv_sec = 0; + timeout.tv_usec = WAIT4PACKET_TIMEOUT; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + n_fds = select(fd + 1, &rfds, NULL, NULL, &timeout); + if (n_fds < 0) { + rc = errno; + LOG_ERR(rc, "Failed to select"); + continue; + } + + /* + * no matter what, receive packet from nic first, as the nic + * has small amount of memory. Without read, the sending could + * fail due to OOM. + * + * TODO: We might want to do something smart here to prevent attack or + * just rx flooding. Disable the Receive Enable first, drain the buffer + * with oob_nic_receive(), then Tx, and enable Receive Enable after. + */ + for (n_io = 0; n_io < 16; n_io++) { + rc = oob_nic_receive(nic, buf, sizeof(buf)); + if (rc <= 0) { + no_rcv++; + break; + } + oob_intf_send(intf, buf, rc); + no_rcv = 0; + } + + /* + * if we didn't receive any packet for NO_RCV_CHECK_THRESHOLD times, + * check the nic status + */ + if (no_rcv >= NO_RCV_CHECK_THRESHOLD) { + while(oob_nic_get_status(nic, &sts)) { + usleep(1000); + } + LOG_INFO("Failed to receive packets for %d times. NIC status is " + "%x.%x", NO_RCV_CHECK_THRESHOLD, sts.ons_byte1, sts.ons_byte2); + /* + * if the NIC went through initialization, or not set force up, need to + * re-program the filters by calling oob_nic_start(). + */ + if ((sts.ons_byte1 & NIC_STATUS_D1_INIT) + || !(sts.ons_byte1 & NIC_STATUS_D1_FORCE_UP)) { + while(oob_nic_start(nic, mac)) { + usleep(1000); + } + } + no_rcv = 0; + } + + if (n_fds > 0 && FD_ISSET(fd, &rfds)) { + for (n_io = 0; n_io < 1; n_io++) { + rc = oob_intf_receive(intf, buf, sizeof(buf)); + if (rc <= 0) { + break; + } + oob_nic_send(nic, buf, rc); + } + } + } +} + +int main(int argc, const char **argv) { + + uint8_t mac[6]; + oob_nic *nic; + oob_intf *intf; + struct wedge_eeprom_st eeprom; + int rc; + int from_eeprom = 0; + + nic = oob_nic_open(0, 0x49); + if (!nic) { + return -1; + } + + /* read EEPROM for the MAC */ + if (wedge_eeprom_parse(NULL, &eeprom) == 0) { + if (eeprom.fbw_mac_size <= 0) { + LOG_ERR(EFAULT, "Invalid extended MAC size: %d", eeprom.fbw_mac_size); + } else { + uint16_t carry; + int pos; + /* use the last MAC address from the extended MAC range */ + memcpy(mac, eeprom.fbw_mac_base, sizeof(mac)); + if (eeprom.fbw_mac_size > 128) { + LOG_ERR(EFAULT, "Extended MAC size (%d) is too large.", + eeprom.fbw_mac_size); + carry = 127; + } else { + /* + * hack around bug device which have the same MAC address on + * left and right. + */ + if (strncmp(eeprom.fbw_location, "LEFT", FBW_EEPROM_F_LOCATION) == 0) { + carry = eeprom.fbw_mac_size - 2; + } else { + carry = eeprom.fbw_mac_size - 1; + } + } + for (pos = sizeof(mac) - 1; pos >= 0 && carry; pos--) { + uint16_t tmp = mac[pos] + carry; + mac[pos] = tmp & 0xFF; + carry = tmp >> 8; + } + from_eeprom = 1; + } + } + + if (!from_eeprom) { + while (oob_nic_get_mac(nic, mac)) { + usleep(1000); + } + /* + * increase the last byte of the mac by 1 and turn on the + * local administered bit to use it as the oob nic mac + */ + mac[0] |= 0x2; + mac[5]++; + } + + LOG_INFO("Retrieve MAC %x:%x:%x:%x:%x:%x from %s", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + (from_eeprom) ? "EEPROM" : "NIC"); + + /* create the tap interface */ + intf = oob_intf_create("oob", mac); + if (!intf) { + return -1; + } + + while (oob_nic_start(nic, mac)) { + usleep(1000); + } + + io_loop(nic, intf, mac); + + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/nic.c b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/nic.c new file mode 100644 index 0000000..a4dc071 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/nic.c @@ -0,0 +1,487 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "nic.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "facebook/i2c-dev.h" +#include "facebook/log.h" + +struct oob_nic_t { + int on_bus; + uint8_t on_addr; + int on_file; /* the file descriptor */ + uint8_t on_mac[6]; /* the mac address assigned to this NIC */ +}; + +oob_nic* oob_nic_open(int bus, uint8_t addr) { + oob_nic *dev = NULL; + char fn[32]; + int rc; + + /* address must be 7 bits maximum */ + if ((addr & 0x80)) { + LOG_ERR(EINVAL, "Address 0x%x has the 8th bit", addr); + return NULL; + } + + dev = calloc(1, sizeof(*dev)); + if (!dev) { + return NULL; + } + dev->on_bus = bus; + dev->on_addr = addr; + + /* construct the device file name */ + snprintf(fn, sizeof(fn), "/dev/i2c-%d", bus); + dev->on_file = open(fn, O_RDWR); + if (dev->on_file == -1) { + LOG_ERR(errno, "Failed to open i2c device %s", fn); + goto err_out; + } + + /* assign the device address */ + rc = ioctl(dev->on_file, I2C_SLAVE, dev->on_addr); + if (rc < 0) { + LOG_ERR(errno, "Failed to open slave @ address 0x%x", dev->on_addr); + goto err_out; + } + + return dev; + + err_out: + oob_nic_close(dev); + return NULL; +} + +void oob_nic_close(oob_nic *dev) { + if (!dev) { + return; + } + if (dev->on_file != -1) { + close(dev->on_file); + } + free(dev); +} + +int oob_nic_get_mac(oob_nic *dev, uint8_t mac[6]) { + int rc; + uint8_t buf[64]; + + rc = i2c_smbus_read_block_data(dev->on_file, NIC_READ_MAC_CMD, buf); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to get MAC on %d-%x", + dev->on_bus, dev->on_addr); + return -rc; + } + + if (rc != NIC_READ_MAC_RES_LEN) { + LOG_ERR(EFAULT, "Unexpected response len (%d) for get MAC on %d-%x", + rc, dev->on_bus, dev->on_addr); + return -EFAULT; + } + + if (buf[0] != NIC_READ_MAC_RES_OPT) { + LOG_ERR(EFAULT, "Unexpected response opt code (0x%x) get MAC on %d-%x", + buf[0], dev->on_bus, dev->on_addr); + return -EFAULT; + } + + memcpy(mac, &buf[1], 6); + + LOG_DBG("Get MAC on %d-%x: %x:%x:%x:%x:%x:%x", dev->on_bus, dev->on_addr, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return 0; +} + +int oob_nic_get_status(oob_nic *dev, oob_nic_status *status) { + int rc; + uint8_t buf[64]; + + rc = i2c_smbus_read_block_data(dev->on_file, NIC_READ_STATUS_CMD, buf); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to get status on %d-%x", + dev->on_bus, dev->on_addr); + return -rc; + } + + if (rc != NIC_READ_STATUS_RES_LEN) { + LOG_ERR(EFAULT, "Unexpected response len (%d) for get status on %d-%x", + rc, dev->on_bus, dev->on_addr); + return -EFAULT; + } + + if (buf[0] != NIC_READ_STATUS_RES_OPT) { + LOG_ERR(EFAULT, "Unexpected response opt code (0x%x) get status on %d-%x", + buf[0], dev->on_bus, dev->on_addr); + return -EFAULT; + } + + memset(status, 0, sizeof(*status)); + status->ons_byte1 = buf[1]; + status->ons_byte2 = buf[2]; + + LOG_VER("Get status on %d-%x: byte1:0x%x byte2:0x%x", + dev->on_bus, dev->on_addr, + status->ons_byte1, status->ons_byte2); + return 0; +} + +int oob_nic_receive(oob_nic *dev, uint8_t *buf, int len) { + + int rc = 0; + uint8_t pkt[I2C_SMBUS_BLOCK_LARGE_MAX]; + uint8_t opt; + int copied = 0; + int to_copy; + int expect_first = 1; + int n_frags = 0; + +#define _COPY_DATA(n, data) do { \ + int to_copy; \ + if (copied >= len) { \ + break; \ + } \ + to_copy = (n < len - copied) ? n : len - copied; \ + if (to_copy) { \ + memcpy(buf + copied, data, to_copy); \ + } \ + copied += to_copy; \ +} while(0) + + do { + rc = i2c_smbus_read_block_large_data(dev->on_file, NIC_READ_PKT_CMD, pkt); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to get packet on %d-%x", + dev->on_bus, dev->on_addr); + goto err_out; + } + if (rc > I2C_SMBUS_BLOCK_LARGE_MAX) { + LOG_ERR(EFAULT, "Too large i2c block (%d) received on %d-%x", + rc, dev->on_bus, dev->on_addr); + rc = EFAULT; + goto err_out; + } + opt = pkt[0]; + switch (opt) { + case NIC_READ_PKT_RES_FIRST_OPT: + if (!expect_first) { + rc = EFAULT; + LOG_ERR(rc, "Received more than one buffer with FIRST set"); + goto err_out; + } + expect_first = 0; + n_frags++; + _COPY_DATA(rc - 1, &pkt[1]); + break; + case NIC_READ_PKT_RES_MIDDLE_OPT: + if (expect_first) { + rc = EFAULT; + LOG_ERR(rc, "Received MIDDLE before getting FIRST"); + goto err_out; + } + _COPY_DATA(rc - 1, &pkt[1]); + n_frags++; + break; + case NIC_READ_PKT_RES_LAST_OPT: + if (expect_first) { + rc = EFAULT; + LOG_ERR(rc, "Received LAST before getting FIRST"); + goto err_out; + } + if (rc != NIC_READ_PKT_RES_LAST_LEN) { + LOG_ERR(EFAULT, "Expect %d bytes (got %d) for LAST segement", + NIC_READ_PKT_RES_LAST_LEN, rc); + rc = EFAULT; + goto err_out; + } + /* TODO: pkt status???? */ + break; + case NIC_READ_STATUS_RES_OPT: + /* that means no pkt available */ + if (!expect_first) { + rc = EFAULT; + LOG_ERR(rc, "Received STATUS in the middle of packet"); + goto err_out; + } + //LOG_VER("Received STATUS when receiving the packet"); + return 0; + default: + rc = EFAULT; + LOG_ERR(rc, "Unexpected opt code 0x%x", opt); + goto err_out; + } + } while (opt != NIC_READ_PKT_RES_LAST_OPT); + + LOG_VER("Received a packet with %d bytes in %d fragments", copied, n_frags); + return copied; + + err_out: + return -rc; +#undef _COPY_DATA +} + +int oob_nic_send(oob_nic *dev, const uint8_t *data, int len) { + + int rc; + uint8_t to_send; + int has_sent = 0; + int is_first = 1; + uint8_t cmd; + int n_frags = 0; + + if (len <= 0 || len > NIC_PKT_SIZE_MAX) { + rc = EINVAL; + LOG_ERR(rc, "Invalid packet length %d", len); + return -rc; + } + + while (len) { + to_send = (len < OOB_NIC_PKT_FRAGMENT_SIZE) + ? len : OOB_NIC_PKT_FRAGMENT_SIZE; + + if (is_first) { + if (to_send >= len) { + /* this is the last pkt also */ + cmd = NIC_WRITE_PKT_SINGLE_CMD; + } else { + cmd = NIC_WRITE_PKT_FIRST_CMD; + } + is_first = 0; + } else { + if (to_send >= len) { + /* this is the last pkt */ + cmd = NIC_WRITE_PKT_LAST_CMD; + } else { + cmd = NIC_WRITE_PKT_MIDDLE_CMD; + } + } + + rc = i2c_smbus_write_block_large_data(dev->on_file, cmd, + to_send, data + has_sent); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to sent packet with cmd 0x%x, has_sent=%d " + "to_send=%d", cmd, has_sent, to_send); + return -rc; + } + + has_sent += to_send; + len -= to_send; + n_frags++; + } + + LOG_VER("Sent a packet with %d bytes in %d fragments", has_sent, n_frags); + + return has_sent; +} + +static int oob_nic_set_mng_ctrl(oob_nic *dev, const uint8_t *data, int len) { + int rc; + + if (len <= 0) { + rc = EINVAL; + LOG_ERR(rc, "Invalid data length: %d", len); + return -rc; + } + + rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_MNG_CTRL_CMD, + len, data); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to send management control command for parameter # %d", + data[0]); + return -rc; + } + + return 0; +} + +static int oob_nic_set_force_up(oob_nic *dev, int enable) { + uint8_t cmd[2]; + + cmd[0] = NIC_MNG_CTRL_KEEP_LINK_UP_NUM; + cmd[1] = enable + ? NIC_MNG_CTRL_KEEP_LINK_UP_ENABLE : NIC_MNG_CTRL_KEEP_LINK_UP_DISABLE; + + LOG_DBG("Turn %s link force up", enable ? "on" : "off"); + return oob_nic_set_mng_ctrl(dev, cmd, sizeof(cmd)); +} + +static int oob_nic_setup_filters(oob_nic *dev, const uint8_t mac[6]) { + int rc; + int i; + uint32_t cmd32; + uint8_t buf[32]; + uint8_t *cmd; + + /* + * Command to set MAC filter + * Seven bytes are required to load the MAC address filters. + * Data 2—MAC address filters pair number (3:0). + * Data 3—MSB of MAC address. + * ... + * Data 8: LSB of MAC address. + */ + /* set MAC filter to pair 0 */ + cmd = buf; + *cmd++ = NIC_FILTER_MAC_NUM; + *cmd++ = NIC_FILTER_MAC_PAIR0; /* pair 0 */ + for (i = 0; i < 6; i++) { + *cmd++ = mac[i]; + } + rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD, + cmd - buf, buf); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to set MAC filter"); + return -rc; + } + + /* + * Command to enable filter + * + * 9 bytes to load the extended decision filters (MDEF_EXT & MDEF) + * Data 2—MDEF filter index (valid values are 0...6) + * Data 3—MSB of MDEF_EXT (DecisionFilter0) + * .... + * Data 6—LSB of MDEF_EXT (DecisionFilter0) + * Data 7—MSB of MDEF (DecisionFilter0) + * .... + * Data 10—LSB of MDEF (DecisionFilter0) + */ + + /* enable MAC filter pair 0 on filter 0 */ + cmd = buf; + *cmd++ = NIC_FILTER_DECISION_EXT_NUM; + *cmd++ = NIC_FILTER_MDEF0; + /* enable filter for traffic from network and host */ + cmd32 = NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_NET_EN_OFFSET) + | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET); + for (i = 0; i < sizeof(cmd32); i++) { + *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; + } + /* enable mac pair 0 */ + cmd32 = NIC_FILTER_MDEF_BIT_VAL(NIC_FILTER_MDEF_MAC_AND_OFFSET, + NIC_FILTER_MAC_PAIR0); + for (i = 0; i < sizeof(cmd32); i++) { + *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; + } + rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD, + cmd - buf, buf); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to set MAC filter to MDEF 0"); + return -rc; + } + /* enable ARP and ND on filter 1*/ + cmd = buf; + *cmd++ = NIC_FILTER_DECISION_EXT_NUM; + *cmd++ = NIC_FILTER_MDEF1; + /* enable filter for traffic from network and host */ + cmd32 = NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_NET_EN_OFFSET) + | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET); + for (i = 0; i < sizeof(cmd32); i++) { + *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; + } + /* enable ARP and ND */ + cmd32 = NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_ARP_REQ_OR_OFFSET) + | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_ARP_RES_OR_OFFSET) + | NIC_FILTER_MDEF_BIT(NIC_FILTER_MDEF_NBG_OR_OFFSET); + for (i = 0; i < sizeof(cmd32); i++) { + *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; + } + rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD, + cmd - buf, buf); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to set ARP and ND filter to MDEF 1"); + return -rc; + } + + /* make filter 0, matching MAC, to be mng only */ + cmd = buf; + *cmd++ = NIC_FILTER_MNG_ONLY_NUM; + cmd32 = NIC_FILTER_MNG_ONLY_FILTER0; + for (i = 0; i < sizeof(cmd32); i++) { + *cmd++ = (cmd32 >> (24 - 8 * i)) & 0xFF; + } + rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_FILTER_CMD, + cmd - buf, buf); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to enabled management only filter"); + return -rc; + } + + return 0; +} + +int oob_nic_start(oob_nic *dev, const uint8_t mac[6]) { + int rc; + uint8_t cmd; + + /* force the link up, no matter what the status of the main link */ + rc = oob_nic_set_force_up(dev, 1); + if (rc != 0) { + return rc; + } + + oob_nic_setup_filters(dev, mac); + + /* first byte is the control */ + cmd = NIC_WRITE_RECV_ENABLE_EN + | NIC_WRITE_RECV_ENABLE_STA + | NIC_WRITE_RECV_ENABLE_NM_UNSUPP /* TODO, to support ALERT */ + | NIC_WRITE_RECV_ENABLE_RESERVED; + + rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_RECV_ENABLE_CMD, + 1, &cmd); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to start receive function"); + return -rc; + } + LOG_DBG("Started receive function"); + return 0; +} + +int oob_nic_stop(oob_nic *dev) { + int rc; + uint8_t ctrl; + /* don't set any enable bits, which turns off the receive func */ + ctrl = NIC_WRITE_RECV_ENABLE_RESERVED; + rc = i2c_smbus_write_block_data(dev->on_file, NIC_WRITE_RECV_ENABLE_CMD, + 1, &ctrl); + if (rc < 0) { + rc = errno; + LOG_ERR(rc, "Failed to stop receive function"); + return -rc; + } + LOG_DBG("Stopped receive function"); + return 0; +} diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/nic.h b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/nic.h new file mode 100644 index 0000000..1ac7ff8 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/nic.h @@ -0,0 +1,44 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef NIC_H +#define NIC_H + +#include <stdint.h> + +#include "nic_defs.h" + +typedef struct oob_nic_t oob_nic; + +oob_nic* oob_nic_open(int bus, uint8_t addr); +void oob_nic_close(oob_nic* dev); + +/* MAC */ +int oob_nic_get_mac(oob_nic *dev, uint8_t mac[6]); + +/* Status */ +typedef struct oob_nic_status_t oob_nic_status; +int oob_nic_get_status(oob_nic *dev, oob_nic_status *status); + +int oob_nic_start(oob_nic *dev, const uint8_t mac[6]); +int oob_nic_stop(oob_nic *dev); + +int oob_nic_send(oob_nic *dev, const uint8_t *data, int len); + +int oob_nic_receive(oob_nic *dev, uint8_t *buf, int len); + +#endif diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/nic_defs.h b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/nic_defs.h new file mode 100644 index 0000000..1ae8721 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic/src/nic_defs.h @@ -0,0 +1,143 @@ +/* + * Copyright 2014-present Facebook. All Rights Reserved. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef NIC_DEFS_H +#define NIC_DEFS_H + +#include <stdint.h> + +#define OOB_NIC_PKT_FRAGMENT_SIZE 240 +#define NIC_PKT_SIZE_MAX 1536 + +/** Get System MAC Address */ +#define NIC_READ_MAC_CMD 0xD4 +#define NIC_READ_MAC_RES_OPT 0xD4 +#define NIC_READ_MAC_RES_LEN 7 + +/** Read Status */ +#define NIC_READ_STATUS_CMD 0xDE +#define NIC_READ_STATUS_RES_OPT 0xDD +#define NIC_READ_STATUS_RES_LEN 3 + +struct oob_nic_status_t { + uint8_t ons_byte1; + uint8_t ons_byte2; +}; + +#define NIC_STATUS_D1_POWER_DR 0x00 +#define NIC_STATUS_D1_POWER_D0U 0x01 +#define NIC_STATUS_D1_POWER_D0 0x10 +#define NIC_STATUS_D1_POWER_D3 0x11 +#define NIC_STATUS_D1_PORT_MSB (0x1 << 2) +#define NIC_STATUS_D1_INIT (0x1 << 3) +#define NIC_STATUS_D1_FORCE_UP (0x1 << 4) +#define NIC_STATUS_D1_LINK (0x1 << 5) +#define NIC_STATUS_D1_TCO_CMD_ABORT (0x1 << 6) +#define NIC_STATUS_D1_PORT_LSB (0x1 << 7) + +#define NIC_STATUS_D2_ICR (0x1 << 1) +#define NIC_STATUS_D2_IPI (0x1 << 2) +#define NIC_STATUS_D2_DRV_VALID (0x1 << 3) + +/** Receive TCO Packet */ +#define NIC_READ_PKT_CMD 0xC0 +#define NIC_READ_PKT_RES_FIRST_OPT 0x90 +#define NIC_READ_PKT_RES_MIDDLE_OPT 0x10 +#define NIC_READ_PKT_RES_LAST_OPT 0x50 +#define NIC_READ_PKT_RES_LAST_LEN 17 + +/** Transmit Packet */ +#define NIC_WRITE_PKT_SINGLE_CMD 0xC4 +#define NIC_WRITE_PKT_FIRST_CMD 0x84 +#define NIC_WRITE_PKT_MIDDLE_CMD 0x04 +#define NIC_WRITE_PKT_LAST_CMD 0x44 + +/** Management Control */ +#define NIC_WRITE_MNG_CTRL_CMD 0xC1 + +#define NIC_MNG_CTRL_KEEP_LINK_UP_NUM 0x00 +#define NIC_MNG_CTRL_KEEP_LINK_UP_ENABLE 0x01 +#define NIC_MNG_CTRL_KEEP_LINK_UP_DISABLE 0x00 + +/** Update MNG RCV Filter Parameters */ +#define NIC_WRITE_FILTER_CMD 0xCC + +#define NIC_FILTER_MAC_NUM 0x66 +#define NIC_FILTER_MAC_PAIR0 0 +#define NIC_FILTER_MAC_PAIR1 1 +#define NIC_FILTER_MAC_PAIR2 2 +#define NIC_FILTER_MAC_PAIR3 3 + +#define NIC_FILTER_MNG_ONLY_NUM 0xF +#define NIC_FILTER_MNG_ONLY_FILTER0 (0x1) +#define NIC_FILTER_MNG_ONLY_FILTER1 (0x1 << 1) +#define NIC_FILTER_MNG_ONLY_FILTER2 (0x1 << 2) +#define NIC_FILTER_MNG_ONLY_FILTER3 (0x1 << 3) +#define NIC_FILTER_MNG_ONLY_FILTER4 (0x1 << 4) + +#define NIC_FILTER_DECISION_EXT_NUM 0x68 +#define NIC_FILTER_MDEF0 0 /* index 0 */ +#define NIC_FILTER_MDEF1 1 /* index 1 */ +#define NIC_FILTER_MDEF2 2 /* index 2 */ +#define NIC_FILTER_MDEF3 3 /* index 3 */ +#define NIC_FILTER_MDEF4 4 /* index 4 */ +#define NIC_FILTER_MDEF5 5 /* index 5 */ +#define NIC_FILTER_MDEF6 6 /* index 6 */ +#define NIC_FILTER_MDEF7 7 /* index 7 */ + +#define NIC_FILTER_MDEF_MAC_AND_OFFSET 0 +#define NIC_FILTER_MDEF_BCAST_AND_OFFSET 4 +#define NIC_FILTER_MDEF_VLAN_AND_OFFSET 5 +#define NIC_FILTER_MDEF_IPV4_AND_OFFSET 13 +#define NIC_FILTER_MDEF_IPV6_AND_OFFSET 17 +#define NIC_FILTER_MDEF_MAC_OR_OFFSET 21 +#define NIC_FILTER_MDEF_BCAST_OR_OFFSET 25 +#define NIC_FILTER_MDEF_MCAST_AND_OFFSET 26 +#define NIC_FILTER_MDEF_ARP_REQ_OR_OFFSET 27 +#define NIC_FILTER_MDEF_ARP_RES_OR_OFFSET 28 +#define NIC_FILTER_MDEF_NBG_OR_OFFSET 29 +#define NIC_FILTER_MDEF_PORT298_OR_OFFSET 30 +#define NIC_FILTER_MDEF_PORT26F_OR_OFFSET 31 + +#define NIC_FILTER_MDEF_EXT_ETHTYPE_AND_OFFSET 0 +#define NIC_FILTER_MDEF_EXT_ETHTYPE_OR_OFFSET 8 +#define NIC_FILTER_MDEF_EXT_FLEX_PORT_OR_OFFSET 16 +#define NIC_FILTER_MDEF_EXT_FLEX_TCO_OR_OFFSET 24 +#define NIC_FILTER_MDEF_EXT_NCSI_DISABLE_OFFSET 28 +#define NIC_FILTER_MDEF_EXT_FLOW_CONTROL_DISCARD_OFFSET 29 +#define NIC_FILTER_MDEF_EXT_NET_EN_OFFSET 30 +#define NIC_FILTER_MDEF_EXT_HOST_EN_OFFSET 31 + +#define NIC_FILTER_MDEF_BIT(offset) ((0x1) << (offset)) +#define NIC_FILTER_MDEF_BIT_VAL(offset, val) ((0x1) << ((offset) + (val))) + +/** Receive Enable */ +#define NIC_WRITE_RECV_ENABLE_CMD 0xCA +#define NIC_WRITE_RECV_ENABLE_LEN_MAX 14 + +#define NIC_WRITE_RECV_ENABLE_EN 0x1 +#define NIC_WRITE_RECV_ENABLE_ALL (0x1 << 1) +#define NIC_WRITE_RECV_ENABLE_STA (0x1 << 2) +#define NIC_WRITE_RECV_ENABLE_ARP_RES (0x1 << 3) +#define NIC_WRITE_RECV_ENABLE_NM_ALERT (0x00 << 4) +#define NIC_WRITE_RECV_ENABLE_NM_ASYNC (0x01 << 4) +#define NIC_WRITE_RECV_ENABLE_NM_DIRECT (0x02 << 4) +#define NIC_WRITE_RECV_ENABLE_NM_UNSUPP (0x03 << 4) +#define NIC_WRITE_RECV_ENABLE_RESERVED (0x1 << 6) +#define NIC_WRITE_RECV_ENABLE_CBDM (0x1 << 7) + +#endif diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic_0.1.bb new file mode 100644 index 0000000..30f167f --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/oob-nic/oob-nic_0.1.bb @@ -0,0 +1,44 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +SUMMARY = "OOB Shared NIC driver" +DESCRIPTION = "The shared-nic driver" +SECTION = "base" +PR = "r2" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://main.c;beginline=4;endline=16;md5=da35978751a9d71b73679307c4d296ec" + +SRC_URI = "file://src \ + " + +S = "${WORKDIR}/src" + +DEPENDS += "fbutils libwedge-eeprom" + +RDEPENDS_${PN} += "libwedge-eeprom" + +do_install() { + install -d ${D}${sbindir} + install -m 755 oob-nic ${D}${sbindir}/oob-nic + install -m 755 i2craw ${D}${sbindir}/i2craw + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 etc/oob-nic.sh ${D}${sysconfdir}/init.d/oob-nic.sh + update-rc.d -r ${D} oob-nic.sh start 80 S . +} + +FILES_${PN} = " ${sbindir} ${sysconfdir} " diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/rest-api/files/plat_tree.py b/meta-facebook/meta-yosemite/recipes-yosemite/rest-api/files/plat_tree.py new file mode 100644 index 0000000..b93e98e --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/rest-api/files/plat_tree.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +from ctypes import * +import json +import ssl +import socket +import os +from node_api import get_node_api +from node_spb import get_node_spb +from node_bmc import get_node_bmc +from node_server import get_node_server +from node_fruid import get_node_fruid +from node_sensors import get_node_sensors +from node_config import get_node_config +from tree import tree +from pal import * + +def populate_server_node(num): + prsnt = pal_is_server_prsnt(num) + if prsnt == None or prsnt == 0: + return None + + r_server = tree("server" + repr(num), data = get_node_server(num)) + + r_fruid = tree("fruid", data = get_node_fruid("slot" + repr(num))) + + r_sensors = tree("sensors", data = get_node_sensors("slot" + repr(num))) + + r_config = tree("config", data = get_node_config("slot" + repr(num))) + + r_server.addChildren([r_fruid, r_sensors, r_config]) + + return r_server + +# Initialize Platform specific Resource Tree +def init_plat_tree(): + + # Create /api end point as root node + r_api = tree("api", data = get_node_api()) + + # Add /api/spb to represent side plane board + r_spb = tree("spb", data = get_node_spb()) + r_api.addChild(r_spb) + + # Add servers /api/server[1-max] + num = pal_get_num_slots() + for i in range(1, num+1): + r_server = populate_server_node(i) + if r_server: + r_api.addChild(r_server) + + # TODO: Need to add /api/nic to represent NIC Mezz Card + + # Add /api/spb/fruid end point + r_temp = tree("fruid", data = get_node_fruid("spb")) + r_spb.addChild(r_temp) + + # /api/spb/bmc end point + r_temp = tree("bmc", data = get_node_bmc()) + r_spb.addChild(r_temp) + + # /api/spb/sensors end point + r_temp = tree("sensors", data = get_node_sensors("spb")) + r_spb.addChild(r_temp) + + return r_api diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/rest-api/files/setup-rest-api.sh b/meta-facebook/meta-yosemite/recipes-yosemite/rest-api/files/setup-rest-api.sh new file mode 100644 index 0000000..bdd79b6 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/rest-api/files/setup-rest-api.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: setup-rest-api +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Set REST API handler +### END INIT INFO + +echo -n "Setup REST API handler... " +/usr/local/bin/rest.py > /tmp/rest.log 2>&1 & +echo "done." diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/rest-api/rest-api_0.2.bbappend b/meta-facebook/meta-yosemite/recipes-yosemite/rest-api/rest-api_0.2.bbappend new file mode 100644 index 0000000..ce33bba --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/rest-api/rest-api_0.2.bbappend @@ -0,0 +1,62 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "Rest API Daemon" +DESCRIPTION = "Daemon to handle RESTful interface." +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://rest.py;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0" + +DEPENDS_append = " update-rc.d-native" + +S = "${WORKDIR}" + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" +SRC_URI += "file://setup-rest-api.sh \ + file://plat_tree.py \ + file://node_api.py \ + file://node_spb.py \ + file://node_bmc.py \ + file://node_server.py \ + file://node_fruid.py \ + file://node_sensors.py \ + file://node_config.py \ + " + +binfiles += "setup-rest-api.sh plat_tree.py node_api.py node_spb.py node_bmc.py node_server.py node_fruid.py node_sensors.py node_config.py" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${dst}/$f + ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f + done + for f in ${otherfiles}; do + install -m 644 $f ${dst}/$f + done + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-rest-api.sh ${D}${sysconfdir}/init.d/setup-rest-api.sh + update-rc.d -r ${D} setup-rest-api.sh start 95 2 3 4 5 . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/rest-api ${prefix}/local/bin ${sysconfdir} " diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/sensor-mon/files/setup-sensord.sh b/meta-facebook/meta-yosemite/recipes-yosemite/sensor-mon/files/setup-sensord.sh new file mode 100644 index 0000000..3f4b38e --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/sensor-mon/files/setup-sensord.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: setup-sensord +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Setup sensor monitoring +### END INIT INFO + +. /usr/local/fbpackages/utils/ast-functions + +# TODO: check for the if slot/server is present before starting the daemon +echo -n "Setup sensor monitoring for yosemite... " +/usr/local/bin/sensord slot1 slot2 slot3 slot4 +echo "done." diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/sensor-mon/sensor-mon_0.1.bbappend b/meta-facebook/meta-yosemite/recipes-yosemite/sensor-mon/sensor-mon_0.1.bbappend new file mode 100644 index 0000000..687a599 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/sensor-mon/sensor-mon_0.1.bbappend @@ -0,0 +1,58 @@ +# Copyright 2015-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI += "file://setup-sensord.sh \ + " + +S = "${WORKDIR}" + +CFLAGS_prepend = " -DCONFIG_YOSEMITE " + +LDFLAGS_append = " -lyosemite_sensor " + +DEPENDS_append = "libyosemite-sensor update-rc.d-native" + +pkgdir = "sensor-mon" + +do_install() { + dst="${D}/usr/local/fbpackages/${pkgdir}" + bin="${D}/usr/local/bin" + install -d $dst + install -d $bin + for f in ${binfiles}; do + install -m 755 $f ${dst}/$f + ln -snf ../fbpackages/${pkgdir}/$f ${bin}/$f + done + for f in ${otherfiles}; do + install -m 644 $f ${dst}/$f + done + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 setup-sensord.sh ${D}${sysconfdir}/init.d/setup-sensord.sh + update-rc.d -r ${D} setup-sensord.sh start 91 S . +} + +FBPACKAGEDIR = "${prefix}/local/fbpackages" + +FILES_${PN} = "${FBPACKAGEDIR}/sensor-mon ${prefix}/local/bin ${sysconfdir} " + +# Inhibit complaints about .debug directories for the sensord binary: + +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" +INHIBIT_PACKAGE_STRIP = "1" diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/sensor-setup/files/sensor-setup.sh b/meta-facebook/meta-yosemite/recipes-yosemite/sensor-setup/files/sensor-setup.sh new file mode 100644 index 0000000..a53b316 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/sensor-setup/files/sensor-setup.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: sensor-setup +# Required-Start: power-on +# Required-Stop: +# Default-Start: S +# Default-Stop: +# Short-Description: Power on micro-server +### END INIT INFO + +# Eventually, this will be used to configure the various (mostly +# i2c-based) sensors, once we have a kernel version that supports +# doing this more dynamically. +# +# For now, we're using it to install the lm75 and pmbus module so that it +# can detect the fourth temperature sensor, which is located +# on the uServer, which doesn't get power until power-on executes. +# +# Similarly, the pmbus sensor seems to have an easier time of +# detecting the NCP4200 buck converters after poweron. This has not +# been carefully explored. + +modprobe lm75 +modprobe pmbus + +# Enable the ADC inputs; adc0 - adc7 are connected to various voltage sensors + +echo 1 > /sys/devices/platform/ast_adc.0/adc0_en +echo 1 > /sys/devices/platform/ast_adc.0/adc1_en +echo 1 > /sys/devices/platform/ast_adc.0/adc2_en +echo 1 > /sys/devices/platform/ast_adc.0/adc3_en +echo 1 > /sys/devices/platform/ast_adc.0/adc4_en +echo 1 > /sys/devices/platform/ast_adc.0/adc5_en +echo 1 > /sys/devices/platform/ast_adc.0/adc6_en +echo 1 > /sys/devices/platform/ast_adc.0/adc7_en diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/sensor-setup/sensor-setup_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/sensor-setup/sensor-setup_0.1.bb new file mode 100644 index 0000000..1b0f937 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/sensor-setup/sensor-setup_0.1.bb @@ -0,0 +1,38 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "Configure the sensors" +DESCRIPTION = "The script configure sensors" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://sensor-setup.sh;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0" + +DEPENDS_append = " update-rc.d-native" + +SRC_URI = "file://sensor-setup.sh \ + " + +S = "${WORKDIR}" + +do_install() { + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 sensor-setup.sh ${D}${sysconfdir}/init.d/sensor-setup.sh + update-rc.d -r ${D} sensor-setup.sh start 90 S . +} + +FILES_${PN} = " ${sysconfdir} " diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/usb-console/files/usbcons.sh b/meta-facebook/meta-yosemite/recipes-yosemite/usb-console/files/usbcons.sh new file mode 100755 index 0000000..de284bb --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/usb-console/files/usbcons.sh @@ -0,0 +1,80 @@ +#! /bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +### BEGIN INIT INFO +# Provides: usbcons +# Required-Start: +# Required-Stop: +# Default-Start: S +# Default-Stop: 0 6 +# Short-Description: Creates a virtual USB serial device and starts a console +# on it. +# +### END INIT INFO + +PATH=/sbin:/bin:/usr/sbin:/usr/bin +NAME=usbcons +PIDFILE=/run/usbcons.pid +DESC="USB Serial Console" + +# source function library +. /etc/init.d/functions + +STOPPER= +ACTION="$1" + +case "$ACTION" in + start) + # Ability to prevent this from starting by editing cmdline in u-boot. + # Keeping this here until I get gadget switching working properly. (t4906522) + if grep "nousbcons" /proc/cmdline > /dev/null 2>&1 + then + echo "USB Console Disabled." + exit 0 + fi + echo -n "Starting $DESC: " + /usr/local/bin/usbmon.sh > /dev/null 2>&1 & + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + killall usbmon.sh + echo "$NAME." + ;; + restart|force-reload) + echo -n "Restarting $DESC: " + killall usbmon.sh + sleep 1 + /usr/local/bin/usbmon.sh > /dev/null 2>&1 & + echo "$NAME." + ;; + status) + status $DAEMON + exit $? + ;; + *) + N=${0##*/} + N=${N#[SK]??} + echo "Usage: $N {start|stop|status|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/usb-console/files/usbmon.sh b/meta-facebook/meta-yosemite/recipes-yosemite/usb-console/files/usbmon.sh new file mode 100755 index 0000000..0030775 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/usb-console/files/usbmon.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +# + +modprobe g_cdc host_addr=02:00:00:00:00:02 dev_addr=02:00:00:00:00:01 +while true; do + getty /dev/ttyGS0 57600 + sleep 1 +done diff --git a/meta-facebook/meta-yosemite/recipes-yosemite/usb-console/usb-console_0.1.bb b/meta-facebook/meta-yosemite/recipes-yosemite/usb-console/usb-console_0.1.bb new file mode 100644 index 0000000..c934f46 --- /dev/null +++ b/meta-facebook/meta-yosemite/recipes-yosemite/usb-console/usb-console_0.1.bb @@ -0,0 +1,42 @@ +# Copyright 2014-present Facebook. All Rights Reserved. +# +# This program file 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; version 2 of the License. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program in a file named COPYING; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301 USA +SUMMARY = "Set up a USB serial console" +DESCRIPTION = "Sets up a USB serial console" +SECTION = "base" +PR = "r1" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://usbcons.sh;beginline=5;endline=18;md5=0b1ee7d6f844d472fa306b2fee2167e0" + +DEPENDS_append = " update-rc.d-native" + +SRC_URI = "file://usbcons.sh \ + file://usbmon.sh \ + " + +S = "${WORKDIR}" + +do_install() { + install -d ${D}${sysconfdir}/init.d + install -d ${D}${sysconfdir}/rcS.d + install -m 755 usbcons.sh ${D}${sysconfdir}/init.d/usbcons.sh + update-rc.d -r ${D} usbcons.sh start 90 S . + localbindir="${D}/usr/local/bin" + install -d ${localbindir} + install -m 755 usbmon.sh ${localbindir}/usbmon.sh +} + +FILES_${PN} = " ${sysconfdir} /usr/local" |