Statistics
| Branch: | Revision:

root / hw / esp.c @ 7c470ff1

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