4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
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.
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.
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/>.
36 avr_io_t * port = avr->io_port;
38 while (port && res == -1) {
40 res = port->ioctl(port, ctl, io_param);
51 io->next = avr->io_port;
63 avr_io_addr_t a = AVR_DATA_TO_IO(addr);
64 if (avr->io[a].r.param || avr->io[a].r.c) {
65 if (avr->io[a].r.param != param || avr->io[a].r.c != readp) {
66 AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_read(): Already registered, refusing to override.\n");
67 AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_read(%04x : %p/%p): %p/%p\n", a,
68 avr->io[a].r.c, avr->io[a].r.param, readp, param);
72 avr->io[a].r.param = param;
73 avr->io[a].r.c = readp;
83 int io = (intptr_t)param;
84 for (int i = 0; i < avr->io_shared_io[io].used; i++) {
85 avr_io_write_t c = avr->io_shared_io[io].io[i].c;
87 c(avr, addr, v, avr->io_shared_io[io].io[i].param);
92 avr_register_io_write(
95 avr_io_write_t writep,
98 avr_io_addr_t a = AVR_DATA_TO_IO(addr);
101 AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_write(): IO address 0x%04x out of range (max 0x%04x).\n",
106 * Verifying that some other piece of code is not installed to watch write
107 * on this address. If there is, this code installs a "dispatcher" callback
108 * instead to handle multiple clients, otherwise, it continues as usual
110 if (avr->io[a].w.param || avr->io[a].w.c) {
111 if (avr->io[a].w.param != param || avr->io[a].w.c != writep) {
112 // if the muxer not already installed, allocate a new slot
113 if (avr->io[a].w.c != _avr_io_mux_write) {
114 int no = avr->io_shared_io_count++;
115 if (avr->io_shared_io_count > 4) {
116 AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_write(): Too many shared IO registers.\n");
119 AVR_LOG(avr, LOG_TRACE, "IO: avr_register_io_write(%04x): Installing muxer on register.\n", addr);
120 avr->io_shared_io[no].used = 1;
121 avr->io_shared_io[no].io[0].param = avr->io[a].w.param;
122 avr->io_shared_io[no].io[0].c = avr->io[a].w.c;
123 avr->io[a].w.param = (void*)(intptr_t)no;
124 avr->io[a].w.c = _avr_io_mux_write;
126 int no = (intptr_t)avr->io[a].w.param;
127 int d = avr->io_shared_io[no].used++;
128 if (avr->io_shared_io[no].used > 4) {
129 AVR_LOG(avr, LOG_ERROR, "IO: avr_register_io_write(): Too many callbacks on %04x.\n", addr);
132 avr->io_shared_io[no].io[d].param = param;
133 avr->io_shared_io[no].io[d].c = writep;
137 avr->io[a].w.param = param;
138 avr->io[a].w.c = writep;
147 avr_io_t * port = avr->io_port;
149 if (port->irq && port->irq_ioctl_get == ctl && port->irq_count > index)
150 return port->irq + index;
163 avr_io_addr_t a = AVR_DATA_TO_IO(addr);
164 if (avr->io[a].irq == NULL) {
166 * Prepare an array of names for the io IRQs. Ideally we'd love to have
167 * a proper name for these, but it's not possible at this time.
171 const char * namep[9];
172 for (int ni = 0; ni < 9; ni++) {
174 sprintf(d, "=avr.io%04x.%d", addr, ni);
176 sprintf(d, "8=avr.io%04x.all", addr);
180 avr->io[a].irq = avr_alloc_irq(&avr->irq_pool, 0, 9, namep);
181 // mark the pin ones as filtered, so they only are raised when changing
182 for (int i = 0; i < 8; i++)
183 avr->io[a].irq[i].flags |= IRQ_FLAG_FILTERED;
185 return index < 9 ? avr->io[a].irq + index : NULL;
195 // allocate this module's IRQ
196 io->irq_count = count;
199 const char ** irq_names = NULL;
202 irq_names = malloc(count * sizeof(char*));
203 memset(irq_names, 0, count * sizeof(char*));
205 for (int i = 0; i < count; i++) {
207 * this bit takes the io module 'kind' ("port")
208 * the IRQ name ("=0") and the last character of the ioctl ('p','o','r','A')
209 * to create a full name "=porta.0"
212 // copy the 'flags' of the name out
213 const char * kind = io->irq_names[i];
214 while (isdigit(*kind))
216 while (!isalpha(*kind))
219 // strcpy(dst, io->avr->mmcu);
224 strcpy(dst, io->kind);
226 // add port name, if any
227 if ((ctl & 0xff) > ' ')
228 *dst ++ = tolower(ctl & 0xff);
230 // add the rest of the irq name
235 // printf("%s\n", buf);
236 irq_names[i] = strdup(buf);
239 irqs = avr_alloc_irq(&io->avr->irq_pool, 0,
242 for (int i = 0; i < count; i++)
243 free((char*)irq_names[i]);
244 free((char*)irq_names);
249 io->irq_ioctl_get = ctl;
259 avr_free_irq(io->irq, io->irq_count);
261 io->irq_ioctl_get = 0;
270 avr_io_t * port = avr->io_port;
272 avr_io_t * next = port->next;
273 avr_deallocate_io(port);