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