Annotation of qemu/hw/esp.c, revision 1.1.1.12
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.12! root 64: uint32_t status;
1.1.1.7 root 65: uint32_t dma;
1.1.1.9 root 66: SCSIBus bus;
1.1.1.4 root 67: SCSIDevice *current_dev;
1.1.1.12! root 68: SCSIRequest *current_req;
1.1.1.4 root 69: uint8_t cmdbuf[TI_BUFSZ];
1.1.1.7 root 70: uint32_t cmdlen;
71: uint32_t do_cmd;
1.1.1.5 root 72:
73: /* The amount of data left in the current DMA transfer. */
74: uint32_t dma_left;
75: /* The size of the current DMA transfer. Zero if no transfer is in
76: progress. */
77: uint32_t dma_counter;
78: uint8_t *async_buf;
79: uint32_t async_len;
1.1.1.7 root 80:
1.1.1.10 root 81: ESPDMAMemoryReadWriteFunc dma_memory_read;
82: ESPDMAMemoryReadWriteFunc dma_memory_write;
1.1.1.5 root 83: void *dma_opaque;
1.1.1.11 root 84: int dma_enabled;
85: void (*dma_cb)(ESPState *s);
1.1.1.3 root 86: };
1.1 root 87:
1.1.1.6 root 88: #define ESP_TCLO 0x0
89: #define ESP_TCMID 0x1
90: #define ESP_FIFO 0x2
91: #define ESP_CMD 0x3
92: #define ESP_RSTAT 0x4
93: #define ESP_WBUSID 0x4
94: #define ESP_RINTR 0x5
95: #define ESP_WSEL 0x5
96: #define ESP_RSEQ 0x6
97: #define ESP_WSYNTP 0x6
98: #define ESP_RFLAGS 0x7
99: #define ESP_WSYNO 0x7
100: #define ESP_CFG1 0x8
101: #define ESP_RRES1 0x9
102: #define ESP_WCCF 0x9
103: #define ESP_RRES2 0xa
104: #define ESP_WTEST 0xa
105: #define ESP_CFG2 0xb
106: #define ESP_CFG3 0xc
107: #define ESP_RES3 0xd
108: #define ESP_TCHI 0xe
109: #define ESP_RES4 0xf
110:
111: #define CMD_DMA 0x80
112: #define CMD_CMD 0x7f
113:
114: #define CMD_NOP 0x00
115: #define CMD_FLUSH 0x01
116: #define CMD_RESET 0x02
117: #define CMD_BUSRESET 0x03
118: #define CMD_TI 0x10
119: #define CMD_ICCS 0x11
120: #define CMD_MSGACC 0x12
1.1.1.9 root 121: #define CMD_PAD 0x18
1.1.1.6 root 122: #define CMD_SATN 0x1a
1.1.1.9 root 123: #define CMD_SEL 0x41
1.1.1.6 root 124: #define CMD_SELATN 0x42
125: #define CMD_SELATNS 0x43
126: #define CMD_ENSEL 0x44
127:
1.1 root 128: #define STAT_DO 0x00
129: #define STAT_DI 0x01
130: #define STAT_CD 0x02
131: #define STAT_ST 0x03
1.1.1.7 root 132: #define STAT_MO 0x06
133: #define STAT_MI 0x07
1.1.1.6 root 134: #define STAT_PIO_MASK 0x06
1.1 root 135:
136: #define STAT_TC 0x10
1.1.1.5 root 137: #define STAT_PE 0x20
138: #define STAT_GE 0x40
1.1.1.7 root 139: #define STAT_INT 0x80
140:
141: #define BUSID_DID 0x07
1.1 root 142:
143: #define INTR_FC 0x08
144: #define INTR_BS 0x10
145: #define INTR_DC 0x20
1.1.1.2 root 146: #define INTR_RST 0x80
1.1 root 147:
148: #define SEQ_0 0x0
149: #define SEQ_CD 0x4
150:
1.1.1.6 root 151: #define CFG1_RESREPT 0x40
152:
153: #define TCHI_FAS100A 0x4
154:
1.1.1.7 root 155: static void esp_raise_irq(ESPState *s)
156: {
157: if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
158: s->rregs[ESP_RSTAT] |= STAT_INT;
159: qemu_irq_raise(s->irq);
1.1.1.10 root 160: DPRINTF("Raise IRQ\n");
1.1.1.7 root 161: }
162: }
163:
164: static void esp_lower_irq(ESPState *s)
165: {
166: if (s->rregs[ESP_RSTAT] & STAT_INT) {
167: s->rregs[ESP_RSTAT] &= ~STAT_INT;
168: qemu_irq_lower(s->irq);
1.1.1.10 root 169: DPRINTF("Lower IRQ\n");
1.1.1.7 root 170: }
171: }
172:
1.1.1.11 root 173: static void esp_dma_enable(void *opaque, int irq, int level)
174: {
175: DeviceState *d = opaque;
176: ESPState *s = container_of(d, ESPState, busdev.qdev);
177:
178: if (level) {
179: s->dma_enabled = 1;
180: DPRINTF("Raise enable\n");
181: if (s->dma_cb) {
182: s->dma_cb(s);
183: s->dma_cb = NULL;
184: }
185: } else {
186: DPRINTF("Lower enable\n");
187: s->dma_enabled = 0;
188: }
189: }
190:
1.1.1.12! root 191: static void esp_request_cancelled(SCSIRequest *req)
! 192: {
! 193: ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
! 194:
! 195: if (req == s->current_req) {
! 196: scsi_req_unref(s->current_req);
! 197: s->current_req = NULL;
! 198: s->current_dev = NULL;
! 199: }
! 200: }
! 201:
1.1.1.7 root 202: static uint32_t get_cmd(ESPState *s, uint8_t *buf)
1.1 root 203: {
1.1.1.5 root 204: uint32_t dmalen;
1.1 root 205: int target;
206:
1.1.1.7 root 207: target = s->wregs[ESP_WBUSID] & BUSID_DID;
1.1.1.2 root 208: if (s->dma) {
1.1.1.7 root 209: dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
210: s->dma_memory_read(s->dma_opaque, buf, dmalen);
1.1.1.2 root 211: } else {
1.1.1.7 root 212: dmalen = s->ti_size;
213: memcpy(buf, s->ti_buf, dmalen);
1.1.1.12! root 214: buf[0] = buf[2] >> 5;
1.1.1.2 root 215: }
1.1.1.7 root 216: DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
1.1.1.4 root 217:
1.1 root 218: s->ti_size = 0;
1.1.1.2 root 219: s->ti_rptr = 0;
220: s->ti_wptr = 0;
1.1 root 221:
1.1.1.12! root 222: if (s->current_req) {
1.1.1.5 root 223: /* Started a new command before the old one finished. Cancel it. */
1.1.1.12! root 224: scsi_req_cancel(s->current_req);
1.1.1.5 root 225: s->async_len = 0;
226: }
227:
1.1.1.9 root 228: if (target >= ESP_MAX_DEVS || !s->bus.devs[target]) {
1.1.1.4 root 229: // No such drive
1.1.1.7 root 230: s->rregs[ESP_RSTAT] = 0;
1.1.1.6 root 231: s->rregs[ESP_RINTR] = INTR_DC;
232: s->rregs[ESP_RSEQ] = SEQ_0;
1.1.1.7 root 233: esp_raise_irq(s);
1.1.1.6 root 234: return 0;
1.1 root 235: }
1.1.1.9 root 236: s->current_dev = s->bus.devs[target];
1.1.1.4 root 237: return dmalen;
238: }
239:
1.1.1.9 root 240: static void do_busid_cmd(ESPState *s, uint8_t *buf, uint8_t busid)
1.1.1.4 root 241: {
242: int32_t datalen;
243: int lun;
244:
1.1.1.9 root 245: DPRINTF("do_busid_cmd: busid 0x%x\n", busid);
246: lun = busid & 7;
1.1.1.12! root 247: s->current_req = scsi_req_new(s->current_dev, 0, lun, NULL);
! 248: datalen = scsi_req_enqueue(s->current_req, buf);
1.1.1.5 root 249: s->ti_size = datalen;
250: if (datalen != 0) {
1.1.1.7 root 251: s->rregs[ESP_RSTAT] = STAT_TC;
1.1.1.5 root 252: s->dma_left = 0;
253: s->dma_counter = 0;
1.1.1.4 root 254: if (datalen > 0) {
1.1.1.6 root 255: s->rregs[ESP_RSTAT] |= STAT_DI;
1.1.1.4 root 256: } else {
1.1.1.6 root 257: s->rregs[ESP_RSTAT] |= STAT_DO;
1.1.1.2 root 258: }
1.1.1.12! root 259: scsi_req_continue(s->current_req);
1.1 root 260: }
1.1.1.6 root 261: s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
262: s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7 root 263: esp_raise_irq(s);
1.1 root 264: }
265:
1.1.1.9 root 266: static void do_cmd(ESPState *s, uint8_t *buf)
267: {
268: uint8_t busid = buf[0];
269:
270: do_busid_cmd(s, &buf[1], busid);
271: }
272:
1.1.1.4 root 273: static void handle_satn(ESPState *s)
274: {
275: uint8_t buf[32];
276: int len;
277:
1.1.1.11 root 278: if (!s->dma_enabled) {
279: s->dma_cb = handle_satn;
280: return;
281: }
1.1.1.4 root 282: len = get_cmd(s, buf);
283: if (len)
284: do_cmd(s, buf);
285: }
286:
1.1.1.9 root 287: static void handle_s_without_atn(ESPState *s)
288: {
289: uint8_t buf[32];
290: int len;
291:
1.1.1.11 root 292: if (!s->dma_enabled) {
293: s->dma_cb = handle_s_without_atn;
294: return;
295: }
1.1.1.9 root 296: len = get_cmd(s, buf);
297: if (len) {
298: do_busid_cmd(s, buf, 0);
299: }
300: }
301:
1.1.1.4 root 302: static void handle_satn_stop(ESPState *s)
1.1 root 303: {
1.1.1.11 root 304: if (!s->dma_enabled) {
305: s->dma_cb = handle_satn_stop;
306: return;
307: }
1.1.1.4 root 308: s->cmdlen = get_cmd(s, s->cmdbuf);
309: if (s->cmdlen) {
310: DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
311: s->do_cmd = 1;
1.1.1.7 root 312: s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
1.1.1.6 root 313: s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
314: s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7 root 315: esp_raise_irq(s);
1.1.1.4 root 316: }
317: }
1.1 root 318:
1.1.1.4 root 319: static void write_response(ESPState *s)
320: {
1.1.1.12! root 321: DPRINTF("Transfer status (status=%d)\n", s->status);
! 322: s->ti_buf[0] = s->status;
1.1.1.4 root 323: s->ti_buf[1] = 0;
1.1.1.2 root 324: if (s->dma) {
1.1.1.7 root 325: s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
326: s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
1.1.1.6 root 327: s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
328: s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.2 root 329: } else {
1.1.1.6 root 330: s->ti_size = 2;
331: s->ti_rptr = 0;
332: s->ti_wptr = 0;
333: s->rregs[ESP_RFLAGS] = 2;
1.1.1.2 root 334: }
1.1.1.7 root 335: esp_raise_irq(s);
1.1.1.5 root 336: }
1.1 root 337:
1.1.1.5 root 338: static void esp_dma_done(ESPState *s)
339: {
1.1.1.7 root 340: s->rregs[ESP_RSTAT] |= STAT_TC;
1.1.1.6 root 341: s->rregs[ESP_RINTR] = INTR_BS;
342: s->rregs[ESP_RSEQ] = 0;
343: s->rregs[ESP_RFLAGS] = 0;
344: s->rregs[ESP_TCLO] = 0;
345: s->rregs[ESP_TCMID] = 0;
1.1.1.7 root 346: esp_raise_irq(s);
1.1 root 347: }
1.1.1.2 root 348:
1.1.1.5 root 349: static void esp_do_dma(ESPState *s)
350: {
351: uint32_t len;
352: int to_device;
353:
354: to_device = (s->ti_size < 0);
355: len = s->dma_left;
356: if (s->do_cmd) {
357: DPRINTF("command len %d + %d\n", s->cmdlen, len);
1.1.1.7 root 358: s->dma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
1.1.1.5 root 359: s->ti_size = 0;
360: s->cmdlen = 0;
361: s->do_cmd = 0;
362: do_cmd(s, s->cmdbuf);
363: return;
364: }
365: if (s->async_len == 0) {
366: /* Defer until data is available. */
367: return;
368: }
369: if (len > s->async_len) {
370: len = s->async_len;
371: }
372: if (to_device) {
1.1.1.7 root 373: s->dma_memory_read(s->dma_opaque, s->async_buf, len);
1.1.1.5 root 374: } else {
1.1.1.7 root 375: s->dma_memory_write(s->dma_opaque, s->async_buf, len);
1.1.1.5 root 376: }
377: s->dma_left -= len;
378: s->async_buf += len;
379: s->async_len -= len;
380: if (to_device)
381: s->ti_size += len;
382: else
383: s->ti_size -= len;
384: if (s->async_len == 0) {
1.1.1.12! root 385: scsi_req_continue(s->current_req);
! 386: /* If there is still data to be read from the device then
! 387: complete the DMA operation immediately. Otherwise defer
! 388: until the scsi layer has completed. */
! 389: if (to_device || s->dma_left != 0 || s->ti_size == 0) {
! 390: return;
1.1.1.5 root 391: }
392: }
1.1.1.12! root 393:
! 394: /* Partially filled a scsi buffer. Complete immediately. */
! 395: esp_dma_done(s);
1.1.1.5 root 396: }
397:
1.1.1.12! root 398: static void esp_command_complete(SCSIRequest *req, uint32_t status)
1.1.1.4 root 399: {
1.1.1.12! root 400: ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
1.1.1.4 root 401:
1.1.1.12! root 402: DPRINTF("SCSI Command complete\n");
! 403: if (s->ti_size != 0) {
! 404: DPRINTF("SCSI command completed unexpectedly\n");
! 405: }
! 406: s->ti_size = 0;
! 407: s->dma_left = 0;
! 408: s->async_len = 0;
! 409: if (status) {
! 410: DPRINTF("Command failed\n");
! 411: }
! 412: s->status = status;
! 413: s->rregs[ESP_RSTAT] = STAT_ST;
! 414: esp_dma_done(s);
! 415: if (s->current_req) {
! 416: scsi_req_unref(s->current_req);
! 417: s->current_req = NULL;
1.1.1.5 root 418: s->current_dev = NULL;
1.1.1.12! root 419: }
! 420: }
! 421:
! 422: static void esp_transfer_data(SCSIRequest *req, uint32_t len)
! 423: {
! 424: ESPState *s = DO_UPCAST(ESPState, busdev.qdev, req->bus->qbus.parent);
! 425:
! 426: DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
! 427: s->async_len = len;
! 428: s->async_buf = scsi_req_get_buf(req);
! 429: if (s->dma_left) {
! 430: esp_do_dma(s);
! 431: } else if (s->dma_counter != 0 && s->ti_size <= 0) {
! 432: /* If this was the last part of a DMA transfer then the
! 433: completion interrupt is deferred to here. */
! 434: esp_dma_done(s);
1.1.1.5 root 435: }
1.1.1.4 root 436: }
1.1 root 437:
438: static void handle_ti(ESPState *s)
439: {
1.1.1.5 root 440: uint32_t dmalen, minlen;
1.1 root 441:
1.1.1.6 root 442: dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
1.1.1.4 root 443: if (dmalen==0) {
444: dmalen=0x10000;
445: }
1.1.1.5 root 446: s->dma_counter = dmalen;
1.1.1.4 root 447:
448: if (s->do_cmd)
449: minlen = (dmalen < 32) ? dmalen : 32;
1.1.1.5 root 450: else if (s->ti_size < 0)
451: minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
1.1.1.4 root 452: else
453: minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
454: DPRINTF("Transfer Information len %d\n", minlen);
1.1.1.2 root 455: if (s->dma) {
1.1.1.5 root 456: s->dma_left = minlen;
1.1.1.6 root 457: s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.5 root 458: esp_do_dma(s);
1.1.1.4 root 459: } else if (s->do_cmd) {
460: DPRINTF("command len %d\n", s->cmdlen);
461: s->ti_size = 0;
462: s->cmdlen = 0;
463: s->do_cmd = 0;
464: do_cmd(s, s->cmdbuf);
465: return;
466: }
1.1 root 467: }
468:
1.1.1.10 root 469: static void esp_hard_reset(DeviceState *d)
1.1 root 470: {
1.1.1.9 root 471: ESPState *s = container_of(d, ESPState, busdev.qdev);
1.1.1.5 root 472:
1.1.1.6 root 473: memset(s->rregs, 0, ESP_REGS);
474: memset(s->wregs, 0, ESP_REGS);
475: s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
1.1.1.3 root 476: s->ti_size = 0;
477: s->ti_rptr = 0;
478: s->ti_wptr = 0;
479: s->dma = 0;
1.1.1.4 root 480: s->do_cmd = 0;
1.1.1.11 root 481: s->dma_cb = NULL;
1.1.1.7 root 482:
483: s->rregs[ESP_CFG1] = 7;
1.1 root 484: }
485:
1.1.1.10 root 486: static void esp_soft_reset(DeviceState *d)
487: {
488: ESPState *s = container_of(d, ESPState, busdev.qdev);
489:
490: qemu_irq_lower(s->irq);
491: esp_hard_reset(d);
492: }
493:
1.1.1.6 root 494: static void parent_esp_reset(void *opaque, int irq, int level)
495: {
1.1.1.10 root 496: if (level) {
497: esp_soft_reset(opaque);
498: }
1.1.1.6 root 499: }
500:
1.1.1.11 root 501: static void esp_gpio_demux(void *opaque, int irq, int level)
502: {
503: switch (irq) {
504: case 0:
505: parent_esp_reset(opaque, irq, level);
506: break;
507: case 1:
508: esp_dma_enable(opaque, irq, level);
509: break;
510: }
511: }
512:
1.1 root 513: static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
514: {
515: ESPState *s = opaque;
1.1.1.8 root 516: uint32_t saddr, old_val;
1.1 root 517:
1.1.1.7 root 518: saddr = addr >> s->it_shift;
1.1.1.2 root 519: DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
1.1 root 520: switch (saddr) {
1.1.1.6 root 521: case ESP_FIFO:
522: if (s->ti_size > 0) {
523: s->ti_size--;
524: if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
1.1.1.7 root 525: /* Data out. */
526: ESP_ERROR("PIO data read not implemented\n");
1.1.1.6 root 527: s->rregs[ESP_FIFO] = 0;
1.1.1.4 root 528: } else {
1.1.1.6 root 529: s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
1.1.1.4 root 530: }
1.1.1.7 root 531: esp_raise_irq(s);
1.1.1.6 root 532: }
533: if (s->ti_size == 0) {
1.1.1.2 root 534: s->ti_rptr = 0;
535: s->ti_wptr = 0;
536: }
1.1.1.6 root 537: break;
538: case ESP_RINTR:
1.1.1.8 root 539: /* Clear sequence step, interrupt register and all status bits
540: except TC */
541: old_val = s->rregs[ESP_RINTR];
542: s->rregs[ESP_RINTR] = 0;
543: s->rregs[ESP_RSTAT] &= ~STAT_TC;
544: s->rregs[ESP_RSEQ] = SEQ_CD;
1.1.1.7 root 545: esp_lower_irq(s);
1.1.1.8 root 546:
547: return old_val;
1.1 root 548: default:
1.1.1.6 root 549: break;
1.1 root 550: }
551: return s->rregs[saddr];
552: }
553:
554: static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
555: {
556: ESPState *s = opaque;
557: uint32_t saddr;
558:
1.1.1.7 root 559: saddr = addr >> s->it_shift;
1.1.1.6 root 560: DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],
561: val);
1.1 root 562: switch (saddr) {
1.1.1.6 root 563: case ESP_TCLO:
564: case ESP_TCMID:
565: s->rregs[ESP_RSTAT] &= ~STAT_TC;
1.1.1.2 root 566: break;
1.1.1.6 root 567: case ESP_FIFO:
1.1.1.4 root 568: if (s->do_cmd) {
569: s->cmdbuf[s->cmdlen++] = val & 0xff;
1.1.1.7 root 570: } else if (s->ti_size == TI_BUFSZ - 1) {
571: ESP_ERROR("fifo overrun\n");
1.1.1.4 root 572: } else {
573: s->ti_size++;
574: s->ti_buf[s->ti_wptr++] = val & 0xff;
575: }
1.1.1.6 root 576: break;
577: case ESP_CMD:
1.1.1.2 root 578: s->rregs[saddr] = val;
1.1.1.6 root 579: if (val & CMD_DMA) {
580: s->dma = 1;
1.1.1.5 root 581: /* Reload DMA counter. */
1.1.1.6 root 582: s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
583: s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
584: } else {
585: s->dma = 0;
586: }
587: switch(val & CMD_CMD) {
588: case CMD_NOP:
589: DPRINTF("NOP (%2.2x)\n", val);
590: break;
591: case CMD_FLUSH:
592: DPRINTF("Flush FIFO (%2.2x)\n", val);
1.1.1.2 root 593: //s->ti_size = 0;
1.1.1.6 root 594: s->rregs[ESP_RINTR] = INTR_FC;
595: s->rregs[ESP_RSEQ] = 0;
1.1.1.7 root 596: s->rregs[ESP_RFLAGS] = 0;
1.1.1.6 root 597: break;
598: case CMD_RESET:
599: DPRINTF("Chip reset (%2.2x)\n", val);
1.1.1.10 root 600: esp_soft_reset(&s->busdev.qdev);
1.1.1.6 root 601: break;
602: case CMD_BUSRESET:
603: DPRINTF("Bus reset (%2.2x)\n", val);
604: s->rregs[ESP_RINTR] = INTR_RST;
605: if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
1.1.1.7 root 606: esp_raise_irq(s);
1.1.1.2 root 607: }
1.1.1.6 root 608: break;
609: case CMD_TI:
610: handle_ti(s);
611: break;
612: case CMD_ICCS:
613: DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
614: write_response(s);
1.1.1.7 root 615: s->rregs[ESP_RINTR] = INTR_FC;
616: s->rregs[ESP_RSTAT] |= STAT_MI;
1.1.1.6 root 617: break;
618: case CMD_MSGACC:
619: DPRINTF("Message Accepted (%2.2x)\n", val);
620: s->rregs[ESP_RINTR] = INTR_DC;
621: s->rregs[ESP_RSEQ] = 0;
1.1.1.9 root 622: s->rregs[ESP_RFLAGS] = 0;
623: esp_raise_irq(s);
624: break;
625: case CMD_PAD:
626: DPRINTF("Transfer padding (%2.2x)\n", val);
627: s->rregs[ESP_RSTAT] = STAT_TC;
628: s->rregs[ESP_RINTR] = INTR_FC;
629: s->rregs[ESP_RSEQ] = 0;
1.1.1.6 root 630: break;
631: case CMD_SATN:
632: DPRINTF("Set ATN (%2.2x)\n", val);
633: break;
1.1.1.9 root 634: case CMD_SEL:
635: DPRINTF("Select without ATN (%2.2x)\n", val);
636: handle_s_without_atn(s);
637: break;
1.1.1.6 root 638: case CMD_SELATN:
1.1.1.9 root 639: DPRINTF("Select with ATN (%2.2x)\n", val);
1.1.1.6 root 640: handle_satn(s);
641: break;
642: case CMD_SELATNS:
1.1.1.9 root 643: DPRINTF("Select with ATN & stop (%2.2x)\n", val);
1.1.1.6 root 644: handle_satn_stop(s);
645: break;
646: case CMD_ENSEL:
647: DPRINTF("Enable selection (%2.2x)\n", val);
1.1.1.7 root 648: s->rregs[ESP_RINTR] = 0;
1.1.1.6 root 649: break;
650: default:
1.1.1.7 root 651: ESP_ERROR("Unhandled ESP command (%2.2x)\n", val);
1.1.1.6 root 652: break;
653: }
654: break;
655: case ESP_WBUSID ... ESP_WSYNO:
656: break;
657: case ESP_CFG1:
1.1.1.2 root 658: s->rregs[saddr] = val;
659: break;
1.1.1.6 root 660: case ESP_WCCF ... ESP_WTEST:
1.1.1.2 root 661: break;
1.1.1.7 root 662: case ESP_CFG2 ... ESP_RES4:
1.1.1.2 root 663: s->rregs[saddr] = val;
664: break;
1.1 root 665: default:
1.1.1.7 root 666: ESP_ERROR("invalid write of 0x%02x at [0x%x]\n", val, saddr);
667: return;
1.1 root 668: }
669: s->wregs[saddr] = val;
670: }
671:
1.1.1.9 root 672: static CPUReadMemoryFunc * const esp_mem_read[3] = {
1.1 root 673: esp_mem_readb,
1.1.1.6 root 674: NULL,
675: NULL,
1.1 root 676: };
677:
1.1.1.9 root 678: static CPUWriteMemoryFunc * const esp_mem_write[3] = {
1.1 root 679: esp_mem_writeb,
1.1.1.6 root 680: NULL,
1.1.1.7 root 681: esp_mem_writeb,
1.1 root 682: };
683:
1.1.1.9 root 684: static const VMStateDescription vmstate_esp = {
685: .name ="esp",
686: .version_id = 3,
687: .minimum_version_id = 3,
688: .minimum_version_id_old = 3,
689: .fields = (VMStateField []) {
690: VMSTATE_BUFFER(rregs, ESPState),
691: VMSTATE_BUFFER(wregs, ESPState),
692: VMSTATE_INT32(ti_size, ESPState),
693: VMSTATE_UINT32(ti_rptr, ESPState),
694: VMSTATE_UINT32(ti_wptr, ESPState),
695: VMSTATE_BUFFER(ti_buf, ESPState),
1.1.1.12! root 696: VMSTATE_UINT32(status, ESPState),
1.1.1.9 root 697: VMSTATE_UINT32(dma, ESPState),
698: VMSTATE_BUFFER(cmdbuf, ESPState),
699: VMSTATE_UINT32(cmdlen, ESPState),
700: VMSTATE_UINT32(do_cmd, ESPState),
701: VMSTATE_UINT32(dma_left, ESPState),
702: VMSTATE_END_OF_LIST()
1.1.1.5 root 703: }
1.1.1.9 root 704: };
1.1.1.5 root 705:
1.1.1.8 root 706: void esp_init(target_phys_addr_t espaddr, int it_shift,
1.1.1.10 root 707: ESPDMAMemoryReadWriteFunc dma_memory_read,
708: ESPDMAMemoryReadWriteFunc dma_memory_write,
1.1.1.11 root 709: void *dma_opaque, qemu_irq irq, qemu_irq *reset,
710: qemu_irq *dma_enable)
1.1.1.8 root 711: {
712: DeviceState *dev;
713: SysBusDevice *s;
714: ESPState *esp;
715:
716: dev = qdev_create(NULL, "esp");
717: esp = DO_UPCAST(ESPState, busdev.qdev, dev);
718: esp->dma_memory_read = dma_memory_read;
719: esp->dma_memory_write = dma_memory_write;
720: esp->dma_opaque = dma_opaque;
721: esp->it_shift = it_shift;
1.1.1.11 root 722: /* XXX for now until rc4030 has been changed to use DMA enable signal */
723: esp->dma_enabled = 1;
1.1.1.9 root 724: qdev_init_nofail(dev);
1.1.1.8 root 725: s = sysbus_from_qdev(dev);
726: sysbus_connect_irq(s, 0, irq);
727: sysbus_mmio_map(s, 0, espaddr);
1.1.1.9 root 728: *reset = qdev_get_gpio_in(dev, 0);
1.1.1.11 root 729: *dma_enable = qdev_get_gpio_in(dev, 1);
1.1.1.8 root 730: }
731:
1.1.1.12! root 732: static const struct SCSIBusOps esp_scsi_ops = {
! 733: .transfer_data = esp_transfer_data,
! 734: .complete = esp_command_complete,
! 735: .cancel = esp_request_cancelled
! 736: };
! 737:
1.1.1.9 root 738: static int esp_init1(SysBusDevice *dev)
1.1 root 739: {
1.1.1.8 root 740: ESPState *s = FROM_SYSBUS(ESPState, dev);
1.1.1.5 root 741: int esp_io_memory;
1.1 root 742:
1.1.1.8 root 743: sysbus_init_irq(dev, &s->irq);
744: assert(s->it_shift != -1);
1.1 root 745:
1.1.1.11 root 746: esp_io_memory = cpu_register_io_memory(esp_mem_read, esp_mem_write, s,
747: DEVICE_NATIVE_ENDIAN);
1.1.1.8 root 748: sysbus_init_mmio(dev, ESP_REGS << s->it_shift, esp_io_memory);
1.1 root 749:
1.1.1.11 root 750: qdev_init_gpio_in(&dev->qdev, esp_gpio_demux, 2);
1.1.1.6 root 751:
1.1.1.12! root 752: scsi_bus_new(&s->bus, &dev->qdev, 0, ESP_MAX_DEVS, &esp_scsi_ops);
1.1.1.10 root 753: return scsi_bus_legacy_handle_cmdline(&s->bus);
1.1.1.5 root 754: }
1.1.1.8 root 755:
1.1.1.9 root 756: static SysBusDeviceInfo esp_info = {
757: .init = esp_init1,
758: .qdev.name = "esp",
759: .qdev.size = sizeof(ESPState),
760: .qdev.vmsd = &vmstate_esp,
1.1.1.10 root 761: .qdev.reset = esp_hard_reset,
1.1.1.9 root 762: .qdev.props = (Property[]) {
763: {.name = NULL}
764: }
765: };
766:
1.1.1.8 root 767: static void esp_register_devices(void)
768: {
1.1.1.9 root 769: sysbus_register_withprop(&esp_info);
1.1.1.8 root 770: }
771:
772: device_init(esp_register_devices)
unix.superglobalmegacorp.com