Annotation of qemu/roms/openbios/drivers/obio.c, revision 1.1.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.