Annotation of qemu/roms/SLOF/clients/net-snk/app/biosemu/io.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.