8250: Customized base baudrate
[qemu] / hw / slavio_misc.c
1 /*
2  * QEMU Sparc SLAVIO aux io port emulation
3  *
4  * Copyright (c) 2005 Fabrice Bellard
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 #include "hw.h"
25 #include "sun4m.h"
26 #include "sysemu.h"
27
28 /* debug misc */
29 //#define DEBUG_MISC
30
31 /*
32  * This is the auxio port, chip control and system control part of
33  * chip STP2001 (Slave I/O), also produced as NCR89C105. See
34  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
35  *
36  * This also includes the PMC CPU idle controller.
37  */
38
39 #ifdef DEBUG_MISC
40 #define MISC_DPRINTF(fmt, args...) \
41 do { printf("MISC: " fmt , ##args); } while (0)
42 #else
43 #define MISC_DPRINTF(fmt, args...)
44 #endif
45
46 typedef struct MiscState {
47     qemu_irq irq;
48     uint8_t config;
49     uint8_t aux1, aux2;
50     uint8_t diag, mctrl;
51     uint32_t sysctrl;
52     uint16_t leds;
53     CPUState *env;
54     qemu_irq fdc_tc;
55 } MiscState;
56
57 #define MISC_SIZE 1
58 #define SYSCTRL_MAXADDR 3
59 #define SYSCTRL_SIZE (SYSCTRL_MAXADDR + 1)
60 #define LED_MAXADDR 1
61 #define LED_SIZE (LED_MAXADDR + 1)
62
63 #define MISC_MASK 0x0fff0000
64 #define MISC_LEDS 0x01600000
65 #define MISC_CFG  0x01800000
66 #define MISC_DIAG 0x01a00000
67 #define MISC_MDM  0x01b00000
68 #define MISC_SYS  0x01f00000
69
70 #define AUX1_TC        0x02
71
72 #define AUX2_PWROFF    0x01
73 #define AUX2_PWRINTCLR 0x02
74 #define AUX2_PWRFAIL   0x20
75
76 #define CFG_PWRINTEN   0x08
77
78 #define SYS_RESET      0x01
79 #define SYS_RESETSTAT  0x02
80
81 static void slavio_misc_update_irq(void *opaque)
82 {
83     MiscState *s = opaque;
84
85     if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
86         MISC_DPRINTF("Raise IRQ\n");
87         qemu_irq_raise(s->irq);
88     } else {
89         MISC_DPRINTF("Lower IRQ\n");
90         qemu_irq_lower(s->irq);
91     }
92 }
93
94 static void slavio_misc_reset(void *opaque)
95 {
96     MiscState *s = opaque;
97
98     // Diagnostic and system control registers not cleared in reset
99     s->config = s->aux1 = s->aux2 = s->mctrl = 0;
100 }
101
102 void slavio_set_power_fail(void *opaque, int power_failing)
103 {
104     MiscState *s = opaque;
105
106     MISC_DPRINTF("Power fail: %d, config: %d\n", power_failing, s->config);
107     if (power_failing && (s->config & CFG_PWRINTEN)) {
108         s->aux2 |= AUX2_PWRFAIL;
109     } else {
110         s->aux2 &= ~AUX2_PWRFAIL;
111     }
112     slavio_misc_update_irq(s);
113 }
114
115 static void slavio_misc_mem_writeb(void *opaque, target_phys_addr_t addr,
116                                    uint32_t val)
117 {
118     MiscState *s = opaque;
119
120     switch (addr & MISC_MASK) {
121     case MISC_CFG:
122         MISC_DPRINTF("Write config %2.2x\n", val & 0xff);
123         s->config = val & 0xff;
124         slavio_misc_update_irq(s);
125         break;
126     case MISC_DIAG:
127         MISC_DPRINTF("Write diag %2.2x\n", val & 0xff);
128         s->diag = val & 0xff;
129         break;
130     case MISC_MDM:
131         MISC_DPRINTF("Write modem control %2.2x\n", val & 0xff);
132         s->mctrl = val & 0xff;
133         break;
134     default:
135         break;
136     }
137 }
138
139 static uint32_t slavio_misc_mem_readb(void *opaque, target_phys_addr_t addr)
140 {
141     MiscState *s = opaque;
142     uint32_t ret = 0;
143
144     switch (addr & MISC_MASK) {
145     case MISC_CFG:
146         ret = s->config;
147         MISC_DPRINTF("Read config %2.2x\n", ret);
148         break;
149     case MISC_DIAG:
150         ret = s->diag;
151         MISC_DPRINTF("Read diag %2.2x\n", ret);
152         break;
153     case MISC_MDM:
154         ret = s->mctrl;
155         MISC_DPRINTF("Read modem control %2.2x\n", ret);
156         break;
157     default:
158         break;
159     }
160     return ret;
161 }
162
163 static CPUReadMemoryFunc *slavio_misc_mem_read[3] = {
164     slavio_misc_mem_readb,
165     NULL,
166     NULL,
167 };
168
169 static CPUWriteMemoryFunc *slavio_misc_mem_write[3] = {
170     slavio_misc_mem_writeb,
171     NULL,
172     NULL,
173 };
174
175 static void slavio_aux1_mem_writeb(void *opaque, target_phys_addr_t addr,
176                                    uint32_t val)
177 {
178     MiscState *s = opaque;
179
180     MISC_DPRINTF("Write aux1 %2.2x\n", val & 0xff);
181     if (val & AUX1_TC) {
182         // Send a pulse to floppy terminal count line
183         if (s->fdc_tc) {
184             qemu_irq_raise(s->fdc_tc);
185             qemu_irq_lower(s->fdc_tc);
186         }
187         val &= ~AUX1_TC;
188     }
189     s->aux1 = val & 0xff;
190 }
191
192 static uint32_t slavio_aux1_mem_readb(void *opaque, target_phys_addr_t addr)
193 {
194     MiscState *s = opaque;
195     uint32_t ret = 0;
196
197     ret = s->aux1;
198     MISC_DPRINTF("Read aux1 %2.2x\n", ret);
199
200     return ret;
201 }
202
203 static CPUReadMemoryFunc *slavio_aux1_mem_read[3] = {
204     slavio_aux1_mem_readb,
205     NULL,
206     NULL,
207 };
208
209 static CPUWriteMemoryFunc *slavio_aux1_mem_write[3] = {
210     slavio_aux1_mem_writeb,
211     NULL,
212     NULL,
213 };
214
215 static void slavio_aux2_mem_writeb(void *opaque, target_phys_addr_t addr,
216                                    uint32_t val)
217 {
218     MiscState *s = opaque;
219
220     val &= AUX2_PWRINTCLR | AUX2_PWROFF;
221     MISC_DPRINTF("Write aux2 %2.2x\n", val);
222     val |= s->aux2 & AUX2_PWRFAIL;
223     if (val & AUX2_PWRINTCLR) // Clear Power Fail int
224         val &= AUX2_PWROFF;
225     s->aux2 = val;
226     if (val & AUX2_PWROFF)
227         qemu_system_shutdown_request();
228     slavio_misc_update_irq(s);
229 }
230
231 static uint32_t slavio_aux2_mem_readb(void *opaque, target_phys_addr_t addr)
232 {
233     MiscState *s = opaque;
234     uint32_t ret = 0;
235
236     ret = s->aux2;
237     MISC_DPRINTF("Read aux2 %2.2x\n", ret);
238
239     return ret;
240 }
241
242 static CPUReadMemoryFunc *slavio_aux2_mem_read[3] = {
243     slavio_aux2_mem_readb,
244     NULL,
245     NULL,
246 };
247
248 static CPUWriteMemoryFunc *slavio_aux2_mem_write[3] = {
249     slavio_aux2_mem_writeb,
250     NULL,
251     NULL,
252 };
253
254 static void apc_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
255 {
256     MiscState *s = opaque;
257
258     MISC_DPRINTF("Write power management %2.2x\n", val & 0xff);
259     cpu_interrupt(s->env, CPU_INTERRUPT_HALT);
260 }
261
262 static uint32_t apc_mem_readb(void *opaque, target_phys_addr_t addr)
263 {
264     uint32_t ret = 0;
265
266     MISC_DPRINTF("Read power management %2.2x\n", ret);
267     return ret;
268 }
269
270 static CPUReadMemoryFunc *apc_mem_read[3] = {
271     apc_mem_readb,
272     NULL,
273     NULL,
274 };
275
276 static CPUWriteMemoryFunc *apc_mem_write[3] = {
277     apc_mem_writeb,
278     NULL,
279     NULL,
280 };
281
282 static uint32_t slavio_sysctrl_mem_readl(void *opaque, target_phys_addr_t addr)
283 {
284     MiscState *s = opaque;
285     uint32_t ret = 0, saddr;
286
287     saddr = addr & SYSCTRL_MAXADDR;
288     switch (saddr) {
289     case 0:
290         ret = s->sysctrl;
291         break;
292     default:
293         break;
294     }
295     MISC_DPRINTF("Read system control reg 0x" TARGET_FMT_plx " = %x\n", addr,
296                  ret);
297     return ret;
298 }
299
300 static void slavio_sysctrl_mem_writel(void *opaque, target_phys_addr_t addr,
301                                       uint32_t val)
302 {
303     MiscState *s = opaque;
304     uint32_t saddr;
305
306     saddr = addr & SYSCTRL_MAXADDR;
307     MISC_DPRINTF("Write system control reg 0x" TARGET_FMT_plx " =  %x\n", addr,
308                  val);
309     switch (saddr) {
310     case 0:
311         if (val & SYS_RESET) {
312             s->sysctrl = SYS_RESETSTAT;
313             qemu_system_reset_request();
314         }
315         break;
316     default:
317         break;
318     }
319 }
320
321 static CPUReadMemoryFunc *slavio_sysctrl_mem_read[3] = {
322     NULL,
323     NULL,
324     slavio_sysctrl_mem_readl,
325 };
326
327 static CPUWriteMemoryFunc *slavio_sysctrl_mem_write[3] = {
328     NULL,
329     NULL,
330     slavio_sysctrl_mem_writel,
331 };
332
333 static uint32_t slavio_led_mem_readw(void *opaque, target_phys_addr_t addr)
334 {
335     MiscState *s = opaque;
336     uint32_t ret = 0, saddr;
337
338     saddr = addr & LED_MAXADDR;
339     switch (saddr) {
340     case 0:
341         ret = s->leds;
342         break;
343     default:
344         break;
345     }
346     MISC_DPRINTF("Read diagnostic LED reg 0x" TARGET_FMT_plx " = %x\n", addr,
347                  ret);
348     return ret;
349 }
350
351 static void slavio_led_mem_writew(void *opaque, target_phys_addr_t addr,
352                                   uint32_t val)
353 {
354     MiscState *s = opaque;
355     uint32_t saddr;
356
357     saddr = addr & LED_MAXADDR;
358     MISC_DPRINTF("Write diagnostic LED reg 0x" TARGET_FMT_plx " =  %x\n", addr,
359                  val);
360     switch (saddr) {
361     case 0:
362         s->leds = val;
363         break;
364     default:
365         break;
366     }
367 }
368
369 static CPUReadMemoryFunc *slavio_led_mem_read[3] = {
370     NULL,
371     slavio_led_mem_readw,
372     NULL,
373 };
374
375 static CPUWriteMemoryFunc *slavio_led_mem_write[3] = {
376     NULL,
377     slavio_led_mem_writew,
378     NULL,
379 };
380
381 static void slavio_misc_save(QEMUFile *f, void *opaque)
382 {
383     MiscState *s = opaque;
384     int tmp;
385     uint8_t tmp8;
386
387     tmp = 0;
388     qemu_put_be32s(f, &tmp); /* ignored, was IRQ.  */
389     qemu_put_8s(f, &s->config);
390     qemu_put_8s(f, &s->aux1);
391     qemu_put_8s(f, &s->aux2);
392     qemu_put_8s(f, &s->diag);
393     qemu_put_8s(f, &s->mctrl);
394     tmp8 = s->sysctrl & 0xff;
395     qemu_put_8s(f, &tmp8);
396 }
397
398 static int slavio_misc_load(QEMUFile *f, void *opaque, int version_id)
399 {
400     MiscState *s = opaque;
401     int tmp;
402     uint8_t tmp8;
403
404     if (version_id != 1)
405         return -EINVAL;
406
407     qemu_get_be32s(f, &tmp);
408     qemu_get_8s(f, &s->config);
409     qemu_get_8s(f, &s->aux1);
410     qemu_get_8s(f, &s->aux2);
411     qemu_get_8s(f, &s->diag);
412     qemu_get_8s(f, &s->mctrl);
413     qemu_get_8s(f, &tmp8);
414     s->sysctrl = (uint32_t)tmp8;
415     return 0;
416 }
417
418 void *slavio_misc_init(target_phys_addr_t base, target_phys_addr_t power_base,
419                        target_phys_addr_t aux1_base,
420                        target_phys_addr_t aux2_base, qemu_irq irq,
421                        CPUState *env, qemu_irq **fdc_tc)
422 {
423     int io;
424     MiscState *s;
425
426     s = qemu_mallocz(sizeof(MiscState));
427     if (!s)
428         return NULL;
429
430     if (base) {
431         /* 8 bit registers */
432         io = cpu_register_io_memory(0, slavio_misc_mem_read,
433                                     slavio_misc_mem_write, s);
434         // Slavio control
435         cpu_register_physical_memory(base + MISC_CFG, MISC_SIZE, io);
436         // Diagnostics
437         cpu_register_physical_memory(base + MISC_DIAG, MISC_SIZE, io);
438         // Modem control
439         cpu_register_physical_memory(base + MISC_MDM, MISC_SIZE, io);
440
441         /* 16 bit registers */
442         io = cpu_register_io_memory(0, slavio_led_mem_read,
443                                     slavio_led_mem_write, s);
444         /* ss600mp diag LEDs */
445         cpu_register_physical_memory(base + MISC_LEDS, MISC_SIZE, io);
446
447         /* 32 bit registers */
448         io = cpu_register_io_memory(0, slavio_sysctrl_mem_read,
449                                     slavio_sysctrl_mem_write, s);
450         // System control
451         cpu_register_physical_memory(base + MISC_SYS, SYSCTRL_SIZE, io);
452     }
453
454     // AUX 1 (Misc System Functions)
455     if (aux1_base) {
456         io = cpu_register_io_memory(0, slavio_aux1_mem_read,
457                                     slavio_aux1_mem_write, s);
458         cpu_register_physical_memory(aux1_base, MISC_SIZE, io);
459     }
460
461     // AUX 2 (Software Powerdown Control)
462     if (aux2_base) {
463         io = cpu_register_io_memory(0, slavio_aux2_mem_read,
464                                     slavio_aux2_mem_write, s);
465         cpu_register_physical_memory(aux2_base, MISC_SIZE, io);
466     }
467
468     // Power management (APC) XXX: not a Slavio device
469     if (power_base) {
470         io = cpu_register_io_memory(0, apc_mem_read, apc_mem_write, s);
471         cpu_register_physical_memory(power_base, MISC_SIZE, io);
472     }
473
474     s->irq = irq;
475     s->env = env;
476     *fdc_tc = &s->fdc_tc;
477
478     register_savevm("slavio_misc", base, 1, slavio_misc_save, slavio_misc_load,
479                     s);
480     qemu_register_reset(slavio_misc_reset, s);
481     slavio_misc_reset(s);
482
483     return s;
484 }