uppercase fix (Anthony Liguori)
[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 1024*1024 // XXX
42 #define DMA_VER 0xa0000000
43 #define DMA_INTR 1
44 #define DMA_INTREN 0x10
45 #define DMA_LOADED 0x04000000
46 typedef struct ESPState ESPState;
47
48 typedef int ESPDMAFunc(ESPState *s, 
49                        target_phys_addr_t phys_addr, 
50                        int transfer_size1);
51
52 struct ESPState {
53     BlockDriverState **bd;
54     uint8_t rregs[ESP_MAXREG];
55     uint8_t wregs[ESP_MAXREG];
56     int irq;
57     uint32_t espdmaregs[ESPDMA_REGS];
58     uint32_t ti_size;
59     uint32_t ti_rptr, ti_wptr;
60     int ti_dir;
61     uint8_t ti_buf[TI_BUFSZ];
62     int dma;
63     ESPDMAFunc *dma_cb;
64     int64_t offset, len;
65     int target;
66 };
67
68 #define STAT_DO 0x00
69 #define STAT_DI 0x01
70 #define STAT_CD 0x02
71 #define STAT_ST 0x03
72 #define STAT_MI 0x06
73 #define STAT_MO 0x07
74
75 #define STAT_TC 0x10
76 #define STAT_IN 0x80
77
78 #define INTR_FC 0x08
79 #define INTR_BS 0x10
80 #define INTR_DC 0x20
81 #define INTR_RST 0x80
82
83 #define SEQ_0 0x0
84 #define SEQ_CD 0x4
85
86 /* XXX: stolen from ide.c, move to common ATAPI/SCSI library */
87 static void lba_to_msf(uint8_t *buf, int lba)
88 {
89     lba += 150;
90     buf[0] = (lba / 75) / 60;
91     buf[1] = (lba / 75) % 60;
92     buf[2] = lba % 75;
93 }
94
95 static inline void cpu_to_ube16(uint8_t *buf, int val)
96 {
97     buf[0] = val >> 8;
98     buf[1] = val;
99 }
100
101 static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
102 {
103     buf[0] = val >> 24;
104     buf[1] = val >> 16;
105     buf[2] = val >> 8;
106     buf[3] = val;
107 }
108
109 /* same toc as bochs. Return -1 if error or the toc length */
110 /* XXX: check this */
111 static int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track)
112 {
113     uint8_t *q;
114     int len;
115     
116     if (start_track > 1 && start_track != 0xaa)
117         return -1;
118     q = buf + 2;
119     *q++ = 1; /* first session */
120     *q++ = 1; /* last session */
121     if (start_track <= 1) {
122         *q++ = 0; /* reserved */
123         *q++ = 0x14; /* ADR, control */
124         *q++ = 1;    /* track number */
125         *q++ = 0; /* reserved */
126         if (msf) {
127             *q++ = 0; /* reserved */
128             lba_to_msf(q, 0);
129             q += 3;
130         } else {
131             /* sector 0 */
132             cpu_to_ube32(q, 0);
133             q += 4;
134         }
135     }
136     /* lead out track */
137     *q++ = 0; /* reserved */
138     *q++ = 0x16; /* ADR, control */
139     *q++ = 0xaa; /* track number */
140     *q++ = 0; /* reserved */
141     if (msf) {
142         *q++ = 0; /* reserved */
143         lba_to_msf(q, nb_sectors);
144         q += 3;
145     } else {
146         cpu_to_ube32(q, nb_sectors);
147         q += 4;
148     }
149     len = q - buf;
150     cpu_to_ube16(buf, len - 2);
151     return len;
152 }
153
154 /* mostly same info as PearPc */
155 static int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, 
156                               int session_num)
157 {
158     uint8_t *q;
159     int len;
160     
161     q = buf + 2;
162     *q++ = 1; /* first session */
163     *q++ = 1; /* last session */
164
165     *q++ = 1; /* session number */
166     *q++ = 0x14; /* data track */
167     *q++ = 0; /* track number */
168     *q++ = 0xa0; /* lead-in */
169     *q++ = 0; /* min */
170     *q++ = 0; /* sec */
171     *q++ = 0; /* frame */
172     *q++ = 0;
173     *q++ = 1; /* first track */
174     *q++ = 0x00; /* disk type */
175     *q++ = 0x00;
176     
177     *q++ = 1; /* session number */
178     *q++ = 0x14; /* data track */
179     *q++ = 0; /* track number */
180     *q++ = 0xa1;
181     *q++ = 0; /* min */
182     *q++ = 0; /* sec */
183     *q++ = 0; /* frame */
184     *q++ = 0;
185     *q++ = 1; /* last track */
186     *q++ = 0x00;
187     *q++ = 0x00;
188     
189     *q++ = 1; /* session number */
190     *q++ = 0x14; /* data track */
191     *q++ = 0; /* track number */
192     *q++ = 0xa2; /* lead-out */
193     *q++ = 0; /* min */
194     *q++ = 0; /* sec */
195     *q++ = 0; /* frame */
196     if (msf) {
197         *q++ = 0; /* reserved */
198         lba_to_msf(q, nb_sectors);
199         q += 3;
200     } else {
201         cpu_to_ube32(q, nb_sectors);
202         q += 4;
203     }
204
205     *q++ = 1; /* session number */
206     *q++ = 0x14; /* ADR, control */
207     *q++ = 0;    /* track number */
208     *q++ = 1;    /* point */
209     *q++ = 0; /* min */
210     *q++ = 0; /* sec */
211     *q++ = 0; /* frame */
212     if (msf) {
213         *q++ = 0; 
214         lba_to_msf(q, 0);
215         q += 3;
216     } else {
217         *q++ = 0; 
218         *q++ = 0; 
219         *q++ = 0; 
220         *q++ = 0; 
221     }
222
223     len = q - buf;
224     cpu_to_ube16(buf, len - 2);
225     return len;
226 }
227
228 static int esp_write_dma_cb(ESPState *s, 
229                             target_phys_addr_t phys_addr, 
230                             int transfer_size1)
231 {
232     DPRINTF("Write callback (offset %lld len %lld size %d trans_size %d)\n",
233             s->offset, s->len, s->ti_size, transfer_size1);
234     bdrv_write(s->bd[s->target], s->offset, s->ti_buf, s->len);
235     s->offset = 0;
236     s->len = 0;
237     s->target = 0;
238     return 0;
239 }
240
241 static void handle_satn(ESPState *s)
242 {
243     uint8_t buf[32];
244     uint32_t dmaptr, dmalen;
245     unsigned int i;
246     int64_t nb_sectors;
247     int target;
248
249     dmalen = s->wregs[0] | (s->wregs[1] << 8);
250     target = s->wregs[4] & 7;
251     DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
252     if (s->dma) {
253         dmaptr = iommu_translate(s->espdmaregs[1]);
254         DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
255         cpu_physical_memory_read(dmaptr, buf, dmalen);
256     } else {
257         buf[0] = 0;
258         memcpy(&buf[1], s->ti_buf, dmalen);
259         dmalen++;
260     }
261     for (i = 0; i < dmalen; i++) {
262         DPRINTF("Command %2.2x\n", buf[i]);
263     }
264     s->ti_dir = 0;
265     s->ti_size = 0;
266     s->ti_rptr = 0;
267     s->ti_wptr = 0;
268
269     if (target >= 4 || !s->bd[target]) { // No such drive
270         s->rregs[4] = STAT_IN;
271         s->rregs[5] = INTR_DC;
272         s->rregs[6] = SEQ_0;
273         s->espdmaregs[0] |= DMA_INTR;
274         pic_set_irq(s->irq, 1);
275         return;
276     }
277     switch (buf[1]) {
278     case 0x0:
279         DPRINTF("Test Unit Ready (len %d)\n", buf[5]);
280         break;
281     case 0x12:
282         DPRINTF("Inquiry (len %d)\n", buf[5]);
283         memset(s->ti_buf, 0, 36);
284         if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
285             s->ti_buf[0] = 5;
286             memcpy(&s->ti_buf[16], "QEMU CDROM     ", 16);
287         } else {
288             s->ti_buf[0] = 0;
289             memcpy(&s->ti_buf[16], "QEMU HARDDISK  ", 16);
290         }
291         memcpy(&s->ti_buf[8], "QEMU   ", 8);
292         s->ti_buf[2] = 1;
293         s->ti_buf[3] = 2;
294         s->ti_buf[4] = 32;
295         s->ti_dir = 1;
296         s->ti_size = 36;
297         break;
298     case 0x1a:
299         DPRINTF("Mode Sense(6) (page %d, len %d)\n", buf[3], buf[5]);
300         break;
301     case 0x25:
302         DPRINTF("Read Capacity (len %d)\n", buf[5]);
303         memset(s->ti_buf, 0, 8);
304         bdrv_get_geometry(s->bd[target], &nb_sectors);
305         s->ti_buf[0] = (nb_sectors >> 24) & 0xff;
306         s->ti_buf[1] = (nb_sectors >> 16) & 0xff;
307         s->ti_buf[2] = (nb_sectors >> 8) & 0xff;
308         s->ti_buf[3] = nb_sectors & 0xff;
309         s->ti_buf[4] = 0;
310         s->ti_buf[5] = 0;
311         if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM)
312             s->ti_buf[6] = 8; // sector size 2048
313         else
314             s->ti_buf[6] = 2; // sector size 512
315         s->ti_buf[7] = 0;
316         s->ti_dir = 1;
317         s->ti_size = 8;
318         break;
319     case 0x28:
320         {
321             int64_t offset, len;
322
323             if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
324                 offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
325                 len = ((buf[8] << 8) | buf[9]) * 4;
326                 s->ti_size = len * 2048;
327             } else {
328                 offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
329                 len = (buf[8] << 8) | buf[9];
330                 s->ti_size = len * 512;
331             }
332             DPRINTF("Read (10) (offset %lld len %lld)\n", offset, len);
333             if (s->ti_size > TI_BUFSZ) {
334                 DPRINTF("size too large %d\n", s->ti_size);
335             }
336             bdrv_read(s->bd[target], offset, s->ti_buf, len);
337             // XXX error handling
338             s->ti_dir = 1;
339             break;
340         }
341     case 0x2a:
342         {
343             int64_t offset, len;
344
345             if (bdrv_get_type_hint(s->bd[target]) == BDRV_TYPE_CDROM) {
346                 offset = ((buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]) * 4;
347                 len = ((buf[8] << 8) | buf[9]) * 4;
348                 s->ti_size = len * 2048;
349             } else {
350                 offset = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6];
351                 len = (buf[8] << 8) | buf[9];
352                 s->ti_size = len * 512;
353             }
354             DPRINTF("Write (10) (offset %lld len %lld)\n", offset, len);
355             if (s->ti_size > TI_BUFSZ) {
356                 DPRINTF("size too large %d\n", s->ti_size);
357             }
358             s->dma_cb = esp_write_dma_cb;
359             s->offset = offset;
360             s->len = len;
361             s->target = target;
362             // XXX error handling
363             s->ti_dir = 0;
364             break;
365         }
366     case 0x43:
367         {
368             int start_track, format, msf, len;
369
370             msf = buf[2] & 2;
371             format = buf[3] & 0xf;
372             start_track = buf[7];
373             bdrv_get_geometry(s->bd[target], &nb_sectors);
374             DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1);
375             switch(format) {
376             case 0:
377                 len = cdrom_read_toc(nb_sectors, buf, msf, start_track);
378                 if (len < 0)
379                     goto error_cmd;
380                 s->ti_size = len;
381                 break;
382             case 1:
383                 /* multi session : only a single session defined */
384                 memset(buf, 0, 12);
385                 buf[1] = 0x0a;
386                 buf[2] = 0x01;
387                 buf[3] = 0x01;
388                 s->ti_size = 12;
389                 break;
390             case 2:
391                 len = cdrom_read_toc_raw(nb_sectors, buf, msf, start_track);
392                 if (len < 0)
393                     goto error_cmd;
394                 s->ti_size = len;
395                 break;
396             default:
397             error_cmd:
398                 DPRINTF("Read TOC error\n");
399                 // XXX error handling
400                 break;
401             }
402             s->ti_dir = 1;
403             break;
404         }
405     default:
406         DPRINTF("Unknown SCSI command (%2.2x)\n", buf[1]);
407         break;
408     }
409     s->rregs[4] = STAT_IN | STAT_TC | STAT_DI;
410     s->rregs[5] = INTR_BS | INTR_FC;
411     s->rregs[6] = SEQ_CD;
412     s->espdmaregs[0] |= DMA_INTR;
413     pic_set_irq(s->irq, 1);
414 }
415
416 static void dma_write(ESPState *s, const uint8_t *buf, uint32_t len)
417 {
418     uint32_t dmaptr, dmalen;
419
420     dmalen = s->wregs[0] | (s->wregs[1] << 8);
421     DPRINTF("Transfer status len %d\n", dmalen);
422     if (s->dma) {
423         dmaptr = iommu_translate(s->espdmaregs[1]);
424         DPRINTF("DMA Direction: %c\n", s->espdmaregs[0] & 0x100? 'w': 'r');
425         cpu_physical_memory_write(dmaptr, buf, len);
426         s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
427         s->rregs[5] = INTR_BS | INTR_FC;
428         s->rregs[6] = SEQ_CD;
429     } else {
430         memcpy(s->ti_buf, buf, len);
431         s->ti_size = dmalen;
432         s->ti_rptr = 0;
433         s->ti_wptr = 0;
434         s->rregs[7] = dmalen;
435     }
436     s->espdmaregs[0] |= DMA_INTR;
437     pic_set_irq(s->irq, 1);
438
439 }
440
441 static const uint8_t okbuf[] = {0, 0};
442
443 static void handle_ti(ESPState *s)
444 {
445     uint32_t dmaptr, dmalen;
446     unsigned int i;
447
448     dmalen = s->wregs[0] | (s->wregs[1] << 8);
449     DPRINTF("Transfer Information len %d\n", dmalen);
450     if (s->dma) {
451         dmaptr = iommu_translate(s->espdmaregs[1]);
452         DPRINTF("DMA Direction: %c, addr 0x%8.8x\n", s->espdmaregs[0] & 0x100? 'w': 'r', dmaptr);
453         for (i = 0; i < s->ti_size; i++) {
454             dmaptr = iommu_translate(s->espdmaregs[1] + i);
455             if (s->ti_dir)
456                 cpu_physical_memory_write(dmaptr, &s->ti_buf[i], 1);
457             else
458                 cpu_physical_memory_read(dmaptr, &s->ti_buf[i], 1);
459         }
460         if (s->dma_cb) {
461             s->dma_cb(s, s->espdmaregs[1], dmalen);
462             s->dma_cb = NULL;
463         }
464         s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
465         s->rregs[5] = INTR_BS;
466         s->rregs[6] = 0;
467         s->espdmaregs[0] |= DMA_INTR;
468     } else {
469         s->ti_size = dmalen;
470         s->ti_rptr = 0;
471         s->ti_wptr = 0;
472         s->rregs[7] = dmalen;
473     }   
474     pic_set_irq(s->irq, 1);
475 }
476
477 static void esp_reset(void *opaque)
478 {
479     ESPState *s = opaque;
480     memset(s->rregs, 0, ESP_MAXREG);
481     memset(s->wregs, 0, ESP_MAXREG);
482     s->rregs[0x0e] = 0x4; // Indicate fas100a
483     memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
484     s->ti_size = 0;
485     s->ti_rptr = 0;
486     s->ti_wptr = 0;
487     s->ti_dir = 0;
488     s->dma = 0;
489     s->dma_cb = NULL;
490 }
491
492 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
493 {
494     ESPState *s = opaque;
495     uint32_t saddr;
496
497     saddr = (addr & ESP_MAXREG) >> 2;
498     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
499     switch (saddr) {
500     case 2:
501         // FIFO
502         if (s->ti_size > 0) {
503             s->ti_size--;
504             s->rregs[saddr] = s->ti_buf[s->ti_rptr++];
505             pic_set_irq(s->irq, 1);
506         }
507         if (s->ti_size == 0) {
508             s->ti_rptr = 0;
509             s->ti_wptr = 0;
510         }
511         break;
512     case 5:
513         // interrupt
514         // Clear status bits except TC
515         s->rregs[4] &= STAT_TC;
516         pic_set_irq(s->irq, 0);
517         s->espdmaregs[0] &= ~DMA_INTR;
518         break;
519     default:
520         break;
521     }
522     return s->rregs[saddr];
523 }
524
525 static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
526 {
527     ESPState *s = opaque;
528     uint32_t saddr;
529
530     saddr = (addr & ESP_MAXREG) >> 2;
531     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
532     switch (saddr) {
533     case 0:
534     case 1:
535         s->rregs[saddr] = val;
536         break;
537     case 2:
538         // FIFO
539         s->ti_size++;
540         s->ti_buf[s->ti_wptr++] = val & 0xff;
541         break;
542     case 3:
543         s->rregs[saddr] = val;
544         // Command
545         if (val & 0x80) {
546             s->dma = 1;
547         } else {
548             s->dma = 0;
549         }
550         switch(val & 0x7f) {
551         case 0:
552             DPRINTF("NOP (%2.2x)\n", val);
553             break;
554         case 1:
555             DPRINTF("Flush FIFO (%2.2x)\n", val);
556             //s->ti_size = 0;
557             s->rregs[5] = INTR_FC;
558             s->rregs[6] = 0;
559             break;
560         case 2:
561             DPRINTF("Chip reset (%2.2x)\n", val);
562             esp_reset(s);
563             break;
564         case 3:
565             DPRINTF("Bus reset (%2.2x)\n", val);
566             s->rregs[5] = INTR_RST;
567             if (!(s->wregs[8] & 0x40)) {
568                 s->espdmaregs[0] |= DMA_INTR;
569                 pic_set_irq(s->irq, 1);
570             }
571             break;
572         case 0x10:
573             handle_ti(s);
574             break;
575         case 0x11:
576             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
577             dma_write(s, okbuf, 2);
578             break;
579         case 0x12:
580             DPRINTF("Message Accepted (%2.2x)\n", val);
581             dma_write(s, okbuf, 2);
582             s->rregs[5] = INTR_DC;
583             s->rregs[6] = 0;
584             break;
585         case 0x1a:
586             DPRINTF("Set ATN (%2.2x)\n", val);
587             break;
588         case 0x42:
589             handle_satn(s);
590             break;
591         case 0x43:
592             DPRINTF("Set ATN & stop (%2.2x)\n", val);
593             handle_satn(s);
594             break;
595         default:
596             DPRINTF("Unhandled ESP command (%2.2x)\n", val);
597             break;
598         }
599         break;
600     case 4 ... 7:
601         break;
602     case 8:
603         s->rregs[saddr] = val;
604         break;
605     case 9 ... 10:
606         break;
607     case 11:
608         s->rregs[saddr] = val & 0x15;
609         break;
610     case 12 ... 15:
611         s->rregs[saddr] = val;
612         break;
613     default:
614         break;
615     }
616     s->wregs[saddr] = val;
617 }
618
619 static CPUReadMemoryFunc *esp_mem_read[3] = {
620     esp_mem_readb,
621     esp_mem_readb,
622     esp_mem_readb,
623 };
624
625 static CPUWriteMemoryFunc *esp_mem_write[3] = {
626     esp_mem_writeb,
627     esp_mem_writeb,
628     esp_mem_writeb,
629 };
630
631 static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
632 {
633     ESPState *s = opaque;
634     uint32_t saddr;
635
636     saddr = (addr & ESPDMA_MAXADDR) >> 2;
637     DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
638
639     return s->espdmaregs[saddr];
640 }
641
642 static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
643 {
644     ESPState *s = opaque;
645     uint32_t saddr;
646
647     saddr = (addr & ESPDMA_MAXADDR) >> 2;
648     DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
649     switch (saddr) {
650     case 0:
651         if (!(val & DMA_INTREN))
652             pic_set_irq(s->irq, 0);
653         if (val & 0x80) {
654             esp_reset(s);
655         } else if (val & 0x40) {
656             val &= ~0x40;
657         } else if (val == 0)
658             val = 0x40;
659         val &= 0x0fffffff;
660         val |= DMA_VER;
661         break;
662     case 1:
663         s->espdmaregs[0] = DMA_LOADED;
664         break;
665     default:
666         break;
667     }
668     s->espdmaregs[saddr] = val;
669 }
670
671 static CPUReadMemoryFunc *espdma_mem_read[3] = {
672     espdma_mem_readl,
673     espdma_mem_readl,
674     espdma_mem_readl,
675 };
676
677 static CPUWriteMemoryFunc *espdma_mem_write[3] = {
678     espdma_mem_writel,
679     espdma_mem_writel,
680     espdma_mem_writel,
681 };
682
683 static void esp_save(QEMUFile *f, void *opaque)
684 {
685     ESPState *s = opaque;
686     unsigned int i;
687
688     qemu_put_buffer(f, s->rregs, ESP_MAXREG);
689     qemu_put_buffer(f, s->wregs, ESP_MAXREG);
690     qemu_put_be32s(f, &s->irq);
691     for (i = 0; i < ESPDMA_REGS; i++)
692         qemu_put_be32s(f, &s->espdmaregs[i]);
693     qemu_put_be32s(f, &s->ti_size);
694     qemu_put_be32s(f, &s->ti_rptr);
695     qemu_put_be32s(f, &s->ti_wptr);
696     qemu_put_be32s(f, &s->ti_dir);
697     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
698     qemu_put_be32s(f, &s->dma);
699 }
700
701 static int esp_load(QEMUFile *f, void *opaque, int version_id)
702 {
703     ESPState *s = opaque;
704     unsigned int i;
705     
706     if (version_id != 1)
707         return -EINVAL;
708
709     qemu_get_buffer(f, s->rregs, ESP_MAXREG);
710     qemu_get_buffer(f, s->wregs, ESP_MAXREG);
711     qemu_get_be32s(f, &s->irq);
712     for (i = 0; i < ESPDMA_REGS; i++)
713         qemu_get_be32s(f, &s->espdmaregs[i]);
714     qemu_get_be32s(f, &s->ti_size);
715     qemu_get_be32s(f, &s->ti_rptr);
716     qemu_get_be32s(f, &s->ti_wptr);
717     qemu_get_be32s(f, &s->ti_dir);
718     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
719     qemu_get_be32s(f, &s->dma);
720
721     return 0;
722 }
723
724 void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
725 {
726     ESPState *s;
727     int esp_io_memory, espdma_io_memory;
728
729     s = qemu_mallocz(sizeof(ESPState));
730     if (!s)
731         return;
732
733     s->bd = bd;
734     s->irq = irq;
735
736     esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
737     cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
738
739     espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
740     cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
741
742     esp_reset(s);
743
744     register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
745     qemu_register_reset(esp_reset, s);
746 }
747