Statistics
| Branch: | Revision:

root / hw / esp.c @ c6df7102

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