Statistics
| Branch: | Revision:

root / hw / esp.c @ ff753bb9

History | View | Annotate | Download (19.8 kB)

1 6f7e9aec bellard
/*
2 67e999be bellard
 * QEMU ESP/NCR53C9x emulation
3 5fafdf24 ths
 *
4 4e9aec74 pbrook
 * Copyright (c) 2005-2006 Fabrice Bellard
5 5fafdf24 ths
 *
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 5d20fa6b blueswir1
25 cfb9de9c Paul Brook
#include "sysbus.h"
26 43b443b6 Gerd Hoffmann
#include "scsi.h"
27 1cd3af54 Gerd Hoffmann
#include "esp.h"
28 6f7e9aec bellard
29 6f7e9aec bellard
/* debug ESP card */
30 2f275b8f bellard
//#define DEBUG_ESP
31 6f7e9aec bellard
32 67e999be bellard
/*
33 5ad6bb97 blueswir1
 * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
34 5ad6bb97 blueswir1
 * also produced as NCR89C100. See
35 67e999be bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
36 67e999be bellard
 * and
37 67e999be bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
38 67e999be bellard
 */
39 67e999be bellard
40 6f7e9aec bellard
#ifdef DEBUG_ESP
41 001faf32 Blue Swirl
#define DPRINTF(fmt, ...)                                       \
42 001faf32 Blue Swirl
    do { printf("ESP: " fmt , ## __VA_ARGS__); } while (0)
43 6f7e9aec bellard
#else
44 001faf32 Blue Swirl
#define DPRINTF(fmt, ...) do {} while (0)
45 6f7e9aec bellard
#endif
46 6f7e9aec bellard
47 001faf32 Blue Swirl
#define ESP_ERROR(fmt, ...)                                             \
48 001faf32 Blue Swirl
    do { printf("ESP ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
49 8dea1dd4 blueswir1
50 5aca8c3b blueswir1
#define ESP_REGS 16
51 8dea1dd4 blueswir1
#define TI_BUFSZ 16
52 67e999be bellard
53 4e9aec74 pbrook
typedef struct ESPState ESPState;
54 6f7e9aec bellard
55 4e9aec74 pbrook
struct ESPState {
56 cfb9de9c Paul Brook
    SysBusDevice busdev;
57 5d20fa6b blueswir1
    uint32_t it_shift;
58 70c0de96 blueswir1
    qemu_irq irq;
59 5aca8c3b blueswir1
    uint8_t rregs[ESP_REGS];
60 5aca8c3b blueswir1
    uint8_t wregs[ESP_REGS];
61 67e999be bellard
    int32_t ti_size;
62 4f6200f0 bellard
    uint32_t ti_rptr, ti_wptr;
63 4f6200f0 bellard
    uint8_t ti_buf[TI_BUFSZ];
64 22548760 blueswir1
    uint32_t sense;
65 22548760 blueswir1
    uint32_t dma;
66 ca9c39fa Gerd Hoffmann
    SCSIBus bus;
67 2e5d83bb pbrook
    SCSIDevice *current_dev;
68 9f149aa9 pbrook
    uint8_t cmdbuf[TI_BUFSZ];
69 22548760 blueswir1
    uint32_t cmdlen;
70 22548760 blueswir1
    uint32_t do_cmd;
71 4d611c9a pbrook
72 6787f5fa pbrook
    /* The amount of data left in the current DMA transfer.  */
73 4d611c9a pbrook
    uint32_t dma_left;
74 6787f5fa pbrook
    /* The size of the current DMA transfer.  Zero if no transfer is in
75 6787f5fa pbrook
       progress.  */
76 6787f5fa pbrook
    uint32_t dma_counter;
77 a917d384 pbrook
    uint8_t *async_buf;
78 4d611c9a pbrook
    uint32_t async_len;
79 8b17de88 blueswir1
80 ff9868ec Blue Swirl
    ESPDMAMemoryReadWriteFunc dma_memory_read;
81 ff9868ec Blue Swirl
    ESPDMAMemoryReadWriteFunc dma_memory_write;
82 67e999be bellard
    void *dma_opaque;
83 73d74342 Blue Swirl
    int dma_enabled;
84 73d74342 Blue Swirl
    void (*dma_cb)(ESPState *s);
85 4e9aec74 pbrook
};
86 6f7e9aec bellard
87 5ad6bb97 blueswir1
#define ESP_TCLO   0x0
88 5ad6bb97 blueswir1
#define ESP_TCMID  0x1
89 5ad6bb97 blueswir1
#define ESP_FIFO   0x2
90 5ad6bb97 blueswir1
#define ESP_CMD    0x3
91 5ad6bb97 blueswir1
#define ESP_RSTAT  0x4
92 5ad6bb97 blueswir1
#define ESP_WBUSID 0x4
93 5ad6bb97 blueswir1
#define ESP_RINTR  0x5
94 5ad6bb97 blueswir1
#define ESP_WSEL   0x5
95 5ad6bb97 blueswir1
#define ESP_RSEQ   0x6
96 5ad6bb97 blueswir1
#define ESP_WSYNTP 0x6
97 5ad6bb97 blueswir1
#define ESP_RFLAGS 0x7
98 5ad6bb97 blueswir1
#define ESP_WSYNO  0x7
99 5ad6bb97 blueswir1
#define ESP_CFG1   0x8
100 5ad6bb97 blueswir1
#define ESP_RRES1  0x9
101 5ad6bb97 blueswir1
#define ESP_WCCF   0x9
102 5ad6bb97 blueswir1
#define ESP_RRES2  0xa
103 5ad6bb97 blueswir1
#define ESP_WTEST  0xa
104 5ad6bb97 blueswir1
#define ESP_CFG2   0xb
105 5ad6bb97 blueswir1
#define ESP_CFG3   0xc
106 5ad6bb97 blueswir1
#define ESP_RES3   0xd
107 5ad6bb97 blueswir1
#define ESP_TCHI   0xe
108 5ad6bb97 blueswir1
#define ESP_RES4   0xf
109 5ad6bb97 blueswir1
110 5ad6bb97 blueswir1
#define CMD_DMA 0x80
111 5ad6bb97 blueswir1
#define CMD_CMD 0x7f
112 5ad6bb97 blueswir1
113 5ad6bb97 blueswir1
#define CMD_NOP      0x00
114 5ad6bb97 blueswir1
#define CMD_FLUSH    0x01
115 5ad6bb97 blueswir1
#define CMD_RESET    0x02
116 5ad6bb97 blueswir1
#define CMD_BUSRESET 0x03
117 5ad6bb97 blueswir1
#define CMD_TI       0x10
118 5ad6bb97 blueswir1
#define CMD_ICCS     0x11
119 5ad6bb97 blueswir1
#define CMD_MSGACC   0x12
120 0fd0eb21 Blue Swirl
#define CMD_PAD      0x18
121 5ad6bb97 blueswir1
#define CMD_SATN     0x1a
122 5e1e0a3b Blue Swirl
#define CMD_SEL      0x41
123 5ad6bb97 blueswir1
#define CMD_SELATN   0x42
124 5ad6bb97 blueswir1
#define CMD_SELATNS  0x43
125 5ad6bb97 blueswir1
#define CMD_ENSEL    0x44
126 5ad6bb97 blueswir1
127 2f275b8f bellard
#define STAT_DO 0x00
128 2f275b8f bellard
#define STAT_DI 0x01
129 2f275b8f bellard
#define STAT_CD 0x02
130 2f275b8f bellard
#define STAT_ST 0x03
131 8dea1dd4 blueswir1
#define STAT_MO 0x06
132 8dea1dd4 blueswir1
#define STAT_MI 0x07
133 5ad6bb97 blueswir1
#define STAT_PIO_MASK 0x06
134 2f275b8f bellard
135 2f275b8f bellard
#define STAT_TC 0x10
136 4d611c9a pbrook
#define STAT_PE 0x20
137 4d611c9a pbrook
#define STAT_GE 0x40
138 c73f96fd blueswir1
#define STAT_INT 0x80
139 2f275b8f bellard
140 8dea1dd4 blueswir1
#define BUSID_DID 0x07
141 8dea1dd4 blueswir1
142 2f275b8f bellard
#define INTR_FC 0x08
143 2f275b8f bellard
#define INTR_BS 0x10
144 2f275b8f bellard
#define INTR_DC 0x20
145 9e61bde5 bellard
#define INTR_RST 0x80
146 2f275b8f bellard
147 2f275b8f bellard
#define SEQ_0 0x0
148 2f275b8f bellard
#define SEQ_CD 0x4
149 2f275b8f bellard
150 5ad6bb97 blueswir1
#define CFG1_RESREPT 0x40
151 5ad6bb97 blueswir1
152 5ad6bb97 blueswir1
#define TCHI_FAS100A 0x4
153 5ad6bb97 blueswir1
154 c73f96fd blueswir1
static void esp_raise_irq(ESPState *s)
155 c73f96fd blueswir1
{
156 c73f96fd blueswir1
    if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
157 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] |= STAT_INT;
158 c73f96fd blueswir1
        qemu_irq_raise(s->irq);
159 dca47edd Blue Swirl
        DPRINTF("Raise IRQ\n");
160 c73f96fd blueswir1
    }
161 c73f96fd blueswir1
}
162 c73f96fd blueswir1
163 c73f96fd blueswir1
static void esp_lower_irq(ESPState *s)
164 c73f96fd blueswir1
{
165 c73f96fd blueswir1
    if (s->rregs[ESP_RSTAT] & STAT_INT) {
166 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] &= ~STAT_INT;
167 c73f96fd blueswir1
        qemu_irq_lower(s->irq);
168 dca47edd Blue Swirl
        DPRINTF("Lower IRQ\n");
169 c73f96fd blueswir1
    }
170 c73f96fd blueswir1
}
171 c73f96fd blueswir1
172 73d74342 Blue Swirl
static void esp_dma_enable(void *opaque, int irq, int level)
173 73d74342 Blue Swirl
{
174 73d74342 Blue Swirl
    DeviceState *d = opaque;
175 73d74342 Blue Swirl
    ESPState *s = container_of(d, ESPState, busdev.qdev);
176 73d74342 Blue Swirl
177 73d74342 Blue Swirl
    if (level) {
178 73d74342 Blue Swirl
        s->dma_enabled = 1;
179 73d74342 Blue Swirl
        DPRINTF("Raise enable\n");
180 73d74342 Blue Swirl
        if (s->dma_cb) {
181 73d74342 Blue Swirl
            s->dma_cb(s);
182 73d74342 Blue Swirl
            s->dma_cb = NULL;
183 73d74342 Blue Swirl
        }
184 73d74342 Blue Swirl
    } else {
185 73d74342 Blue Swirl
        DPRINTF("Lower enable\n");
186 73d74342 Blue Swirl
        s->dma_enabled = 0;
187 73d74342 Blue Swirl
    }
188 73d74342 Blue Swirl
}
189 73d74342 Blue Swirl
190 22548760 blueswir1
static uint32_t get_cmd(ESPState *s, uint8_t *buf)
191 2f275b8f bellard
{
192 a917d384 pbrook
    uint32_t dmalen;
193 2f275b8f bellard
    int target;
194 2f275b8f bellard
195 8dea1dd4 blueswir1
    target = s->wregs[ESP_WBUSID] & BUSID_DID;
196 4f6200f0 bellard
    if (s->dma) {
197 fc4d65da blueswir1
        dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
198 8b17de88 blueswir1
        s->dma_memory_read(s->dma_opaque, buf, dmalen);
199 4f6200f0 bellard
    } else {
200 fc4d65da blueswir1
        dmalen = s->ti_size;
201 fc4d65da blueswir1
        memcpy(buf, s->ti_buf, dmalen);
202 f930d07e blueswir1
        buf[0] = 0;
203 4f6200f0 bellard
    }
204 fc4d65da blueswir1
    DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
205 2e5d83bb pbrook
206 2f275b8f bellard
    s->ti_size = 0;
207 4f6200f0 bellard
    s->ti_rptr = 0;
208 4f6200f0 bellard
    s->ti_wptr = 0;
209 2f275b8f bellard
210 a917d384 pbrook
    if (s->current_dev) {
211 a917d384 pbrook
        /* Started a new command before the old one finished.  Cancel it.  */
212 d52affa7 Gerd Hoffmann
        s->current_dev->info->cancel_io(s->current_dev, 0);
213 a917d384 pbrook
        s->async_len = 0;
214 a917d384 pbrook
    }
215 a917d384 pbrook
216 ca9c39fa Gerd Hoffmann
    if (target >= ESP_MAX_DEVS || !s->bus.devs[target]) {
217 2e5d83bb pbrook
        // No such drive
218 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] = 0;
219 5ad6bb97 blueswir1
        s->rregs[ESP_RINTR] = INTR_DC;
220 5ad6bb97 blueswir1
        s->rregs[ESP_RSEQ] = SEQ_0;
221 c73f96fd blueswir1
        esp_raise_irq(s);
222 f930d07e blueswir1
        return 0;
223 2f275b8f bellard
    }
224 ca9c39fa Gerd Hoffmann
    s->current_dev = s->bus.devs[target];
225 9f149aa9 pbrook
    return dmalen;
226 9f149aa9 pbrook
}
227 9f149aa9 pbrook
228 f2818f22 Artyom Tarasenko
static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
229 9f149aa9 pbrook
{
230 9f149aa9 pbrook
    int32_t datalen;
231 9f149aa9 pbrook
    int lun;
232 9f149aa9 pbrook
233 f2818f22 Artyom Tarasenko
    DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
234 f2818f22 Artyom Tarasenko
    lun = busid & 7;
235 d52affa7 Gerd Hoffmann
    datalen = s->current_dev->info->send_command(s->current_dev, 0, buf, lun);
236 67e999be bellard
    s->ti_size = datalen;
237 67e999be bellard
    if (datalen != 0) {
238 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] = STAT_TC;
239 a917d384 pbrook
        s->dma_left = 0;
240 6787f5fa pbrook
        s->dma_counter = 0;
241 2e5d83bb pbrook
        if (datalen > 0) {
242 5ad6bb97 blueswir1
            s->rregs[ESP_RSTAT] |= STAT_DI;
243 d52affa7 Gerd Hoffmann
            s->current_dev->info->read_data(s->current_dev, 0);
244 2e5d83bb pbrook
        } else {
245 5ad6bb97 blueswir1
            s->rregs[ESP_RSTAT] |= STAT_DO;
246 d52affa7 Gerd Hoffmann
            s->current_dev->info->write_data(s->current_dev, 0);
247 b9788fc4 bellard
        }
248 2f275b8f bellard
    }
249 5ad6bb97 blueswir1
    s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
250 5ad6bb97 blueswir1
    s->rregs[ESP_RSEQ] = SEQ_CD;
251 c73f96fd blueswir1
    esp_raise_irq(s);
252 2f275b8f bellard
}
253 2f275b8f bellard
254 f2818f22 Artyom Tarasenko
static void do_cmd(ESPState *s, uint8_t *buf)
255 f2818f22 Artyom Tarasenko
{
256 f2818f22 Artyom Tarasenko
    uint8_t busid = buf[0];
257 f2818f22 Artyom Tarasenko
258 f2818f22 Artyom Tarasenko
    do_busid_cmd(s, &buf[1], busid);
259 f2818f22 Artyom Tarasenko
}
260 f2818f22 Artyom Tarasenko
261 9f149aa9 pbrook
static void handle_satn(ESPState *s)
262 9f149aa9 pbrook
{
263 9f149aa9 pbrook
    uint8_t buf[32];
264 9f149aa9 pbrook
    int len;
265 9f149aa9 pbrook
266 73d74342 Blue Swirl
    if (!s->dma_enabled) {
267 73d74342 Blue Swirl
        s->dma_cb = handle_satn;
268 73d74342 Blue Swirl
        return;
269 73d74342 Blue Swirl
    }
270 9f149aa9 pbrook
    len = get_cmd(s, buf);
271 9f149aa9 pbrook
    if (len)
272 9f149aa9 pbrook
        do_cmd(s, buf);
273 9f149aa9 pbrook
}
274 9f149aa9 pbrook
275 f2818f22 Artyom Tarasenko
static void handle_s_without_atn(ESPState *s)
276 f2818f22 Artyom Tarasenko
{
277 f2818f22 Artyom Tarasenko
    uint8_t buf[32];
278 f2818f22 Artyom Tarasenko
    int len;
279 f2818f22 Artyom Tarasenko
280 73d74342 Blue Swirl
    if (!s->dma_enabled) {
281 73d74342 Blue Swirl
        s->dma_cb = handle_s_without_atn;
282 73d74342 Blue Swirl
        return;
283 73d74342 Blue Swirl
    }
284 f2818f22 Artyom Tarasenko
    len = get_cmd(s, buf);
285 f2818f22 Artyom Tarasenko
    if (len) {
286 f2818f22 Artyom Tarasenko
        do_busid_cmd(s, buf, 0);
287 f2818f22 Artyom Tarasenko
    }
288 f2818f22 Artyom Tarasenko
}
289 f2818f22 Artyom Tarasenko
290 9f149aa9 pbrook
static void handle_satn_stop(ESPState *s)
291 9f149aa9 pbrook
{
292 73d74342 Blue Swirl
    if (!s->dma_enabled) {
293 73d74342 Blue Swirl
        s->dma_cb = handle_satn_stop;
294 73d74342 Blue Swirl
        return;
295 73d74342 Blue Swirl
    }
296 9f149aa9 pbrook
    s->cmdlen = get_cmd(s, s->cmdbuf);
297 9f149aa9 pbrook
    if (s->cmdlen) {
298 9f149aa9 pbrook
        DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
299 9f149aa9 pbrook
        s->do_cmd = 1;
300 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
301 5ad6bb97 blueswir1
        s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
302 5ad6bb97 blueswir1
        s->rregs[ESP_RSEQ] = SEQ_CD;
303 c73f96fd blueswir1
        esp_raise_irq(s);
304 9f149aa9 pbrook
    }
305 9f149aa9 pbrook
}
306 9f149aa9 pbrook
307 0fc5c15a pbrook
static void write_response(ESPState *s)
308 2f275b8f bellard
{
309 0fc5c15a pbrook
    DPRINTF("Transfer status (sense=%d)\n", s->sense);
310 0fc5c15a pbrook
    s->ti_buf[0] = s->sense;
311 0fc5c15a pbrook
    s->ti_buf[1] = 0;
312 4f6200f0 bellard
    if (s->dma) {
313 8b17de88 blueswir1
        s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
314 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
315 5ad6bb97 blueswir1
        s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
316 5ad6bb97 blueswir1
        s->rregs[ESP_RSEQ] = SEQ_CD;
317 4f6200f0 bellard
    } else {
318 f930d07e blueswir1
        s->ti_size = 2;
319 f930d07e blueswir1
        s->ti_rptr = 0;
320 f930d07e blueswir1
        s->ti_wptr = 0;
321 5ad6bb97 blueswir1
        s->rregs[ESP_RFLAGS] = 2;
322 4f6200f0 bellard
    }
323 c73f96fd blueswir1
    esp_raise_irq(s);
324 2f275b8f bellard
}
325 4f6200f0 bellard
326 a917d384 pbrook
static void esp_dma_done(ESPState *s)
327 a917d384 pbrook
{
328 c73f96fd blueswir1
    s->rregs[ESP_RSTAT] |= STAT_TC;
329 5ad6bb97 blueswir1
    s->rregs[ESP_RINTR] = INTR_BS;
330 5ad6bb97 blueswir1
    s->rregs[ESP_RSEQ] = 0;
331 5ad6bb97 blueswir1
    s->rregs[ESP_RFLAGS] = 0;
332 5ad6bb97 blueswir1
    s->rregs[ESP_TCLO] = 0;
333 5ad6bb97 blueswir1
    s->rregs[ESP_TCMID] = 0;
334 c73f96fd blueswir1
    esp_raise_irq(s);
335 a917d384 pbrook
}
336 a917d384 pbrook
337 4d611c9a pbrook
static void esp_do_dma(ESPState *s)
338 4d611c9a pbrook
{
339 67e999be bellard
    uint32_t len;
340 4d611c9a pbrook
    int to_device;
341 a917d384 pbrook
342 67e999be bellard
    to_device = (s->ti_size < 0);
343 a917d384 pbrook
    len = s->dma_left;
344 4d611c9a pbrook
    if (s->do_cmd) {
345 4d611c9a pbrook
        DPRINTF("command len %d + %d\n", s->cmdlen, len);
346 8b17de88 blueswir1
        s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
347 4d611c9a pbrook
        s->ti_size = 0;
348 4d611c9a pbrook
        s->cmdlen = 0;
349 4d611c9a pbrook
        s->do_cmd = 0;
350 4d611c9a pbrook
        do_cmd(s, s->cmdbuf);
351 4d611c9a pbrook
        return;
352 a917d384 pbrook
    }
353 a917d384 pbrook
    if (s->async_len == 0) {
354 a917d384 pbrook
        /* Defer until data is available.  */
355 a917d384 pbrook
        return;
356 a917d384 pbrook
    }
357 a917d384 pbrook
    if (len > s->async_len) {
358 a917d384 pbrook
        len = s->async_len;
359 a917d384 pbrook
    }
360 a917d384 pbrook
    if (to_device) {
361 8b17de88 blueswir1
        s->dma_memory_read(s->dma_opaque, s->async_buf, len);
362 4d611c9a pbrook
    } else {
363 8b17de88 blueswir1
        s->dma_memory_write(s->dma_opaque, s->async_buf, len);
364 a917d384 pbrook
    }
365 a917d384 pbrook
    s->dma_left -= len;
366 a917d384 pbrook
    s->async_buf += len;
367 a917d384 pbrook
    s->async_len -= len;
368 6787f5fa pbrook
    if (to_device)
369 6787f5fa pbrook
        s->ti_size += len;
370 6787f5fa pbrook
    else
371 6787f5fa pbrook
        s->ti_size -= len;
372 a917d384 pbrook
    if (s->async_len == 0) {
373 4d611c9a pbrook
        if (to_device) {
374 67e999be bellard
            // ti_size is negative
375 d52affa7 Gerd Hoffmann
            s->current_dev->info->write_data(s->current_dev, 0);
376 4d611c9a pbrook
        } else {
377 d52affa7 Gerd Hoffmann
            s->current_dev->info->read_data(s->current_dev, 0);
378 6787f5fa pbrook
            /* If there is still data to be read from the device then
379 8dea1dd4 blueswir1
               complete the DMA operation immediately.  Otherwise defer
380 6787f5fa pbrook
               until the scsi layer has completed.  */
381 6787f5fa pbrook
            if (s->dma_left == 0 && s->ti_size > 0) {
382 6787f5fa pbrook
                esp_dma_done(s);
383 6787f5fa pbrook
            }
384 4d611c9a pbrook
        }
385 6787f5fa pbrook
    } else {
386 6787f5fa pbrook
        /* Partially filled a scsi buffer. Complete immediately.  */
387 a917d384 pbrook
        esp_dma_done(s);
388 a917d384 pbrook
    }
389 4d611c9a pbrook
}
390 4d611c9a pbrook
391 d52affa7 Gerd Hoffmann
static void esp_command_complete(SCSIBus *bus, int reason, uint32_t tag,
392 a917d384 pbrook
                                 uint32_t arg)
393 2e5d83bb pbrook
{
394 d52affa7 Gerd Hoffmann
    ESPState *s = DO_UPCAST(ESPState, busdev.qdev, bus->qbus.parent);
395 2e5d83bb pbrook
396 4d611c9a pbrook
    if (reason == SCSI_REASON_DONE) {
397 4d611c9a pbrook
        DPRINTF("SCSI Command complete\n");
398 4d611c9a pbrook
        if (s->ti_size != 0)
399 4d611c9a pbrook
            DPRINTF("SCSI command completed unexpectedly\n");
400 4d611c9a pbrook
        s->ti_size = 0;
401 a917d384 pbrook
        s->dma_left = 0;
402 a917d384 pbrook
        s->async_len = 0;
403 a917d384 pbrook
        if (arg)
404 4d611c9a pbrook
            DPRINTF("Command failed\n");
405 a917d384 pbrook
        s->sense = arg;
406 5ad6bb97 blueswir1
        s->rregs[ESP_RSTAT] = STAT_ST;
407 a917d384 pbrook
        esp_dma_done(s);
408 a917d384 pbrook
        s->current_dev = NULL;
409 4d611c9a pbrook
    } else {
410 4d611c9a pbrook
        DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
411 a917d384 pbrook
        s->async_len = arg;
412 d52affa7 Gerd Hoffmann
        s->async_buf = s->current_dev->info->get_buf(s->current_dev, 0);
413 6787f5fa pbrook
        if (s->dma_left) {
414 a917d384 pbrook
            esp_do_dma(s);
415 6787f5fa pbrook
        } else if (s->dma_counter != 0 && s->ti_size <= 0) {
416 6787f5fa pbrook
            /* If this was the last part of a DMA transfer then the
417 6787f5fa pbrook
               completion interrupt is deferred to here.  */
418 6787f5fa pbrook
            esp_dma_done(s);
419 6787f5fa pbrook
        }
420 4d611c9a pbrook
    }
421 2e5d83bb pbrook
}
422 2e5d83bb pbrook
423 2f275b8f bellard
static void handle_ti(ESPState *s)
424 2f275b8f bellard
{
425 4d611c9a pbrook
    uint32_t dmalen, minlen;
426 2f275b8f bellard
427 5ad6bb97 blueswir1
    dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
428 db59203d pbrook
    if (dmalen==0) {
429 db59203d pbrook
      dmalen=0x10000;
430 db59203d pbrook
    }
431 6787f5fa pbrook
    s->dma_counter = dmalen;
432 db59203d pbrook
433 9f149aa9 pbrook
    if (s->do_cmd)
434 9f149aa9 pbrook
        minlen = (dmalen < 32) ? dmalen : 32;
435 67e999be bellard
    else if (s->ti_size < 0)
436 67e999be bellard
        minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
437 9f149aa9 pbrook
    else
438 9f149aa9 pbrook
        minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
439 db59203d pbrook
    DPRINTF("Transfer Information len %d\n", minlen);
440 4f6200f0 bellard
    if (s->dma) {
441 4d611c9a pbrook
        s->dma_left = minlen;
442 5ad6bb97 blueswir1
        s->rregs[ESP_RSTAT] &= ~STAT_TC;
443 4d611c9a pbrook
        esp_do_dma(s);
444 9f149aa9 pbrook
    } else if (s->do_cmd) {
445 9f149aa9 pbrook
        DPRINTF("command len %d\n", s->cmdlen);
446 9f149aa9 pbrook
        s->ti_size = 0;
447 9f149aa9 pbrook
        s->cmdlen = 0;
448 9f149aa9 pbrook
        s->do_cmd = 0;
449 9f149aa9 pbrook
        do_cmd(s, s->cmdbuf);
450 9f149aa9 pbrook
        return;
451 9f149aa9 pbrook
    }
452 2f275b8f bellard
}
453 2f275b8f bellard
454 85948643 Blue Swirl
static void esp_hard_reset(DeviceState *d)
455 6f7e9aec bellard
{
456 63235df8 Blue Swirl
    ESPState *s = container_of(d, ESPState, busdev.qdev);
457 67e999be bellard
458 5aca8c3b blueswir1
    memset(s->rregs, 0, ESP_REGS);
459 5aca8c3b blueswir1
    memset(s->wregs, 0, ESP_REGS);
460 5ad6bb97 blueswir1
    s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
461 4e9aec74 pbrook
    s->ti_size = 0;
462 4e9aec74 pbrook
    s->ti_rptr = 0;
463 4e9aec74 pbrook
    s->ti_wptr = 0;
464 4e9aec74 pbrook
    s->dma = 0;
465 9f149aa9 pbrook
    s->do_cmd = 0;
466 73d74342 Blue Swirl
    s->dma_cb = NULL;
467 8dea1dd4 blueswir1
468 8dea1dd4 blueswir1
    s->rregs[ESP_CFG1] = 7;
469 6f7e9aec bellard
}
470 6f7e9aec bellard
471 85948643 Blue Swirl
static void esp_soft_reset(DeviceState *d)
472 85948643 Blue Swirl
{
473 85948643 Blue Swirl
    ESPState *s = container_of(d, ESPState, busdev.qdev);
474 85948643 Blue Swirl
475 85948643 Blue Swirl
    qemu_irq_lower(s->irq);
476 85948643 Blue Swirl
    esp_hard_reset(d);
477 85948643 Blue Swirl
}
478 85948643 Blue Swirl
479 2d069bab blueswir1
static void parent_esp_reset(void *opaque, int irq, int level)
480 2d069bab blueswir1
{
481 85948643 Blue Swirl
    if (level) {
482 85948643 Blue Swirl
        esp_soft_reset(opaque);
483 85948643 Blue Swirl
    }
484 2d069bab blueswir1
}
485 2d069bab blueswir1
486 73d74342 Blue Swirl
static void esp_gpio_demux(void *opaque, int irq, int level)
487 73d74342 Blue Swirl
{
488 73d74342 Blue Swirl
    switch (irq) {
489 73d74342 Blue Swirl
    case 0:
490 73d74342 Blue Swirl
        parent_esp_reset(opaque, irq, level);
491 73d74342 Blue Swirl
        break;
492 73d74342 Blue Swirl
    case 1:
493 73d74342 Blue Swirl
        esp_dma_enable(opaque, irq, level);
494 73d74342 Blue Swirl
        break;
495 73d74342 Blue Swirl
    }
496 73d74342 Blue Swirl
}
497 73d74342 Blue Swirl
498 c227f099 Anthony Liguori
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
499 6f7e9aec bellard
{
500 6f7e9aec bellard
    ESPState *s = opaque;
501 2814df28 Blue Swirl
    uint32_t saddr, old_val;
502 6f7e9aec bellard
503 e64d7d59 blueswir1
    saddr = addr >> s->it_shift;
504 9e61bde5 bellard
    DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
505 6f7e9aec bellard
    switch (saddr) {
506 5ad6bb97 blueswir1
    case ESP_FIFO:
507 f930d07e blueswir1
        if (s->ti_size > 0) {
508 f930d07e blueswir1
            s->ti_size--;
509 5ad6bb97 blueswir1
            if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
510 8dea1dd4 blueswir1
                /* Data out.  */
511 8dea1dd4 blueswir1
                ESP_ERROR("PIO data read not implemented\n");
512 5ad6bb97 blueswir1
                s->rregs[ESP_FIFO] = 0;
513 2e5d83bb pbrook
            } else {
514 5ad6bb97 blueswir1
                s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
515 2e5d83bb pbrook
            }
516 c73f96fd blueswir1
            esp_raise_irq(s);
517 f930d07e blueswir1
        }
518 f930d07e blueswir1
        if (s->ti_size == 0) {
519 4f6200f0 bellard
            s->ti_rptr = 0;
520 4f6200f0 bellard
            s->ti_wptr = 0;
521 4f6200f0 bellard
        }
522 f930d07e blueswir1
        break;
523 5ad6bb97 blueswir1
    case ESP_RINTR:
524 2814df28 Blue Swirl
        /* Clear sequence step, interrupt register and all status bits
525 2814df28 Blue Swirl
           except TC */
526 2814df28 Blue Swirl
        old_val = s->rregs[ESP_RINTR];
527 2814df28 Blue Swirl
        s->rregs[ESP_RINTR] = 0;
528 2814df28 Blue Swirl
        s->rregs[ESP_RSTAT] &= ~STAT_TC;
529 2814df28 Blue Swirl
        s->rregs[ESP_RSEQ] = SEQ_CD;
530 c73f96fd blueswir1
        esp_lower_irq(s);
531 2814df28 Blue Swirl
532 2814df28 Blue Swirl
        return old_val;
533 6f7e9aec bellard
    default:
534 f930d07e blueswir1
        break;
535 6f7e9aec bellard
    }
536 2f275b8f bellard
    return s->rregs[saddr];
537 6f7e9aec bellard
}
538 6f7e9aec bellard
539 c227f099 Anthony Liguori
static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
540 6f7e9aec bellard
{
541 6f7e9aec bellard
    ESPState *s = opaque;
542 6f7e9aec bellard
    uint32_t saddr;
543 6f7e9aec bellard
544 e64d7d59 blueswir1
    saddr = addr >> s->it_shift;
545 5ad6bb97 blueswir1
    DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],
546 5ad6bb97 blueswir1
            val);
547 6f7e9aec bellard
    switch (saddr) {
548 5ad6bb97 blueswir1
    case ESP_TCLO:
549 5ad6bb97 blueswir1
    case ESP_TCMID:
550 5ad6bb97 blueswir1
        s->rregs[ESP_RSTAT] &= ~STAT_TC;
551 4f6200f0 bellard
        break;
552 5ad6bb97 blueswir1
    case ESP_FIFO:
553 9f149aa9 pbrook
        if (s->do_cmd) {
554 9f149aa9 pbrook
            s->cmdbuf[s->cmdlen++] = val & 0xff;
555 8dea1dd4 blueswir1
        } else if (s->ti_size == TI_BUFSZ - 1) {
556 8dea1dd4 blueswir1
            ESP_ERROR("fifo overrun\n");
557 2e5d83bb pbrook
        } else {
558 2e5d83bb pbrook
            s->ti_size++;
559 2e5d83bb pbrook
            s->ti_buf[s->ti_wptr++] = val & 0xff;
560 2e5d83bb pbrook
        }
561 f930d07e blueswir1
        break;
562 5ad6bb97 blueswir1
    case ESP_CMD:
563 4f6200f0 bellard
        s->rregs[saddr] = val;
564 5ad6bb97 blueswir1
        if (val & CMD_DMA) {
565 f930d07e blueswir1
            s->dma = 1;
566 6787f5fa pbrook
            /* Reload DMA counter.  */
567 5ad6bb97 blueswir1
            s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
568 5ad6bb97 blueswir1
            s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
569 f930d07e blueswir1
        } else {
570 f930d07e blueswir1
            s->dma = 0;
571 f930d07e blueswir1
        }
572 5ad6bb97 blueswir1
        switch(val & CMD_CMD) {
573 5ad6bb97 blueswir1
        case CMD_NOP:
574 f930d07e blueswir1
            DPRINTF("NOP (%2.2x)\n", val);
575 f930d07e blueswir1
            break;
576 5ad6bb97 blueswir1
        case CMD_FLUSH:
577 f930d07e blueswir1
            DPRINTF("Flush FIFO (%2.2x)\n", val);
578 9e61bde5 bellard
            //s->ti_size = 0;
579 5ad6bb97 blueswir1
            s->rregs[ESP_RINTR] = INTR_FC;
580 5ad6bb97 blueswir1
            s->rregs[ESP_RSEQ] = 0;
581 a214c598 blueswir1
            s->rregs[ESP_RFLAGS] = 0;
582 f930d07e blueswir1
            break;
583 5ad6bb97 blueswir1
        case CMD_RESET:
584 f930d07e blueswir1
            DPRINTF("Chip reset (%2.2x)\n", val);
585 85948643 Blue Swirl
            esp_soft_reset(&s->busdev.qdev);
586 f930d07e blueswir1
            break;
587 5ad6bb97 blueswir1
        case CMD_BUSRESET:
588 f930d07e blueswir1
            DPRINTF("Bus reset (%2.2x)\n", val);
589 5ad6bb97 blueswir1
            s->rregs[ESP_RINTR] = INTR_RST;
590 5ad6bb97 blueswir1
            if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
591 c73f96fd blueswir1
                esp_raise_irq(s);
592 9e61bde5 bellard
            }
593 f930d07e blueswir1
            break;
594 5ad6bb97 blueswir1
        case CMD_TI:
595 f930d07e blueswir1
            handle_ti(s);
596 f930d07e blueswir1
            break;
597 5ad6bb97 blueswir1
        case CMD_ICCS:
598 f930d07e blueswir1
            DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
599 f930d07e blueswir1
            write_response(s);
600 4bf5801d blueswir1
            s->rregs[ESP_RINTR] = INTR_FC;
601 4bf5801d blueswir1
            s->rregs[ESP_RSTAT] |= STAT_MI;
602 f930d07e blueswir1
            break;
603 5ad6bb97 blueswir1
        case CMD_MSGACC:
604 f930d07e blueswir1
            DPRINTF("Message Accepted (%2.2x)\n", val);
605 5ad6bb97 blueswir1
            s->rregs[ESP_RINTR] = INTR_DC;
606 5ad6bb97 blueswir1
            s->rregs[ESP_RSEQ] = 0;
607 4e2a68c1 Artyom Tarasenko
            s->rregs[ESP_RFLAGS] = 0;
608 4e2a68c1 Artyom Tarasenko
            esp_raise_irq(s);
609 f930d07e blueswir1
            break;
610 0fd0eb21 Blue Swirl
        case CMD_PAD:
611 0fd0eb21 Blue Swirl
            DPRINTF("Transfer padding (%2.2x)\n", val);
612 0fd0eb21 Blue Swirl
            s->rregs[ESP_RSTAT] = STAT_TC;
613 0fd0eb21 Blue Swirl
            s->rregs[ESP_RINTR] = INTR_FC;
614 0fd0eb21 Blue Swirl
            s->rregs[ESP_RSEQ] = 0;
615 0fd0eb21 Blue Swirl
            break;
616 5ad6bb97 blueswir1
        case CMD_SATN:
617 f930d07e blueswir1
            DPRINTF("Set ATN (%2.2x)\n", val);
618 f930d07e blueswir1
            break;
619 5e1e0a3b Blue Swirl
        case CMD_SEL:
620 5e1e0a3b Blue Swirl
            DPRINTF("Select without ATN (%2.2x)\n", val);
621 f2818f22 Artyom Tarasenko
            handle_s_without_atn(s);
622 5e1e0a3b Blue Swirl
            break;
623 5ad6bb97 blueswir1
        case CMD_SELATN:
624 5e1e0a3b Blue Swirl
            DPRINTF("Select with ATN (%2.2x)\n", val);
625 f930d07e blueswir1
            handle_satn(s);
626 f930d07e blueswir1
            break;
627 5ad6bb97 blueswir1
        case CMD_SELATNS:
628 5e1e0a3b Blue Swirl
            DPRINTF("Select with ATN & stop (%2.2x)\n", val);
629 f930d07e blueswir1
            handle_satn_stop(s);
630 f930d07e blueswir1
            break;
631 5ad6bb97 blueswir1
        case CMD_ENSEL:
632 74ec6048 blueswir1
            DPRINTF("Enable selection (%2.2x)\n", val);
633 e3926838 blueswir1
            s->rregs[ESP_RINTR] = 0;
634 74ec6048 blueswir1
            break;
635 f930d07e blueswir1
        default:
636 8dea1dd4 blueswir1
            ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
637 f930d07e blueswir1
            break;
638 f930d07e blueswir1
        }
639 f930d07e blueswir1
        break;
640 5ad6bb97 blueswir1
    case ESP_WBUSID ... ESP_WSYNO:
641 f930d07e blueswir1
        break;
642 5ad6bb97 blueswir1
    case ESP_CFG1:
643 4f6200f0 bellard
        s->rregs[saddr] = val;
644 4f6200f0 bellard
        break;
645 5ad6bb97 blueswir1
    case ESP_WCCF ... ESP_WTEST:
646 4f6200f0 bellard
        break;
647 b44c08fa blueswir1
    case ESP_CFG2 ... ESP_RES4:
648 4f6200f0 bellard
        s->rregs[saddr] = val;
649 4f6200f0 bellard
        break;
650 6f7e9aec bellard
    default:
651 8dea1dd4 blueswir1
        ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
652 8dea1dd4 blueswir1
        return;
653 6f7e9aec bellard
    }
654 2f275b8f bellard
    s->wregs[saddr] = val;
655 6f7e9aec bellard
}
656 6f7e9aec bellard
657 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const esp_mem_read[3] = {
658 6f7e9aec bellard
    esp_mem_readb,
659 7c560456 blueswir1
    NULL,
660 7c560456 blueswir1
    NULL,
661 6f7e9aec bellard
};
662 6f7e9aec bellard
663 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const esp_mem_write[3] = {
664 6f7e9aec bellard
    esp_mem_writeb,
665 7c560456 blueswir1
    NULL,
666 daa41b00 blueswir1
    esp_mem_writeb,
667 6f7e9aec bellard
};
668 6f7e9aec bellard
669 cc9952f3 Blue Swirl
static const VMStateDescription vmstate_esp = {
670 cc9952f3 Blue Swirl
    .name ="esp",
671 cc9952f3 Blue Swirl
    .version_id = 3,
672 cc9952f3 Blue Swirl
    .minimum_version_id = 3,
673 cc9952f3 Blue Swirl
    .minimum_version_id_old = 3,
674 cc9952f3 Blue Swirl
    .fields      = (VMStateField []) {
675 cc9952f3 Blue Swirl
        VMSTATE_BUFFER(rregs, ESPState),
676 cc9952f3 Blue Swirl
        VMSTATE_BUFFER(wregs, ESPState),
677 cc9952f3 Blue Swirl
        VMSTATE_INT32(ti_size, ESPState),
678 cc9952f3 Blue Swirl
        VMSTATE_UINT32(ti_rptr, ESPState),
679 cc9952f3 Blue Swirl
        VMSTATE_UINT32(ti_wptr, ESPState),
680 cc9952f3 Blue Swirl
        VMSTATE_BUFFER(ti_buf, ESPState),
681 cc9952f3 Blue Swirl
        VMSTATE_UINT32(sense, ESPState),
682 cc9952f3 Blue Swirl
        VMSTATE_UINT32(dma, ESPState),
683 cc9952f3 Blue Swirl
        VMSTATE_BUFFER(cmdbuf, ESPState),
684 cc9952f3 Blue Swirl
        VMSTATE_UINT32(cmdlen, ESPState),
685 cc9952f3 Blue Swirl
        VMSTATE_UINT32(do_cmd, ESPState),
686 cc9952f3 Blue Swirl
        VMSTATE_UINT32(dma_left, ESPState),
687 cc9952f3 Blue Swirl
        VMSTATE_END_OF_LIST()
688 cc9952f3 Blue Swirl
    }
689 cc9952f3 Blue Swirl
};
690 6f7e9aec bellard
691 c227f099 Anthony Liguori
void esp_init(target_phys_addr_t espaddr, int it_shift,
692 ff9868ec Blue Swirl
              ESPDMAMemoryReadWriteFunc dma_memory_read,
693 ff9868ec Blue Swirl
              ESPDMAMemoryReadWriteFunc dma_memory_write,
694 73d74342 Blue Swirl
              void *dma_opaque, qemu_irq irq, qemu_irq *reset,
695 73d74342 Blue Swirl
              qemu_irq *dma_enable)
696 6f7e9aec bellard
{
697 cfb9de9c Paul Brook
    DeviceState *dev;
698 cfb9de9c Paul Brook
    SysBusDevice *s;
699 ee6847d1 Gerd Hoffmann
    ESPState *esp;
700 cfb9de9c Paul Brook
701 cfb9de9c Paul Brook
    dev = qdev_create(NULL, "esp");
702 ee6847d1 Gerd Hoffmann
    esp = DO_UPCAST(ESPState, busdev.qdev, dev);
703 ee6847d1 Gerd Hoffmann
    esp->dma_memory_read = dma_memory_read;
704 ee6847d1 Gerd Hoffmann
    esp->dma_memory_write = dma_memory_write;
705 ee6847d1 Gerd Hoffmann
    esp->dma_opaque = dma_opaque;
706 ee6847d1 Gerd Hoffmann
    esp->it_shift = it_shift;
707 73d74342 Blue Swirl
    /* XXX for now until rc4030 has been changed to use DMA enable signal */
708 73d74342 Blue Swirl
    esp->dma_enabled = 1;
709 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
710 cfb9de9c Paul Brook
    s = sysbus_from_qdev(dev);
711 cfb9de9c Paul Brook
    sysbus_connect_irq(s, 0, irq);
712 cfb9de9c Paul Brook
    sysbus_mmio_map(s, 0, espaddr);
713 74ff8d90 Blue Swirl
    *reset = qdev_get_gpio_in(dev, 0);
714 73d74342 Blue Swirl
    *dma_enable = qdev_get_gpio_in(dev, 1);
715 cfb9de9c Paul Brook
}
716 6f7e9aec bellard
717 81a322d4 Gerd Hoffmann
static int esp_init1(SysBusDevice *dev)
718 cfb9de9c Paul Brook
{
719 cfb9de9c Paul Brook
    ESPState *s = FROM_SYSBUS(ESPState, dev);
720 cfb9de9c Paul Brook
    int esp_io_memory;
721 6f7e9aec bellard
722 cfb9de9c Paul Brook
    sysbus_init_irq(dev, &s->irq);
723 cfb9de9c Paul Brook
    assert(s->it_shift != -1);
724 6f7e9aec bellard
725 1eed09cb Avi Kivity
    esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s);
726 cfb9de9c Paul Brook
    sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
727 6f7e9aec bellard
728 73d74342 Blue Swirl
    qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
729 2d069bab blueswir1
730 ca9c39fa Gerd Hoffmann
    scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete);
731 fa66b909 Markus Armbruster
    return scsi_bus_legacy_handle_cmdline(&s->bus);
732 67e999be bellard
}
733 cfb9de9c Paul Brook
734 63235df8 Blue Swirl
static SysBusDeviceInfo esp_info = {
735 63235df8 Blue Swirl
    .init = esp_init1,
736 63235df8 Blue Swirl
    .qdev.name  = "esp",
737 63235df8 Blue Swirl
    .qdev.size  = sizeof(ESPState),
738 63235df8 Blue Swirl
    .qdev.vmsd  = &vmstate_esp,
739 85948643 Blue Swirl
    .qdev.reset = esp_hard_reset,
740 63235df8 Blue Swirl
    .qdev.props = (Property[]) {
741 63235df8 Blue Swirl
        {.name = NULL}
742 63235df8 Blue Swirl
    }
743 63235df8 Blue Swirl
};
744 63235df8 Blue Swirl
745 cfb9de9c Paul Brook
static void esp_register_devices(void)
746 cfb9de9c Paul Brook
{
747 63235df8 Blue Swirl
    sysbus_register_withprop(&esp_info);
748 cfb9de9c Paul Brook
}
749 cfb9de9c Paul Brook
750 cfb9de9c Paul Brook
device_init(esp_register_devices)