*/
#include "hw.h"
#include "pci.h"
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
#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
#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
#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 {
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;
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);
}
}
+
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:
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);
}
+
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);
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");
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);
// 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;
}