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