1
/******************************************************************************
2
* Copyright (c) 2004, 2008 IBM Corporation
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
10
* IBM Corporation - initial implementation
11
*****************************************************************************/
21
#include <x86emu/x86emu.h>
25
//defined in net-snk/kernel/timer.c
26
extern uint64_t get_time(void);
28
// these are not used, only needed for linking, must be overridden using X86emu_setupPioFuncs
29
// with the functions and struct below
31
outb(uint8_t val, uint16_t port)
33
printf("WARNING: outb not implemented!\n");
38
outw(uint16_t val, uint16_t port)
40
printf("WARNING: outw not implemented!\n");
45
outl(uint32_t val, uint16_t port)
47
printf("WARNING: outl not implemented!\n");
54
printf("WARNING: inb not implemented!\n");
62
printf("WARNING: inw not implemented!\n");
70
printf("WARNING: inl not implemented!\n");
75
uint32_t pci_cfg_read(X86EMU_pioAddr addr, uint8_t size);
76
void pci_cfg_write(X86EMU_pioAddr addr, uint32_t val, uint8_t size);
77
uint8_t handle_port_61h();
80
my_inb(X86EMU_pioAddr addr)
83
uint64_t translated_addr = addr;
84
uint8_t translated = dev_translate_address(&translated_addr);
85
if (translated != 0) {
86
//translation successfull, access Device I/O (BAR or Legacy...)
87
DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__,
89
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
90
rval = read_io((void *)translated_addr, 1);
91
DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %02x\n", __FUNCTION__,
97
//8254 KB Controller / Timer Port
98
rval = handle_port_61h();
99
//DEBUG_PRINTF_IO("%s(%04x) KB / Timer Port B --> %02x\n", __FUNCTION__, addr, rval);
106
// PCI Config Mechanism 1 Ports
107
return (uint8_t) pci_cfg_read(addr, 1);
110
CHECK_DBG(DEBUG_INTR) {
113
M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
115
// no break, intentional fall-through to default!!
118
("%s(%04x) reading from bios_device.io_buffer\n",
120
rval = *((uint8_t *) (bios_device.io_buffer + addr));
121
DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %02x\n",
122
__FUNCTION__, addr, rval);
130
my_inw(X86EMU_pioAddr addr)
132
uint64_t translated_addr = addr;
133
uint8_t translated = dev_translate_address(&translated_addr);
134
if (translated != 0) {
135
//translation successfull, access Device I/O (BAR or Legacy...)
136
DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__,
138
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
140
if ((translated_addr & (uint64_t) 0x1) == 0) {
141
// 16 bit aligned access...
142
uint16_t tempval = read_io((void *)translated_addr, 2);
143
//little endian conversion
144
rval = in16le((void *) &tempval);
146
// unaligned access, read single bytes, little-endian
147
rval = (read_io((void *)translated_addr, 1) << 8)
148
| (read_io((void *)(translated_addr + 1), 1));
150
DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %04x\n", __FUNCTION__,
157
//PCI Config Mechanism 1
158
return (uint16_t) pci_cfg_read(addr, 2);
162
("%s(%04x) reading from bios_device.io_buffer\n",
165
in16le((void *) bios_device.io_buffer + addr);
166
DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %04x\n",
167
__FUNCTION__, addr, rval);
175
my_inl(X86EMU_pioAddr addr)
177
uint64_t translated_addr = addr;
178
uint8_t translated = dev_translate_address(&translated_addr);
179
if (translated != 0) {
180
//translation successfull, access Device I/O (BAR or Legacy...)
181
DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__,
183
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
185
if ((translated_addr & (uint64_t) 0x3) == 0) {
186
// 32 bit aligned access...
187
uint32_t tempval = read_io((void *) translated_addr, 4);
188
//little endian conversion
189
rval = in32le((void *) &tempval);
191
// unaligned access, read single bytes, little-endian
192
rval = (read_io((void *)(translated_addr), 1) << 24)
193
| (read_io((void *)(translated_addr + 1), 1) << 16)
194
| (read_io((void *)(translated_addr + 2), 1) << 8)
195
| (read_io((void *)(translated_addr + 3), 1));
197
DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %08x\n", __FUNCTION__,
203
//PCI Config Mechanism 1
204
return pci_cfg_read(addr, 4);
208
("%s(%04x) reading from bios_device.io_buffer\n",
211
in32le((void *) bios_device.io_buffer + addr);
212
DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %08x\n",
213
__FUNCTION__, addr, rval);
221
my_outb(X86EMU_pioAddr addr, uint8_t val)
223
uint64_t translated_addr = addr;
224
uint8_t translated = dev_translate_address(&translated_addr);
225
if (translated != 0) {
226
//translation successfull, access Device I/O (BAR or Legacy...)
227
DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n",
228
__FUNCTION__, addr, val);
229
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
230
write_io((void *) translated_addr, val, 1);
231
DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %02x\n", __FUNCTION__,
239
// PCI Config Mechanism 1 Ports
240
pci_cfg_write(addr, val, 1);
244
("%s(%04x,%02x) writing to bios_device.io_buffer\n",
245
__FUNCTION__, addr, val);
246
*((uint8_t *) (bios_device.io_buffer + addr)) = val;
253
my_outw(X86EMU_pioAddr addr, uint16_t val)
255
uint64_t translated_addr = addr;
256
uint8_t translated = dev_translate_address(&translated_addr);
257
if (translated != 0) {
258
//translation successfull, access Device I/O (BAR or Legacy...)
259
DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n",
260
__FUNCTION__, addr, val);
261
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
262
if ((translated_addr & (uint64_t) 0x1) == 0) {
263
// little-endian conversion
264
uint16_t tempval = in16le((void *) &val);
265
// 16 bit aligned access...
266
write_io((void *) translated_addr, tempval, 2);
268
// unaligned access, write single bytes, little-endian
269
write_io(((void *) (translated_addr + 1)),
270
(uint8_t) ((val & 0xFF00) >> 8), 1);
271
write_io(((void *) translated_addr),
272
(uint8_t) (val & 0x00FF), 1);
274
DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %04x\n", __FUNCTION__,
280
// PCI Config Mechanism 1 Ports
281
pci_cfg_write(addr, val, 2);
285
("%s(%04x,%04x) writing to bios_device.io_buffer\n",
286
__FUNCTION__, addr, val);
287
out16le((void *) bios_device.io_buffer + addr, val);
294
my_outl(X86EMU_pioAddr addr, uint32_t val)
296
uint64_t translated_addr = addr;
297
uint8_t translated = dev_translate_address(&translated_addr);
298
if (translated != 0) {
299
//translation successfull, access Device I/O (BAR or Legacy...)
300
DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n",
301
__FUNCTION__, addr, val);
302
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
303
if ((translated_addr & (uint64_t) 0x3) == 0) {
304
// little-endian conversion
305
uint32_t tempval = in32le((void *) &val);
306
// 32 bit aligned access...
307
write_io((void *) translated_addr, tempval, 4);
309
// unaligned access, write single bytes, little-endian
310
write_io(((void *) translated_addr + 3),
311
(uint8_t) ((val & 0xFF000000) >> 24), 1);
312
write_io(((void *) translated_addr + 2),
313
(uint8_t) ((val & 0x00FF0000) >> 16), 1);
314
write_io(((void *) translated_addr + 1),
315
(uint8_t) ((val & 0x0000FF00) >> 8), 1);
316
write_io(((void *) translated_addr),
317
(uint8_t) (val & 0x000000FF), 1);
319
DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %08x\n", __FUNCTION__,
324
// PCI Config Mechanism 1 Ports
325
pci_cfg_write(addr, val, 4);
329
("%s(%04x,%08x) writing to bios_device.io_buffer\n",
330
__FUNCTION__, addr, val);
331
out32le((void *) bios_device.io_buffer + addr, val);
338
pci_cfg_read(X86EMU_pioAddr addr, uint8_t size)
340
uint32_t rval = 0xFFFFFFFF;
341
if ((addr >= 0xCFC) && ((addr + size) <= 0xCFF)) {
342
// PCI Configuration Mechanism 1 step 1
343
// write to 0xCF8, sets bus, device, function and Config Space offset
344
// later read from 0xCFC-0xCFF returns the value...
345
uint8_t bus, devfn, offs;
346
uint32_t port_cf8_val = my_inl(0xCF8);
347
if ((port_cf8_val & 0x80000000) != 0) {
348
//highest bit enables config space mapping
349
bus = (port_cf8_val & 0x00FF0000) >> 16;
350
devfn = (port_cf8_val & 0x0000FF00) >> 8;
351
offs = (port_cf8_val & 0x000000FF);
352
offs += (addr - 0xCFC); // if addr is not 0xcfc, the offset is moved accordingly
353
if ((bus != bios_device.bus)
354
|| (devfn != bios_device.devfn)) {
355
// fail accesses to any device but ours...
357
("Config access invalid! bus: %x, devfn: %x, offs: %x\n",
362
(uint32_t) rtas_pci_config_read(bios_device.
367
("%s(%04x) PCI Config Read @%02x, size: %d --> 0x%08x\n",
368
__FUNCTION__, addr, offs, size, rval);
376
pci_cfg_write(X86EMU_pioAddr addr, uint32_t val, uint8_t size)
378
if ((addr >= 0xCFC) && ((addr + size) <= 0xCFF)) {
379
// PCI Configuration Mechanism 1 step 1
380
// write to 0xCF8, sets bus, device, function and Config Space offset
381
// later write to 0xCFC-0xCFF sets the value...
382
uint8_t bus, devfn, offs;
383
uint32_t port_cf8_val = my_inl(0xCF8);
384
if ((port_cf8_val & 0x80000000) != 0) {
385
//highest bit enables config space mapping
386
bus = (port_cf8_val & 0x00FF0000) >> 16;
387
devfn = (port_cf8_val & 0x0000FF00) >> 8;
388
offs = (port_cf8_val & 0x000000FF);
389
offs += (addr - 0xCFC); // if addr is not 0xcfc, the offset is moved accordingly
390
if ((bus != bios_device.bus)
391
|| (devfn != bios_device.devfn)) {
392
// fail accesses to any device but ours...
394
("Config access invalid! bus: %x, devfn: %x, offs: %x\n",
398
rtas_pci_config_write(bios_device.puid,
399
size, bus, devfn, offs,
402
("%s(%04x) PCI Config Write @%02x, size: %d <-- 0x%08x\n",
403
__FUNCTION__, addr, offs, size, val);
412
static uint64_t last_time = 0;
413
uint64_t curr_time = get_time();
414
uint64_t time_diff; // time since last call
415
uint32_t period_ticks; // length of a period in ticks
416
uint32_t nr_periods; //number of periods passed since last call
417
// bit 4 should toggle with every (DRAM) refresh cycle... (66kHz??)
418
time_diff = curr_time - last_time;
419
// at 66kHz a period is ~ 15 ns long, converted to ticks: (tb_freq is ticks/second)
420
// TODO: as long as the frequency does not change, we should not calculate this every time
421
period_ticks = (15 * tb_freq) / 1000000;
422
nr_periods = time_diff / period_ticks;
423
// if the number if ticks passed since last call is odd, we toggle bit 4
424
if ((nr_periods % 2) != 0) {
425
*((uint8_t *) (bios_device.io_buffer + 0x61)) ^= 0x10;
427
//finally read the value from the io_buffer
428
return *((uint8_t *) (bios_device.io_buffer + 0x61));