]> git.proxmox.com Git - mirror_qemu.git/blob - hw/esp.c
Fix SCSI cdrom boot, thanks Blue Swirl.
[mirror_qemu.git] / hw / esp.c
1 /*
2 * QEMU ESP/NCR53C9x emulation
3 *
4 * Copyright (c) 2005-2006 Fabrice Bellard
5 *
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 */
24 #include "vl.h"
25
26 /* debug ESP card */
27 //#define DEBUG_ESP
28
29 /*
30 * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O), also
31 * produced as NCR89C100. See
32 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
33 * and
34 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
35 */
36
37 #ifdef DEBUG_ESP
38 #define DPRINTF(fmt, args...) \
39 do { printf("ESP: " fmt , ##args); } while (0)
40 #else
41 #define DPRINTF(fmt, args...)
42 #endif
43
44 #define ESP_MAXREG 0x3f
45 #define TI_BUFSZ 32
46 /* The HBA is ID 7, so for simplicitly limit to 7 devices. */
47 #define ESP_MAX_DEVS 7
48
49 typedef struct ESPState ESPState;
50
51 struct ESPState {
52 BlockDriverState **bd;
53 uint8_t rregs[ESP_MAXREG];
54 uint8_t wregs[ESP_MAXREG];
55 int32_t ti_size;
56 uint32_t ti_rptr, ti_wptr;
57 uint8_t ti_buf[TI_BUFSZ];
58 int sense;
59 int dma;
60 SCSIDevice *scsi_dev[MAX_DISKS];
61 SCSIDevice *current_dev;
62 uint8_t cmdbuf[TI_BUFSZ];
63 int cmdlen;
64 int do_cmd;
65
66 /* The amount of data left in the current DMA transfer. */
67 uint32_t dma_left;
68 /* The size of the current DMA transfer. Zero if no transfer is in
69 progress. */
70 uint32_t dma_counter;
71 uint8_t *async_buf;
72 uint32_t async_len;
73 void *dma_opaque;
74 };
75
76 #define STAT_DO 0x00
77 #define STAT_DI 0x01
78 #define STAT_CD 0x02
79 #define STAT_ST 0x03
80 #define STAT_MI 0x06
81 #define STAT_MO 0x07
82
83 #define STAT_TC 0x10
84 #define STAT_PE 0x20
85 #define STAT_GE 0x40
86 #define STAT_IN 0x80
87
88 #define INTR_FC 0x08
89 #define INTR_BS 0x10
90 #define INTR_DC 0x20
91 #define INTR_RST 0x80
92
93 #define SEQ_0 0x0
94 #define SEQ_CD 0x4
95
96 static int get_cmd(ESPState *s, uint8_t *buf)
97 {
98 uint32_t dmalen;
99 int target;
100
101 dmalen = s->rregs[0] | (s->rregs[1] << 8);
102 target = s->wregs[4] & 7;
103 DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
104 if (s->dma) {
105 espdma_memory_read(s->dma_opaque, buf, dmalen);
106 } else {
107 buf[0] = 0;
108 memcpy(&buf[1], s->ti_buf, dmalen);
109 dmalen++;
110 }
111
112 s->ti_size = 0;
113 s->ti_rptr = 0;
114 s->ti_wptr = 0;
115
116 if (s->current_dev) {
117 /* Started a new command before the old one finished. Cancel it. */
118 scsi_cancel_io(s->current_dev, 0);
119 s->async_len = 0;
120 }
121
122 if (target >= MAX_DISKS || !s->scsi_dev[target]) {
123 // No such drive
124 s->rregs[4] = STAT_IN;
125 s->rregs[5] = INTR_DC;
126 s->rregs[6] = SEQ_0;
127 espdma_raise_irq(s->dma_opaque);
128 return 0;
129 }
130 s->current_dev = s->scsi_dev[target];
131 return dmalen;
132 }
133
134 static void do_cmd(ESPState *s, uint8_t *buf)
135 {
136 int32_t datalen;
137 int lun;
138
139 DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
140 lun = buf[0] & 7;
141 datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
142 s->ti_size = datalen;
143 if (datalen != 0) {
144 s->rregs[4] = STAT_IN | STAT_TC;
145 s->dma_left = 0;
146 s->dma_counter = 0;
147 if (datalen > 0) {
148 s->rregs[4] |= STAT_DI;
149 scsi_read_data(s->current_dev, 0);
150 } else {
151 s->rregs[4] |= STAT_DO;
152 scsi_write_data(s->current_dev, 0);
153 }
154 }
155 s->rregs[5] = INTR_BS | INTR_FC;
156 s->rregs[6] = SEQ_CD;
157 espdma_raise_irq(s->dma_opaque);
158 }
159
160 static void handle_satn(ESPState *s)
161 {
162 uint8_t buf[32];
163 int len;
164
165 len = get_cmd(s, buf);
166 if (len)
167 do_cmd(s, buf);
168 }
169
170 static void handle_satn_stop(ESPState *s)
171 {
172 s->cmdlen = get_cmd(s, s->cmdbuf);
173 if (s->cmdlen) {
174 DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
175 s->do_cmd = 1;
176 s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
177 s->rregs[5] = INTR_BS | INTR_FC;
178 s->rregs[6] = SEQ_CD;
179 espdma_raise_irq(s->dma_opaque);
180 }
181 }
182
183 static void write_response(ESPState *s)
184 {
185 DPRINTF("Transfer status (sense=%d)\n", s->sense);
186 s->ti_buf[0] = s->sense;
187 s->ti_buf[1] = 0;
188 if (s->dma) {
189 espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
190 s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
191 s->rregs[5] = INTR_BS | INTR_FC;
192 s->rregs[6] = SEQ_CD;
193 } else {
194 s->ti_size = 2;
195 s->ti_rptr = 0;
196 s->ti_wptr = 0;
197 s->rregs[7] = 2;
198 }
199 espdma_raise_irq(s->dma_opaque);
200 }
201
202 static void esp_dma_done(ESPState *s)
203 {
204 s->rregs[4] |= STAT_IN | STAT_TC;
205 s->rregs[5] = INTR_BS;
206 s->rregs[6] = 0;
207 s->rregs[7] = 0;
208 s->rregs[0] = 0;
209 s->rregs[1] = 0;
210 espdma_raise_irq(s->dma_opaque);
211 }
212
213 static void esp_do_dma(ESPState *s)
214 {
215 uint32_t len;
216 int to_device;
217
218 to_device = (s->ti_size < 0);
219 len = s->dma_left;
220 if (s->do_cmd) {
221 DPRINTF("command len %d + %d\n", s->cmdlen, len);
222 espdma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
223 s->ti_size = 0;
224 s->cmdlen = 0;
225 s->do_cmd = 0;
226 do_cmd(s, s->cmdbuf);
227 return;
228 }
229 if (s->async_len == 0) {
230 /* Defer until data is available. */
231 return;
232 }
233 if (len > s->async_len) {
234 len = s->async_len;
235 }
236 if (to_device) {
237 espdma_memory_read(s->dma_opaque, s->async_buf, len);
238 } else {
239 espdma_memory_write(s->dma_opaque, s->async_buf, len);
240 }
241 s->dma_left -= len;
242 s->async_buf += len;
243 s->async_len -= len;
244 if (to_device)
245 s->ti_size += len;
246 else
247 s->ti_size -= len;
248 if (s->async_len == 0) {
249 if (to_device) {
250 // ti_size is negative
251 scsi_write_data(s->current_dev, 0);
252 } else {
253 scsi_read_data(s->current_dev, 0);
254 /* If there is still data to be read from the device then
255 complete the DMA operation immeriately. Otherwise defer
256 until the scsi layer has completed. */
257 if (s->dma_left == 0 && s->ti_size > 0) {
258 esp_dma_done(s);
259 }
260 }
261 } else {
262 /* Partially filled a scsi buffer. Complete immediately. */
263 esp_dma_done(s);
264 }
265 }
266
267 static void esp_command_complete(void *opaque, int reason, uint32_t tag,
268 uint32_t arg)
269 {
270 ESPState *s = (ESPState *)opaque;
271
272 if (reason == SCSI_REASON_DONE) {
273 DPRINTF("SCSI Command complete\n");
274 if (s->ti_size != 0)
275 DPRINTF("SCSI command completed unexpectedly\n");
276 s->ti_size = 0;
277 s->dma_left = 0;
278 s->async_len = 0;
279 if (arg)
280 DPRINTF("Command failed\n");
281 s->sense = arg;
282 s->rregs[4] = STAT_ST;
283 esp_dma_done(s);
284 s->current_dev = NULL;
285 } else {
286 DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
287 s->async_len = arg;
288 s->async_buf = scsi_get_buf(s->current_dev, 0);
289 if (s->dma_left) {
290 esp_do_dma(s);
291 } else if (s->dma_counter != 0 && s->ti_size <= 0) {
292 /* If this was the last part of a DMA transfer then the
293 completion interrupt is deferred to here. */
294 esp_dma_done(s);
295 }
296 }
297 }
298
299 static void handle_ti(ESPState *s)
300 {
301 uint32_t dmalen, minlen;
302
303 dmalen = s->rregs[0] | (s->rregs[1] << 8);
304 if (dmalen==0) {
305 dmalen=0x10000;
306 }
307 s->dma_counter = dmalen;
308
309 if (s->do_cmd)
310 minlen = (dmalen < 32) ? dmalen : 32;
311 else if (s->ti_size < 0)
312 minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
313 else
314 minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
315 DPRINTF("Transfer Information len %d\n", minlen);
316 if (s->dma) {
317 s->dma_left = minlen;
318 s->rregs[4] &= ~STAT_TC;
319 esp_do_dma(s);
320 } else if (s->do_cmd) {
321 DPRINTF("command len %d\n", s->cmdlen);
322 s->ti_size = 0;
323 s->cmdlen = 0;
324 s->do_cmd = 0;
325 do_cmd(s, s->cmdbuf);
326 return;
327 }
328 }
329
330 void esp_reset(void *opaque)
331 {
332 ESPState *s = opaque;
333
334 memset(s->rregs, 0, ESP_MAXREG);
335 memset(s->wregs, 0, ESP_MAXREG);
336 s->rregs[0x0e] = 0x4; // Indicate fas100a
337 s->ti_size = 0;
338 s->ti_rptr = 0;
339 s->ti_wptr = 0;
340 s->dma = 0;
341 s->do_cmd = 0;
342 }
343
344 static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
345 {
346 ESPState *s = opaque;
347 uint32_t saddr;
348
349 saddr = (addr & ESP_MAXREG) >> 2;
350 DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
351 switch (saddr) {
352 case 2:
353 // FIFO
354 if (s->ti_size > 0) {
355 s->ti_size--;
356 if ((s->rregs[4] & 6) == 0) {
357 /* Data in/out. */
358 fprintf(stderr, "esp: PIO data read not implemented\n");
359 s->rregs[2] = 0;
360 } else {
361 s->rregs[2] = s->ti_buf[s->ti_rptr++];
362 }
363 espdma_raise_irq(s->dma_opaque);
364 }
365 if (s->ti_size == 0) {
366 s->ti_rptr = 0;
367 s->ti_wptr = 0;
368 }
369 break;
370 case 5:
371 // interrupt
372 // Clear interrupt/error status bits
373 s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);
374 espdma_clear_irq(s->dma_opaque);
375 break;
376 default:
377 break;
378 }
379 return s->rregs[saddr];
380 }
381
382 static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
383 {
384 ESPState *s = opaque;
385 uint32_t saddr;
386
387 saddr = (addr & ESP_MAXREG) >> 2;
388 DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
389 switch (saddr) {
390 case 0:
391 case 1:
392 s->rregs[4] &= ~STAT_TC;
393 break;
394 case 2:
395 // FIFO
396 if (s->do_cmd) {
397 s->cmdbuf[s->cmdlen++] = val & 0xff;
398 } else if ((s->rregs[4] & 6) == 0) {
399 uint8_t buf;
400 buf = val & 0xff;
401 s->ti_size--;
402 fprintf(stderr, "esp: PIO data write not implemented\n");
403 } else {
404 s->ti_size++;
405 s->ti_buf[s->ti_wptr++] = val & 0xff;
406 }
407 break;
408 case 3:
409 s->rregs[saddr] = val;
410 // Command
411 if (val & 0x80) {
412 s->dma = 1;
413 /* Reload DMA counter. */
414 s->rregs[0] = s->wregs[0];
415 s->rregs[1] = s->wregs[1];
416 } else {
417 s->dma = 0;
418 }
419 switch(val & 0x7f) {
420 case 0:
421 DPRINTF("NOP (%2.2x)\n", val);
422 break;
423 case 1:
424 DPRINTF("Flush FIFO (%2.2x)\n", val);
425 //s->ti_size = 0;
426 s->rregs[5] = INTR_FC;
427 s->rregs[6] = 0;
428 break;
429 case 2:
430 DPRINTF("Chip reset (%2.2x)\n", val);
431 esp_reset(s);
432 break;
433 case 3:
434 DPRINTF("Bus reset (%2.2x)\n", val);
435 s->rregs[5] = INTR_RST;
436 if (!(s->wregs[8] & 0x40)) {
437 espdma_raise_irq(s->dma_opaque);
438 }
439 break;
440 case 0x10:
441 handle_ti(s);
442 break;
443 case 0x11:
444 DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
445 write_response(s);
446 break;
447 case 0x12:
448 DPRINTF("Message Accepted (%2.2x)\n", val);
449 write_response(s);
450 s->rregs[5] = INTR_DC;
451 s->rregs[6] = 0;
452 break;
453 case 0x1a:
454 DPRINTF("Set ATN (%2.2x)\n", val);
455 break;
456 case 0x42:
457 DPRINTF("Set ATN (%2.2x)\n", val);
458 handle_satn(s);
459 break;
460 case 0x43:
461 DPRINTF("Set ATN & stop (%2.2x)\n", val);
462 handle_satn_stop(s);
463 break;
464 default:
465 DPRINTF("Unhandled ESP command (%2.2x)\n", val);
466 break;
467 }
468 break;
469 case 4 ... 7:
470 break;
471 case 8:
472 s->rregs[saddr] = val;
473 break;
474 case 9 ... 10:
475 break;
476 case 11:
477 s->rregs[saddr] = val & 0x15;
478 break;
479 case 12 ... 15:
480 s->rregs[saddr] = val;
481 break;
482 default:
483 break;
484 }
485 s->wregs[saddr] = val;
486 }
487
488 static CPUReadMemoryFunc *esp_mem_read[3] = {
489 esp_mem_readb,
490 esp_mem_readb,
491 esp_mem_readb,
492 };
493
494 static CPUWriteMemoryFunc *esp_mem_write[3] = {
495 esp_mem_writeb,
496 esp_mem_writeb,
497 esp_mem_writeb,
498 };
499
500 static void esp_save(QEMUFile *f, void *opaque)
501 {
502 ESPState *s = opaque;
503
504 qemu_put_buffer(f, s->rregs, ESP_MAXREG);
505 qemu_put_buffer(f, s->wregs, ESP_MAXREG);
506 qemu_put_be32s(f, &s->ti_size);
507 qemu_put_be32s(f, &s->ti_rptr);
508 qemu_put_be32s(f, &s->ti_wptr);
509 qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
510 qemu_put_be32s(f, &s->dma);
511 }
512
513 static int esp_load(QEMUFile *f, void *opaque, int version_id)
514 {
515 ESPState *s = opaque;
516
517 if (version_id != 2)
518 return -EINVAL; // Cannot emulate 1
519
520 qemu_get_buffer(f, s->rregs, ESP_MAXREG);
521 qemu_get_buffer(f, s->wregs, ESP_MAXREG);
522 qemu_get_be32s(f, &s->ti_size);
523 qemu_get_be32s(f, &s->ti_rptr);
524 qemu_get_be32s(f, &s->ti_wptr);
525 qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
526 qemu_get_be32s(f, &s->dma);
527
528 return 0;
529 }
530
531 void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id)
532 {
533 ESPState *s = (ESPState *)opaque;
534
535 if (id < 0) {
536 for (id = 0; id < ESP_MAX_DEVS; id++) {
537 if (s->scsi_dev[id] == NULL)
538 break;
539 }
540 }
541 if (id >= ESP_MAX_DEVS) {
542 DPRINTF("Bad Device ID %d\n", id);
543 return;
544 }
545 if (s->scsi_dev[id]) {
546 DPRINTF("Destroying device %d\n", id);
547 scsi_disk_destroy(s->scsi_dev[id]);
548 }
549 DPRINTF("Attaching block device %d\n", id);
550 /* Command queueing is not implemented. */
551 s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
552 }
553
554 void *esp_init(BlockDriverState **bd, uint32_t espaddr, void *dma_opaque)
555 {
556 ESPState *s;
557 int esp_io_memory;
558
559 s = qemu_mallocz(sizeof(ESPState));
560 if (!s)
561 return NULL;
562
563 s->bd = bd;
564 s->dma_opaque = dma_opaque;
565
566 esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
567 cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
568
569 esp_reset(s);
570
571 register_savevm("esp", espaddr, 2, esp_save, esp_load, s);
572 qemu_register_reset(esp_reset, s);
573
574 return s;
575 }