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