|
|
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.