sparc fixes (Blue Swirl)
[qemu] / hw / esp.c
1 /*
2  * QEMU ESP 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 "vl.h"
25
26 /* debug ESP card */
27 #define DEBUG_ESP
28
29 #ifdef DEBUG_ESP
30 #define DPRINTF(fmt, args...) \
31 do { printf("ESP: " fmt , ##args); } while (0)
32 #else
33 #define DPRINTF(fmt, args...)
34 #endif
35
36 #define ESPDMA_REGS 4
37 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
38 #define ESP_MAXREG 0x3f
39
40 typedef struct ESPState {
41     BlockDriverState **bd;
42     uint8_t regs[ESP_MAXREG];
43     int irq;
44     uint32_t espdmaregs[ESPDMA_REGS];
45 } ESPState;
46
47 static void esp_reset(void *opaque)
48 {
49     ESPState *s = opaque;
50     memset(s->regs, 0, ESP_MAXREG);
51     s->regs[0x0e] = 0x4; // Indicate fas100a
52     memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
53 }
54
55 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
56 {
57     ESPState *s = opaque;
58     uint32_t saddr;
59
60     saddr = (addr & ESP_MAXREG) >> 2;
61     switch (saddr) {
62     default:
63         break;
64     }
65     DPRINTF("esp: read reg[%d]: 0x%2.2x\n", saddr, s->regs[saddr]);
66     return s->regs[saddr];
67 }
68
69 static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
70 {
71     ESPState *s = opaque;
72     uint32_t saddr;
73
74     saddr = (addr & ESP_MAXREG) >> 2;
75     DPRINTF("esp: write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->regs[saddr], val);
76     switch (saddr) {
77     case 3:
78         // Command
79         switch(val & 0x7f) {
80         case 0:
81             DPRINTF("esp: NOP (%2.2x)\n", val);
82             break;
83         case 2:
84             DPRINTF("esp: Chip reset (%2.2x)\n", val);
85             esp_reset(s);
86             break;
87         case 3:
88             DPRINTF("esp: Bus reset (%2.2x)\n", val);
89             break;
90         case 0x1a:
91             DPRINTF("esp: Set ATN (%2.2x)\n", val);
92             break;
93         case 0x42:
94             DPRINTF("esp: Select with ATN (%2.2x)\n", val);
95             s->regs[4] = 0x1a; // Status: TCNT | TDONE | CMD
96             s->regs[5] = 0x20; // Intr: Disconnect, nobody there
97             s->regs[6] = 0x4;  // Seq: Cmd done
98             pic_set_irq(s->irq, 1);
99             break;
100         }
101         break;
102     case 4 ... 7:
103     case 9 ... 0xf:
104         break;
105     default:
106         s->regs[saddr] = val;
107         break;
108     }
109 }
110
111 static CPUReadMemoryFunc *esp_mem_read[3] = {
112     esp_mem_readb,
113     esp_mem_readb,
114     esp_mem_readb,
115 };
116
117 static CPUWriteMemoryFunc *esp_mem_write[3] = {
118     esp_mem_writeb,
119     esp_mem_writeb,
120     esp_mem_writeb,
121 };
122
123 static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
124 {
125     ESPState *s = opaque;
126     uint32_t saddr;
127
128     saddr = (addr & ESPDMA_MAXADDR) >> 2;
129     return s->espdmaregs[saddr];
130 }
131
132 static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
133 {
134     ESPState *s = opaque;
135     uint32_t saddr;
136
137     saddr = (addr & ESPDMA_MAXADDR) >> 2;
138     s->espdmaregs[saddr] = val;
139 }
140
141 static CPUReadMemoryFunc *espdma_mem_read[3] = {
142     espdma_mem_readl,
143     espdma_mem_readl,
144     espdma_mem_readl,
145 };
146
147 static CPUWriteMemoryFunc *espdma_mem_write[3] = {
148     espdma_mem_writel,
149     espdma_mem_writel,
150     espdma_mem_writel,
151 };
152
153 static void esp_save(QEMUFile *f, void *opaque)
154 {
155     ESPState *s = opaque;
156     
157 }
158
159 static int esp_load(QEMUFile *f, void *opaque, int version_id)
160 {
161     ESPState *s = opaque;
162     
163     if (version_id != 1)
164         return -EINVAL;
165
166     return 0;
167 }
168
169 void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
170 {
171     ESPState *s;
172     int esp_io_memory, espdma_io_memory;
173
174     s = qemu_mallocz(sizeof(ESPState));
175     if (!s)
176         return;
177
178     s->bd = bd;
179     s->irq = irq;
180
181     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
182     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
183
184     espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
185     cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
186
187     esp_reset(s);
188
189     register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
190     qemu_register_reset(esp_reset, s);
191 }
192