Separate the DMA controllers - Convert ESP to new DMA methods (Blue Swirl)
[qemu] / hw / esp.c
1 /*
2  * QEMU ESP/NCR53C9x 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 /*
30  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O), also
31  * produced as NCR89C100. See
32  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
33  * and
34  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
35  */
36
37 #ifdef DEBUG_ESP
38 #define DPRINTF(fmt, args...) \
39 do { printf("ESP: " fmt , ##args); } while (0)
40 #else
41 #define DPRINTF(fmt, args...)
42 #endif
43
44 #define ESP_MAXREG 0x3f
45 #define TI_BUFSZ 32
46
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     int32_t ti_size;
54     uint32_t ti_rptr, ti_wptr;
55     uint8_t ti_buf[TI_BUFSZ];
56     int sense;
57     int dma;
58     SCSIDevice *scsi_dev[MAX_DISKS];
59     SCSIDevice *current_dev;
60     uint8_t cmdbuf[TI_BUFSZ];
61     int cmdlen;
62     int do_cmd;
63
64     uint32_t dma_left;
65     uint8_t *async_buf;
66     uint32_t async_len;
67     void *dma_opaque;
68 };
69
70 #define STAT_DO 0x00
71 #define STAT_DI 0x01
72 #define STAT_CD 0x02
73 #define STAT_ST 0x03
74 #define STAT_MI 0x06
75 #define STAT_MO 0x07
76
77 #define STAT_TC 0x10
78 #define STAT_PE 0x20
79 #define STAT_GE 0x40
80 #define STAT_IN 0x80
81
82 #define INTR_FC 0x08
83 #define INTR_BS 0x10
84 #define INTR_DC 0x20
85 #define INTR_RST 0x80
86
87 #define SEQ_0 0x0
88 #define SEQ_CD 0x4
89
90 static int get_cmd(ESPState *s, uint8_t *buf)
91 {
92     uint32_t dmalen;
93     int target;
94
95     dmalen = s->wregs[0] | (s->wregs[1] << 8);
96     target = s->wregs[4] & 7;
97     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
98     if (s->dma) {
99         espdma_memory_read(s->dma_opaque, buf, dmalen);
100     } else {
101         buf[0] = 0;
102         memcpy(&buf[1], s->ti_buf, dmalen);
103         dmalen++;
104     }
105
106     s->ti_size = 0;
107     s->ti_rptr = 0;
108     s->ti_wptr = 0;
109
110     if (s->current_dev) {
111         /* Started a new command before the old one finished.  Cancel it.  */
112         scsi_cancel_io(s->current_dev, 0);
113         s->async_len = 0;
114     }
115
116     if (target >= MAX_DISKS || !s->scsi_dev[target]) {
117         // No such drive
118         s->rregs[4] = STAT_IN;
119         s->rregs[5] = INTR_DC;
120         s->rregs[6] = SEQ_0;
121         espdma_raise_irq(s->dma_opaque);
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     s->ti_size = datalen;
137     if (datalen != 0) {
138         s->rregs[4] = STAT_IN | STAT_TC;
139         s->dma_left = 0;
140         if (datalen > 0) {
141             s->rregs[4] |= STAT_DI;
142             scsi_read_data(s->current_dev, 0);
143         } else {
144             s->rregs[4] |= STAT_DO;
145             scsi_write_data(s->current_dev, 0);
146         }
147     }
148     s->rregs[5] = INTR_BS | INTR_FC;
149     s->rregs[6] = SEQ_CD;
150     espdma_raise_irq(s->dma_opaque);
151 }
152
153 static void handle_satn(ESPState *s)
154 {
155     uint8_t buf[32];
156     int len;
157
158     len = get_cmd(s, buf);
159     if (len)
160         do_cmd(s, buf);
161 }
162
163 static void handle_satn_stop(ESPState *s)
164 {
165     s->cmdlen = get_cmd(s, s->cmdbuf);
166     if (s->cmdlen) {
167         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
168         s->do_cmd = 1;
169         s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
170         s->rregs[5] = INTR_BS | INTR_FC;
171         s->rregs[6] = SEQ_CD;
172         espdma_raise_irq(s->dma_opaque);
173     }
174 }
175
176 static void write_response(ESPState *s)
177 {
178     DPRINTF("Transfer status (sense=%d)\n", s->sense);
179     s->ti_buf[0] = s->sense;
180     s->ti_buf[1] = 0;
181     if (s->dma) {
182         espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
183         s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
184         s->rregs[5] = INTR_BS | INTR_FC;
185         s->rregs[6] = SEQ_CD;
186     } else {
187         s->ti_size = 2;
188         s->ti_rptr = 0;
189         s->ti_wptr = 0;
190         s->rregs[7] = 2;
191     }
192     espdma_raise_irq(s->dma_opaque);
193 }
194
195 static void esp_dma_done(ESPState *s)
196 {
197     s->rregs[4] |= STAT_IN | STAT_TC;
198     s->rregs[5] = INTR_BS;
199     s->rregs[6] = 0;
200     s->rregs[7] = 0;
201     espdma_raise_irq(s->dma_opaque);
202 }
203
204 static void esp_do_dma(ESPState *s)
205 {
206     uint32_t len;
207     int to_device;
208
209     to_device = (s->ti_size < 0);
210     len = s->dma_left;
211     if (s->do_cmd) {
212         DPRINTF("command len %d + %d\n", s->cmdlen, len);
213         espdma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
214         s->ti_size = 0;
215         s->cmdlen = 0;
216         s->do_cmd = 0;
217         do_cmd(s, s->cmdbuf);
218         return;
219     }
220     if (s->async_len == 0) {
221         /* Defer until data is available.  */
222         return;
223     }
224     if (len > s->async_len) {
225         len = s->async_len;
226     }
227     if (to_device) {
228         espdma_memory_read(s->dma_opaque, s->async_buf, len);
229     } else {
230         espdma_memory_write(s->dma_opaque, s->async_buf, len);
231     }
232     s->dma_left -= len;
233     s->async_buf += len;
234     s->async_len -= len;
235     if (s->async_len == 0) {
236         if (to_device) {
237             // ti_size is negative
238             s->ti_size += len;
239             scsi_write_data(s->current_dev, 0);
240         } else {
241             s->ti_size -= len;
242             scsi_read_data(s->current_dev, 0);
243         }
244     }
245     if (s->dma_left == 0) {
246         esp_dma_done(s);
247     }
248 }
249
250 static void esp_command_complete(void *opaque, int reason, uint32_t tag,
251                                  uint32_t arg)
252 {
253     ESPState *s = (ESPState *)opaque;
254
255     if (reason == SCSI_REASON_DONE) {
256         DPRINTF("SCSI Command complete\n");
257         if (s->ti_size != 0)
258             DPRINTF("SCSI command completed unexpectedly\n");
259         s->ti_size = 0;
260         s->dma_left = 0;
261         s->async_len = 0;
262         if (arg)
263             DPRINTF("Command failed\n");
264         s->sense = arg;
265         s->rregs[4] = STAT_ST;
266         esp_dma_done(s);
267         s->current_dev = NULL;
268     } else {
269         DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
270         s->async_len = arg;
271         s->async_buf = scsi_get_buf(s->current_dev, 0);
272         if (s->dma_left)
273             esp_do_dma(s);
274     }
275 }
276
277 static void handle_ti(ESPState *s)
278 {
279     uint32_t dmalen, minlen;
280
281     dmalen = s->wregs[0] | (s->wregs[1] << 8);
282     if (dmalen==0) {
283       dmalen=0x10000;
284     }
285
286     if (s->do_cmd)
287         minlen = (dmalen < 32) ? dmalen : 32;
288     else if (s->ti_size < 0)
289         minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
290     else
291         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
292     DPRINTF("Transfer Information len %d\n", minlen);
293     if (s->dma) {
294         s->dma_left = minlen;
295         s->rregs[4] &= ~STAT_TC;
296         esp_do_dma(s);
297     } else if (s->do_cmd) {
298         DPRINTF("command len %d\n", s->cmdlen);
299         s->ti_size = 0;
300         s->cmdlen = 0;
301         s->do_cmd = 0;
302         do_cmd(s, s->cmdbuf);
303         return;
304     }
305 }
306
307 void esp_reset(void *opaque)
308 {
309     ESPState *s = opaque;
310
311     memset(s->rregs, 0, ESP_MAXREG);
312     memset(s->wregs, 0, ESP_MAXREG);
313     s->rregs[0x0e] = 0x4; // Indicate fas100a
314     s->ti_size = 0;
315     s->ti_rptr = 0;
316     s->ti_wptr = 0;
317     s->dma = 0;
318     s->do_cmd = 0;
319 }
320
321 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
322 {
323     ESPState *s = opaque;
324     uint32_t saddr;
325
326     saddr = (addr & ESP_MAXREG) >> 2;
327     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
328     switch (saddr) {
329     case 2:
330         // FIFO
331         if (s->ti_size > 0) {
332             s->ti_size--;
333             if ((s->rregs[4] & 6) == 0) {
334                 /* Data in/out.  */
335                 fprintf(stderr, "esp: PIO data read not implemented\n");
336                 s->rregs[2] = 0;
337             } else {
338                 s->rregs[2] = s->ti_buf[s->ti_rptr++];
339             }
340             espdma_raise_irq(s->dma_opaque);
341         }
342         if (s->ti_size == 0) {
343             s->ti_rptr = 0;
344             s->ti_wptr = 0;
345         }
346         break;
347     case 5:
348         // interrupt
349         // Clear interrupt/error status bits
350         s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);
351         espdma_clear_irq(s->dma_opaque);
352         break;
353     default:
354         break;
355     }
356     return s->rregs[saddr];
357 }
358
359 static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
360 {
361     ESPState *s = opaque;
362     uint32_t saddr;
363
364     saddr = (addr & ESP_MAXREG) >> 2;
365     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
366     switch (saddr) {
367     case 0:
368     case 1:
369         s->rregs[saddr] = val;
370         s->rregs[4] &= ~STAT_TC;
371         break;
372     case 2:
373         // FIFO
374         if (s->do_cmd) {
375             s->cmdbuf[s->cmdlen++] = val & 0xff;
376         } else if ((s->rregs[4] & 6) == 0) {
377             uint8_t buf;
378             buf = val & 0xff;
379             s->ti_size--;
380             fprintf(stderr, "esp: PIO data write not implemented\n");
381         } else {
382             s->ti_size++;
383             s->ti_buf[s->ti_wptr++] = val & 0xff;
384         }
385         break;
386     case 3:
387         s->rregs[saddr] = val;
388         // Command
389         if (val & 0x80) {
390             s->dma = 1;
391         } else {
392             s->dma = 0;
393         }
394         switch(val & 0x7f) {
395         case 0:
396             DPRINTF("NOP (%2.2x)\n", val);
397             break;
398         case 1:
399             DPRINTF("Flush FIFO (%2.2x)\n", val);
400             //s->ti_size = 0;
401             s->rregs[5] = INTR_FC;
402             s->rregs[6] = 0;
403             break;
404         case 2:
405             DPRINTF("Chip reset (%2.2x)\n", val);
406             esp_reset(s);
407             break;
408         case 3:
409             DPRINTF("Bus reset (%2.2x)\n", val);
410             s->rregs[5] = INTR_RST;
411             if (!(s->wregs[8] & 0x40)) {
412                 espdma_raise_irq(s->dma_opaque);
413             }
414             break;
415         case 0x10:
416             handle_ti(s);
417             break;
418         case 0x11:
419             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
420             write_response(s);
421             break;
422         case 0x12:
423             DPRINTF("Message Accepted (%2.2x)\n", val);
424             write_response(s);
425             s->rregs[5] = INTR_DC;
426             s->rregs[6] = 0;
427             break;
428         case 0x1a:
429             DPRINTF("Set ATN (%2.2x)\n", val);
430             break;
431         case 0x42:
432             DPRINTF("Set ATN (%2.2x)\n", val);
433             handle_satn(s);
434             break;
435         case 0x43:
436             DPRINTF("Set ATN & stop (%2.2x)\n", val);
437             handle_satn_stop(s);
438             break;
439         default:
440             DPRINTF("Unhandled ESP command (%2.2x)\n", val);
441             break;
442         }
443         break;
444     case 4 ... 7:
445         break;
446     case 8:
447         s->rregs[saddr] = val;
448         break;
449     case 9 ... 10:
450         break;
451     case 11:
452         s->rregs[saddr] = val & 0x15;
453         break;
454     case 12 ... 15:
455         s->rregs[saddr] = val;
456         break;
457     default:
458         break;
459     }
460     s->wregs[saddr] = val;
461 }
462
463 static CPUReadMemoryFunc *esp_mem_read[3] = {
464     esp_mem_readb,
465     esp_mem_readb,
466     esp_mem_readb,
467 };
468
469 static CPUWriteMemoryFunc *esp_mem_write[3] = {
470     esp_mem_writeb,
471     esp_mem_writeb,
472     esp_mem_writeb,
473 };
474
475 static void esp_save(QEMUFile *f, void *opaque)
476 {
477     ESPState *s = opaque;
478
479     qemu_put_buffer(f, s->rregs, ESP_MAXREG);
480     qemu_put_buffer(f, s->wregs, ESP_MAXREG);
481     qemu_put_be32s(f, &s->ti_size);
482     qemu_put_be32s(f, &s->ti_rptr);
483     qemu_put_be32s(f, &s->ti_wptr);
484     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
485     qemu_put_be32s(f, &s->dma);
486 }
487
488 static int esp_load(QEMUFile *f, void *opaque, int version_id)
489 {
490     ESPState *s = opaque;
491     
492     if (version_id != 2)
493         return -EINVAL; // Cannot emulate 1
494
495     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
496     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
497     qemu_get_be32s(f, &s->ti_size);
498     qemu_get_be32s(f, &s->ti_rptr);
499     qemu_get_be32s(f, &s->ti_wptr);
500     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
501     qemu_get_be32s(f, &s->dma);
502
503     return 0;
504 }
505
506 void *esp_init(BlockDriverState **bd, uint32_t espaddr, void *dma_opaque)
507 {
508     ESPState *s;
509     int esp_io_memory;
510     int i;
511
512     s = qemu_mallocz(sizeof(ESPState));
513     if (!s)
514         return NULL;
515
516     s->bd = bd;
517     s->dma_opaque = dma_opaque;
518
519     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
520     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
521
522     esp_reset(s);
523
524     register_savevm("esp", espaddr, 2, esp_save, esp_load, s);
525     qemu_register_reset(esp_reset, s);
526     for (i = 0; i < MAX_DISKS; i++) {
527         if (bs_table[i]) {
528             /* Command queueing is not implemented.  */
529             s->scsi_dev[i] =
530                 scsi_disk_init(bs_table[i], 0, esp_command_complete, s);
531         }
532     }
533
534     return s;
535 }