Statistics
| Branch: | Revision:

root / hw / esp.c @ 5425a216

History | View | Annotate | Download (14.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 "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->sense);
511
    qemu_put_be32s(f, &s->dma);
512
    qemu_put_buffer(f, s->cmdbuf, TI_BUFSZ);
513
    qemu_put_be32s(f, &s->cmdlen);
514
    qemu_put_be32s(f, &s->do_cmd);
515
    qemu_put_be32s(f, &s->dma_left);
516
    // There should be no transfers in progress, so dma_counter is not saved
517
}
518

    
519
static int esp_load(QEMUFile *f, void *opaque, int version_id)
520
{
521
    ESPState *s = opaque;
522
    
523
    if (version_id != 3)
524
        return -EINVAL; // Cannot emulate 2
525

    
526
    qemu_get_buffer(f, s->rregs, ESP_MAXREG);
527
    qemu_get_buffer(f, s->wregs, ESP_MAXREG);
528
    qemu_get_be32s(f, &s->ti_size);
529
    qemu_get_be32s(f, &s->ti_rptr);
530
    qemu_get_be32s(f, &s->ti_wptr);
531
    qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
532
    qemu_get_be32s(f, &s->sense);
533
    qemu_get_be32s(f, &s->dma);
534
    qemu_get_buffer(f, s->cmdbuf, TI_BUFSZ);
535
    qemu_get_be32s(f, &s->cmdlen);
536
    qemu_get_be32s(f, &s->do_cmd);
537
    qemu_get_be32s(f, &s->dma_left);
538

    
539
    return 0;
540
}
541

    
542
void esp_scsi_attach(void *opaque, BlockDriverState *bd, int id)
543
{
544
    ESPState *s = (ESPState *)opaque;
545

    
546
    if (id < 0) {
547
        for (id = 0; id < ESP_MAX_DEVS; id++) {
548
            if (s->scsi_dev[id] == NULL)
549
                break;
550
        }
551
    }
552
    if (id >= ESP_MAX_DEVS) {
553
        DPRINTF("Bad Device ID %d\n", id);
554
        return;
555
    }
556
    if (s->scsi_dev[id]) {
557
        DPRINTF("Destroying device %d\n", id);
558
        scsi_disk_destroy(s->scsi_dev[id]);
559
    }
560
    DPRINTF("Attaching block device %d\n", id);
561
    /* Command queueing is not implemented.  */
562
    s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
563
}
564

    
565
void *esp_init(BlockDriverState **bd, uint32_t espaddr, void *dma_opaque)
566
{
567
    ESPState *s;
568
    int esp_io_memory;
569

    
570
    s = qemu_mallocz(sizeof(ESPState));
571
    if (!s)
572
        return NULL;
573

    
574
    s->bd = bd;
575
    s->dma_opaque = dma_opaque;
576

    
577
    esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
578
    cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
579

    
580
    esp_reset(s);
581

    
582
    register_savevm("esp", espaddr, 3, esp_save, esp_load, s);
583
    qemu_register_reset(esp_reset, s);
584

    
585
    return s;
586
}