Statistics
| Branch: | Revision:

root / hw / esp.c @ 2cae4119

History | View | Annotate | Download (19.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 fabaaf1d Hervé Poussineau
 * Copyright (c) 2012 Herve Poussineau
6 5fafdf24 ths
 *
7 6f7e9aec bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 6f7e9aec bellard
 * of this software and associated documentation files (the "Software"), to deal
9 6f7e9aec bellard
 * in the Software without restriction, including without limitation the rights
10 6f7e9aec bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 6f7e9aec bellard
 * copies of the Software, and to permit persons to whom the Software is
12 6f7e9aec bellard
 * furnished to do so, subject to the following conditions:
13 6f7e9aec bellard
 *
14 6f7e9aec bellard
 * The above copyright notice and this permission notice shall be included in
15 6f7e9aec bellard
 * all copies or substantial portions of the Software.
16 6f7e9aec bellard
 *
17 6f7e9aec bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 6f7e9aec bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 6f7e9aec bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 6f7e9aec bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 6f7e9aec bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 6f7e9aec bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 6f7e9aec bellard
 * THE SOFTWARE.
24 6f7e9aec bellard
 */
25 5d20fa6b blueswir1
26 cfb9de9c Paul Brook
#include "sysbus.h"
27 1cd3af54 Gerd Hoffmann
#include "esp.h"
28 bf4b9889 Blue Swirl
#include "trace.h"
29 3af4e9aa Hervé Poussineau
#include "qemu-log.h"
30 6f7e9aec bellard
31 67e999be bellard
/*
32 5ad6bb97 blueswir1
 * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
33 5ad6bb97 blueswir1
 * also produced as NCR89C100. See
34 67e999be bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
35 67e999be bellard
 * and
36 67e999be bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
37 67e999be bellard
 */
38 67e999be bellard
39 c73f96fd blueswir1
static void esp_raise_irq(ESPState *s)
40 c73f96fd blueswir1
{
41 c73f96fd blueswir1
    if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
42 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] |= STAT_INT;
43 c73f96fd blueswir1
        qemu_irq_raise(s->irq);
44 bf4b9889 Blue Swirl
        trace_esp_raise_irq();
45 c73f96fd blueswir1
    }
46 c73f96fd blueswir1
}
47 c73f96fd blueswir1
48 c73f96fd blueswir1
static void esp_lower_irq(ESPState *s)
49 c73f96fd blueswir1
{
50 c73f96fd blueswir1
    if (s->rregs[ESP_RSTAT] & STAT_INT) {
51 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] &= ~STAT_INT;
52 c73f96fd blueswir1
        qemu_irq_lower(s->irq);
53 bf4b9889 Blue Swirl
        trace_esp_lower_irq();
54 c73f96fd blueswir1
    }
55 c73f96fd blueswir1
}
56 c73f96fd blueswir1
57 9c7e23fc Hervé Poussineau
void esp_dma_enable(ESPState *s, int irq, int level)
58 73d74342 Blue Swirl
{
59 73d74342 Blue Swirl
    if (level) {
60 73d74342 Blue Swirl
        s->dma_enabled = 1;
61 bf4b9889 Blue Swirl
        trace_esp_dma_enable();
62 73d74342 Blue Swirl
        if (s->dma_cb) {
63 73d74342 Blue Swirl
            s->dma_cb(s);
64 73d74342 Blue Swirl
            s->dma_cb = NULL;
65 73d74342 Blue Swirl
        }
66 73d74342 Blue Swirl
    } else {
67 bf4b9889 Blue Swirl
        trace_esp_dma_disable();
68 73d74342 Blue Swirl
        s->dma_enabled = 0;
69 73d74342 Blue Swirl
    }
70 73d74342 Blue Swirl
}
71 73d74342 Blue Swirl
72 9c7e23fc Hervé Poussineau
void esp_request_cancelled(SCSIRequest *req)
73 94d3f98a Paolo Bonzini
{
74 e6810db8 Hervé Poussineau
    ESPState *s = req->hba_private;
75 94d3f98a Paolo Bonzini
76 94d3f98a Paolo Bonzini
    if (req == s->current_req) {
77 94d3f98a Paolo Bonzini
        scsi_req_unref(s->current_req);
78 94d3f98a Paolo Bonzini
        s->current_req = NULL;
79 94d3f98a Paolo Bonzini
        s->current_dev = NULL;
80 94d3f98a Paolo Bonzini
    }
81 94d3f98a Paolo Bonzini
}
82 94d3f98a Paolo Bonzini
83 22548760 blueswir1
static uint32_t get_cmd(ESPState *s, uint8_t *buf)
84 2f275b8f bellard
{
85 a917d384 pbrook
    uint32_t dmalen;
86 2f275b8f bellard
    int target;
87 2f275b8f bellard
88 8dea1dd4 blueswir1
    target = s->wregs[ESP_WBUSID] & BUSID_DID;
89 4f6200f0 bellard
    if (s->dma) {
90 9ea73f8b Paolo Bonzini
        dmalen = s->rregs[ESP_TCLO];
91 9ea73f8b Paolo Bonzini
        dmalen |= s->rregs[ESP_TCMID] << 8;
92 9ea73f8b Paolo Bonzini
        dmalen |= s->rregs[ESP_TCHI] << 16;
93 8b17de88 blueswir1
        s->dma_memory_read(s->dma_opaque, buf, dmalen);
94 4f6200f0 bellard
    } else {
95 fc4d65da blueswir1
        dmalen = s->ti_size;
96 fc4d65da blueswir1
        memcpy(buf, s->ti_buf, dmalen);
97 75ef8496 Hervé Poussineau
        buf[0] = buf[2] >> 5;
98 4f6200f0 bellard
    }
99 bf4b9889 Blue Swirl
    trace_esp_get_cmd(dmalen, target);
100 2e5d83bb pbrook
101 2f275b8f bellard
    s->ti_size = 0;
102 4f6200f0 bellard
    s->ti_rptr = 0;
103 4f6200f0 bellard
    s->ti_wptr = 0;
104 2f275b8f bellard
105 429bef69 Hervé Poussineau
    if (s->current_req) {
106 a917d384 pbrook
        /* Started a new command before the old one finished.  Cancel it.  */
107 94d3f98a Paolo Bonzini
        scsi_req_cancel(s->current_req);
108 a917d384 pbrook
        s->async_len = 0;
109 a917d384 pbrook
    }
110 a917d384 pbrook
111 0d3545e7 Paolo Bonzini
    s->current_dev = scsi_device_find(&s->bus, 0, target, 0);
112 f48a7a6e Paolo Bonzini
    if (!s->current_dev) {
113 2e5d83bb pbrook
        // No such drive
114 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] = 0;
115 5ad6bb97 blueswir1
        s->rregs[ESP_RINTR] = INTR_DC;
116 5ad6bb97 blueswir1
        s->rregs[ESP_RSEQ] = SEQ_0;
117 c73f96fd blueswir1
        esp_raise_irq(s);
118 f930d07e blueswir1
        return 0;
119 2f275b8f bellard
    }
120 9f149aa9 pbrook
    return dmalen;
121 9f149aa9 pbrook
}
122 9f149aa9 pbrook
123 f2818f22 Artyom Tarasenko
static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
124 9f149aa9 pbrook
{
125 9f149aa9 pbrook
    int32_t datalen;
126 9f149aa9 pbrook
    int lun;
127 f48a7a6e Paolo Bonzini
    SCSIDevice *current_lun;
128 9f149aa9 pbrook
129 bf4b9889 Blue Swirl
    trace_esp_do_busid_cmd(busid);
130 f2818f22 Artyom Tarasenko
    lun = busid & 7;
131 0d3545e7 Paolo Bonzini
    current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
132 e6810db8 Hervé Poussineau
    s->current_req = scsi_req_new(current_lun, 0, lun, buf, s);
133 c39ce112 Paolo Bonzini
    datalen = scsi_req_enqueue(s->current_req);
134 67e999be bellard
    s->ti_size = datalen;
135 67e999be bellard
    if (datalen != 0) {
136 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] = STAT_TC;
137 a917d384 pbrook
        s->dma_left = 0;
138 6787f5fa pbrook
        s->dma_counter = 0;
139 2e5d83bb pbrook
        if (datalen > 0) {
140 5ad6bb97 blueswir1
            s->rregs[ESP_RSTAT] |= STAT_DI;
141 2e5d83bb pbrook
        } else {
142 5ad6bb97 blueswir1
            s->rregs[ESP_RSTAT] |= STAT_DO;
143 b9788fc4 bellard
        }
144 ad3376cc Paolo Bonzini
        scsi_req_continue(s->current_req);
145 2f275b8f bellard
    }
146 5ad6bb97 blueswir1
    s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
147 5ad6bb97 blueswir1
    s->rregs[ESP_RSEQ] = SEQ_CD;
148 c73f96fd blueswir1
    esp_raise_irq(s);
149 2f275b8f bellard
}
150 2f275b8f bellard
151 f2818f22 Artyom Tarasenko
static void do_cmd(ESPState *s, uint8_t *buf)
152 f2818f22 Artyom Tarasenko
{
153 f2818f22 Artyom Tarasenko
    uint8_t busid = buf[0];
154 f2818f22 Artyom Tarasenko
155 f2818f22 Artyom Tarasenko
    do_busid_cmd(s, &buf[1], busid);
156 f2818f22 Artyom Tarasenko
}
157 f2818f22 Artyom Tarasenko
158 9f149aa9 pbrook
static void handle_satn(ESPState *s)
159 9f149aa9 pbrook
{
160 9f149aa9 pbrook
    uint8_t buf[32];
161 9f149aa9 pbrook
    int len;
162 9f149aa9 pbrook
163 1b26eaa1 Hervé Poussineau
    if (s->dma && !s->dma_enabled) {
164 73d74342 Blue Swirl
        s->dma_cb = handle_satn;
165 73d74342 Blue Swirl
        return;
166 73d74342 Blue Swirl
    }
167 9f149aa9 pbrook
    len = get_cmd(s, buf);
168 9f149aa9 pbrook
    if (len)
169 9f149aa9 pbrook
        do_cmd(s, buf);
170 9f149aa9 pbrook
}
171 9f149aa9 pbrook
172 f2818f22 Artyom Tarasenko
static void handle_s_without_atn(ESPState *s)
173 f2818f22 Artyom Tarasenko
{
174 f2818f22 Artyom Tarasenko
    uint8_t buf[32];
175 f2818f22 Artyom Tarasenko
    int len;
176 f2818f22 Artyom Tarasenko
177 1b26eaa1 Hervé Poussineau
    if (s->dma && !s->dma_enabled) {
178 73d74342 Blue Swirl
        s->dma_cb = handle_s_without_atn;
179 73d74342 Blue Swirl
        return;
180 73d74342 Blue Swirl
    }
181 f2818f22 Artyom Tarasenko
    len = get_cmd(s, buf);
182 f2818f22 Artyom Tarasenko
    if (len) {
183 f2818f22 Artyom Tarasenko
        do_busid_cmd(s, buf, 0);
184 f2818f22 Artyom Tarasenko
    }
185 f2818f22 Artyom Tarasenko
}
186 f2818f22 Artyom Tarasenko
187 9f149aa9 pbrook
static void handle_satn_stop(ESPState *s)
188 9f149aa9 pbrook
{
189 1b26eaa1 Hervé Poussineau
    if (s->dma && !s->dma_enabled) {
190 73d74342 Blue Swirl
        s->dma_cb = handle_satn_stop;
191 73d74342 Blue Swirl
        return;
192 73d74342 Blue Swirl
    }
193 9f149aa9 pbrook
    s->cmdlen = get_cmd(s, s->cmdbuf);
194 9f149aa9 pbrook
    if (s->cmdlen) {
195 bf4b9889 Blue Swirl
        trace_esp_handle_satn_stop(s->cmdlen);
196 9f149aa9 pbrook
        s->do_cmd = 1;
197 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
198 5ad6bb97 blueswir1
        s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
199 5ad6bb97 blueswir1
        s->rregs[ESP_RSEQ] = SEQ_CD;
200 c73f96fd blueswir1
        esp_raise_irq(s);
201 9f149aa9 pbrook
    }
202 9f149aa9 pbrook
}
203 9f149aa9 pbrook
204 0fc5c15a pbrook
static void write_response(ESPState *s)
205 2f275b8f bellard
{
206 bf4b9889 Blue Swirl
    trace_esp_write_response(s->status);
207 3944966d Paolo Bonzini
    s->ti_buf[0] = s->status;
208 0fc5c15a pbrook
    s->ti_buf[1] = 0;
209 4f6200f0 bellard
    if (s->dma) {
210 8b17de88 blueswir1
        s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
211 c73f96fd blueswir1
        s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
212 5ad6bb97 blueswir1
        s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
213 5ad6bb97 blueswir1
        s->rregs[ESP_RSEQ] = SEQ_CD;
214 4f6200f0 bellard
    } else {
215 f930d07e blueswir1
        s->ti_size = 2;
216 f930d07e blueswir1
        s->ti_rptr = 0;
217 f930d07e blueswir1
        s->ti_wptr = 0;
218 5ad6bb97 blueswir1
        s->rregs[ESP_RFLAGS] = 2;
219 4f6200f0 bellard
    }
220 c73f96fd blueswir1
    esp_raise_irq(s);
221 2f275b8f bellard
}
222 4f6200f0 bellard
223 a917d384 pbrook
static void esp_dma_done(ESPState *s)
224 a917d384 pbrook
{
225 c73f96fd blueswir1
    s->rregs[ESP_RSTAT] |= STAT_TC;
226 5ad6bb97 blueswir1
    s->rregs[ESP_RINTR] = INTR_BS;
227 5ad6bb97 blueswir1
    s->rregs[ESP_RSEQ] = 0;
228 5ad6bb97 blueswir1
    s->rregs[ESP_RFLAGS] = 0;
229 5ad6bb97 blueswir1
    s->rregs[ESP_TCLO] = 0;
230 5ad6bb97 blueswir1
    s->rregs[ESP_TCMID] = 0;
231 9ea73f8b Paolo Bonzini
    s->rregs[ESP_TCHI] = 0;
232 c73f96fd blueswir1
    esp_raise_irq(s);
233 a917d384 pbrook
}
234 a917d384 pbrook
235 4d611c9a pbrook
static void esp_do_dma(ESPState *s)
236 4d611c9a pbrook
{
237 67e999be bellard
    uint32_t len;
238 4d611c9a pbrook
    int to_device;
239 a917d384 pbrook
240 67e999be bellard
    to_device = (s->ti_size < 0);
241 a917d384 pbrook
    len = s->dma_left;
242 4d611c9a pbrook
    if (s->do_cmd) {
243 bf4b9889 Blue Swirl
        trace_esp_do_dma(s->cmdlen, len);
244 8b17de88 blueswir1
        s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
245 4d611c9a pbrook
        s->ti_size = 0;
246 4d611c9a pbrook
        s->cmdlen = 0;
247 4d611c9a pbrook
        s->do_cmd = 0;
248 4d611c9a pbrook
        do_cmd(s, s->cmdbuf);
249 4d611c9a pbrook
        return;
250 a917d384 pbrook
    }
251 a917d384 pbrook
    if (s->async_len == 0) {
252 a917d384 pbrook
        /* Defer until data is available.  */
253 a917d384 pbrook
        return;
254 a917d384 pbrook
    }
255 a917d384 pbrook
    if (len > s->async_len) {
256 a917d384 pbrook
        len = s->async_len;
257 a917d384 pbrook
    }
258 a917d384 pbrook
    if (to_device) {
259 8b17de88 blueswir1
        s->dma_memory_read(s->dma_opaque, s->async_buf, len);
260 4d611c9a pbrook
    } else {
261 8b17de88 blueswir1
        s->dma_memory_write(s->dma_opaque, s->async_buf, len);
262 a917d384 pbrook
    }
263 a917d384 pbrook
    s->dma_left -= len;
264 a917d384 pbrook
    s->async_buf += len;
265 a917d384 pbrook
    s->async_len -= len;
266 6787f5fa pbrook
    if (to_device)
267 6787f5fa pbrook
        s->ti_size += len;
268 6787f5fa pbrook
    else
269 6787f5fa pbrook
        s->ti_size -= len;
270 a917d384 pbrook
    if (s->async_len == 0) {
271 ad3376cc Paolo Bonzini
        scsi_req_continue(s->current_req);
272 ad3376cc Paolo Bonzini
        /* If there is still data to be read from the device then
273 ad3376cc Paolo Bonzini
           complete the DMA operation immediately.  Otherwise defer
274 ad3376cc Paolo Bonzini
           until the scsi layer has completed.  */
275 ad3376cc Paolo Bonzini
        if (to_device || s->dma_left != 0 || s->ti_size == 0) {
276 ad3376cc Paolo Bonzini
            return;
277 4d611c9a pbrook
        }
278 a917d384 pbrook
    }
279 ad3376cc Paolo Bonzini
280 ad3376cc Paolo Bonzini
    /* Partially filled a scsi buffer. Complete immediately.  */
281 ad3376cc Paolo Bonzini
    esp_dma_done(s);
282 4d611c9a pbrook
}
283 4d611c9a pbrook
284 9c7e23fc Hervé Poussineau
void esp_command_complete(SCSIRequest *req, uint32_t status,
285 01e95455 Paolo Bonzini
                                 size_t resid)
286 2e5d83bb pbrook
{
287 e6810db8 Hervé Poussineau
    ESPState *s = req->hba_private;
288 2e5d83bb pbrook
289 bf4b9889 Blue Swirl
    trace_esp_command_complete();
290 c6df7102 Paolo Bonzini
    if (s->ti_size != 0) {
291 bf4b9889 Blue Swirl
        trace_esp_command_complete_unexpected();
292 c6df7102 Paolo Bonzini
    }
293 c6df7102 Paolo Bonzini
    s->ti_size = 0;
294 c6df7102 Paolo Bonzini
    s->dma_left = 0;
295 c6df7102 Paolo Bonzini
    s->async_len = 0;
296 aba1f023 Paolo Bonzini
    if (status) {
297 bf4b9889 Blue Swirl
        trace_esp_command_complete_fail();
298 c6df7102 Paolo Bonzini
    }
299 aba1f023 Paolo Bonzini
    s->status = status;
300 c6df7102 Paolo Bonzini
    s->rregs[ESP_RSTAT] = STAT_ST;
301 c6df7102 Paolo Bonzini
    esp_dma_done(s);
302 c6df7102 Paolo Bonzini
    if (s->current_req) {
303 c6df7102 Paolo Bonzini
        scsi_req_unref(s->current_req);
304 c6df7102 Paolo Bonzini
        s->current_req = NULL;
305 c6df7102 Paolo Bonzini
        s->current_dev = NULL;
306 c6df7102 Paolo Bonzini
    }
307 c6df7102 Paolo Bonzini
}
308 c6df7102 Paolo Bonzini
309 9c7e23fc Hervé Poussineau
void esp_transfer_data(SCSIRequest *req, uint32_t len)
310 c6df7102 Paolo Bonzini
{
311 e6810db8 Hervé Poussineau
    ESPState *s = req->hba_private;
312 c6df7102 Paolo Bonzini
313 bf4b9889 Blue Swirl
    trace_esp_transfer_data(s->dma_left, s->ti_size);
314 aba1f023 Paolo Bonzini
    s->async_len = len;
315 c6df7102 Paolo Bonzini
    s->async_buf = scsi_req_get_buf(req);
316 c6df7102 Paolo Bonzini
    if (s->dma_left) {
317 c6df7102 Paolo Bonzini
        esp_do_dma(s);
318 c6df7102 Paolo Bonzini
    } else if (s->dma_counter != 0 && s->ti_size <= 0) {
319 c6df7102 Paolo Bonzini
        /* If this was the last part of a DMA transfer then the
320 c6df7102 Paolo Bonzini
           completion interrupt is deferred to here.  */
321 a917d384 pbrook
        esp_dma_done(s);
322 4d611c9a pbrook
    }
323 2e5d83bb pbrook
}
324 2e5d83bb pbrook
325 2f275b8f bellard
static void handle_ti(ESPState *s)
326 2f275b8f bellard
{
327 4d611c9a pbrook
    uint32_t dmalen, minlen;
328 2f275b8f bellard
329 7246e160 Hervé Poussineau
    if (s->dma && !s->dma_enabled) {
330 7246e160 Hervé Poussineau
        s->dma_cb = handle_ti;
331 7246e160 Hervé Poussineau
        return;
332 7246e160 Hervé Poussineau
    }
333 7246e160 Hervé Poussineau
334 9ea73f8b Paolo Bonzini
    dmalen = s->rregs[ESP_TCLO];
335 9ea73f8b Paolo Bonzini
    dmalen |= s->rregs[ESP_TCMID] << 8;
336 9ea73f8b Paolo Bonzini
    dmalen |= s->rregs[ESP_TCHI] << 16;
337 db59203d pbrook
    if (dmalen==0) {
338 db59203d pbrook
      dmalen=0x10000;
339 db59203d pbrook
    }
340 6787f5fa pbrook
    s->dma_counter = dmalen;
341 db59203d pbrook
342 9f149aa9 pbrook
    if (s->do_cmd)
343 9f149aa9 pbrook
        minlen = (dmalen < 32) ? dmalen : 32;
344 67e999be bellard
    else if (s->ti_size < 0)
345 67e999be bellard
        minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
346 9f149aa9 pbrook
    else
347 9f149aa9 pbrook
        minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
348 bf4b9889 Blue Swirl
    trace_esp_handle_ti(minlen);
349 4f6200f0 bellard
    if (s->dma) {
350 4d611c9a pbrook
        s->dma_left = minlen;
351 5ad6bb97 blueswir1
        s->rregs[ESP_RSTAT] &= ~STAT_TC;
352 4d611c9a pbrook
        esp_do_dma(s);
353 9f149aa9 pbrook
    } else if (s->do_cmd) {
354 bf4b9889 Blue Swirl
        trace_esp_handle_ti_cmd(s->cmdlen);
355 9f149aa9 pbrook
        s->ti_size = 0;
356 9f149aa9 pbrook
        s->cmdlen = 0;
357 9f149aa9 pbrook
        s->do_cmd = 0;
358 9f149aa9 pbrook
        do_cmd(s, s->cmdbuf);
359 9f149aa9 pbrook
        return;
360 9f149aa9 pbrook
    }
361 2f275b8f bellard
}
362 2f275b8f bellard
363 9c7e23fc Hervé Poussineau
void esp_hard_reset(ESPState *s)
364 6f7e9aec bellard
{
365 5aca8c3b blueswir1
    memset(s->rregs, 0, ESP_REGS);
366 5aca8c3b blueswir1
    memset(s->wregs, 0, ESP_REGS);
367 d32e4b3d Hervé Poussineau
    s->rregs[ESP_TCHI] = s->chip_id;
368 4e9aec74 pbrook
    s->ti_size = 0;
369 4e9aec74 pbrook
    s->ti_rptr = 0;
370 4e9aec74 pbrook
    s->ti_wptr = 0;
371 4e9aec74 pbrook
    s->dma = 0;
372 9f149aa9 pbrook
    s->do_cmd = 0;
373 73d74342 Blue Swirl
    s->dma_cb = NULL;
374 8dea1dd4 blueswir1
375 8dea1dd4 blueswir1
    s->rregs[ESP_CFG1] = 7;
376 6f7e9aec bellard
}
377 6f7e9aec bellard
378 a391fdbc Hervé Poussineau
static void esp_soft_reset(ESPState *s)
379 85948643 Blue Swirl
{
380 85948643 Blue Swirl
    qemu_irq_lower(s->irq);
381 a391fdbc Hervé Poussineau
    esp_hard_reset(s);
382 85948643 Blue Swirl
}
383 85948643 Blue Swirl
384 a391fdbc Hervé Poussineau
static void parent_esp_reset(ESPState *s, int irq, int level)
385 2d069bab blueswir1
{
386 85948643 Blue Swirl
    if (level) {
387 a391fdbc Hervé Poussineau
        esp_soft_reset(s);
388 85948643 Blue Swirl
    }
389 2d069bab blueswir1
}
390 2d069bab blueswir1
391 9c7e23fc Hervé Poussineau
uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
392 73d74342 Blue Swirl
{
393 a391fdbc Hervé Poussineau
    uint32_t old_val;
394 73d74342 Blue Swirl
395 bf4b9889 Blue Swirl
    trace_esp_mem_readb(saddr, s->rregs[saddr]);
396 6f7e9aec bellard
    switch (saddr) {
397 5ad6bb97 blueswir1
    case ESP_FIFO:
398 f930d07e blueswir1
        if (s->ti_size > 0) {
399 f930d07e blueswir1
            s->ti_size--;
400 5ad6bb97 blueswir1
            if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
401 8dea1dd4 blueswir1
                /* Data out.  */
402 3af4e9aa Hervé Poussineau
                qemu_log_mask(LOG_UNIMP,
403 3af4e9aa Hervé Poussineau
                              "esp: PIO data read not implemented\n");
404 5ad6bb97 blueswir1
                s->rregs[ESP_FIFO] = 0;
405 2e5d83bb pbrook
            } else {
406 5ad6bb97 blueswir1
                s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
407 2e5d83bb pbrook
            }
408 c73f96fd blueswir1
            esp_raise_irq(s);
409 f930d07e blueswir1
        }
410 f930d07e blueswir1
        if (s->ti_size == 0) {
411 4f6200f0 bellard
            s->ti_rptr = 0;
412 4f6200f0 bellard
            s->ti_wptr = 0;
413 4f6200f0 bellard
        }
414 f930d07e blueswir1
        break;
415 5ad6bb97 blueswir1
    case ESP_RINTR:
416 2814df28 Blue Swirl
        /* Clear sequence step, interrupt register and all status bits
417 2814df28 Blue Swirl
           except TC */
418 2814df28 Blue Swirl
        old_val = s->rregs[ESP_RINTR];
419 2814df28 Blue Swirl
        s->rregs[ESP_RINTR] = 0;
420 2814df28 Blue Swirl
        s->rregs[ESP_RSTAT] &= ~STAT_TC;
421 2814df28 Blue Swirl
        s->rregs[ESP_RSEQ] = SEQ_CD;
422 c73f96fd blueswir1
        esp_lower_irq(s);
423 2814df28 Blue Swirl
424 2814df28 Blue Swirl
        return old_val;
425 6f7e9aec bellard
    default:
426 f930d07e blueswir1
        break;
427 6f7e9aec bellard
    }
428 2f275b8f bellard
    return s->rregs[saddr];
429 6f7e9aec bellard
}
430 6f7e9aec bellard
431 9c7e23fc Hervé Poussineau
void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
432 6f7e9aec bellard
{
433 bf4b9889 Blue Swirl
    trace_esp_mem_writeb(saddr, s->wregs[saddr], val);
434 6f7e9aec bellard
    switch (saddr) {
435 5ad6bb97 blueswir1
    case ESP_TCLO:
436 5ad6bb97 blueswir1
    case ESP_TCMID:
437 9ea73f8b Paolo Bonzini
    case ESP_TCHI:
438 5ad6bb97 blueswir1
        s->rregs[ESP_RSTAT] &= ~STAT_TC;
439 4f6200f0 bellard
        break;
440 5ad6bb97 blueswir1
    case ESP_FIFO:
441 9f149aa9 pbrook
        if (s->do_cmd) {
442 9f149aa9 pbrook
            s->cmdbuf[s->cmdlen++] = val & 0xff;
443 8dea1dd4 blueswir1
        } else if (s->ti_size == TI_BUFSZ - 1) {
444 3af4e9aa Hervé Poussineau
            trace_esp_error_fifo_overrun();
445 2e5d83bb pbrook
        } else {
446 2e5d83bb pbrook
            s->ti_size++;
447 2e5d83bb pbrook
            s->ti_buf[s->ti_wptr++] = val & 0xff;
448 2e5d83bb pbrook
        }
449 f930d07e blueswir1
        break;
450 5ad6bb97 blueswir1
    case ESP_CMD:
451 4f6200f0 bellard
        s->rregs[saddr] = val;
452 5ad6bb97 blueswir1
        if (val & CMD_DMA) {
453 f930d07e blueswir1
            s->dma = 1;
454 6787f5fa pbrook
            /* Reload DMA counter.  */
455 5ad6bb97 blueswir1
            s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
456 5ad6bb97 blueswir1
            s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
457 9ea73f8b Paolo Bonzini
            s->rregs[ESP_TCHI] = s->wregs[ESP_TCHI];
458 f930d07e blueswir1
        } else {
459 f930d07e blueswir1
            s->dma = 0;
460 f930d07e blueswir1
        }
461 5ad6bb97 blueswir1
        switch(val & CMD_CMD) {
462 5ad6bb97 blueswir1
        case CMD_NOP:
463 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_nop(val);
464 f930d07e blueswir1
            break;
465 5ad6bb97 blueswir1
        case CMD_FLUSH:
466 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_flush(val);
467 9e61bde5 bellard
            //s->ti_size = 0;
468 5ad6bb97 blueswir1
            s->rregs[ESP_RINTR] = INTR_FC;
469 5ad6bb97 blueswir1
            s->rregs[ESP_RSEQ] = 0;
470 a214c598 blueswir1
            s->rregs[ESP_RFLAGS] = 0;
471 f930d07e blueswir1
            break;
472 5ad6bb97 blueswir1
        case CMD_RESET:
473 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_reset(val);
474 a391fdbc Hervé Poussineau
            esp_soft_reset(s);
475 f930d07e blueswir1
            break;
476 5ad6bb97 blueswir1
        case CMD_BUSRESET:
477 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_bus_reset(val);
478 5ad6bb97 blueswir1
            s->rregs[ESP_RINTR] = INTR_RST;
479 5ad6bb97 blueswir1
            if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
480 c73f96fd blueswir1
                esp_raise_irq(s);
481 9e61bde5 bellard
            }
482 f930d07e blueswir1
            break;
483 5ad6bb97 blueswir1
        case CMD_TI:
484 f930d07e blueswir1
            handle_ti(s);
485 f930d07e blueswir1
            break;
486 5ad6bb97 blueswir1
        case CMD_ICCS:
487 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_iccs(val);
488 f930d07e blueswir1
            write_response(s);
489 4bf5801d blueswir1
            s->rregs[ESP_RINTR] = INTR_FC;
490 4bf5801d blueswir1
            s->rregs[ESP_RSTAT] |= STAT_MI;
491 f930d07e blueswir1
            break;
492 5ad6bb97 blueswir1
        case CMD_MSGACC:
493 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_msgacc(val);
494 5ad6bb97 blueswir1
            s->rregs[ESP_RINTR] = INTR_DC;
495 5ad6bb97 blueswir1
            s->rregs[ESP_RSEQ] = 0;
496 4e2a68c1 Artyom Tarasenko
            s->rregs[ESP_RFLAGS] = 0;
497 4e2a68c1 Artyom Tarasenko
            esp_raise_irq(s);
498 f930d07e blueswir1
            break;
499 0fd0eb21 Blue Swirl
        case CMD_PAD:
500 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_pad(val);
501 0fd0eb21 Blue Swirl
            s->rregs[ESP_RSTAT] = STAT_TC;
502 0fd0eb21 Blue Swirl
            s->rregs[ESP_RINTR] = INTR_FC;
503 0fd0eb21 Blue Swirl
            s->rregs[ESP_RSEQ] = 0;
504 0fd0eb21 Blue Swirl
            break;
505 5ad6bb97 blueswir1
        case CMD_SATN:
506 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_satn(val);
507 f930d07e blueswir1
            break;
508 6915bff1 Hervé Poussineau
        case CMD_RSTATN:
509 6915bff1 Hervé Poussineau
            trace_esp_mem_writeb_cmd_rstatn(val);
510 6915bff1 Hervé Poussineau
            break;
511 5e1e0a3b Blue Swirl
        case CMD_SEL:
512 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_sel(val);
513 f2818f22 Artyom Tarasenko
            handle_s_without_atn(s);
514 5e1e0a3b Blue Swirl
            break;
515 5ad6bb97 blueswir1
        case CMD_SELATN:
516 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_selatn(val);
517 f930d07e blueswir1
            handle_satn(s);
518 f930d07e blueswir1
            break;
519 5ad6bb97 blueswir1
        case CMD_SELATNS:
520 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_selatns(val);
521 f930d07e blueswir1
            handle_satn_stop(s);
522 f930d07e blueswir1
            break;
523 5ad6bb97 blueswir1
        case CMD_ENSEL:
524 bf4b9889 Blue Swirl
            trace_esp_mem_writeb_cmd_ensel(val);
525 e3926838 blueswir1
            s->rregs[ESP_RINTR] = 0;
526 74ec6048 blueswir1
            break;
527 6fe84c18 Hervé Poussineau
        case CMD_DISSEL:
528 6fe84c18 Hervé Poussineau
            trace_esp_mem_writeb_cmd_dissel(val);
529 6fe84c18 Hervé Poussineau
            s->rregs[ESP_RINTR] = 0;
530 6fe84c18 Hervé Poussineau
            esp_raise_irq(s);
531 6fe84c18 Hervé Poussineau
            break;
532 f930d07e blueswir1
        default:
533 3af4e9aa Hervé Poussineau
            trace_esp_error_unhandled_command(val);
534 f930d07e blueswir1
            break;
535 f930d07e blueswir1
        }
536 f930d07e blueswir1
        break;
537 5ad6bb97 blueswir1
    case ESP_WBUSID ... ESP_WSYNO:
538 f930d07e blueswir1
        break;
539 5ad6bb97 blueswir1
    case ESP_CFG1:
540 9ea73f8b Paolo Bonzini
    case ESP_CFG2: case ESP_CFG3:
541 9ea73f8b Paolo Bonzini
    case ESP_RES3: case ESP_RES4:
542 4f6200f0 bellard
        s->rregs[saddr] = val;
543 4f6200f0 bellard
        break;
544 5ad6bb97 blueswir1
    case ESP_WCCF ... ESP_WTEST:
545 4f6200f0 bellard
        break;
546 6f7e9aec bellard
    default:
547 3af4e9aa Hervé Poussineau
        trace_esp_error_invalid_write(val, saddr);
548 8dea1dd4 blueswir1
        return;
549 6f7e9aec bellard
    }
550 2f275b8f bellard
    s->wregs[saddr] = val;
551 6f7e9aec bellard
}
552 6f7e9aec bellard
553 67bb5314 Avi Kivity
static bool esp_mem_accepts(void *opaque, target_phys_addr_t addr,
554 67bb5314 Avi Kivity
                            unsigned size, bool is_write)
555 67bb5314 Avi Kivity
{
556 67bb5314 Avi Kivity
    return (size == 1) || (is_write && size == 4);
557 67bb5314 Avi Kivity
}
558 6f7e9aec bellard
559 9c7e23fc Hervé Poussineau
const VMStateDescription vmstate_esp = {
560 cc9952f3 Blue Swirl
    .name ="esp",
561 cc9952f3 Blue Swirl
    .version_id = 3,
562 cc9952f3 Blue Swirl
    .minimum_version_id = 3,
563 cc9952f3 Blue Swirl
    .minimum_version_id_old = 3,
564 cc9952f3 Blue Swirl
    .fields      = (VMStateField []) {
565 cc9952f3 Blue Swirl
        VMSTATE_BUFFER(rregs, ESPState),
566 cc9952f3 Blue Swirl
        VMSTATE_BUFFER(wregs, ESPState),
567 cc9952f3 Blue Swirl
        VMSTATE_INT32(ti_size, ESPState),
568 cc9952f3 Blue Swirl
        VMSTATE_UINT32(ti_rptr, ESPState),
569 cc9952f3 Blue Swirl
        VMSTATE_UINT32(ti_wptr, ESPState),
570 cc9952f3 Blue Swirl
        VMSTATE_BUFFER(ti_buf, ESPState),
571 3944966d Paolo Bonzini
        VMSTATE_UINT32(status, ESPState),
572 cc9952f3 Blue Swirl
        VMSTATE_UINT32(dma, ESPState),
573 cc9952f3 Blue Swirl
        VMSTATE_BUFFER(cmdbuf, ESPState),
574 cc9952f3 Blue Swirl
        VMSTATE_UINT32(cmdlen, ESPState),
575 cc9952f3 Blue Swirl
        VMSTATE_UINT32(do_cmd, ESPState),
576 cc9952f3 Blue Swirl
        VMSTATE_UINT32(dma_left, ESPState),
577 cc9952f3 Blue Swirl
        VMSTATE_END_OF_LIST()
578 cc9952f3 Blue Swirl
    }
579 cc9952f3 Blue Swirl
};
580 6f7e9aec bellard
581 a391fdbc Hervé Poussineau
typedef struct {
582 a391fdbc Hervé Poussineau
    SysBusDevice busdev;
583 a391fdbc Hervé Poussineau
    MemoryRegion iomem;
584 a391fdbc Hervé Poussineau
    uint32_t it_shift;
585 a391fdbc Hervé Poussineau
    ESPState esp;
586 a391fdbc Hervé Poussineau
} SysBusESPState;
587 a391fdbc Hervé Poussineau
588 a391fdbc Hervé Poussineau
static void sysbus_esp_mem_write(void *opaque, target_phys_addr_t addr,
589 a391fdbc Hervé Poussineau
                                 uint64_t val, unsigned int size)
590 a391fdbc Hervé Poussineau
{
591 a391fdbc Hervé Poussineau
    SysBusESPState *sysbus = opaque;
592 a391fdbc Hervé Poussineau
    uint32_t saddr;
593 a391fdbc Hervé Poussineau
594 a391fdbc Hervé Poussineau
    saddr = addr >> sysbus->it_shift;
595 a391fdbc Hervé Poussineau
    esp_reg_write(&sysbus->esp, saddr, val);
596 a391fdbc Hervé Poussineau
}
597 a391fdbc Hervé Poussineau
598 a391fdbc Hervé Poussineau
static uint64_t sysbus_esp_mem_read(void *opaque, target_phys_addr_t addr,
599 a391fdbc Hervé Poussineau
                                    unsigned int size)
600 a391fdbc Hervé Poussineau
{
601 a391fdbc Hervé Poussineau
    SysBusESPState *sysbus = opaque;
602 a391fdbc Hervé Poussineau
    uint32_t saddr;
603 a391fdbc Hervé Poussineau
604 a391fdbc Hervé Poussineau
    saddr = addr >> sysbus->it_shift;
605 a391fdbc Hervé Poussineau
    return esp_reg_read(&sysbus->esp, saddr);
606 a391fdbc Hervé Poussineau
}
607 a391fdbc Hervé Poussineau
608 a391fdbc Hervé Poussineau
static const MemoryRegionOps sysbus_esp_mem_ops = {
609 a391fdbc Hervé Poussineau
    .read = sysbus_esp_mem_read,
610 a391fdbc Hervé Poussineau
    .write = sysbus_esp_mem_write,
611 a391fdbc Hervé Poussineau
    .endianness = DEVICE_NATIVE_ENDIAN,
612 a391fdbc Hervé Poussineau
    .valid.accepts = esp_mem_accepts,
613 a391fdbc Hervé Poussineau
};
614 a391fdbc Hervé Poussineau
615 c227f099 Anthony Liguori
void esp_init(target_phys_addr_t espaddr, int it_shift,
616 ff9868ec Blue Swirl
              ESPDMAMemoryReadWriteFunc dma_memory_read,
617 ff9868ec Blue Swirl
              ESPDMAMemoryReadWriteFunc dma_memory_write,
618 73d74342 Blue Swirl
              void *dma_opaque, qemu_irq irq, qemu_irq *reset,
619 73d74342 Blue Swirl
              qemu_irq *dma_enable)
620 6f7e9aec bellard
{
621 cfb9de9c Paul Brook
    DeviceState *dev;
622 cfb9de9c Paul Brook
    SysBusDevice *s;
623 a391fdbc Hervé Poussineau
    SysBusESPState *sysbus;
624 ee6847d1 Gerd Hoffmann
    ESPState *esp;
625 cfb9de9c Paul Brook
626 cfb9de9c Paul Brook
    dev = qdev_create(NULL, "esp");
627 a391fdbc Hervé Poussineau
    sysbus = DO_UPCAST(SysBusESPState, busdev.qdev, dev);
628 a391fdbc Hervé Poussineau
    esp = &sysbus->esp;
629 ee6847d1 Gerd Hoffmann
    esp->dma_memory_read = dma_memory_read;
630 ee6847d1 Gerd Hoffmann
    esp->dma_memory_write = dma_memory_write;
631 ee6847d1 Gerd Hoffmann
    esp->dma_opaque = dma_opaque;
632 a391fdbc Hervé Poussineau
    sysbus->it_shift = it_shift;
633 73d74342 Blue Swirl
    /* XXX for now until rc4030 has been changed to use DMA enable signal */
634 73d74342 Blue Swirl
    esp->dma_enabled = 1;
635 e23a1b33 Markus Armbruster
    qdev_init_nofail(dev);
636 cfb9de9c Paul Brook
    s = sysbus_from_qdev(dev);
637 cfb9de9c Paul Brook
    sysbus_connect_irq(s, 0, irq);
638 cfb9de9c Paul Brook
    sysbus_mmio_map(s, 0, espaddr);
639 74ff8d90 Blue Swirl
    *reset = qdev_get_gpio_in(dev, 0);
640 73d74342 Blue Swirl
    *dma_enable = qdev_get_gpio_in(dev, 1);
641 cfb9de9c Paul Brook
}
642 6f7e9aec bellard
643 afd4030c Paolo Bonzini
static const struct SCSIBusInfo esp_scsi_info = {
644 afd4030c Paolo Bonzini
    .tcq = false,
645 7e0380b9 Paolo Bonzini
    .max_target = ESP_MAX_DEVS,
646 7e0380b9 Paolo Bonzini
    .max_lun = 7,
647 afd4030c Paolo Bonzini
648 c6df7102 Paolo Bonzini
    .transfer_data = esp_transfer_data,
649 94d3f98a Paolo Bonzini
    .complete = esp_command_complete,
650 94d3f98a Paolo Bonzini
    .cancel = esp_request_cancelled
651 cfdc1bb0 Paolo Bonzini
};
652 cfdc1bb0 Paolo Bonzini
653 a391fdbc Hervé Poussineau
static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
654 cfb9de9c Paul Brook
{
655 a391fdbc Hervé Poussineau
    DeviceState *d = opaque;
656 a391fdbc Hervé Poussineau
    SysBusESPState *sysbus = container_of(d, SysBusESPState, busdev.qdev);
657 a391fdbc Hervé Poussineau
    ESPState *s = &sysbus->esp;
658 a391fdbc Hervé Poussineau
659 a391fdbc Hervé Poussineau
    switch (irq) {
660 a391fdbc Hervé Poussineau
    case 0:
661 a391fdbc Hervé Poussineau
        parent_esp_reset(s, irq, level);
662 a391fdbc Hervé Poussineau
        break;
663 a391fdbc Hervé Poussineau
    case 1:
664 a391fdbc Hervé Poussineau
        esp_dma_enable(opaque, irq, level);
665 a391fdbc Hervé Poussineau
        break;
666 a391fdbc Hervé Poussineau
    }
667 a391fdbc Hervé Poussineau
}
668 a391fdbc Hervé Poussineau
669 a391fdbc Hervé Poussineau
static int sysbus_esp_init(SysBusDevice *dev)
670 a391fdbc Hervé Poussineau
{
671 a391fdbc Hervé Poussineau
    SysBusESPState *sysbus = FROM_SYSBUS(SysBusESPState, dev);
672 a391fdbc Hervé Poussineau
    ESPState *s = &sysbus->esp;
673 6f7e9aec bellard
674 cfb9de9c Paul Brook
    sysbus_init_irq(dev, &s->irq);
675 a391fdbc Hervé Poussineau
    assert(sysbus->it_shift != -1);
676 6f7e9aec bellard
677 d32e4b3d Hervé Poussineau
    s->chip_id = TCHI_FAS100A;
678 a391fdbc Hervé Poussineau
    memory_region_init_io(&sysbus->iomem, &sysbus_esp_mem_ops, sysbus,
679 a391fdbc Hervé Poussineau
                          "esp", ESP_REGS << sysbus->it_shift);
680 a391fdbc Hervé Poussineau
    sysbus_init_mmio(dev, &sysbus->iomem);
681 6f7e9aec bellard
682 a391fdbc Hervé Poussineau
    qdev_init_gpio_in(&dev->qdev, sysbus_esp_gpio_demux, 2);
683 2d069bab blueswir1
684 afd4030c Paolo Bonzini
    scsi_bus_new(&s->bus, &dev->qdev, &esp_scsi_info);
685 fa66b909 Markus Armbruster
    return scsi_bus_legacy_handle_cmdline(&s->bus);
686 67e999be bellard
}
687 cfb9de9c Paul Brook
688 a391fdbc Hervé Poussineau
static void sysbus_esp_hard_reset(DeviceState *dev)
689 a391fdbc Hervé Poussineau
{
690 a391fdbc Hervé Poussineau
    SysBusESPState *sysbus = DO_UPCAST(SysBusESPState, busdev.qdev, dev);
691 a391fdbc Hervé Poussineau
    esp_hard_reset(&sysbus->esp);
692 a391fdbc Hervé Poussineau
}
693 a391fdbc Hervé Poussineau
694 a391fdbc Hervé Poussineau
static const VMStateDescription vmstate_sysbus_esp_scsi = {
695 a391fdbc Hervé Poussineau
    .name = "sysbusespscsi",
696 a391fdbc Hervé Poussineau
    .version_id = 0,
697 a391fdbc Hervé Poussineau
    .minimum_version_id = 0,
698 a391fdbc Hervé Poussineau
    .minimum_version_id_old = 0,
699 a391fdbc Hervé Poussineau
    .fields = (VMStateField[]) {
700 a391fdbc Hervé Poussineau
        VMSTATE_STRUCT(esp, SysBusESPState, 0, vmstate_esp, ESPState),
701 a391fdbc Hervé Poussineau
        VMSTATE_END_OF_LIST()
702 a391fdbc Hervé Poussineau
    }
703 999e12bb Anthony Liguori
};
704 999e12bb Anthony Liguori
705 a391fdbc Hervé Poussineau
static void sysbus_esp_class_init(ObjectClass *klass, void *data)
706 999e12bb Anthony Liguori
{
707 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
708 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
709 999e12bb Anthony Liguori
710 a391fdbc Hervé Poussineau
    k->init = sysbus_esp_init;
711 a391fdbc Hervé Poussineau
    dc->reset = sysbus_esp_hard_reset;
712 a391fdbc Hervé Poussineau
    dc->vmsd = &vmstate_sysbus_esp_scsi;
713 999e12bb Anthony Liguori
}
714 999e12bb Anthony Liguori
715 1f077308 Hervé Poussineau
static const TypeInfo sysbus_esp_info = {
716 39bffca2 Anthony Liguori
    .name          = "esp",
717 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
718 a391fdbc Hervé Poussineau
    .instance_size = sizeof(SysBusESPState),
719 a391fdbc Hervé Poussineau
    .class_init    = sysbus_esp_class_init,
720 63235df8 Blue Swirl
};
721 63235df8 Blue Swirl
722 83f7d43a Andreas Färber
static void esp_register_types(void)
723 cfb9de9c Paul Brook
{
724 a391fdbc Hervé Poussineau
    type_register_static(&sysbus_esp_info);
725 cfb9de9c Paul Brook
}
726 cfb9de9c Paul Brook
727 83f7d43a Andreas Färber
type_init(esp_register_types)