From f3aeb1ea334e480235d0c15faf4fe2479efd8a8c Mon Sep 17 00:00:00 2001 From: Rostislav Lisovy Date: Sun, 3 Apr 2011 20:47:43 +0200 Subject: [PATCH] Most of the card logic is implemented. Socket doesn't work. Not tested. --- src/qemu/hw/mf624.c | 308 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 263 insertions(+), 45 deletions(-) diff --git a/src/qemu/hw/mf624.c b/src/qemu/hw/mf624.c index d4a0aa4..a4208ea 100755 --- a/src/qemu/hw/mf624.c +++ b/src/qemu/hw/mf624.c @@ -6,20 +6,29 @@ */ #include "hw.h" #include "pci.h" +#include +#include +#include +#include +#include +#include #define PCI_VENDOR_ID_HUMUSOFT 0x186c #define PCI_DEVICE_ID_MF624 0x0624 - #define PCI_CLASS_SIGNAL_PROCESSING_CONTROLLER 0x1180 -/* --- Hardware specific --- */ + +#define BAR0_size 32 +#define BAR2_size 128 +#define BAR4_size 128 + /* BAR0 */ #define INTCSR_off 0x4C #define GPIOC_off 0x54 /* BAR2 */ #define ADDATA_off 0x00 -#define ADCTRL_off ADDATA_off +#define ADCTRL_off 0x00 #define ADDATA1_off 0x02 #define ADDATA2_off 0x04 #define ADDATA3_off 0x06 @@ -28,9 +37,9 @@ #define ADDATA6_off 0x0C #define ADDATA7_off 0x0E #define DOUT_off 0x10 -#define DIN_off DOUT_off +#define DIN_off 0x10 #define ADSTART_off 0x20 -#define DA0_off ADSTART_off +#define DA0_off 0x20 #define DA1_off 0x22 #define DA2_off 0x24 #define DA3_off 0x26 @@ -39,6 +48,9 @@ #define DA6_off 0x2C #define DA7_off 0x2E +#define GPIOC_EOLC_mask (1 << 17) +#define GPIOC_LDAC_mask (1 << 23) +#define GPIOC_DACEN_mask (1 << 26) typedef struct { @@ -48,29 +60,48 @@ typedef struct { typedef struct { uint16_t ADDATA; - #define ADCTRL ADDATA + uint16_t ADCTRL; uint16_t ADDATA1; - // ... + uint16_t ADDATA2; + uint16_t ADDATA3; + uint16_t ADDATA4; + uint16_t ADDATA5; + uint16_t ADDATA6; + uint16_t ADDATA7; uint16_t DIN; - #define DOUT DIN - // ... + uint16_t DOUT; + uint16_t DA0; + uint16_t DA1; + uint16_t DA2; + uint16_t DA3; + uint16_t DA4; + uint16_t DA5; + uint16_t DA6; + uint16_t DA7; } BAR2_t; typedef struct { - uint32_t CTR0STATUS; - #define CTR0MODE CTR0STATUS; - uint32_t CTR0; - #define CTR0A CTR0 - // .... +// uint32_t CTR0STATUS; +// uint32_t CTR0MODE; +// uint32_t CTR0; +// uint32_t CTR0A; +// ... } BAR4_t; typedef struct { PCIDevice dev; + int socket_srv; + int socket_tmp; + + uint16_t real_world_AD[8]; /* The real voltage which is on inputs od A/D convertors. + Until new conversion is started, there is old value in + ADC registers*/ + // for cpu_register_physical_memory() function - unsigned int BAR0_offset; - unsigned int BAR2_offset; - unsigned int BAR4_offset; + unsigned int BAR0_mem_table_index; + unsigned int BAR2_mem_table_index; + unsigned int BAR4_mem_table_index; // Internal registers values BAR0_t BAR0; @@ -78,18 +109,134 @@ typedef struct { BAR4_t BAR4; } mf624_state_t; +//----------------------------------------------------------------------------- +void mf624_init_registers(mf624_state_t* s) +{ +#define INTCSR_default_value 0x000300 +#define GPIOC_default_value 0x006C0 | (0x10 << 21) | (2 << 25) + + //Initialize all registers to default values + s->BAR0.INTCSR = INTCSR_default_value; + s->BAR0.GPIOC = GPIOC_default_value; + s->BAR2.ADDATA = 0x0; + s->BAR2.ADCTRL = 0x0; + s->BAR2.ADDATA1 = 0x0; + s->BAR2.ADDATA2 = 0x0; + s->BAR2.ADDATA3 = 0x0; + s->BAR2.ADDATA4 = 0x0; + s->BAR2.ADDATA5 = 0x0; + s->BAR2.ADDATA6 = 0x0; + s->BAR2.ADDATA7 = 0x0; + + s->BAR2.DIN = 0xFF; + s->BAR2.DOUT = 0x00; + s->BAR2.DA0 = 0x3FFF; + s->BAR2.DA1 = 0x3FFF; + s->BAR2.DA2 = 0x3FFF; + s->BAR2.DA3 = 0x3FFF; + s->BAR2.DA4 = 0x3FFF; + s->BAR2.DA5 = 0x3FFF; + s->BAR2.DA6 = 0x3FFF; + s->BAR2.DA7 = 0x3FFF; + +} + + +void socket_write(const char* reg, unsigned int val) +{ + printf("%s=%x\n", reg, val); +} + +void init_socket(mf624_state_t* dev) +{ + struct sockaddr_in addr_srv; + struct sockaddr_in addr_client; + int port = 55555; + int yes = 1; + + dev->socket_srv = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (dev->socket_srv == -1) { + perror("socket()"); + return; + } + + if (setsockopt(dev->socket_srv, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { + perror("setsockopt()"); + return; + } + + + socklen_t len = sizeof(addr_srv); + memset(&addr_srv, 0, len); + addr_srv.sin_family = AF_INET; + addr_srv.sin_addr.s_addr = htonl(INADDR_ANY); + addr_srv.sin_port = htons(port); + if(bind(dev->socket_srv, (struct sockaddr*) &addr_srv, len) == -1) { + perror("bind()"); + return; + } + + if (listen(dev->socket_srv, 5) == -1) { + perror("listen()"); + return; + } + + while(1) { + socklen_t len_client = sizeof(addr_client); + dev->socket_tmp = accept(dev->socket_srv, (struct sockaddr*) &addr_client, &len_client); + if (dev->socket_tmp == -1) { + perror("accept()"); + continue; + } + //open(dev, ); + //close(dev->socket_tmp); + } +} + +//----------------------------------------------------------------------------- void mf624_BAR0_write32(void *opaque, target_phys_addr_t addr, uint32_t value) { mf624_state_t *s = opaque; - switch (addr) { + switch (addr % BAR0_size) { case INTCSR_off: - s->BAR0.INTCSR = value; + s->BAR0.INTCSR = (value & 0x7FF) | INTCSR_default_value; // Only first 11 bits are writable + socket_write("INTCSR", s->BAR0.INTCSR); break; case GPIOC_off: - s->BAR0.GPIOC = value; + //Don't write anywhere else than into these two bits + s->BAR0.GPIOC = (value & (GPIOC_LDAC_mask | GPIOC_DACEN_mask)) | GPIOC_default_value; + socket_write("GPIOC", s->BAR0.GPIOC); + + //Is DAC enabled & Output enabled? + if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && + (s->BAR0.GPIOC & GPIOC_DACEN_mask)) { + socket_write("DA0", s->BAR2.DA0); + socket_write("DA1", s->BAR2.DA1); + socket_write("DA2", s->BAR2.DA2); + socket_write("DA3", s->BAR2.DA3); + socket_write("DA4", s->BAR2.DA4); + socket_write("DA5", s->BAR2.DA5); + socket_write("DA6", s->BAR2.DA6); + socket_write("DA7", s->BAR2.DA7); + } + + //Is output forced to GND? + if (!(s->BAR0.GPIOC & GPIOC_DACEN_mask)) + { + #define GND 0 + socket_write("DA0", GND); + socket_write("DA1", GND); + socket_write("DA2", GND); + socket_write("DA3", GND); + socket_write("DA4", GND); + socket_write("DA5", GND); + socket_write("DA6", GND); + socket_write("DA7", GND); + } + break; default: printf("mf624_BAR0_write32(): addr = %d; value = %d\n", addr, value); @@ -97,11 +244,12 @@ void mf624_BAR0_write32(void *opaque, target_phys_addr_t addr, uint32_t value) } } + uint32_t mf624_BAR0_read32(void *opaque, target_phys_addr_t addr) { mf624_state_t *s = opaque; - switch (addr) { + switch (addr % BAR0_size) { case INTCSR_off: return s->BAR0.INTCSR; case GPIOC_off: @@ -115,17 +263,80 @@ uint32_t mf624_BAR0_read32(void *opaque, target_phys_addr_t addr) uint32_t mf624_BAR2_read16(void *opaque, target_phys_addr_t addr) { - printf("mf624_BAR2_read16(): addr = %d\n", addr); - return 0x0; + int i; + mf624_state_t *s = opaque; + + switch (addr % BAR2_size) { + case ADDATA_off: + return s->BAR2.ADDATA; //FIXME Madness? This ... is ... FIFO! + + case ADDATA1_off: + if (!(s->BAR0.GPIOC & GPIOC_EOLC_mask)) { //Has the conversion already ended? + return s->BAR2.ADDATA1; + } + return 0xFFFF; // Semirandom value + + case ADDATA2_off: + if (!(s->BAR0.GPIOC & GPIOC_EOLC_mask)) { //Has the conversion already ended? + return s->BAR2.ADDATA2; + } + return 0xFFFF; // Semirandom value + + case DIN_off: + return s->BAR2.DIN; + + /* A/D Conversion Start. Reading this register triggers A/D + conversion for all channels selected in ADCTRL. */ + case ADSTART_off: + s->BAR0.GPIOC |= GPIOC_EOLC_mask; // Conversion in progress + for (i = 0; i < 500000; i++) + ; // Small delay simulating real conversion + + // Check before assignement, if particular ADC is enabled + s->BAR2.ADDATA = (s->BAR2.ADCTRL & (1 << 0)) ? s->real_world_AD[0] : s->BAR2.ADDATA; + s->BAR2.ADDATA1 = (s->BAR2.ADCTRL & (1 << 1)) ? s->real_world_AD[1] : s->BAR2.ADDATA1; + s->BAR2.ADDATA2 = (s->BAR2.ADCTRL & (1 << 2)) ? s->real_world_AD[2] : s->BAR2.ADDATA2; + s->BAR2.ADDATA3 = (s->BAR2.ADCTRL & (1 << 3)) ? s->real_world_AD[3] : s->BAR2.ADDATA3; + s->BAR2.ADDATA4 = (s->BAR2.ADCTRL & (1 << 4)) ? s->real_world_AD[4] : s->BAR2.ADDATA4; + s->BAR2.ADDATA5 = (s->BAR2.ADCTRL & (1 << 5)) ? s->real_world_AD[5] : s->BAR2.ADDATA5; + s->BAR2.ADDATA6 = (s->BAR2.ADCTRL & (1 << 6)) ? s->real_world_AD[6] : s->BAR2.ADDATA6; + s->BAR2.ADDATA7 = (s->BAR2.ADCTRL & (1 << 7)) ? s->real_world_AD[7] : s->BAR2.ADDATA7; + + return 0xFFFF; // Semirandom value + default: + printf("mf624_BAR2_read16(): addr = %d\n", addr); + return 0x0; + } } + void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t value) { mf624_state_t *s = opaque; - switch (addr - 128) { + switch (addr % BAR2_size) { + case ADCTRL_off: + s->BAR2.ADCTRL = value; + socket_write("ADCTRL", s->BAR2.ADCTRL); + break; case DOUT_off: s->BAR2.DOUT = value; + socket_write("DOUT", s->BAR2.DOUT); + break; + case DA0_off: + s->BAR2.DA0 = value; + //Is DAC enabled & Output enabled? + if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && + (s->BAR0.GPIOC & GPIOC_DACEN_mask)) { + socket_write("DA0", s->BAR2.DA0); + } + break; + case DA1_off: + s->BAR2.DA1 = value; + if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && + (s->BAR0.GPIOC & GPIOC_DACEN_mask)) { + socket_write("DA1", s->BAR2.DA1); + } break; default: printf("mf624_BAR2_write16(): addr = %d; value = %d\n", addr, value); @@ -134,6 +345,7 @@ void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t value) } + void mf624_BAR4_write32(void *opaque, target_phys_addr_t addr, uint32_t value) { printf("mf624_BAR4_write32(): addr = %d; value = %d\n", addr, value); @@ -190,16 +402,16 @@ static void mf624_map(PCIDevice *pci_dev, int region_num, switch (region_num) { case 0: - printf("reg%d, addr = %x\n", region_num, addr); - cpu_register_physical_memory(addr + 0x0, 32, s->BAR0_offset); + //printf("reg%d, addr = %x\n", region_num, addr); + cpu_register_physical_memory(addr + 0x0, BAR0_size, s->BAR0_mem_table_index); break; case 2: - printf("reg%d, addr = %x\n", region_num, addr); - cpu_register_physical_memory(addr + 0x0, 128, s->BAR2_offset); + //printf("reg%d, addr = %x\n", region_num, addr); + cpu_register_physical_memory(addr + 0x0, BAR2_size, s->BAR2_mem_table_index); break; case 4: - printf("reg%d, addr = %x\n", region_num, addr); - cpu_register_physical_memory(addr + 0x0, 128, s->BAR4_offset); + //printf("reg%d, addr = %x\n", region_num, addr); + cpu_register_physical_memory(addr + 0x0, BAR4_size, s->BAR4_mem_table_index); break; default: printf("FFFUUU\n"); @@ -212,6 +424,8 @@ static int pci_mf624_init(PCIDevice *pci_dev) mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev); //alocation of mf624_state_t uint8_t *pci_conf; + mf624_init_registers(s); + pci_conf = s->dev.config; pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_HUMUSOFT); pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_MF624); @@ -225,34 +439,38 @@ static int pci_mf624_init(PCIDevice *pci_dev) // return value of cpu_register_io_memory is IO INDEX - s->BAR0_offset = cpu_register_io_memory(mf624_BAR0_read, - mf624_BAR0_write, - s, - DEVICE_NATIVE_ENDIAN); + s->BAR0_mem_table_index = cpu_register_io_memory(mf624_BAR0_read, + mf624_BAR0_write, + s, + DEVICE_NATIVE_ENDIAN); - s->BAR2_offset = cpu_register_io_memory(mf624_BAR2_read, - mf624_BAR2_write, - s, - DEVICE_NATIVE_ENDIAN); + s->BAR2_mem_table_index = cpu_register_io_memory(mf624_BAR2_read, + mf624_BAR2_write, + s, + DEVICE_NATIVE_ENDIAN); - s->BAR4_offset = cpu_register_io_memory(mf624_BAR4_read, - mf624_BAR4_write, - s, - DEVICE_NATIVE_ENDIAN); + s->BAR4_mem_table_index = cpu_register_io_memory(mf624_BAR4_read, + mf624_BAR4_write, + s, + DEVICE_NATIVE_ENDIAN); //printf("BAR0: %d\n", s->BAR0_offset); //printf("BAR2: %d\n", s->BAR2_offset); //printf("BAR4: %d\n", s->BAR4_offset); - pci_register_bar(&s->dev, 0, 32, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map); - pci_register_bar(&s->dev, 2, 128, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map); - pci_register_bar(&s->dev, 4, 128, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map); + pci_register_bar(&s->dev, 0, BAR0_size, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map); + pci_register_bar(&s->dev, 2, BAR2_size, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map); + pci_register_bar(&s->dev, 4, BAR4_size, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map); + //init_socket(s); return 0; } static int pci_mf624_exit(PCIDevice *pci_dev) { + mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev); + close(s->socket_srv); + return 0; } -- 2.39.2