Statistics
| Branch: | Revision:

root / hw / esp.c @ 37952117

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