sparc merge (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 #define pic_set_irq(irq, level) \
33 do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
34 #else
35 #define DPRINTF(fmt, args...)
36 #endif
37
38 #define ESPDMA_REGS 4
39 #define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
40 #define ESP_MAXREG 0x3f
41 #define TI_BUFSZ 65536
42 #define DMA_VER 0xa0000000
43 #define DMA_INTR 1
44 #define DMA_INTREN 0x10
45 #define DMA_LOADED 0x04000000
46
47 typedef struct ESPState {
48     BlockDriverState **bd;
49     uint8_t rregs[ESP_MAXREG];
50     uint8_t wregs[ESP_MAXREG];
51     int irq;
52     uint32_t espdmaregs[ESPDMA_REGS];
53     uint32_t ti_size;
54     uint32_t ti_rptr, ti_wptr;
55     int ti_dir;
56     uint8_t ti_buf[TI_BUFSZ];
57     int dma;
58 } ESPState;
59
60 #define STAT_DO 0x00
61 #define STAT_DI 0x01
62 #define STAT_CD 0x02
63 #define STAT_ST 0x03
64 #define STAT_MI 0x06
65 #define STAT_MO 0x07
66
67 #define STAT_TC 0x10
68 #define STAT_IN 0x80
69
70 #define INTR_FC 0x08
71 #define INTR_BS 0x10
72 #define INTR_DC 0x20
73 #define INTR_RST 0x80
74
75 #define SEQ_0 0x0
76 #define SEQ_CD 0x4
77
78 static void handle_satn(ESPState *s)
79 {
80     uint8_t buf[32];
81     uint32_t dmaptr, dmalen;
82     unsigned int i;
83     int64_t nb_sectors;
84     int target;
85
86     dmalen = s->wregs[0] | (s->wregs[1] << 8);
87     target = s->wregs[4] & 7;
88     DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
89     if (s->dma) {
90         dmaptr = iommu_translate(s->espdmaregs[1]);
91         DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
92         cpu_physical_memory_read(dmaptr, buf, dmalen);
93     } else {
94         buf[0] = 0;
95         memcpy(&buf[1], s->ti_buf, dmalen);
96         dmalen++;
97     }
98     for (i = 0; i < dmalen; i++) {
99         DPRINTF("Command %2.2x\n", buf[i]);
100     }
101     s->ti_dir = 0;
102     s->ti_size = 0;
103     s->ti_rptr = 0;
104     s->ti_wptr = 0;
105
106     if (target >= 4 || !s->bd[target]) { // No such drive
107         s->rregs[4] = STAT_IN;
108         s->rregs[5] = INTR_DC;
109         s->rregs[6] = SEQ_0;
110         s->espdmaregs[0] |= DMA_INTR;
111         pic_set_irq(s->irq, 1);
112         return;
113     }
114     switch (buf[1]) {
115     case 0x0:
116         DPRINTF("Test Unit Ready (len %d)\n", buf[5]);
117         break;
118     case 0x12:
119         DPRINTF("Inquiry (len %d)\n", buf[5]);
120         memset(s->ti_buf, 0, 36);
121         if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
122             s->ti_buf[0] = 5;
123             memcpy(&s->ti_buf[16], "QEMU CDROM     ", 16);
124         } else {
125             s->ti_buf[0] = 0;
126             memcpy(&s->ti_buf[16], "QEMU HARDDISK  ", 16);
127         }
128         memcpy(&s->ti_buf[8], "QEMU   ", 8);
129         s->ti_buf[2] = 1;
130         s->ti_buf[3] = 2;
131         s->ti_dir = 1;
132         s->ti_size = 36;
133         break;
134     case 0x1a:
135         DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[3], buf[5]);
136         break;
137     case 0x25:
138         DPRINTF("Read Capacity (len %d)\n", buf[5]);
139         memset(s->ti_buf, 0, 8);
140         bdrv_get_geometry(s->bd[target], &nb_sectors);
141         s->ti_buf[0] = (nb_sectors >> 24) & 0xff;
142         s->ti_buf[1] = (nb_sectors >> 16) & 0xff;
143         s->ti_buf[2] = (nb_sectors >> 8) & 0xff;
144         s->ti_buf[3] = nb_sectors & 0xff;
145         s->ti_buf[4] = 0;
146         s->ti_buf[5] = 0;
147         if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM)
148             s->ti_buf[6] = 8; // sector size 2048
149         else
150             s->ti_buf[6] = 2; // sector size 512
151         s->ti_buf[7] = 0;
152         s->ti_dir = 1;
153         s->ti_size = 8;
154         break;
155     case 0x28:
156         {
157             int64_t offset, len;
158
159             if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
160                 offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
161                 len = ((buf[8] << 8) | buf[9]) * 4;
162                 s->ti_size = len * 2048;
163             } else {
164                 offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
165                 len = (buf[8] << 8) | buf[9];
166                 s->ti_size = len * 512;
167             }
168             DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);
169             bdrv_read(s->bd[target], offset, s->ti_buf, len);
170             // XXX error handling
171             s->ti_dir = 1;
172             break;
173         }
174     case 0x2a:
175         {
176             int64_t offset, len;
177
178             if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
179                 offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
180                 len = ((buf[8] << 8) | buf[9]) * 4;
181                 s->ti_size = len * 2048;
182             } else {
183                 offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
184                 len = (buf[8] << 8) | buf[9];
185                 s->ti_size = len * 512;
186             }
187             DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
188             bdrv_write(s->bd[target], offset, s->ti_buf, len);
189             // XXX error handling
190             s->ti_dir = 0;
191             break;
192         }
193     default:
194         DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);
195         break;
196     }
197     s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;
198     s->rregs[5] = INTR_BS | INTR_FC;
199     s->rregs[6] = SEQ_CD;
200     s->espdmaregs[0] |= DMA_INTR;
201     pic_set_irq(s->irq, 1);
202 }
203
204 static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
205 {
206     uint32_t dmaptr, dmalen;
207
208     dmalen = s->wregs[0] | (s->wregs[1] << 8);
209     DPRINTF("Transfer status len %d\n", dmalen);
210     if (s->dma) {
211         dmaptr = iommu_translate(s->espdmaregs[1]);
212         DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
213         cpu_physical_memory_write(dmaptr, buf, len);
214         s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
215         s->rregs[5] = INTR_BS | INTR_FC;
216         s->rregs[6] = SEQ_CD;
217     } else {
218         memcpy(s->ti_buf, buf, len);
219         s->ti_size = dmalen;
220         s->ti_rptr = 0;
221         s->ti_wptr = 0;
222         s->rregs[7] = dmalen;
223     }
224     s->espdmaregs[0] |= DMA_INTR;
225     pic_set_irq(s->irq, 1);
226
227 }
228
229 static const uint8_t okbuf[] = {0, 0};
230
231 static void handle_ti(ESPState *s)
232 {
233     uint32_t dmaptr, dmalen;
234     unsigned int i;
235
236     dmalen = s->wregs[0] | (s->wregs[1] << 8);
237     DPRINTF("Transfer Information len %d\n", dmalen);
238     if (s->dma) {
239         dmaptr = iommu_translate(s->espdmaregs[1]);
240         DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
241         for (i = 0; i < s->ti_size; i++) {
242             dmaptr = iommu_translate(s->espdmaregs[1] + i);
243             if (s->ti_dir)
244                 cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
245             else
246                 cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
247         }
248         s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
249         s->rregs[5] = INTR_BS;
250         s->rregs[6] = 0;
251         s->espdmaregs[0] |= DMA_INTR;
252     } else {
253         s->ti_size = dmalen;
254         s->ti_rptr = 0;
255         s->ti_wptr = 0;
256         s->rregs[7] = dmalen;
257     }   
258     pic_set_irq(s->irq, 1);
259 }
260
261 static void esp_reset(void *opaque)
262 {
263     ESPState *s = opaque;
264     memset(s->rregs, 0, ESP_MAXREG);
265     s->rregs[0x0e] = 0x4; // Indicate fas100a
266     memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
267 }
268
269 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
270 {
271     ESPState *s = opaque;
272     uint32_t saddr;
273
274     saddr = (addr & ESP_MAXREG) >> 2;
275     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
276     switch (saddr) {
277     case 2:
278         // FIFO
279         if (s->ti_size > 0) {
280             s->ti_size--;
281             s->rregs[saddr] = s->ti_buf[s->ti_rptr++];
282             pic_set_irq(s->irq, 1);
283         }
284         if (s->ti_size == 0) {
285             s->ti_rptr = 0;
286             s->ti_wptr = 0;
287         }
288         break;
289     case 5:
290         // interrupt
291         // Clear status bits except TC
292         s->rregs[4] &= STAT_TC;
293         pic_set_irq(s->irq, 0);
294         s->espdmaregs[0] &= ~DMA_INTR;
295         break;
296     default:
297         break;
298     }
299     return s->rregs[saddr];
300 }
301
302 static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
303 {
304     ESPState *s = opaque;
305     uint32_t saddr;
306
307     saddr = (addr & ESP_MAXREG) >> 2;
308     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
309     switch (saddr) {
310     case 0:
311     case 1:
312         s->rregs[saddr] = val;
313         break;
314     case 2:
315         // FIFO
316         s->ti_size++;
317         s->ti_buf[s->ti_wptr++] = val & 0xff;
318         break;
319     case 3:
320         s->rregs[saddr] = val;
321         // Command
322         if (val & 0x80) {
323             s->dma = 1;
324         } else {
325             s->dma = 0;
326         }
327         switch(val & 0x7f) {
328         case 0:
329             DPRINTF("NOP (%2.2x)\n", val);
330             break;
331         case 1:
332             DPRINTF("Flush FIFO (%2.2x)\n", val);
333             //s->ti_size = 0;
334             s->rregs[5] = INTR_FC;
335             s->rregs[6] = 0;
336             break;
337         case 2:
338             DPRINTF("Chip reset (%2.2x)\n", val);
339             esp_reset(s);
340             break;
341         case 3:
342             DPRINTF("Bus reset (%2.2x)\n", val);
343             s->rregs[5] = INTR_RST;
344             if (!(s->wregs[8] & 0x40)) {
345                 s->espdmaregs[0] |= DMA_INTR;
346                 pic_set_irq(s->irq, 1);
347             }
348             break;
349         case 0x10:
350             handle_ti(s);
351             break;
352         case 0x11:
353             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
354             dma_write(s, okbuf, 2);
355             break;
356         case 0x12:
357             DPRINTF("Message Accepted (%2.2x)\n", val);
358             dma_write(s, okbuf, 2);
359             s->rregs[5] = INTR_DC;
360             s->rregs[6] = 0;
361             break;
362         case 0x1a:
363             DPRINTF("Set ATN (%2.2x)\n", val);
364             break;
365         case 0x42:
366             handle_satn(s);
367             break;
368         case 0x43:
369             DPRINTF("Set ATN & stop (%2.2x)\n", val);
370             handle_satn(s);
371             break;
372         default:
373             DPRINTF("Unhandled ESP command (%2.2x)\n", val);
374             break;
375         }
376         break;
377     case 4 ... 7:
378         break;
379     case 8:
380         s->rregs[saddr] = val;
381         break;
382     case 9 ... 10:
383         break;
384     case 11:
385         s->rregs[saddr] = val & 0x15;
386         break;
387     case 12 ... 15:
388         s->rregs[saddr] = val;
389         break;
390     default:
391         break;
392     }
393     s->wregs[saddr] = val;
394 }
395
396 static CPUReadMemoryFunc *esp_mem_read[3] = {
397     esp_mem_readb,
398     esp_mem_readb,
399     esp_mem_readb,
400 };
401
402 static CPUWriteMemoryFunc *esp_mem_write[3] = {
403     esp_mem_writeb,
404     esp_mem_writeb,
405     esp_mem_writeb,
406 };
407
408 static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
409 {
410     ESPState *s = opaque;
411     uint32_t saddr;
412
413     saddr = (addr & ESPDMA_MAXADDR) >> 2;
414     DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
415
416     return s->espdmaregs[saddr];
417 }
418
419 static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
420 {
421     ESPState *s = opaque;
422     uint32_t saddr;
423
424     saddr = (addr & ESPDMA_MAXADDR) >> 2;
425     DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
426     switch (saddr) {
427     case 0:
428         if (!(val & DMA_INTREN))
429             pic_set_irq(s->irq, 0);
430         if (val & 0x80) {
431             esp_reset(s);
432         } else if (val & 0x40) {
433             val &= ~0x40;
434         } else if (val == 0)
435             val = 0x40;
436         val &= 0x0fffffff;
437         val |= DMA_VER;
438         break;
439     case 1:
440         s->espdmaregs[0] = DMA_LOADED;
441         break;
442     default:
443         break;
444     }
445     s->espdmaregs[saddr] = val;
446 }
447
448 static CPUReadMemoryFunc *espdma_mem_read[3] = {
449     espdma_mem_readl,
450     espdma_mem_readl,
451     espdma_mem_readl,
452 };
453
454 static CPUWriteMemoryFunc *espdma_mem_write[3] = {
455     espdma_mem_writel,
456     espdma_mem_writel,
457     espdma_mem_writel,
458 };
459
460 static void esp_save(QEMUFile *f, void *opaque)
461 {
462     ESPState *s = opaque;
463     unsigned int i;
464
465     qemu_put_buffer(f, s->rregs, ESP_MAXREG);
466     qemu_put_buffer(f, s->wregs, ESP_MAXREG);
467     qemu_put_be32s(f, &s->irq);
468     for (i = 0; i < ESPDMA_REGS; i++)
469         qemu_put_be32s(f, &s->espdmaregs[i]);
470     qemu_put_be32s(f, &s->ti_size);
471     qemu_put_be32s(f, &s->ti_rptr);
472     qemu_put_be32s(f, &s->ti_wptr);
473     qemu_put_be32s(f, &s->ti_dir);
474     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
475     qemu_put_be32s(f, &s->dma);
476 }
477
478 static int esp_load(QEMUFile *f, void *opaque, int version_id)
479 {
480     ESPState *s = opaque;
481     unsigned int i;
482     
483     if (version_id != 1)
484         return -EINVAL;
485
486     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
487     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
488     qemu_get_be32s(f, &s->irq);
489     for (i = 0; i < ESPDMA_REGS; i++)
490         qemu_get_be32s(f, &s->espdmaregs[i]);
491     qemu_get_be32s(f, &s->ti_size);
492     qemu_get_be32s(f, &s->ti_rptr);
493     qemu_get_be32s(f, &s->ti_wptr);
494     qemu_get_be32s(f, &s->ti_dir);
495     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
496     qemu_get_be32s(f, &s->dma);
497
498     return 0;
499 }
500
501 void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
502 {
503     ESPState *s;
504     int esp_io_memory, espdma_io_memory;
505
506     s = qemu_mallocz(sizeof(ESPState));
507     if (!s)
508         return;
509
510     s->bd = bd;
511     s->irq = irq;
512
513     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
514     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
515
516     espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
517     cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
518
519     esp_reset(s);
520
521     register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
522     qemu_register_reset(esp_reset, s);
523 }
524