#include <regs.h>
#include <types.h>
#include <errno.h>
#include <const.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

#include <inout.h>
#include <pcicnfg.h>

#define IRQ_BASE_OFFSET	0x40
#define PCI_IO_SPACE_BASE 0x0

extern void *_glob_data;			/* base of static storage */


static struct {
	u_char *pconf;
	u_int8 val;
	u_int8 buffer[256];
} drvstat;


error_code check()
{
	return SUCCESS;
}

error_code irqsort()
{
	u_int32 base_addr=0xB800;

	drvstat.val=IN(drvstat.pconf+0x4c);

	outc(base_addr+0x30, 0xff);

#if defined(_MPF386) && defined(PIC_CISR)
	/* clear interrupt(s) on PIC */
	outc(0x20, 0x20);
#endif
	return 0;
}

int init_irq(u_int8 bus, u_int8 dev, u_int func)
{
	u_int32 vector = pci_get_irq_line(bus, dev, func) + IRQ_BASE_OFFSET;
	error_code error = SUCCESS;

	printf("vector at bus:%d device:%d function:%d  = %x\n", bus, dev, func, vector);
	
	drvstat.pconf = (u_char *)( (pci_read_configuration_dword(bus, dev, func, 
					offsetof(pci_config_reg,base_addrs[1])) & ~1 ) | PCI_IO_SPACE_BASE);
	OUT(drvstat.pconf+0x4c, 0x53);	/* Enable the IRQs on the card (in the PLX) */

	if ((error = _os_irq(vector, 10, irqsort, _glob_data)) != SUCCESS)
	{
		printf("error at os_irq(): %d \n", error);
			return error;
	}

	if ((error = _pic_enable(vector)) != SUCCESS)
		return error;


	return error;
}

int deinit_irq(u_int8 bus, u_int8 dev, u_int func)
{
	u_int32 vector = pci_get_irq_line(bus, dev, func) + IRQ_BASE_OFFSET;
	error_code error = SUCCESS;

	printf("vector at bus:%d device:%d function:%d  = %x\n", bus, dev, func, vector);
	drvstat.pconf = (u_char *)( (pci_read_configuration_dword(bus, dev, func, 
					offsetof(pci_config_reg,base_addrs[1])) & ~1 ) | PCI_IO_SPACE_BASE);
	OUT(drvstat.pconf+0x4c, 0x13);	/* Disable the IRQs on the card (in the PLX) */

	_pic_disable(vector);
	_os_irq(vector, 10, 0, _glob_data);

	return error;
}

int main()
{
	u_int8 bus, dev, i;
	u_int16 bus_info;
	u_int32 base_addr=0, index = 0;
	error_code error;

	while (pci_find_device(0x144a,
		0x7248, index, &bus, &dev) == SUCCESS)
	{
		u_int8 device=dev & 0x1f, func=dev >> 5;
		index++;
		printf("%d. DIO-Card found at bus:%d device:%d function:%d\n",
			index, bus, device, func);
		// read vendor byte
		printf("Vendor-ID %4X\n", 
		   pci_read_configuration_word(bus, device, func, 
		     offsetof(pci_config_reg, vendor_id)));

		printf("Command-Reg: %8X\n", 
		pci_read_configuration_word(bus, device, func, 
						offsetof(pci_config_reg,command_reg)));
		printf("Status-Reg: %8X\n", 
		pci_read_configuration_word(bus, device, func, 
						offsetof(pci_config_reg,status_reg)));
		i=0;
		while (i<4)
		{
			printf("Baseaddress[%d]: %8lX\n", i, 
			(pci_read_configuration_dword(bus, device, func, 
						offsetof_base_addrs(i)) & ~1));
			i++;
		}

		bus_info = pci_read_configuration_word(\
					bus, 
					device, 
					func,
					offsetof(pci_config_reg,command_reg)) \
					| B_PCIC_IO_SPACE;	

		pci_write_configuration_word(
					bus, device, func,
					offsetof(pci_config_reg,command_reg), bus_info);


		base_addr=0xB800;

		OUT(base_addr+0x3, 0xB);
		OUT(base_addr+0, 0x55);
		printf("*Baseaddress: %x\n",
		  IN(base_addr+0x0));

	/*
		deinit_irq(bus, device, func);
		deinit_irq(bus, device, func);
		deinit_irq(bus, device, func);
		return;
	*/

	/*    enable irq */
		OUT(base_addr+0x20, 0x2);
		init_irq(bus, device, func);

		i=0;
		while (i<29)
		{
			u_int32 time=100;
			signal_code sig;
			_os_sleep(&time, &sig);
			printf("Value: 0x%x\n", drvstat.val);
			drvstat.val=IN(drvstat.pconf+0x4c);
			i++;
		};

		deinit_irq(bus, device, func);
	}
	return EXIT_SUCCESS;	
}