Browse Source
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1326 c046a42c-6fe2-441c-8c8c-71466251a162stable-0.10
12 changed files with 1751 additions and 676 deletions
@ -0,0 +1,192 @@ |
|||
/*
|
|||
* QEMU ESP emulation |
|||
* |
|||
* Copyright (c) 2005 Fabrice Bellard |
|||
* |
|||
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
* of this software and associated documentation files (the "Software"), to deal |
|||
* in the Software without restriction, including without limitation the rights |
|||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
* copies of the Software, and to permit persons to whom the Software is |
|||
* furnished to do so, subject to the following conditions: |
|||
* |
|||
* The above copyright notice and this permission notice shall be included in |
|||
* all copies or substantial portions of the Software. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
* THE SOFTWARE. |
|||
*/ |
|||
#include "vl.h" |
|||
|
|||
/* debug ESP card */ |
|||
#define DEBUG_ESP |
|||
|
|||
#ifdef DEBUG_ESP |
|||
#define DPRINTF(fmt, args...) \ |
|||
do { printf("ESP: " fmt , ##args); } while (0) |
|||
#else |
|||
#define DPRINTF(fmt, args...) |
|||
#endif |
|||
|
|||
#define ESPDMA_REGS 4 |
|||
#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1) |
|||
#define ESP_MAXREG 0x3f |
|||
|
|||
typedef struct ESPState { |
|||
BlockDriverState **bd; |
|||
uint8_t regs[ESP_MAXREG]; |
|||
int irq; |
|||
uint32_t espdmaregs[ESPDMA_REGS]; |
|||
} ESPState; |
|||
|
|||
static void esp_reset(void *opaque) |
|||
{ |
|||
ESPState *s = opaque; |
|||
memset(s->regs, 0, ESP_MAXREG); |
|||
s->regs[0x0e] = 0x4; // Indicate fas100a
|
|||
memset(s->espdmaregs, 0, ESPDMA_REGS * 4); |
|||
} |
|||
|
|||
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) |
|||
{ |
|||
ESPState *s = opaque; |
|||
uint32_t saddr; |
|||
|
|||
saddr = (addr & ESP_MAXREG) >> 2; |
|||
switch (saddr) { |
|||
default: |
|||
break; |
|||
} |
|||
DPRINTF("esp: read reg[%d]: 0x%2.2x\n", saddr, s->regs[saddr]); |
|||
return s->regs[saddr]; |
|||
} |
|||
|
|||
static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
|||
{ |
|||
ESPState *s = opaque; |
|||
uint32_t saddr; |
|||
|
|||
saddr = (addr & ESP_MAXREG) >> 2; |
|||
DPRINTF("esp: write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->regs[saddr], val); |
|||
switch (saddr) { |
|||
case 3: |
|||
// Command
|
|||
switch(val & 0x7f) { |
|||
case 0: |
|||
DPRINTF("esp: NOP (%2.2x)\n", val); |
|||
break; |
|||
case 2: |
|||
DPRINTF("esp: Chip reset (%2.2x)\n", val); |
|||
esp_reset(s); |
|||
break; |
|||
case 3: |
|||
DPRINTF("esp: Bus reset (%2.2x)\n", val); |
|||
break; |
|||
case 0x1a: |
|||
DPRINTF("esp: Set ATN (%2.2x)\n", val); |
|||
break; |
|||
case 0x42: |
|||
DPRINTF("esp: Select with ATN (%2.2x)\n", val); |
|||
s->regs[4] = 0x1a; // Status: TCNT | TDONE | CMD
|
|||
s->regs[5] = 0x20; // Intr: Disconnect, nobody there
|
|||
s->regs[6] = 0x4; // Seq: Cmd done
|
|||
pic_set_irq(s->irq, 1); |
|||
break; |
|||
} |
|||
break; |
|||
case 4 ... 7: |
|||
case 9 ... 0xf: |
|||
break; |
|||
default: |
|||
s->regs[saddr] = val; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
static CPUReadMemoryFunc *esp_mem_read[3] = { |
|||
esp_mem_readb, |
|||
esp_mem_readb, |
|||
esp_mem_readb, |
|||
}; |
|||
|
|||
static CPUWriteMemoryFunc *esp_mem_write[3] = { |
|||
esp_mem_writeb, |
|||
esp_mem_writeb, |
|||
esp_mem_writeb, |
|||
}; |
|||
|
|||
static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr) |
|||
{ |
|||
ESPState *s = opaque; |
|||
uint32_t saddr; |
|||
|
|||
saddr = (addr & ESPDMA_MAXADDR) >> 2; |
|||
return s->espdmaregs[saddr]; |
|||
} |
|||
|
|||
static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
|||
{ |
|||
ESPState *s = opaque; |
|||
uint32_t saddr; |
|||
|
|||
saddr = (addr & ESPDMA_MAXADDR) >> 2; |
|||
s->espdmaregs[saddr] = val; |
|||
} |
|||
|
|||
static CPUReadMemoryFunc *espdma_mem_read[3] = { |
|||
espdma_mem_readl, |
|||
espdma_mem_readl, |
|||
espdma_mem_readl, |
|||
}; |
|||
|
|||
static CPUWriteMemoryFunc *espdma_mem_write[3] = { |
|||
espdma_mem_writel, |
|||
espdma_mem_writel, |
|||
espdma_mem_writel, |
|||
}; |
|||
|
|||
static void esp_save(QEMUFile *f, void *opaque) |
|||
{ |
|||
ESPState *s = opaque; |
|||
|
|||
} |
|||
|
|||
static int esp_load(QEMUFile *f, void *opaque, int version_id) |
|||
{ |
|||
ESPState *s = opaque; |
|||
|
|||
if (version_id != 1) |
|||
return -EINVAL; |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr) |
|||
{ |
|||
ESPState *s; |
|||
int esp_io_memory, espdma_io_memory; |
|||
|
|||
s = qemu_mallocz(sizeof(ESPState)); |
|||
if (!s) |
|||
return; |
|||
|
|||
s->bd = bd; |
|||
s->irq = irq; |
|||
|
|||
esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s); |
|||
cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory); |
|||
|
|||
espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s); |
|||
cpu_register_physical_memory(espdaddr, 16, espdma_io_memory); |
|||
|
|||
esp_reset(s); |
|||
|
|||
register_savevm("esp", espaddr, 1, esp_save, esp_load, s); |
|||
qemu_register_reset(esp_reset, s); |
|||
} |
|||
|
|||
Binary file not shown.
File diff suppressed because it is too large
Loading…
Reference in new issue