]> Git Repo - qemu.git/blob - hw/esp.c
linux-user: rlimit conversion between host and target.
[qemu.git] / hw / esp.c
1 /*
2  * QEMU ESP/NCR53C9x emulation
3  *
4  * Copyright (c) 2005-2006 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #include "sysbus.h"
26 #include "scsi.h"
27 #include "esp.h"
28
29 /* debug ESP card */
30 //#define DEBUG_ESP
31
32 /*
33  * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O),
34  * also produced as NCR89C100. See
35  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
36  * and
37  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
38  */
39
40 #ifdef DEBUG_ESP
41 #define DPRINTF(fmt, ...)                                       \
42     do { printf("ESP: " fmt , ## __VA_ARGS__); } while (0)
43 #else
44 #define DPRINTF(fmt, ...) do {} while (0)
45 #endif
46
47 #define ESP_ERROR(fmt, ...)                                             \
48     do { printf("ESP ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
49
50 #define ESP_REGS 16
51 #define TI_BUFSZ 16
52
53 typedef struct ESPState ESPState;
54
55 struct ESPState {
56     SysBusDevice busdev;
57     uint32_t it_shift;
58     qemu_irq irq;
59     uint8_t rregs[ESP_REGS];
60     uint8_t wregs[ESP_REGS];
61     int32_t ti_size;
62     uint32_t ti_rptr, ti_wptr;
63     uint8_t ti_buf[TI_BUFSZ];
64     uint32_t sense;
65     uint32_t dma;
66     SCSIBus bus;
67     SCSIDevice *current_dev;
68     uint8_t cmdbuf[TI_BUFSZ];
69     uint32_t cmdlen;
70     uint32_t do_cmd;
71
72     /* The amount of data left in the current DMA transfer.  */
73     uint32_t dma_left;
74     /* The size of the current DMA transfer.  Zero if no transfer is in
75        progress.  */
76     uint32_t dma_counter;
77     uint8_t *async_buf;
78     uint32_t async_len;
79
80     ESPDMAMemoryReadWriteFunc dma_memory_read;
81     ESPDMAMemoryReadWriteFunc dma_memory_write;
82     void *dma_opaque;
83 };
84
85 #define ESP_TCLO   0x0
86 #define ESP_TCMID  0x1
87 #define ESP_FIFO   0x2
88 #define ESP_CMD    0x3
89 #define ESP_RSTAT  0x4
90 #define ESP_WBUSID 0x4
91 #define ESP_RINTR  0x5
92 #define ESP_WSEL   0x5
93 #define ESP_RSEQ   0x6
94 #define ESP_WSYNTP 0x6
95 #define ESP_RFLAGS 0x7
96 #define ESP_WSYNO  0x7
97 #define ESP_CFG1   0x8
98 #define ESP_RRES1  0x9
99 #define ESP_WCCF   0x9
100 #define ESP_RRES2  0xa
101 #define ESP_WTEST  0xa
102 #define ESP_CFG2   0xb
103 #define ESP_CFG3   0xc
104 #define ESP_RES3   0xd
105 #define ESP_TCHI   0xe
106 #define ESP_RES4   0xf
107
108 #define CMD_DMA 0x80
109 #define CMD_CMD 0x7f
110
111 #define CMD_NOP      0x00
112 #define CMD_FLUSH    0x01
113 #define CMD_RESET    0x02
114 #define CMD_BUSRESET 0x03
115 #define CMD_TI       0x10
116 #define CMD_ICCS     0x11
117 #define CMD_MSGACC   0x12
118 #define CMD_PAD      0x18
119 #define CMD_SATN     0x1a
120 #define CMD_SEL      0x41
121 #define CMD_SELATN   0x42
122 #define CMD_SELATNS  0x43
123 #define CMD_ENSEL    0x44
124
125 #define STAT_DO 0x00
126 #define STAT_DI 0x01
127 #define STAT_CD 0x02
128 #define STAT_ST 0x03
129 #define STAT_MO 0x06
130 #define STAT_MI 0x07
131 #define STAT_PIO_MASK 0x06
132
133 #define STAT_TC 0x10
134 #define STAT_PE 0x20
135 #define STAT_GE 0x40
136 #define STAT_INT 0x80
137
138 #define BUSID_DID 0x07
139
140 #define INTR_FC 0x08
141 #define INTR_BS 0x10
142 #define INTR_DC 0x20
143 #define INTR_RST 0x80
144
145 #define SEQ_0 0x0
146 #define SEQ_CD 0x4
147
148 #define CFG1_RESREPT 0x40
149
150 #define TCHI_FAS100A 0x4
151
152 static void esp_raise_irq(ESPState *s)
153 {
154     if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
155         s->rregs[ESP_RSTAT] |= STAT_INT;
156         qemu_irq_raise(s->irq);
157         DPRINTF("Raise IRQ\n");
158     }
159 }
160
161 static void esp_lower_irq(ESPState *s)
162 {
163     if (s->rregs[ESP_RSTAT] & STAT_INT) {
164         s->rregs[ESP_RSTAT] &= ~STAT_INT;
165         qemu_irq_lower(s->irq);
166         DPRINTF("Lower IRQ\n");
167     }
168 }
169
170 static uint32_t get_cmd(ESPState *s, uint8_t *buf)
171 {
172     uint32_t dmalen;
173     int target;
174
175     target = s->wregs[ESP_WBUSID] & BUSID_DID;
176     if (s->dma) {
177         dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
178         s->dma_memory_read(s->dma_opaque, buf, dmalen);
179     } else {
180         dmalen = s->ti_size;
181         memcpy(buf, s->ti_buf, dmalen);
182         buf[0] = 0;
183     }
184     DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
185
186     s->ti_size = 0;
187     s->ti_rptr = 0;
188     s->ti_wptr = 0;
189
190     if (s->current_dev) {
191         /* Started a new command before the old one finished.  Cancel it.  */
192         s->current_dev->info->cancel_io(s->current_dev, 0);
193         s->async_len = 0;
194     }
195
196     if (target >= ESP_MAX_DEVS || !s->bus.devs[target]) {
197         // No such drive
198         s->rregs[ESP_RSTAT] = 0;
199         s->rregs[ESP_RINTR] = INTR_DC;
200         s->rregs[ESP_RSEQ] = SEQ_0;
201         esp_raise_irq(s);
202         return 0;
203     }
204     s->current_dev = s->bus.devs[target];
205     return dmalen;
206 }
207
208 static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
209 {
210     int32_t datalen;
211     int lun;
212
213     DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
214     lun = busid & 7;
215     datalen = s->current_dev->info->send_command(s->current_dev, 0, buf, lun);
216     s->ti_size = datalen;
217     if (datalen != 0) {
218         s->rregs[ESP_RSTAT] = STAT_TC;
219         s->dma_left = 0;
220         s->dma_counter = 0;
221         if (datalen > 0) {
222             s->rregs[ESP_RSTAT] |= STAT_DI;
223             s->current_dev->info->read_data(s->current_dev, 0);
224         } else {
225             s->rregs[ESP_RSTAT] |= STAT_DO;
226             s->current_dev->info->write_data(s->current_dev, 0);
227         }
228     }
229     s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
230     s->rregs[ESP_RSEQ] = SEQ_CD;
231     esp_raise_irq(s);
232 }
233
234 static void do_cmd(ESPState *s, uint8_t *buf)
235 {
236     uint8_t busid = buf[0];
237
238     do_busid_cmd(s, &buf[1], busid);
239 }
240
241 static void handle_satn(ESPState *s)
242 {
243     uint8_t buf[32];
244     int len;
245
246     len = get_cmd(s, buf);
247     if (len)
248         do_cmd(s, buf);
249 }
250
251 static void handle_s_without_atn(ESPState *s)
252 {
253     uint8_t buf[32];
254     int len;
255
256     len = get_cmd(s, buf);
257     if (len) {
258         do_busid_cmd(s, buf, 0);
259     }
260 }
261
262 static void handle_satn_stop(ESPState *s)
263 {
264     s->cmdlen = get_cmd(s, s->cmdbuf);
265     if (s->cmdlen) {
266         DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
267         s->do_cmd = 1;
268         s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
269         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
270         s->rregs[ESP_RSEQ] = SEQ_CD;
271         esp_raise_irq(s);
272     }
273 }
274
275 static void write_response(ESPState *s)
276 {
277     DPRINTF("Transfer status (sense=%d)\n", s->sense);
278     s->ti_buf[0] = s->sense;
279     s->ti_buf[1] = 0;
280     if (s->dma) {
281         s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
282         s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
283         s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
284         s->rregs[ESP_RSEQ] = SEQ_CD;
285     } else {
286         s->ti_size = 2;
287         s->ti_rptr = 0;
288         s->ti_wptr = 0;
289         s->rregs[ESP_RFLAGS] = 2;
290     }
291     esp_raise_irq(s);
292 }
293
294 static void esp_dma_done(ESPState *s)
295 {
296     s->rregs[ESP_RSTAT] |= STAT_TC;
297     s->rregs[ESP_RINTR] = INTR_BS;
298     s->rregs[ESP_RSEQ] = 0;
299     s->rregs[ESP_RFLAGS] = 0;
300     s->rregs[ESP_TCLO] = 0;
301     s->rregs[ESP_TCMID] = 0;
302     esp_raise_irq(s);
303 }
304
305 static void esp_do_dma(ESPState *s)
306 {
307     uint32_t len;
308     int to_device;
309
310     to_device = (s->ti_size < 0);
311     len = s->dma_left;
312     if (s->do_cmd) {
313         DPRINTF("command len %d + %d\n", s->cmdlen, len);
314         s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
315         s->ti_size = 0;
316         s->cmdlen = 0;
317         s->do_cmd = 0;
318         do_cmd(s, s->cmdbuf);
319         return;
320     }
321     if (s->async_len == 0) {
322         /* Defer until data is available.  */
323         return;
324     }
325     if (len > s->async_len) {
326         len = s->async_len;
327     }
328     if (to_device) {
329         s->dma_memory_read(s->dma_opaque, s->async_buf, len);
330     } else {
331         s->dma_memory_write(s->dma_opaque, s->async_buf, len);
332     }
333     s->dma_left -= len;
334     s->async_buf += len;
335     s->async_len -= len;
336     if (to_device)
337         s->ti_size += len;
338     else
339         s->ti_size -= len;
340     if (s->async_len == 0) {
341         if (to_device) {
342             // ti_size is negative
343             s->current_dev->info->write_data(s->current_dev, 0);
344         } else {
345             s->current_dev->info->read_data(s->current_dev, 0);
346             /* If there is still data to be read from the device then
347                complete the DMA operation immediately.  Otherwise defer
348                until the scsi layer has completed.  */
349             if (s->dma_left == 0 && s->ti_size > 0) {
350                 esp_dma_done(s);
351             }
352         }
353     } else {
354         /* Partially filled a scsi buffer. Complete immediately.  */
355         esp_dma_done(s);
356     }
357 }
358
359 static void esp_command_complete(SCSIBus *bus, int reason, uint32_t tag,
360                                  uint32_t arg)
361 {
362     ESPState *s = DO_UPCAST(ESPState, busdev.qdev, bus->qbus.parent);
363
364     if (reason == SCSI_REASON_DONE) {
365         DPRINTF("SCSI Command complete\n");
366         if (s->ti_size != 0)
367             DPRINTF("SCSI command completed unexpectedly\n");
368         s->ti_size = 0;
369         s->dma_left = 0;
370         s->async_len = 0;
371         if (arg)
372             DPRINTF("Command failed\n");
373         s->sense = arg;
374         s->rregs[ESP_RSTAT] = STAT_ST;
375         esp_dma_done(s);
376         s->current_dev = NULL;
377     } else {
378         DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
379         s->async_len = arg;
380         s->async_buf = s->current_dev->info->get_buf(s->current_dev, 0);
381         if (s->dma_left) {
382             esp_do_dma(s);
383         } else if (s->dma_counter != 0 && s->ti_size <= 0) {
384             /* If this was the last part of a DMA transfer then the
385                completion interrupt is deferred to here.  */
386             esp_dma_done(s);
387         }
388     }
389 }
390
391 static void handle_ti(ESPState *s)
392 {
393     uint32_t dmalen, minlen;
394
395     dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
396     if (dmalen==0) {
397       dmalen=0x10000;
398     }
399     s->dma_counter = dmalen;
400
401     if (s->do_cmd)
402         minlen = (dmalen < 32) ? dmalen : 32;
403     else if (s->ti_size < 0)
404         minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
405     else
406         minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
407     DPRINTF("Transfer Information len %d\n", minlen);
408     if (s->dma) {
409         s->dma_left = minlen;
410         s->rregs[ESP_RSTAT] &= ~STAT_TC;
411         esp_do_dma(s);
412     } else if (s->do_cmd) {
413         DPRINTF("command len %d\n", s->cmdlen);
414         s->ti_size = 0;
415         s->cmdlen = 0;
416         s->do_cmd = 0;
417         do_cmd(s, s->cmdbuf);
418         return;
419     }
420 }
421
422 static void esp_reset(DeviceState *d)
423 {
424     ESPState *s = container_of(d, ESPState, busdev.qdev);
425
426     memset(s->rregs, 0, ESP_REGS);
427     memset(s->wregs, 0, ESP_REGS);
428     s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
429     s->ti_size = 0;
430     s->ti_rptr = 0;
431     s->ti_wptr = 0;
432     s->dma = 0;
433     s->do_cmd = 0;
434
435     s->rregs[ESP_CFG1] = 7;
436 }
437
438 static void parent_esp_reset(void *opaque, int irq, int level)
439 {
440     if (level)
441         esp_reset(opaque);
442 }
443
444 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
445 {
446     ESPState *s = opaque;
447     uint32_t saddr, old_val;
448
449     saddr = addr >> s->it_shift;
450     DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
451     switch (saddr) {
452     case ESP_FIFO:
453         if (s->ti_size > 0) {
454             s->ti_size--;
455             if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
456                 /* Data out.  */
457                 ESP_ERROR("PIO data read not implemented\n");
458                 s->rregs[ESP_FIFO] = 0;
459             } else {
460                 s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
461             }
462             esp_raise_irq(s);
463         }
464         if (s->ti_size == 0) {
465             s->ti_rptr = 0;
466             s->ti_wptr = 0;
467         }
468         break;
469     case ESP_RINTR:
470         /* Clear sequence step, interrupt register and all status bits
471            except TC */
472         old_val = s->rregs[ESP_RINTR];
473         s->rregs[ESP_RINTR] = 0;
474         s->rregs[ESP_RSTAT] &= ~STAT_TC;
475         s->rregs[ESP_RSEQ] = SEQ_CD;
476         esp_lower_irq(s);
477
478         return old_val;
479     default:
480         break;
481     }
482     return s->rregs[saddr];
483 }
484
485 static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
486 {
487     ESPState *s = opaque;
488     uint32_t saddr;
489
490     saddr = addr >> s->it_shift;
491     DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],
492             val);
493     switch (saddr) {
494     case ESP_TCLO:
495     case ESP_TCMID:
496         s->rregs[ESP_RSTAT] &= ~STAT_TC;
497         break;
498     case ESP_FIFO:
499         if (s->do_cmd) {
500             s->cmdbuf[s->cmdlen++] = val & 0xff;
501         } else if (s->ti_size == TI_BUFSZ - 1) {
502             ESP_ERROR("fifo overrun\n");
503         } else {
504             s->ti_size++;
505             s->ti_buf[s->ti_wptr++] = val & 0xff;
506         }
507         break;
508     case ESP_CMD:
509         s->rregs[saddr] = val;
510         if (val & CMD_DMA) {
511             s->dma = 1;
512             /* Reload DMA counter.  */
513             s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
514             s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
515         } else {
516             s->dma = 0;
517         }
518         switch(val & CMD_CMD) {
519         case CMD_NOP:
520             DPRINTF("NOP (%2.2x)\n", val);
521             break;
522         case CMD_FLUSH:
523             DPRINTF("Flush FIFO (%2.2x)\n", val);
524             //s->ti_size = 0;
525             s->rregs[ESP_RINTR] = INTR_FC;
526             s->rregs[ESP_RSEQ] = 0;
527             s->rregs[ESP_RFLAGS] = 0;
528             break;
529         case CMD_RESET:
530             DPRINTF("Chip reset (%2.2x)\n", val);
531             esp_reset(&s->busdev.qdev);
532             break;
533         case CMD_BUSRESET:
534             DPRINTF("Bus reset (%2.2x)\n", val);
535             s->rregs[ESP_RINTR] = INTR_RST;
536             if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
537                 esp_raise_irq(s);
538             }
539             break;
540         case CMD_TI:
541             handle_ti(s);
542             break;
543         case CMD_ICCS:
544             DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
545             write_response(s);
546             s->rregs[ESP_RINTR] = INTR_FC;
547             s->rregs[ESP_RSTAT] |= STAT_MI;
548             break;
549         case CMD_MSGACC:
550             DPRINTF("Message Accepted (%2.2x)\n", val);
551             s->rregs[ESP_RINTR] = INTR_DC;
552             s->rregs[ESP_RSEQ] = 0;
553             s->rregs[ESP_RFLAGS] = 0;
554             esp_raise_irq(s);
555             break;
556         case CMD_PAD:
557             DPRINTF("Transfer padding (%2.2x)\n", val);
558             s->rregs[ESP_RSTAT] = STAT_TC;
559             s->rregs[ESP_RINTR] = INTR_FC;
560             s->rregs[ESP_RSEQ] = 0;
561             break;
562         case CMD_SATN:
563             DPRINTF("Set ATN (%2.2x)\n", val);
564             break;
565         case CMD_SEL:
566             DPRINTF("Select without ATN (%2.2x)\n", val);
567             handle_s_without_atn(s);
568             break;
569         case CMD_SELATN:
570             DPRINTF("Select with ATN (%2.2x)\n", val);
571             handle_satn(s);
572             break;
573         case CMD_SELATNS:
574             DPRINTF("Select with ATN & stop (%2.2x)\n", val);
575             handle_satn_stop(s);
576             break;
577         case CMD_ENSEL:
578             DPRINTF("Enable selection (%2.2x)\n", val);
579             s->rregs[ESP_RINTR] = 0;
580             break;
581         default:
582             ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
583             break;
584         }
585         break;
586     case ESP_WBUSID ... ESP_WSYNO:
587         break;
588     case ESP_CFG1:
589         s->rregs[saddr] = val;
590         break;
591     case ESP_WCCF ... ESP_WTEST:
592         break;
593     case ESP_CFG2 ... ESP_RES4:
594         s->rregs[saddr] = val;
595         break;
596     default:
597         ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
598         return;
599     }
600     s->wregs[saddr] = val;
601 }
602
603 static CPUReadMemoryFunc * const esp_mem_read[3] = {
604     esp_mem_readb,
605     NULL,
606     NULL,
607 };
608
609 static CPUWriteMemoryFunc * const esp_mem_write[3] = {
610     esp_mem_writeb,
611     NULL,
612     esp_mem_writeb,
613 };
614
615 static const VMStateDescription vmstate_esp = {
616     .name ="esp",
617     .version_id = 3,
618     .minimum_version_id = 3,
619     .minimum_version_id_old = 3,
620     .fields      = (VMStateField []) {
621         VMSTATE_BUFFER(rregs, ESPState),
622         VMSTATE_BUFFER(wregs, ESPState),
623         VMSTATE_INT32(ti_size, ESPState),
624         VMSTATE_UINT32(ti_rptr, ESPState),
625         VMSTATE_UINT32(ti_wptr, ESPState),
626         VMSTATE_BUFFER(ti_buf, ESPState),
627         VMSTATE_UINT32(sense, ESPState),
628         VMSTATE_UINT32(dma, ESPState),
629         VMSTATE_BUFFER(cmdbuf, ESPState),
630         VMSTATE_UINT32(cmdlen, ESPState),
631         VMSTATE_UINT32(do_cmd, ESPState),
632         VMSTATE_UINT32(dma_left, ESPState),
633         VMSTATE_END_OF_LIST()
634     }
635 };
636
637 void esp_init(target_phys_addr_t espaddr, int it_shift,
638               ESPDMAMemoryReadWriteFunc dma_memory_read,
639               ESPDMAMemoryReadWriteFunc dma_memory_write,
640               void *dma_opaque, qemu_irq irq, qemu_irq *reset)
641 {
642     DeviceState *dev;
643     SysBusDevice *s;
644     ESPState *esp;
645
646     dev = qdev_create(NULL, "esp");
647     esp = DO_UPCAST(ESPState, busdev.qdev, dev);
648     esp->dma_memory_read = dma_memory_read;
649     esp->dma_memory_write = dma_memory_write;
650     esp->dma_opaque = dma_opaque;
651     esp->it_shift = it_shift;
652     qdev_init_nofail(dev);
653     s = sysbus_from_qdev(dev);
654     sysbus_connect_irq(s, 0, irq);
655     sysbus_mmio_map(s, 0, espaddr);
656     *reset = qdev_get_gpio_in(dev, 0);
657 }
658
659 static int esp_init1(SysBusDevice *dev)
660 {
661     ESPState *s = FROM_SYSBUS(ESPState, dev);
662     int esp_io_memory;
663
664     sysbus_init_irq(dev, &s->irq);
665     assert(s->it_shift != -1);
666
667     esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s);
668     sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
669
670     qdev_init_gpio_in(&dev->qdev, parent_esp_reset, 1);
671
672     scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, esp_command_complete);
673     scsi_bus_legacy_handle_cmdline(&s->bus);
674     return 0;
675 }
676
677 static SysBusDeviceInfo esp_info = {
678     .init = esp_init1,
679     .qdev.name  = "esp",
680     .qdev.size  = sizeof(ESPState),
681     .qdev.vmsd  = &vmstate_esp,
682     .qdev.reset = esp_reset,
683     .qdev.props = (Property[]) {
684         {.name = NULL}
685     }
686 };
687
688 static void esp_register_devices(void)
689 {
690     sysbus_register_withprop(&esp_info);
691 }
692
693 device_init(esp_register_devices)
This page took 0.064989 seconds and 4 git commands to generate.