Statistics
| Branch: | Revision:

root / hw / esp.c @ 26a76461

History | View | Annotate | Download (14.5 kB)

1 6f7e9aec bellard
/*
2 6f7e9aec bellard
 * QEMU ESP emulation
3 6f7e9aec bellard
 * 
4 4e9aec74 pbrook
 * Copyright (c) 2005-2006 Fabrice Bellard
5 6f7e9aec bellard
 * 
6 6f7e9aec bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 6f7e9aec bellard
 * of this software and associated documentation files (the "Software"), to deal
8 6f7e9aec bellard
 * in the Software without restriction, including without limitation the rights
9 6f7e9aec bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 6f7e9aec bellard
 * copies of the Software, and to permit persons to whom the Software is
11 6f7e9aec bellard
 * furnished to do so, subject to the following conditions:
12 6f7e9aec bellard
 *
13 6f7e9aec bellard
 * The above copyright notice and this permission notice shall be included in
14 6f7e9aec bellard
 * all copies or substantial portions of the Software.
15 6f7e9aec bellard
 *
16 6f7e9aec bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 6f7e9aec bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 6f7e9aec bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 6f7e9aec bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 6f7e9aec bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 6f7e9aec bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 6f7e9aec bellard
 * THE SOFTWARE.
23 6f7e9aec bellard
 */
24 6f7e9aec bellard
#include "vl.h"
25 6f7e9aec bellard
26 6f7e9aec bellard
/* debug ESP card */
27 2f275b8f bellard
//#define DEBUG_ESP
28 6f7e9aec bellard
29 6f7e9aec bellard
#ifdef DEBUG_ESP
30 6f7e9aec bellard
#define DPRINTF(fmt, args...) \
31 6f7e9aec bellard
do { printf("ESP: " fmt , ##args); } while (0)
32 9e61bde5 bellard
#define pic_set_irq(irq, level) \
33 9e61bde5 bellard
do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
34 6f7e9aec bellard
#else
35 6f7e9aec bellard
#define DPRINTF(fmt, args...)
36 6f7e9aec bellard
#endif
37 6f7e9aec bellard
38 6f7e9aec bellard
#define ESPDMA_REGS 4
39 6f7e9aec bellard
#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
40 6f7e9aec bellard
#define ESP_MAXREG 0x3f
41 2e5d83bb pbrook
#define TI_BUFSZ 32
42 4f6200f0 bellard
#define DMA_VER 0xa0000000
43 9e61bde5 bellard
#define DMA_INTR 1
44 9e61bde5 bellard
#define DMA_INTREN 0x10
45 2e5d83bb pbrook
#define DMA_WRITE_MEM 0x100
46 4f6200f0 bellard
#define DMA_LOADED 0x04000000
47 4e9aec74 pbrook
typedef struct ESPState ESPState;
48 6f7e9aec bellard
49 4e9aec74 pbrook
struct ESPState {
50 6f7e9aec bellard
    BlockDriverState **bd;
51 2f275b8f bellard
    uint8_t rregs[ESP_MAXREG];
52 2f275b8f bellard
    uint8_t wregs[ESP_MAXREG];
53 6f7e9aec bellard
    int irq;
54 6f7e9aec bellard
    uint32_t espdmaregs[ESPDMA_REGS];
55 2f275b8f bellard
    uint32_t ti_size;
56 4f6200f0 bellard
    uint32_t ti_rptr, ti_wptr;
57 4f6200f0 bellard
    uint8_t ti_buf[TI_BUFSZ];
58 0fc5c15a pbrook
    int sense;
59 4f6200f0 bellard
    int dma;
60 2e5d83bb pbrook
    SCSIDevice *scsi_dev[MAX_DISKS];
61 2e5d83bb pbrook
    SCSIDevice *current_dev;
62 9f149aa9 pbrook
    uint8_t cmdbuf[TI_BUFSZ];
63 9f149aa9 pbrook
    int cmdlen;
64 9f149aa9 pbrook
    int do_cmd;
65 4e9aec74 pbrook
};
66 6f7e9aec bellard
67 2f275b8f bellard
#define STAT_DO 0x00
68 2f275b8f bellard
#define STAT_DI 0x01
69 2f275b8f bellard
#define STAT_CD 0x02
70 2f275b8f bellard
#define STAT_ST 0x03
71 2f275b8f bellard
#define STAT_MI 0x06
72 2f275b8f bellard
#define STAT_MO 0x07
73 2f275b8f bellard
74 2f275b8f bellard
#define STAT_TC 0x10
75 2f275b8f bellard
#define STAT_IN 0x80
76 2f275b8f bellard
77 2f275b8f bellard
#define INTR_FC 0x08
78 2f275b8f bellard
#define INTR_BS 0x10
79 2f275b8f bellard
#define INTR_DC 0x20
80 9e61bde5 bellard
#define INTR_RST 0x80
81 2f275b8f bellard
82 2f275b8f bellard
#define SEQ_0 0x0
83 2f275b8f bellard
#define SEQ_CD 0x4
84 2f275b8f bellard
85 9f149aa9 pbrook
static int get_cmd(ESPState *s, uint8_t *buf)
86 2f275b8f bellard
{
87 2f275b8f bellard
    uint32_t dmaptr, dmalen;
88 2f275b8f bellard
    int target;
89 2f275b8f bellard
90 2f275b8f bellard
    dmalen = s->wregs[0] | (s->wregs[1] << 8);
91 4f6200f0 bellard
    target = s->wregs[4] & 7;
92 9f149aa9 pbrook
    DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
93 4f6200f0 bellard
    if (s->dma) {
94 4f6200f0 bellard
        dmaptr = iommu_translate(s->espdmaregs[1]);
95 2e5d83bb pbrook
        DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
96 2e5d83bb pbrook
                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
97 4f6200f0 bellard
        cpu_physical_memory_read(dmaptr, buf, dmalen);
98 4f6200f0 bellard
    } else {
99 4f6200f0 bellard
        buf[0] = 0;
100 4f6200f0 bellard
        memcpy(&buf[1], s->ti_buf, dmalen);
101 4f6200f0 bellard
        dmalen++;
102 4f6200f0 bellard
    }
103 2e5d83bb pbrook
104 2f275b8f bellard
    s->ti_size = 0;
105 4f6200f0 bellard
    s->ti_rptr = 0;
106 4f6200f0 bellard
    s->ti_wptr = 0;
107 2f275b8f bellard
108 2e5d83bb pbrook
    if (target >= 4 || !s->scsi_dev[target]) {
109 2e5d83bb pbrook
        // No such drive
110 2f275b8f bellard
        s->rregs[4] = STAT_IN;
111 2f275b8f bellard
        s->rregs[5] = INTR_DC;
112 2f275b8f bellard
        s->rregs[6] = SEQ_0;
113 9e61bde5 bellard
        s->espdmaregs[0] |= DMA_INTR;
114 2f275b8f bellard
        pic_set_irq(s->irq, 1);
115 9f149aa9 pbrook
        return 0;
116 2f275b8f bellard
    }
117 2e5d83bb pbrook
    s->current_dev = s->scsi_dev[target];
118 9f149aa9 pbrook
    return dmalen;
119 9f149aa9 pbrook
}
120 9f149aa9 pbrook
121 9f149aa9 pbrook
static void do_cmd(ESPState *s, uint8_t *buf)
122 9f149aa9 pbrook
{
123 9f149aa9 pbrook
    int32_t datalen;
124 9f149aa9 pbrook
    int lun;
125 9f149aa9 pbrook
126 9f149aa9 pbrook
    DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
127 9f149aa9 pbrook
    lun = buf[0] & 7;
128 0fc5c15a pbrook
    datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
129 2e5d83bb pbrook
    if (datalen == 0) {
130 2e5d83bb pbrook
        s->ti_size = 0;
131 2e5d83bb pbrook
    } else {
132 2e5d83bb pbrook
        s->rregs[4] = STAT_IN | STAT_TC;
133 2e5d83bb pbrook
        if (datalen > 0) {
134 2e5d83bb pbrook
            s->rregs[4] |= STAT_DI;
135 2e5d83bb pbrook
            s->ti_size = datalen;
136 2e5d83bb pbrook
        } else {
137 2e5d83bb pbrook
            s->rregs[4] |= STAT_DO;
138 2e5d83bb pbrook
            s->ti_size = -datalen;
139 b9788fc4 bellard
        }
140 2f275b8f bellard
    }
141 2f275b8f bellard
    s->rregs[5] = INTR_BS | INTR_FC;
142 2f275b8f bellard
    s->rregs[6] = SEQ_CD;
143 9e61bde5 bellard
    s->espdmaregs[0] |= DMA_INTR;
144 2f275b8f bellard
    pic_set_irq(s->irq, 1);
145 2f275b8f bellard
}
146 2f275b8f bellard
147 9f149aa9 pbrook
static void handle_satn(ESPState *s)
148 9f149aa9 pbrook
{
149 9f149aa9 pbrook
    uint8_t buf[32];
150 9f149aa9 pbrook
    int len;
151 9f149aa9 pbrook
152 9f149aa9 pbrook
    len = get_cmd(s, buf);
153 9f149aa9 pbrook
    if (len)
154 9f149aa9 pbrook
        do_cmd(s, buf);
155 9f149aa9 pbrook
}
156 9f149aa9 pbrook
157 9f149aa9 pbrook
static void handle_satn_stop(ESPState *s)
158 9f149aa9 pbrook
{
159 9f149aa9 pbrook
    s->cmdlen = get_cmd(s, s->cmdbuf);
160 9f149aa9 pbrook
    if (s->cmdlen) {
161 9f149aa9 pbrook
        DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
162 9f149aa9 pbrook
        s->do_cmd = 1;
163 9f149aa9 pbrook
        s->espdmaregs[1] += s->cmdlen;
164 9f149aa9 pbrook
        s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
165 9f149aa9 pbrook
        s->rregs[5] = INTR_BS | INTR_FC;
166 9f149aa9 pbrook
        s->rregs[6] = SEQ_CD;
167 9f149aa9 pbrook
        s->espdmaregs[0] |= DMA_INTR;
168 9f149aa9 pbrook
        pic_set_irq(s->irq, 1);
169 9f149aa9 pbrook
    }
170 9f149aa9 pbrook
}
171 9f149aa9 pbrook
172 0fc5c15a pbrook
static void write_response(ESPState *s)
173 2f275b8f bellard
{
174 db59203d pbrook
    uint32_t dmaptr;
175 2f275b8f bellard
176 0fc5c15a pbrook
    DPRINTF("Transfer status (sense=%d)\n", s->sense);
177 0fc5c15a pbrook
    s->ti_buf[0] = s->sense;
178 0fc5c15a pbrook
    s->ti_buf[1] = 0;
179 4f6200f0 bellard
    if (s->dma) {
180 4f6200f0 bellard
        dmaptr = iommu_translate(s->espdmaregs[1]);
181 2e5d83bb pbrook
        DPRINTF("DMA Direction: %c\n",
182 2e5d83bb pbrook
                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
183 0fc5c15a pbrook
        cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
184 4f6200f0 bellard
        s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
185 4f6200f0 bellard
        s->rregs[5] = INTR_BS | INTR_FC;
186 4f6200f0 bellard
        s->rregs[6] = SEQ_CD;
187 4f6200f0 bellard
    } else {
188 0fc5c15a pbrook
        s->ti_size = 2;
189 4f6200f0 bellard
        s->ti_rptr = 0;
190 4f6200f0 bellard
        s->ti_wptr = 0;
191 0fc5c15a pbrook
        s->rregs[7] = 2;
192 4f6200f0 bellard
    }
193 9e61bde5 bellard
    s->espdmaregs[0] |= DMA_INTR;
194 2f275b8f bellard
    pic_set_irq(s->irq, 1);
195 2f275b8f bellard
196 2f275b8f bellard
}
197 4f6200f0 bellard
198 0fc5c15a pbrook
static void esp_command_complete(void *opaque, uint32_t tag, int sense)
199 2e5d83bb pbrook
{
200 2e5d83bb pbrook
    ESPState *s = (ESPState *)opaque;
201 2e5d83bb pbrook
202 2e5d83bb pbrook
    DPRINTF("SCSI Command complete\n");
203 2e5d83bb pbrook
    if (s->ti_size != 0)
204 2e5d83bb pbrook
        DPRINTF("SCSI command completed unexpectedly\n");
205 2e5d83bb pbrook
    s->ti_size = 0;
206 0fc5c15a pbrook
    if (sense)
207 2e5d83bb pbrook
        DPRINTF("Command failed\n");
208 0fc5c15a pbrook
    s->sense = sense;
209 2e5d83bb pbrook
    s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
210 2e5d83bb pbrook
}
211 2e5d83bb pbrook
212 2f275b8f bellard
static void handle_ti(ESPState *s)
213 2f275b8f bellard
{
214 db59203d pbrook
    uint32_t dmaptr, dmalen, minlen, len, from, to;
215 2f275b8f bellard
    unsigned int i;
216 2e5d83bb pbrook
    int to_device;
217 2e5d83bb pbrook
    uint8_t buf[TARGET_PAGE_SIZE];
218 2f275b8f bellard
219 2f275b8f bellard
    dmalen = s->wregs[0] | (s->wregs[1] << 8);
220 db59203d pbrook
    if (dmalen==0) {
221 db59203d pbrook
      dmalen=0x10000;
222 db59203d pbrook
    }
223 db59203d pbrook
224 9f149aa9 pbrook
    if (s->do_cmd)
225 9f149aa9 pbrook
        minlen = (dmalen < 32) ? dmalen : 32;
226 9f149aa9 pbrook
    else
227 9f149aa9 pbrook
        minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
228 db59203d pbrook
    DPRINTF("Transfer Information len %d\n", minlen);
229 4f6200f0 bellard
    if (s->dma) {
230 4f6200f0 bellard
        dmaptr = iommu_translate(s->espdmaregs[1]);
231 2e5d83bb pbrook
        /* Check if the transfer writes to to reads from the device.  */
232 2e5d83bb pbrook
        to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
233 2e5d83bb pbrook
        DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n",
234 2e5d83bb pbrook
                to_device ? 'r': 'w', dmaptr, s->ti_size);
235 db59203d pbrook
        from = s->espdmaregs[1];
236 db59203d pbrook
        to = from + minlen;
237 db59203d pbrook
        for (i = 0; i < minlen; i += len, from += len) {
238 4f6200f0 bellard
            dmaptr = iommu_translate(s->espdmaregs[1] + i);
239 db59203d pbrook
            if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
240 db59203d pbrook
               len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
241 db59203d pbrook
            } else {
242 db59203d pbrook
               len = to - from;
243 db59203d pbrook
            }
244 db59203d pbrook
            DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
245 2e5d83bb pbrook
            s->ti_size -= len;
246 9f149aa9 pbrook
            if (s->do_cmd) {
247 9f149aa9 pbrook
                DPRINTF("command len %d + %d\n", s->cmdlen, len);
248 9f149aa9 pbrook
                cpu_physical_memory_read(dmaptr, &s->cmdbuf[s->cmdlen], len);
249 9f149aa9 pbrook
                s->ti_size = 0;
250 9f149aa9 pbrook
                s->cmdlen = 0;
251 9f149aa9 pbrook
                s->do_cmd = 0;
252 9f149aa9 pbrook
                do_cmd(s, s->cmdbuf);
253 9f149aa9 pbrook
                return;
254 2e5d83bb pbrook
            } else {
255 9f149aa9 pbrook
                if (to_device) {
256 9f149aa9 pbrook
                    cpu_physical_memory_read(dmaptr, buf, len);
257 9f149aa9 pbrook
                    scsi_write_data(s->current_dev, buf, len);
258 9f149aa9 pbrook
                } else {
259 9f149aa9 pbrook
                    scsi_read_data(s->current_dev, buf, len);
260 9f149aa9 pbrook
                    cpu_physical_memory_write(dmaptr, buf, len);
261 9f149aa9 pbrook
                }
262 2e5d83bb pbrook
            }
263 9f149aa9 pbrook
        }
264 2e5d83bb pbrook
        if (s->ti_size) {
265 2e5d83bb pbrook
            s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
266 4e9aec74 pbrook
        }
267 db59203d pbrook
        s->rregs[5] = INTR_BS;
268 4f6200f0 bellard
        s->rregs[6] = 0;
269 db59203d pbrook
        s->rregs[7] = 0;
270 9e61bde5 bellard
        s->espdmaregs[0] |= DMA_INTR;
271 9f149aa9 pbrook
    } else if (s->do_cmd) {
272 9f149aa9 pbrook
        DPRINTF("command len %d\n", s->cmdlen);
273 9f149aa9 pbrook
        s->ti_size = 0;
274 9f149aa9 pbrook
        s->cmdlen = 0;
275 9f149aa9 pbrook
        s->do_cmd = 0;
276 9f149aa9 pbrook
        do_cmd(s, s->cmdbuf);
277 9f149aa9 pbrook
        return;
278 9f149aa9 pbrook
    }
279 2f275b8f bellard
    pic_set_irq(s->irq, 1);
280 2f275b8f bellard
}
281 2f275b8f bellard
282 6f7e9aec bellard
static void esp_reset(void *opaque)
283 6f7e9aec bellard
{
284 6f7e9aec bellard
    ESPState *s = opaque;
285 2f275b8f bellard
    memset(s->rregs, 0, ESP_MAXREG);
286 4e9aec74 pbrook
    memset(s->wregs, 0, ESP_MAXREG);
287 2f275b8f bellard
    s->rregs[0x0e] = 0x4; // Indicate fas100a
288 6f7e9aec bellard
    memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
289 4e9aec74 pbrook
    s->ti_size = 0;
290 4e9aec74 pbrook
    s->ti_rptr = 0;
291 4e9aec74 pbrook
    s->ti_wptr = 0;
292 4e9aec74 pbrook
    s->dma = 0;
293 9f149aa9 pbrook
    s->do_cmd = 0;
294 6f7e9aec bellard
}
295 6f7e9aec bellard
296 6f7e9aec bellard
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
297 6f7e9aec bellard
{
298 6f7e9aec bellard
    ESPState *s = opaque;
299 6f7e9aec bellard
    uint32_t saddr;
300 6f7e9aec bellard
301 6f7e9aec bellard
    saddr = (addr & ESP_MAXREG) >> 2;
302 9e61bde5 bellard
    DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
303 6f7e9aec bellard
    switch (saddr) {
304 4f6200f0 bellard
    case 2:
305 4f6200f0 bellard
        // FIFO
306 4f6200f0 bellard
        if (s->ti_size > 0) {
307 4f6200f0 bellard
            s->ti_size--;
308 2e5d83bb pbrook
            if ((s->rregs[4] & 6) == 0) {
309 2e5d83bb pbrook
                /* Data in/out.  */
310 2e5d83bb pbrook
                scsi_read_data(s->current_dev, &s->rregs[2], 0);
311 2e5d83bb pbrook
            } else {
312 2e5d83bb pbrook
                s->rregs[2] = s->ti_buf[s->ti_rptr++];
313 2e5d83bb pbrook
            }
314 4f6200f0 bellard
            pic_set_irq(s->irq, 1);
315 4f6200f0 bellard
        }
316 4f6200f0 bellard
        if (s->ti_size == 0) {
317 4f6200f0 bellard
            s->ti_rptr = 0;
318 4f6200f0 bellard
            s->ti_wptr = 0;
319 4f6200f0 bellard
        }
320 4f6200f0 bellard
        break;
321 9e61bde5 bellard
    case 5:
322 9e61bde5 bellard
        // interrupt
323 9e61bde5 bellard
        // Clear status bits except TC
324 9e61bde5 bellard
        s->rregs[4] &= STAT_TC;
325 9e61bde5 bellard
        pic_set_irq(s->irq, 0);
326 9e61bde5 bellard
        s->espdmaregs[0] &= ~DMA_INTR;
327 9e61bde5 bellard
        break;
328 6f7e9aec bellard
    default:
329 6f7e9aec bellard
        break;
330 6f7e9aec bellard
    }
331 2f275b8f bellard
    return s->rregs[saddr];
332 6f7e9aec bellard
}
333 6f7e9aec bellard
334 6f7e9aec bellard
static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
335 6f7e9aec bellard
{
336 6f7e9aec bellard
    ESPState *s = opaque;
337 6f7e9aec bellard
    uint32_t saddr;
338 6f7e9aec bellard
339 6f7e9aec bellard
    saddr = (addr & ESP_MAXREG) >> 2;
340 2f275b8f bellard
    DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
341 6f7e9aec bellard
    switch (saddr) {
342 4f6200f0 bellard
    case 0:
343 4f6200f0 bellard
    case 1:
344 4f6200f0 bellard
        s->rregs[saddr] = val;
345 4f6200f0 bellard
        break;
346 4f6200f0 bellard
    case 2:
347 4f6200f0 bellard
        // FIFO
348 9f149aa9 pbrook
        if (s->do_cmd) {
349 9f149aa9 pbrook
            s->cmdbuf[s->cmdlen++] = val & 0xff;
350 9f149aa9 pbrook
        } else if ((s->rregs[4] & 6) == 0) {
351 2e5d83bb pbrook
            uint8_t buf;
352 2e5d83bb pbrook
            buf = val & 0xff;
353 2e5d83bb pbrook
            s->ti_size--;
354 2e5d83bb pbrook
            scsi_write_data(s->current_dev, &buf, 0);
355 2e5d83bb pbrook
        } else {
356 2e5d83bb pbrook
            s->ti_size++;
357 2e5d83bb pbrook
            s->ti_buf[s->ti_wptr++] = val & 0xff;
358 2e5d83bb pbrook
        }
359 4f6200f0 bellard
        break;
360 6f7e9aec bellard
    case 3:
361 4f6200f0 bellard
        s->rregs[saddr] = val;
362 6f7e9aec bellard
        // Command
363 4f6200f0 bellard
        if (val & 0x80) {
364 4f6200f0 bellard
            s->dma = 1;
365 4f6200f0 bellard
        } else {
366 4f6200f0 bellard
            s->dma = 0;
367 4f6200f0 bellard
        }
368 6f7e9aec bellard
        switch(val & 0x7f) {
369 6f7e9aec bellard
        case 0:
370 2f275b8f bellard
            DPRINTF("NOP (%2.2x)\n", val);
371 2f275b8f bellard
            break;
372 2f275b8f bellard
        case 1:
373 2f275b8f bellard
            DPRINTF("Flush FIFO (%2.2x)\n", val);
374 9e61bde5 bellard
            //s->ti_size = 0;
375 2f275b8f bellard
            s->rregs[5] = INTR_FC;
376 9e61bde5 bellard
            s->rregs[6] = 0;
377 6f7e9aec bellard
            break;
378 6f7e9aec bellard
        case 2:
379 2f275b8f bellard
            DPRINTF("Chip reset (%2.2x)\n", val);
380 6f7e9aec bellard
            esp_reset(s);
381 6f7e9aec bellard
            break;
382 6f7e9aec bellard
        case 3:
383 2f275b8f bellard
            DPRINTF("Bus reset (%2.2x)\n", val);
384 9e61bde5 bellard
            s->rregs[5] = INTR_RST;
385 9e61bde5 bellard
            if (!(s->wregs[8] & 0x40)) {
386 9e61bde5 bellard
                s->espdmaregs[0] |= DMA_INTR;
387 9e61bde5 bellard
                pic_set_irq(s->irq, 1);
388 9e61bde5 bellard
            }
389 2f275b8f bellard
            break;
390 2f275b8f bellard
        case 0x10:
391 2f275b8f bellard
            handle_ti(s);
392 2f275b8f bellard
            break;
393 2f275b8f bellard
        case 0x11:
394 2f275b8f bellard
            DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
395 0fc5c15a pbrook
            write_response(s);
396 2f275b8f bellard
            break;
397 2f275b8f bellard
        case 0x12:
398 2f275b8f bellard
            DPRINTF("Message Accepted (%2.2x)\n", val);
399 0fc5c15a pbrook
            write_response(s);
400 2f275b8f bellard
            s->rregs[5] = INTR_DC;
401 2f275b8f bellard
            s->rregs[6] = 0;
402 6f7e9aec bellard
            break;
403 6f7e9aec bellard
        case 0x1a:
404 2f275b8f bellard
            DPRINTF("Set ATN (%2.2x)\n", val);
405 6f7e9aec bellard
            break;
406 6f7e9aec bellard
        case 0x42:
407 9f149aa9 pbrook
            DPRINTF("Set ATN (%2.2x)\n", val);
408 2f275b8f bellard
            handle_satn(s);
409 2f275b8f bellard
            break;
410 2f275b8f bellard
        case 0x43:
411 2f275b8f bellard
            DPRINTF("Set ATN & stop (%2.2x)\n", val);
412 9f149aa9 pbrook
            handle_satn_stop(s);
413 2f275b8f bellard
            break;
414 2f275b8f bellard
        default:
415 4f6200f0 bellard
            DPRINTF("Unhandled ESP command (%2.2x)\n", val);
416 6f7e9aec bellard
            break;
417 6f7e9aec bellard
        }
418 6f7e9aec bellard
        break;
419 6f7e9aec bellard
    case 4 ... 7:
420 6f7e9aec bellard
        break;
421 4f6200f0 bellard
    case 8:
422 4f6200f0 bellard
        s->rregs[saddr] = val;
423 4f6200f0 bellard
        break;
424 4f6200f0 bellard
    case 9 ... 10:
425 4f6200f0 bellard
        break;
426 9e61bde5 bellard
    case 11:
427 9e61bde5 bellard
        s->rregs[saddr] = val & 0x15;
428 9e61bde5 bellard
        break;
429 9e61bde5 bellard
    case 12 ... 15:
430 4f6200f0 bellard
        s->rregs[saddr] = val;
431 4f6200f0 bellard
        break;
432 6f7e9aec bellard
    default:
433 6f7e9aec bellard
        break;
434 6f7e9aec bellard
    }
435 2f275b8f bellard
    s->wregs[saddr] = val;
436 6f7e9aec bellard
}
437 6f7e9aec bellard
438 6f7e9aec bellard
static CPUReadMemoryFunc *esp_mem_read[3] = {
439 6f7e9aec bellard
    esp_mem_readb,
440 6f7e9aec bellard
    esp_mem_readb,
441 6f7e9aec bellard
    esp_mem_readb,
442 6f7e9aec bellard
};
443 6f7e9aec bellard
444 6f7e9aec bellard
static CPUWriteMemoryFunc *esp_mem_write[3] = {
445 6f7e9aec bellard
    esp_mem_writeb,
446 6f7e9aec bellard
    esp_mem_writeb,
447 6f7e9aec bellard
    esp_mem_writeb,
448 6f7e9aec bellard
};
449 6f7e9aec bellard
450 6f7e9aec bellard
static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
451 6f7e9aec bellard
{
452 6f7e9aec bellard
    ESPState *s = opaque;
453 6f7e9aec bellard
    uint32_t saddr;
454 6f7e9aec bellard
455 6f7e9aec bellard
    saddr = (addr & ESPDMA_MAXADDR) >> 2;
456 4f6200f0 bellard
    DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
457 4f6200f0 bellard
458 6f7e9aec bellard
    return s->espdmaregs[saddr];
459 6f7e9aec bellard
}
460 6f7e9aec bellard
461 6f7e9aec bellard
static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
462 6f7e9aec bellard
{
463 6f7e9aec bellard
    ESPState *s = opaque;
464 6f7e9aec bellard
    uint32_t saddr;
465 6f7e9aec bellard
466 6f7e9aec bellard
    saddr = (addr & ESPDMA_MAXADDR) >> 2;
467 4f6200f0 bellard
    DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
468 2f275b8f bellard
    switch (saddr) {
469 2f275b8f bellard
    case 0:
470 9e61bde5 bellard
        if (!(val & DMA_INTREN))
471 2f275b8f bellard
            pic_set_irq(s->irq, 0);
472 4f6200f0 bellard
        if (val & 0x80) {
473 4f6200f0 bellard
            esp_reset(s);
474 4f6200f0 bellard
        } else if (val & 0x40) {
475 4f6200f0 bellard
            val &= ~0x40;
476 4f6200f0 bellard
        } else if (val == 0)
477 4f6200f0 bellard
            val = 0x40;
478 4f6200f0 bellard
        val &= 0x0fffffff;
479 4f6200f0 bellard
        val |= DMA_VER;
480 2f275b8f bellard
        break;
481 4f6200f0 bellard
    case 1:
482 e4d165c2 pbrook
        s->espdmaregs[0] |= DMA_LOADED;
483 4f6200f0 bellard
        break;
484 2f275b8f bellard
    default:
485 2f275b8f bellard
        break;
486 2f275b8f bellard
    }
487 6f7e9aec bellard
    s->espdmaregs[saddr] = val;
488 6f7e9aec bellard
}
489 6f7e9aec bellard
490 6f7e9aec bellard
static CPUReadMemoryFunc *espdma_mem_read[3] = {
491 6f7e9aec bellard
    espdma_mem_readl,
492 6f7e9aec bellard
    espdma_mem_readl,
493 6f7e9aec bellard
    espdma_mem_readl,
494 6f7e9aec bellard
};
495 6f7e9aec bellard
496 6f7e9aec bellard
static CPUWriteMemoryFunc *espdma_mem_write[3] = {
497 6f7e9aec bellard
    espdma_mem_writel,
498 6f7e9aec bellard
    espdma_mem_writel,
499 6f7e9aec bellard
    espdma_mem_writel,
500 6f7e9aec bellard
};
501 6f7e9aec bellard
502 6f7e9aec bellard
static void esp_save(QEMUFile *f, void *opaque)
503 6f7e9aec bellard
{
504 6f7e9aec bellard
    ESPState *s = opaque;
505 2f275b8f bellard
    unsigned int i;
506 2f275b8f bellard
507 2f275b8f bellard
    qemu_put_buffer(f, s->rregs, ESP_MAXREG);
508 2f275b8f bellard
    qemu_put_buffer(f, s->wregs, ESP_MAXREG);
509 2f275b8f bellard
    qemu_put_be32s(f, &s->irq);
510 2f275b8f bellard
    for (i = 0; i < ESPDMA_REGS; i++)
511 2f275b8f bellard
        qemu_put_be32s(f, &s->espdmaregs[i]);
512 4f6200f0 bellard
    qemu_put_be32s(f, &s->ti_size);
513 4f6200f0 bellard
    qemu_put_be32s(f, &s->ti_rptr);
514 4f6200f0 bellard
    qemu_put_be32s(f, &s->ti_wptr);
515 4f6200f0 bellard
    qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
516 4f6200f0 bellard
    qemu_put_be32s(f, &s->dma);
517 6f7e9aec bellard
}
518 6f7e9aec bellard
519 6f7e9aec bellard
static int esp_load(QEMUFile *f, void *opaque, int version_id)
520 6f7e9aec bellard
{
521 6f7e9aec bellard
    ESPState *s = opaque;
522 2f275b8f bellard
    unsigned int i;
523 6f7e9aec bellard
    
524 6f7e9aec bellard
    if (version_id != 1)
525 6f7e9aec bellard
        return -EINVAL;
526 6f7e9aec bellard
527 2f275b8f bellard
    qemu_get_buffer(f, s->rregs, ESP_MAXREG);
528 2f275b8f bellard
    qemu_get_buffer(f, s->wregs, ESP_MAXREG);
529 2f275b8f bellard
    qemu_get_be32s(f, &s->irq);
530 2f275b8f bellard
    for (i = 0; i < ESPDMA_REGS; i++)
531 2f275b8f bellard
        qemu_get_be32s(f, &s->espdmaregs[i]);
532 4f6200f0 bellard
    qemu_get_be32s(f, &s->ti_size);
533 4f6200f0 bellard
    qemu_get_be32s(f, &s->ti_rptr);
534 4f6200f0 bellard
    qemu_get_be32s(f, &s->ti_wptr);
535 4f6200f0 bellard
    qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
536 4f6200f0 bellard
    qemu_get_be32s(f, &s->dma);
537 2f275b8f bellard
538 6f7e9aec bellard
    return 0;
539 6f7e9aec bellard
}
540 6f7e9aec bellard
541 6f7e9aec bellard
void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
542 6f7e9aec bellard
{
543 6f7e9aec bellard
    ESPState *s;
544 6f7e9aec bellard
    int esp_io_memory, espdma_io_memory;
545 2e5d83bb pbrook
    int i;
546 6f7e9aec bellard
547 6f7e9aec bellard
    s = qemu_mallocz(sizeof(ESPState));
548 6f7e9aec bellard
    if (!s)
549 6f7e9aec bellard
        return;
550 6f7e9aec bellard
551 6f7e9aec bellard
    s->bd = bd;
552 6f7e9aec bellard
    s->irq = irq;
553 6f7e9aec bellard
554 6f7e9aec bellard
    esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
555 6f7e9aec bellard
    cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
556 6f7e9aec bellard
557 6f7e9aec bellard
    espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
558 6f7e9aec bellard
    cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
559 6f7e9aec bellard
560 6f7e9aec bellard
    esp_reset(s);
561 6f7e9aec bellard
562 6f7e9aec bellard
    register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
563 6f7e9aec bellard
    qemu_register_reset(esp_reset, s);
564 2e5d83bb pbrook
    for (i = 0; i < MAX_DISKS; i++) {
565 2e5d83bb pbrook
        if (bs_table[i]) {
566 2e5d83bb pbrook
            s->scsi_dev[i] =
567 2e5d83bb pbrook
                scsi_disk_init(bs_table[i], esp_command_complete, s);
568 2e5d83bb pbrook
        }
569 2e5d83bb pbrook
    }
570 6f7e9aec bellard
}