Statistics
| Branch: | Revision:

root / hw / esp.c @ 6f7e9aec

History | View | Annotate | Download (4.7 kB)

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
#else
33
#define DPRINTF(fmt, args...)
34
#endif
35

    
36
#define ESPDMA_REGS 4
37
#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
38
#define ESP_MAXREG 0x3f
39

    
40
typedef struct ESPState {
41
    BlockDriverState **bd;
42
    uint8_t regs[ESP_MAXREG];
43
    int irq;
44
    uint32_t espdmaregs[ESPDMA_REGS];
45
} ESPState;
46

    
47
static void esp_reset(void *opaque)
48
{
49
    ESPState *s = opaque;
50
    memset(s->regs, 0, ESP_MAXREG);
51
    s->regs[0x0e] = 0x4; // Indicate fas100a
52
    memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
53
}
54

    
55
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
56
{
57
    ESPState *s = opaque;
58
    uint32_t saddr;
59

    
60
    saddr = (addr & ESP_MAXREG) >> 2;
61
    switch (saddr) {
62
    default:
63
        break;
64
    }
65
    DPRINTF("esp: read reg[%d]: 0x%2.2x\n", saddr, s->regs[saddr]);
66
    return s->regs[saddr];
67
}
68

    
69
static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
70
{
71
    ESPState *s = opaque;
72
    uint32_t saddr;
73

    
74
    saddr = (addr & ESP_MAXREG) >> 2;
75
    DPRINTF("esp: write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->regs[saddr], val);
76
    switch (saddr) {
77
    case 3:
78
        // Command
79
        switch(val & 0x7f) {
80
        case 0:
81
            DPRINTF("esp: NOP (%2.2x)\n", val);
82
            break;
83
        case 2:
84
            DPRINTF("esp: Chip reset (%2.2x)\n", val);
85
            esp_reset(s);
86
            break;
87
        case 3:
88
            DPRINTF("esp: Bus reset (%2.2x)\n", val);
89
            break;
90
        case 0x1a:
91
            DPRINTF("esp: Set ATN (%2.2x)\n", val);
92
            break;
93
        case 0x42:
94
            DPRINTF("esp: Select with ATN (%2.2x)\n", val);
95
            s->regs[4] = 0x1a; // Status: TCNT | TDONE | CMD
96
            s->regs[5] = 0x20; // Intr: Disconnect, nobody there
97
            s->regs[6] = 0x4;  // Seq: Cmd done
98
            pic_set_irq(s->irq, 1);
99
            break;
100
        }
101
        break;
102
    case 4 ... 7:
103
    case 9 ... 0xf:
104
        break;
105
    default:
106
        s->regs[saddr] = val;
107
        break;
108
    }
109
}
110

    
111
static CPUReadMemoryFunc *esp_mem_read[3] = {
112
    esp_mem_readb,
113
    esp_mem_readb,
114
    esp_mem_readb,
115
};
116

    
117
static CPUWriteMemoryFunc *esp_mem_write[3] = {
118
    esp_mem_writeb,
119
    esp_mem_writeb,
120
    esp_mem_writeb,
121
};
122

    
123
static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
124
{
125
    ESPState *s = opaque;
126
    uint32_t saddr;
127

    
128
    saddr = (addr & ESPDMA_MAXADDR) >> 2;
129
    return s->espdmaregs[saddr];
130
}
131

    
132
static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
133
{
134
    ESPState *s = opaque;
135
    uint32_t saddr;
136

    
137
    saddr = (addr & ESPDMA_MAXADDR) >> 2;
138
    s->espdmaregs[saddr] = val;
139
}
140

    
141
static CPUReadMemoryFunc *espdma_mem_read[3] = {
142
    espdma_mem_readl,
143
    espdma_mem_readl,
144
    espdma_mem_readl,
145
};
146

    
147
static CPUWriteMemoryFunc *espdma_mem_write[3] = {
148
    espdma_mem_writel,
149
    espdma_mem_writel,
150
    espdma_mem_writel,
151
};
152

    
153
static void esp_save(QEMUFile *f, void *opaque)
154
{
155
    ESPState *s = opaque;
156
    
157
}
158

    
159
static int esp_load(QEMUFile *f, void *opaque, int version_id)
160
{
161
    ESPState *s = opaque;
162
    
163
    if (version_id != 1)
164
        return -EINVAL;
165

    
166
    return 0;
167
}
168

    
169
void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
170
{
171
    ESPState *s;
172
    int esp_io_memory, espdma_io_memory;
173

    
174
    s = qemu_mallocz(sizeof(ESPState));
175
    if (!s)
176
        return;
177

    
178
    s->bd = bd;
179
    s->irq = irq;
180

    
181
    esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
182
    cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
183

    
184
    espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
185
    cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
186

    
187
    esp_reset(s);
188

    
189
    register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
190
    qemu_register_reset(esp_reset, s);
191
}
192