|
|
1.1 ! root 1: /* ! 2: * QEMU Sun4u System Emulator ! 3: * ! 4: * Copyright (c) 2005 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: #include "m48t59.h" ! 26: ! 27: #define KERNEL_LOAD_ADDR 0x00404000 ! 28: #define CMDLINE_ADDR 0x003ff000 ! 29: #define INITRD_LOAD_ADDR 0x00300000 ! 30: #define PROM_ADDR 0x1fff0000000ULL ! 31: #define APB_SPECIAL_BASE 0x1fe00000000ULL ! 32: #define APB_MEM_BASE 0x1ff00000000ULL ! 33: #define VGA_BASE (APB_MEM_BASE + 0x400000ULL) ! 34: #define PROM_FILENAMEB "proll-sparc64.bin" ! 35: #define PROM_FILENAMEE "proll-sparc64.elf" ! 36: #define NVRAM_SIZE 0x2000 ! 37: ! 38: /* TSC handling */ ! 39: ! 40: uint64_t cpu_get_tsc() ! 41: { ! 42: return qemu_get_clock(vm_clock); ! 43: } ! 44: ! 45: int DMA_get_channel_mode (int nchan) ! 46: { ! 47: return 0; ! 48: } ! 49: int DMA_read_memory (int nchan, void *buf, int pos, int size) ! 50: { ! 51: return 0; ! 52: } ! 53: int DMA_write_memory (int nchan, void *buf, int pos, int size) ! 54: { ! 55: return 0; ! 56: } ! 57: void DMA_hold_DREQ (int nchan) {} ! 58: void DMA_release_DREQ (int nchan) {} ! 59: void DMA_schedule(int nchan) {} ! 60: void DMA_run (void) {} ! 61: void DMA_init (int high_page_enable) {} ! 62: void DMA_register_channel (int nchan, ! 63: DMA_transfer_handler transfer_handler, ! 64: void *opaque) ! 65: { ! 66: } ! 67: ! 68: /* NVRAM helpers */ ! 69: void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value) ! 70: { ! 71: m48t59_set_addr(nvram, addr); ! 72: m48t59_write(nvram, value); ! 73: } ! 74: ! 75: uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr) ! 76: { ! 77: m48t59_set_addr(nvram, addr); ! 78: return m48t59_read(nvram); ! 79: } ! 80: ! 81: void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value) ! 82: { ! 83: m48t59_set_addr(nvram, addr); ! 84: m48t59_write(nvram, value >> 8); ! 85: m48t59_set_addr(nvram, addr + 1); ! 86: m48t59_write(nvram, value & 0xFF); ! 87: } ! 88: ! 89: uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr) ! 90: { ! 91: uint16_t tmp; ! 92: ! 93: m48t59_set_addr(nvram, addr); ! 94: tmp = m48t59_read(nvram) << 8; ! 95: m48t59_set_addr(nvram, addr + 1); ! 96: tmp |= m48t59_read(nvram); ! 97: ! 98: return tmp; ! 99: } ! 100: ! 101: void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value) ! 102: { ! 103: m48t59_set_addr(nvram, addr); ! 104: m48t59_write(nvram, value >> 24); ! 105: m48t59_set_addr(nvram, addr + 1); ! 106: m48t59_write(nvram, (value >> 16) & 0xFF); ! 107: m48t59_set_addr(nvram, addr + 2); ! 108: m48t59_write(nvram, (value >> 8) & 0xFF); ! 109: m48t59_set_addr(nvram, addr + 3); ! 110: m48t59_write(nvram, value & 0xFF); ! 111: } ! 112: ! 113: uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr) ! 114: { ! 115: uint32_t tmp; ! 116: ! 117: m48t59_set_addr(nvram, addr); ! 118: tmp = m48t59_read(nvram) << 24; ! 119: m48t59_set_addr(nvram, addr + 1); ! 120: tmp |= m48t59_read(nvram) << 16; ! 121: m48t59_set_addr(nvram, addr + 2); ! 122: tmp |= m48t59_read(nvram) << 8; ! 123: m48t59_set_addr(nvram, addr + 3); ! 124: tmp |= m48t59_read(nvram); ! 125: ! 126: return tmp; ! 127: } ! 128: ! 129: void NVRAM_set_string (m48t59_t *nvram, uint32_t addr, ! 130: const unsigned char *str, uint32_t max) ! 131: { ! 132: int i; ! 133: ! 134: for (i = 0; i < max && str[i] != '\0'; i++) { ! 135: m48t59_set_addr(nvram, addr + i); ! 136: m48t59_write(nvram, str[i]); ! 137: } ! 138: m48t59_set_addr(nvram, addr + max - 1); ! 139: m48t59_write(nvram, '\0'); ! 140: } ! 141: ! 142: int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max) ! 143: { ! 144: int i; ! 145: ! 146: memset(dst, 0, max); ! 147: for (i = 0; i < max; i++) { ! 148: dst[i] = NVRAM_get_byte(nvram, addr + i); ! 149: if (dst[i] == '\0') ! 150: break; ! 151: } ! 152: ! 153: return i; ! 154: } ! 155: ! 156: static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value) ! 157: { ! 158: uint16_t tmp; ! 159: uint16_t pd, pd1, pd2; ! 160: ! 161: tmp = prev >> 8; ! 162: pd = prev ^ value; ! 163: pd1 = pd & 0x000F; ! 164: pd2 = ((pd >> 4) & 0x000F) ^ pd1; ! 165: tmp ^= (pd1 << 3) | (pd1 << 8); ! 166: tmp ^= pd2 | (pd2 << 7) | (pd2 << 12); ! 167: ! 168: return tmp; ! 169: } ! 170: ! 171: uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count) ! 172: { ! 173: uint32_t i; ! 174: uint16_t crc = 0xFFFF; ! 175: int odd; ! 176: ! 177: odd = count & 1; ! 178: count &= ~1; ! 179: for (i = 0; i != count; i++) { ! 180: crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i)); ! 181: } ! 182: if (odd) { ! 183: crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8); ! 184: } ! 185: ! 186: return crc; ! 187: } ! 188: ! 189: extern int nographic; ! 190: ! 191: int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size, ! 192: const unsigned char *arch, ! 193: uint32_t RAM_size, int boot_device, ! 194: uint32_t kernel_image, uint32_t kernel_size, ! 195: const char *cmdline, ! 196: uint32_t initrd_image, uint32_t initrd_size, ! 197: uint32_t NVRAM_image, ! 198: int width, int height, int depth) ! 199: { ! 200: uint16_t crc; ! 201: ! 202: /* Set parameters for Open Hack'Ware BIOS */ ! 203: NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16); ! 204: NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */ ! 205: NVRAM_set_word(nvram, 0x14, NVRAM_size); ! 206: NVRAM_set_string(nvram, 0x20, arch, 16); ! 207: NVRAM_set_byte(nvram, 0x2f, nographic & 0xff); ! 208: NVRAM_set_lword(nvram, 0x30, RAM_size); ! 209: NVRAM_set_byte(nvram, 0x34, boot_device); ! 210: NVRAM_set_lword(nvram, 0x38, kernel_image); ! 211: NVRAM_set_lword(nvram, 0x3C, kernel_size); ! 212: if (cmdline) { ! 213: /* XXX: put the cmdline in NVRAM too ? */ ! 214: strcpy(phys_ram_base + CMDLINE_ADDR, cmdline); ! 215: NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR); ! 216: NVRAM_set_lword(nvram, 0x44, strlen(cmdline)); ! 217: } else { ! 218: NVRAM_set_lword(nvram, 0x40, 0); ! 219: NVRAM_set_lword(nvram, 0x44, 0); ! 220: } ! 221: NVRAM_set_lword(nvram, 0x48, initrd_image); ! 222: NVRAM_set_lword(nvram, 0x4C, initrd_size); ! 223: NVRAM_set_lword(nvram, 0x50, NVRAM_image); ! 224: ! 225: NVRAM_set_word(nvram, 0x54, width); ! 226: NVRAM_set_word(nvram, 0x56, height); ! 227: NVRAM_set_word(nvram, 0x58, depth); ! 228: crc = NVRAM_compute_crc(nvram, 0x00, 0xF8); ! 229: NVRAM_set_word(nvram, 0xFC, crc); ! 230: ! 231: return 0; ! 232: } ! 233: ! 234: void pic_info() ! 235: { ! 236: } ! 237: ! 238: void irq_info() ! 239: { ! 240: } ! 241: ! 242: void pic_set_irq(int irq, int level) ! 243: { ! 244: } ! 245: ! 246: void pic_set_irq_new(void *opaque, int irq, int level) ! 247: { ! 248: } ! 249: ! 250: void qemu_system_powerdown(void) ! 251: { ! 252: } ! 253: ! 254: static const int ide_iobase[2] = { 0x1f0, 0x170 }; ! 255: static const int ide_iobase2[2] = { 0x3f6, 0x376 }; ! 256: static const int ide_irq[2] = { 14, 15 }; ! 257: ! 258: static const int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; ! 259: static const int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 }; ! 260: ! 261: static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc }; ! 262: static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; ! 263: ! 264: static fdctrl_t *floppy_controller; ! 265: ! 266: /* Sun4u hardware initialisation */ ! 267: static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, ! 268: DisplayState *ds, const char **fd_filename, int snapshot, ! 269: const char *kernel_filename, const char *kernel_cmdline, ! 270: const char *initrd_filename) ! 271: { ! 272: char buf[1024]; ! 273: m48t59_t *nvram; ! 274: int ret, linux_boot; ! 275: unsigned int i; ! 276: long prom_offset, initrd_size, kernel_size; ! 277: PCIBus *pci_bus; ! 278: ! 279: linux_boot = (kernel_filename != NULL); ! 280: ! 281: /* allocate RAM */ ! 282: cpu_register_physical_memory(0, ram_size, 0); ! 283: ! 284: prom_offset = ram_size + vga_ram_size; ! 285: ! 286: snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE); ! 287: ret = load_elf(buf, phys_ram_base + prom_offset); ! 288: if (ret < 0) { ! 289: snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB); ! 290: ret = load_image(buf, phys_ram_base + prom_offset); ! 291: } ! 292: if (ret < 0) { ! 293: fprintf(stderr, "qemu: could not load prom '%s'\n", ! 294: buf); ! 295: exit(1); ! 296: } ! 297: cpu_register_physical_memory(PROM_ADDR, (ret + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK, ! 298: prom_offset | IO_MEM_ROM); ! 299: ! 300: kernel_size = 0; ! 301: initrd_size = 0; ! 302: if (linux_boot) { ! 303: kernel_size = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); ! 304: if (kernel_size < 0) ! 305: kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); ! 306: if (kernel_size < 0) ! 307: kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR); ! 308: if (kernel_size < 0) { ! 309: fprintf(stderr, "qemu: could not load kernel '%s'\n", ! 310: kernel_filename); ! 311: exit(1); ! 312: } ! 313: ! 314: /* load initrd */ ! 315: if (initrd_filename) { ! 316: initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); ! 317: if (initrd_size < 0) { ! 318: fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", ! 319: initrd_filename); ! 320: exit(1); ! 321: } ! 322: } ! 323: if (initrd_size > 0) { ! 324: for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) { ! 325: if (ldl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i) ! 326: == 0x48647253) { // HdrS ! 327: stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 16, INITRD_LOAD_ADDR); ! 328: stl_raw(phys_ram_base + KERNEL_LOAD_ADDR + i + 20, initrd_size); ! 329: break; ! 330: } ! 331: } ! 332: } ! 333: } ! 334: pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE); ! 335: isa_mem_base = VGA_BASE; ! 336: vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, ! 337: vga_ram_size, 0, 0); ! 338: cpu_register_physical_memory(VGA_BASE, vga_ram_size, ram_size); ! 339: //pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + ram_size, ram_size, vga_ram_size); ! 340: ! 341: for(i = 0; i < MAX_SERIAL_PORTS; i++) { ! 342: if (serial_hds[i]) { ! 343: serial_init(serial_io[i], serial_irq[i], serial_hds[i]); ! 344: } ! 345: } ! 346: ! 347: for(i = 0; i < MAX_PARALLEL_PORTS; i++) { ! 348: if (parallel_hds[i]) { ! 349: parallel_init(parallel_io[i], parallel_irq[i], parallel_hds[i]); ! 350: } ! 351: } ! 352: ! 353: for(i = 0; i < nb_nics; i++) { ! 354: pci_ne2000_init(pci_bus, &nd_table[i]); ! 355: } ! 356: ! 357: pci_cmd646_ide_init(pci_bus, bs_table, 1); ! 358: kbd_init(); ! 359: floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); ! 360: nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE); ! 361: sun4u_NVRAM_set_params(nvram, NVRAM_SIZE, "Sun4u", ram_size, boot_device, ! 362: KERNEL_LOAD_ADDR, kernel_size, ! 363: kernel_cmdline, ! 364: INITRD_LOAD_ADDR, initrd_size, ! 365: /* XXX: need an option to load a NVRAM image */ ! 366: 0, ! 367: graphic_width, graphic_height, graphic_depth); ! 368: ! 369: } ! 370: ! 371: QEMUMachine sun4u_machine = { ! 372: "sun4u", ! 373: "Sun4u platform", ! 374: sun4u_init, ! 375: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.