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) |