Commit e5b39b1ee2635b85534b5a2f54f2307210294c32

Authored by dmakow
1 parent fd35d26c

Removed Windows end characters

Showing 1 changed file with 524 additions and 524 deletions
hw/at91_pio.c
1   -/*
2   - * AT91 Parallel I/O Controller
3   - *
4   - * Copyright (c) 2009 Filip Navara
5   - *
6   - * Permission is hereby granted, free of charge, to any person obtaining a copy
7   - * of this software and associated documentation files (the "Software"), to deal
8   - * in the Software without restriction, including without limitation the rights
9   - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10   - * copies of the Software, and to permit persons to whom the Software is
11   - * furnished to do so, subject to the following conditions:
12   - *
13   - * The above copyright notice and this permission notice shall be included in
14   - * all copies or substantial portions of the Software.
15   - *
16   - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19   - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22   - * THE SOFTWARE.
23   - */
24   -
25   -/* TODO: Glitch-filter, multi-driver (ie. open drain) */
26   -
27   -#include "sysbus.h"
28   -
29   -//#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
30   -#define DPRINTF(fmt, ...) do { } while (0)
31   -
32   -/* Segment Display */
33   -#define SEGTOP // displayed at the top of the terminal window
34   -#define SEGPUTCHAR(com, pin, offset, symb) \
35   -if (!(s->odsr & (1 << com)) && (s->odsr & (1 << pin))) segline[offset] = symb
36   -#ifdef SEGTOP
37   - #define SEGPRINT printf("\x1B[%d;60H%s", ln++, segline)
38   -#else
39   - #define SEGPRINT printf("\x1B[20C%s\n", segline)
40   -#endif
41   -
42   -
43   -/*
44   - * Input/Output GPIO pins:
45   - * 32x PIO device
46   - * 32x peripheral A
47   - * 32x peripheral B
48   - */
49   -
50   -#define PIO_SIZE 0x200
51   -#define PIO_PINS 32
52   -
53   -#define PIO_PER 0x00 /* PIO Enable Register */
54   -#define PIO_PDR 0x04 /* PIO Disable Register */
55   -#define PIO_PSR 0x08 /* PIO Status Register */
56   -#define PIO_OER 0x10 /* Output Enable Register */
57   -#define PIO_ODR 0x14 /* Output Disable Register */
58   -#define PIO_OSR 0x18 /* Output Status Register */
59   -#define PIO_IFER 0x20 /* Input Filter Enable Register */
60   -#define PIO_IFDR 0x24 /* Input Filter Disable Register */
61   -#define PIO_IFSR 0x28 /* Input Filter Status Register */
62   -#define PIO_SODR 0x30 /* Set Output Data Register */
63   -#define PIO_CODR 0x34 /* Clear Output Data Register */
64   -#define PIO_ODSR 0x38 /* Output Data Status Register */
65   -#define PIO_PDSR 0x3c /* Pin Data Status Register */
66   -#define PIO_IER 0x40 /* Interrupt Enable Register */
67   -#define PIO_IDR 0x44 /* Interrupt Disable Register */
68   -#define PIO_IMR 0x48 /* Interrupt Mask Register */
69   -#define PIO_ISR 0x4c /* Interrupt Status Register */
70   -#define PIO_MDER 0x50 /* Multi-driver Enable Register */
71   -#define PIO_MDDR 0x54 /* Multi-driver Disable Register */
72   -#define PIO_MDSR 0x58 /* Multi-driver Status Register */
73   -#define PIO_PPUDR 0x60 /* Pull-up Disable Register */
74   -#define PIO_PPUER 0x64 /* Pull-up Enable Register */
75   -#define PIO_PPUSR 0x68 /* Pull-up Status Register */
76   -#define PIO_ASR 0x70 /* Select A Register */
77   -#define PIO_BSR 0x74 /* Select B Register */
78   -#define PIO_ABSR 0x78 /* AB Select Status Register */
79   -#define PIO_OWER 0xa0 /* Output Write Enable Register */
80   -#define PIO_OWDR 0xa4 /* Output Write Disable Register */
81   -#define PIO_OWSR 0xa8 /* Output Write Status Register */
82   -
83   -typedef struct PIOState {
84   - SysBusDevice busdev;
85   - qemu_irq out[PIO_PINS * 3];
86   - qemu_irq parent_irq;
87   - uint32_t psr;
88   - uint32_t osr;
89   - uint32_t ifsr;
90   - uint32_t odsr;
91   - uint32_t pdsr;
92   - uint32_t imr;
93   - uint32_t isr;
94   - uint32_t mdsr;
95   - uint32_t ppusr;
96   - uint32_t absr;
97   - uint32_t owsr;
98   - /* Mask of unknown state of PIO pins, needed for pull-up resistor
99   - implementation */
100   - uint32_t unknown_state;
101   - int portid;
102   -} PIOState;
103   -
104   -void at91_pio_set_pin(void *opaque, int pin, int level)
105   -{
106   - DPRINTF("In at91_pio_set_pin, opaque=%p, pin=%d, level=%d\n", opaque, pin, level);
107   - PIOState *s = opaque;
108   - int mask = 1 << (pin % PIO_PINS);
109   - int input_set = pin / PIO_PINS;
110   - int output_set = !!(s->absr & mask);
111   - uint32_t saved_pdsr;
112   -
113   - if (input_set == 0) {
114   - /* PIO pin -> Peripheral / IO */
115   -
116   - DPRINTF("In at91_pio_set_pin, s->osr=%08x, s->psr=%08x, mask=%08x\n",s->osr, s->psr, mask);
117   -
118   - /* Skip input if output mode is enabled for the pin */
119   - if (s->osr & mask)
120   - return;
121   -
122   - if (s->psr & mask) {
123   - saved_pdsr = s->pdsr;
124   - s->pdsr &= ~mask;
125   - s->unknown_state &= ~mask;
126   - if (level == -1) {
127   - s->unknown_state |= mask;
128   - } else if (level) {
129   - DPRINTF("In at91_pio_set_pin, setting level\n");
130   - s->unknown_state &= ~mask;
131   - s->pdsr |= mask;
132   - }
133   - if (saved_pdsr != s->pdsr) {
134   - s->isr |= mask;
135   - qemu_set_irq(s->parent_irq, !!(s->isr & s->imr));
136   - }
137   - } else {
138   - qemu_set_irq(s->out[PIO_PINS + (output_set * PIO_PINS)], level);
139   - }
140   - DPRINTF("In at91_pio_set_pin, s->pdsr=%08x\n",s->pdsr);
141   -
142   - } else {
143   - /* Peripheral -> PIO pin */
144   - if ((~s->psr & mask) && input_set == output_set) {
145   - qemu_set_irq(s->out[pin & PIO_PINS], level);
146   - }
147   - }
148   -}
149   -
150   -static uint32_t at91_pio_mem_read(void *opaque, target_phys_addr_t offset)
151   -{
152   - PIOState *s = opaque;
153   - int isr;
154   -
155   - offset &= PIO_SIZE - 1;
156   - switch (offset) {
157   - case PIO_PSR:
158   - return s->psr;
159   - case PIO_OSR:
160   - return s->osr;
161   - case PIO_IFSR:
162   - return s->ifsr;
163   - case PIO_ODSR:
164   - return s->odsr;
165   - case PIO_PDSR:
166   - DPRINTF("In at91_pio_mem_read, reading PDSR, s->pdsr=%08x, s->unknown_state=%08x, retval=%08x\n",
167   - s->pdsr, s->unknown_state,
168   - (s->pdsr & ~s->unknown_state) |
169   - (s->ppusr & s->unknown_state));
170   - return
171   - (s->pdsr & ~s->unknown_state) |
172   - (s->ppusr & s->unknown_state);
173   - case PIO_IMR:
174   - return s->imr;
175   - case PIO_ISR:
176   - isr = s->isr;
177   - s->isr = 0;
178   - qemu_set_irq(s->parent_irq, 0);
179   - return isr;
180   - case PIO_MDSR:
181   - return s->mdsr;
182   - case PIO_PPUSR:
183   - return s->ppusr;
184   - case PIO_ABSR:
185   - return s->absr;
186   - case PIO_OWSR:
187   - return s->owsr;
188   - default:
189   - return 0;
190   - }
191   -}
192   -
193   -static void at91_pio_mem_write(void *opaque, target_phys_addr_t offset,
194   - uint32_t value)
195   -{
196   - PIOState *s = opaque;
197   - int i;
198   -
199   - DPRINTF("Writing PIO: portid=%d, offset=0x%08lx, value=0x%08x\n", s->portid, offset, value);
200   -
201   - offset &= PIO_SIZE - 1;
202   -
203   - uint32_t prev;
204   -
205   - int segdisp_refresh = 0;
206   -
207   - switch (offset) {
208   - case PIO_PER:
209   - s->psr |= value; //we should also detect LED state change in some cases
210   - //printf("enabling, psr=0x%08x\n", s->psr);
211   - break;
212   - case PIO_PDR:
213   - s->psr &= ~value;
214   - //printf("disabling, psr=0x%08x\n", s->psr);
215   - break;
216   - case PIO_OER:
217   - s->osr |= value;
218   - break;
219   - case PIO_ODR:
220   - s->osr &= ~value;
221   - break;
222   - case PIO_IFER:
223   - s->ifsr |= value;
224   - break;
225   - case PIO_IFDR:
226   - s->ifsr &= ~value;
227   - break;
228   - case PIO_SODR:
229   - prev = s->odsr;
230   - s->odsr |= value;
231   - for (i = 0; i < PIO_PINS; i++)
232   - if (value & (1 << i) & s->osr & s->psr)
233   - {
234   - qemu_set_irq(s->out[i], 1);
235   - if ((prev & (1 << i)) != (s->odsr & (1 << i)))
236   - {
237   - DPRINTF("Port %c%d set\n",'A' + s->portid, i);
238   - if (
239   - (s->portid == 1) && (i >= 20) && (i <= 27)
240   - && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) )
241   - && !(s->odsr & (1 << 31))
242   - )
243   - segdisp_refresh = 1;
244   - else if (
245   - ((s->portid == 1) && ((i == 28) || (i == 30))
246   - && !(s->odsr & (1 << 31)))
247   - || ((s->portid == 1) && (i == 31)
248   - && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) ))
249   - )
250   - segdisp_refresh = 1;
251   - else if ((s->portid == 1) && (i == 8))
252   - printf("LED1 off\n");
253   - else if ((s->portid == 2) && (i == 29))
254   - printf("LED2 off\n");
255   - }
256   - }
257   - break;
258   - case PIO_CODR:
259   - prev = s->odsr;
260   - s->odsr &= ~value;
261   - for (i = 0; i < PIO_PINS; i++)
262   - if (value & (1 << i) & s->osr & s->psr)
263   - {
264   - qemu_set_irq(s->out[i], 0);
265   - if ((prev & (1 << i)) != (s->odsr & (1 << i)))
266   - {
267   - DPRINTF("Port %c%d reset\n",'A' + s->portid, i);
268   - if (
269   - (s->portid == 1) && (i >= 20) && (i <= 27)
270   - && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) )
271   - && !(s->odsr & (1 << 31))
272   - )
273   - segdisp_refresh = 1;
274   - else if (
275   - ((s->portid == 1) && ((i == 28) || (i == 30))
276   - && !(s->odsr & (1 << 31)))
277   - || ((s->portid == 1) && (i == 31)
278   - && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) ))
279   - )
280   - segdisp_refresh = 1;
281   - else if ((s->portid == 1) && (i == 8))
282   - printf("LED1 on\n");
283   - else if ((s->portid == 2) && (i == 29))
284   - printf("LED2 on\n");
285   - }
286   - }
287   - break;
288   - case PIO_ODSR:
289   - prev = s->odsr;
290   - s->odsr = (s->odsr & ~s->owsr) | (value & s->owsr);
291   - for (i = 0; i < PIO_PINS; i++)
292   - if (s->owsr & (1 << i))
293   - {
294   - qemu_set_irq(s->out[i], !!(value & (1 << i)));
295   - if ((prev & (1 << i)) != (s->odsr & (1 << i)))
296   - {
297   - DPRINTF("Port %c%d written\n",'A' + s->portid, i);
298   - if (
299   - (s->portid == 1) && (i >= 20) && (i <= 27)
300   - && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) )
301   - && !(s->odsr & (1 << 31))
302   - )
303   - segdisp_refresh = 1;
304   - else if (
305   - ((s->portid == 1) && ((i == 28) || (i == 30))
306   - && !(s->odsr & (1 << 31)))
307   - || ((s->portid == 1) && (i == 31)
308   - && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) ))
309   - )
310   - segdisp_refresh = 1;
311   - else if ((s->portid == 1) && (i == 8))
312   - printf("LED1 %s\n", ((s->odsr & (1 << i)) ? "off" : "on"));
313   - else if ((s->portid == 2) && (i == 29))
314   - printf("LED2 %s\n", ((s->odsr & (1 << i)) ? "off" : "on"));
315   - }
316   - }
317   - break;
318   - case PIO_IER:
319   - s->imr |= value;
320   - break;
321   - case PIO_IDR:
322   - s->imr &= ~value;
323   - break;
324   - case PIO_MDER:
325   - s->mdsr |= value;
326   - break;
327   - case PIO_MDDR:
328   - s->mdsr &= ~value;
329   - break;
330   - case PIO_PPUER:
331   - s->ppusr |= value;
332   - break;
333   - case PIO_PPUDR:
334   - s->ppusr &= ~value;
335   - break;
336   - case PIO_ASR:
337   - s->absr &= ~value;
338   - break;
339   - case PIO_BSR:
340   - s->absr |= value;
341   - break;
342   - case PIO_OWER:
343   - s->owsr |= value;
344   - break;
345   - case PIO_OWDR:
346   - s->owsr &= ~value;
347   - break;
348   - default:
349   - return;
350   - }
351   - if (segdisp_refresh)
352   - {
353   - // printf("Segment display changed\n");
354   - char segline[12];
355   - int ln;
356   -
357   -#ifdef SEGTOP
358   - printf("\x1B[s" "\x1B""7");
359   -#else
360   - printf("\n");
361   -#endif
362   - printf("\x1B[91m");
363   -
364   - strcpy(segline, " ");
365   - ln = 1;
366   - SEGPRINT;
367   - SEGPRINT;
368   -
369   - if (s->odsr & (1 << 31))
370   - {
371   - while (ln <= 7)
372   - SEGPRINT;
373   - }
374   - else
375   - {
376   - strcpy(segline, " ");
377   - SEGPUTCHAR(28,25,0+1,'-');
378   - SEGPUTCHAR(28,25,0+2,'-');
379   - SEGPUTCHAR(30,25,6+1,'-');
380   - SEGPUTCHAR(30,25,6+2,'-');
381   - SEGPRINT;
382   -
383   - strcpy(segline, " ");
384   - SEGPUTCHAR(28,27,0+0,'|');
385   - SEGPUTCHAR(28,24,0+3,'|');
386   - SEGPUTCHAR(30,27,6+0,'|');
387   - SEGPUTCHAR(30,24,6+3,'|');
388   - SEGPRINT;
389   -
390   - strcpy(segline, " ");
391   - SEGPUTCHAR(28,26,0+1,'-');
392   - SEGPUTCHAR(28,26,0+2,'-');
393   - SEGPUTCHAR(30,26,6+1,'-');
394   - SEGPUTCHAR(30,26,6+2,'-');
395   - SEGPRINT;
396   -
397   - strcpy(segline, " ");
398   - SEGPUTCHAR(28,20,0+0,'|');
399   - SEGPUTCHAR(28,22,0+3,'|');
400   - SEGPUTCHAR(30,20,6+0,'|');
401   - SEGPUTCHAR(30,22,6+3,'|');
402   - SEGPRINT;
403   -
404   - strcpy(segline, " ");
405   - SEGPUTCHAR(28,21,0+1,'-');
406   - SEGPUTCHAR(28,21,0+2,'-');
407   - SEGPUTCHAR(30,21,6+1,'-');
408   - SEGPUTCHAR(30,21,6+2,'-');
409   - SEGPUTCHAR(28,23,0+4,'.');
410   - SEGPUTCHAR(30,23,6+4,'.');
411   - SEGPRINT;
412   - }
413   -
414   -#ifdef SEGTOP
415   - printf("\x1B""8" "\x1B[u");
416   -#else
417   - printf("\x1B[8A");
418   -#endif
419   - printf("\x1B[0m");
420   - fflush(stdout);
421   - }
422   -}
423   -
424   -static CPUReadMemoryFunc *at91_pio_readfn[] = {
425   - at91_pio_mem_read,
426   - at91_pio_mem_read,
427   - at91_pio_mem_read,
428   -};
429   -
430   -static CPUWriteMemoryFunc *at91_pio_writefn[] = {
431   - at91_pio_mem_write,
432   - at91_pio_mem_write,
433   - at91_pio_mem_write,
434   -};
435   -
436   -static void at91_pio_save(QEMUFile *f, void *opaque)
437   -{
438   - PIOState *s = opaque;
439   -
440   - qemu_put_be32(f, s->psr);
441   - qemu_put_be32(f, s->osr);
442   - qemu_put_be32(f, s->ifsr);
443   - qemu_put_be32(f, s->odsr);
444   - qemu_put_be32(f, s->pdsr);
445   - qemu_put_be32(f, s->imr);
446   - qemu_put_be32(f, s->isr);
447   - qemu_put_be32(f, s->mdsr);
448   - qemu_put_be32(f, s->ppusr);
449   - qemu_put_be32(f, s->absr);
450   - qemu_put_be32(f, s->owsr);
451   - qemu_put_be32(f, s->unknown_state);
452   -}
453   -
454   -static int at91_pio_load(QEMUFile *f, void *opaque, int version_id)
455   -{
456   - PIOState *s = opaque;
457   -
458   - if (version_id != 1)
459   - return -EINVAL;
460   -
461   - s->psr = qemu_get_be32(f);
462   - s->osr = qemu_get_be32(f);
463   - s->ifsr = qemu_get_be32(f);
464   - s->odsr = qemu_get_be32(f);
465   - s->pdsr = qemu_get_be32(f);
466   - s->imr = qemu_get_be32(f);
467   - s->isr = qemu_get_be32(f);
468   - s->mdsr = qemu_get_be32(f);
469   - s->ppusr = qemu_get_be32(f);
470   - s->absr = qemu_get_be32(f);
471   - s->owsr = qemu_get_be32(f);
472   - s->unknown_state = qemu_get_be32(f);
473   -
474   - return 0;
475   -}
476   -
477   -static void at91_pio_reset(void *opaque)
478   -{
479   - PIOState *s = opaque;
480   -
481   - s->psr = 0xffffffff;
482   - s->osr = 0;
483   - s->ifsr = 0;
484   - s->odsr = 0;
485   - s->pdsr = 0;
486   - s->imr = 0;
487   - s->isr = 0;
488   - s->mdsr = 0;
489   - s->ppusr = 0;
490   - s->absr = 0;
491   - s->owsr = 0;
492   - s->unknown_state = 0xffffffff;
493   -}
494   -
495   -void* at91_io_state[5];
496   -int at91_io_cnt = 0;
497   -
498   -static void at91_pio_init(SysBusDevice *dev)
499   -{
500   - DPRINTF("at91_pio_init called\n");
501   - PIOState *s = FROM_SYSBUS(typeof (*s), dev);
502   - s->portid = at91_io_cnt;
503   - at91_io_state[at91_io_cnt++] = s;
504   - int pio_regs;
505   -
506   - sysbus_init_irq(dev, &s->parent_irq);
507   - qdev_init_gpio_in(&dev->qdev, at91_pio_set_pin, PIO_PINS * 3);
508   - qdev_init_gpio_out(&dev->qdev, s->out, PIO_PINS * 3);
509   -
510   - pio_regs = cpu_register_io_memory(at91_pio_readfn, at91_pio_writefn, s);
511   - sysbus_init_mmio(dev, PIO_SIZE, pio_regs);
512   -
513   - at91_pio_reset(s);
514   - qemu_register_reset(at91_pio_reset, s);
515   -
516   - register_savevm("at91_pio", -1, 1, at91_pio_save, at91_pio_load, s);
517   -}
518   -
519   -static void at91_pio_register(void)
520   -{
521   - sysbus_register_dev("at91,pio", sizeof(PIOState), at91_pio_init);
522   -}
523   -
524   -device_init(at91_pio_register)
  1 +/*
  2 + * AT91 Parallel I/O Controller
  3 + *
  4 + * Copyright (c) 2009 Filip Navara
  5 + *
  6 + * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 + * of this software and associated documentation files (the "Software"), to deal
  8 + * in the Software without restriction, including without limitation the rights
  9 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 + * copies of the Software, and to permit persons to whom the Software is
  11 + * furnished to do so, subject to the following conditions:
  12 + *
  13 + * The above copyright notice and this permission notice shall be included in
  14 + * all copies or substantial portions of the Software.
  15 + *
  16 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 + * THE SOFTWARE.
  23 + */
  24 +
  25 +/* TODO: Glitch-filter, multi-driver (ie. open drain) */
  26 +
  27 +#include "sysbus.h"
  28 +
  29 +//#define DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
  30 +#define DPRINTF(fmt, ...) do { } while (0)
  31 +
  32 +/* Segment Display */
  33 +#define SEGTOP // displayed at the top of the terminal window
  34 +#define SEGPUTCHAR(com, pin, offset, symb) \
  35 +if (!(s->odsr & (1 << com)) && (s->odsr & (1 << pin))) segline[offset] = symb
  36 +#ifdef SEGTOP
  37 + #define SEGPRINT printf("\x1B[%d;60H%s", ln++, segline)
  38 +#else
  39 + #define SEGPRINT printf("\x1B[20C%s\n", segline)
  40 +#endif
  41 +
  42 +
  43 +/*
  44 + * Input/Output GPIO pins:
  45 + * 32x PIO device
  46 + * 32x peripheral A
  47 + * 32x peripheral B
  48 + */
  49 +
  50 +#define PIO_SIZE 0x200
  51 +#define PIO_PINS 32
  52 +
  53 +#define PIO_PER 0x00 /* PIO Enable Register */
  54 +#define PIO_PDR 0x04 /* PIO Disable Register */
  55 +#define PIO_PSR 0x08 /* PIO Status Register */
  56 +#define PIO_OER 0x10 /* Output Enable Register */
  57 +#define PIO_ODR 0x14 /* Output Disable Register */
  58 +#define PIO_OSR 0x18 /* Output Status Register */
  59 +#define PIO_IFER 0x20 /* Input Filter Enable Register */
  60 +#define PIO_IFDR 0x24 /* Input Filter Disable Register */
  61 +#define PIO_IFSR 0x28 /* Input Filter Status Register */
  62 +#define PIO_SODR 0x30 /* Set Output Data Register */
  63 +#define PIO_CODR 0x34 /* Clear Output Data Register */
  64 +#define PIO_ODSR 0x38 /* Output Data Status Register */
  65 +#define PIO_PDSR 0x3c /* Pin Data Status Register */
  66 +#define PIO_IER 0x40 /* Interrupt Enable Register */
  67 +#define PIO_IDR 0x44 /* Interrupt Disable Register */
  68 +#define PIO_IMR 0x48 /* Interrupt Mask Register */
  69 +#define PIO_ISR 0x4c /* Interrupt Status Register */
  70 +#define PIO_MDER 0x50 /* Multi-driver Enable Register */
  71 +#define PIO_MDDR 0x54 /* Multi-driver Disable Register */
  72 +#define PIO_MDSR 0x58 /* Multi-driver Status Register */
  73 +#define PIO_PPUDR 0x60 /* Pull-up Disable Register */
  74 +#define PIO_PPUER 0x64 /* Pull-up Enable Register */
  75 +#define PIO_PPUSR 0x68 /* Pull-up Status Register */
  76 +#define PIO_ASR 0x70 /* Select A Register */
  77 +#define PIO_BSR 0x74 /* Select B Register */
  78 +#define PIO_ABSR 0x78 /* AB Select Status Register */
  79 +#define PIO_OWER 0xa0 /* Output Write Enable Register */
  80 +#define PIO_OWDR 0xa4 /* Output Write Disable Register */
  81 +#define PIO_OWSR 0xa8 /* Output Write Status Register */
  82 +
  83 +typedef struct PIOState {
  84 + SysBusDevice busdev;
  85 + qemu_irq out[PIO_PINS * 3];
  86 + qemu_irq parent_irq;
  87 + uint32_t psr;
  88 + uint32_t osr;
  89 + uint32_t ifsr;
  90 + uint32_t odsr;
  91 + uint32_t pdsr;
  92 + uint32_t imr;
  93 + uint32_t isr;
  94 + uint32_t mdsr;
  95 + uint32_t ppusr;
  96 + uint32_t absr;
  97 + uint32_t owsr;
  98 + /* Mask of unknown state of PIO pins, needed for pull-up resistor
  99 + implementation */
  100 + uint32_t unknown_state;
  101 + int portid;
  102 +} PIOState;
  103 +
  104 +void at91_pio_set_pin(void *opaque, int pin, int level)
  105 +{
  106 + DPRINTF("In at91_pio_set_pin, opaque=%p, pin=%d, level=%d\n", opaque, pin, level);
  107 + PIOState *s = opaque;
  108 + int mask = 1 << (pin % PIO_PINS);
  109 + int input_set = pin / PIO_PINS;
  110 + int output_set = !!(s->absr & mask);
  111 + uint32_t saved_pdsr;
  112 +
  113 + if (input_set == 0) {
  114 + /* PIO pin -> Peripheral / IO */
  115 +
  116 + DPRINTF("In at91_pio_set_pin, s->osr=%08x, s->psr=%08x, mask=%08x\n",s->osr, s->psr, mask);
  117 +
  118 + /* Skip input if output mode is enabled for the pin */
  119 + if (s->osr & mask)
  120 + return;
  121 +
  122 + if (s->psr & mask) {
  123 + saved_pdsr = s->pdsr;
  124 + s->pdsr &= ~mask;
  125 + s->unknown_state &= ~mask;
  126 + if (level == -1) {
  127 + s->unknown_state |= mask;
  128 + } else if (level) {
  129 + DPRINTF("In at91_pio_set_pin, setting level\n");
  130 + s->unknown_state &= ~mask;
  131 + s->pdsr |= mask;
  132 + }
  133 + if (saved_pdsr != s->pdsr) {
  134 + s->isr |= mask;
  135 + qemu_set_irq(s->parent_irq, !!(s->isr & s->imr));
  136 + }
  137 + } else {
  138 + qemu_set_irq(s->out[PIO_PINS + (output_set * PIO_PINS)], level);
  139 + }
  140 + DPRINTF("In at91_pio_set_pin, s->pdsr=%08x\n",s->pdsr);
  141 +
  142 + } else {
  143 + /* Peripheral -> PIO pin */
  144 + if ((~s->psr & mask) && input_set == output_set) {
  145 + qemu_set_irq(s->out[pin & PIO_PINS], level);
  146 + }
  147 + }
  148 +}
  149 +
  150 +static uint32_t at91_pio_mem_read(void *opaque, target_phys_addr_t offset)
  151 +{
  152 + PIOState *s = opaque;
  153 + int isr;
  154 +
  155 + offset &= PIO_SIZE - 1;
  156 + switch (offset) {
  157 + case PIO_PSR:
  158 + return s->psr;
  159 + case PIO_OSR:
  160 + return s->osr;
  161 + case PIO_IFSR:
  162 + return s->ifsr;
  163 + case PIO_ODSR:
  164 + return s->odsr;
  165 + case PIO_PDSR:
  166 + DPRINTF("In at91_pio_mem_read, reading PDSR, s->pdsr=%08x, s->unknown_state=%08x, retval=%08x\n",
  167 + s->pdsr, s->unknown_state,
  168 + (s->pdsr & ~s->unknown_state) |
  169 + (s->ppusr & s->unknown_state));
  170 + return
  171 + (s->pdsr & ~s->unknown_state) |
  172 + (s->ppusr & s->unknown_state);
  173 + case PIO_IMR:
  174 + return s->imr;
  175 + case PIO_ISR:
  176 + isr = s->isr;
  177 + s->isr = 0;
  178 + qemu_set_irq(s->parent_irq, 0);
  179 + return isr;
  180 + case PIO_MDSR:
  181 + return s->mdsr;
  182 + case PIO_PPUSR:
  183 + return s->ppusr;
  184 + case PIO_ABSR:
  185 + return s->absr;
  186 + case PIO_OWSR:
  187 + return s->owsr;
  188 + default:
  189 + return 0;
  190 + }
  191 +}
  192 +
  193 +static void at91_pio_mem_write(void *opaque, target_phys_addr_t offset,
  194 + uint32_t value)
  195 +{
  196 + PIOState *s = opaque;
  197 + int i;
  198 +
  199 + DPRINTF("Writing PIO: portid=%d, offset=0x%08lx, value=0x%08x\n", s->portid, offset, value);
  200 +
  201 + offset &= PIO_SIZE - 1;
  202 +
  203 + uint32_t prev;
  204 +
  205 + int segdisp_refresh = 0;
  206 +
  207 + switch (offset) {
  208 + case PIO_PER:
  209 + s->psr |= value; //we should also detect LED state change in some cases
  210 + //printf("enabling, psr=0x%08x\n", s->psr);
  211 + break;
  212 + case PIO_PDR:
  213 + s->psr &= ~value;
  214 + //printf("disabling, psr=0x%08x\n", s->psr);
  215 + break;
  216 + case PIO_OER:
  217 + s->osr |= value;
  218 + break;
  219 + case PIO_ODR:
  220 + s->osr &= ~value;
  221 + break;
  222 + case PIO_IFER:
  223 + s->ifsr |= value;
  224 + break;
  225 + case PIO_IFDR:
  226 + s->ifsr &= ~value;
  227 + break;
  228 + case PIO_SODR:
  229 + prev = s->odsr;
  230 + s->odsr |= value;
  231 + for (i = 0; i < PIO_PINS; i++)
  232 + if (value & (1 << i) & s->osr & s->psr)
  233 + {
  234 + qemu_set_irq(s->out[i], 1);
  235 + if ((prev & (1 << i)) != (s->odsr & (1 << i)))
  236 + {
  237 + DPRINTF("Port %c%d set\n",'A' + s->portid, i);
  238 + if (
  239 + (s->portid == 1) && (i >= 20) && (i <= 27)
  240 + && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) )
  241 + && !(s->odsr & (1 << 31))
  242 + )
  243 + segdisp_refresh = 1;
  244 + else if (
  245 + ((s->portid == 1) && ((i == 28) || (i == 30))
  246 + && !(s->odsr & (1 << 31)))
  247 + || ((s->portid == 1) && (i == 31)
  248 + && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) ))
  249 + )
  250 + segdisp_refresh = 1;
  251 + else if ((s->portid == 1) && (i == 8))
  252 + printf("LED1 off\n");
  253 + else if ((s->portid == 2) && (i == 29))
  254 + printf("LED2 off\n");
  255 + }
  256 + }
  257 + break;
  258 + case PIO_CODR:
  259 + prev = s->odsr;
  260 + s->odsr &= ~value;
  261 + for (i = 0; i < PIO_PINS; i++)
  262 + if (value & (1 << i) & s->osr & s->psr)
  263 + {
  264 + qemu_set_irq(s->out[i], 0);
  265 + if ((prev & (1 << i)) != (s->odsr & (1 << i)))
  266 + {
  267 + DPRINTF("Port %c%d reset\n",'A' + s->portid, i);
  268 + if (
  269 + (s->portid == 1) && (i >= 20) && (i <= 27)
  270 + && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) )
  271 + && !(s->odsr & (1 << 31))
  272 + )
  273 + segdisp_refresh = 1;
  274 + else if (
  275 + ((s->portid == 1) && ((i == 28) || (i == 30))
  276 + && !(s->odsr & (1 << 31)))
  277 + || ((s->portid == 1) && (i == 31)
  278 + && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) ))
  279 + )
  280 + segdisp_refresh = 1;
  281 + else if ((s->portid == 1) && (i == 8))
  282 + printf("LED1 on\n");
  283 + else if ((s->portid == 2) && (i == 29))
  284 + printf("LED2 on\n");
  285 + }
  286 + }
  287 + break;
  288 + case PIO_ODSR:
  289 + prev = s->odsr;
  290 + s->odsr = (s->odsr & ~s->owsr) | (value & s->owsr);
  291 + for (i = 0; i < PIO_PINS; i++)
  292 + if (s->owsr & (1 << i))
  293 + {
  294 + qemu_set_irq(s->out[i], !!(value & (1 << i)));
  295 + if ((prev & (1 << i)) != (s->odsr & (1 << i)))
  296 + {
  297 + DPRINTF("Port %c%d written\n",'A' + s->portid, i);
  298 + if (
  299 + (s->portid == 1) && (i >= 20) && (i <= 27)
  300 + && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) )
  301 + && !(s->odsr & (1 << 31))
  302 + )
  303 + segdisp_refresh = 1;
  304 + else if (
  305 + ((s->portid == 1) && ((i == 28) || (i == 30))
  306 + && !(s->odsr & (1 << 31)))
  307 + || ((s->portid == 1) && (i == 31)
  308 + && ( !(s->odsr & (1 << 28)) || !(s->odsr & (1 << 30)) ))
  309 + )
  310 + segdisp_refresh = 1;
  311 + else if ((s->portid == 1) && (i == 8))
  312 + printf("LED1 %s\n", ((s->odsr & (1 << i)) ? "off" : "on"));
  313 + else if ((s->portid == 2) && (i == 29))
  314 + printf("LED2 %s\n", ((s->odsr & (1 << i)) ? "off" : "on"));
  315 + }
  316 + }
  317 + break;
  318 + case PIO_IER:
  319 + s->imr |= value;
  320 + break;
  321 + case PIO_IDR:
  322 + s->imr &= ~value;
  323 + break;
  324 + case PIO_MDER:
  325 + s->mdsr |= value;
  326 + break;
  327 + case PIO_MDDR:
  328 + s->mdsr &= ~value;
  329 + break;
  330 + case PIO_PPUER:
  331 + s->ppusr |= value;
  332 + break;
  333 + case PIO_PPUDR:
  334 + s->ppusr &= ~value;
  335 + break;
  336 + case PIO_ASR:
  337 + s->absr &= ~value;
  338 + break;
  339 + case PIO_BSR:
  340 + s->absr |= value;
  341 + break;
  342 + case PIO_OWER:
  343 + s->owsr |= value;
  344 + break;
  345 + case PIO_OWDR:
  346 + s->owsr &= ~value;
  347 + break;
  348 + default:
  349 + return;
  350 + }
  351 + if (segdisp_refresh)
  352 + {
  353 + // printf("Segment display changed\n");
  354 + char segline[12];
  355 + int ln;
  356 +
  357 +#ifdef SEGTOP
  358 + printf("\x1B[s" "\x1B""7");
  359 +#else
  360 + printf("\n");
  361 +#endif
  362 + printf("\x1B[91m");
  363 +
  364 + strcpy(segline, " ");
  365 + ln = 1;
  366 + SEGPRINT;
  367 + SEGPRINT;
  368 +
  369 + if (s->odsr & (1 << 31))
  370 + {
  371 + while (ln <= 7)
  372 + SEGPRINT;
  373 + }
  374 + else
  375 + {
  376 + strcpy(segline, " ");
  377 + SEGPUTCHAR(28,25,0+1,'-');
  378 + SEGPUTCHAR(28,25,0+2,'-');
  379 + SEGPUTCHAR(30,25,6+1,'-');
  380 + SEGPUTCHAR(30,25,6+2,'-');
  381 + SEGPRINT;
  382 +
  383 + strcpy(segline, " ");
  384 + SEGPUTCHAR(28,27,0+0,'|');
  385 + SEGPUTCHAR(28,24,0+3,'|');
  386 + SEGPUTCHAR(30,27,6+0,'|');
  387 + SEGPUTCHAR(30,24,6+3,'|');
  388 + SEGPRINT;
  389 +
  390 + strcpy(segline, " ");
  391 + SEGPUTCHAR(28,26,0+1,'-');
  392 + SEGPUTCHAR(28,26,0+2,'-');
  393 + SEGPUTCHAR(30,26,6+1,'-');
  394 + SEGPUTCHAR(30,26,6+2,'-');
  395 + SEGPRINT;
  396 +
  397 + strcpy(segline, " ");
  398 + SEGPUTCHAR(28,20,0+0,'|');
  399 + SEGPUTCHAR(28,22,0+3,'|');
  400 + SEGPUTCHAR(30,20,6+0,'|');
  401 + SEGPUTCHAR(30,22,6+3,'|');
  402 + SEGPRINT;
  403 +
  404 + strcpy(segline, " ");
  405 + SEGPUTCHAR(28,21,0+1,'-');
  406 + SEGPUTCHAR(28,21,0+2,'-');
  407 + SEGPUTCHAR(30,21,6+1,'-');
  408 + SEGPUTCHAR(30,21,6+2,'-');
  409 + SEGPUTCHAR(28,23,0+4,'.');
  410 + SEGPUTCHAR(30,23,6+4,'.');
  411 + SEGPRINT;
  412 + }
  413 +
  414 +#ifdef SEGTOP
  415 + printf("\x1B""8" "\x1B[u");
  416 +#else
  417 + printf("\x1B[8A");
  418 +#endif
  419 + printf("\x1B[0m");
  420 + fflush(stdout);
  421 + }
  422 +}
  423 +
  424 +static CPUReadMemoryFunc *at91_pio_readfn[] = {
  425 + at91_pio_mem_read,
  426 + at91_pio_mem_read,
  427 + at91_pio_mem_read,
  428 +};
  429 +
  430 +static CPUWriteMemoryFunc *at91_pio_writefn[] = {
  431 + at91_pio_mem_write,
  432 + at91_pio_mem_write,
  433 + at91_pio_mem_write,
  434 +};
  435 +
  436 +static void at91_pio_save(QEMUFile *f, void *opaque)
  437 +{
  438 + PIOState *s = opaque;
  439 +
  440 + qemu_put_be32(f, s->psr);
  441 + qemu_put_be32(f, s->osr);
  442 + qemu_put_be32(f, s->ifsr);
  443 + qemu_put_be32(f, s->odsr);
  444 + qemu_put_be32(f, s->pdsr);
  445 + qemu_put_be32(f, s->imr);
  446 + qemu_put_be32(f, s->isr);
  447 + qemu_put_be32(f, s->mdsr);
  448 + qemu_put_be32(f, s->ppusr);
  449 + qemu_put_be32(f, s->absr);
  450 + qemu_put_be32(f, s->owsr);
  451 + qemu_put_be32(f, s->unknown_state);
  452 +}
  453 +
  454 +static int at91_pio_load(QEMUFile *f, void *opaque, int version_id)
  455 +{
  456 + PIOState *s = opaque;
  457 +
  458 + if (version_id != 1)
  459 + return -EINVAL;
  460 +
  461 + s->psr = qemu_get_be32(f);
  462 + s->osr = qemu_get_be32(f);
  463 + s->ifsr = qemu_get_be32(f);
  464 + s->odsr = qemu_get_be32(f);
  465 + s->pdsr = qemu_get_be32(f);
  466 + s->imr = qemu_get_be32(f);
  467 + s->isr = qemu_get_be32(f);
  468 + s->mdsr = qemu_get_be32(f);
  469 + s->ppusr = qemu_get_be32(f);
  470 + s->absr = qemu_get_be32(f);
  471 + s->owsr = qemu_get_be32(f);
  472 + s->unknown_state = qemu_get_be32(f);
  473 +
  474 + return 0;
  475 +}
  476 +
  477 +static void at91_pio_reset(void *opaque)
  478 +{
  479 + PIOState *s = opaque;
  480 +
  481 + s->psr = 0xffffffff;
  482 + s->osr = 0;
  483 + s->ifsr = 0;
  484 + s->odsr = 0;
  485 + s->pdsr = 0;
  486 + s->imr = 0;
  487 + s->isr = 0;
  488 + s->mdsr = 0;
  489 + s->ppusr = 0;
  490 + s->absr = 0;
  491 + s->owsr = 0;
  492 + s->unknown_state = 0xffffffff;
  493 +}
  494 +
  495 +void* at91_io_state[5];
  496 +int at91_io_cnt = 0;
  497 +
  498 +static void at91_pio_init(SysBusDevice *dev)
  499 +{
  500 + DPRINTF("at91_pio_init called\n");
  501 + PIOState *s = FROM_SYSBUS(typeof (*s), dev);
  502 + s->portid = at91_io_cnt;
  503 + at91_io_state[at91_io_cnt++] = s;
  504 + int pio_regs;
  505 +
  506 + sysbus_init_irq(dev, &s->parent_irq);
  507 + qdev_init_gpio_in(&dev->qdev, at91_pio_set_pin, PIO_PINS * 3);
  508 + qdev_init_gpio_out(&dev->qdev, s->out, PIO_PINS * 3);
  509 +
  510 + pio_regs = cpu_register_io_memory(at91_pio_readfn, at91_pio_writefn, s);
  511 + sysbus_init_mmio(dev, PIO_SIZE, pio_regs);
  512 +
  513 + at91_pio_reset(s);
  514 + qemu_register_reset(at91_pio_reset, s);
  515 +
  516 + register_savevm("at91_pio", -1, 1, at91_pio_save, at91_pio_load, s);
  517 +}
  518 +
  519 +static void at91_pio_register(void)
  520 +{
  521 + sysbus_register_dev("at91,pio", sizeof(PIOState), at91_pio_init);
  522 +}
  523 +
  524 +device_init(at91_pio_register)
... ...