Statistics
| Branch: | Revision:

root / hw / esp.c @ 87ecb68b

History | View | Annotate | Download (15.8 kB)

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 "hw.h"
25
#include "block.h"
26
#include "scsi-disk.h"
27
#include "sun4m.h"
28
/* FIXME: Only needed for MAX_DISKS, which is probably wrong.  */
29
#include "sysemu.h"
30

    
31
/* debug ESP card */
32
//#define DEBUG_ESP
33

    
34
/*
35
 * On Sparc32, this is the ESP (NCR53C90) part of chip STP2000 (Master I/O), also
36
 * produced as NCR89C100. See
37
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
38
 * and
39
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
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
/* The HBA is ID 7, so for simplicitly limit to 7 devices.  */
54
#define ESP_MAX_DEVS      7
55

    
56
typedef struct ESPState ESPState;
57

    
58
struct ESPState {
59
    qemu_irq irq;
60
    BlockDriverState **bd;
61
    uint8_t rregs[ESP_REGS];
62
    uint8_t wregs[ESP_REGS];
63
    int32_t ti_size;
64
    uint32_t ti_rptr, ti_wptr;
65
    uint8_t ti_buf[TI_BUFSZ];
66
    int sense;
67
    int dma;
68
    SCSIDevice *scsi_dev[MAX_DISKS];
69
    SCSIDevice *current_dev;
70
    uint8_t cmdbuf[TI_BUFSZ];
71
    int cmdlen;
72
    int do_cmd;
73

    
74
    /* The amount of data left in the current DMA transfer.  */
75
    uint32_t dma_left;
76
    /* The size of the current DMA transfer.  Zero if no transfer is in
77
       progress.  */
78
    uint32_t dma_counter;
79
    uint8_t *async_buf;
80
    uint32_t async_len;
81
    void *dma_opaque;
82
};
83

    
84
#define STAT_DO 0x00
85
#define STAT_DI 0x01
86
#define STAT_CD 0x02
87
#define STAT_ST 0x03
88
#define STAT_MI 0x06
89
#define STAT_MO 0x07
90

    
91
#define STAT_TC 0x10
92
#define STAT_PE 0x20
93
#define STAT_GE 0x40
94
#define STAT_IN 0x80
95

    
96
#define INTR_FC 0x08
97
#define INTR_BS 0x10
98
#define INTR_DC 0x20
99
#define INTR_RST 0x80
100

    
101
#define SEQ_0 0x0
102
#define SEQ_CD 0x4
103

    
104
static int get_cmd(ESPState *s, uint8_t *buf)
105
{
106
    uint32_t dmalen;
107
    int target;
108

    
109
    dmalen = s->rregs[0] | (s->rregs[1] << 8);
110
    target = s->wregs[4] & 7;
111
    DPRINTF("get_cmd: len %d target %d\n", dmalen, target);
112
    if (s->dma) {
113
        espdma_memory_read(s->dma_opaque, buf, dmalen);
114
    } else {
115
        buf[0] = 0;
116
        memcpy(&buf[1], s->ti_buf, dmalen);
117
        dmalen++;
118
    }
119

    
120
    s->ti_size = 0;
121
    s->ti_rptr = 0;
122
    s->ti_wptr = 0;
123

    
124
    if (s->current_dev) {
125
        /* Started a new command before the old one finished.  Cancel it.  */
126
        scsi_cancel_io(s->current_dev, 0);
127
        s->async_len = 0;
128
    }
129

    
130
    if (target >= MAX_DISKS || !s->scsi_dev[target]) {
131
        // No such drive
132
        s->rregs[4] = STAT_IN;
133
        s->rregs[5] = INTR_DC;
134
        s->rregs[6] = SEQ_0;
135
        qemu_irq_raise(s->irq);
136
        return 0;
137
    }
138
    s->current_dev = s->scsi_dev[target];
139
    return dmalen;
140
}
141

    
142
static void do_cmd(ESPState *s, uint8_t *buf)
143
{
144
    int32_t datalen;
145
    int lun;
146

    
147
    DPRINTF("do_cmd: busid 0x%x\n", buf[0]);
148
    lun = buf[0] & 7;
149
    datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
150
    s->ti_size = datalen;
151
    if (datalen != 0) {
152
        s->rregs[4] = STAT_IN | STAT_TC;
153
        s->dma_left = 0;
154
        s->dma_counter = 0;
155
        if (datalen > 0) {
156
            s->rregs[4] |= STAT_DI;
157
            scsi_read_data(s->current_dev, 0);
158
        } else {
159
            s->rregs[4] |= STAT_DO;
160
            scsi_write_data(s->current_dev, 0);
161
        }
162
    }
163
    s->rregs[5] = INTR_BS | INTR_FC;
164
    s->rregs[6] = SEQ_CD;
165
    qemu_irq_raise(s->irq);
166
}
167

    
168
static void handle_satn(ESPState *s)
169
{
170
    uint8_t buf[32];
171
    int len;
172

    
173
    len = get_cmd(s, buf);
174
    if (len)
175
        do_cmd(s, buf);
176
}
177

    
178
static void handle_satn_stop(ESPState *s)
179
{
180
    s->cmdlen = get_cmd(s, s->cmdbuf);
181
    if (s->cmdlen) {
182
        DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
183
        s->do_cmd = 1;
184
        s->rregs[4] = STAT_IN | STAT_TC | STAT_CD;
185
        s->rregs[5] = INTR_BS | INTR_FC;
186
        s->rregs[6] = SEQ_CD;
187
        qemu_irq_raise(s->irq);
188
    }
189
}
190

    
191
static void write_response(ESPState *s)
192
{
193
    DPRINTF("Transfer status (sense=%d)\n", s->sense);
194
    s->ti_buf[0] = s->sense;
195
    s->ti_buf[1] = 0;
196
    if (s->dma) {
197
        espdma_memory_write(s->dma_opaque, s->ti_buf, 2);
198
        s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
199
        s->rregs[5] = INTR_BS | INTR_FC;
200
        s->rregs[6] = SEQ_CD;
201
    } else {
202
        s->ti_size = 2;
203
        s->ti_rptr = 0;
204
        s->ti_wptr = 0;
205
        s->rregs[7] = 2;
206
    }
207
    qemu_irq_raise(s->irq);
208
}
209

    
210
static void esp_dma_done(ESPState *s)
211
{
212
    s->rregs[4] |= STAT_IN | STAT_TC;
213
    s->rregs[5] = INTR_BS;
214
    s->rregs[6] = 0;
215
    s->rregs[7] = 0;
216
    s->rregs[0] = 0;
217
    s->rregs[1] = 0;
218
    qemu_irq_raise(s->irq);
219
}
220

    
221
static void esp_do_dma(ESPState *s)
222
{
223
    uint32_t len;
224
    int to_device;
225

    
226
    to_device = (s->ti_size < 0);
227
    len = s->dma_left;
228
    if (s->do_cmd) {
229
        DPRINTF("command len %d + %d\n", s->cmdlen, len);
230
        espdma_memory_read(s->dma_opaque, &s->cmdbuf[s->cmdlen], len);
231
        s->ti_size = 0;
232
        s->cmdlen = 0;
233
        s->do_cmd = 0;
234
        do_cmd(s, s->cmdbuf);
235
        return;
236
    }
237
    if (s->async_len == 0) {
238
        /* Defer until data is available.  */
239
        return;
240
    }
241
    if (len > s->async_len) {
242
        len = s->async_len;
243
    }
244
    if (to_device) {
245
        espdma_memory_read(s->dma_opaque, s->async_buf, len);
246
    } else {
247
        espdma_memory_write(s->dma_opaque, s->async_buf, len);
248
    }
249
    s->dma_left -= len;
250
    s->async_buf += len;
251
    s->async_len -= len;
252
    if (to_device)
253
        s->ti_size += len;
254
    else
255
        s->ti_size -= len;
256
    if (s->async_len == 0) {
257
        if (to_device) {
258
            // ti_size is negative
259
            scsi_write_data(s->current_dev, 0);
260
        } else {
261
            scsi_read_data(s->current_dev, 0);
262
            /* If there is still data to be read from the device then
263
               complete the DMA operation immeriately.  Otherwise defer
264
               until the scsi layer has completed.  */
265
            if (s->dma_left == 0 && s->ti_size > 0) {
266
                esp_dma_done(s);
267
            }
268
        }
269
    } else {
270
        /* Partially filled a scsi buffer. Complete immediately.  */
271
        esp_dma_done(s);
272
    }
273
}
274

    
275
static void esp_command_complete(void *opaque, int reason, uint32_t tag,
276
                                 uint32_t arg)
277
{
278
    ESPState *s = (ESPState *)opaque;
279

    
280
    if (reason == SCSI_REASON_DONE) {
281
        DPRINTF("SCSI Command complete\n");
282
        if (s->ti_size != 0)
283
            DPRINTF("SCSI command completed unexpectedly\n");
284
        s->ti_size = 0;
285
        s->dma_left = 0;
286
        s->async_len = 0;
287
        if (arg)
288
            DPRINTF("Command failed\n");
289
        s->sense = arg;
290
        s->rregs[4] = STAT_ST;
291
        esp_dma_done(s);
292
        s->current_dev = NULL;
293
    } else {
294
        DPRINTF("transfer %d/%d\n", s->dma_left, s->ti_size);
295
        s->async_len = arg;
296
        s->async_buf = scsi_get_buf(s->current_dev, 0);
297
        if (s->dma_left) {
298
            esp_do_dma(s);
299
        } else if (s->dma_counter != 0 && s->ti_size <= 0) {
300
            /* If this was the last part of a DMA transfer then the
301
               completion interrupt is deferred to here.  */
302
            esp_dma_done(s);
303
        }
304
    }
305
}
306

    
307
static void handle_ti(ESPState *s)
308
{
309
    uint32_t dmalen, minlen;
310

    
311
    dmalen = s->rregs[0] | (s->rregs[1] << 8);
312
    if (dmalen==0) {
313
      dmalen=0x10000;
314
    }
315
    s->dma_counter = dmalen;
316

    
317
    if (s->do_cmd)
318
        minlen = (dmalen < 32) ? dmalen : 32;
319
    else if (s->ti_size < 0)
320
        minlen = (dmalen < -s->ti_size) ? dmalen : -s->ti_size;
321
    else
322
        minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
323
    DPRINTF("Transfer Information len %d\n", minlen);
324
    if (s->dma) {
325
        s->dma_left = minlen;
326
        s->rregs[4] &= ~STAT_TC;
327
        esp_do_dma(s);
328
    } else if (s->do_cmd) {
329
        DPRINTF("command len %d\n", s->cmdlen);
330
        s->ti_size = 0;
331
        s->cmdlen = 0;
332
        s->do_cmd = 0;
333
        do_cmd(s, s->cmdbuf);
334
        return;
335
    }
336
}
337

    
338
static void esp_reset(void *opaque)
339
{
340
    ESPState *s = opaque;
341

    
342
    memset(s->rregs, 0, ESP_REGS);
343
    memset(s->wregs, 0, ESP_REGS);
344
    s->rregs[0x0e] = 0x4; // Indicate fas100a
345
    s->ti_size = 0;
346
    s->ti_rptr = 0;
347
    s->ti_wptr = 0;
348
    s->dma = 0;
349
    s->do_cmd = 0;
350
}
351

    
352
static void parent_esp_reset(void *opaque, int irq, int level)
353
{
354
    if (level)
355
        esp_reset(opaque);
356
}
357

    
358
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
359
{
360
    ESPState *s = opaque;
361
    uint32_t saddr;
362

    
363
    saddr = (addr & ESP_MASK) >> 2;
364
    DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
365
    switch (saddr) {
366
    case 2:
367
        // FIFO
368
        if (s->ti_size > 0) {
369
            s->ti_size--;
370
            if ((s->rregs[4] & 6) == 0) {
371
                /* Data in/out.  */
372
                fprintf(stderr, "esp: PIO data read not implemented\n");
373
                s->rregs[2] = 0;
374
            } else {
375
                s->rregs[2] = s->ti_buf[s->ti_rptr++];
376
            }
377
            qemu_irq_raise(s->irq);
378
        }
379
        if (s->ti_size == 0) {
380
            s->ti_rptr = 0;
381
            s->ti_wptr = 0;
382
        }
383
        break;
384
    case 5:
385
        // interrupt
386
        // Clear interrupt/error status bits
387
        s->rregs[4] &= ~(STAT_IN | STAT_GE | STAT_PE);
388
        qemu_irq_lower(s->irq);
389
        break;
390
    default:
391
        break;
392
    }
393
    return s->rregs[saddr];
394
}
395

    
396
static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
397
{
398
    ESPState *s = opaque;
399
    uint32_t saddr;
400

    
401
    saddr = (addr & ESP_MASK) >> 2;
402
    DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
403
    switch (saddr) {
404
    case 0:
405
    case 1:
406
        s->rregs[4] &= ~STAT_TC;
407
        break;
408
    case 2:
409
        // FIFO
410
        if (s->do_cmd) {
411
            s->cmdbuf[s->cmdlen++] = val & 0xff;
412
        } else if ((s->rregs[4] & 6) == 0) {
413
            uint8_t buf;
414
            buf = val & 0xff;
415
            s->ti_size--;
416
            fprintf(stderr, "esp: PIO data write not implemented\n");
417
        } else {
418
            s->ti_size++;
419
            s->ti_buf[s->ti_wptr++] = val & 0xff;
420
        }
421
        break;
422
    case 3:
423
        s->rregs[saddr] = val;
424
        // Command
425
        if (val & 0x80) {
426
            s->dma = 1;
427
            /* Reload DMA counter.  */
428
            s->rregs[0] = s->wregs[0];
429
            s->rregs[1] = s->wregs[1];
430
        } else {
431
            s->dma = 0;
432
        }
433
        switch(val & 0x7f) {
434
        case 0:
435
            DPRINTF("NOP (%2.2x)\n", val);
436
            break;
437
        case 1:
438
            DPRINTF("Flush FIFO (%2.2x)\n", val);
439
            //s->ti_size = 0;
440
            s->rregs[5] = INTR_FC;
441
            s->rregs[6] = 0;
442
            break;
443
        case 2:
444
            DPRINTF("Chip reset (%2.2x)\n", val);
445
            esp_reset(s);
446
            break;
447
        case 3:
448
            DPRINTF("Bus reset (%2.2x)\n", val);
449
            s->rregs[5] = INTR_RST;
450
            if (!(s->wregs[8] & 0x40)) {
451
                qemu_irq_raise(s->irq);
452
            }
453
            break;
454
        case 0x10:
455
            handle_ti(s);
456
            break;
457
        case 0x11:
458
            DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
459
            write_response(s);
460
            break;
461
        case 0x12:
462
            DPRINTF("Message Accepted (%2.2x)\n", val);
463
            write_response(s);
464
            s->rregs[5] = INTR_DC;
465
            s->rregs[6] = 0;
466
            break;
467
        case 0x1a:
468
            DPRINTF("Set ATN (%2.2x)\n", val);
469
            break;
470
        case 0x42:
471
            DPRINTF("Set ATN (%2.2x)\n", val);
472
            handle_satn(s);
473
            break;
474
        case 0x43:
475
            DPRINTF("Set ATN & stop (%2.2x)\n", val);
476
            handle_satn_stop(s);
477
            break;
478
        case 0x44:
479
            DPRINTF("Enable selection (%2.2x)\n", val);
480
            break;
481
        default:
482
            DPRINTF("Unhandled ESP command (%2.2x)\n", val);
483
            break;
484
        }
485
        break;
486
    case 4 ... 7:
487
        break;
488
    case 8:
489
        s->rregs[saddr] = val;
490
        break;
491
    case 9 ... 10:
492
        break;
493
    case 11:
494
        s->rregs[saddr] = val & 0x15;
495
        break;
496
    case 12 ... 15:
497
        s->rregs[saddr] = val;
498
        break;
499
    default:
500
        break;
501
    }
502
    s->wregs[saddr] = val;
503
}
504

    
505
static CPUReadMemoryFunc *esp_mem_read[3] = {
506
    esp_mem_readb,
507
    esp_mem_readb,
508
    esp_mem_readb,
509
};
510

    
511
static CPUWriteMemoryFunc *esp_mem_write[3] = {
512
    esp_mem_writeb,
513
    esp_mem_writeb,
514
    esp_mem_writeb,
515
};
516

    
517
static void esp_save(QEMUFile *f, void *opaque)
518
{
519
    ESPState *s = opaque;
520

    
521
    qemu_put_buffer(f, s->rregs, ESP_REGS);
522
    qemu_put_buffer(f, s->wregs, ESP_REGS);
523
    qemu_put_be32s(f, &s->ti_size);
524
    qemu_put_be32s(f, &s->ti_rptr);
525
    qemu_put_be32s(f, &s->ti_wptr);
526
    qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
527
    qemu_put_be32s(f, &s->sense);
528
    qemu_put_be32s(f, &s->dma);
529
    qemu_put_buffer(f, s->cmdbuf, TI_BUFSZ);
530
    qemu_put_be32s(f, &s->cmdlen);
531
    qemu_put_be32s(f, &s->do_cmd);
532
    qemu_put_be32s(f, &s->dma_left);
533
    // There should be no transfers in progress, so dma_counter is not saved
534
}
535

    
536
static int esp_load(QEMUFile *f, void *opaque, int version_id)
537
{
538
    ESPState *s = opaque;
539

    
540
    if (version_id != 3)
541
        return -EINVAL; // Cannot emulate 2
542

    
543
    qemu_get_buffer(f, s->rregs, ESP_REGS);
544
    qemu_get_buffer(f, s->wregs, ESP_REGS);
545
    qemu_get_be32s(f, &s->ti_size);
546
    qemu_get_be32s(f, &s->ti_rptr);
547
    qemu_get_be32s(f, &s->ti_wptr);
548
    qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
549
    qemu_get_be32s(f, &s->sense);
550
    qemu_get_be32s(f, &s->dma);
551
    qemu_get_buffer(f, s->cmdbuf, TI_BUFSZ);
552
    qemu_get_be32s(f, &s->cmdlen);
553
    qemu_get_be32s(f, &s->do_cmd);
554
    qemu_get_be32s(f, &s->dma_left);
555

    
556
    return 0;
557
}
558

    
559
void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id)
560
{
561
    ESPState *s = (ESPState *)opaque;
562

    
563
    if (id < 0) {
564
        for (id = 0; id < ESP_MAX_DEVS; id++) {
565
            if (s->scsi_dev[id] == NULL)
566
                break;
567
        }
568
    }
569
    if (id >= ESP_MAX_DEVS) {
570
        DPRINTF("Bad Device ID %d\n", id);
571
        return;
572
    }
573
    if (s->scsi_dev[id]) {
574
        DPRINTF("Destroying device %d\n", id);
575
        scsi_disk_destroy(s->scsi_dev[id]);
576
    }
577
    DPRINTF("Attaching block device %d\n", id);
578
    /* Command queueing is not implemented.  */
579
    s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
580
}
581

    
582
void *esp_init(BlockDriverState **bd, target_phys_addr_t espaddr,
583
               void *dma_opaque, qemu_irq irq, qemu_irq *reset)
584
{
585
    ESPState *s;
586
    int esp_io_memory;
587

    
588
    s = qemu_mallocz(sizeof(ESPState));
589
    if (!s)
590
        return NULL;
591

    
592
    s->bd = bd;
593
    s->irq = irq;
594
    s->dma_opaque = dma_opaque;
595

    
596
    esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
597
    cpu_register_physical_memory(espaddr, ESP_SIZE, esp_io_memory);
598

    
599
    esp_reset(s);
600

    
601
    register_savevm("esp", espaddr, 3, esp_save, esp_load, s);
602
    qemu_register_reset(esp_reset, s);
603

    
604
    *reset = *qemu_allocate_irqs(parent_esp_reset, s, 1);
605

    
606
    return s;
607
}