1 /******************************************************************************
2 * Copyright (c) 2004, 2008 IBM Corporation
3 * Copyright (c) 2009 Pattrick Hueper <phueper@hueper.net>
5 * This program and the accompanying materials
6 * are made available under the terms of the BSD License
7 * which accompanies this distribution, and is available at
8 * http://www.opensource.org/licenses/bsd-license.php
11 * IBM Corporation - initial implementation
12 *****************************************************************************/
15 #include "compat/rtas.h"
16 #include "compat/time.h"
19 #include <x86emu/x86emu.h>
22 #ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
23 #include <device/pci.h>
24 #include <device/pci_ops.h>
27 // those are defined in net-snk/oflib/pci.c
28 extern unsigned int read_io(void *, size_t);
29 extern int write_io(void *, unsigned int, size_t);
31 //defined in net-snk/kernel/timer.c
32 extern u64 get_time(void);
34 #ifdef CONFIG_ARCH_X86
37 // these are not used, only needed for linking, must be overridden using X86emu_setupPioFuncs
38 // with the functions and struct below
40 outb(u8 val, u16 port)
42 printf("WARNING: outb not implemented!\n");
47 outw(u16 val, u16 port)
49 printf("WARNING: outw not implemented!\n");
54 outl(u32 val, u16 port)
56 printf("WARNING: outl not implemented!\n");
63 printf("WARNING: inb not implemented!\n");
71 printf("WARNING: inw not implemented!\n");
79 printf("WARNING: inl not implemented!\n");
85 #if defined(CONFIG_YABEL_DIRECTHW) && (CONFIG_YABEL_DIRECTHW == 1)
86 u8 my_inb(X86EMU_pioAddr addr)
91 DEBUG_PRINTF_IO("inb(0x%04x) = 0x%02x\n", addr, val);
96 u16 my_inw(X86EMU_pioAddr addr)
101 DEBUG_PRINTF_IO("inw(0x%04x) = 0x%04x\n", addr, val);
106 u32 my_inl(X86EMU_pioAddr addr)
111 DEBUG_PRINTF_IO("inl(0x%04x) = 0x%08x\n", addr, val);
116 void my_outb(X86EMU_pioAddr addr, u8 val)
118 DEBUG_PRINTF_IO("outb(0x%02x, 0x%04x)\n", val, addr);
122 void my_outw(X86EMU_pioAddr addr, u16 val)
124 DEBUG_PRINTF_IO("outw(0x%04x, 0x%04x)\n", val, addr);
128 void my_outl(X86EMU_pioAddr addr, u32 val)
130 DEBUG_PRINTF_IO("outl(0x%08x, 0x%04x)\n", val, addr);
136 u32 pci_cfg_read(X86EMU_pioAddr addr, u8 size);
137 void pci_cfg_write(X86EMU_pioAddr addr, u32 val, u8 size);
138 u8 handle_port_61h(void);
141 my_inb(X86EMU_pioAddr addr)
144 unsigned long translated_addr = addr;
145 u8 translated = biosemu_dev_translate_address(&translated_addr);
146 if (translated != 0) {
147 //translation successfull, access Device I/O (BAR or Legacy...)
148 DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __func__,
150 //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __func__, addr, translated_addr);
151 rval = read_io((void *)translated_addr, 1);
152 DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %02x\n", __func__,
158 //8254 KB Controller / Timer Port
159 // rval = handle_port_61h();
161 //DEBUG_PRINTF_IO("%s(%04x) KB / Timer Port B --> %02x\n", __func__, addr, rval);
168 // PCI Config Mechanism 1 Ports
169 return (u8) pci_cfg_read(addr, 1);
172 CHECK_DBG(DEBUG_INTR) {
175 M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
177 // no break, intentional fall-through to default!!
180 ("%s(%04x) reading from bios_device.io_buffer\n",
182 rval = *((u8 *) (bios_device.io_buffer + addr));
183 DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %02x\n",
184 __func__, addr, rval);
192 my_inw(X86EMU_pioAddr addr)
194 unsigned long translated_addr = addr;
195 u8 translated = biosemu_dev_translate_address(&translated_addr);
196 if (translated != 0) {
197 //translation successfull, access Device I/O (BAR or Legacy...)
198 DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __func__,
200 //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __func__, addr, translated_addr);
202 if ((translated_addr & (u64) 0x1) == 0) {
203 // 16 bit aligned access...
204 u16 tempval = read_io((void *)translated_addr, 2);
205 //little endian conversion
206 rval = in16le((void *) &tempval);
208 // unaligned access, read single bytes, little-endian
209 rval = (read_io((void *)translated_addr, 1) << 8)
210 | (read_io((void *)(translated_addr + 1), 1));
212 DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %04x\n", __func__,
219 //PCI Config Mechanism 1
220 return (u16) pci_cfg_read(addr, 2);
224 ("%s(%04x) reading from bios_device.io_buffer\n",
227 in16le((void *) bios_device.io_buffer + addr);
228 DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %04x\n",
229 __func__, addr, rval);
237 my_inl(X86EMU_pioAddr addr)
239 unsigned long translated_addr = addr;
240 u8 translated = biosemu_dev_translate_address(&translated_addr);
241 if (translated != 0) {
242 //translation successfull, access Device I/O (BAR or Legacy...)
243 DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __func__,
245 //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __func__, addr, translated_addr);
247 if ((translated_addr & (u64) 0x3) == 0) {
248 // 32 bit aligned access...
249 u32 tempval = read_io((void *) translated_addr, 4);
250 //little endian conversion
251 rval = in32le((void *) &tempval);
253 // unaligned access, read single bytes, little-endian
254 rval = (read_io((void *)(translated_addr), 1) << 24)
255 | (read_io((void *)(translated_addr + 1), 1) << 16)
256 | (read_io((void *)(translated_addr + 2), 1) << 8)
257 | (read_io((void *)(translated_addr + 3), 1));
259 DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %08x\n", __func__,
265 //PCI Config Mechanism 1
266 return pci_cfg_read(addr, 4);
270 ("%s(%04x) reading from bios_device.io_buffer\n",
273 in32le((void *) bios_device.io_buffer + addr);
274 DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %08x\n",
275 __func__, addr, rval);
283 my_outb(X86EMU_pioAddr addr, u8 val)
285 unsigned long translated_addr = addr;
286 u8 translated = biosemu_dev_translate_address(&translated_addr);
287 if (translated != 0) {
288 //translation successfull, access Device I/O (BAR or Legacy...)
289 DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n",
290 __func__, addr, val);
291 //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __func__, addr, translated_addr);
292 write_io((void *) translated_addr, val, 1);
293 DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %02x\n", __func__,
301 // PCI Config Mechanism 1 Ports
302 pci_cfg_write(addr, val, 1);
306 ("%s(%04x,%02x) writing to bios_device.io_buffer\n",
307 __func__, addr, val);
308 *((u8 *) (bios_device.io_buffer + addr)) = val;
315 my_outw(X86EMU_pioAddr addr, u16 val)
317 unsigned long translated_addr = addr;
318 u8 translated = biosemu_dev_translate_address(&translated_addr);
319 if (translated != 0) {
320 //translation successfull, access Device I/O (BAR or Legacy...)
321 DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n",
322 __func__, addr, val);
323 //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __func__, addr, translated_addr);
324 if ((translated_addr & (u64) 0x1) == 0) {
325 // little-endian conversion
326 u16 tempval = in16le((void *) &val);
327 // 16 bit aligned access...
328 write_io((void *) translated_addr, tempval, 2);
330 // unaligned access, write single bytes, little-endian
331 write_io(((void *) (translated_addr + 1)),
332 (u8) ((val & 0xFF00) >> 8), 1);
333 write_io(((void *) translated_addr),
334 (u8) (val & 0x00FF), 1);
336 DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %04x\n", __func__,
342 // PCI Config Mechanism 1 Ports
343 pci_cfg_write(addr, val, 2);
347 ("%s(%04x,%04x) writing to bios_device.io_buffer\n",
348 __func__, addr, val);
349 out16le((void *) bios_device.io_buffer + addr, val);
356 my_outl(X86EMU_pioAddr addr, u32 val)
358 unsigned long translated_addr = addr;
359 u8 translated = biosemu_dev_translate_address(&translated_addr);
360 if (translated != 0) {
361 //translation successfull, access Device I/O (BAR or Legacy...)
362 DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n",
363 __func__, addr, val);
364 //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __func__, addr, translated_addr);
365 if ((translated_addr & (u64) 0x3) == 0) {
366 // little-endian conversion
367 u32 tempval = in32le((void *) &val);
368 // 32 bit aligned access...
369 write_io((void *) translated_addr, tempval, 4);
371 // unaligned access, write single bytes, little-endian
372 write_io(((void *) translated_addr + 3),
373 (u8) ((val & 0xFF000000) >> 24), 1);
374 write_io(((void *) translated_addr + 2),
375 (u8) ((val & 0x00FF0000) >> 16), 1);
376 write_io(((void *) translated_addr + 1),
377 (u8) ((val & 0x0000FF00) >> 8), 1);
378 write_io(((void *) translated_addr),
379 (u8) (val & 0x000000FF), 1);
381 DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %08x\n", __func__,
386 // PCI Config Mechanism 1 Ports
387 pci_cfg_write(addr, val, 4);
391 ("%s(%04x,%08x) writing to bios_device.io_buffer\n",
392 __func__, addr, val);
393 out32le((void *) bios_device.io_buffer + addr, val);
400 pci_cfg_read(X86EMU_pioAddr addr, u8 size)
402 u32 rval = 0xFFFFFFFF;
404 if ((addr >= 0xCFC) && ((addr + size) <= 0xD00)) {
405 // PCI Configuration Mechanism 1 step 1
406 // write to 0xCF8, sets bus, device, function and Config Space offset
407 // later read from 0xCFC-0xCFF returns the value...
409 u32 port_cf8_val = my_inl(0xCF8);
410 if ((port_cf8_val & 0x80000000) != 0) {
411 //highest bit enables config space mapping
412 bus = (port_cf8_val & 0x00FF0000) >> 16;
413 devfn = (port_cf8_val & 0x0000FF00) >> 8;
414 offs = (port_cf8_val & 0x000000FF);
415 offs += (addr - 0xCFC); // if addr is not 0xcfc, the offset is moved accordingly
416 DEBUG_PRINTF_INTR("%s(): PCI Config Read from device: bus: %02x, devfn: %02x, offset: %02x\n",
417 __func__, bus, devfn, offs);
418 #if defined(CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES) && CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES==1
419 dev = dev_find_slot(bus, devfn);
420 DEBUG_PRINTF_INTR("%s(): dev_find_slot() returned: %s\n",
421 __func__, dev_path(dev));
423 // fail accesses to non-existent devices...
425 dev = bios_device.dev;
426 if ((bus != bios_device.bus)
427 || (devfn != bios_device.devfn)) {
428 // fail accesses to any device but ours...
431 ("%s(): Config read access invalid device! bus: %02x (%02x), devfn: %02x (%02x), offs: %02x\n",
432 __func__, bus, bios_device.bus, devfn,
433 bios_device.devfn, offs);
438 #ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
441 rval = pci_read_config8(dev, offs);
444 rval = pci_read_config16(dev, offs);
447 rval = pci_read_config32(dev, offs);
452 (u32) rtas_pci_config_read(bios_device.
458 ("%s(%04x) PCI Config Read @%02x, size: %d --> 0x%08x\n",
459 __func__, addr, offs, size, rval);
467 pci_cfg_write(X86EMU_pioAddr addr, u32 val, u8 size)
469 if ((addr >= 0xCFC) && ((addr + size) <= 0xD00)) {
470 // PCI Configuration Mechanism 1 step 1
471 // write to 0xCF8, sets bus, device, function and Config Space offset
472 // later write to 0xCFC-0xCFF sets the value...
474 u32 port_cf8_val = my_inl(0xCF8);
475 if ((port_cf8_val & 0x80000000) != 0) {
476 //highest bit enables config space mapping
477 bus = (port_cf8_val & 0x00FF0000) >> 16;
478 devfn = (port_cf8_val & 0x0000FF00) >> 8;
479 offs = (port_cf8_val & 0x000000FF);
480 offs += (addr - 0xCFC); // if addr is not 0xcfc, the offset is moved accordingly
481 if ((bus != bios_device.bus)
482 || (devfn != bios_device.devfn)) {
483 // fail accesses to any device but ours...
485 ("Config write access invalid! PCI device %x:%x.%x, offs: %x\n",
486 bus, devfn >> 3, devfn & 7, offs);
489 #ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
492 pci_write_config8(bios_device.dev, offs, val);
495 pci_write_config16(bios_device.dev, offs, val);
498 pci_write_config32(bios_device.dev, offs, val);
502 rtas_pci_config_write(bios_device.puid,
503 size, bus, devfn, offs,
507 ("%s(%04x) PCI Config Write @%02x, size: %d <-- 0x%08x\n",
508 __func__, addr, offs, size, val);
515 handle_port_61h(void)
517 static u64 last_time = 0;
518 u64 curr_time = get_time();
519 u64 time_diff; // time since last call
520 u32 period_ticks; // length of a period in ticks
521 u32 nr_periods; //number of periods passed since last call
522 // bit 4 should toggle with every (DRAM) refresh cycle... (66kHz??)
523 time_diff = curr_time - last_time;
524 // at 66kHz a period is ~ 15 ns long, converted to ticks: (tb_freq is ticks/second)
525 // TODO: as long as the frequency does not change, we should not calculate this every time
526 period_ticks = (15 * tb_freq) / 1000000;
527 nr_periods = time_diff / period_ticks;
528 // if the number if ticks passed since last call is odd, we toggle bit 4
529 if ((nr_periods % 2) != 0) {
530 *((u8 *) (bios_device.io_buffer + 0x61)) ^= 0x10;
532 //finally read the value from the io_buffer
533 return *((u8 *) (bios_device.io_buffer + 0x61));