Statistics
| Branch: | Revision:

root / hw / esp.c @ 0fc5c15a

History | View | Annotate | Download (13.1 kB)

1
/*
2
 * QEMU ESP 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
#ifdef DEBUG_ESP
30
#define DPRINTF(fmt, args...) \
31
do { printf("ESP: " fmt , ##args); } while (0)
32
#define pic_set_irq(irq, level) \
33
do { printf("ESP: set_irq(%d): %d\n", (irq), (level)); pic_set_irq((irq),(level));} while (0)
34
#else
35
#define DPRINTF(fmt, args...)
36
#endif
37

    
38
#define ESPDMA_REGS 4
39
#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
40
#define ESP_MAXREG 0x3f
41
#define TI_BUFSZ 32
42
#define DMA_VER 0xa0000000
43
#define DMA_INTR 1
44
#define DMA_INTREN 0x10
45
#define DMA_WRITE_MEM 0x100
46
#define DMA_LOADED 0x04000000
47
typedef struct ESPState ESPState;
48

    
49
struct ESPState {
50
    BlockDriverState **bd;
51
    uint8_t rregs[ESP_MAXREG];
52
    uint8_t wregs[ESP_MAXREG];
53
    int irq;
54
    uint32_t espdmaregs[ESPDMA_REGS];
55
    uint32_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
};
63

    
64
#define STAT_DO 0x00
65
#define STAT_DI 0x01
66
#define STAT_CD 0x02
67
#define STAT_ST 0x03
68
#define STAT_MI 0x06
69
#define STAT_MO 0x07
70

    
71
#define STAT_TC 0x10
72
#define STAT_IN 0x80
73

    
74
#define INTR_FC 0x08
75
#define INTR_BS 0x10
76
#define INTR_DC 0x20
77
#define INTR_RST 0x80
78

    
79
#define SEQ_0 0x0
80
#define SEQ_CD 0x4
81

    
82
static void handle_satn(ESPState *s)
83
{
84
    uint8_t buf[32];
85
    uint32_t dmaptr, dmalen;
86
    int target;
87
    int32_t datalen;
88
    int lun;
89

    
90
    dmalen = s->wregs[0] | (s->wregs[1] << 8);
91
    target = s->wregs[4] & 7;
92
    DPRINTF("Select with ATN len %d target %d\n", dmalen, target);
93
    if (s->dma) {
94
        dmaptr = iommu_translate(s->espdmaregs[1]);
95
        DPRINTF("DMA Direction: %c, addr 0x%8.8x\n",
96
                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r', dmaptr);
97
        cpu_physical_memory_read(dmaptr, buf, dmalen);
98
    } else {
99
        buf[0] = 0;
100
        memcpy(&buf[1], s->ti_buf, dmalen);
101
        dmalen++;
102
    }
103
    DPRINTF("busid 0x%x\n", buf[0]);
104
    lun = buf[0] & 7;
105

    
106
    s->ti_size = 0;
107
    s->ti_rptr = 0;
108
    s->ti_wptr = 0;
109

    
110
    if (target >= 4 || !s->scsi_dev[target]) {
111
        // No such drive
112
        s->rregs[4] = STAT_IN;
113
        s->rregs[5] = INTR_DC;
114
        s->rregs[6] = SEQ_0;
115
        s->espdmaregs[0] |= DMA_INTR;
116
        pic_set_irq(s->irq, 1);
117
        return;
118
    }
119
    s->current_dev = s->scsi_dev[target];
120
    datalen = scsi_send_command(s->current_dev, 0, &buf[1], lun);
121
    if (datalen == 0) {
122
        s->ti_size = 0;
123
    } else {
124
        s->rregs[4] = STAT_IN | STAT_TC;
125
        if (datalen > 0) {
126
            s->rregs[4] |= STAT_DI;
127
            s->ti_size = datalen;
128
        } else {
129
            s->rregs[4] |= STAT_DO;
130
            s->ti_size = -datalen;
131
        }
132
    }
133
    s->rregs[5] = INTR_BS | INTR_FC;
134
    s->rregs[6] = SEQ_CD;
135
    s->espdmaregs[0] |= DMA_INTR;
136
    pic_set_irq(s->irq, 1);
137
}
138

    
139
static void write_response(ESPState *s)
140
{
141
    uint32_t dmaptr;
142

    
143
    DPRINTF("Transfer status (sense=%d)\n", s->sense);
144
    s->ti_buf[0] = s->sense;
145
    s->ti_buf[1] = 0;
146
    if (s->dma) {
147
        dmaptr = iommu_translate(s->espdmaregs[1]);
148
        DPRINTF("DMA Direction: %c\n",
149
                s->espdmaregs[0] & DMA_WRITE_MEM ? 'w': 'r');
150
        cpu_physical_memory_write(dmaptr, s->ti_buf, 2);
151
        s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
152
        s->rregs[5] = INTR_BS | INTR_FC;
153
        s->rregs[6] = SEQ_CD;
154
    } else {
155
        s->ti_size = 2;
156
        s->ti_rptr = 0;
157
        s->ti_wptr = 0;
158
        s->rregs[7] = 2;
159
    }
160
    s->espdmaregs[0] |= DMA_INTR;
161
    pic_set_irq(s->irq, 1);
162

    
163
}
164

    
165
static void esp_command_complete(void *opaque, uint32_t tag, int sense)
166
{
167
    ESPState *s = (ESPState *)opaque;
168

    
169
    DPRINTF("SCSI Command complete\n");
170
    if (s->ti_size != 0)
171
        DPRINTF("SCSI command completed unexpectedly\n");
172
    s->ti_size = 0;
173
    if (sense)
174
        DPRINTF("Command failed\n");
175
    s->sense = sense;
176
    s->rregs[4] = STAT_IN | STAT_TC | STAT_ST;
177
}
178

    
179
static void handle_ti(ESPState *s)
180
{
181
    uint32_t dmaptr, dmalen, minlen, len, from, to;
182
    unsigned int i;
183
    int to_device;
184
    uint8_t buf[TARGET_PAGE_SIZE];
185

    
186
    dmalen = s->wregs[0] | (s->wregs[1] << 8);
187
    if (dmalen==0) {
188
      dmalen=0x10000;
189
    }
190

    
191
    minlen = (dmalen < s->ti_size) ? dmalen : s->ti_size;
192
    DPRINTF("Transfer Information len %d\n", minlen);
193
    if (s->dma) {
194
        dmaptr = iommu_translate(s->espdmaregs[1]);
195
        /* Check if the transfer writes to to reads from the device.  */
196
        to_device = (s->espdmaregs[0] & DMA_WRITE_MEM) == 0;
197
        DPRINTF("DMA Direction: %c, addr 0x%8.8x %08x\n",
198
                to_device ? 'r': 'w', dmaptr, s->ti_size);
199
        from = s->espdmaregs[1];
200
        to = from + minlen;
201
        for (i = 0; i < minlen; i += len, from += len) {
202
            dmaptr = iommu_translate(s->espdmaregs[1] + i);
203
            if ((from & TARGET_PAGE_MASK) != (to & TARGET_PAGE_MASK)) {
204
               len = TARGET_PAGE_SIZE - (from & ~TARGET_PAGE_MASK);
205
            } else {
206
               len = to - from;
207
            }
208
            DPRINTF("DMA address p %08x v %08x len %08x, from %08x, to %08x\n", dmaptr, s->espdmaregs[1] + i, len, from, to);
209
            s->ti_size -= len;
210
            if (to_device) {
211
                cpu_physical_memory_read(dmaptr, buf, len);
212
                scsi_write_data(s->current_dev, buf, len);
213
            } else {
214
                scsi_read_data(s->current_dev, buf, len);
215
                cpu_physical_memory_write(dmaptr, buf, len);
216
            }
217
        }
218
        if (s->ti_size) {
219
            s->rregs[4] = STAT_IN | STAT_TC | (to_device ? STAT_DO : STAT_DI);
220
        }
221
        s->rregs[5] = INTR_BS;
222
        s->rregs[6] = 0;
223
        s->rregs[7] = 0;
224
        s->espdmaregs[0] |= DMA_INTR;
225
    }        
226
    pic_set_irq(s->irq, 1);
227
}
228

    
229
static void esp_reset(void *opaque)
230
{
231
    ESPState *s = opaque;
232
    memset(s->rregs, 0, ESP_MAXREG);
233
    memset(s->wregs, 0, ESP_MAXREG);
234
    s->rregs[0x0e] = 0x4; // Indicate fas100a
235
    memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
236
    s->ti_size = 0;
237
    s->ti_rptr = 0;
238
    s->ti_wptr = 0;
239
    s->dma = 0;
240
}
241

    
242
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
243
{
244
    ESPState *s = opaque;
245
    uint32_t saddr;
246

    
247
    saddr = (addr & ESP_MAXREG) >> 2;
248
    DPRINTF("read reg[%d]: 0x%2.2x\n", saddr, s->rregs[saddr]);
249
    switch (saddr) {
250
    case 2:
251
        // FIFO
252
        if (s->ti_size > 0) {
253
            s->ti_size--;
254
            if ((s->rregs[4] & 6) == 0) {
255
                /* Data in/out.  */
256
                scsi_read_data(s->current_dev, &s->rregs[2], 0);
257
            } else {
258
                s->rregs[2] = s->ti_buf[s->ti_rptr++];
259
            }
260
            pic_set_irq(s->irq, 1);
261
        }
262
        if (s->ti_size == 0) {
263
            s->ti_rptr = 0;
264
            s->ti_wptr = 0;
265
        }
266
        break;
267
    case 5:
268
        // interrupt
269
        // Clear status bits except TC
270
        s->rregs[4] &= STAT_TC;
271
        pic_set_irq(s->irq, 0);
272
        s->espdmaregs[0] &= ~DMA_INTR;
273
        break;
274
    default:
275
        break;
276
    }
277
    return s->rregs[saddr];
278
}
279

    
280
static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
281
{
282
    ESPState *s = opaque;
283
    uint32_t saddr;
284

    
285
    saddr = (addr & ESP_MAXREG) >> 2;
286
    DPRINTF("write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->wregs[saddr], val);
287
    switch (saddr) {
288
    case 0:
289
    case 1:
290
        s->rregs[saddr] = val;
291
        break;
292
    case 2:
293
        // FIFO
294
        if ((s->rregs[4] & 6) == 0) {
295
            uint8_t buf;
296
            buf = val & 0xff;
297
            s->ti_size--;
298
            scsi_write_data(s->current_dev, &buf, 0);
299
        } else {
300
            s->ti_size++;
301
            s->ti_buf[s->ti_wptr++] = val & 0xff;
302
        }
303
        break;
304
    case 3:
305
        s->rregs[saddr] = val;
306
        // Command
307
        if (val & 0x80) {
308
            s->dma = 1;
309
        } else {
310
            s->dma = 0;
311
        }
312
        switch(val & 0x7f) {
313
        case 0:
314
            DPRINTF("NOP (%2.2x)\n", val);
315
            break;
316
        case 1:
317
            DPRINTF("Flush FIFO (%2.2x)\n", val);
318
            //s->ti_size = 0;
319
            s->rregs[5] = INTR_FC;
320
            s->rregs[6] = 0;
321
            break;
322
        case 2:
323
            DPRINTF("Chip reset (%2.2x)\n", val);
324
            esp_reset(s);
325
            break;
326
        case 3:
327
            DPRINTF("Bus reset (%2.2x)\n", val);
328
            s->rregs[5] = INTR_RST;
329
            if (!(s->wregs[8] & 0x40)) {
330
                s->espdmaregs[0] |= DMA_INTR;
331
                pic_set_irq(s->irq, 1);
332
            }
333
            break;
334
        case 0x10:
335
            handle_ti(s);
336
            break;
337
        case 0x11:
338
            DPRINTF("Initiator Command Complete Sequence (%2.2x)\n", val);
339
            write_response(s);
340
            break;
341
        case 0x12:
342
            DPRINTF("Message Accepted (%2.2x)\n", val);
343
            write_response(s);
344
            s->rregs[5] = INTR_DC;
345
            s->rregs[6] = 0;
346
            break;
347
        case 0x1a:
348
            DPRINTF("Set ATN (%2.2x)\n", val);
349
            break;
350
        case 0x42:
351
            handle_satn(s);
352
            break;
353
        case 0x43:
354
            DPRINTF("Set ATN & stop (%2.2x)\n", val);
355
            handle_satn(s);
356
            break;
357
        default:
358
            DPRINTF("Unhandled ESP command (%2.2x)\n", val);
359
            break;
360
        }
361
        break;
362
    case 4 ... 7:
363
        break;
364
    case 8:
365
        s->rregs[saddr] = val;
366
        break;
367
    case 9 ... 10:
368
        break;
369
    case 11:
370
        s->rregs[saddr] = val & 0x15;
371
        break;
372
    case 12 ... 15:
373
        s->rregs[saddr] = val;
374
        break;
375
    default:
376
        break;
377
    }
378
    s->wregs[saddr] = val;
379
}
380

    
381
static CPUReadMemoryFunc *esp_mem_read[3] = {
382
    esp_mem_readb,
383
    esp_mem_readb,
384
    esp_mem_readb,
385
};
386

    
387
static CPUWriteMemoryFunc *esp_mem_write[3] = {
388
    esp_mem_writeb,
389
    esp_mem_writeb,
390
    esp_mem_writeb,
391
};
392

    
393
static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
394
{
395
    ESPState *s = opaque;
396
    uint32_t saddr;
397

    
398
    saddr = (addr & ESPDMA_MAXADDR) >> 2;
399
    DPRINTF("read dmareg[%d]: 0x%8.8x\n", saddr, s->espdmaregs[saddr]);
400

    
401
    return s->espdmaregs[saddr];
402
}
403

    
404
static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
405
{
406
    ESPState *s = opaque;
407
    uint32_t saddr;
408

    
409
    saddr = (addr & ESPDMA_MAXADDR) >> 2;
410
    DPRINTF("write dmareg[%d]: 0x%8.8x -> 0x%8.8x\n", saddr, s->espdmaregs[saddr], val);
411
    switch (saddr) {
412
    case 0:
413
        if (!(val & DMA_INTREN))
414
            pic_set_irq(s->irq, 0);
415
        if (val & 0x80) {
416
            esp_reset(s);
417
        } else if (val & 0x40) {
418
            val &= ~0x40;
419
        } else if (val == 0)
420
            val = 0x40;
421
        val &= 0x0fffffff;
422
        val |= DMA_VER;
423
        break;
424
    case 1:
425
        s->espdmaregs[0] |= DMA_LOADED;
426
        break;
427
    default:
428
        break;
429
    }
430
    s->espdmaregs[saddr] = val;
431
}
432

    
433
static CPUReadMemoryFunc *espdma_mem_read[3] = {
434
    espdma_mem_readl,
435
    espdma_mem_readl,
436
    espdma_mem_readl,
437
};
438

    
439
static CPUWriteMemoryFunc *espdma_mem_write[3] = {
440
    espdma_mem_writel,
441
    espdma_mem_writel,
442
    espdma_mem_writel,
443
};
444

    
445
static void esp_save(QEMUFile *f, void *opaque)
446
{
447
    ESPState *s = opaque;
448
    unsigned int i;
449

    
450
    qemu_put_buffer(f, s->rregs, ESP_MAXREG);
451
    qemu_put_buffer(f, s->wregs, ESP_MAXREG);
452
    qemu_put_be32s(f, &s->irq);
453
    for (i = 0; i < ESPDMA_REGS; i++)
454
        qemu_put_be32s(f, &s->espdmaregs[i]);
455
    qemu_put_be32s(f, &s->ti_size);
456
    qemu_put_be32s(f, &s->ti_rptr);
457
    qemu_put_be32s(f, &s->ti_wptr);
458
    qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
459
    qemu_put_be32s(f, &s->dma);
460
}
461

    
462
static int esp_load(QEMUFile *f, void *opaque, int version_id)
463
{
464
    ESPState *s = opaque;
465
    unsigned int i;
466
    
467
    if (version_id != 1)
468
        return -EINVAL;
469

    
470
    qemu_get_buffer(f, s->rregs, ESP_MAXREG);
471
    qemu_get_buffer(f, s->wregs, ESP_MAXREG);
472
    qemu_get_be32s(f, &s->irq);
473
    for (i = 0; i < ESPDMA_REGS; i++)
474
        qemu_get_be32s(f, &s->espdmaregs[i]);
475
    qemu_get_be32s(f, &s->ti_size);
476
    qemu_get_be32s(f, &s->ti_rptr);
477
    qemu_get_be32s(f, &s->ti_wptr);
478
    qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
479
    qemu_get_be32s(f, &s->dma);
480

    
481
    return 0;
482
}
483

    
484
void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
485
{
486
    ESPState *s;
487
    int esp_io_memory, espdma_io_memory;
488
    int i;
489

    
490
    s = qemu_mallocz(sizeof(ESPState));
491
    if (!s)
492
        return;
493

    
494
    s->bd = bd;
495
    s->irq = irq;
496

    
497
    esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
498
    cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
499

    
500
    espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
501
    cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
502

    
503
    esp_reset(s);
504

    
505
    register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
506
    qemu_register_reset(esp_reset, s);
507
    for (i = 0; i < MAX_DISKS; i++) {
508
        if (bs_table[i]) {
509
            s->scsi_dev[i] =
510
                scsi_disk_init(bs_table[i], esp_command_complete, s);
511
        }
512
    }
513
}
514