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