Annotation of qemu/hw/esp.c, revision 1.1.1.7
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.6 root 25: #include "hw.h"
26: #include "scsi-disk.h"
1.1.1.7 ! root 27: #include "scsi.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
41: #define DPRINTF(fmt, args...) \
42: do { printf("ESP: " fmt , ##args); } while (0)
43: #else
1.1.1.7 ! root 44: #define DPRINTF(fmt, args...) do {} while (0)
1.1 root 45: #endif
46:
1.1.1.7 ! root 47: #define ESP_ERROR(fmt, args...) \
! 48: do { printf("ESP ERROR: %s: " fmt, __func__ , ##args); } while (0)
! 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.7 ! root 56: uint32_t it_shift;
1.1.1.6 root 57: qemu_irq irq;
58: uint8_t rregs[ESP_REGS];
59: uint8_t wregs[ESP_REGS];
1.1.1.5 root 60: int32_t ti_size;
1.1.1.2 root 61: uint32_t ti_rptr, ti_wptr;
62: uint8_t ti_buf[TI_BUFSZ];
1.1.1.7 ! root 63: uint32_t sense;
! 64: uint32_t dma;
1.1.1.6 root 65: SCSIDevice *scsi_dev[ESP_MAX_DEVS];
1.1.1.4 root 66: SCSIDevice *current_dev;
67: uint8_t cmdbuf[TI_BUFSZ];
1.1.1.7 ! root 68: uint32_t cmdlen;
! 69: uint32_t do_cmd;
1.1.1.5 root 70:
71: /* The amount of data left in the current DMA transfer. */
72: uint32_t dma_left;
73: /* The size of the current DMA transfer. Zero if no transfer is in
74: progress. */
75: uint32_t dma_counter;
76: uint8_t *async_buf;
77: uint32_t async_len;
1.1.1.7 ! root 78:
! 79: espdma_memory_read_write dma_memory_read;
! 80: espdma_memory_read_write dma_memory_write;
1.1.1.5 root 81: void *dma_opaque;
1.1.1.3 root 82: };
1.1 root 83:
1.1.1.6 root 84: #define ESP_TCLO 0x0
85: #define ESP_TCMID 0x1
86: #define ESP_FIFO 0x2
87: #define ESP_CMD 0x3
88: #define ESP_RSTAT 0x4
89: #define ESP_WBUSID 0x4
90: #define ESP_RINTR 0x5
91: #define ESP_WSEL 0x5
92: #define ESP_RSEQ 0x6
93: #define ESP_WSYNTP 0x6
94: #define ESP_RFLAGS 0x7
95: #define ESP_WSYNO 0x7
96: #define ESP_CFG1 0x8
97: #define ESP_RRES1 0x9
98: #define ESP_WCCF 0x9
99: #define ESP_RRES2 0xa
100: #define ESP_WTEST 0xa
101: #define ESP_CFG2 0xb
102: #define ESP_CFG3 0xc
103: #define ESP_RES3 0xd
104: #define ESP_TCHI 0xe
105: #define ESP_RES4 0xf
106:
107: #define CMD_DMA 0x80
108: #define CMD_CMD 0x7f
109:
110: #define CMD_NOP 0x00
111: #define CMD_FLUSH 0x01
112: #define CMD_RESET 0x02
113: #define CMD_BUSRESET 0x03
114: #define CMD_TI 0x10
115: #define CMD_ICCS 0x11
116: #define CMD_MSGACC 0x12
117: #define CMD_SATN 0x1a
118: #define CMD_SELATN 0x42
119: #define CMD_SELATNS 0x43
120: #define CMD_ENSEL 0x44
121:
1.1 root 122: #define STAT_DO 0x00
123: #define STAT_DI 0x01
124: #define STAT_CD 0x02
125: #define STAT_ST 0x03
1.1.1.7 ! root 126: #define STAT_MO 0x06
! 127: #define STAT_MI 0x07
1.1.1.6 root 128: #define STAT_PIO_MASK 0x06
1.1 root 129:
130: #define STAT_TC 0x10
1.1.1.5 root 131: #define STAT_PE 0x20
132: #define STAT_GE 0x40
1.1.1.7 ! root 133: #define STAT_INT 0x80
! 134:
! 135: #define BUSID_DID 0x07
1.1 root 136:
137: #define INTR_FC 0x08
138: #define INTR_BS 0x10
139: #define INTR_DC 0x20
1.1.1.2 root 140: #define INTR_RST 0x80
1.1 root 141:
142: #define SEQ_0 0x0
143: #define SEQ_CD 0x4
144:
1.1.1.6 root 145: #define CFG1_RESREPT 0x40
146:
147: #define TCHI_FAS100A 0x4
148:
1.1.1.7 ! root 149: static void esp_raise_irq(ESPState *s)
! 150: {
! 151: if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
! 152: s->rregs[ESP_RSTAT] |= STAT_INT;
! 153: qemu_irq_raise(s->irq);
! 154: }
! 155: }
! 156:
! 157: static void esp_lower_irq(ESPState *s)
! 158: {
! 159: if (s->rregs[ESP_RSTAT] & STAT_INT) {
! 160: s->rregs[ESP_RSTAT] &= ~STAT_INT;
! 161: qemu_irq_lower(s->irq);
! 162: }
! 163: }
! 164:
! 165: static uint32_t get_cmd(ESPState *s, uint8_t *buf)
1.1 root 166: {
1.1.1.5 root 167: uint32_t dmalen;
1.1 root 168: int target;
169:
1.1.1.7 ! root 170: target = s->wregs[ESP_WBUSID] & BUSID_DID;
1.1.1.2 root 171: if (s->dma) {
1.1.1.7 ! root 172: dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
! 173: s->dma_memory_read(s->dma_opaque, buf, dmalen);
1.1.1.2 root 174: } else {
1.1.1.7 ! root 175: dmalen = s->ti_size;
! 176: memcpy(buf, s->ti_buf, dmalen);
1.1.1.6 root 177: buf[0] = 0;
1.1.1.2 root 178: }
1.1.1.7 ! root 179: DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
1.1.1.4 root 180:
1.1 root 181: s->ti_size = 0;
1.1.1.2 root 182: s->ti_rptr = 0;
183: s->ti_wptr = 0;
1.1 root 184:
1.1.1.5 root 185: if (s->current_dev) {
186: /* Started a new command before the old one finished. Cancel it. */
1.1.1.6 root 187: s->current_dev->cancel_io(s->current_dev, 0);
1.1.1.5 root 188: s->async_len = 0;
189: }
190:
1.1.1.6 root 191: if (target >= ESP_MAX_DEVS || !s->scsi_dev[target]) {
1.1.1.4 root 192: // No such drive
1.1.1.7 ! root 193: s->rregs[ESP_RSTAT] = 0;
1.1.1.6 root 194: s->rregs[ESP_RINTR] = INTR_DC;
195: s->rregs[ESP_RSEQ] = SEQ_0;
1.1.1.7 ! root 196: esp_raise_irq(s);
1.1.1.6 root 197: return 0;
1.1 root 198: }
1.1.1.4 root 199: s->current_dev = s->scsi_dev[target];
200: return dmalen;
201: }
202:
203: static void do_cmd(ESPState *s, uint8_t *buf)
204: {
205: int32_t datalen;
206: int lun;
207:
208: DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
209: lun = buf[0] & 7;
1.1.1.6 root 210: datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
1.1.1.5 root 211: s->ti_size = datalen;
212: if (datalen != 0) {
1.1.1.7 ! root 213: s->rregs[ESP_RSTAT] = STAT_TC;
1.1.1.5 root 214: s->dma_left = 0;
215: s->dma_counter = 0;
1.1.1.4 root 216: if (datalen > 0) {
1.1.1.6 root 217: s->rregs[ESP_RSTAT] |= STAT_DI;
218: s->current_dev->read_data(s->current_dev, 0);
1.1.1.4 root 219: } else {
1.1.1.6 root 220: s->rregs[ESP_RSTAT] |= STAT_DO;
221: s->current_dev->write_data(s->current_dev, 0);
1.1.1.2 root 222: }
1.1 root 223: }
1.1.1.6 root 224: s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
225: s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7 ! root 226: esp_raise_irq(s);
1.1 root 227: }
228:
1.1.1.4 root 229: static void handle_satn(ESPState *s)
230: {
231: uint8_t buf[32];
232: int len;
233:
234: len = get_cmd(s, buf);
235: if (len)
236: do_cmd(s, buf);
237: }
238:
239: static void handle_satn_stop(ESPState *s)
1.1 root 240: {
1.1.1.4 root 241: s->cmdlen = get_cmd(s, s->cmdbuf);
242: if (s->cmdlen) {
243: DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
244: s->do_cmd = 1;
1.1.1.7 ! root 245: s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
1.1.1.6 root 246: s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
247: s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7 ! root 248: esp_raise_irq(s);
1.1.1.4 root 249: }
250: }
1.1 root 251:
1.1.1.4 root 252: static void write_response(ESPState *s)
253: {
254: DPRINTF("Transfer status (sense=%d)\n", s->sense);
255: s->ti_buf[0] = s->sense;
256: s->ti_buf[1] = 0;
1.1.1.2 root 257: if (s->dma) {
1.1.1.7 ! root 258: s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
! 259: s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
1.1.1.6 root 260: s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
261: s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.2 root 262: } else {
1.1.1.6 root 263: s->ti_size = 2;
264: s->ti_rptr = 0;
265: s->ti_wptr = 0;
266: s->rregs[ESP_RFLAGS] = 2;
1.1.1.2 root 267: }
1.1.1.7 ! root 268: esp_raise_irq(s);
1.1.1.5 root 269: }
1.1 root 270:
1.1.1.5 root 271: static void esp_dma_done(ESPState *s)
272: {
1.1.1.7 ! root 273: s->rregs[ESP_RSTAT] |= STAT_TC;
1.1.1.6 root 274: s->rregs[ESP_RINTR] = INTR_BS;
275: s->rregs[ESP_RSEQ] = 0;
276: s->rregs[ESP_RFLAGS] = 0;
277: s->rregs[ESP_TCLO] = 0;
278: s->rregs[ESP_TCMID] = 0;
1.1.1.7 ! root 279: esp_raise_irq(s);
1.1 root 280: }
1.1.1.2 root 281:
1.1.1.5 root 282: static void esp_do_dma(ESPState *s)
283: {
284: uint32_t len;
285: int to_device;
286:
287: to_device = (s->ti_size < 0);
288: len = s->dma_left;
289: if (s->do_cmd) {
290: DPRINTF("command len %d + %d\n", s->cmdlen, len);
1.1.1.7 ! root 291: s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
1.1.1.5 root 292: s->ti_size = 0;
293: s->cmdlen = 0;
294: s->do_cmd = 0;
295: do_cmd(s, s->cmdbuf);
296: return;
297: }
298: if (s->async_len == 0) {
299: /* Defer until data is available. */
300: return;
301: }
302: if (len > s->async_len) {
303: len = s->async_len;
304: }
305: if (to_device) {
1.1.1.7 ! root 306: s->dma_memory_read(s->dma_opaque, s->async_buf, len);
1.1.1.5 root 307: } else {
1.1.1.7 ! root 308: s->dma_memory_write(s->dma_opaque, s->async_buf, len);
1.1.1.5 root 309: }
310: s->dma_left -= len;
311: s->async_buf += len;
312: s->async_len -= len;
313: if (to_device)
314: s->ti_size += len;
315: else
316: s->ti_size -= len;
317: if (s->async_len == 0) {
318: if (to_device) {
319: // ti_size is negative
1.1.1.6 root 320: s->current_dev->write_data(s->current_dev, 0);
1.1.1.5 root 321: } else {
1.1.1.6 root 322: s->current_dev->read_data(s->current_dev, 0);
1.1.1.5 root 323: /* If there is still data to be read from the device then
1.1.1.7 ! root 324: complete the DMA operation immediately. Otherwise defer
1.1.1.5 root 325: until the scsi layer has completed. */
326: if (s->dma_left == 0 && s->ti_size > 0) {
327: esp_dma_done(s);
328: }
329: }
330: } else {
331: /* Partially filled a scsi buffer. Complete immediately. */
332: esp_dma_done(s);
333: }
334: }
335:
336: static void esp_command_complete(void *opaque, int reason, uint32_t tag,
337: uint32_t arg)
1.1.1.4 root 338: {
339: ESPState *s = (ESPState *)opaque;
340:
1.1.1.5 root 341: if (reason == SCSI_REASON_DONE) {
342: DPRINTF("SCSI Command complete\n");
343: if (s->ti_size != 0)
344: DPRINTF("SCSI command completed unexpectedly\n");
345: s->ti_size = 0;
346: s->dma_left = 0;
347: s->async_len = 0;
348: if (arg)
349: DPRINTF("Command failed\n");
350: s->sense = arg;
1.1.1.6 root 351: s->rregs[ESP_RSTAT] = STAT_ST;
1.1.1.5 root 352: esp_dma_done(s);
353: s->current_dev = NULL;
354: } else {
355: DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
356: s->async_len = arg;
1.1.1.6 root 357: s->async_buf = s->current_dev->get_buf(s->current_dev, 0);
1.1.1.5 root 358: if (s->dma_left) {
359: esp_do_dma(s);
360: } else if (s->dma_counter != 0 && s->ti_size <= 0) {
361: /* If this was the last part of a DMA transfer then the
362: completion interrupt is deferred to here. */
363: esp_dma_done(s);
364: }
365: }
1.1.1.4 root 366: }
1.1 root 367:
368: static void handle_ti(ESPState *s)
369: {
1.1.1.5 root 370: uint32_t dmalen, minlen;
1.1 root 371:
1.1.1.6 root 372: dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
1.1.1.4 root 373: if (dmalen==0) {
374: dmalen=0x10000;
375: }
1.1.1.5 root 376: s->dma_counter = dmalen;
1.1.1.4 root 377:
378: if (s->do_cmd)
379: minlen = (dmalen < 32) ? dmalen : 32;
1.1.1.5 root 380: else if (s->ti_size < 0)
381: minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
1.1.1.4 root 382: else
383: minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
384: DPRINTF("Transfer Information len %d\n", minlen);
1.1.1.2 root 385: if (s->dma) {
1.1.1.5 root 386: s->dma_left = minlen;
1.1.1.6 root 387: s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.5 root 388: esp_do_dma(s);
1.1.1.4 root 389: } else if (s->do_cmd) {
390: DPRINTF("command len %d\n", s->cmdlen);
391: s->ti_size = 0;
392: s->cmdlen = 0;
393: s->do_cmd = 0;
394: do_cmd(s, s->cmdbuf);
395: return;
396: }
1.1 root 397: }
398:
1.1.1.6 root 399: static void esp_reset(void *opaque)
1.1 root 400: {
401: ESPState *s = opaque;
1.1.1.5 root 402:
1.1.1.7 ! root 403: esp_lower_irq(s);
! 404:
1.1.1.6 root 405: memset(s->rregs, 0, ESP_REGS);
406: memset(s->wregs, 0, ESP_REGS);
407: s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
1.1.1.3 root 408: s->ti_size = 0;
409: s->ti_rptr = 0;
410: s->ti_wptr = 0;
411: s->dma = 0;
1.1.1.4 root 412: s->do_cmd = 0;
1.1.1.7 ! root 413:
! 414: s->rregs[ESP_CFG1] = 7;
1.1 root 415: }
416:
1.1.1.6 root 417: static void parent_esp_reset(void *opaque, int irq, int level)
418: {
419: if (level)
420: esp_reset(opaque);
421: }
422:
1.1 root 423: static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
424: {
425: ESPState *s = opaque;
426: uint32_t saddr;
427:
1.1.1.7 ! root 428: saddr = addr >> s->it_shift;
1.1.1.2 root 429: DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
1.1 root 430: switch (saddr) {
1.1.1.6 root 431: case ESP_FIFO:
432: if (s->ti_size > 0) {
433: s->ti_size--;
434: if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
1.1.1.7 ! root 435: /* Data out. */
! 436: ESP_ERROR("PIO data read not implemented\n");
1.1.1.6 root 437: s->rregs[ESP_FIFO] = 0;
1.1.1.4 root 438: } else {
1.1.1.6 root 439: s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
1.1.1.4 root 440: }
1.1.1.7 ! root 441: esp_raise_irq(s);
1.1.1.6 root 442: }
443: if (s->ti_size == 0) {
1.1.1.2 root 444: s->ti_rptr = 0;
445: s->ti_wptr = 0;
446: }
1.1.1.6 root 447: break;
448: case ESP_RINTR:
1.1.1.5 root 449: // Clear interrupt/error status bits
1.1.1.7 ! root 450: s->rregs[ESP_RSTAT] &= ~(STAT_GE | STAT_PE);
! 451: esp_lower_irq(s);
1.1.1.2 root 452: break;
1.1 root 453: default:
1.1.1.6 root 454: break;
1.1 root 455: }
456: return s->rregs[saddr];
457: }
458:
459: static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
460: {
461: ESPState *s = opaque;
462: uint32_t saddr;
463:
1.1.1.7 ! root 464: saddr = addr >> s->it_shift;
1.1.1.6 root 465: DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],
466: val);
1.1 root 467: switch (saddr) {
1.1.1.6 root 468: case ESP_TCLO:
469: case ESP_TCMID:
470: s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.2 root 471: break;
1.1.1.6 root 472: case ESP_FIFO:
1.1.1.4 root 473: if (s->do_cmd) {
474: s->cmdbuf[s->cmdlen++] = val & 0xff;
1.1.1.7 ! root 475: } else if (s->ti_size == TI_BUFSZ - 1) {
! 476: ESP_ERROR("fifo overrun\n");
1.1.1.4 root 477: } else {
478: s->ti_size++;
479: s->ti_buf[s->ti_wptr++] = val & 0xff;
480: }
1.1.1.6 root 481: break;
482: case ESP_CMD:
1.1.1.2 root 483: s->rregs[saddr] = val;
1.1.1.6 root 484: if (val & CMD_DMA) {
485: s->dma = 1;
1.1.1.5 root 486: /* Reload DMA counter. */
1.1.1.6 root 487: s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
488: s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
489: } else {
490: s->dma = 0;
491: }
492: switch(val & CMD_CMD) {
493: case CMD_NOP:
494: DPRINTF("NOP (%2.2x)\n", val);
495: break;
496: case CMD_FLUSH:
497: DPRINTF("Flush FIFO (%2.2x)\n", val);
1.1.1.2 root 498: //s->ti_size = 0;
1.1.1.6 root 499: s->rregs[ESP_RINTR] = INTR_FC;
500: s->rregs[ESP_RSEQ] = 0;
1.1.1.7 ! root 501: s->rregs[ESP_RFLAGS] = 0;
1.1.1.6 root 502: break;
503: case CMD_RESET:
504: DPRINTF("Chip reset (%2.2x)\n", val);
505: esp_reset(s);
506: break;
507: case CMD_BUSRESET:
508: DPRINTF("Bus reset (%2.2x)\n", val);
509: s->rregs[ESP_RINTR] = INTR_RST;
510: if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
1.1.1.7 ! root 511: esp_raise_irq(s);
1.1.1.2 root 512: }
1.1.1.6 root 513: break;
514: case CMD_TI:
515: handle_ti(s);
516: break;
517: case CMD_ICCS:
518: DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
519: write_response(s);
1.1.1.7 ! root 520: s->rregs[ESP_RINTR] = INTR_FC;
! 521: s->rregs[ESP_RSTAT] |= STAT_MI;
1.1.1.6 root 522: break;
523: case CMD_MSGACC:
524: DPRINTF("Message Accepted (%2.2x)\n", val);
525: write_response(s);
526: s->rregs[ESP_RINTR] = INTR_DC;
527: s->rregs[ESP_RSEQ] = 0;
528: break;
529: case CMD_SATN:
530: DPRINTF("Set ATN (%2.2x)\n", val);
531: break;
532: case CMD_SELATN:
533: DPRINTF("Set ATN (%2.2x)\n", val);
534: handle_satn(s);
535: break;
536: case CMD_SELATNS:
537: DPRINTF("Set ATN & stop (%2.2x)\n", val);
538: handle_satn_stop(s);
539: break;
540: case CMD_ENSEL:
541: DPRINTF("Enable selection (%2.2x)\n", val);
1.1.1.7 ! root 542: s->rregs[ESP_RINTR] = 0;
1.1.1.6 root 543: break;
544: default:
1.1.1.7 ! root 545: ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
1.1.1.6 root 546: break;
547: }
548: break;
549: case ESP_WBUSID ... ESP_WSYNO:
550: break;
551: case ESP_CFG1:
1.1.1.2 root 552: s->rregs[saddr] = val;
553: break;
1.1.1.6 root 554: case ESP_WCCF ... ESP_WTEST:
1.1.1.2 root 555: break;
1.1.1.7 ! root 556: case ESP_CFG2 ... ESP_RES4:
1.1.1.2 root 557: s->rregs[saddr] = val;
558: break;
1.1 root 559: default:
1.1.1.7 ! root 560: ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
! 561: return;
1.1 root 562: }
563: s->wregs[saddr] = val;
564: }
565:
566: static CPUReadMemoryFunc *esp_mem_read[3] = {
567: esp_mem_readb,
1.1.1.6 root 568: NULL,
569: NULL,
1.1 root 570: };
571:
572: static CPUWriteMemoryFunc *esp_mem_write[3] = {
573: esp_mem_writeb,
1.1.1.6 root 574: NULL,
1.1.1.7 ! root 575: esp_mem_writeb,
1.1 root 576: };
577:
578: static void esp_save(QEMUFile *f, void *opaque)
579: {
580: ESPState *s = opaque;
581:
1.1.1.6 root 582: qemu_put_buffer(f, s->rregs, ESP_REGS);
583: qemu_put_buffer(f, s->wregs, ESP_REGS);
1.1.1.7 ! root 584: qemu_put_sbe32s(f, &s->ti_size);
1.1.1.2 root 585: qemu_put_be32s(f, &s->ti_rptr);
586: qemu_put_be32s(f, &s->ti_wptr);
587: qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
1.1.1.6 root 588: qemu_put_be32s(f, &s->sense);
1.1.1.2 root 589: qemu_put_be32s(f, &s->dma);
1.1.1.6 root 590: qemu_put_buffer(f, s->cmdbuf, TI_BUFSZ);
591: qemu_put_be32s(f, &s->cmdlen);
592: qemu_put_be32s(f, &s->do_cmd);
593: qemu_put_be32s(f, &s->dma_left);
594: // There should be no transfers in progress, so dma_counter is not saved
1.1 root 595: }
596:
597: static int esp_load(QEMUFile *f, void *opaque, int version_id)
598: {
599: ESPState *s = opaque;
600:
1.1.1.6 root 601: if (version_id != 3)
602: return -EINVAL; // Cannot emulate 2
603:
604: qemu_get_buffer(f, s->rregs, ESP_REGS);
605: qemu_get_buffer(f, s->wregs, ESP_REGS);
1.1.1.7 ! root 606: qemu_get_sbe32s(f, &s->ti_size);
1.1.1.2 root 607: qemu_get_be32s(f, &s->ti_rptr);
608: qemu_get_be32s(f, &s->ti_wptr);
609: qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
1.1.1.6 root 610: qemu_get_be32s(f, &s->sense);
1.1.1.2 root 611: qemu_get_be32s(f, &s->dma);
1.1.1.6 root 612: qemu_get_buffer(f, s->cmdbuf, TI_BUFSZ);
613: qemu_get_be32s(f, &s->cmdlen);
614: qemu_get_be32s(f, &s->do_cmd);
615: qemu_get_be32s(f, &s->dma_left);
1.1 root 616:
617: return 0;
618: }
619:
1.1.1.5 root 620: void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id)
621: {
622: ESPState *s = (ESPState *)opaque;
623:
624: if (id < 0) {
625: for (id = 0; id < ESP_MAX_DEVS; id++) {
1.1.1.7 ! root 626: if (id == (s->rregs[ESP_CFG1] & 0x7))
! 627: continue;
1.1.1.5 root 628: if (s->scsi_dev[id] == NULL)
629: break;
630: }
631: }
632: if (id >= ESP_MAX_DEVS) {
633: DPRINTF("Bad Device ID %d\n", id);
634: return;
635: }
636: if (s->scsi_dev[id]) {
637: DPRINTF("Destroying device %d\n", id);
1.1.1.6 root 638: s->scsi_dev[id]->destroy(s->scsi_dev[id]);
1.1.1.5 root 639: }
640: DPRINTF("Attaching block device %d\n", id);
641: /* Command queueing is not implemented. */
1.1.1.6 root 642: s->scsi_dev[id] = scsi_generic_init(bd, 0, esp_command_complete, s);
643: if (s->scsi_dev[id] == NULL)
644: s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
1.1.1.5 root 645: }
646:
1.1.1.7 ! root 647: void *esp_init(target_phys_addr_t espaddr, int it_shift,
! 648: espdma_memory_read_write dma_memory_read,
! 649: espdma_memory_read_write dma_memory_write,
1.1.1.6 root 650: void *dma_opaque, qemu_irq irq, qemu_irq *reset)
1.1 root 651: {
652: ESPState *s;
1.1.1.5 root 653: int esp_io_memory;
1.1 root 654:
655: s = qemu_mallocz(sizeof(ESPState));
656:
1.1.1.6 root 657: s->irq = irq;
1.1.1.7 ! root 658: s->it_shift = it_shift;
! 659: s->dma_memory_read = dma_memory_read;
! 660: s->dma_memory_write = dma_memory_write;
1.1.1.5 root 661: s->dma_opaque = dma_opaque;
1.1 root 662:
663: esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
1.1.1.7 ! root 664: cpu_register_physical_memory(espaddr, ESP_REGS << it_shift, esp_io_memory);
1.1 root 665:
666: esp_reset(s);
667:
1.1.1.6 root 668: register_savevm("esp", espaddr, 3, esp_save, esp_load, s);
1.1 root 669: qemu_register_reset(esp_reset, s);
670:
1.1.1.6 root 671: *reset = *qemu_allocate_irqs(parent_esp_reset, s, 1);
672:
1.1.1.5 root 673: return s;
674: }
unix.superglobalmegacorp.com