Merge git://gitorious.org/~luki/simavr/lukis-simavr into dev-home
[simavr] / simavr / sim / sim_io.c
1 /*
2         sim_io.c
3
4         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "sim_io.h"
27
28 int avr_ioctl(avr_t *avr, uint32_t ctl, void * io_param)
29 {
30         avr_io_t * port = avr->io_port;
31         int res = -1;
32         while (port && res == -1) {
33                 if (port->ioctl)
34                         res = port->ioctl(port, ctl, io_param);
35                 port = port->next;
36         }
37         return res;
38 }
39
40 void avr_register_io(avr_t *avr, avr_io_t * io)
41 {
42         io->next = avr->io_port;
43         io->avr = avr;
44         avr->io_port = io;
45 }
46
47 void avr_register_io_read(avr_t *avr, avr_io_addr_t addr, avr_io_read_t readp, void * param)
48 {
49         avr_io_addr_t a = AVR_DATA_TO_IO(addr);
50         avr->io[a].r.param = param;
51         avr->io[a].r.c = readp;
52 }
53
54 void avr_register_io_write(avr_t *avr, avr_io_addr_t addr, avr_io_write_t writep, void * param)
55 {
56         avr_io_addr_t a = AVR_DATA_TO_IO(addr);
57         avr->io[a].w.param = param;
58         avr->io[a].w.c = writep;
59 }
60
61 struct avr_irq_t * avr_io_getirq(avr_t * avr, uint32_t ctl, int index)
62 {
63         avr_io_t * port = avr->io_port;
64         while (port) {
65                 if (port->irq && port->irq_ioctl_get == ctl && port->irq_count > index)
66                         return port->irq + index;
67                 port = port->next;
68         }
69         return NULL;
70         
71 }
72
73 avr_irq_t * avr_iomem_getirq(avr_t * avr, avr_io_addr_t addr, int index)
74 {
75         avr_io_addr_t a = AVR_DATA_TO_IO(addr);
76         if (avr->io[a].irq == NULL) {
77                 avr->io[a].irq = avr_alloc_irq(0, 9);
78                 // mark the pin ones as filtered, so they only are raised when changing
79                 for (int i = 0; i < 8; i++)
80                         avr->io[a].irq[i].flags |= IRQ_FLAG_FILTERED;
81         }
82         return index < 9 ? avr->io[a].irq + index : NULL;
83 }
84
85 struct avr_irq_t * avr_io_setirqs(avr_io_t * io, uint32_t ctl, int count, struct avr_irq_t * irqs)
86 {
87         // allocate this module's IRQ
88         io->irq_count = count;
89         io->irq = irqs ? irqs : avr_alloc_irq(0, count);
90         io->irq_ioctl_get = ctl;
91         return io->irq;
92 }
93
94 static void avr_deallocate_io(avr_io_t * io)
95 {
96         if (io->dealloc)
97                 io->dealloc(io);
98         avr_free_irq(io->irq, io->irq_count);
99         io->irq_count = 0;
100         io->irq_ioctl_get = 0;
101         io->avr = NULL;
102         io->next = NULL;
103 }
104
105 void avr_deallocate_ios(avr_t * avr)
106 {
107         avr_io_t * port = avr->io_port;
108         while (port) {
109                 avr_io_t * next = port->next;
110                 avr_deallocate_io(port);
111                 port = next;
112         }
113         avr->io_port = NULL;
114 }