Annotation of qemu/roms/SLOF/clients/net-snk/app/biosemu/io.c, revision 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.