Annotation of qemu/roms/openbios/drivers/sbus.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *   OpenBIOS SBus 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: #include "drivers/drivers.h"
                     19: #include "libopenbios/ofmem.h"
                     20: 
                     21: #define SBUS_REGS        0x28
                     22: #define SBUS_SLOTS       16
                     23: #define APC_REGS         0x10
                     24: #define APC_OFFSET       0x0a000000ULL
                     25: #define CS4231_REGS      0x40
                     26: #define CS4231_OFFSET    0x0c000000ULL
                     27: #define MACIO_ESPDMA     0x00400000ULL /* ESP DMA controller */
                     28: #define MACIO_ESP        0x00800000ULL /* ESP SCSI */
                     29: #define SS600MP_ESPDMA   0x00081000ULL
                     30: #define SS600MP_ESP      0x00080000ULL
                     31: #define SS600MP_LEBUFFER (SS600MP_ESPDMA + 0x10) // XXX should be 0x40000
                     32: #define LEDMA_REGS       0x4
                     33: #define LE_REGS          0x20
                     34: 
                     35: #ifdef CONFIG_DEBUG_SBUS
                     36: #define DPRINTF(fmt, args...)                   \
                     37:     do { printk(fmt , ##args); } while (0)
                     38: #else
                     39: #define DPRINTF(fmt, args...)
                     40: #endif
                     41: 
                     42: typedef struct le_private {
                     43:     uint32_t *dmaregs;
                     44:     uint32_t *regs;
                     45: } le_private_t;
                     46: 
                     47: static void
                     48: ob_sbus_node_init(uint64_t base)
                     49: {
                     50:     void *regs;
                     51: 
                     52:     push_str("/iommu/sbus");
                     53:     fword("find-device");
                     54: 
                     55:     PUSH(base >> 32);
                     56:     fword("encode-int");
                     57:     PUSH(base & 0xffffffff);
                     58:     fword("encode-int");
                     59:     fword("encode+");
                     60:     PUSH(SBUS_REGS);
                     61:     fword("encode-int");
                     62:     fword("encode+");
                     63:     push_str("reg");
                     64:     fword("property");
                     65: 
                     66:     regs = (void *)ofmem_map_io(base, SBUS_REGS);
                     67:     PUSH((unsigned long)regs);
                     68:     fword("encode-int");
                     69:     push_str("address");
                     70:     fword("property");
                     71: }
                     72: 
                     73: static void
                     74: ob_le_init(unsigned int slot, uint64_t base, unsigned long leoffset, unsigned long dmaoffset)
                     75: {
                     76:     le_private_t *le;
                     77: 
                     78:     le = malloc(sizeof(le_private_t));
                     79:     if (!le) {
                     80:         DPRINTF("Can't allocate LANCE private structure\n");
                     81:         return;
                     82:     }
                     83: 
                     84:     /* Get the IO region for DMA registers */
                     85:     le->dmaregs = (void *)ofmem_map_io(base + (uint64_t)dmaoffset, LEDMA_REGS);
                     86:     if (le->dmaregs == NULL) {
                     87:         DPRINTF("Can't map LANCE DMA registers\n");
                     88:         return;
                     89:     }
                     90: 
                     91:     /* Now it appears that the Solaris kernel forgets to set up the LANCE DMA mapping
                     92:        and so it must inherit the one from OpenBIOS. The symptom of this is that the
                     93:        LANCE DMA base addr register is still zero, and so we start sending network 
                     94:        packets containing random areas of memory.
                     95:        
                     96:        The correct fix for this should be to use dvma_alloc() to grab a section of
                     97:        memory and point the LANCE DMA buffers to use that instead; this gets
                     98:        slightly further but still crashes. Time-consuming investigation on various
                     99:        hacked versions of QEMU seems to indicate that Solaris always assumes the LANCE 
                    100:        DMA base address is fixed 0xff000000 when setting up the IOMMU for the LANCE
                    101:        card. Hence we imitate this behaviour here. */
                    102:     le->dmaregs[3] = 0xff000000;
                    103:     
                    104:     push_str("/iommu/sbus/ledma");
                    105:     fword("find-device");
                    106:     PUSH(slot);
                    107:     fword("encode-int");
                    108:     PUSH(dmaoffset);
                    109:     fword("encode-int");
                    110:     fword("encode+");
                    111:     PUSH(0x00000020);
                    112:     fword("encode-int");
                    113:     fword("encode+");
                    114:     push_str("reg");
                    115:     fword("property");
                    116: 
                    117:     /* Get the IO region for Lance registers */
                    118:     le->regs = (void *)ofmem_map_io(base + (uint64_t)leoffset, LE_REGS);
                    119:     if (le->regs == NULL) {
                    120:         DPRINTF("Can't map LANCE registers\n");
                    121:         return;
                    122:     }
                    123:     
                    124:     push_str("/iommu/sbus/ledma/le");
                    125:     fword("find-device");
                    126:     PUSH(slot);
                    127:     fword("encode-int");
                    128:     PUSH(leoffset);
                    129:     fword("encode-int");
                    130:     fword("encode+");
                    131:     PUSH(0x00000004);
                    132:     fword("encode-int");
                    133:     fword("encode+");
                    134:     push_str("reg");
                    135:     fword("property");
                    136: }
                    137: 
                    138: uint16_t graphic_depth;
                    139: 
                    140: static void
                    141: ob_tcx_init(unsigned int slot, const char *path)
                    142: {
                    143:     phandle_t chosen, aliases;
                    144: 
                    145:     push_str(path);
                    146:     fword("find-device");
                    147: 
                    148:     PUSH(slot);
                    149:     fword("encode-int");
                    150:     PUSH(0x00800000);
                    151:     fword("encode-int");
                    152:     fword("encode+");
                    153:     PUSH(0x00100000);
                    154:     fword("encode-int");
                    155:     fword("encode+");
                    156: 
                    157:     PUSH(slot);
                    158:     fword("encode-int");
                    159:     fword("encode+");
                    160:     PUSH(0x02000000);
                    161:     fword("encode-int");
                    162:     fword("encode+");
                    163:     if (graphic_depth == 24) {
                    164:         PUSH(0x00400000);
                    165:     } else {
                    166:         PUSH(0x00000001);
                    167:     }
                    168:     fword("encode-int");
                    169:     fword("encode+");
                    170: 
                    171:     PUSH(slot);
                    172:     fword("encode-int");
                    173:     fword("encode+");
                    174:     PUSH(0x04000000);
                    175:     fword("encode-int");
                    176:     fword("encode+");
                    177:     if (graphic_depth == 24) {
                    178:         PUSH(0x00400000);
                    179:     } else {
                    180:         PUSH(0x00000001);
                    181:     }
                    182:     fword("encode-int");
                    183:     fword("encode+");
                    184: 
                    185:     PUSH(slot);
                    186:     fword("encode-int");
                    187:     fword("encode+");
                    188:     PUSH(0x06000000);
                    189:     fword("encode-int");
                    190:     fword("encode+");
                    191:     PUSH(0x00800000);
                    192:     fword("encode-int");
                    193:     fword("encode+");
                    194: 
                    195:     PUSH(slot);
                    196:     fword("encode-int");
                    197:     fword("encode+");
                    198:     PUSH(0x0a000000);
                    199:     fword("encode-int");
                    200:     fword("encode+");
                    201:     if (graphic_depth == 24) {
                    202:         PUSH(0x00400000);
                    203:     } else {
                    204:         PUSH(0x00000001);
                    205:     }
                    206:     fword("encode-int");
                    207:     fword("encode+");
                    208: 
                    209:     PUSH(slot);
                    210:     fword("encode-int");
                    211:     fword("encode+");
                    212:     PUSH(0x0c000000);
                    213:     fword("encode-int");
                    214:     fword("encode+");
                    215:     if (graphic_depth == 24) {
                    216:         PUSH(0x00800000);
                    217:     } else {
                    218:         PUSH(0x00000001);
                    219:     }
                    220:     fword("encode-int");
                    221:     fword("encode+");
                    222: 
                    223:     PUSH(slot);
                    224:     fword("encode-int");
                    225:     fword("encode+");
                    226:     PUSH(0x0e000000);
                    227:     fword("encode-int");
                    228:     fword("encode+");
                    229:     if (graphic_depth == 24) {
                    230:         PUSH(0x00800000);
                    231:     } else {
                    232:         PUSH(0x00000001);
                    233:     }
                    234:     fword("encode-int");
                    235:     fword("encode+");
                    236: 
                    237:     PUSH(slot);
                    238:     fword("encode-int");
                    239:     fword("encode+");
                    240:     PUSH(0x00700000);
                    241:     fword("encode-int");
                    242:     fword("encode+");
                    243:     PUSH(0x00001000);
                    244:     fword("encode-int");
                    245:     fword("encode+");
                    246: 
                    247:     PUSH(slot);
                    248:     fword("encode-int");
                    249:     fword("encode+");
                    250:     PUSH(0x00200000);
                    251:     fword("encode-int");
                    252:     fword("encode+");
                    253:     if (graphic_depth == 24) {
                    254:         PUSH(0x00004000);
                    255:     } else {
                    256:         PUSH(0x00000004);
                    257:     }
                    258:     fword("encode-int");
                    259:     fword("encode+");
                    260: 
                    261:     PUSH(slot);
                    262:     fword("encode-int");
                    263:     fword("encode+");
                    264:     if (graphic_depth == 24) {
                    265:         PUSH(0x00301000);
                    266:     } else {
                    267:         PUSH(0x00300000);
                    268:     }
                    269:     fword("encode-int");
                    270:     fword("encode+");
                    271:     if (graphic_depth == 24) {
                    272:         PUSH(0x00001000);
                    273:     } else {
                    274:         PUSH(0x0000081c);
                    275:     }
                    276:     fword("encode-int");
                    277:     fword("encode+");
                    278: 
                    279:     PUSH(slot);
                    280:     fword("encode-int");
                    281:     fword("encode+");
                    282:     PUSH(0x00000000);
                    283:     fword("encode-int");
                    284:     fword("encode+");
                    285:     PUSH(0x00010000);
                    286:     fword("encode-int");
                    287:     fword("encode+");
                    288: 
                    289:     PUSH(slot);
                    290:     fword("encode-int");
                    291:     fword("encode+");
                    292:     PUSH(0x00240000);
                    293:     fword("encode-int");
                    294:     fword("encode+");
                    295:     if (graphic_depth == 24) {
                    296:         PUSH(0x00004000);
                    297:     } else {
                    298:         PUSH(0x00000004);
                    299:     }
                    300:     fword("encode-int");
                    301:     fword("encode+");
                    302: 
                    303:     PUSH(slot);
                    304:     fword("encode-int");
                    305:     fword("encode+");
                    306:     PUSH(0x00280000);
                    307:     fword("encode-int");
                    308:     fword("encode+");
                    309:     if (graphic_depth == 24) {
                    310:         PUSH(0x00008000);
                    311:     } else {
                    312:         PUSH(0x00000001);
                    313:     }
                    314:     fword("encode-int");
                    315:     fword("encode+");
                    316: 
                    317:     push_str("reg");
                    318:     fword("property");
                    319: 
                    320:     PUSH((int)graphic_depth);
                    321:     fword("encode-int");
                    322:     push_str("depth");
                    323:     fword("property");
                    324: 
                    325:     if (graphic_depth == 8) {
                    326:         push_str("true");
                    327:         fword("encode-string");
                    328:         push_str("tcx-8-bit");
                    329:         fword("property");
                    330:     }
                    331: 
                    332:     chosen = find_dev("/chosen");
                    333:     push_str(path);
                    334:     fword("open-dev");
                    335:     set_int_property(chosen, "screen", POP());
                    336: 
                    337:     aliases = find_dev("/aliases");
                    338:     set_property(aliases, "screen", path, strlen(path) + 1);
                    339: }
                    340: 
                    341: static void
                    342: ob_apc_init(unsigned int slot, unsigned long base)
                    343: {
                    344:     push_str("/iommu/sbus");
                    345:     fword("find-device");
                    346:     fword("new-device");
                    347: 
                    348:     push_str("power-management");
                    349:     fword("device-name");
                    350: 
                    351:     PUSH(slot);
                    352:     fword("encode-int");
                    353:     PUSH(base);
                    354:     fword("encode-int");
                    355:     fword("encode+");
                    356:     PUSH(APC_REGS);
                    357:     fword("encode-int");
                    358:     fword("encode+");
                    359:     push_str("reg");
                    360:     fword("property");
                    361: 
                    362:     fword("finish-device");
                    363: }
                    364: 
                    365: static void
                    366: ob_cs4231_init(unsigned int slot)
                    367: {
                    368:     push_str("/iommu/sbus");
                    369:     fword("find-device");
                    370:     fword("new-device");
                    371: 
                    372:     push_str("SUNW,CS4231");
                    373:     fword("device-name");
                    374: 
                    375:     push_str("serial");
                    376:     fword("device-type");
                    377: 
                    378:     PUSH(slot);
                    379:     fword("encode-int");
                    380:     PUSH(CS4231_OFFSET);
                    381:     fword("encode-int");
                    382:     fword("encode+");
                    383:     PUSH(CS4231_REGS);
                    384:     fword("encode-int");
                    385:     fword("encode+");
                    386:     push_str("reg");
                    387:     fword("property");
                    388: 
                    389:     PUSH(5);
                    390:     fword("encode-int");
                    391:     PUSH(0);
                    392:     fword("encode-int");
                    393:     fword("encode+");
                    394:     push_str("intr");
                    395:     fword("property");
                    396: 
                    397:     PUSH(5);
                    398:     fword("encode-int");
                    399:     push_str("interrupts");
                    400:     fword("property");
                    401: 
                    402:     push_str("audio");
                    403:     fword("encode-string");
                    404:     push_str("alias");
                    405:     fword("property");
                    406: 
                    407:     fword("finish-device");
                    408: }
                    409: 
                    410: static void
                    411: ob_macio_init(unsigned int slot, uint64_t base, unsigned long offset)
                    412: {
                    413:     // All devices were integrated to NCR89C100, see
                    414:     // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
                    415: 
                    416:     // NCR 53c9x, aka ESP. See
                    417:     // http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR53C9X.txt
                    418: #ifdef CONFIG_DRIVER_ESP
                    419:     ob_esp_init(slot, base, offset + MACIO_ESP, offset + MACIO_ESPDMA);
                    420: #endif
                    421: 
                    422:     // NCR 92C990, Am7990, Lance. See http://www.amd.com
                    423:     ob_le_init(slot, base, offset + 0x00c00000, offset + 0x00400010);
                    424: 
                    425:     // Parallel port
                    426:     //ob_bpp_init(base);
                    427: }
                    428: 
                    429: static void
                    430: sbus_probe_slot_ss5(unsigned int slot, uint64_t base)
                    431: {
                    432:     // OpenBIOS and Qemu don't know how to do Sbus probing
                    433:     switch(slot) {
                    434:     case 3: // SUNW,tcx
                    435:         ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx");
                    436:         break;
                    437:     case 4:
                    438:         // SUNW,CS4231
                    439:         ob_cs4231_init(slot);
                    440:         // Power management (APC)
                    441:         ob_apc_init(slot, APC_OFFSET);
                    442:         break;
                    443:     case 5: // MACIO: le, esp, bpp
                    444:         ob_macio_init(slot, base, 0x08000000);
                    445:         break;
                    446:     default:
                    447:         break;
                    448:     }
                    449: }
                    450: 
                    451: static void
                    452: sbus_probe_slot_ss10(unsigned int slot, uint64_t base)
                    453: {
                    454:     // OpenBIOS and Qemu don't know how to do Sbus probing
                    455:     switch(slot) {
                    456:     case 2: // SUNW,tcx
                    457:         ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx");
                    458:         break;
                    459:     case 0xf: // le, esp, bpp, power-management
                    460:         ob_macio_init(slot, base, 0);
                    461:         // Power management (APC) XXX should not exist
                    462:         ob_apc_init(slot, APC_OFFSET);
                    463:         break;
                    464:     default:
                    465:         break;
                    466:     }
                    467: }
                    468: 
                    469: static void
                    470: sbus_probe_slot_ss600mp(unsigned int slot, uint64_t base)
                    471: {
                    472:     // OpenBIOS and Qemu don't know how to do Sbus probing
                    473:     switch(slot) {
                    474:     case 2: // SUNW,tcx
                    475:         ob_tcx_init(slot, "/iommu/sbus/SUNW,tcx");
                    476:         break;
                    477:     case 0xf: // le, esp, bpp, power-management
                    478: #ifdef CONFIG_DRIVER_ESP
                    479:         ob_esp_init(slot, base, SS600MP_ESP, SS600MP_ESPDMA);
                    480: #endif
                    481:         // NCR 92C990, Am7990, Lance. See http://www.amd.com
                    482:         ob_le_init(slot, base, 0x00060000, SS600MP_LEBUFFER);
                    483:         // Power management (APC) XXX should not exist
                    484:         ob_apc_init(slot, APC_OFFSET);
                    485:         break;
                    486:     default:
                    487:         break;
                    488:     }
                    489: }
                    490: 
                    491: static void
                    492: ob_sbus_open(void)
                    493: {
                    494:        int ret=1;
                    495:        RET ( -ret );
                    496: }
                    497: 
                    498: static void
                    499: ob_sbus_close(void)
                    500: {
                    501:        selfword("close-deblocker");
                    502: }
                    503: 
                    504: static void
                    505: ob_sbus_initialize(void)
                    506: {
                    507: }
                    508: 
                    509: 
                    510: NODE_METHODS(ob_sbus_node) = {
                    511:        { NULL,                 ob_sbus_initialize      },
                    512:        { "open",               ob_sbus_open            },
                    513:        { "close",              ob_sbus_close           },
                    514: };
                    515: 
                    516: struct sbus_offset {
                    517:     int slot, type;
                    518:     uint64_t base;
                    519:     unsigned long size;
                    520: };
                    521: 
                    522: static const struct sbus_offset sbus_offsets_ss5[SBUS_SLOTS] = {
                    523:     { 0, 0, 0x20000000, 0x10000000,},
                    524:     { 1, 0, 0x30000000, 0x10000000,},
                    525:     { 2, 0, 0x40000000, 0x10000000,},
                    526:     { 3, 0, 0x50000000, 0x10000000,},
                    527:     { 4, 0, 0x60000000, 0x10000000,},
                    528:     { 5, 0, 0x70000000, 0x10000000,},
                    529: };
                    530: 
                    531: /* Shared with ss600mp */
                    532: static const struct sbus_offset sbus_offsets_ss10[SBUS_SLOTS] = {
                    533:     { 0, 0, 0xe00000000ULL, 0x10000000,},
                    534:     { 1, 0, 0xe10000000ULL, 0x10000000,},
                    535:     { 2, 0, 0xe20000000ULL, 0x10000000,},
                    536:     { 3, 0, 0xe30000000ULL, 0x10000000,},
                    537:     [0xf] = { 0xf, 0, 0xef0000000ULL, 0x10000000,},
                    538: };
                    539: 
                    540: static void
                    541: ob_add_sbus_range(const struct sbus_offset *range, int notfirst)
                    542: {
                    543:     if (!notfirst) {
                    544:         push_str("/iommu/sbus");
                    545:         fword("find-device");
                    546:     }
                    547:     PUSH(range->slot);
                    548:     fword("encode-int");
                    549:     if (notfirst)
                    550:         fword("encode+");
                    551:     PUSH(range->type);
                    552:     fword("encode-int");
                    553:     fword("encode+");
                    554:     PUSH(range->base >> 32);
                    555:     fword("encode-int");
                    556:     fword("encode+");
                    557:     PUSH(range->base & 0xffffffff);
                    558:     fword("encode-int");
                    559:     fword("encode+");
                    560:     PUSH(range->size);
                    561:     fword("encode-int");
                    562:     fword("encode+");
                    563: }
                    564: 
                    565: static int
                    566: ob_sbus_init_ss5(void)
                    567: {
                    568:     unsigned int slot;
                    569:     int notfirst = 0;
                    570: 
                    571:     for (slot = 0; slot < SBUS_SLOTS; slot++) {
                    572:         if (sbus_offsets_ss5[slot].size > 0)
                    573:             ob_add_sbus_range(&sbus_offsets_ss5[slot], notfirst++);
                    574:     }
                    575:     push_str("ranges");
                    576:     fword("property");
                    577: 
                    578:     for (slot = 0; slot < SBUS_SLOTS; slot++) {
                    579:         if (sbus_offsets_ss5[slot].size > 0)
                    580:             sbus_probe_slot_ss5(slot, sbus_offsets_ss5[slot].base);
                    581:     }
                    582: 
                    583:     return 0;
                    584: }
                    585: 
                    586: static int
                    587: ob_sbus_init_ss10(void)
                    588: {
                    589:     unsigned int slot;
                    590:     int notfirst = 0;
                    591: 
                    592:     for (slot = 0; slot < SBUS_SLOTS; slot++) {
                    593:         if (sbus_offsets_ss10[slot].size > 0)
                    594:             ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++);
                    595:     }
                    596:     push_str("ranges");
                    597:     fword("property");
                    598: 
                    599:     for (slot = 0; slot < SBUS_SLOTS; slot++) {
                    600:         if (sbus_offsets_ss10[slot].size > 0)
                    601:             sbus_probe_slot_ss10(slot, sbus_offsets_ss10[slot].base);
                    602:     }
                    603: 
                    604:     return 0;
                    605: }
                    606: 
                    607: static int
                    608: ob_sbus_init_ss600mp(void)
                    609: {
                    610:     unsigned int slot;
                    611:     int notfirst = 0;
                    612: 
                    613:     for (slot = 0; slot < SBUS_SLOTS; slot++) {
                    614:         if (sbus_offsets_ss10[slot].size > 0)
                    615:             ob_add_sbus_range(&sbus_offsets_ss10[slot], notfirst++);
                    616:     }
                    617:     push_str("ranges");
                    618:     fword("property");
                    619: 
                    620:     for (slot = 0; slot < SBUS_SLOTS; slot++) {
                    621:         if (sbus_offsets_ss10[slot].size > 0)
                    622:             sbus_probe_slot_ss600mp(slot, sbus_offsets_ss10[slot].base);
                    623:     }
                    624: 
                    625:     return 0;
                    626: }
                    627: 
                    628: int ob_sbus_init(uint64_t base, int machine_id)
                    629: {
                    630:     ob_sbus_node_init(base);
                    631: 
                    632:     switch (machine_id) {
                    633:     case 66:
                    634:         return ob_sbus_init_ss600mp();
                    635:     case 64 ... 65:
                    636:         return ob_sbus_init_ss10();
                    637:     case 32 ... 63:
                    638:         return ob_sbus_init_ss5();
                    639:     default:
                    640:         return -1;
                    641:     }
                    642: }

unix.superglobalmegacorp.com

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