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