/* This file is in the public domain. */ /* "driver" for the various machine registers that appear in the I/O space, like the psw, the pirq, the pars/pdrs, etc.... */ #include "pdp11.h" #include "driver.h" extern DRIVER reg_driver; static void fixpirq(void) { int i; i = 0; if (pirq & 0xf000 ) i += 4; if (pirq & (0x0c00 << i)) i += 2; if (pirq & (0x0200 << i)) i += 1; pirq = (pirq & 0xfe00) | (0x22 * i); if (i > 0) interrupt(®_driver,0240,i); } static void reg_init(UNUSED(DRIVER *d), char *iomask) { int i; iomask[IOMASK(017777776)] = 1; /* psw */ iomask[IOMASK(017777766)] = 1; /* cpu error */ iomask[IOMASK(017777772)] = 1; /* pirq */ iomask[IOMASK(017777750)] = 1; /* maint */ iomask[IOMASK(017777770)] = 1; /* micro-break */ iomask[IOMASK(017777774)] = 1; /* stack limit */ iomask[IOMASK(017777570)] = 1; /* console switch */ for (i=0;i<8;i++) { iomask[IOMASK(017777600+i+i)] = 1; /* user i pdr */ iomask[IOMASK(017777620+i+i)] = 1; /* user d pdr */ iomask[IOMASK(017777640+i+i)] = 1; /* user i par */ iomask[IOMASK(017777660+i+i)] = 1; /* user d par */ iomask[IOMASK(017772200+i+i)] = 1; /* supervisor i pdr */ iomask[IOMASK(017772220+i+i)] = 1; /* supervisor d pdr */ iomask[IOMASK(017772240+i+i)] = 1; /* supervisor i par */ iomask[IOMASK(017772260+i+i)] = 1; /* supervisor d par */ iomask[IOMASK(017772300+i+i)] = 1; /* kernel i pdr */ iomask[IOMASK(017772320+i+i)] = 1; /* kernel d pdr */ iomask[IOMASK(017772340+i+i)] = 1; /* kernel i par */ iomask[IOMASK(017772360+i+i)] = 1; /* kernel d par */ } iomask[IOMASK(017777572)] = 1; /* mmr0 */ iomask[IOMASK(017777574)] = 1; /* mmr1 */ iomask[IOMASK(017777576)] = 1; /* mmr2 */ iomask[IOMASK(017777516)] = 1; /* mmr3 */ iomask[IOMASK(017777746)] = 1; /* cache control */ iomask[IOMASK(017777752)] = 1; /* hit/miss */ iomask[IOMASK(017777744)] = 1; /* mem sys err */ for (i=0;i<0100;i+=2) iomask[IOMASK(017770200+i)] = 1; /* UNIBUS map */ } static int reg_io(UNUSED(DRIVER *d), int loc, int op,int data, UNUSED(void (*fxn)(void *))) { int rv; switch (loc&~1) { case IOMASK(017777776): /* psw */ rv = reg_access(loc,&psw,op,/*(pswc_cm==MODE_K)?PSW_T:(PSW_CM|PSW_PM|PSW_PRI|PSW_T)*/PSW_T,data); checkpsw(); break; case IOMASK(017777766): /* cpu error */ switch (op & IO_OP) { case IO_R: return(cpu_error); break; case IO_W: cpu_error = 0; break; } break; case IOMASK(017777772): /* pirq */ rv = reg_access(loc,&pirq,op,0x01ff,data); fixpirq(); break; case IOMASK(017777750): /* maint */ rv = reg_access(loc,&maint,op,~0,data); break; case IOMASK(017777572): /* mmr0 */ rv = reg_access(loc,&mmr0,op,MMR0_RO|MMR0_MBZ,data); break; case IOMASK(017777574): /* mmr1 */ rv = reg_access(loc,&mmr1,op,MMR_FROZEN?~0:0,data); break; case IOMASK(017777576): /* mmr2 */ rv = reg_access(loc,&mmr2,op,MMR_FROZEN?~0:0,data); break; case IOMASK(017777516): /* mmr3 */ rv = reg_access(loc,&mmr3,op,MMR_FROZEN?~0:MMR3_MBZ,data); break; case IOMASK(017777770): /* micro-break */ rv = reg_access(loc,µ_break,op,0,data); break; case IOMASK(017777774): /* stack limit */ rv = reg_access(loc,&stack_limit,op,0x00ff,data); break; case IOMASK(017777570): /* console switch */ rv = reg_access(loc,&console_switch,op,0,data); break; case IOMASK(017777746): /* cache control */ rv = reg_access(loc,&cache_control,op,CACHECTL_MBZ,data); break; case IOMASK(017777752): /* hit/miss */ rv = reg_access(loc,&hitmiss,op,~0,data); break; case IOMASK(017777744): /* mem sys err */ rv = reg_access(loc,&mem_sys_err,op,MEM_SYS_ERR_MBZ,data); break; default: switch (loc & 017777700) { case IOMASK(017777600): /* user i pdr */ rv = reg_access(loc,&pdesc[MODE_U][MMAN_ISPACE][(loc&017)>>1].pdr,op,PDR_MBZ,data); if (pswc_cm == MODE_U) clear1pac(MMAN_ISPACE,(loc&017)>>1); break; case IOMASK(017777620): /* user d pdr */ rv = reg_access(loc,&pdesc[MODE_U][MMAN_DSPACE][(loc&017)>>1].pdr,op,PDR_MBZ,data); if (pswc_cm == MODE_U) clear1pac(MMAN_DSPACE,(loc&017)>>1); break; case IOMASK(017777640): /* user i par */ rv = reg_access(loc,&pdesc[MODE_U][MMAN_ISPACE][(loc&017)>>1].par,op,0,data); if (pswc_cm == MODE_U) clear1pac(MMAN_ISPACE,(loc&017)>>1); break; case IOMASK(017777660): /* user d par */ rv = reg_access(loc,&pdesc[MODE_U][MMAN_DSPACE][(loc&017)>>1].par,op,0,data); if (pswc_cm == MODE_U) clear1pac(MMAN_DSPACE,(loc&017)>>1); break; case IOMASK(017772200): /* supervisor i pdr */ rv = reg_access(loc,&pdesc[MODE_S][MMAN_ISPACE][(loc&017)>>1].pdr,op,PDR_MBZ,data); if (pswc_cm == MODE_S) clear1pac(MMAN_ISPACE,(loc&017)>>1); break; case IOMASK(017772220): /* supervisor d pdr */ rv = reg_access(loc,&pdesc[MODE_S][MMAN_DSPACE][(loc&017)>>1].pdr,op,PDR_MBZ,data); if (pswc_cm == MODE_S) clear1pac(MMAN_DSPACE,(loc&017)>>1); break; case IOMASK(017772240): /* supervisor i par */ rv = reg_access(loc,&pdesc[MODE_S][MMAN_ISPACE][(loc&017)>>1].par,op,0,data); if (pswc_cm == MODE_S) clear1pac(MMAN_ISPACE,(loc&017)>>1); break; case IOMASK(017772260): /* supervisor d par */ rv = reg_access(loc,&pdesc[MODE_S][MMAN_DSPACE][(loc&017)>>1].par,op,0,data); if (pswc_cm == MODE_S) clear1pac(MMAN_DSPACE,(loc&017)>>1); break; case IOMASK(017772300): /* kernel i pdr */ rv = reg_access(loc,&pdesc[MODE_K][MMAN_ISPACE][(loc&017)>>1].pdr,op,PDR_MBZ,data); if (pswc_cm == MODE_K) clear1pac(MMAN_ISPACE,(loc&017)>>1); break; case IOMASK(017772320): /* kernel d pdr */ rv = reg_access(loc,&pdesc[MODE_K][MMAN_DSPACE][(loc&017)>>1].pdr,op,PDR_MBZ,data); if (pswc_cm == MODE_K) clear1pac(MMAN_DSPACE,(loc&017)>>1); break; case IOMASK(017772340): /* kernel i par */ rv = reg_access(loc,&pdesc[MODE_K][MMAN_ISPACE][(loc&017)>>1].par,op,0,data); if (pswc_cm == MODE_K) clear1pac(MMAN_ISPACE,(loc&017)>>1); break; case IOMASK(017772360): /* kernel d par */ rv = reg_access(loc,&pdesc[MODE_K][MMAN_DSPACE][(loc&017)>>1].par,op,0,data); if (pswc_cm == MODE_K) clear1pac(MMAN_DSPACE,(loc&017)>>1); break; case IOMASK(017770200): /* UNIBUS map */ case IOMASK(017770220): case IOMASK(017770240): case IOMASK(017770260): rv = reg_access(loc,(loc&2)?&ubam[(loc&037)>>2].lsb:&ubam[(loc&037)>>2].msb,op,0,data); break; } break; } return(rv); } static void reg_busreset(UNUSED(DRIVER *d)) { pirq = 0; stack_limit = 0; } static void reg_reset(UNUSED(DRIVER *d)) { } static int reg_intchk(INTRQ *irq) { return(pirq&(0x100<pri)); } DRIVER reg_driver = { DVR_NORMW, "processor registers", reg_init, 0, reg_io, reg_busreset, reg_reset, reg_intchk, 0 };