]> rtime.felk.cvut.cz Git - mf6xx.git/blob - src/qemu/hw/mf624.c
Suppress warning which breaks compilation.
[mf6xx.git] / src / qemu / hw / mf624.c
1 /* 
2  * Humusoft MF624 DAQ card implementation
3  * 
4  * Copyright (C) 2011 Rostislav Lisovy (lisovy@gmail.com)
5  * 
6  * Licensed under GPLv2 license
7  */
8 #include "hw.h"
9 #include "pci.h"
10 #include "qemu-thread.h"
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/types.h> 
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <sys/socket.h>
17
18 /* #define QEMU_VER_ABOVE_015 */
19
20 #define PCI_VENDOR_ID_HUMUSOFT          0x186c
21 #define PCI_DEVICE_ID_MF624             0x0624
22 #define PCI_CLASS_SIGNAL_PROCESSING_CONTROLLER  0x1180
23
24
25 #define BAR0_size                       32
26 #define BAR2_size                       128
27 #define BAR4_size                       128
28
29 /* BAR0 */
30 #define INTCSR_off                      0x4C
31 #define GPIOC_off                       0x54
32
33 /* BAR2 */ 
34 #define ADDATA_off                      0x00
35 #define ADCTRL_off                      0x00
36 #define ADDATA1_off                     0x02
37 #define ADDATA2_off                     0x04
38 #define ADDATA3_off                     0x06
39 #define ADDATA4_off                     0x08
40 #define ADDATA5_off                     0x0A
41 #define ADDATA6_off                     0x0C
42 #define ADDATA7_off                     0x0E
43 #define DOUT_off                        0x10
44 #define DIN_off                         0x10
45 #define ADSTART_off                     0x20
46 #define DA0_off                         0x20
47 #define DA1_off                         0x22
48 #define DA2_off                         0x24
49 #define DA3_off                         0x26
50 #define DA4_off                         0x28
51 #define DA5_off                         0x2A
52 #define DA6_off                         0x2C
53 #define DA7_off                         0x2E
54
55 #define GPIOC_EOLC_mask                 (1 << 17)
56 #define GPIOC_LDAC_mask                 (1 << 23)
57 #define GPIOC_DACEN_mask                (1 << 26)
58
59
60 typedef struct {
61         uint32_t INTCSR;
62         uint32_t GPIOC;
63 } BAR0_t;
64
65 typedef struct {
66         uint16_t ADDATA;
67         uint16_t ADCTRL;
68         uint16_t ADDATA1;
69         uint16_t ADDATA2;
70         uint16_t ADDATA3;
71         uint16_t ADDATA4;
72         uint16_t ADDATA5;
73         uint16_t ADDATA6;
74         uint16_t ADDATA7;
75         uint16_t DIN;
76         uint16_t DOUT;
77         uint16_t DA0;
78         uint16_t DA1;
79         uint16_t DA2;
80         uint16_t DA3;
81         uint16_t DA4;
82         uint16_t DA5;
83         uint16_t DA6;
84         uint16_t DA7;
85 } BAR2_t;
86
87 /* Not implemented */
88 typedef struct {
89 //      uint32_t CTR0STATUS;
90 //      uint32_t CTR0MODE;
91 //      uint32_t CTR0;
92 //      uint32_t CTR0A;
93 //      ...
94 } BAR4_t;
95
96 typedef struct {
97         PCIDevice dev;
98     #ifdef QEMU_VER_ABOVE_015
99         MemoryRegion mmio_bar0;
100         MemoryRegion mmio_bar2;
101         MemoryRegion mmio_bar4;
102     #endif /*QEMU_VER_ABOVE_015*/
103
104         int socket_srv;
105         int socket_tmp;
106         uint32_t port;
107         int addr;
108
109          /* The real voltage which is on inputs od A/D convertors.
110         Until new conversion is started, there is still old value in ADC registers*/    
111         unsigned int real_world_AD0; //Value in "ADC internal" format
112         unsigned int real_world_AD1;
113         unsigned int real_world_AD2;
114         unsigned int real_world_AD3;
115         unsigned int real_world_AD4;
116         unsigned int real_world_AD5;
117         unsigned int real_world_AD6;
118         unsigned int real_world_AD7;
119
120         // for cpu_register_physical_memory() function
121         unsigned int BAR0_mem_table_index;
122         unsigned int BAR2_mem_table_index;
123         unsigned int BAR4_mem_table_index;
124         
125         // Internal registers values
126         BAR0_t BAR0;
127         BAR2_t BAR2;
128         BAR4_t BAR4;
129
130
131         int ADDATA_FIFO[8]; //this array tells us which ADCs are being converted        
132         unsigned int ADDATA_FIFO_POSITION; //ADDATA is FIFO register; 
133                                 //We need to know, position in this FIFO =
134                                 //Which value will come next
135 } mf624_state_t;
136
137 int instance = 0; // Global variable shared between multiple mf624 devices
138
139
140 static int16_t volts_to_adinternal(double volt)
141 {
142         if (volt > 9.99) {
143                 volt = 9.99;
144         }
145         else if (volt < -10) {
146                 volt = -10;
147         }
148
149         return ((int16_t) ((volt*0x8000)/10))>>2;
150 }
151
152 static double dacinternal_to_volts(int16_t dacinternal)
153 {
154         return ((((double)dacinternal)/0x4000)*20.0 - 10.0);
155 }
156
157 //-----------------------------------------------------------------------------
158
159 /* Initialize register values due to MF624 manual */
160 static void mf624_init_registers(mf624_state_t* s)
161 {
162 #define INTCSR_default_value            0x000300
163 #define GPIOC_default_value             0x006C0 | (0x10 << 21) | (2 << 25)
164
165         //Initialize all registers to default values
166         s->BAR0.INTCSR = INTCSR_default_value;
167         s->BAR0.GPIOC = GPIOC_default_value; 
168         s->BAR2.ADDATA = 0x0;
169         s->BAR2.ADCTRL = 0x0;
170         s->BAR2.ADDATA1 = 0x0;
171         s->BAR2.ADDATA2 = 0x0;
172         s->BAR2.ADDATA3 = 0x0;
173         s->BAR2.ADDATA4 = 0x0;
174         s->BAR2.ADDATA5 = 0x0;
175         s->BAR2.ADDATA6 = 0x0;
176         s->BAR2.ADDATA7 = 0x0;
177
178         s->BAR2.DIN = 0xFF;
179         s->BAR2.DOUT = 0x00;
180         s->BAR2.DA0 = 0x3FFF;
181         s->BAR2.DA1 = 0x3FFF;
182         s->BAR2.DA2 = 0x3FFF;
183         s->BAR2.DA3 = 0x3FFF;
184         s->BAR2.DA4 = 0x3FFF;
185         s->BAR2.DA5 = 0x3FFF;
186         s->BAR2.DA6 = 0x3FFF;
187         s->BAR2.DA7 = 0x3FFF;
188
189         s->ADDATA_FIFO_POSITION = 0;
190 }
191
192 /* After some widget's value is changed, new value is send via socket to Qemu */
193 static void socket_write(mf624_state_t *s, const char* reg, double val)
194 {
195         int status;
196         char write_buffer[256];
197         snprintf(write_buffer, 255, "%s=%f\n", reg, val);
198
199         status = write(s->socket_tmp, write_buffer, strlen(write_buffer));
200         if (status < 0) {
201                 //perror("write()");
202                 printf("Error writing into socket. Is there no client connected?\n");
203         }
204 }
205
206 #define STRING_BUFF_SIZE        256
207 static void socket_read(mf624_state_t* dev)
208 {
209         // For parsing read instructions
210         char reg[STRING_BUFF_SIZE+1];
211         float val;
212         // For reading from socket
213         char read_buffer[STRING_BUFF_SIZE];
214         int received_length = 0;
215         int status;
216
217
218         while(1) {
219                 memset(read_buffer, '\0', STRING_BUFF_SIZE);
220                 received_length = read(dev->socket_tmp, read_buffer, STRING_BUFF_SIZE-1);
221                 if (received_length < 0) {
222                         perror("read()");
223                         return;
224                 }
225                 
226                 if (received_length == 0) {
227                         printf("Error while reading from socket. Client disconnected?\n");
228                         return;
229                 }
230
231                 // REG has "same size +1" as READ_BUFFER to avoid buffer overflow
232                 status = sscanf(read_buffer, "%[A-Z0-9]=%f", reg, &val);
233                 if (status == 2) {
234                         if(!strcmp(reg, "DIN")) {
235                                 dev->BAR2.DIN = val;
236                         }
237                         else if(!strcmp(reg, "ADC0")) {
238                                 dev->real_world_AD0 = volts_to_adinternal(val);
239                         }
240                         else if(!strcmp(reg, "ADC1")) {
241                                 dev->real_world_AD1 = volts_to_adinternal(val);
242                         }
243                         else if(!strcmp(reg, "ADC2")) {
244                                 dev->real_world_AD2 = volts_to_adinternal(val);
245                         }
246                         else if(!strcmp(reg, "ADC3")) {
247                                 dev->real_world_AD3 = volts_to_adinternal(val);
248                         }
249                         else if(!strcmp(reg, "ADC4")) {
250                                 dev->real_world_AD4 = volts_to_adinternal(val);
251                         }
252                         else if(!strcmp(reg, "ADC5")) {
253                                 dev->real_world_AD5 = volts_to_adinternal(val);
254                         }
255                         else if(!strcmp(reg, "ADC6")) {
256                                 dev->real_world_AD6 = volts_to_adinternal(val);
257                         }
258                         else if(!strcmp(reg, "ADC7")) {
259                                 dev->real_world_AD7 = volts_to_adinternal(val);
260                         }
261                         else {
262                                 printf("reg = %s; val = %f\n", reg, val);
263                         } 
264                 }
265         }
266 }
267
268
269 static void* init_socket(void* ptr)
270 {
271         struct sockaddr_in addr_client;
272         struct sockaddr_in addr_srv;
273         int port;
274         int yes = 1;
275         
276         mf624_state_t* dev = (mf624_state_t*) ptr;
277
278         dev->socket_tmp = -1;
279         port = dev->port;
280
281         dev->socket_srv = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
282         if (dev->socket_srv == -1) {
283                 perror("socket()");
284                 return NULL;
285         }
286         
287         if (setsockopt(dev->socket_srv, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
288                 perror("setsockopt()");
289                 return NULL;
290         }
291
292
293         socklen_t len = sizeof(addr_srv);
294         memset(&addr_srv, 0, len);
295         addr_srv.sin_family = AF_INET;
296         addr_srv.sin_addr.s_addr = htonl(INADDR_ANY);
297         addr_srv.sin_port = htons(port);
298         if(bind(dev->socket_srv, (struct sockaddr*) &addr_srv, len) == -1) {
299                 perror("bind()");
300                 return NULL;
301         }
302         
303         if (listen(dev->socket_srv, 5) == -1) {
304                 perror("listen()");
305                 return NULL;
306         }
307
308
309         while(1) {
310                 printf("Waiting on port %d for MF624 client to connect\n", dev->port);
311                 socklen_t len_client = sizeof(addr_client);
312                 dev->socket_tmp = accept(dev->socket_srv, (struct sockaddr*) &addr_client, &len_client);
313                 if (dev->socket_tmp == -1) {
314                         perror("accept()");
315                 }
316
317                 printf("Client connected\n");
318         
319                 socket_read(dev); // should run forever if everything is OK; 
320                                 // If error occurs (client disconnected), returns here
321                 
322                 close(dev->socket_tmp);
323         }
324
325         return NULL;
326 }
327
328 //-----------------------------------------------------------------------------
329
330 static void mf624_BAR0_write32(void *opaque, target_phys_addr_t addr, uint32_t value)
331 {
332         mf624_state_t *s = opaque;
333
334         switch (addr % BAR0_size) {
335                 case INTCSR_off:
336                         s->BAR0.INTCSR = (value & 0x7FF) | INTCSR_default_value; // Only first 11 bits are writable
337                         socket_write(s, "INTCSR", s->BAR0.INTCSR);
338                         break;
339                         
340                 case GPIOC_off:
341                         //Don't write anywhere else than into these two bits
342                         s->BAR0.GPIOC = (value & (GPIOC_LDAC_mask | GPIOC_DACEN_mask)) | GPIOC_default_value;
343                         socket_write(s, "GPIOC", s->BAR0.GPIOC);
344
345                         //Is DAC enabled & Output enabled?
346                         if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) &&
347                                 (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
348                                 socket_write(s, "DA0", dacinternal_to_volts(s->BAR2.DA0));
349                                 socket_write(s, "DA1", dacinternal_to_volts(s->BAR2.DA1));
350                                 socket_write(s, "DA2", dacinternal_to_volts(s->BAR2.DA2));
351                                 socket_write(s, "DA3", dacinternal_to_volts(s->BAR2.DA3));
352                                 socket_write(s, "DA4", dacinternal_to_volts(s->BAR2.DA4));
353                                 socket_write(s, "DA5", dacinternal_to_volts(s->BAR2.DA5));
354                                 socket_write(s, "DA6", dacinternal_to_volts(s->BAR2.DA6));
355                                 socket_write(s, "DA7", dacinternal_to_volts(s->BAR2.DA7));
356                         }
357                         
358                         //Is output forced to GND?
359                         if (!(s->BAR0.GPIOC & GPIOC_DACEN_mask))
360                         {
361                                 #define GND     0
362                                 socket_write(s, "DA0", dacinternal_to_volts(GND));
363                                 socket_write(s, "DA1", dacinternal_to_volts(GND));
364                                 socket_write(s, "DA2", dacinternal_to_volts(GND));
365                                 socket_write(s, "DA3", dacinternal_to_volts(GND));
366                                 socket_write(s, "DA4", dacinternal_to_volts(GND));
367                                 socket_write(s, "DA5", dacinternal_to_volts(GND));
368                                 socket_write(s, "DA6", dacinternal_to_volts(GND));
369                                 socket_write(s, "DA7", dacinternal_to_volts(GND));
370                         }
371                         break;
372                         
373                 default:
374                         printf("mf624_BAR0_write32(): addr = " TARGET_FMT_plx "; value = %d\n", addr, value);
375                         break;
376         }
377 }
378
379
380 static uint32_t mf624_BAR0_read32(void *opaque, target_phys_addr_t addr)
381 {
382         mf624_state_t *s = opaque;
383
384         switch (addr % BAR0_size) {
385                 case INTCSR_off:
386                         return s->BAR0.INTCSR;
387
388                 case GPIOC_off:
389                         return s->BAR0.GPIOC;
390
391                 default:
392                         printf("mf624_BAR0_read32(): addr = " TARGET_FMT_plx "\n", addr);
393                         return 0x0;
394         }
395 }
396
397
398 static uint32_t mf624_BAR2_read16(void *opaque, target_phys_addr_t addr)
399 {
400         int i;
401         int ADDATA_val = 0xFFFF;
402         mf624_state_t *s = opaque;
403
404         switch (addr % BAR2_size) {
405                 /* Reading from ADDATA FIFO register */
406                 case ADDATA_off:
407                 case ADDATA1_off: // Mirrored registers
408                 case ADDATA2_off:
409                 case ADDATA3_off:
410                 case ADDATA4_off:
411                 case ADDATA5_off:
412                 case ADDATA6_off:
413                 case ADDATA7_off:
414                         if (!(s->BAR0.GPIOC & GPIOC_EOLC_mask)) { //Has the conversion already ended?
415                                 #define ADC_CHANNELS    8
416                                 for(i = s->ADDATA_FIFO_POSITION; i < ADC_CHANNELS; i ++) {
417                                         if (s->BAR2.ADCTRL & (1 << i)) {
418                                                 s->ADDATA_FIFO_POSITION = i; // Move to next AD to be read
419                                         }
420                                 }
421                                 
422                                 switch (s->ADDATA_FIFO_POSITION)
423                                 {
424                                         case 0:
425                                                 ADDATA_val = s->BAR2.ADDATA;
426                                                 break;
427                                         case 1:
428                                                 ADDATA_val = s->BAR2.ADDATA1;
429                                                 break;
430                                         case 2:
431                                                 ADDATA_val = s->BAR2.ADDATA2;
432                                                 break;
433                                         case 3:
434                                                 ADDATA_val = s->BAR2.ADDATA3;
435                                                 break;
436                                         case 4:
437                                                 ADDATA_val = s->BAR2.ADDATA4;
438                                                 break;
439                                         case 5:
440                                                 ADDATA_val = s->BAR2.ADDATA5;
441                                                 break;
442                                         case 6:
443                                                 ADDATA_val = s->BAR2.ADDATA6;
444                                                 break;
445                                         case 7:
446                                                 ADDATA_val = s->BAR2.ADDATA7;
447                                                 break;
448                                         default: // restart counter
449                                                 s->ADDATA_FIFO_POSITION = 0;
450                                                 ADDATA_val = s->BAR2.ADDATA;
451                                                 break;
452                                 }
453                                 s->ADDATA_FIFO_POSITION ++;
454                                 return ADDATA_val;
455                         }
456                         return 0xFFFF; // Semirandom value
457
458                 /* Digital Input*/
459                 case DIN_off:
460                         return s->BAR2.DIN;
461
462                 /* A/D Conversion Start. Reading this register triggers A/D
463                 conversion for all channels selected in ADCTRL. */
464                 case ADSTART_off:
465                         s->BAR0.GPIOC |= GPIOC_EOLC_mask; // Conversion in progress
466                         s->ADDATA_FIFO_POSITION = 0;
467                         for (i = 0; i < 5000; i++) 
468                                 ; // Small delay simulating real conversion
469
470                         // Check before assignement, if particular ADC is enabled
471                         s->BAR2.ADDATA  = (s->BAR2.ADCTRL & (1 << 0)) ? s->real_world_AD0 : s->BAR2.ADDATA;
472                         s->BAR2.ADDATA1 = (s->BAR2.ADCTRL & (1 << 1)) ? s->real_world_AD1 : s->BAR2.ADDATA1;
473                         s->BAR2.ADDATA2 = (s->BAR2.ADCTRL & (1 << 2)) ? s->real_world_AD2 : s->BAR2.ADDATA2;
474                         s->BAR2.ADDATA3 = (s->BAR2.ADCTRL & (1 << 3)) ? s->real_world_AD3 : s->BAR2.ADDATA3;
475                         s->BAR2.ADDATA4 = (s->BAR2.ADCTRL & (1 << 4)) ? s->real_world_AD4 : s->BAR2.ADDATA4;
476                         s->BAR2.ADDATA5 = (s->BAR2.ADCTRL & (1 << 5)) ? s->real_world_AD5 : s->BAR2.ADDATA5;
477                         s->BAR2.ADDATA6 = (s->BAR2.ADCTRL & (1 << 6)) ? s->real_world_AD6 : s->BAR2.ADDATA6;
478                         s->BAR2.ADDATA7 = (s->BAR2.ADCTRL & (1 << 7)) ? s->real_world_AD7 : s->BAR2.ADDATA7;
479                         
480                         //All channels converted
481                         s->BAR0.GPIOC &= ~ GPIOC_EOLC_mask;
482                         
483                         return 0xFFFF; // Semirandom value
484
485                 default:
486                         printf("mf624_BAR2_read16(): addr = " TARGET_FMT_plx "\n", addr);
487                         return 0x0;
488         }
489 }
490
491
492 static void mf624_BAR2_write16(void *opaque, target_phys_addr_t addr, uint32_t value)
493 {
494         mf624_state_t *s = opaque;
495
496         switch (addr % BAR2_size) {
497                 case ADCTRL_off:
498                         s->BAR2.ADCTRL = value;
499                         socket_write(s, "ADCTRL", s->BAR2.ADCTRL);
500                         break;
501
502                 case DOUT_off:
503                         s->BAR2.DOUT = value;
504                         socket_write(s, "DOUT", s->BAR2.DOUT);
505                         break;
506
507                 case DA0_off:
508                         s->BAR2.DA0 = value;
509                         //Is DAC enabled & Output enabled?
510                         if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) &&
511                                 (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
512                                 socket_write(s, "DA0", dacinternal_to_volts(s->BAR2.DA0));
513                         }
514                         break;
515
516                 case DA1_off:
517                         s->BAR2.DA1 = value;
518                         if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
519                                 (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
520                                 socket_write(s, "DA1", dacinternal_to_volts(s->BAR2.DA1));
521                         }
522                         break;
523
524                 case DA2_off:
525                         s->BAR2.DA2 = value;
526                         if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
527                                 (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
528                                 socket_write(s, "DA2", dacinternal_to_volts(s->BAR2.DA2));
529                         }
530                         break;
531
532                 case DA3_off:
533                         s->BAR2.DA3 = value;
534                         if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
535                                 (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
536                                 socket_write(s, "DA3", dacinternal_to_volts(s->BAR2.DA3));
537                         }
538                         break;
539
540                 case DA4_off:
541                         s->BAR2.DA4 = value;
542                         if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
543                                 (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
544                                 socket_write(s, "DA4", dacinternal_to_volts(s->BAR2.DA4));
545                         }
546                         break;
547
548                 case DA5_off:
549                         s->BAR2.DA5 = value;
550                         if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
551                                 (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
552                                 socket_write(s, "DA5", dacinternal_to_volts(s->BAR2.DA5));
553                         }
554                         break;
555
556                 case DA6_off:
557                         s->BAR2.DA6 = value;
558                         if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
559                                 (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
560                                 socket_write(s, "DA6", dacinternal_to_volts(s->BAR2.DA6));
561                         }
562                         break;
563
564                 case DA7_off:
565                         s->BAR2.DA7 = value;
566                         if (!(s->BAR0.GPIOC & GPIOC_LDAC_mask) && 
567                                 (s->BAR0.GPIOC & GPIOC_DACEN_mask)) {
568                                 socket_write(s, "DA7", dacinternal_to_volts(s->BAR2.DA7));
569                         }
570                         break;
571
572                 default:
573                         printf("mf624_BAR2_write16(): addr = " TARGET_FMT_plx "; value = %d\n", addr, value);
574                         break;
575         }
576 }
577
578
579 static void mf624_BAR4_write32(void *opaque, target_phys_addr_t addr, uint32_t value)
580 {
581         printf("mf624_BAR4_write32(): addr = " TARGET_FMT_plx "; value = %d\n", addr, value);
582 }
583
584 static uint32_t mf624_BAR4_read32(void *opaque, target_phys_addr_t addr)
585 {
586         printf("mf624_BAR4_read32(): addr = " TARGET_FMT_plx "\n", addr);
587         return 0x0;
588 }
589
590 //-----------------------------------------------------------------------------
591
592 #ifdef QEMU_VER_ABOVE_015
593
594 static const MemoryRegionOps mf624_BAR0_mmio_ops = {
595     .old_mmio = {
596         .read = {
597             NULL,
598             NULL,
599             mf624_BAR0_read32,
600         },
601         .write = {
602             NULL,
603             NULL,
604             mf624_BAR0_write32,
605         },
606     },
607     .endianness = DEVICE_LITTLE_ENDIAN,
608 };
609
610 static const MemoryRegionOps mf624_BAR2_mmio_ops = {
611     .old_mmio = {
612         .read = {
613             NULL,
614             mf624_BAR2_read16,
615             NULL,
616         },
617         .write = {
618             NULL,
619             mf624_BAR2_write16,
620             NULL,
621         },
622     },
623     .endianness = DEVICE_LITTLE_ENDIAN,
624 };
625
626 static const MemoryRegionOps mf624_BAR4_mmio_ops = {
627     .old_mmio = {
628         .read = {
629             NULL,
630             NULL,
631             mf624_BAR4_read32,
632         },
633         .write = {
634             NULL,
635             NULL,
636             mf624_BAR4_write32,
637         },
638     },
639     .endianness = DEVICE_LITTLE_ENDIAN,
640 };
641
642 #else /*QEMU_VER_ABOVE_015*/
643
644 static CPUReadMemoryFunc * const mf624_BAR0_read[3] = {
645         NULL, /* read8 */
646         NULL, /* read16 */
647         mf624_BAR0_read32,
648 };
649  
650 static CPUWriteMemoryFunc * const mf624_BAR0_write[3] = {
651         NULL, /* write8 */
652         NULL, /* write16 */
653         mf624_BAR0_write32,
654 };
655
656 static CPUReadMemoryFunc * const mf624_BAR2_read[3] = {
657         NULL, /* read8 */
658         mf624_BAR2_read16,
659         NULL, /* read32 */
660 };
661  
662 static CPUWriteMemoryFunc * const mf624_BAR2_write[3] = {
663         NULL, /* write8 */
664         mf624_BAR2_write16,
665         NULL, /* write32 */
666 };
667
668 static CPUReadMemoryFunc * const mf624_BAR4_read[3] = {
669         NULL, /* read8 */
670         NULL, /* read16 */
671         mf624_BAR4_read32,
672 };
673  
674 static CPUWriteMemoryFunc * const mf624_BAR4_write[3] = {
675         NULL, /* write8 */
676         NULL, /* write16 */
677         mf624_BAR4_write32,
678 };
679
680
681 //-----------------------------------------------------------------------------
682         
683 static void mf624_map(PCIDevice *pci_dev, int region_num,
684                        pcibus_t addr, pcibus_t size, int type)
685 {
686         mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev);
687
688         switch (region_num) {
689                 case 0:
690                         //printf("reg%d, addr = %x\n", region_num, addr);
691                         cpu_register_physical_memory(addr + 0x0, BAR0_size, s->BAR0_mem_table_index);
692                         break;
693                 case 2:
694                         //printf("reg%d, addr = %x\n", region_num, addr);
695                         cpu_register_physical_memory(addr + 0x0, BAR2_size, s->BAR2_mem_table_index);
696                         break;
697                 case 4:
698                         //printf("reg%d, addr = %x\n", region_num, addr);
699                         cpu_register_physical_memory(addr + 0x0, BAR4_size, s->BAR4_mem_table_index);
700                         break;
701                 default:
702                         printf("FFFUUU\n");
703         }
704
705 }
706
707 #endif /*QEMU_VER_ABOVE_015*/
708
709 #define DEFAULT_PORT                    55555
710 static int pci_mf624_init(PCIDevice *pci_dev)
711 {
712         mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev); //alocation of mf624_state_t
713         uint8_t *pci_conf;
714         QemuThread socket_thread;
715
716         printf("MF624 Loaded.\n");
717
718         if (s->port == DEFAULT_PORT) {
719                 s->port += instance; // Each instance of the same device should have another port number
720                 instance ++;
721         }
722
723         //Set all internal registers to default values
724         mf624_init_registers(s);
725
726         pci_conf = s->dev.config;
727         pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_HUMUSOFT);
728         pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_MF624);
729         pci_config_set_class(pci_conf, PCI_CLASS_SIGNAL_PROCESSING_CONTROLLER);
730         pci_conf[PCI_SUBSYSTEM_VENDOR_ID] = PCI_VENDOR_ID_HUMUSOFT & 0xff;
731         pci_conf[PCI_SUBSYSTEM_VENDOR_ID + 1] = PCI_VENDOR_ID_HUMUSOFT >> 8;
732         pci_conf[PCI_SUBSYSTEM_ID] = PCI_DEVICE_ID_MF624 & 0xff;
733         pci_conf[PCI_SUBSYSTEM_ID + 1] = PCI_DEVICE_ID_MF624 >> 8;
734
735         pci_conf[PCI_INTERRUPT_PIN] = 0x1; // interrupt pin 0
736
737     #ifdef QEMU_VER_ABOVE_015
738         memory_region_init_io(&s->mmio_bar0, &mf624_BAR0_mmio_ops, s, "mf624_bar0", BAR0_size);
739         memory_region_init_io(&s->mmio_bar2, &mf624_BAR2_mmio_ops, s, "mf624_bar2", BAR2_size);
740         memory_region_init_io(&s->mmio_bar4, &mf624_BAR4_mmio_ops, s, "mf624_bar4", BAR4_size);
741         pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_bar0);
742         pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_bar2);
743         pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_bar4);
744     #else  /*QEMU_VER_ABOVE_015*/
745         s->BAR0_mem_table_index = cpu_register_io_memory(mf624_BAR0_read,
746                                                  mf624_BAR0_write,
747                                                  s,
748                                                  DEVICE_NATIVE_ENDIAN);
749
750         s->BAR2_mem_table_index = cpu_register_io_memory(mf624_BAR2_read,
751                                                  mf624_BAR2_write,
752                                                  s,
753                                                  DEVICE_NATIVE_ENDIAN);
754
755         s->BAR4_mem_table_index = cpu_register_io_memory(mf624_BAR4_read,
756                                                  mf624_BAR4_write,
757                                                  s,
758                                                  DEVICE_NATIVE_ENDIAN);
759
760         pci_register_bar(&s->dev, 0, BAR0_size, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map);
761         pci_register_bar(&s->dev, 2, BAR2_size, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map);
762         pci_register_bar(&s->dev, 4, BAR4_size, PCI_BASE_ADDRESS_SPACE_MEMORY, mf624_map);
763     #endif  /*QEMU_VER_ABOVE_015*/
764
765         //Create thread, which will be blocked on reading from socket (connected to "I/O GUI")
766         qemu_thread_create(&socket_thread, init_socket, (void*) s);
767         return 0;
768 }
769
770 static int pci_mf624_exit(PCIDevice *pci_dev)
771 {
772         mf624_state_t *s = DO_UPCAST(mf624_state_t, dev, pci_dev);
773         close(s->socket_srv);
774
775         return 0;
776 }
777
778
779 static PCIDeviceInfo mf624_info = {
780         .qdev.name  = "mf624",
781         .qdev.size  = sizeof(mf624_state_t),
782         .init       = pci_mf624_init,
783         .exit       = pci_mf624_exit,
784         .qdev.props = (Property[]) {
785                 DEFINE_PROP_UINT32("port", mf624_state_t, port, DEFAULT_PORT),
786                 DEFINE_PROP_END_OF_LIST(),
787         }
788 };
789
790 static void mf624_register_device(void)
791 {
792         pci_qdev_register(&mf624_info);
793 }
794
795 device_init(mf624_register_device)