|
|
1.1 ! root 1: /****************************************************************************** ! 2: * Copyright (c) 2004, 2008 IBM Corporation ! 3: * All rights reserved. ! 4: * This program and the accompanying materials ! 5: * are made available under the terms of the BSD License ! 6: * which accompanies this distribution, and is available at ! 7: * http://www.opensource.org/licenses/bsd-license.php ! 8: * ! 9: * Contributors: ! 10: * IBM Corporation - initial implementation ! 11: *****************************************************************************/ ! 12: ! 13: #include <stdio.h> ! 14: #include <cpu.h> ! 15: #include "device.h" ! 16: #include "rtas.h" ! 17: #include "debug.h" ! 18: #include "device.h" ! 19: #include <stdint.h> ! 20: #include <x86emu/x86emu.h> ! 21: #include <time.h> ! 22: ! 23: // those are defined in net-snk/oflib/pci.c ! 24: extern unsigned int read_io(void *, size_t); ! 25: extern int write_io(void *, unsigned int, size_t); ! 26: ! 27: //defined in net-snk/kernel/timer.c ! 28: extern uint64_t get_time(void); ! 29: ! 30: // these are not used, only needed for linking, must be overridden using X86emu_setupPioFuncs ! 31: // with the functions and struct below ! 32: void ! 33: outb(uint8_t val, uint16_t port) ! 34: { ! 35: printf("WARNING: outb not implemented!\n"); ! 36: HALT_SYS(); ! 37: } ! 38: ! 39: void ! 40: outw(uint16_t val, uint16_t port) ! 41: { ! 42: printf("WARNING: outw not implemented!\n"); ! 43: HALT_SYS(); ! 44: } ! 45: ! 46: void ! 47: outl(uint32_t val, uint16_t port) ! 48: { ! 49: printf("WARNING: outl not implemented!\n"); ! 50: HALT_SYS(); ! 51: } ! 52: ! 53: uint8_t ! 54: inb(uint16_t port) ! 55: { ! 56: printf("WARNING: inb not implemented!\n"); ! 57: HALT_SYS(); ! 58: return 0; ! 59: } ! 60: ! 61: uint16_t ! 62: inw(uint16_t port) ! 63: { ! 64: printf("WARNING: inw not implemented!\n"); ! 65: HALT_SYS(); ! 66: return 0; ! 67: } ! 68: ! 69: uint32_t ! 70: inl(uint16_t port) ! 71: { ! 72: printf("WARNING: inl not implemented!\n"); ! 73: HALT_SYS(); ! 74: return 0; ! 75: } ! 76: ! 77: uint32_t pci_cfg_read(X86EMU_pioAddr addr, uint8_t size); ! 78: void pci_cfg_write(X86EMU_pioAddr addr, uint32_t val, uint8_t size); ! 79: uint8_t handle_port_61h(); ! 80: ! 81: uint8_t ! 82: my_inb(X86EMU_pioAddr addr) ! 83: { ! 84: uint8_t rval = 0xFF; ! 85: uint64_t translated_addr = addr; ! 86: uint8_t translated = dev_translate_address(&translated_addr); ! 87: if (translated != 0) { ! 88: //translation successfull, access Device I/O (BAR or Legacy...) ! 89: DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__, ! 90: addr); ! 91: //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); ! 92: rval = read_io((void *)translated_addr, 1); ! 93: DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %02x\n", __FUNCTION__, ! 94: addr, rval); ! 95: return rval; ! 96: } else { ! 97: switch (addr) { ! 98: case 0x61: ! 99: //8254 KB Controller / Timer Port ! 100: rval = handle_port_61h(); ! 101: //DEBUG_PRINTF_IO("%s(%04x) KB / Timer Port B --> %02x\n", __FUNCTION__, addr, rval); ! 102: return rval; ! 103: break; ! 104: case 0xCFC: ! 105: case 0xCFD: ! 106: case 0xCFE: ! 107: case 0xCFF: ! 108: // PCI Config Mechanism 1 Ports ! 109: return (uint8_t) pci_cfg_read(addr, 1); ! 110: break; ! 111: case 0x0a: ! 112: CHECK_DBG(DEBUG_INTR) { ! 113: X86EMU_trace_on(); ! 114: } ! 115: M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F; ! 116: //HALT_SYS(); ! 117: // no break, intentional fall-through to default!! ! 118: default: ! 119: DEBUG_PRINTF_IO ! 120: ("%s(%04x) reading from bios_device.io_buffer\n", ! 121: __FUNCTION__, addr); ! 122: rval = *((uint8_t *) (bios_device.io_buffer + addr)); ! 123: DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %02x\n", ! 124: __FUNCTION__, addr, rval); ! 125: return rval; ! 126: break; ! 127: } ! 128: } ! 129: } ! 130: ! 131: uint16_t ! 132: my_inw(X86EMU_pioAddr addr) ! 133: { ! 134: uint64_t translated_addr = addr; ! 135: uint8_t translated = dev_translate_address(&translated_addr); ! 136: if (translated != 0) { ! 137: //translation successfull, access Device I/O (BAR or Legacy...) ! 138: DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__, ! 139: addr); ! 140: //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); ! 141: uint16_t rval; ! 142: if ((translated_addr & (uint64_t) 0x1) == 0) { ! 143: // 16 bit aligned access... ! 144: uint16_t tempval = read_io((void *)translated_addr, 2); ! 145: //little endian conversion ! 146: rval = in16le((void *) &tempval); ! 147: } else { ! 148: // unaligned access, read single bytes, little-endian ! 149: rval = (read_io((void *)translated_addr, 1) << 8) ! 150: | (read_io((void *)(translated_addr + 1), 1)); ! 151: } ! 152: DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %04x\n", __FUNCTION__, ! 153: addr, rval); ! 154: return rval; ! 155: } else { ! 156: switch (addr) { ! 157: case 0xCFC: ! 158: case 0xCFE: ! 159: //PCI Config Mechanism 1 ! 160: return (uint16_t) pci_cfg_read(addr, 2); ! 161: break; ! 162: default: ! 163: DEBUG_PRINTF_IO ! 164: ("%s(%04x) reading from bios_device.io_buffer\n", ! 165: __FUNCTION__, addr); ! 166: uint16_t rval = ! 167: in16le((void *) bios_device.io_buffer + addr); ! 168: DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %04x\n", ! 169: __FUNCTION__, addr, rval); ! 170: return rval; ! 171: break; ! 172: } ! 173: } ! 174: } ! 175: ! 176: uint32_t ! 177: my_inl(X86EMU_pioAddr addr) ! 178: { ! 179: uint64_t translated_addr = addr; ! 180: uint8_t translated = dev_translate_address(&translated_addr); ! 181: if (translated != 0) { ! 182: //translation successfull, access Device I/O (BAR or Legacy...) ! 183: DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__, ! 184: addr); ! 185: //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); ! 186: uint32_t rval; ! 187: if ((translated_addr & (uint64_t) 0x3) == 0) { ! 188: // 32 bit aligned access... ! 189: uint32_t tempval = read_io((void *) translated_addr, 4); ! 190: //little endian conversion ! 191: rval = in32le((void *) &tempval); ! 192: } else { ! 193: // unaligned access, read single bytes, little-endian ! 194: rval = (read_io((void *)(translated_addr), 1) << 24) ! 195: | (read_io((void *)(translated_addr + 1), 1) << 16) ! 196: | (read_io((void *)(translated_addr + 2), 1) << 8) ! 197: | (read_io((void *)(translated_addr + 3), 1)); ! 198: } ! 199: DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %08x\n", __FUNCTION__, ! 200: addr, rval); ! 201: return rval; ! 202: } else { ! 203: switch (addr) { ! 204: case 0xCFC: ! 205: //PCI Config Mechanism 1 ! 206: return pci_cfg_read(addr, 4); ! 207: break; ! 208: default: ! 209: DEBUG_PRINTF_IO ! 210: ("%s(%04x) reading from bios_device.io_buffer\n", ! 211: __FUNCTION__, addr); ! 212: uint32_t rval = ! 213: in32le((void *) bios_device.io_buffer + addr); ! 214: DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %08x\n", ! 215: __FUNCTION__, addr, rval); ! 216: return rval; ! 217: break; ! 218: } ! 219: } ! 220: } ! 221: ! 222: void ! 223: my_outb(X86EMU_pioAddr addr, uint8_t val) ! 224: { ! 225: uint64_t translated_addr = addr; ! 226: uint8_t translated = dev_translate_address(&translated_addr); ! 227: if (translated != 0) { ! 228: //translation successfull, access Device I/O (BAR or Legacy...) ! 229: DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n", ! 230: __FUNCTION__, addr, val); ! 231: //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); ! 232: write_io((void *) translated_addr, val, 1); ! 233: DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %02x\n", __FUNCTION__, ! 234: addr, val); ! 235: } else { ! 236: switch (addr) { ! 237: case 0xCFC: ! 238: case 0xCFD: ! 239: case 0xCFE: ! 240: case 0xCFF: ! 241: // PCI Config Mechanism 1 Ports ! 242: pci_cfg_write(addr, val, 1); ! 243: break; ! 244: default: ! 245: DEBUG_PRINTF_IO ! 246: ("%s(%04x,%02x) writing to bios_device.io_buffer\n", ! 247: __FUNCTION__, addr, val); ! 248: *((uint8_t *) (bios_device.io_buffer + addr)) = val; ! 249: break; ! 250: } ! 251: } ! 252: } ! 253: ! 254: void ! 255: my_outw(X86EMU_pioAddr addr, uint16_t val) ! 256: { ! 257: uint64_t translated_addr = addr; ! 258: uint8_t translated = dev_translate_address(&translated_addr); ! 259: if (translated != 0) { ! 260: //translation successfull, access Device I/O (BAR or Legacy...) ! 261: DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n", ! 262: __FUNCTION__, addr, val); ! 263: //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); ! 264: if ((translated_addr & (uint64_t) 0x1) == 0) { ! 265: // little-endian conversion ! 266: uint16_t tempval = in16le((void *) &val); ! 267: // 16 bit aligned access... ! 268: write_io((void *) translated_addr, tempval, 2); ! 269: } else { ! 270: // unaligned access, write single bytes, little-endian ! 271: write_io(((void *) (translated_addr + 1)), ! 272: (uint8_t) ((val & 0xFF00) >> 8), 1); ! 273: write_io(((void *) translated_addr), ! 274: (uint8_t) (val & 0x00FF), 1); ! 275: } ! 276: DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %04x\n", __FUNCTION__, ! 277: addr, val); ! 278: } else { ! 279: switch (addr) { ! 280: case 0xCFC: ! 281: case 0xCFE: ! 282: // PCI Config Mechanism 1 Ports ! 283: pci_cfg_write(addr, val, 2); ! 284: break; ! 285: default: ! 286: DEBUG_PRINTF_IO ! 287: ("%s(%04x,%04x) writing to bios_device.io_buffer\n", ! 288: __FUNCTION__, addr, val); ! 289: out16le((void *) bios_device.io_buffer + addr, val); ! 290: break; ! 291: } ! 292: } ! 293: } ! 294: ! 295: void ! 296: my_outl(X86EMU_pioAddr addr, uint32_t val) ! 297: { ! 298: uint64_t translated_addr = addr; ! 299: uint8_t translated = dev_translate_address(&translated_addr); ! 300: if (translated != 0) { ! 301: //translation successfull, access Device I/O (BAR or Legacy...) ! 302: DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n", ! 303: __FUNCTION__, addr, val); ! 304: //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr); ! 305: if ((translated_addr & (uint64_t) 0x3) == 0) { ! 306: // little-endian conversion ! 307: uint32_t tempval = in32le((void *) &val); ! 308: // 32 bit aligned access... ! 309: write_io((void *) translated_addr, tempval, 4); ! 310: } else { ! 311: // unaligned access, write single bytes, little-endian ! 312: write_io(((void *) translated_addr + 3), ! 313: (uint8_t) ((val & 0xFF000000) >> 24), 1); ! 314: write_io(((void *) translated_addr + 2), ! 315: (uint8_t) ((val & 0x00FF0000) >> 16), 1); ! 316: write_io(((void *) translated_addr + 1), ! 317: (uint8_t) ((val & 0x0000FF00) >> 8), 1); ! 318: write_io(((void *) translated_addr), ! 319: (uint8_t) (val & 0x000000FF), 1); ! 320: } ! 321: DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %08x\n", __FUNCTION__, ! 322: addr, val); ! 323: } else { ! 324: switch (addr) { ! 325: case 0xCFC: ! 326: // PCI Config Mechanism 1 Ports ! 327: pci_cfg_write(addr, val, 4); ! 328: break; ! 329: default: ! 330: DEBUG_PRINTF_IO ! 331: ("%s(%04x,%08x) writing to bios_device.io_buffer\n", ! 332: __FUNCTION__, addr, val); ! 333: out32le((void *) bios_device.io_buffer + addr, val); ! 334: break; ! 335: } ! 336: } ! 337: } ! 338: ! 339: uint32_t ! 340: pci_cfg_read(X86EMU_pioAddr addr, uint8_t size) ! 341: { ! 342: uint32_t rval = 0xFFFFFFFF; ! 343: if ((addr >= 0xCFC) && ((addr + size) <= 0xCFF)) { ! 344: // PCI Configuration Mechanism 1 step 1 ! 345: // write to 0xCF8, sets bus, device, function and Config Space offset ! 346: // later read from 0xCFC-0xCFF returns the value... ! 347: uint8_t bus, devfn, offs; ! 348: uint32_t port_cf8_val = my_inl(0xCF8); ! 349: if ((port_cf8_val & 0x80000000) != 0) { ! 350: //highest bit enables config space mapping ! 351: bus = (port_cf8_val & 0x00FF0000) >> 16; ! 352: devfn = (port_cf8_val & 0x0000FF00) >> 8; ! 353: offs = (port_cf8_val & 0x000000FF); ! 354: offs += (addr - 0xCFC); // if addr is not 0xcfc, the offset is moved accordingly ! 355: if ((bus != bios_device.bus) ! 356: || (devfn != bios_device.devfn)) { ! 357: // fail accesses to any device but ours... ! 358: printf ! 359: ("Config access invalid! bus: %x, devfn: %x, offs: %x\n", ! 360: bus, devfn, offs); ! 361: HALT_SYS(); ! 362: } else { ! 363: rval = ! 364: (uint32_t) rtas_pci_config_read(bios_device. ! 365: puid, size, ! 366: bus, devfn, ! 367: offs); ! 368: DEBUG_PRINTF_IO ! 369: ("%s(%04x) PCI Config Read @%02x, size: %d --> 0x%08x\n", ! 370: __FUNCTION__, addr, offs, size, rval); ! 371: } ! 372: } ! 373: } ! 374: return rval; ! 375: } ! 376: ! 377: void ! 378: pci_cfg_write(X86EMU_pioAddr addr, uint32_t val, uint8_t size) ! 379: { ! 380: if ((addr >= 0xCFC) && ((addr + size) <= 0xCFF)) { ! 381: // PCI Configuration Mechanism 1 step 1 ! 382: // write to 0xCF8, sets bus, device, function and Config Space offset ! 383: // later write to 0xCFC-0xCFF sets the value... ! 384: uint8_t bus, devfn, offs; ! 385: uint32_t port_cf8_val = my_inl(0xCF8); ! 386: if ((port_cf8_val & 0x80000000) != 0) { ! 387: //highest bit enables config space mapping ! 388: bus = (port_cf8_val & 0x00FF0000) >> 16; ! 389: devfn = (port_cf8_val & 0x0000FF00) >> 8; ! 390: offs = (port_cf8_val & 0x000000FF); ! 391: offs += (addr - 0xCFC); // if addr is not 0xcfc, the offset is moved accordingly ! 392: if ((bus != bios_device.bus) ! 393: || (devfn != bios_device.devfn)) { ! 394: // fail accesses to any device but ours... ! 395: printf ! 396: ("Config access invalid! bus: %x, devfn: %x, offs: %x\n", ! 397: bus, devfn, offs); ! 398: HALT_SYS(); ! 399: } else { ! 400: rtas_pci_config_write(bios_device.puid, ! 401: size, bus, devfn, offs, ! 402: val); ! 403: DEBUG_PRINTF_IO ! 404: ("%s(%04x) PCI Config Write @%02x, size: %d <-- 0x%08x\n", ! 405: __FUNCTION__, addr, offs, size, val); ! 406: } ! 407: } ! 408: } ! 409: } ! 410: ! 411: uint8_t ! 412: handle_port_61h() ! 413: { ! 414: static uint64_t last_time = 0; ! 415: uint64_t curr_time = get_time(); ! 416: uint64_t time_diff; // time since last call ! 417: uint32_t period_ticks; // length of a period in ticks ! 418: uint32_t nr_periods; //number of periods passed since last call ! 419: // bit 4 should toggle with every (DRAM) refresh cycle... (66kHz??) ! 420: time_diff = curr_time - last_time; ! 421: // at 66kHz a period is ~ 15 ns long, converted to ticks: (tb_freq is ticks/second) ! 422: // TODO: as long as the frequency does not change, we should not calculate this every time ! 423: period_ticks = (15 * tb_freq) / 1000000; ! 424: nr_periods = time_diff / period_ticks; ! 425: // if the number if ticks passed since last call is odd, we toggle bit 4 ! 426: if ((nr_periods % 2) != 0) { ! 427: *((uint8_t *) (bios_device.io_buffer + 0x61)) ^= 0x10; ! 428: } ! 429: //finally read the value from the io_buffer ! 430: return *((uint8_t *) (bios_device.io_buffer + 0x61)); ! 431: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.