#include <kernel/kernel.h>
#include <kernel/driver.h>
#include <kernel/ramdisk.h>
#include <kernel/config.h>
#include <stdlib.h>
#include <wchar.h>

/*!
 *  \ingroup	drivers
 *  \defgroup	isa ISA bus
 *  @{
 */

device_t *isa;
wchar_t devname[16];
int num_resources;
device_resource_t *resources;
word vendor, device;

void isaAddItem(hashelem_t* elem)
{
	device_resource_t res;
	wchar_t *data, *ch;

	data = (wchar_t*) elem->data;
	if (wcsicmp(elem->str, L"name") == 0)
		wcscpy(devname, data);
	else if (wcsicmp(elem->str, L"io") == 0)
	{
		ch = wcschr(data, ',');
		if (ch)
		{
			*ch = 0;
			ch++;
		}
		else
			ch = L"1";

		res.cls = dresIo;
		res.u.io.base = wcstol(data, NULL, 16);
		res.u.io.length = wcstol(ch, NULL, 0);
		goto add_resource;
	}
	else if (wcsicmp(elem->str, L"memory") == 0)
	{
		ch = wcschr(data, ',');
		if (ch)
		{
			*ch = 0;
			ch++;
		}
		else
			ch = L"1";

		res.cls = dresMemory;
		res.u.memory.base = wcstol(data, NULL, 16);
		res.u.memory.length = wcstol(ch, NULL, 0);
		goto add_resource;
	}
	else if (wcsicmp(elem->str, L"irq") == 0)
	{
		res.cls = dresIrq;
		res.u.irq = wcstol(data, NULL, 0);
		goto add_resource;
	}
	else if (wcsicmp(elem->str, L"vendor") == 0)
		vendor = wcstol(data, NULL, 16);
	else if (wcsicmp(elem->str, L"device") == 0)
		device = wcstol(data, NULL, 16);
	else
		wprintf(L"%s: invalid keyword\n", elem->str);

	return;

add_resource:
	num_resources++;
	resources = realloc(resources, sizeof(device_resource_t) * num_resources);
	resources[num_resources - 1] = res;
}

bool STDCALL INIT_CODE drvInit(driver_t* drv)
{
	void* file;
	//char line[256], *p, *dest;
	char* p;
	size_t length;
	hashtable_t *table;
	device_config_t *cfg;

	file = ramOpen(L"isa.cfg");
	if (!file)
		return false;

	isa = hndAlloc(sizeof(device_t), NULL);
	isa->driver = drv;
	isa->request = NULL;
	isa->req_first = isa->req_last = NULL;
	isa->config = NULL;
	devRegister(L"isa", isa, NULL);

	length = ramFileLength(L"isa.cfg");

	p = (char*) file;

	while (p < (char*) file + length)
	{
		memset(devname, 0, sizeof(devname));
		num_resources = 0;
		resources = NULL;
		vendor = 0xffff;
		device = 0xffff;

		table = cfgParseStrLine((const char**) &p);
		hashList(table, isaAddItem);
		cfgDeleteTable(table);

		if (devname[0])
		{
			cfg = hndAlloc(sizeof(device_config_t), NULL);
			cfg->parent = isa;
			cfg->vendor_id = vendor;
			cfg->device_id = device;
			cfg->subsystem = 0xffffffff;
			cfg->num_resources = num_resources;
			cfg->resources = resources;
			devRegister(devname, NULL, cfg);
		}
	}

	return true;
}

//@}