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