Annotation of qemu/hw/alpha_typhoon.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * DEC 21272 (TSUNAMI/TYPHOON) chipset emulation.
                      3:  *
                      4:  * Written by Richard Henderson.
                      5:  *
                      6:  * This work is licensed under the GNU GPL license version 2 or later.
                      7:  */
                      8: 
                      9: #include "cpu.h"
                     10: #include "exec-all.h"
                     11: #include "hw.h"
                     12: #include "devices.h"
                     13: #include "sysemu.h"
                     14: #include "alpha_sys.h"
                     15: #include "exec-memory.h"
                     16: 
                     17: 
                     18: typedef struct TyphoonCchip {
                     19:     MemoryRegion region;
                     20:     uint64_t misc;
                     21:     uint64_t drir;
                     22:     uint64_t dim[4];
                     23:     uint32_t iic[4];
1.1.1.2 ! root       24:     CPUAlphaState *cpu[4];
1.1       root       25: } TyphoonCchip;
                     26: 
                     27: typedef struct TyphoonWindow {
                     28:     uint32_t base_addr;
                     29:     uint32_t mask;
                     30:     uint32_t translated_base_pfn;
                     31: } TyphoonWindow;
                     32:  
                     33: typedef struct TyphoonPchip {
                     34:     MemoryRegion region;
                     35:     MemoryRegion reg_iack;
                     36:     MemoryRegion reg_mem;
                     37:     MemoryRegion reg_io;
                     38:     MemoryRegion reg_conf;
                     39:     uint64_t ctl;
                     40:     TyphoonWindow win[4];
                     41: } TyphoonPchip;
                     42: 
                     43: typedef struct TyphoonState {
                     44:     PCIHostState host;
                     45:     TyphoonCchip cchip;
                     46:     TyphoonPchip pchip;
                     47:     MemoryRegion dchip_region;
                     48:     MemoryRegion ram_region;
                     49: 
                     50:     /* QEMU emulation state.  */
                     51:     uint32_t latch_tmp;
                     52: } TyphoonState;
                     53: 
                     54: /* Called when one of DRIR or DIM changes.  */
1.1.1.2 ! root       55: static void cpu_irq_change(CPUAlphaState *env, uint64_t req)
1.1       root       56: {
                     57:     /* If there are any non-masked interrupts, tell the cpu.  */
                     58:     if (env) {
                     59:         if (req) {
                     60:             cpu_interrupt(env, CPU_INTERRUPT_HARD);
                     61:         } else {
                     62:             cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
                     63:         }
                     64:     }
                     65: }
                     66: 
                     67: static uint64_t cchip_read(void *opaque, target_phys_addr_t addr, unsigned size)
                     68: {
1.1.1.2 ! root       69:     CPUAlphaState *env = cpu_single_env;
1.1       root       70:     TyphoonState *s = opaque;
                     71:     uint64_t ret = 0;
                     72: 
                     73:     if (addr & 4) {
                     74:         return s->latch_tmp;
                     75:     }
                     76: 
                     77:     switch (addr) {
                     78:     case 0x0000:
                     79:         /* CSC: Cchip System Configuration Register.  */
                     80:         /* All sorts of data here; probably the only thing relevant is
                     81:            PIP<14> Pchip 1 Present = 0.  */
                     82:         break;
                     83: 
                     84:     case 0x0040:
                     85:         /* MTR: Memory Timing Register.  */
                     86:         /* All sorts of stuff related to real DRAM.  */
                     87:         break;
                     88: 
                     89:     case 0x0080:
                     90:         /* MISC: Miscellaneous Register.  */
                     91:         ret = s->cchip.misc | (env->cpu_index & 3);
                     92:         break;
                     93: 
                     94:     case 0x00c0:
                     95:         /* MPD: Memory Presence Detect Register.  */
                     96:         break;
                     97: 
                     98:     case 0x0100: /* AAR0 */
                     99:     case 0x0140: /* AAR1 */
                    100:     case 0x0180: /* AAR2 */
                    101:     case 0x01c0: /* AAR3 */
                    102:         /* AAR: Array Address Register.  */
                    103:         /* All sorts of information about DRAM.  */
                    104:         break;
                    105: 
                    106:     case 0x0200:
                    107:         /* DIM0: Device Interrupt Mask Register, CPU0.  */
                    108:         ret = s->cchip.dim[0];
                    109:         break;
                    110:     case 0x0240:
                    111:         /* DIM1: Device Interrupt Mask Register, CPU1.  */
                    112:         ret = s->cchip.dim[1];
                    113:         break;
                    114:     case 0x0280:
                    115:         /* DIR0: Device Interrupt Request Register, CPU0.  */
                    116:         ret = s->cchip.dim[0] & s->cchip.drir;
                    117:         break;
                    118:     case 0x02c0:
                    119:         /* DIR1: Device Interrupt Request Register, CPU1.  */
                    120:         ret = s->cchip.dim[1] & s->cchip.drir;
                    121:         break;
                    122:     case 0x0300:
                    123:         /* DRIR: Device Raw Interrupt Request Register.  */
                    124:         ret = s->cchip.drir;
                    125:         break;
                    126: 
                    127:     case 0x0340:
                    128:         /* PRBEN: Probe Enable Register.  */
                    129:         break;
                    130: 
                    131:     case 0x0380:
                    132:         /* IIC0: Interval Ignore Count Register, CPU0.  */
                    133:         ret = s->cchip.iic[0];
                    134:         break;
                    135:     case 0x03c0:
                    136:         /* IIC1: Interval Ignore Count Register, CPU1.  */
                    137:         ret = s->cchip.iic[1];
                    138:         break;
                    139: 
                    140:     case 0x0400: /* MPR0 */
                    141:     case 0x0440: /* MPR1 */
                    142:     case 0x0480: /* MPR2 */
                    143:     case 0x04c0: /* MPR3 */
                    144:         /* MPR: Memory Programming Register.  */
                    145:         break;
                    146: 
                    147:     case 0x0580:
                    148:         /* TTR: TIGbus Timing Register.  */
                    149:         /* All sorts of stuff related to interrupt delivery timings.  */
                    150:         break;
                    151:     case 0x05c0:
                    152:         /* TDR: TIGbug Device Timing Register.  */
                    153:         break;
                    154: 
                    155:     case 0x0600:
                    156:         /* DIM2: Device Interrupt Mask Register, CPU2.  */
                    157:         ret = s->cchip.dim[2];
                    158:         break;
                    159:     case 0x0640:
                    160:         /* DIM3: Device Interrupt Mask Register, CPU3.  */
                    161:         ret = s->cchip.dim[3];
                    162:         break;
                    163:     case 0x0680:
                    164:         /* DIR2: Device Interrupt Request Register, CPU2.  */
                    165:         ret = s->cchip.dim[2] & s->cchip.drir;
                    166:         break;
                    167:     case 0x06c0:
                    168:         /* DIR3: Device Interrupt Request Register, CPU3.  */
                    169:         ret = s->cchip.dim[3] & s->cchip.drir;
                    170:         break;
                    171: 
                    172:     case 0x0700:
                    173:         /* IIC2: Interval Ignore Count Register, CPU2.  */
                    174:         ret = s->cchip.iic[2];
                    175:         break;
                    176:     case 0x0740:
                    177:         /* IIC3: Interval Ignore Count Register, CPU3.  */
                    178:         ret = s->cchip.iic[3];
                    179:         break;
                    180: 
                    181:     case 0x0780:
                    182:         /* PWR: Power Management Control.   */
                    183:         break;
                    184:     
                    185:     case 0x0c00: /* CMONCTLA */
                    186:     case 0x0c40: /* CMONCTLB */
                    187:     case 0x0c80: /* CMONCNT01 */
                    188:     case 0x0cc0: /* CMONCNT23 */
                    189:         break;
                    190: 
                    191:     default:
                    192:         cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
                    193:         return -1;
                    194:     }
                    195: 
                    196:     s->latch_tmp = ret >> 32;
                    197:     return ret;
                    198: }
                    199: 
                    200: static uint64_t dchip_read(void *opaque, target_phys_addr_t addr, unsigned size)
                    201: {
                    202:     /* Skip this.  It's all related to DRAM timing and setup.  */
                    203:     return 0;
                    204: }
                    205: 
                    206: static uint64_t pchip_read(void *opaque, target_phys_addr_t addr, unsigned size)
                    207: {
                    208:     TyphoonState *s = opaque;
                    209:     uint64_t ret = 0;
                    210: 
                    211:     if (addr & 4) {
                    212:         return s->latch_tmp;
                    213:     }
                    214: 
                    215:     switch (addr) {
                    216:     case 0x0000:
                    217:         /* WSBA0: Window Space Base Address Register.  */
                    218:         ret = s->pchip.win[0].base_addr;
                    219:         break;
                    220:     case 0x0040:
                    221:         /* WSBA1 */
                    222:         ret = s->pchip.win[1].base_addr;
                    223:         break;
                    224:     case 0x0080:
                    225:         /* WSBA2 */
                    226:         ret = s->pchip.win[2].base_addr;
                    227:         break;
                    228:     case 0x00c0:
                    229:         /* WSBA3 */
                    230:         ret = s->pchip.win[3].base_addr;
                    231:         break;
                    232: 
                    233:     case 0x0100:
                    234:         /* WSM0: Window Space Mask Register.  */
                    235:         ret = s->pchip.win[0].mask;
                    236:         break;
                    237:     case 0x0140:
                    238:         /* WSM1 */
                    239:         ret = s->pchip.win[1].mask;
                    240:         break;
                    241:     case 0x0180:
                    242:         /* WSM2 */
                    243:         ret = s->pchip.win[2].mask;
                    244:         break;
                    245:     case 0x01c0:
                    246:         /* WSM3 */
                    247:         ret = s->pchip.win[3].mask;
                    248:         break;
                    249: 
                    250:     case 0x0200:
                    251:         /* TBA0: Translated Base Address Register.  */
                    252:         ret = (uint64_t)s->pchip.win[0].translated_base_pfn << 10;
                    253:         break;
                    254:     case 0x0240:
                    255:         /* TBA1 */
                    256:         ret = (uint64_t)s->pchip.win[1].translated_base_pfn << 10;
                    257:         break;
                    258:     case 0x0280:
                    259:         /* TBA2 */
                    260:         ret = (uint64_t)s->pchip.win[2].translated_base_pfn << 10;
                    261:         break;
                    262:     case 0x02c0:
                    263:         /* TBA3 */
                    264:         ret = (uint64_t)s->pchip.win[3].translated_base_pfn << 10;
                    265:         break;
                    266: 
                    267:     case 0x0300:
                    268:         /* PCTL: Pchip Control Register.  */
                    269:         ret = s->pchip.ctl;
                    270:         break;
                    271:     case 0x0340:
                    272:         /* PLAT: Pchip Master Latency Register.  */
                    273:         break;
                    274:     case 0x03c0:
                    275:         /* PERROR: Pchip Error Register.  */
                    276:         break;
                    277:     case 0x0400:
                    278:         /* PERRMASK: Pchip Error Mask Register.  */
                    279:         break;
                    280:     case 0x0440:
                    281:         /* PERRSET: Pchip Error Set Register.  */
                    282:         break;
                    283:     case 0x0480:
                    284:         /* TLBIV: Translation Buffer Invalidate Virtual Register (WO).  */
                    285:         break;
                    286:     case 0x04c0:
                    287:         /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
                    288:         break;
                    289:     case 0x0500: /* PMONCTL */
                    290:     case 0x0540: /* PMONCNT */
                    291:     case 0x0800: /* SPRST */
                    292:         break;
                    293: 
                    294:     default:
                    295:         cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
                    296:         return -1;
                    297:     }
                    298: 
                    299:     s->latch_tmp = ret >> 32;
                    300:     return ret;
                    301: }
                    302: 
                    303: static void cchip_write(void *opaque, target_phys_addr_t addr,
                    304:                         uint64_t v32, unsigned size)
                    305: {
                    306:     TyphoonState *s = opaque;
                    307:     uint64_t val, oldval, newval;
                    308: 
                    309:     if (addr & 4) {
                    310:         val = v32 << 32 | s->latch_tmp;
                    311:         addr ^= 4;
                    312:     } else {
                    313:         s->latch_tmp = v32;
                    314:         return;
                    315:     }
                    316: 
                    317:     switch (addr) {
                    318:     case 0x0000:
                    319:         /* CSC: Cchip System Configuration Register.  */
                    320:         /* All sorts of data here; nothing relevant RW.  */
                    321:         break;
                    322: 
                    323:     case 0x0040:
                    324:         /* MTR: Memory Timing Register.  */
                    325:         /* All sorts of stuff related to real DRAM.  */
                    326:         break;
                    327: 
                    328:     case 0x0080:
                    329:         /* MISC: Miscellaneous Register.  */
                    330:         newval = oldval = s->cchip.misc;
                    331:         newval &= ~(val & 0x10000ff0);     /* W1C fields */
                    332:         if (val & 0x100000) {
                    333:             newval &= ~0xff0000ull;        /* ACL clears ABT and ABW */
                    334:         } else {
                    335:             newval |= val & 0x00f00000;    /* ABT field is W1S */
                    336:             if ((newval & 0xf0000) == 0) {
                    337:                 newval |= val & 0xf0000;   /* ABW field is W1S iff zero */
                    338:             }
                    339:         }
                    340:         newval |= (val & 0xf000) >> 4;     /* IPREQ field sets IPINTR.  */
                    341: 
                    342:         newval &= ~0xf0000000000ull;       /* WO and RW fields */
                    343:         newval |= val & 0xf0000000000ull;
                    344:         s->cchip.misc = newval;
                    345: 
                    346:         /* Pass on changes to IPI and ITI state.  */
                    347:         if ((newval ^ oldval) & 0xff0) {
                    348:             int i;
                    349:             for (i = 0; i < 4; ++i) {
1.1.1.2 ! root      350:                 CPUAlphaState *env = s->cchip.cpu[i];
1.1       root      351:                 if (env) {
                    352:                     /* IPI can be either cleared or set by the write.  */
                    353:                     if (newval & (1 << (i + 8))) {
                    354:                         cpu_interrupt(env, CPU_INTERRUPT_SMP);
                    355:                     } else {
                    356:                         cpu_reset_interrupt(env, CPU_INTERRUPT_SMP);
                    357:                     }
                    358: 
                    359:                     /* ITI can only be cleared by the write.  */
                    360:                     if ((newval & (1 << (i + 4))) == 0) {
                    361:                         cpu_reset_interrupt(env, CPU_INTERRUPT_TIMER);
                    362:                     }
                    363:                 }
                    364:             }
                    365:         }
                    366:         break;
                    367: 
                    368:     case 0x00c0:
                    369:         /* MPD: Memory Presence Detect Register.  */
                    370:         break;
                    371: 
                    372:     case 0x0100: /* AAR0 */
                    373:     case 0x0140: /* AAR1 */
                    374:     case 0x0180: /* AAR2 */
                    375:     case 0x01c0: /* AAR3 */
                    376:         /* AAR: Array Address Register.  */
                    377:         /* All sorts of information about DRAM.  */
                    378:         break;
                    379: 
                    380:     case 0x0200: /* DIM0 */
                    381:         /* DIM: Device Interrupt Mask Register, CPU0.  */
                    382:         s->cchip.dim[0] = val;
                    383:         cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
                    384:         break;
                    385:     case 0x0240: /* DIM1 */
                    386:         /* DIM: Device Interrupt Mask Register, CPU1.  */
                    387:         s->cchip.dim[0] = val;
                    388:         cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
                    389:         break;
                    390: 
                    391:     case 0x0280: /* DIR0 (RO) */
                    392:     case 0x02c0: /* DIR1 (RO) */
                    393:     case 0x0300: /* DRIR (RO) */
                    394:         break;
                    395: 
                    396:     case 0x0340:
                    397:         /* PRBEN: Probe Enable Register.  */
                    398:         break;
                    399: 
                    400:     case 0x0380: /* IIC0 */
                    401:         s->cchip.iic[0] = val & 0xffffff;
                    402:         break;
                    403:     case 0x03c0: /* IIC1 */
                    404:         s->cchip.iic[1] = val & 0xffffff;
                    405:         break;
                    406: 
                    407:     case 0x0400: /* MPR0 */
                    408:     case 0x0440: /* MPR1 */
                    409:     case 0x0480: /* MPR2 */
                    410:     case 0x04c0: /* MPR3 */
                    411:         /* MPR: Memory Programming Register.  */
                    412:         break;
                    413: 
                    414:     case 0x0580:
                    415:         /* TTR: TIGbus Timing Register.  */
                    416:         /* All sorts of stuff related to interrupt delivery timings.  */
                    417:         break;
                    418:     case 0x05c0:
                    419:         /* TDR: TIGbug Device Timing Register.  */
                    420:         break;
                    421: 
                    422:     case 0x0600:
                    423:         /* DIM2: Device Interrupt Mask Register, CPU2.  */
                    424:         s->cchip.dim[2] = val;
                    425:         cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
                    426:         break;
                    427:     case 0x0640:
                    428:         /* DIM3: Device Interrupt Mask Register, CPU3.  */
                    429:         s->cchip.dim[3] = val;
                    430:         cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
                    431:         break;
                    432: 
                    433:     case 0x0680: /* DIR2 (RO) */
                    434:     case 0x06c0: /* DIR3 (RO) */
                    435:         break;
                    436: 
                    437:     case 0x0700: /* IIC2 */
                    438:         s->cchip.iic[2] = val & 0xffffff;
                    439:         break;
                    440:     case 0x0740: /* IIC3 */
                    441:         s->cchip.iic[3] = val & 0xffffff;
                    442:         break;
                    443: 
                    444:     case 0x0780:
                    445:         /* PWR: Power Management Control.   */
                    446:         break;
                    447:     
                    448:     case 0x0c00: /* CMONCTLA */
                    449:     case 0x0c40: /* CMONCTLB */
                    450:     case 0x0c80: /* CMONCNT01 */
                    451:     case 0x0cc0: /* CMONCNT23 */
                    452:         break;
                    453: 
                    454:     default:
                    455:         cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
                    456:         return;
                    457:     }
                    458: }
                    459: 
                    460: static void dchip_write(void *opaque, target_phys_addr_t addr,
                    461:                         uint64_t val, unsigned size)
                    462: {
                    463:     /* Skip this.  It's all related to DRAM timing and setup.  */
                    464: }
                    465: 
                    466: static void pchip_write(void *opaque, target_phys_addr_t addr,
                    467:                         uint64_t v32, unsigned size)
                    468: {
                    469:     TyphoonState *s = opaque;
                    470:     uint64_t val, oldval;
                    471: 
                    472:     if (addr & 4) {
                    473:         val = v32 << 32 | s->latch_tmp;
                    474:         addr ^= 4;
                    475:     } else {
                    476:         s->latch_tmp = v32;
                    477:         return;
                    478:     }
                    479: 
                    480:     switch (addr) {
                    481:     case 0x0000:
                    482:         /* WSBA0: Window Space Base Address Register.  */
                    483:         s->pchip.win[0].base_addr = val;
                    484:         break;
                    485:     case 0x0040:
                    486:         /* WSBA1 */
                    487:         s->pchip.win[1].base_addr = val;
                    488:         break;
                    489:     case 0x0080:
                    490:         /* WSBA2 */
                    491:         s->pchip.win[2].base_addr = val;
                    492:         break;
                    493:     case 0x00c0:
                    494:         /* WSBA3 */
                    495:         s->pchip.win[3].base_addr = val;
                    496:         break;
                    497: 
                    498:     case 0x0100:
                    499:         /* WSM0: Window Space Mask Register.  */
                    500:         s->pchip.win[0].mask = val;
                    501:         break;
                    502:     case 0x0140:
                    503:         /* WSM1 */
                    504:         s->pchip.win[1].mask = val;
                    505:         break;
                    506:     case 0x0180:
                    507:         /* WSM2 */
                    508:         s->pchip.win[2].mask = val;
                    509:         break;
                    510:     case 0x01c0:
                    511:         /* WSM3 */
                    512:         s->pchip.win[3].mask = val;
                    513:         break;
                    514: 
                    515:     case 0x0200:
                    516:         /* TBA0: Translated Base Address Register.  */
                    517:         s->pchip.win[0].translated_base_pfn = val >> 10;
                    518:         break;
                    519:     case 0x0240:
                    520:         /* TBA1 */
                    521:         s->pchip.win[1].translated_base_pfn = val >> 10;
                    522:         break;
                    523:     case 0x0280:
                    524:         /* TBA2 */
                    525:         s->pchip.win[2].translated_base_pfn = val >> 10;
                    526:         break;
                    527:     case 0x02c0:
                    528:         /* TBA3 */
                    529:         s->pchip.win[3].translated_base_pfn = val >> 10;
                    530:         break;
                    531: 
                    532:     case 0x0300:
                    533:         /* PCTL: Pchip Control Register.  */
                    534:         oldval = s->pchip.ctl;
                    535:         oldval &= ~0x00001cff0fc7ffull;       /* RW fields */
                    536:         oldval |= val & 0x00001cff0fc7ffull;
                    537: 
                    538:         s->pchip.ctl = oldval;
                    539:         break;
                    540: 
                    541:     case 0x0340:
                    542:         /* PLAT: Pchip Master Latency Register.  */
                    543:         break;
                    544:     case 0x03c0:
                    545:         /* PERROR: Pchip Error Register.  */
                    546:         break;
                    547:     case 0x0400:
                    548:         /* PERRMASK: Pchip Error Mask Register.  */
                    549:         break;
                    550:     case 0x0440:
                    551:         /* PERRSET: Pchip Error Set Register.  */
                    552:         break;
                    553: 
                    554:     case 0x0480:
                    555:         /* TLBIV: Translation Buffer Invalidate Virtual Register.  */
                    556:         break;
                    557: 
                    558:     case 0x04c0:
                    559:         /* TLBIA: Translation Buffer Invalidate All Register (WO).  */
                    560:         break;
                    561: 
                    562:     case 0x0500:
                    563:         /* PMONCTL */
                    564:     case 0x0540:
                    565:         /* PMONCNT */
                    566:     case 0x0800:
                    567:         /* SPRST */
                    568:         break;
                    569: 
                    570:     default:
                    571:         cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
                    572:         return;
                    573:     }
                    574: }
                    575: 
                    576: static const MemoryRegionOps cchip_ops = {
                    577:     .read = cchip_read,
                    578:     .write = cchip_write,
                    579:     .endianness = DEVICE_LITTLE_ENDIAN,
                    580:     .valid = {
                    581:         .min_access_size = 4,  /* ??? Should be 8.  */
                    582:         .max_access_size = 8,
                    583:     },
                    584:     .impl = {
                    585:         .min_access_size = 4,
                    586:         .max_access_size = 4,
                    587:     },
                    588: };
                    589: 
                    590: static const MemoryRegionOps dchip_ops = {
                    591:     .read = dchip_read,
                    592:     .write = dchip_write,
                    593:     .endianness = DEVICE_LITTLE_ENDIAN,
                    594:     .valid = {
                    595:         .min_access_size = 4,  /* ??? Should be 8.  */
                    596:         .max_access_size = 8,
                    597:     },
                    598:     .impl = {
                    599:         .min_access_size = 4,
                    600:         .max_access_size = 8,
                    601:     },
                    602: };
                    603: 
                    604: static const MemoryRegionOps pchip_ops = {
                    605:     .read = pchip_read,
                    606:     .write = pchip_write,
                    607:     .endianness = DEVICE_LITTLE_ENDIAN,
                    608:     .valid = {
                    609:         .min_access_size = 4,  /* ??? Should be 8.  */
                    610:         .max_access_size = 8,
                    611:     },
                    612:     .impl = {
                    613:         .min_access_size = 4,
                    614:         .max_access_size = 4,
                    615:     },
                    616: };
                    617: 
                    618: static void typhoon_set_irq(void *opaque, int irq, int level)
                    619: {
                    620:     TyphoonState *s = opaque;
                    621:     uint64_t drir;
                    622:     int i;
                    623: 
                    624:     /* Set/Reset the bit in CCHIP.DRIR based on IRQ+LEVEL.  */
                    625:     drir = s->cchip.drir;
                    626:     if (level) {
                    627:         drir |= 1ull << irq;
                    628:     } else {
                    629:         drir &= ~(1ull << irq);
                    630:     }
                    631:     s->cchip.drir = drir;
                    632: 
                    633:     for (i = 0; i < 4; ++i) {
                    634:         cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir);
                    635:     }
                    636: }
                    637: 
                    638: static void typhoon_set_isa_irq(void *opaque, int irq, int level)
                    639: {
                    640:     typhoon_set_irq(opaque, 55, level);
                    641: }
                    642: 
                    643: static void typhoon_set_timer_irq(void *opaque, int irq, int level)
                    644: {
                    645:     TyphoonState *s = opaque;
                    646:     int i;
                    647: 
                    648:     /* Thankfully, the mc146818rtc code doesn't track the IRQ state,
                    649:        and so we don't have to worry about missing interrupts just
                    650:        because we never actually ACK the interrupt.  Just ignore any
                    651:        case of the interrupt level going low.  */
                    652:     if (level == 0) {
                    653:         return;
                    654:     }
                    655: 
                    656:     /* Deliver the interrupt to each CPU, considering each CPU's IIC.  */
                    657:     for (i = 0; i < 4; ++i) {
1.1.1.2 ! root      658:         CPUAlphaState *env = s->cchip.cpu[i];
1.1       root      659:         if (env) {
                    660:             uint32_t iic = s->cchip.iic[i];
                    661: 
                    662:             /* ??? The verbage in Section 10.2.2.10 isn't 100% clear.
                    663:                Bit 24 is the OverFlow bit, RO, and set when the count
                    664:                decrements past 0.  When is OF cleared?  My guess is that
                    665:                OF is actually cleared when the IIC is written, and that
                    666:                the ICNT field always decrements.  At least, that's an
                    667:                interpretation that makes sense, and "allows the CPU to
                    668:                determine exactly how mant interval timer ticks were
                    669:                skipped".  At least within the next 4M ticks...  */
                    670: 
                    671:             iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000);
                    672:             s->cchip.iic[i] = iic;
                    673: 
                    674:             if (iic & 0x1000000) {
                    675:                 /* Set the ITI bit for this cpu.  */
                    676:                 s->cchip.misc |= 1 << (i + 4);
                    677:                 /* And signal the interrupt.  */
                    678:                 cpu_interrupt(env, CPU_INTERRUPT_TIMER);
                    679:             }
                    680:         }
                    681:     }
                    682: }
                    683: 
                    684: static void typhoon_alarm_timer(void *opaque)
                    685: {
                    686:     TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
                    687:     int cpu = (uintptr_t)opaque & 3;
                    688: 
                    689:     /* Set the ITI bit for this cpu.  */
                    690:     s->cchip.misc |= 1 << (cpu + 4);
                    691:     cpu_interrupt(s->cchip.cpu[cpu], CPU_INTERRUPT_TIMER);
                    692: }
                    693: 
1.1.1.2 ! root      694: PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
        !           695:                      qemu_irq *p_rtc_irq,
        !           696:                      CPUAlphaState *cpus[4], pci_map_irq_fn sys_map_irq)
1.1       root      697: {
                    698:     const uint64_t MB = 1024 * 1024;
                    699:     const uint64_t GB = 1024 * MB;
                    700:     MemoryRegion *addr_space = get_system_memory();
                    701:     MemoryRegion *addr_space_io = get_system_io();
                    702:     DeviceState *dev;
                    703:     PCIHostState *p;
                    704:     TyphoonState *s;
                    705:     PCIBus *b;
                    706:     int i;
                    707: 
                    708:     dev = qdev_create(NULL, "typhoon-pcihost");
                    709:     qdev_init_nofail(dev);
                    710: 
                    711:     p = FROM_SYSBUS(PCIHostState, sysbus_from_qdev(dev));
                    712:     s = container_of(p, TyphoonState, host);
                    713: 
                    714:     /* Remember the CPUs so that we can deliver interrupts to them.  */
                    715:     for (i = 0; i < 4; i++) {
1.1.1.2 ! root      716:         CPUAlphaState *env = cpus[i];
1.1       root      717:         s->cchip.cpu[i] = env;
                    718:         if (env) {
                    719:             env->alarm_timer = qemu_new_timer_ns(rtc_clock,
                    720:                                                  typhoon_alarm_timer,
                    721:                                                  (void *)((uintptr_t)s + i));
                    722:         }
                    723:     }
                    724: 
                    725:     *p_rtc_irq = *qemu_allocate_irqs(typhoon_set_timer_irq, s, 1);
                    726: 
                    727:     /* Main memory region, 0x00.0000.0000.  Real hardware supports 32GB,
                    728:        but the address space hole reserved at this point is 8TB.  */
1.1.1.2 ! root      729:     memory_region_init_ram(&s->ram_region, "ram", ram_size);
        !           730:     vmstate_register_ram_global(&s->ram_region);
1.1       root      731:     memory_region_add_subregion(addr_space, 0, &s->ram_region);
                    732: 
                    733:     /* TIGbus, 0x801.0000.0000, 1GB.  */
                    734:     /* ??? The TIGbus is used for delivering interrupts, and access to
                    735:        the flash ROM.  I'm not sure that we need to implement it at all.  */
                    736: 
                    737:     /* Pchip0 CSRs, 0x801.8000.0000, 256MB.  */
                    738:     memory_region_init_io(&s->pchip.region, &pchip_ops, s, "pchip0", 256*MB);
                    739:     memory_region_add_subregion(addr_space, 0x80180000000ULL,
                    740:                                 &s->pchip.region);
                    741: 
                    742:     /* Cchip CSRs, 0x801.A000.0000, 256MB.  */
                    743:     memory_region_init_io(&s->cchip.region, &cchip_ops, s, "cchip0", 256*MB);
                    744:     memory_region_add_subregion(addr_space, 0x801a0000000ULL,
                    745:                                 &s->cchip.region);
                    746: 
                    747:     /* Dchip CSRs, 0x801.B000.0000, 256MB.  */
                    748:     memory_region_init_io(&s->dchip_region, &dchip_ops, s, "dchip0", 256*MB);
                    749:     memory_region_add_subregion(addr_space, 0x801b0000000ULL,
                    750:                                 &s->dchip_region);
                    751: 
                    752:     /* Pchip0 PCI memory, 0x800.0000.0000, 4GB.  */
                    753:     memory_region_init(&s->pchip.reg_mem, "pci0-mem", 4*GB);
                    754:     memory_region_add_subregion(addr_space, 0x80000000000ULL,
                    755:                                 &s->pchip.reg_mem);
                    756: 
                    757:     /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB.  */
                    758:     /* ??? Ideally we drop the "system" i/o space on the floor and give the
                    759:        PCI subsystem the full address space reserved by the chipset.
                    760:        We can't do that until the MEM and IO paths in memory.c are unified.  */
                    761:     memory_region_init_io(&s->pchip.reg_io, &alpha_pci_bw_io_ops, NULL,
                    762:                           "pci0-io", 32*MB);
                    763:     memory_region_add_subregion(addr_space, 0x801fc000000ULL,
                    764:                                 &s->pchip.reg_io);
                    765: 
                    766:     b = pci_register_bus(&s->host.busdev.qdev, "pci",
                    767:                          typhoon_set_irq, sys_map_irq, s,
                    768:                          &s->pchip.reg_mem, addr_space_io, 0, 64);
                    769:     s->host.bus = b;
                    770: 
                    771:     /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB.  */
                    772:     memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b,
                    773:                           "pci0-iack", 64*MB);
                    774:     memory_region_add_subregion(addr_space, 0x801f8000000ULL,
                    775:                                 &s->pchip.reg_iack);
                    776: 
                    777:     /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB.  */
                    778:     memory_region_init_io(&s->pchip.reg_conf, &alpha_pci_conf1_ops, b,
                    779:                           "pci0-conf", 16*MB);
                    780:     memory_region_add_subregion(addr_space, 0x801fe000000ULL,
                    781:                                 &s->pchip.reg_conf);
                    782: 
                    783:     /* For the record, these are the mappings for the second PCI bus.
                    784:        We can get away with not implementing them because we indicate
                    785:        via the Cchip.CSC<PIP> bit that Pchip1 is not present.  */
                    786:     /* Pchip1 PCI memory, 0x802.0000.0000, 4GB.  */
                    787:     /* Pchip1 CSRs, 0x802.8000.0000, 256MB.  */
                    788:     /* Pchip1 PCI special/interrupt acknowledge, 0x802.F800.0000, 64MB.  */
                    789:     /* Pchip1 PCI I/O, 0x802.FC00.0000, 32MB.  */
                    790:     /* Pchip1 PCI configuration, 0x802.FE00.0000, 16MB.  */
                    791: 
                    792:     /* Init the ISA bus.  */
                    793:     /* ??? Technically there should be a cy82c693ub pci-isa bridge.  */
                    794:     {
                    795:         qemu_irq isa_pci_irq, *isa_irqs;
                    796: 
1.1.1.2 ! root      797:         *isa_bus = isa_bus_new(NULL, addr_space_io);
1.1       root      798:         isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1);
1.1.1.2 ! root      799:         isa_irqs = i8259_init(*isa_bus, isa_pci_irq);
        !           800:         isa_bus_irqs(*isa_bus, isa_irqs);
1.1       root      801:     }
                    802: 
                    803:     return b;
                    804: }
                    805: 
                    806: static int typhoon_pcihost_init(SysBusDevice *dev)
                    807: {
                    808:     return 0;
                    809: }
                    810: 
1.1.1.2 ! root      811: static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)
        !           812: {
        !           813:     DeviceClass *dc = DEVICE_CLASS(klass);
        !           814:     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
        !           815: 
        !           816:     k->init = typhoon_pcihost_init;
        !           817:     dc->no_user = 1;
        !           818: }
        !           819: 
        !           820: static TypeInfo typhoon_pcihost_info = {
        !           821:     .name          = "typhoon-pcihost",
        !           822:     .parent        = TYPE_SYS_BUS_DEVICE,
        !           823:     .instance_size = sizeof(TyphoonState),
        !           824:     .class_init    = typhoon_pcihost_class_init,
1.1       root      825: };
                    826: 
1.1.1.2 ! root      827: static void typhoon_register_types(void)
1.1       root      828: {
1.1.1.2 ! root      829:     type_register_static(&typhoon_pcihost_info);
1.1       root      830: }
1.1.1.2 ! root      831: 
        !           832: type_init(typhoon_register_types)

unix.superglobalmegacorp.com