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