SCSI and USB async IO support.
[qemu] / hw / esp.c
1 /*
2  * QEMU ESP emulation
3  * 
4  * Copyright (c) 2005-2006 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 32
42 #define DMA_VER 0xa0000000
43 #define DMA_INTR 1
44 #define DMA_INTREN 0x10
45 #define DMA_WRITE_MEM 0x100
46 #define DMA_LOADED 0x04000000
47 typedef struct ESPState ESPState;
48
49 struct ESPState {
50     BlockDriverState **bd;
51     uint8_t rregs[ESP_MAXREG];
52     uint8_t wregs[ESP_MAXREG];
53     int irq;
54     uint32_t espdmaregs[ESPDMA_REGS];
55     uint32_t ti_size;
56     uint32_t ti_rptr, ti_wptr;
57     uint8_t ti_buf[TI_BUFSZ];
58     int sense;
59     int dma;
60     SCSIDevice *scsi_dev[MAX_DISKS];
61     SCSIDevice *current_dev;
62     uint8_t cmdbuf[TI_BUFSZ];
63     int cmdlen;
64     int do_cmd;
65
66     uint32_t dma_left;
67     uint8_t async_buf[TARGET_PAGE_SIZE];
68     uint32_t async_ptr;
69     uint32_t async_len;
70 };
71
72 #define STAT_DO 0x00
73 #define STAT_DI 0x01
74 #define STAT_CD 0x02
75 #define STAT_ST 0x03
76 #define STAT_MI 0x06
77 #define STAT_MO 0x07
78
79 #define STAT_TC 0x10
80 #define STAT_PE 0x20
81 #define STAT_GE 0x40
82 #define STAT_IN 0x80
83
84 #define INTR_FC 0x08
85 #define INTR_BS 0x10
86 #define INTR_DC 0x20
87 #define INTR_RST 0x80
88
89 #define SEQ_0 0x0
90 #define SEQ_CD 0x4
91
92 static int get_cmd(ESPState *s, uint8_t *buf)
93 {
94     uint32_t dmaptr, dmalen;
95     int target;
96
97     dmalen = s->wregs[0] | (s->wregs[1] << 8);
98     target = s->wregs[4] & 7;
99     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
100     if (s->dma) {
101         dmaptr = iommu_translate(s->espdmaregs[1]);
102         DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
103                 s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
104         cpu_physical_memory_read(dmaptr, buf, dmalen);
105     } else {
106         buf[0] = 0;
107         memcpy(&buf[1], s->ti_buf, dmalen);
108         dmalen++;
109     }
110
111     s->ti_size = 0;
112     s->ti_rptr = 0;
113     s->ti_wptr = 0;
114
115     if (target >= 4 || !s->scsi_dev[target]) {
116         // No such drive
117         s->rregs[4] = STAT_IN;
118         s->rregs[5] = INTR_DC;
119         s->rregs[6] = SEQ_0;
120         s->espdmaregs[0] |= DMA_INTR;
121         pic_set_irq(s->irq, 1);
122         return 0;
123     }
124     s->current_dev = s->scsi_dev[target];
125     return dmalen;
126 }
127
128 static void do_cmd(ESPState *s, uint8_t *buf)
129 {
130     int32_t datalen;
131     int lun;
132
133     DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
134     lun = buf[0] & 7;
135     datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
136     if (datalen == 0) {
137         s->ti_size = 0;
138     } else {
139         s->rregs[4] = STAT_IN | STAT_TC;
140         if (datalen > 0) {
141             s->rregs[4] |= STAT_DI;
142             s->ti_size = datalen;
143         } else {
144             s->rregs[4] |= STAT_DO;
145             s->ti_size = -datalen;
146         }
147     }
148     s->rregs[5] = INTR_BS | INTR_FC;
149     s->rregs[6] = SEQ_CD;
150     s->espdmaregs[0] |= DMA_INTR;
151     pic_set_irq(s->irq, 1);
152 }
153
154 static void handle_satn(ESPState *s)
155 {
156     uint8_t buf[32];
157     int len;
158
159     len = get_cmd(s, buf);
160     if (len)
161         do_cmd(s, buf);
162 }
163
164 static void handle_satn_stop(ESPState *s)
165 {
166     s->cmdlen = get_cmd(s, s->cmdbuf);
167     if (s->cmdlen) {
168         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
169         s->do_cmd = 1;
170         s->espdmaregs[1] += s->cmdlen;
171         s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
172         s->rregs[5] = INTR_BS | INTR_FC;
173         s->rregs[6] = SEQ_CD;
174         s->espdmaregs[0] |= DMA_INTR;
175         pic_set_irq(s->irq, 1);
176     }
177 }
178
179 static void write_response(ESPState *s)
180 {
181     uint32_t dmaptr;
182
183     DPRINTF("Transfer status (sense=%d)\n", s->sense);
184     s->ti_buf[0] = s->sense;
185     s->ti_buf[1] = 0;
186     if (s->dma) {
187         dmaptr = iommu_translate(s->espdmaregs[1]);
188         DPRINTF("DMA Direction: %c\n",
189                 s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
190         cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
191         s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
192         s->rregs[5] = INTR_BS | INTR_FC;
193         s->rregs[6] = SEQ_CD;
194     } else {
195         s->ti_size = 2;
196         s->ti_rptr = 0;
197         s->ti_wptr = 0;
198         s->rregs[7] = 2;
199     }
200     s->espdmaregs[0] |= DMA_INTR;
201     pic_set_irq(s->irq, 1);
202
203 }
204
205 static void esp_do_dma(ESPState *s)
206 {
207     uint32_t dmaptr, minlen, len, from, to;
208     int to_device;
209     dmaptr = iommu_translate(s->espdmaregs[1]);
210     to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
211     from = s->espdmaregs[1];
212     minlen = s->dma_left;
213     to = from + minlen;
214     dmaptr = iommu_translate(s->espdmaregs[1]);
215     if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
216        len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
217     } else {
218        len = to - from;
219     }
220     DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1], len, from, to);
221     s->espdmaregs[1] += len;
222     if (s->do_cmd) {
223         s->ti_size -= len;
224         DPRINTF("command len %d + %d\n", s->cmdlen, len);
225         cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
226         s->ti_size = 0;
227         s->cmdlen = 0;
228         s->do_cmd = 0;
229         do_cmd(s, s->cmdbuf);
230         return;
231     } else {
232         s->async_len = len;
233         s->dma_left -= len;
234         if (to_device) {
235             s->async_ptr = -1;
236             cpu_physical_memory_read(dmaptr, s->async_buf, len);
237             scsi_write_data(s->current_dev, s->async_buf, len);
238         } else {
239             s->async_ptr = dmaptr;
240             scsi_read_data(s->current_dev, s->async_buf, len);
241         }
242     }
243 }
244
245 static void esp_command_complete(void *opaque, uint32_t reason, int sense)
246 {
247     ESPState *s = (ESPState *)opaque;
248
249     s->ti_size -= s->async_len;
250     s->espdmaregs[1] += s->async_len;
251     if (s->async_ptr != (uint32_t)-1) {
252         cpu_physical_memory_write(s->async_ptr, s->async_buf, s->async_len);
253     }
254     if (reason == SCSI_REASON_DONE) {
255         DPRINTF("SCSI Command complete\n");
256         if (s->ti_size != 0)
257             DPRINTF("SCSI command completed unexpectedly\n");
258         s->ti_size = 0;
259         if (sense)
260             DPRINTF("Command failed\n");
261         s->sense = sense;
262     } else {
263         DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
264     }
265     if (s->dma_left) {
266         esp_do_dma(s);
267     } else {
268         if (s->ti_size) {
269             s->rregs[4] |= STAT_IN | STAT_TC;
270         } else {
271             s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
272         }
273         s->rregs[5] = INTR_BS;
274         s->rregs[6] = 0;
275         s->rregs[7] = 0;
276         s->espdmaregs[0] |= DMA_INTR;
277         pic_set_irq(s->irq, 1);
278     }
279 }
280
281 static void handle_ti(ESPState *s)
282 {
283     uint32_t dmalen, minlen;
284
285     dmalen = s->wregs[0] | (s->wregs[1] << 8);
286     if (dmalen==0) {
287       dmalen=0x10000;
288     }
289
290     if (s->do_cmd)
291         minlen = (dmalen < 32) ? dmalen : 32;
292     else
293         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
294     DPRINTF("Transfer Information len %d\n", minlen);
295     if (s->dma) {
296         s->dma_left = minlen;
297         s->rregs[4] &= ~STAT_TC;
298         esp_do_dma(s);
299     } else if (s->do_cmd) {
300         DPRINTF("command len %d\n", s->cmdlen);
301         s->ti_size = 0;
302         s->cmdlen = 0;
303         s->do_cmd = 0;
304         do_cmd(s, s->cmdbuf);
305         return;
306     }
307 }
308
309 static void esp_reset(void *opaque)
310 {
311     ESPState *s = opaque;
312     memset(s->rregs, 0, ESP_MAXREG);
313     memset(s->wregs, 0, ESP_MAXREG);
314     s->rregs[0x0e] = 0x4; // Indicate fas100a
315     memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
316     s->ti_size = 0;
317     s->ti_rptr = 0;
318     s->ti_wptr = 0;
319     s->dma = 0;
320     s->do_cmd = 0;
321 }
322
323 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
324 {
325     ESPState *s = opaque;
326     uint32_t saddr;
327
328     saddr = (addr & ESP_MAXREG) >> 2;
329     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
330     switch (saddr) {
331     case 2:
332         // FIFO
333         if (s->ti_size > 0) {
334             s->ti_size--;
335             if ((s->rregs[4] & 6) == 0) {
336                 /* Data in/out.  */
337                 scsi_read_data(s->current_dev, &s->rregs[2], 0);
338             } else {
339                 s->rregs[2] = s->ti_buf[s->ti_rptr++];
340             }
341             pic_set_irq(s->irq, 1);
342         }
343         if (s->ti_size == 0) {
344             s->ti_rptr = 0;
345             s->ti_wptr = 0;
346         }
347         break;
348     case 5:
349         // interrupt
350         // Clear interrupt/error status bits
351         s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);
352         pic_set_irq(s->irq, 0);
353         s->espdmaregs[0] &= ~DMA_INTR;
354         break;
355     default:
356         break;
357     }
358     return s->rregs[saddr];
359 }
360
361 static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
362 {
363     ESPState *s = opaque;
364     uint32_t saddr;
365
366     saddr = (addr & ESP_MAXREG) >> 2;
367     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
368     switch (saddr) {
369     case 0:
370     case 1:
371         s->rregs[saddr] = val;
372         s->rregs[4] &= ~STAT_TC;
373         break;
374     case 2:
375         // FIFO
376         if (s->do_cmd) {
377             s->cmdbuf[s->cmdlen++] = val & 0xff;
378         } else if ((s->rregs[4] & 6) == 0) {
379             uint8_t buf;
380             buf = val & 0xff;
381             s->ti_size--;
382             scsi_write_data(s->current_dev, &buf, 0);
383         } else {
384             s->ti_size++;
385             s->ti_buf[s->ti_wptr++] = val & 0xff;
386         }
387         break;
388     case 3:
389         s->rregs[saddr] = val;
390         // Command
391         if (val & 0x80) {
392             s->dma = 1;
393         } else {
394             s->dma = 0;
395         }
396         switch(val & 0x7f) {
397         case 0:
398             DPRINTF("NOP (%2.2x)\n", val);
399             break;
400         case 1:
401             DPRINTF("Flush FIFO (%2.2x)\n", val);
402             //s->ti_size = 0;
403             s->rregs[5] = INTR_FC;
404             s->rregs[6] = 0;
405             break;
406         case 2:
407             DPRINTF("Chip reset (%2.2x)\n", val);
408             esp_reset(s);
409             break;
410         case 3:
411             DPRINTF("Bus reset (%2.2x)\n", val);
412             s->rregs[5] = INTR_RST;
413             if (!(s->wregs[8] & 0x40)) {
414                 s->espdmaregs[0] |= DMA_INTR;
415                 pic_set_irq(s->irq, 1);
416             }
417             break;
418         case 0x10:
419             handle_ti(s);
420             break;
421         case 0x11:
422             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
423             write_response(s);
424             break;
425         case 0x12:
426             DPRINTF("Message Accepted (%2.2x)\n", val);
427             write_response(s);
428             s->rregs[5] = INTR_DC;
429             s->rregs[6] = 0;
430             break;
431         case 0x1a:
432             DPRINTF("Set ATN (%2.2x)\n", val);
433             break;
434         case 0x42:
435             DPRINTF("Set ATN (%2.2x)\n", val);
436             handle_satn(s);
437             break;
438         case 0x43:
439             DPRINTF("Set ATN & stop (%2.2x)\n", val);
440             handle_satn_stop(s);
441             break;
442         default:
443             DPRINTF("Unhandled ESP command (%2.2x)\n", val);
444             break;
445         }
446         break;
447     case 4 ... 7:
448         break;
449     case 8:
450         s->rregs[saddr] = val;
451         break;
452     case 9 ... 10:
453         break;
454     case 11:
455         s->rregs[saddr] = val & 0x15;
456         break;
457     case 12 ... 15:
458         s->rregs[saddr] = val;
459         break;
460     default:
461         break;
462     }
463     s->wregs[saddr] = val;
464 }
465
466 static CPUReadMemoryFunc *esp_mem_read[3] = {
467     esp_mem_readb,
468     esp_mem_readb,
469     esp_mem_readb,
470 };
471
472 static CPUWriteMemoryFunc *esp_mem_write[3] = {
473     esp_mem_writeb,
474     esp_mem_writeb,
475     esp_mem_writeb,
476 };
477
478 static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
479 {
480     ESPState *s = opaque;
481     uint32_t saddr;
482
483     saddr = (addr & ESPDMA_MAXADDR) >> 2;
484     DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
485
486     return s->espdmaregs[saddr];
487 }
488
489 static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
490 {
491     ESPState *s = opaque;
492     uint32_t saddr;
493
494     saddr = (addr & ESPDMA_MAXADDR) >> 2;
495     DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
496     switch (saddr) {
497     case 0:
498         if (!(val & DMA_INTREN))
499             pic_set_irq(s->irq, 0);
500         if (val & 0x80) {
501             esp_reset(s);
502         } else if (val & 0x40) {
503             val &= ~0x40;
504         } else if (val == 0)
505             val = 0x40;
506         val &= 0x0fffffff;
507         val |= DMA_VER;
508         break;
509     case 1:
510         s->espdmaregs[0] |= DMA_LOADED;
511         break;
512     default:
513         break;
514     }
515     s->espdmaregs[saddr] = val;
516 }
517
518 static CPUReadMemoryFunc *espdma_mem_read[3] = {
519     espdma_mem_readl,
520     espdma_mem_readl,
521     espdma_mem_readl,
522 };
523
524 static CPUWriteMemoryFunc *espdma_mem_write[3] = {
525     espdma_mem_writel,
526     espdma_mem_writel,
527     espdma_mem_writel,
528 };
529
530 static void esp_save(QEMUFile *f, void *opaque)
531 {
532     ESPState *s = opaque;
533     unsigned int i;
534
535     qemu_put_buffer(f, s->rregs, ESP_MAXREG);
536     qemu_put_buffer(f, s->wregs, ESP_MAXREG);
537     qemu_put_be32s(f, &s->irq);
538     for (i = 0; i < ESPDMA_REGS; i++)
539         qemu_put_be32s(f, &s->espdmaregs[i]);
540     qemu_put_be32s(f, &s->ti_size);
541     qemu_put_be32s(f, &s->ti_rptr);
542     qemu_put_be32s(f, &s->ti_wptr);
543     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
544     qemu_put_be32s(f, &s->dma);
545 }
546
547 static int esp_load(QEMUFile *f, void *opaque, int version_id)
548 {
549     ESPState *s = opaque;
550     unsigned int i;
551     
552     if (version_id != 1)
553         return -EINVAL;
554
555     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
556     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
557     qemu_get_be32s(f, &s->irq);
558     for (i = 0; i < ESPDMA_REGS; i++)
559         qemu_get_be32s(f, &s->espdmaregs[i]);
560     qemu_get_be32s(f, &s->ti_size);
561     qemu_get_be32s(f, &s->ti_rptr);
562     qemu_get_be32s(f, &s->ti_wptr);
563     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
564     qemu_get_be32s(f, &s->dma);
565
566     return 0;
567 }
568
569 void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
570 {
571     ESPState *s;
572     int esp_io_memory, espdma_io_memory;
573     int i;
574
575     s = qemu_mallocz(sizeof(ESPState));
576     if (!s)
577         return;
578
579     s->bd = bd;
580     s->irq = irq;
581
582     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
583     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
584
585     espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
586     cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
587
588     esp_reset(s);
589
590     register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
591     qemu_register_reset(esp_reset, s);
592     for (i = 0; i < MAX_DISKS; i++) {
593         if (bs_table[i]) {
594             s->scsi_dev[i] =
595                 scsi_disk_init(bs_table[i], esp_command_complete, s);
596         }
597     }
598 }
599