|
|
1.1 ! root 1: /* ! 2: * machine-specific hardware routines, ! 3: * these for MicroVAX II ! 4: */ ! 5: ! 6: #include "sys/param.h" ! 7: #include "sys/pte.h" ! 8: #include "sys/mtpr.h" ! 9: #include "sys/vm.h" ! 10: #include "sys/qbio.h" ! 11: #include "sys/clock.h" ! 12: ! 13: #define IORESET 0x37 /* reset all IO connections */ ! 14: #define PARENB 01 /* mser: enable parity error traps */ ! 15: ! 16: /* ! 17: * bits in console mailbox ! 18: */ ! 19: ! 20: #define HALTACT 03 /* halt action */ ! 21: #define HMRBOOT 0 /* halt: restart, then boot (if halts disabled!) */ ! 22: #define HMRST 01 /* halt: restart regardless (but never boot) */ ! 23: #define HMBOOT 02 /* halt: boot */ ! 24: #define BOOTIH 04 /* boot inhibit */ ! 25: #define RSTIH 010 /* restart inhibit */ ! 26: ! 27: char *iospace; ! 28: int delayfact = 1; /* factor for DELAY macro */ ! 29: ! 30: /* ! 31: * adjust physical top of memory to useful top of memory: ! 32: * preserve space for console program (1024 bytes) ! 33: * and memory bitmap (one bit per 512-byte page; why do we save it?) ! 34: */ ! 35: machmem(hi) ! 36: int hi; ! 37: { ! 38: return(hi - (hi/(NBPG*NBBY)) - 1024); ! 39: } ! 40: ! 41: /* ! 42: * miscellaneous machine-dependent initialization ! 43: * called just after mapping turned on ! 44: * ! 45: * - make instruction emulation code accessible from user space ! 46: * - reset and enable IO ! 47: */ ! 48: machinit() ! 49: { ! 50: register int *p; /* pun; really struct pte */ ! 51: register char *e; ! 52: register struct iomflow *q; ! 53: extern char _emulbeg, _emulend; ! 54: ! 55: e = &_emulbeg; ! 56: p = (int *)&Sysmap[btop((int)e & ~KSTART)]; ! 57: do { ! 58: *p = (*p &~ PG_PROT) | PG_URKR; ! 59: p++; ! 60: e += NBPG; ! 61: } while (e < &_emulend); ! 62: mtpr(IORESET, 0); ! 63: q = (struct iomflow *)iospace; ! 64: q->c.mser = q->c.mser | PARENB; /* clear stale error bits */ ! 65: } ! 66: ! 67: /* ! 68: * stray interrupt handling: ! 69: * just decrypt it and return ! 70: */ ! 71: strayintr(v) ! 72: int v; ! 73: { ! 74: if (v < 0x200) ! 75: printf("stray interrupt at 0x%x\n", v); ! 76: else ! 77: printf("stray Q-bus interrupt at 0%o\n", v-0x200); ! 78: } ! 79: ! 80: /* ! 81: * how big is io space? ! 82: */ ! 83: ! 84: mchiopsize() ! 85: { ! 86: return (sizeof(struct iomflow)); ! 87: } ! 88: ! 89: /* ! 90: * set up the page tables for iospace ! 91: * called while the system page table is being assembled; ! 92: * memory mapping is off ! 93: * pt is the first page table of an area ! 94: * mapping what mchiopsize returned ! 95: */ ! 96: ! 97: mchiopinit(pt) ! 98: struct pte *pt; ! 99: { ! 100: register long *p; /* pun, for efficiency */ ! 101: register long b; ! 102: register int i; ! 103: ! 104: p = (long *)pt; ! 105: *p++ = PG_V|PG_KW|btop(0x20080000); /* cpu regs */ ! 106: *p++ = PG_V|PG_KW|btop(0x200b8000); /* watch chip regs */ ! 107: b = btop(0x20088000); /* Q-bus map */ ! 108: for (i = 0; i < (8192*sizeof(long))/NBPG; i++) ! 109: *p++ = PG_V|PG_KW|b++; ! 110: b = btop(0x20000000); /* Q-bus io regs */ ! 111: for (i = 0; i < 8192/NBPG; i++) ! 112: *p++ = PG_V|PG_KW|b++; ! 113: } ! 114: ! 115: /* ! 116: * return the IO regs for a Q-bus adapter ! 117: * (there's really only one, but only this code knows that) ! 118: */ ! 119: ! 120: caddr_t ! 121: qbaaddr(u) ! 122: int u; ! 123: { ! 124: if (u != 0) ! 125: return (0); ! 126: return ((caddr_t)&((struct iomflow *)iospace)->u[u]); ! 127: } ! 128: ! 129: /* ! 130: * arrange for a restart on halt ! 131: * -- it would be slightly preferable ! 132: * to fall back to a boot if the restart fails; ! 133: * alas, to do that on MicroVAX II, ! 134: * you must disable console halts ! 135: */ ! 136: ! 137: setrestart() ! 138: { ! 139: register short *p; ! 140: ! 141: p = &((struct iomflow *)iospace)->w.cpmbx; ! 142: *p &=~ (BOOTIH|RSTIH|HALTACT); ! 143: *p |= HMRST; /* always just restart */ ! 144: } ! 145: ! 146: /* ! 147: * arrange for a boot, now or on next halt ! 148: * -- sometimes called with mapping disabled ! 149: */ ! 150: ! 151: setboot() ! 152: { ! 153: register short *p; ! 154: ! 155: if (mfpr(MAPEN)) ! 156: p = &((struct iomflow *)iospace)->w.cpmbx; ! 157: else ! 158: p = (short *)0x200b801c; ! 159: *p &=~ (BOOTIH|HALTACT); ! 160: *p |= HMBOOT; /* halt mode `boot' */ ! 161: } ! 162: ! 163: /* ! 164: * time-of-year clock: ! 165: * in MicroVAX, it's a watch chip ! 166: * just use it as a counter with funny digits ! 167: */ ! 168: ! 169: #define BYEAR 82 /* arbitrary non-leap-year base */ ! 170: #define TODRRES 100 /* TODR units per second */ ! 171: ! 172: #define UIP 0200 /* csra - update in progress */ ! 173: #define AMAG 040 /* csra - magic clock modes */ ! 174: #define SET 0200 /* csrb - set clock */ ! 175: #define DM 04 /* csrb - binary (not bcd) */ ! 176: #define M24 02 /* csrb - 24-hour mode */ ! 177: #define VRT 0200 /* csrd - valid clock */ ! 178: ! 179: #define BOFF (SET|DM|M24) /* stop clock and ready for setting */ ! 180: #define BON (DM|M24) /* let clock go again */ ! 181: ! 182: static char dmsize[] = { ! 183: 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, ! 184: 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, ! 185: }; ! 186: ! 187: struct ty { /* just for convenience */ ! 188: char sec, min, hr, day, mon, yr; ! 189: }; ! 190: ! 191: gettodr() ! 192: { ! 193: register int s, i; ! 194: register struct watchregs *regs; ! 195: struct ty ty; ! 196: ! 197: regs = &((struct iomflow *)iospace)->w; ! 198: while(regs->csra & UIP) ! 199: ; ! 200: /* ! 201: * we now have 244us to read the clock ! 202: */ ! 203: if ((regs->csrd & VRT) == 0) { /* invalid time */ ! 204: regs->csrb = BOFF; ! 205: regs->csra = AMAG; ! 206: regs->yr = 0; /* just make it wrong */ ! 207: regs->csrb = BON; ! 208: return (0); /* and return a wrong answer */ ! 209: } ! 210: s = spl7(); ! 211: ty.sec = regs->sec; ! 212: ty.min = regs->min; ! 213: ty.hr = regs->hr; ! 214: ty.day = regs->day; ! 215: ty.mon = regs->mon; ! 216: ty.yr = regs->yr; ! 217: splx(s); ! 218: if (ty.sec < 0 || ty.sec > 59 ! 219: || ty.min < 0 || ty.min > 59 ! 220: || ty.hr < 0 || ty.hr > 23 ! 221: || ty.day < 1 || ty.day > 31 ! 222: || ty.mon < 1 || ty.mon > 12 ! 223: || ty.yr < BYEAR || ty.yr > BYEAR+1) ! 224: return 0; ! 225: if (ty.yr > BYEAR) ! 226: ty.mon += 12; /* overflow */ ! 227: s = 0; ! 228: for(i = 0; i < ty.mon-1; i++) ! 229: s += dmsize[i]; ! 230: s += ty.day-1; ! 231: s = 24*s + ty.hr; ! 232: s = 60*s + ty.min; ! 233: s = 60*s + ty.sec; ! 234: return (s*TODRRES+TODRZERO); ! 235: } ! 236: ! 237: /* ! 238: * This routine is used to set the MicroVAX-II toy register. ! 239: */ ! 240: settodr(tim) ! 241: { ! 242: register int yd; ! 243: register struct watchregs *regs; ! 244: struct ty ty; ! 245: ! 246: regs = &((struct iomflow *)iospace)->w; ! 247: tim = (tim - TODRZERO)/TODRRES; /* truncated -- too bad */ ! 248: ty.sec = tim % 60; ! 249: tim /= 60; ! 250: ty.min = tim % 60; ! 251: tim /= 60; ! 252: ty.hr = tim % 24; ! 253: tim /= 24; ! 254: yd = tim % 365; ! 255: tim /= 365; ! 256: ty.yr = BYEAR + tim; ! 257: for (ty.mon = 0; yd > dmsize[ty.mon]; ty.mon++) ! 258: yd -= dmsize[ty.mon]; ! 259: ty.day = yd; ! 260: regs->csrb = BOFF; ! 261: regs->csra = AMAG; ! 262: regs->sec = ty.sec; ! 263: regs->min = ty.min; ! 264: regs->hr = ty.hr; ! 265: regs->day = ty.day+1; ! 266: regs->mon = ty.mon+1; ! 267: regs->yr = ty.yr; ! 268: regs->csrb = BON; ! 269: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.