/*
 * Copyright (c) 2009 Corey Tabaka
 *
 * 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 <app.h>
#include <debug.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <compiler.h>
#include <platform.h>
#include <dev/pci.h>

#if defined(WITH_LIB_CONSOLE)
#include <lib/console.h>

/*
 * enumerates pci devices
 */
static void pci_list(void)
{
	pci_location_t state;
	uint16_t device_id, vendor_id;
	uint8_t header_type;
	int busses = 0, devices = 0, lines = 0, devfn, ret;
	char c;
	
	printf("Scanning...\n");
	
	for (state.bus = 0; state.bus <= pci_get_last_bus(); state.bus++) {
		busses++;
		
		for (devfn = 0; devfn < 256; devfn++) {
			state.dev_fn = devfn;
			
			ret = pci_read_config_half(&state, PCI_CONFIG_VENDOR_ID, &vendor_id);
			if (ret != _PCI_SUCCESSFUL) goto error;
			
			ret = pci_read_config_half(&state, PCI_CONFIG_DEVICE_ID, &device_id);
			if (ret != _PCI_SUCCESSFUL) goto error;
			
			ret = pci_read_config_byte(&state, PCI_CONFIG_HEADER_TYPE, &header_type);
			if (ret != _PCI_SUCCESSFUL) goto error;
			
			if (vendor_id != 0xffff) {
				printf("%02x:%02x vendor_id=%04x device_id=%04x, header_type=%02x\n", state.bus, state.dev_fn,
						vendor_id, device_id, header_type);
				devices++;
				lines++;
			}
			
			if (~header_type & PCI_HEADER_TYPE_MULTI_FN) {
				// this is not a multi-function device, so advance to the next device
				devfn |= 7;
			}
			
			if (lines == 23) {
				printf("... press any key to continue, q to quit ...");
				while(getc(&c) < 0);
				printf("\n");
				lines = 0;
				
				if (c == 'q' || c == 'Q') goto quit;
			}
		}
	}

	printf("... done. Scanned %d busses, %d device/functions\n", busses, devices);
quit:
	return;
	
error:
	printf("Error while reading PCI config space: %02x\n", ret);
}

/*
 * a somewhat fugly pci config space examin/modify command. this should probably
 * be broken up a bit.
 */
static int pci_config(int argc, const cmd_args *argv)
{
	pci_location_t loc;
	pci_config_t config;
	uint32_t offset;
	unsigned int i;
	int ret;
	
	if (argc < 5) {
		return -1;
	}
	
	if (!strcmp(argv[2].str, "dump")) {
		loc.bus = atoui(argv[3].str);
		loc.dev_fn = atoui(argv[4].str);
		
		for (i=0; i < sizeof(pci_config_t); i++) {
			ret = pci_read_config_byte(&loc, i, (uint8_t *) &config + i);
			if (ret != _PCI_SUCCESSFUL) goto error;
		}
		
		printf("Device at %02x:%02x vendor id=%04x device id=%04x\n", loc.bus,
			loc.dev_fn, config.vendor_id, config.device_id);
		printf("command=%04x status=%04x pi=%02x sub cls=%02x base cls=%02x\n",
			config.command, config.status, config.program_interface,
			config.sub_class, config.base_class);
		
		for (i=0; i < 6; i+=2) {
			printf("bat%d=%08x  bat%d=%08x\n", i, config.base_addresses[i],
				i+1, config.base_addresses[i+1]);
		}
	} else if (!strcmp(argv[2].str, "rb") || !strcmp(argv[2].str, "rh") || !strcmp(argv[2].str, "rw")) {
		if (argc != 6) {
			return -1;
		}
		
		loc.bus = atoui(argv[3].str);
		loc.dev_fn = atoui(argv[4].str);
		offset = atoui(argv[5].str);
		
		switch (argv[2].str[1]) {
			case 'b': {
				uint8_t value;
				ret = pci_read_config_byte(&loc, offset, &value);
				if (ret != _PCI_SUCCESSFUL) goto error;
				
				printf("byte at device %02x:%02x config offset %04x: %02x\n", loc.bus, loc.dev_fn, offset, value);
			}
			break;
			
			case 'h': {
				uint16_t value;
				ret = pci_read_config_half(&loc, offset, &value);
				if (ret != _PCI_SUCCESSFUL) goto error;
				
				printf("half at device %02x:%02x config offset %04x: %04x\n", loc.bus, loc.dev_fn, offset, value);
			}
			break;
			
			case 'w': {
				uint32_t value;
				ret = pci_read_config_word(&loc, offset, &value);
				if (ret != _PCI_SUCCESSFUL) goto error;
				
				printf("word at device %02x:%02x config offset %04x: %08x\n", loc.bus, loc.dev_fn, offset, value);
			}
			break;
		}
	} else if (!strcmp(argv[2].str, "mb") || !strcmp(argv[2].str, "mh") || !strcmp(argv[2].str, "mw")) {
		if (argc != 7) {
			return -1;
		}
		
		loc.bus = atoui(argv[3].str);
		loc.dev_fn = atoui(argv[4].str);
		offset = atoui(argv[5].str);
		
		switch (argv[2].str[1]) {
			case 'b': {
				uint8_t value = atoui(argv[6].str);
				ret = pci_write_config_byte(&loc, offset, value);
				if (ret != _PCI_SUCCESSFUL) goto error;
				
				printf("byte to device %02x:%02x config offset %04x: %02x\n", loc.bus, loc.dev_fn, offset, value);
			}
			break;
			
			case 'h': {
				uint16_t value = atoui(argv[6].str);
				ret = pci_write_config_half(&loc, offset, value);
				if (ret != _PCI_SUCCESSFUL) goto error;
				
				printf("half to device %02x:%02x config offset %04x: %04x\n", loc.bus, loc.dev_fn, offset, value);
			}
			break;
			
			case 'w': {
				uint32_t value = atoui(argv[6].str);
				ret = pci_write_config_word(&loc, offset, value);
				if (ret != _PCI_SUCCESSFUL) goto error;
				
				printf("word to device %02x:%02x config offset %04x: %08x\n", loc.bus, loc.dev_fn, offset, value);
			}
			break;
		}
	} else {
		return -1;
	}
	
	return 0;

error:
	printf("Error while reading PCI config space: %02x\n", ret);
	return -2;
}

static int pci_cmd(int argc, const cmd_args *argv)
{
	if (argc < 2) {
		printf("pci commands:\n");
usage:
		printf("%s list\n", argv[0].str);
		printf("%s config dump <bus> <devfn>\n", argv[0].str);
		printf("%s config <rb|rh|rw> <bus> <devfn> <offset>\n", argv[0].str);
		printf("%s config <mb|mh|mw> <bus> <devfn> <offset> <value>\n", argv[0].str);
		goto out;
	}
	
	if (!strcmp(argv[1].str, "list")) {
		pci_list();
	} else if (!strcmp(argv[1].str, "config")) {
		if (pci_config(argc, argv)) {
			goto usage;
		}
	} else {
		goto usage;
	}

out:
	return 0;
}

STATIC_COMMAND_START
{ "pci", "pci toolbox", &pci_cmd },
STATIC_COMMAND_END(pcitests);

#endif

APP_START(pcitests)
APP_END

