/*
 * Copyright (c) 2016 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * pci.c: Linux user space PCI bus management.
 *
 * Copyright (c) 2008 Eliot Dresselhaus
 *
 * 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.
 */

#include <vlib/vlib.h>
#include <vlib/pci/pci.h>
#include <vlib/unix/unix.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>

vlib_pci_main_t pci_main;

vlib_pci_device_info_t * __attribute__ ((weak))
vlib_pci_get_device_info (vlib_main_t * vm, vlib_pci_addr_t * addr,
			  clib_error_t ** error)
{
  if (error)
    *error = clib_error_return (0, "unsupported");
  return 0;
}

vlib_pci_addr_t * __attribute__ ((weak)) vlib_pci_get_all_dev_addrs ()
{
  return 0;
}

static clib_error_t *
show_pci_fn (vlib_main_t * vm,
	     unformat_input_t * input, vlib_cli_command_t * cmd)
{
  vlib_pci_addr_t *addr = 0, *addrs;
  int show_all = 0;
  u8 *s = 0;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "all"))
	show_all = 1;
      else
	return clib_error_return (0, "unknown input `%U'",
				  format_unformat_error, input);
    }

  vlib_cli_output (vm, "%-13s%-5s%-12s%-13s%-16s%-32s%s",
		   "Address", "Sock", "VID:PID", "Link Speed", "Driver",
		   "Product Name", "Vital Product Data");

  addrs = vlib_pci_get_all_dev_addrs ();
  /* *INDENT-OFF* */
  vec_foreach (addr, addrs)
    {
      vlib_pci_device_info_t *d;
      d = vlib_pci_get_device_info (vm, addr, 0);

      if (!d)
        continue;

      if (d->device_class != PCI_CLASS_NETWORK_ETHERNET && !show_all)
        continue;

        vec_reset_length (s);
        if (d->numa_node >= 0)
	  s = format (s, "  %d", d->numa_node);

        vlib_cli_output (vm, "%-13U%-5v%04x:%04x   %-13U%-16s%-32v%U",
			 format_vlib_pci_addr, addr, s,
			 d->vendor_id, d->device_id,
			 format_vlib_pci_link_speed, d,
			 d->driver_name ? (char *) d->driver_name : "",
			 d->product_name,
			 format_vlib_pci_vpd, d->vpd_r, 0);
	vlib_pci_free_device_info (d);
    }
  /* *INDENT-ON* */

  vec_free (s);
  vec_free (addrs);
  return 0;
}

uword
unformat_vlib_pci_addr (unformat_input_t * input, va_list * args)
{
  vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
  u32 x[4];

  if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
    return 0;

  addr->domain = x[0];
  addr->bus = x[1];
  addr->slot = x[2];
  addr->function = x[3];

  return 1;
}

u8 *
format_vlib_pci_addr (u8 * s, va_list * va)
{
  vlib_pci_addr_t *addr = va_arg (*va, vlib_pci_addr_t *);
  return format (s, "%04x:%02x:%02x.%x", addr->domain, addr->bus,
		 addr->slot, addr->function);
}

u8 *
format_vlib_pci_link_speed (u8 * s, va_list * va)
{
  vlib_pci_device_info_t *d = va_arg (*va, vlib_pci_device_info_t *);
  pcie_config_regs_t *r =
    pci_config_find_capability (&d->config0, PCI_CAP_ID_PCIE);
  int width;

  if (!r)
    return format (s, "unknown");

  width = (r->link_status >> 4) & 0x3f;

  if ((r->link_status & 0xf) == 1)
    return format (s, "2.5 GT/s x%u", width);
  if ((r->link_status & 0xf) == 2)
    return format (s, "5.0 GT/s x%u", width);
  if ((r->link_status & 0xf) == 3)
    return format (s, "8.0 GT/s x%u", width);
  return format (s, "unknown");
}

u8 *
format_vlib_pci_vpd (u8 * s, va_list * args)
{
  u8 *data = va_arg (*args, u8 *);
  u8 *id = va_arg (*args, u8 *);
  u32 indent = format_get_indent (s);
  char *string_types[] = { "PN", "EC", "SN", "MN", 0 };
  uword p = 0;
  int first_line = 1;

  if (vec_len (data) < 3)
    return s;

  while (p + 3 < vec_len (data))
    {

      if (data[p] == 0 && data[p + 1] == 0)
	return s;

      if (p + data[p + 2] > vec_len (data))
	return s;

      if (id == 0)
	{
	  int is_string = 0;
	  char **c = string_types;

	  while (c[0])
	    {
	      if (*(u16 *) & data[p] == *(u16 *) c[0])
		is_string = 1;
	      c++;
	    }

	  if (data[p + 2])
	    {
	      if (!first_line)
		s = format (s, "\n%U", format_white_space, indent);
	      else
		{
		  first_line = 0;
		  s = format (s, " ");
		}

	      s = format (s, "%c%c: ", data[p], data[p + 1]);
	      if (is_string)
		vec_add (s, data + p + 3, data[p + 2]);
	      else
		{
		  int i;
		  const int max_bytes = 8;
		  s = format (s, "0x");
		  for (i = 0; i < clib_min (data[p + 2], max_bytes); i++)
		    s = format (s, " %02x", data[p + 3 + i]);

		  if (data[p + 2] > max_bytes)
		    s = format (s, " ...");
		}
	    }
	}
      else if (*(u16 *) & data[p] == *(u16 *) id)
	{
	  vec_add (s, data + p + 3, data[p + 2]);
	  return s;
	}

      p += 3 + data[p + 2];
    }

  return s;
}


/* *INDENT-OFF* */
VLIB_CLI_COMMAND (show_pci_command, static) = {
  .path = "show pci",
  .short_help = "show pci [all]",
  .function = show_pci_fn,
};
/* *INDENT-ON* */

clib_error_t *
pci_bus_init (vlib_main_t * vm)
{
  vlib_pci_main_t *pm = &pci_main;
  pm->log_default = vlib_log_register_class ("pci", 0);
  return 0;
}

VLIB_INIT_FUNCTION (pci_bus_init);

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
