Annotation of qemu/roms/openbios/drivers/obio.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *   OpenBIOS Sparc OBIO driver
        !             3:  *
        !             4:  *   (C) 2004 Stefan Reinauer <[email protected]>
        !             5:  *   (C) 2005 Ed Schouten <[email protected]>
        !             6:  *
        !             7:  *   This program is free software; you can redistribute it and/or
        !             8:  *   modify it under the terms of the GNU General Public License
        !             9:  *   version 2
        !            10:  *
        !            11:  */
        !            12: 
        !            13: #include "config.h"
        !            14: #include "libopenbios/bindings.h"
        !            15: #include "kernel/kernel.h"
        !            16: #include "libc/byteorder.h"
        !            17: #include "libc/vsprintf.h"
        !            18: 
        !            19: #include "drivers/drivers.h"
        !            20: #include "arch/common/nvram.h"
        !            21: #include "libopenbios/ofmem.h"
        !            22: #include "obio.h"
        !            23: #include "escc.h"
        !            24: 
        !            25: #define        PROMDEV_KBD     0               /* input from keyboard */
        !            26: #define        PROMDEV_SCREEN  0               /* output to screen */
        !            27: #define        PROMDEV_TTYA    1               /* in/out to ttya */
        !            28: 
        !            29: /* "NCPU" is an historical name that's now a bit of a misnomer.  The sun4m
        !            30:  * architecture registers NCPU CPU-specific interrupts along with one
        !            31:  * system-wide interrupt, regardless of the number of actual CPUs installed.
        !            32:  * See the comment on "NCPU" at <http://stuff.mit.edu/afs/athena/astaff/
        !            33:  * project/opssrc/sys.sunos/sun4m/devaddr.h>.
        !            34:  */
        !            35: #define SUN4M_NCPU      4
        !            36: 
        !            37: /* DECLARE data structures for the nodes.  */
        !            38: DECLARE_UNNAMED_NODE( ob_obio, INSTALL_OPEN, sizeof(int) );
        !            39: 
        !            40: void
        !            41: ob_new_obio_device(const char *name, const char *type)
        !            42: {
        !            43:     push_str("/obio");
        !            44:     fword("find-device");
        !            45:     fword("new-device");
        !            46: 
        !            47:     push_str(name);
        !            48:     fword("device-name");
        !            49: 
        !            50:     if (type) {
        !            51:         push_str(type);
        !            52:         fword("device-type");
        !            53:     }
        !            54: }
        !            55: 
        !            56: static unsigned long
        !            57: map_reg(uint64_t base, uint64_t offset, unsigned long size, int map,
        !            58:         int phys_hi)
        !            59: {
        !            60:     PUSH(phys_hi);
        !            61:     fword("encode-int");
        !            62:     PUSH(offset);
        !            63:     fword("encode-int");
        !            64:     fword("encode+");
        !            65:     PUSH(size);
        !            66:     fword("encode-int");
        !            67:     fword("encode+");
        !            68:     push_str("reg");
        !            69:     fword("property");
        !            70: 
        !            71:     if (map) {
        !            72:         unsigned long addr;
        !            73: 
        !            74:         addr = (unsigned long)ofmem_map_io(base + offset, size);
        !            75: 
        !            76:         PUSH(addr);
        !            77:         fword("encode-int");
        !            78:         push_str("address");
        !            79:         fword("property");
        !            80:         return addr;
        !            81:     }
        !            82:     return 0;
        !            83: }
        !            84: 
        !            85: unsigned long
        !            86: ob_reg(uint64_t base, uint64_t offset, unsigned long size, int map)
        !            87: {
        !            88:     return map_reg(base, offset, size, map, 0);
        !            89: }
        !            90: 
        !            91: void
        !            92: ob_intr(int intr)
        !            93: {
        !            94:     PUSH(intr);
        !            95:     fword("encode-int");
        !            96:     PUSH(0);
        !            97:     fword("encode-int");
        !            98:     fword("encode+");
        !            99:     push_str("intr");
        !           100:     fword("property");
        !           101: }
        !           102: 
        !           103: void
        !           104: ob_eccmemctl_init(uint64_t base)
        !           105: {
        !           106:     uint32_t version, *regs;
        !           107:     const char *mc_type;
        !           108: 
        !           109:     push_str("/");
        !           110:     fword("find-device");
        !           111:     fword("new-device");
        !           112: 
        !           113:     push_str("eccmemctl");
        !           114:     fword("device-name");
        !           115: 
        !           116:     PUSH(0x20);
        !           117:     fword("encode-int");
        !           118:     push_str("width");
        !           119:     fword("property");
        !           120: 
        !           121:     regs = (uint32_t *)map_reg(ECC_BASE, 0, ECC_SIZE, 1, ECC_BASE >> 32);
        !           122: 
        !           123:     version = regs[0];
        !           124:     switch (version) {
        !           125:     case 0x00000000:
        !           126:         mc_type = "MCC";
        !           127:         break;
        !           128:     case 0x10000000:
        !           129:         mc_type = "EMC";
        !           130:         break;
        !           131:     default:
        !           132:     case 0x20000000:
        !           133:         mc_type = "SMC";
        !           134:         break;
        !           135:     }
        !           136:     push_str(mc_type);
        !           137:     fword("encode-string");
        !           138:     push_str("mc-type");
        !           139:     fword("property");
        !           140: 
        !           141:     fword("finish-device");
        !           142: }
        !           143: 
        !           144: static unsigned char *nvram;
        !           145: 
        !           146: #define NVRAM_OB_START   (0)
        !           147: #define NVRAM_OB_SIZE    ((NVRAM_IDPROM - NVRAM_OB_START) & ~15)
        !           148: 
        !           149: void
        !           150: arch_nvram_get(char *data)
        !           151: {
        !           152:     memcpy(data, &nvram[NVRAM_OB_START], NVRAM_OB_SIZE);
        !           153: }
        !           154: 
        !           155: void
        !           156: arch_nvram_put(char *data)
        !           157: {
        !           158:     memcpy(&nvram[NVRAM_OB_START], data, NVRAM_OB_SIZE);
        !           159: }
        !           160: 
        !           161: int
        !           162: arch_nvram_size(void)
        !           163: {
        !           164:     return NVRAM_OB_SIZE;
        !           165: }
        !           166: 
        !           167: void
        !           168: ss5_init(uint64_t base)
        !           169: {
        !           170:     ob_new_obio_device("slavioconfig", NULL);
        !           171: 
        !           172:     ob_reg(base, SLAVIO_SCONFIG, SCONFIG_REGS, 0);
        !           173: 
        !           174:     fword("finish-device");
        !           175: }
        !           176: 
        !           177: static void
        !           178: ob_nvram_init(uint64_t base, uint64_t offset)
        !           179: {
        !           180:     ob_new_obio_device("eeprom", NULL);
        !           181: 
        !           182:     nvram = (unsigned char *)ob_reg(base, offset, NVRAM_SIZE, 1);
        !           183: 
        !           184:     PUSH((unsigned long)nvram);
        !           185:     fword("encode-int");
        !           186:     push_str("address");
        !           187:     fword("property");
        !           188: 
        !           189:     push_str("mk48t08");
        !           190:     fword("model");
        !           191: 
        !           192:     fword("finish-device");
        !           193: 
        !           194:     // Add /idprom
        !           195:     push_str("/");
        !           196:     fword("find-device");
        !           197: 
        !           198:     PUSH((long)&nvram[NVRAM_IDPROM]);
        !           199:     PUSH(32);
        !           200:     fword("encode-bytes");
        !           201:     push_str("idprom");
        !           202:     fword("property");
        !           203: }
        !           204: 
        !           205: static void
        !           206: ob_fd_init(uint64_t base, uint64_t offset, int intr)
        !           207: {
        !           208:     unsigned long addr;
        !           209: 
        !           210:     ob_new_obio_device("SUNW,fdtwo", "block");
        !           211: 
        !           212:     addr = ob_reg(base, offset, FD_REGS, 1);
        !           213: 
        !           214:     ob_intr(intr);
        !           215: 
        !           216:     fword("is-deblocker");
        !           217: 
        !           218:     ob_floppy_init("/obio", "SUNW,fdtwo", 0, addr);
        !           219: 
        !           220:     fword("finish-device");
        !           221: }
        !           222: 
        !           223: static void
        !           224: ob_auxio_init(uint64_t base, uint64_t offset)
        !           225: {
        !           226:     ob_new_obio_device("auxio", NULL);
        !           227: 
        !           228:     ob_reg(base, offset, AUXIO_REGS, 1);
        !           229: 
        !           230:     fword("finish-device");
        !           231: }
        !           232: 
        !           233: volatile unsigned char *power_reg;
        !           234: volatile unsigned int *reset_reg;
        !           235: 
        !           236: static void
        !           237: sparc32_reset_all(void)
        !           238: {
        !           239:     *reset_reg = 1;
        !           240: }
        !           241: 
        !           242: // AUX 2 (Software Powerdown Control) and reset
        !           243: static void
        !           244: ob_aux2_reset_init(uint64_t base, uint64_t offset, int intr)
        !           245: {
        !           246:     ob_new_obio_device("power", NULL);
        !           247: 
        !           248:     power_reg = (void *)ob_reg(base, offset, AUXIO2_REGS, 1);
        !           249: 
        !           250:     // Not in device tree
        !           251:     reset_reg = (unsigned int *)ofmem_map_io(base + (uint64_t)SLAVIO_RESET, RESET_REGS);
        !           252: 
        !           253:     bind_func("sparc32-reset-all", sparc32_reset_all);
        !           254:     push_str("' sparc32-reset-all to reset-all");
        !           255:     fword("eval");
        !           256: 
        !           257:     ob_intr(intr);
        !           258: 
        !           259:     fword("finish-device");
        !           260: }
        !           261: 
        !           262: volatile struct sun4m_timer_regs *counter_regs;
        !           263: 
        !           264: static void
        !           265: ob_counter_init(uint64_t base, unsigned long offset)
        !           266: {
        !           267:     int i;
        !           268: 
        !           269:     ob_new_obio_device("counter", NULL);
        !           270: 
        !           271:     for (i = 0; i < SUN4M_NCPU; i++) {
        !           272:         PUSH(0);
        !           273:         fword("encode-int");
        !           274:         if (i != 0) fword("encode+");
        !           275:         PUSH(offset + (i * PAGE_SIZE));
        !           276:         fword("encode-int");
        !           277:         fword("encode+");
        !           278:         PUSH(COUNTER_REGS);
        !           279:         fword("encode-int");
        !           280:         fword("encode+");
        !           281:     }
        !           282: 
        !           283:     PUSH(0);
        !           284:     fword("encode-int");
        !           285:     fword("encode+");
        !           286:     PUSH(offset + 0x10000);
        !           287:     fword("encode-int");
        !           288:     fword("encode+");
        !           289:     PUSH(COUNTER_REGS);
        !           290:     fword("encode-int");
        !           291:     fword("encode+");
        !           292: 
        !           293:     push_str("reg");
        !           294:     fword("property");
        !           295: 
        !           296: 
        !           297:     counter_regs = (struct sun4m_timer_regs *)ofmem_map_io(base + (uint64_t)offset, sizeof(*counter_regs));
        !           298:     counter_regs->cfg = 0xffffffff;
        !           299:     counter_regs->l10_timer_limit = 0;
        !           300:     counter_regs->cpu_timers[0].l14_timer_limit = 0x9c4000;    /* see comment in obio.h */
        !           301:     counter_regs->cpu_timers[0].cntrl = 1;
        !           302: 
        !           303:     for (i = 0; i < SUN4M_NCPU; i++) {
        !           304:         PUSH((unsigned long)&counter_regs->cpu_timers[i]);
        !           305:         fword("encode-int");
        !           306:         if (i != 0)
        !           307:             fword("encode+");
        !           308:     }
        !           309:     PUSH((unsigned long)&counter_regs->l10_timer_limit);
        !           310:     fword("encode-int");
        !           311:     fword("encode+");
        !           312:     push_str("address");
        !           313:     fword("property");
        !           314: 
        !           315:     fword("finish-device");
        !           316: }
        !           317: 
        !           318: static volatile struct sun4m_intregs *intregs;
        !           319: 
        !           320: static void
        !           321: ob_interrupt_init(uint64_t base, unsigned long offset)
        !           322: {
        !           323:     int i;
        !           324: 
        !           325:     ob_new_obio_device("interrupt", NULL);
        !           326: 
        !           327:     for (i = 0; i < SUN4M_NCPU; i++) {
        !           328:         PUSH(0);
        !           329:         fword("encode-int");
        !           330:         if (i != 0) fword("encode+");
        !           331:         PUSH(offset + (i * PAGE_SIZE));
        !           332:         fword("encode-int");
        !           333:         fword("encode+");
        !           334:         PUSH(INTERRUPT_REGS);
        !           335:         fword("encode-int");
        !           336:         fword("encode+");
        !           337:     }
        !           338: 
        !           339:     PUSH(0);
        !           340:     fword("encode-int");
        !           341:     fword("encode+");
        !           342:     PUSH(offset + 0x10000);
        !           343:     fword("encode-int");
        !           344:     fword("encode+");
        !           345:     PUSH(INTERRUPT_REGS);
        !           346:     fword("encode-int");
        !           347:     fword("encode+");
        !           348: 
        !           349:     push_str("reg");
        !           350:     fword("property");
        !           351: 
        !           352:     intregs = (struct sun4m_intregs *)ofmem_map_io(base | (uint64_t)offset, sizeof(*intregs));
        !           353:     intregs->clear = ~SUN4M_INT_MASKALL;
        !           354:     intregs->cpu_intregs[0].clear = ~0x17fff;
        !           355: 
        !           356:     for (i = 0; i < SUN4M_NCPU; i++) {
        !           357:         PUSH((unsigned long)&intregs->cpu_intregs[i]);
        !           358:         fword("encode-int");
        !           359:         if (i != 0)
        !           360:             fword("encode+");
        !           361:     }
        !           362:     PUSH((unsigned long)&intregs->tbt);
        !           363:     fword("encode-int");
        !           364:     fword("encode+");
        !           365:     push_str("address");
        !           366:     fword("property");
        !           367: 
        !           368:     fword("finish-device");
        !           369: }
        !           370: 
        !           371: /* SMP CPU boot structure */
        !           372: struct smp_cfg {
        !           373:     uint32_t smp_ctx;
        !           374:     uint32_t smp_ctxtbl;
        !           375:     uint32_t smp_entry;
        !           376:     uint32_t valid;
        !           377: };
        !           378: 
        !           379: static struct smp_cfg *smp_header;
        !           380: 
        !           381: int
        !           382: start_cpu(unsigned int pc, unsigned int context_ptr, unsigned int context, int cpu)
        !           383: {
        !           384:     if (!cpu)
        !           385:         return -1;
        !           386: 
        !           387:     cpu &= 7;
        !           388: 
        !           389:     smp_header->smp_entry = pc;
        !           390:     smp_header->smp_ctxtbl = context_ptr;
        !           391:     smp_header->smp_ctx = context;
        !           392:     smp_header->valid = cpu;
        !           393: 
        !           394:     intregs->cpu_intregs[cpu].set = SUN4M_SOFT_INT(14);
        !           395: 
        !           396:     return 0;
        !           397: }
        !           398: 
        !           399: static void
        !           400: ob_smp_init(unsigned long mem_size)
        !           401: {
        !           402:     // See arch/sparc32/entry.S for memory layout
        !           403:     smp_header = (struct smp_cfg *)ofmem_map_io((uint64_t)(mem_size - 0x100),
        !           404:                                           sizeof(struct smp_cfg));
        !           405: }
        !           406: 
        !           407: static void
        !           408: ob_obio_open(__attribute__((unused))int *idx)
        !           409: {
        !           410:        int ret=1;
        !           411:        RET ( -ret );
        !           412: }
        !           413: 
        !           414: static void
        !           415: ob_obio_close(__attribute__((unused))int *idx)
        !           416: {
        !           417:        selfword("close-deblocker");
        !           418: }
        !           419: 
        !           420: static void
        !           421: ob_obio_initialize(__attribute__((unused))int *idx)
        !           422: {
        !           423:     push_str("/");
        !           424:     fword("find-device");
        !           425:     fword("new-device");
        !           426: 
        !           427:     push_str("obio");
        !           428:     fword("device-name");
        !           429: 
        !           430:     push_str("hierarchical");
        !           431:     fword("device-type");
        !           432: 
        !           433:     PUSH(2);
        !           434:     fword("encode-int");
        !           435:     push_str("#address-cells");
        !           436:     fword("property");
        !           437: 
        !           438:     PUSH(1);
        !           439:     fword("encode-int");
        !           440:     push_str("#size-cells");
        !           441:     fword("property");
        !           442: 
        !           443:     fword("finish-device");
        !           444: }
        !           445: 
        !           446: static void
        !           447: ob_set_obio_ranges(uint64_t base)
        !           448: {
        !           449:     push_str("/obio");
        !           450:     fword("find-device");
        !           451:     PUSH(0);
        !           452:     fword("encode-int");
        !           453:     PUSH(0);
        !           454:     fword("encode-int");
        !           455:     fword("encode+");
        !           456:     PUSH(base >> 32);
        !           457:     fword("encode-int");
        !           458:     fword("encode+");
        !           459:     PUSH(base & 0xffffffff);
        !           460:     fword("encode-int");
        !           461:     fword("encode+");
        !           462:     PUSH(SLAVIO_SIZE);
        !           463:     fword("encode-int");
        !           464:     fword("encode+");
        !           465:     push_str("ranges");
        !           466:     fword("property");
        !           467: }
        !           468: 
        !           469: static void
        !           470: ob_obio_decodeunit(__attribute__((unused)) int *idx)
        !           471: {
        !           472:     fword("decode-unit-sbus");
        !           473: }
        !           474: 
        !           475: 
        !           476: static void
        !           477: ob_obio_encodeunit(__attribute__((unused)) int *idx)
        !           478: {
        !           479:     fword("encode-unit-sbus");
        !           480: }
        !           481: 
        !           482: NODE_METHODS(ob_obio) = {
        !           483:        { NULL,                 ob_obio_initialize      },
        !           484:        { "open",               ob_obio_open            },
        !           485:        { "close",              ob_obio_close           },
        !           486:        { "encode-unit",        ob_obio_encodeunit      },
        !           487:        { "decode-unit",        ob_obio_decodeunit      },
        !           488: };
        !           489: 
        !           490: 
        !           491: int
        !           492: ob_obio_init(uint64_t slavio_base, unsigned long fd_offset,
        !           493:              unsigned long counter_offset, unsigned long intr_offset,
        !           494:              unsigned long aux1_offset, unsigned long aux2_offset,
        !           495:              unsigned long mem_size)
        !           496: {
        !           497: 
        !           498:     // All devices were integrated to NCR89C105, see
        !           499:     // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
        !           500: 
        !           501:     //printk("Initializing OBIO devices...\n");
        !           502: #if 0 // XXX
        !           503:     REGISTER_NAMED_NODE(ob_obio, "/obio");
        !           504:     device_end();
        !           505: #endif
        !           506:     ob_set_obio_ranges(slavio_base);
        !           507: 
        !           508:     // Zilog Z8530 serial ports, see http://www.zilog.com
        !           509:     // Must be before zs@0,0 or Linux won't boot
        !           510:     ob_zs_init(slavio_base, SLAVIO_ZS1, ZS_INTR, 0, 0);
        !           511: 
        !           512:     ob_zs_init(slavio_base, SLAVIO_ZS, ZS_INTR, 1, 1);
        !           513: 
        !           514:     // M48T08 NVRAM, see http://www.st.com
        !           515:     ob_nvram_init(slavio_base, SLAVIO_NVRAM);
        !           516: 
        !           517:     // 82078 FDC
        !           518:     if (fd_offset != (unsigned long) -1)
        !           519:         ob_fd_init(slavio_base, fd_offset, FD_INTR);
        !           520: 
        !           521:     ob_auxio_init(slavio_base, aux1_offset);
        !           522: 
        !           523:     if (aux2_offset != (unsigned long) -1)
        !           524:         ob_aux2_reset_init(slavio_base, aux2_offset, AUXIO2_INTR);
        !           525: 
        !           526:     ob_counter_init(slavio_base, counter_offset);
        !           527: 
        !           528:     ob_interrupt_init(slavio_base, intr_offset);
        !           529: 
        !           530:     ob_smp_init(mem_size);
        !           531: 
        !           532:     return 0;
        !           533: }

unix.superglobalmegacorp.com

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