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

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>
1.1.1.2 ! root       15: #include <pci.h>
1.1       root       16: #include "device.h"
                     17: #include "rtas.h"
                     18: #include "debug.h"
                     19: #include "device.h"
                     20: #include <stdint.h>
                     21: #include <x86emu/x86emu.h>
                     22: #include <time.h>
                     23: 
                     24: 
                     25: //defined in net-snk/kernel/timer.c
                     26: extern uint64_t get_time(void);
                     27: 
                     28: // these are not used, only needed for linking,  must be overridden using X86emu_setupPioFuncs
                     29: // with the functions and struct below
                     30: void
                     31: outb(uint8_t val, uint16_t port)
                     32: {
                     33:        printf("WARNING: outb not implemented!\n");
                     34:        HALT_SYS();
                     35: }
                     36: 
                     37: void
                     38: outw(uint16_t val, uint16_t port)
                     39: {
                     40:        printf("WARNING: outw not implemented!\n");
                     41:        HALT_SYS();
                     42: }
                     43: 
                     44: void
                     45: outl(uint32_t val, uint16_t port)
                     46: {
                     47:        printf("WARNING: outl not implemented!\n");
                     48:        HALT_SYS();
                     49: }
                     50: 
                     51: uint8_t
                     52: inb(uint16_t port)
                     53: {
                     54:        printf("WARNING: inb not implemented!\n");
                     55:        HALT_SYS();
                     56:        return 0;
                     57: }
                     58: 
                     59: uint16_t
                     60: inw(uint16_t port)
                     61: {
                     62:        printf("WARNING: inw not implemented!\n");
                     63:        HALT_SYS();
                     64:        return 0;
                     65: }
                     66: 
                     67: uint32_t
                     68: inl(uint16_t port)
                     69: {
                     70:        printf("WARNING: inl not implemented!\n");
                     71:        HALT_SYS();
                     72:        return 0;
                     73: }
                     74: 
                     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();
                     78: 
                     79: uint8_t
                     80: my_inb(X86EMU_pioAddr addr)
                     81: {
                     82:        uint8_t rval = 0xFF;
                     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__,
                     88:                                addr);
                     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__,
                     92:                                addr, rval);
                     93:                return rval;
                     94:        } else {
                     95:                switch (addr) {
                     96:                case 0x61:
                     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);
                    100:                        return rval;
                    101:                        break;
                    102:                case 0xCFC:
                    103:                case 0xCFD:
                    104:                case 0xCFE:
                    105:                case 0xCFF:
                    106:                        // PCI Config Mechanism 1 Ports
                    107:                        return (uint8_t) pci_cfg_read(addr, 1);
                    108:                        break;
                    109:                case 0x0a:
                    110:                        CHECK_DBG(DEBUG_INTR) {
                    111:                                X86EMU_trace_on();
                    112:                        }
                    113:                        M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
                    114:                        //HALT_SYS();
                    115:                        // no break, intentional fall-through to default!!
                    116:                default:
                    117:                        DEBUG_PRINTF_IO
                    118:                            ("%s(%04x) reading from bios_device.io_buffer\n",
                    119:                             __FUNCTION__, addr);
                    120:                        rval = *((uint8_t *) (bios_device.io_buffer + addr));
                    121:                        DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %02x\n",
                    122:                                        __FUNCTION__, addr, rval);
                    123:                        return rval;
                    124:                        break;
                    125:                }
                    126:        }
                    127: }
                    128: 
                    129: uint16_t
                    130: my_inw(X86EMU_pioAddr addr)
                    131: {
                    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__,
                    137:                                addr);
                    138:                //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
                    139:                uint16_t rval;
                    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);
                    145:                } else {
                    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));
                    149:                }
                    150:                DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %04x\n", __FUNCTION__,
                    151:                                addr, rval);
                    152:                return rval;
                    153:        } else {
                    154:                switch (addr) {
                    155:                case 0xCFC:
                    156:                case 0xCFE:
                    157:                        //PCI Config Mechanism 1
                    158:                        return (uint16_t) pci_cfg_read(addr, 2);
                    159:                        break;
                    160:                default:
                    161:                        DEBUG_PRINTF_IO
                    162:                            ("%s(%04x) reading from bios_device.io_buffer\n",
                    163:                             __FUNCTION__, addr);
                    164:                        uint16_t rval =
                    165:                            in16le((void *) bios_device.io_buffer + addr);
                    166:                        DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %04x\n",
                    167:                                        __FUNCTION__, addr, rval);
                    168:                        return rval;
                    169:                        break;
                    170:                }
                    171:        }
                    172: }
                    173: 
                    174: uint32_t
                    175: my_inl(X86EMU_pioAddr addr)
                    176: {
                    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__,
                    182:                                addr);
                    183:                //DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
                    184:                uint32_t rval;
                    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);
                    190:                } else {
                    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));
                    196:                }
                    197:                DEBUG_PRINTF_IO("%s(%04x) Device I/O --> %08x\n", __FUNCTION__,
                    198:                                addr, rval);
                    199:                return rval;
                    200:        } else {
                    201:                switch (addr) {
                    202:                case 0xCFC:
                    203:                        //PCI Config Mechanism 1
                    204:                        return pci_cfg_read(addr, 4);
                    205:                        break;
                    206:                default:
                    207:                        DEBUG_PRINTF_IO
                    208:                            ("%s(%04x) reading from bios_device.io_buffer\n",
                    209:                             __FUNCTION__, addr);
                    210:                        uint32_t rval =
                    211:                            in32le((void *) bios_device.io_buffer + addr);
                    212:                        DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %08x\n",
                    213:                                        __FUNCTION__, addr, rval);
                    214:                        return rval;
                    215:                        break;
                    216:                }
                    217:        }
                    218: }
                    219: 
                    220: void
                    221: my_outb(X86EMU_pioAddr addr, uint8_t val)
                    222: {
                    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__,
                    232:                                addr, val);
                    233:        } else {
                    234:                switch (addr) {
                    235:                case 0xCFC:
                    236:                case 0xCFD:
                    237:                case 0xCFE:
                    238:                case 0xCFF:
                    239:                        // PCI Config Mechanism 1 Ports
                    240:                        pci_cfg_write(addr, val, 1);
                    241:                        break;
                    242:                default:
                    243:                        DEBUG_PRINTF_IO
                    244:                            ("%s(%04x,%02x) writing to bios_device.io_buffer\n",
                    245:                             __FUNCTION__, addr, val);
                    246:                        *((uint8_t *) (bios_device.io_buffer + addr)) = val;
                    247:                        break;
                    248:                }
                    249:        }
                    250: }
                    251: 
                    252: void
                    253: my_outw(X86EMU_pioAddr addr, uint16_t val)
                    254: {
                    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);
                    267:                } else {
                    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);
                    273:                }
                    274:                DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %04x\n", __FUNCTION__,
                    275:                                addr, val);
                    276:        } else {
                    277:                switch (addr) {
                    278:                case 0xCFC:
                    279:                case 0xCFE:
                    280:                        // PCI Config Mechanism 1 Ports
                    281:                        pci_cfg_write(addr, val, 2);
                    282:                        break;
                    283:                default:
                    284:                        DEBUG_PRINTF_IO
                    285:                            ("%s(%04x,%04x) writing to bios_device.io_buffer\n",
                    286:                             __FUNCTION__, addr, val);
                    287:                        out16le((void *) bios_device.io_buffer + addr, val);
                    288:                        break;
                    289:                }
                    290:        }
                    291: }
                    292: 
                    293: void
                    294: my_outl(X86EMU_pioAddr addr, uint32_t val)
                    295: {
                    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);
                    308:                } else {
                    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);
                    318:                }
                    319:                DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %08x\n", __FUNCTION__,
                    320:                                addr, val);
                    321:        } else {
                    322:                switch (addr) {
                    323:                case 0xCFC:
                    324:                        // PCI Config Mechanism 1 Ports
                    325:                        pci_cfg_write(addr, val, 4);
                    326:                        break;
                    327:                default:
                    328:                        DEBUG_PRINTF_IO
                    329:                            ("%s(%04x,%08x) writing to bios_device.io_buffer\n",
                    330:                             __FUNCTION__, addr, val);
                    331:                        out32le((void *) bios_device.io_buffer + addr, val);
                    332:                        break;
                    333:                }
                    334:        }
                    335: }
                    336: 
                    337: uint32_t
                    338: pci_cfg_read(X86EMU_pioAddr addr, uint8_t size)
                    339: {
                    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...
                    356:                                printf
                    357:                                    ("Config access invalid! bus: %x, devfn: %x, offs: %x\n",
                    358:                                     bus, devfn, offs);
                    359:                                HALT_SYS();
                    360:                        } else {
                    361:                                rval =
                    362:                                    (uint32_t) rtas_pci_config_read(bios_device.
                    363:                                                                    puid, size,
                    364:                                                                    bus, devfn,
                    365:                                                                    offs);
                    366:                                DEBUG_PRINTF_IO
                    367:                                    ("%s(%04x) PCI Config Read @%02x, size: %d --> 0x%08x\n",
                    368:                                     __FUNCTION__, addr, offs, size, rval);
                    369:                        }
                    370:                }
                    371:        }
                    372:        return rval;
                    373: }
                    374: 
                    375: void
                    376: pci_cfg_write(X86EMU_pioAddr addr, uint32_t val, uint8_t size)
                    377: {
                    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...
                    393:                                printf
                    394:                                    ("Config access invalid! bus: %x, devfn: %x, offs: %x\n",
                    395:                                     bus, devfn, offs);
                    396:                                HALT_SYS();
                    397:                        } else {
                    398:                                rtas_pci_config_write(bios_device.puid,
                    399:                                                      size, bus, devfn, offs,
                    400:                                                      val);
                    401:                                DEBUG_PRINTF_IO
                    402:                                    ("%s(%04x) PCI Config Write @%02x, size: %d <-- 0x%08x\n",
                    403:                                     __FUNCTION__, addr, offs, size, val);
                    404:                        }
                    405:                }
                    406:        }
                    407: }
                    408: 
                    409: uint8_t
                    410: handle_port_61h()
                    411: {
                    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;
                    426:        }
                    427:        //finally read the value from the io_buffer
                    428:        return *((uint8_t *) (bios_device.io_buffer + 0x61));
                    429: }

unix.superglobalmegacorp.com

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