SCSI support (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 rregs[ESP_MAXREG];
43     uint8_t wregs[ESP_MAXREG];
44     int irq;
45     uint32_t espdmaregs[ESPDMA_REGS];
46     uint32_t ti_size;
47     int ti_dir;
48     uint8_t ti_buf[65536];
49 } ESPState;
50
51 #define STAT_DO 0x00
52 #define STAT_DI 0x01
53 #define STAT_CD 0x02
54 #define STAT_ST 0x03
55 #define STAT_MI 0x06
56 #define STAT_MO 0x07
57
58 #define STAT_TC 0x10
59 #define STAT_IN 0x80
60
61 #define INTR_FC 0x08
62 #define INTR_BS 0x10
63 #define INTR_DC 0x20
64
65 #define SEQ_0 0x0
66 #define SEQ_CD 0x4
67
68 static void handle_satn(ESPState *s)
69 {
70     uint8_t buf[32];
71     uint32_t dmaptr, dmalen;
72     unsigned int i;
73     int64_t nb_sectors;
74     int target;
75
76     dmaptr = iommu_translate(s->espdmaregs[1]);
77     dmalen = s->wregs[0] | (s->wregs[1] << 8);
78     DPRINTF("Select with ATN at %8.8x len %d\n", dmaptr, dmalen);
79     DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
80     cpu_physical_memory_read(dmaptr, buf, dmalen);
81     for (i = 0; i < dmalen; i++) {
82         DPRINTF("Command %2.2x\n", buf[i]);
83     }
84     s->ti_dir = 0;
85     s->ti_size = 0;
86     target = s->wregs[4] & 7;
87
88     if (target > 4 || !s->bd[target]) { // No such drive
89         s->rregs[4] = STAT_IN;
90         s->rregs[5] = INTR_DC;
91         s->rregs[6] = SEQ_0;
92         s->espdmaregs[0] |= 1;
93         pic_set_irq(s->irq, 1);
94         return;
95     }
96     switch (buf[1]) {
97     case 0x0:
98         DPRINTF("Test Unit Ready (len %d)\n", buf[5]);
99         break;
100     case 0x12:
101         DPRINTF("Inquiry (len %d)\n", buf[5]);
102         memset(s->ti_buf, 0, 36);
103         if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
104             s->ti_buf[0] = 5;
105             memcpy(&s->ti_buf[16], "QEMU CDROM     ", 16);
106         } else {
107             s->ti_buf[0] = 0;
108             memcpy(&s->ti_buf[16], "QEMU HARDDISK  ", 16);
109         }
110         memcpy(&s->ti_buf[8], "QEMU   ", 8);
111         s->ti_buf[2] = 1;
112         s->ti_buf[3] = 2;
113         s->ti_dir = 1;
114         s->ti_size = 36;
115         break;
116     case 0x1a:
117         DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[3], buf[5]);
118         break;
119     case 0x25:
120         DPRINTF("Read Capacity (len %d)\n", buf[5]);
121         memset(s->ti_buf, 0, 8);
122         bdrv_get_geometry(s->bd[target], &nb_sectors);
123         s->ti_buf[0] = (nb_sectors >> 24) & 0xff;
124         s->ti_buf[1] = (nb_sectors >> 16) & 0xff;
125         s->ti_buf[2] = (nb_sectors >> 8) & 0xff;
126         s->ti_buf[3] = nb_sectors & 0xff;
127         s->ti_buf[4] = 0;
128         s->ti_buf[5] = 0;
129         s->ti_buf[6] = 2;
130         s->ti_buf[7] = 0;
131         s->ti_dir = 1;
132         s->ti_size = 8;
133         break;
134     case 0x28:
135         {
136             int64_t offset, len;
137
138             offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
139             len = (buf[8] << 8) | buf[9];
140             DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);
141             bdrv_read(s->bd[target], offset, s->ti_buf, len);
142             s->ti_dir = 1;
143             s->ti_size = len * 512;
144             break;
145         }
146     case 0x2a:
147         {
148             int64_t offset, len;
149
150             offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
151             len = (buf[8] << 8) | buf[9];
152             DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
153             bdrv_write(s->bd[target], offset, s->ti_buf, len);
154             s->ti_dir = 0;
155             s->ti_size = len * 512;
156             break;
157         }
158     default:
159         DPRINTF("Unknown command (%2.2x)\n", buf[1]);
160         break;
161     }
162     s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;
163     s->rregs[5] = INTR_BS | INTR_FC;
164     s->rregs[6] = SEQ_CD;
165     s->espdmaregs[0] |= 1;
166     pic_set_irq(s->irq, 1);
167 }
168
169 static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
170 {
171     uint32_t dmaptr, dmalen;
172
173     dmaptr = iommu_translate(s->espdmaregs[1]);
174     dmalen = s->wregs[0] | (s->wregs[1] << 8);
175     DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
176     cpu_physical_memory_write(dmaptr, buf, len);
177     s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
178     s->rregs[5] = INTR_BS | INTR_FC;
179     s->rregs[6] = SEQ_CD;
180     s->espdmaregs[0] |= 1;
181     pic_set_irq(s->irq, 1);
182
183 }
184 static const uint8_t okbuf[] = {0, 0};
185
186 static void handle_ti(ESPState *s)
187 {
188     uint32_t dmaptr, dmalen;
189     unsigned int i;
190
191     dmaptr = iommu_translate(s->espdmaregs[1]);
192     dmalen = s->wregs[0] | (s->wregs[1] << 8);
193     DPRINTF("Transfer Information at %8.8x len %d\n", dmaptr, dmalen);
194     DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
195     for (i = 0; i < s->ti_size; i++) {
196         dmaptr = iommu_translate(s->espdmaregs[1] + i);
197         if (s->ti_dir)
198             cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
199         else
200             cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
201     }
202     s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
203     s->rregs[5] = INTR_BS;
204     s->rregs[6] = 0;
205     s->espdmaregs[0] |= 1;
206     pic_set_irq(s->irq, 1);
207 }
208
209 static void esp_reset(void *opaque)
210 {
211     ESPState *s = opaque;
212     memset(s->rregs, 0, ESP_MAXREG);
213     s->rregs[0x0e] = 0x4; // Indicate fas100a
214     memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
215 }
216
217 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
218 {
219     ESPState *s = opaque;
220     uint32_t saddr;
221
222     saddr = (addr & ESP_MAXREG) >> 2;
223     switch (saddr) {
224     default:
225         break;
226     }
227     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
228     return s->rregs[saddr];
229 }
230
231 static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
232 {
233     ESPState *s = opaque;
234     uint32_t saddr;
235
236     saddr = (addr & ESP_MAXREG) >> 2;
237     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
238     switch (saddr) {
239     case 3:
240         // Command
241         switch(val & 0x7f) {
242         case 0:
243             DPRINTF("NOP (%2.2x)\n", val);
244             break;
245         case 1:
246             DPRINTF("Flush FIFO (%2.2x)\n", val);
247             s->rregs[6] = 0;
248             s->rregs[5] = INTR_FC;
249             break;
250         case 2:
251             DPRINTF("Chip reset (%2.2x)\n", val);
252             esp_reset(s);
253             break;
254         case 3:
255             DPRINTF("Bus reset (%2.2x)\n", val);
256             break;
257         case 0x10:
258             handle_ti(s);
259             break;
260         case 0x11:
261             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
262             dma_write(s, okbuf, 2);
263             break;
264         case 0x12:
265             DPRINTF("Message Accepted (%2.2x)\n", val);
266             dma_write(s, okbuf, 2);
267             s->rregs[5] = INTR_DC;
268             s->rregs[6] = 0;
269             break;
270         case 0x1a:
271             DPRINTF("Set ATN (%2.2x)\n", val);
272             break;
273         case 0x42:
274             handle_satn(s);
275             break;
276         case 0x43:
277             DPRINTF("Set ATN & stop (%2.2x)\n", val);
278             handle_satn(s);
279             break;
280         default:
281             DPRINTF("Unhandled command (%2.2x)\n", val);
282             break;
283         }
284         break;
285     case 4 ... 7:
286     case 9 ... 0xf:
287         break;
288     default:
289         break;
290     }
291     s->wregs[saddr] = val;
292 }
293
294 static CPUReadMemoryFunc *esp_mem_read[3] = {
295     esp_mem_readb,
296     esp_mem_readb,
297     esp_mem_readb,
298 };
299
300 static CPUWriteMemoryFunc *esp_mem_write[3] = {
301     esp_mem_writeb,
302     esp_mem_writeb,
303     esp_mem_writeb,
304 };
305
306 static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
307 {
308     ESPState *s = opaque;
309     uint32_t saddr;
310
311     saddr = (addr & ESPDMA_MAXADDR) >> 2;
312     DPRINTF("read dmareg[%d]: 0x%2.2x\n", saddr, s->espdmaregs[saddr]);
313     return s->espdmaregs[saddr];
314 }
315
316 static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
317 {
318     ESPState *s = opaque;
319     uint32_t saddr;
320
321     saddr = (addr & ESPDMA_MAXADDR) >> 2;
322     DPRINTF("write dmareg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->espdmaregs[saddr], val);
323     switch (saddr) {
324     case 0:
325         if (!(val & 0x10))
326             pic_set_irq(s->irq, 0);
327         break;
328     default:
329         break;
330     }
331     s->espdmaregs[saddr] = val;
332 }
333
334 static CPUReadMemoryFunc *espdma_mem_read[3] = {
335     espdma_mem_readl,
336     espdma_mem_readl,
337     espdma_mem_readl,
338 };
339
340 static CPUWriteMemoryFunc *espdma_mem_write[3] = {
341     espdma_mem_writel,
342     espdma_mem_writel,
343     espdma_mem_writel,
344 };
345
346 static void esp_save(QEMUFile *f, void *opaque)
347 {
348     ESPState *s = opaque;
349     unsigned int i;
350
351     qemu_put_buffer(f, s->rregs, ESP_MAXREG);
352     qemu_put_buffer(f, s->wregs, ESP_MAXREG);
353     qemu_put_be32s(f, &s->irq);
354     for (i = 0; i < ESPDMA_REGS; i++)
355         qemu_put_be32s(f, &s->espdmaregs[i]);
356 }
357
358 static int esp_load(QEMUFile *f, void *opaque, int version_id)
359 {
360     ESPState *s = opaque;
361     unsigned int i;
362     
363     if (version_id != 1)
364         return -EINVAL;
365
366     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
367     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
368     qemu_get_be32s(f, &s->irq);
369     for (i = 0; i < ESPDMA_REGS; i++)
370         qemu_get_be32s(f, &s->espdmaregs[i]);
371
372     return 0;
373 }
374
375 void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
376 {
377     ESPState *s;
378     int esp_io_memory, espdma_io_memory;
379
380     s = qemu_mallocz(sizeof(ESPState));
381     if (!s)
382         return;
383
384     s->bd = bd;
385     s->irq = irq;
386
387     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
388     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
389
390     espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
391     cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
392
393     esp_reset(s);
394
395     register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
396     qemu_register_reset(esp_reset, s);
397 }
398