?? mips_malta.c
字號:
/* * QEMU Malta board support * * Copyright (c) 2006 Aurelien Jarno * * 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 "hw.h"#include "pc.h"#include "fdc.h"#include "net.h"#include "boards.h"#include "smbus.h"#include "block.h"#include "flash.h"#include "mips.h"#include "pci.h"#include "qemu-char.h"#include "sysemu.h"#include "audio/audio.h"#include "boards.h"//#define DEBUG_BOARD_INIT#ifdef TARGET_WORDS_BIGENDIAN#define BIOS_FILENAME "mips_bios.bin"#else#define BIOS_FILENAME "mipsel_bios.bin"#endif#ifdef TARGET_MIPS64#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)#else#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)#endif#define ENVP_ADDR (int32_t)0x80002000#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))#define ENVP_NB_ENTRIES 16#define ENVP_ENTRY_SIZE 256#define MAX_IDE_BUS 2extern FILE *logfile;typedef struct { uint32_t leds; uint32_t brk; uint32_t gpout; uint32_t i2cin; uint32_t i2coe; uint32_t i2cout; uint32_t i2csel; CharDriverState *display; char display_text[9]; SerialState *uart;} MaltaFPGAState;static PITState *pit;static struct _loaderparams { int ram_size; const char *kernel_filename; const char *kernel_cmdline; const char *initrd_filename;} loaderparams;/* Malta FPGA */static void malta_fpga_update_display(void *opaque){ char leds_text[9]; int i; MaltaFPGAState *s = opaque; for (i = 7 ; i >= 0 ; i--) { if (s->leds & (1 << i)) leds_text[i] = '#'; else leds_text[i] = ' '; } leds_text[8] = '\0'; qemu_chr_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text); qemu_chr_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);}/* * EEPROM 24C01 / 24C02 emulation. * * Emulation for serial EEPROMs: * 24C01 - 1024 bit (128 x 8) * 24C02 - 2048 bit (256 x 8) * * Typical device names include Microchip 24C02SC or SGS Thomson ST24C02. *///~ #define DEBUG#if defined(DEBUG)# define logout(fmt, args...) fprintf(stderr, "MALTA\t%-24s" fmt, __func__, ##args)#else# define logout(fmt, args...) ((void)0)#endifstruct _eeprom24c0x_t { uint8_t tick; uint8_t address; uint8_t command; uint8_t ack; uint8_t scl; uint8_t sda; uint8_t data; //~ uint16_t size; uint8_t contents[256];};typedef struct _eeprom24c0x_t eeprom24c0x_t;static eeprom24c0x_t eeprom = { contents: { /* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00, /* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01, /* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00, /* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40, /* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00, /* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000038: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xD0, /* 00000040: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000048: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000050: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000058: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000060: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000068: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000070: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000078: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xF4, },};static uint8_t eeprom24c0x_read(){ logout("%u: scl = %u, sda = %u, data = 0x%02x\n", eeprom.tick, eeprom.scl, eeprom.sda, eeprom.data); return eeprom.sda;}static void eeprom24c0x_write(int scl, int sda){ if (eeprom.scl && scl && (eeprom.sda != sda)) { logout("%u: scl = %u->%u, sda = %u->%u i2c %s\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda, sda ? "stop" : "start"); if (!sda) { eeprom.tick = 1; eeprom.command = 0; } } else if (eeprom.tick == 0 && !eeprom.ack) { /* Waiting for start. */ logout("%u: scl = %u->%u, sda = %u->%u wait for i2c start\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda); } else if (!eeprom.scl && scl) { logout("%u: scl = %u->%u, sda = %u->%u trigger bit\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda); if (eeprom.ack) { logout("\ti2c ack bit = 0\n"); sda = 0; eeprom.ack = 0; } else if (eeprom.sda == sda) { uint8_t bit = (sda != 0); logout("\ti2c bit = %d\n", bit); if (eeprom.tick < 9) { eeprom.command <<= 1; eeprom.command += bit; eeprom.tick++; if (eeprom.tick == 9) { logout("\tcommand 0x%04x, %s\n", eeprom.command, bit ? "read" : "write"); eeprom.ack = 1; } } else if (eeprom.tick < 17) { if (eeprom.command & 1) { sda = ((eeprom.data & 0x80) != 0); } eeprom.address <<= 1; eeprom.address += bit; eeprom.tick++; eeprom.data <<= 1; if (eeprom.tick == 17) { eeprom.data = eeprom.contents[eeprom.address]; logout("\taddress 0x%04x, data 0x%02x\n", eeprom.address, eeprom.data); eeprom.ack = 1; eeprom.tick = 0; } } else if (eeprom.tick >= 17) { sda = 0; } } else { logout("\tsda changed with raising scl\n"); } } else { logout("%u: scl = %u->%u, sda = %u->%u\n", eeprom.tick, eeprom.scl, scl, eeprom.sda, sda); } eeprom.scl = scl; eeprom.sda = sda;}static uint32_t malta_fpga_readl(void *opaque, target_phys_addr_t addr){ MaltaFPGAState *s = opaque; uint32_t val = 0; uint32_t saddr; saddr = (addr & 0xfffff); switch (saddr) { /* SWITCH Register */ case 0x00200: val = 0x00000000; /* All switches closed */ break; /* STATUS Register */ case 0x00208:#ifdef TARGET_WORDS_BIGENDIAN val = 0x00000012;#else val = 0x00000010;#endif break; /* JMPRS Register */ case 0x00210: val = 0x00; break; /* LEDBAR Register */ case 0x00408: val = s->leds; break; /* BRKRES Register */ case 0x00508: val = s->brk; break; /* UART Registers are handled directly by the serial device */ /* GPOUT Register */ case 0x00a00: val = s->gpout; break; /* XXX: implement a real I2C controller */ /* GPINP Register */ case 0x00a08: /* IN = OUT until a real I2C control is implemented */ if (s->i2csel) val = s->i2cout; else val = 0x00; break; /* I2CINP Register */ case 0x00b00: val = ((s->i2cin & ~1) | eeprom24c0x_read()); break; /* I2COE Register */ case 0x00b08: val = s->i2coe; break; /* I2COUT Register */ case 0x00b10: val = s->i2cout; break; /* I2CSEL Register */ case 0x00b18: val = s->i2csel; break; default:#if 0 printf ("malta_fpga_read: Bad register offset 0x" TARGET_FMT_lx "\n", addr);#endif break; } return val;}static void malta_fpga_writel(void *opaque, target_phys_addr_t addr, uint32_t val){ MaltaFPGAState *s = opaque; uint32_t saddr; saddr = (addr & 0xfffff); switch (saddr) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -