1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24: #include "hw.h"
25: #include "block.h"
26: #include "scsi-disk.h"
27: #include "sun4m.h"
28:
29: #include "sysemu.h"
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42: #ifdef DEBUG_ESP
43: #define DPRINTF(fmt, args...) \
44: do { printf("ESP: " fmt , ##args); } while (0)
45: #else
46: #define DPRINTF(fmt, args...)
47: #endif
48:
49: #define ESP_MASK 0x3f
50: #define ESP_REGS 16
51: #define ESP_SIZE (ESP_REGS * 4)
52: #define TI_BUFSZ 32
53:
54: typedef struct ESPState ESPState;
55:
56: struct ESPState {
57: qemu_irq irq;
58: uint8_t rregs[ESP_REGS];
59: uint8_t wregs[ESP_REGS];
60: int32_t ti_size;
61: uint32_t ti_rptr, ti_wptr;
62: uint8_t ti_buf[TI_BUFSZ];
63: int sense;
64: int dma;
65: SCSIDevice *scsi_dev[ESP_MAX_DEVS];
66: SCSIDevice *current_dev;
67: uint8_t cmdbuf[TI_BUFSZ];
68: int cmdlen;
69: int do_cmd;
70:
71:
72: uint32_t dma_left;
73:
74:
75: uint32_t dma_counter;
76: uint8_t *async_buf;
77: uint32_t async_len;
78: void *dma_opaque;
79: };
80:
81: #define ESP_TCLO 0x0
82: #define ESP_TCMID 0x1
83: #define ESP_FIFO 0x2
84: #define ESP_CMD 0x3
85: #define ESP_RSTAT 0x4
86: #define ESP_WBUSID 0x4
87: #define ESP_RINTR 0x5
88: #define ESP_WSEL 0x5
89: #define ESP_RSEQ 0x6
90: #define ESP_WSYNTP 0x6
91: #define ESP_RFLAGS 0x7
92: #define ESP_WSYNO 0x7
93: #define ESP_CFG1 0x8
94: #define ESP_RRES1 0x9
95: #define ESP_WCCF 0x9
96: #define ESP_RRES2 0xa
97: #define ESP_WTEST 0xa
98: #define ESP_CFG2 0xb
99: #define ESP_CFG3 0xc
100: #define ESP_RES3 0xd
101: #define ESP_TCHI 0xe
102: #define ESP_RES4 0xf
103:
104: #define CMD_DMA 0x80
105: #define CMD_CMD 0x7f
106:
107: #define CMD_NOP 0x00
108: #define CMD_FLUSH 0x01
109: #define CMD_RESET 0x02
110: #define CMD_BUSRESET 0x03
111: #define CMD_TI 0x10
112: #define CMD_ICCS 0x11
113: #define CMD_MSGACC 0x12
114: #define CMD_SATN 0x1a
115: #define CMD_SELATN 0x42
116: #define CMD_SELATNS 0x43
117: #define CMD_ENSEL 0x44
118:
119: #define STAT_DO 0x00
120: #define STAT_DI 0x01
121: #define STAT_CD 0x02
122: #define STAT_ST 0x03
123: #define STAT_MI 0x06
124: #define STAT_MO 0x07
125: #define STAT_PIO_MASK 0x06
126:
127: #define STAT_TC 0x10
128: #define STAT_PE 0x20
129: #define STAT_GE 0x40
130: #define STAT_IN 0x80
131:
132: #define INTR_FC 0x08
133: #define INTR_BS 0x10
134: #define INTR_DC 0x20
135: #define INTR_RST 0x80
136:
137: #define SEQ_0 0x0
138: #define SEQ_CD 0x4
139:
140: #define CFG1_RESREPT 0x40
141:
142: #define CFG2_MASK 0x15
143:
144: #define TCHI_FAS100A 0x4
145:
146: static int get_cmd(ESPState *s, uint8_t *buf)
147: {
148: uint32_t dmalen;
149: int target;
150:
151: dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
152: target = s->wregs[ESP_WBUSID] & 7;
153: DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
154: if (s->dma) {
155: espdma_memory_read(s->dma_opaque, buf, dmalen);
156: } else {
157: buf[0] = 0;
158: memcpy(&buf[1], s->ti_buf, dmalen);
159: dmalen++;
160: }
161:
162: s->ti_size = 0;
163: s->ti_rptr = 0;
164: s->ti_wptr = 0;
165:
166: if (s->current_dev) {
167:
168: s->current_dev->cancel_io(s->current_dev, 0);
169: s->async_len = 0;
170: }
171:
172: if (target >= ESP_MAX_DEVS || !s->scsi_dev[target]) {
173:
174: s->rregs[ESP_RSTAT] = STAT_IN;
175: s->rregs[ESP_RINTR] = INTR_DC;
176: s->rregs[ESP_RSEQ] = SEQ_0;
177: qemu_irq_raise(s->irq);
178: return 0;
179: }
180: s->current_dev = s->scsi_dev[target];
181: return dmalen;
182: }
183:
184: static void do_cmd(ESPState *s, uint8_t *buf)
185: {
186: int32_t datalen;
187: int lun;
188:
189: DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
190: lun = buf[0] & 7;
191: datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
192: s->ti_size = datalen;
193: if (datalen != 0) {
194: s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC;
195: s->dma_left = 0;
196: s->dma_counter = 0;
197: if (datalen > 0) {
198: s->rregs[ESP_RSTAT] |= STAT_DI;
199: s->current_dev->read_data(s->current_dev, 0);
200: } else {
201: s->rregs[ESP_RSTAT] |= STAT_DO;
202: s->current_dev->write_data(s->current_dev, 0);
203: }
204: }
205: s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
206: s->rregs[ESP_RSEQ] = SEQ_CD;
207: qemu_irq_raise(s->irq);
208: }
209:
210: static void handle_satn(ESPState *s)
211: {
212: uint8_t buf[32];
213: int len;
214:
215: len = get_cmd(s, buf);
216: if (len)
217: do_cmd(s, buf);
218: }
219:
220: static void handle_satn_stop(ESPState *s)
221: {
222: s->cmdlen = get_cmd(s, s->cmdbuf);
223: if (s->cmdlen) {
224: DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
225: s->do_cmd = 1;
226: s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC | STAT_CD;
227: s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
228: s->rregs[ESP_RSEQ] = SEQ_CD;
229: qemu_irq_raise(s->irq);
230: }
231: }
232:
233: static void write_response(ESPState *s)
234: {
235: DPRINTF("Transfer status (sense=%d)\n", s->sense);
236: s->ti_buf[0] = s->sense;
237: s->ti_buf[1] = 0;
238: if (s->dma) {
239: espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
240: s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC | STAT_ST;
241: s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
242: s->rregs[ESP_RSEQ] = SEQ_CD;
243: } else {
244: s->ti_size = 2;
245: s->ti_rptr = 0;
246: s->ti_wptr = 0;
247: s->rregs[ESP_RFLAGS] = 2;
248: }
249: qemu_irq_raise(s->irq);
250: }
251:
252: static void esp_dma_done(ESPState *s)
253: {
254: s->rregs[ESP_RSTAT] |= STAT_IN | STAT_TC;
255: s->rregs[ESP_RINTR] = INTR_BS;
256: s->rregs[ESP_RSEQ] = 0;
257: s->rregs[ESP_RFLAGS] = 0;
258: s->rregs[ESP_TCLO] = 0;
259: s->rregs[ESP_TCMID] = 0;
260: qemu_irq_raise(s->irq);
261: }
262:
263: static void esp_do_dma(ESPState *s)
264: {
265: uint32_t len;
266: int to_device;
267:
268: to_device = (s->ti_size < 0);
269: len = s->dma_left;
270: if (s->do_cmd) {
271: DPRINTF("command len %d + %d\n", s->cmdlen, len);
272: espdma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
273: s->ti_size = 0;
274: s->cmdlen = 0;
275: s->do_cmd = 0;
276: do_cmd(s, s->cmdbuf);
277: return;
278: }
279: if (s->async_len == 0) {
280:
281: return;
282: }
283: if (len > s->async_len) {
284: len = s->async_len;
285: }
286: if (to_device) {
287: espdma_memory_read(s->dma_opaque, s->async_buf, len);
288: } else {
289: espdma_memory_write(s->dma_opaque, s->async_buf, len);
290: }
291: s->dma_left -= len;
292: s->async_buf += len;
293: s->async_len -= len;
294: if (to_device)
295: s->ti_size += len;
296: else
297: s->ti_size -= len;
298: if (s->async_len == 0) {
299: if (to_device) {
300:
301: s->current_dev->write_data(s->current_dev, 0);
302: } else {
303: s->current_dev->read_data(s->current_dev, 0);
304:
305:
306:
307: if (s->dma_left == 0 && s->ti_size > 0) {
308: esp_dma_done(s);
309: }
310: }
311: } else {
312:
313: esp_dma_done(s);
314: }
315: }
316:
317: static void esp_command_complete(void *opaque, int reason, uint32_t tag,
318: uint32_t arg)
319: {
320: ESPState *s = (ESPState *)opaque;
321:
322: if (reason == SCSI_REASON_DONE) {
323: DPRINTF("SCSI Command complete\n");
324: if (s->ti_size != 0)
325: DPRINTF("SCSI command completed unexpectedly\n");
326: s->ti_size = 0;
327: s->dma_left = 0;
328: s->async_len = 0;
329: if (arg)
330: DPRINTF("Command failed\n");
331: s->sense = arg;
332: s->rregs[ESP_RSTAT] = STAT_ST;
333: esp_dma_done(s);
334: s->current_dev = NULL;
335: } else {
336: DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
337: s->async_len = arg;
338: s->async_buf = s->current_dev->get_buf(s->current_dev, 0);
339: if (s->dma_left) {
340: esp_do_dma(s);
341: } else if (s->dma_counter != 0 && s->ti_size <= 0) {
342:
343:
344: esp_dma_done(s);
345: }
346: }
347: }
348:
349: static void handle_ti(ESPState *s)
350: {
351: uint32_t dmalen, minlen;
352:
353: dmalen = s->rregs[ESP_TCLO] | (s->rregs[ESP_TCMID] << 8);
354: if (dmalen==0) {
355: dmalen=0x10000;
356: }
357: s->dma_counter = dmalen;
358:
359: if (s->do_cmd)
360: minlen = (dmalen < 32) ? dmalen : 32;
361: else if (s->ti_size < 0)
362: minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
363: else
364: minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
365: DPRINTF("Transfer Information len %d\n", minlen);
366: if (s->dma) {
367: s->dma_left = minlen;
368: s->rregs[ESP_RSTAT] &= ~STAT_TC;
369: esp_do_dma(s);
370: } else if (s->do_cmd) {
371: DPRINTF("command len %d\n", s->cmdlen);
372: s->ti_size = 0;
373: s->cmdlen = 0;
374: s->do_cmd = 0;
375: do_cmd(s, s->cmdbuf);
376: return;
377: }
378: }
379:
380: static void esp_reset(void *opaque)
381: {
382: ESPState *s = opaque;
383:
384: memset(s->rregs, 0, ESP_REGS);
385: memset(s->wregs, 0, ESP_REGS);
386: s->rregs[ESP_TCHI] = TCHI_FAS100A;
387: s->ti_size = 0;
388: s->ti_rptr = 0;
389: s->ti_wptr = 0;
390: s->dma = 0;
391: s->do_cmd = 0;
392: }
393:
394: static void parent_esp_reset(void *opaque, int irq, int level)
395: {
396: if (level)
397: esp_reset(opaque);
398: }
399:
400: static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
401: {
402: ESPState *s = opaque;
403: uint32_t saddr;
404:
405: saddr = (addr & ESP_MASK) >> 2;
406: DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
407: switch (saddr) {
408: case ESP_FIFO:
409: if (s->ti_size > 0) {
410: s->ti_size--;
411: if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
412:
413: fprintf(stderr, "esp: PIO data read not implemented\n");
414: s->rregs[ESP_FIFO] = 0;
415: } else {
416: s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
417: }
418: qemu_irq_raise(s->irq);
419: }
420: if (s->ti_size == 0) {
421: s->ti_rptr = 0;
422: s->ti_wptr = 0;
423: }
424: break;
425: case ESP_RINTR:
426:
427: s->rregs[ESP_RSTAT] &= ~(STAT_IN | STAT_GE | STAT_PE);
428: qemu_irq_lower(s->irq);
429: break;
430: default:
431: break;
432: }
433: return s->rregs[saddr];
434: }
435:
436: static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
437: {
438: ESPState *s = opaque;
439: uint32_t saddr;
440:
441: saddr = (addr & ESP_MASK) >> 2;
442: DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr],
443: val);
444: switch (saddr) {
445: case ESP_TCLO:
446: case ESP_TCMID:
447: s->rregs[ESP_RSTAT] &= ~STAT_TC;
448: break;
449: case ESP_FIFO:
450: if (s->do_cmd) {
451: s->cmdbuf[s->cmdlen++] = val & 0xff;
452: } else if ((s->rregs[ESP_RSTAT] & STAT_PIO_MASK) == 0) {
453: uint8_t buf;
454: buf = val & 0xff;
455: s->ti_size--;
456: fprintf(stderr, "esp: PIO data write not implemented\n");
457: } else {
458: s->ti_size++;
459: s->ti_buf[s->ti_wptr++] = val & 0xff;
460: }
461: break;
462: case ESP_CMD:
463: s->rregs[saddr] = val;
464: if (val & CMD_DMA) {
465: s->dma = 1;
466:
467: s->rregs[ESP_TCLO] = s->wregs[ESP_TCLO];
468: s->rregs[ESP_TCMID] = s->wregs[ESP_TCMID];
469: } else {
470: s->dma = 0;
471: }
472: switch(val & CMD_CMD) {
473: case CMD_NOP:
474: DPRINTF("NOP (%2.2x)\n", val);
475: break;
476: case CMD_FLUSH:
477: DPRINTF("Flush FIFO (%2.2x)\n", val);
478:
479: s->rregs[ESP_RINTR] = INTR_FC;
480: s->rregs[ESP_RSEQ] = 0;
481: break;
482: case CMD_RESET:
483: DPRINTF("Chip reset (%2.2x)\n", val);
484: esp_reset(s);
485: break;
486: case CMD_BUSRESET:
487: DPRINTF("Bus reset (%2.2x)\n", val);
488: s->rregs[ESP_RINTR] = INTR_RST;
489: if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
490: qemu_irq_raise(s->irq);
491: }
492: break;
493: case CMD_TI:
494: handle_ti(s);
495: break;
496: case CMD_ICCS:
497: DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
498: write_response(s);
499: break;
500: case CMD_MSGACC:
501: DPRINTF("Message Accepted (%2.2x)\n", val);
502: write_response(s);
503: s->rregs[ESP_RINTR] = INTR_DC;
504: s->rregs[ESP_RSEQ] = 0;
505: break;
506: case CMD_SATN:
507: DPRINTF("Set ATN (%2.2x)\n", val);
508: break;
509: case CMD_SELATN:
510: DPRINTF("Set ATN (%2.2x)\n", val);
511: handle_satn(s);
512: break;
513: case CMD_SELATNS:
514: DPRINTF("Set ATN & stop (%2.2x)\n", val);
515: handle_satn_stop(s);
516: break;
517: case CMD_ENSEL:
518: DPRINTF("Enable selection (%2.2x)\n", val);
519: break;
520: default:
521: DPRINTF("Unhandled ESP command (%2.2x)\n", val);
522: break;
523: }
524: break;
525: case ESP_WBUSID ... ESP_WSYNO:
526: break;
527: case ESP_CFG1:
528: s->rregs[saddr] = val;
529: break;
530: case ESP_WCCF ... ESP_WTEST:
531: break;
532: case ESP_CFG2:
533: s->rregs[saddr] = val & CFG2_MASK;
534: break;
535: case ESP_CFG3 ... ESP_RES4:
536: s->rregs[saddr] = val;
537: break;
538: default:
539: break;
540: }
541: s->wregs[saddr] = val;
542: }
543:
544: static CPUReadMemoryFunc *esp_mem_read[3] = {
545: esp_mem_readb,
546: NULL,
547: NULL,
548: };
549:
550: static CPUWriteMemoryFunc *esp_mem_write[3] = {
551: esp_mem_writeb,
552: NULL,
553: NULL,
554: };
555:
556: static void esp_save(QEMUFile *f, void *opaque)
557: {
558: ESPState *s = opaque;
559:
560: qemu_put_buffer(f, s->rregs, ESP_REGS);
561: qemu_put_buffer(f, s->wregs, ESP_REGS);
562: qemu_put_be32s(f, &s->ti_size);
563: qemu_put_be32s(f, &s->ti_rptr);
564: qemu_put_be32s(f, &s->ti_wptr);
565: qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
566: qemu_put_be32s(f, &s->sense);
567: qemu_put_be32s(f, &s->dma);
568: qemu_put_buffer(f, s->cmdbuf, TI_BUFSZ);