1 /*
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department, The Mach Operating System project at
9 * Carnegie-Mellon University and Ralph Campbell.
10 *
11 * %sccs.include.redist.c%
12 *
13 * @(#)machdep.c 8.5 (Berkeley) 06/02/95
14 */
15
16 /* from: Utah $Hdr: machdep.c 1.63 91/04/24$ */
17
18 #include <sys/param.h>
19 #include <sys/systm.h>
20 #include <sys/signalvar.h>
21 #include <sys/kernel.h>
22 #include <sys/map.h>
23 #include <sys/proc.h>
24 #include <sys/buf.h>
25 #include <sys/reboot.h>
26 #include <sys/conf.h>
27 #include <sys/file.h>
28 #include <sys/clist.h>
29 #include <sys/callout.h>
30 #include <sys/malloc.h>
31 #include <sys/mbuf.h>
32 #include <sys/msgbuf.h>
33 #include <sys/ioctl.h>
34 #include <sys/tty.h>
35 #include <sys/user.h>
36 #include <sys/exec.h>
37 #include <sys/sysctl.h>
38 #include <sys/mount.h>
39 #include <sys/syscallargs.h>
40 #ifdef SYSVSHM
41 #include <sys/shm.h>
42 #endif
43
44 #include <vm/vm_kern.h>
45
46 #include <machine/cpu.h>
47 #include <machine/reg.h>
48 #include <machine/psl.h>
49 #include <machine/pte.h>
50 #include <machine/dc7085cons.h>
51
52 #include <pmax/stand/dec_prom.h>
53
54 #include <pmax/dev/device.h>
55 #include <pmax/dev/sccreg.h>
56 #include <pmax/dev/ascreg.h>
57
58 #include <pmax/pmax/clockreg.h>
59 #include <pmax/pmax/kn01.h>
60 #include <pmax/pmax/kn02.h>
61 #include <pmax/pmax/kmin.h>
62 #include <pmax/pmax/maxine.h>
63 #include <pmax/pmax/kn03.h>
64 #include <pmax/pmax/asic.h>
65 #include <pmax/pmax/turbochannel.h>
66 #include <pmax/pmax/pmaxtype.h>
67 #include <pmax/pmax/cons.h>
68
69 #include <pm.h>
70 #include <cfb.h>
71 #include <mfb.h>
72 #include <xcfb.h>
73 #include <dc.h>
74 #include <dtop.h>
75 #include <scc.h>
76 #include <le.h>
77 #include <asc.h>
78
79 #if NDC > 0
80 extern int dcGetc(), dcparam();
81 extern void dcPutc();
82 #endif
83 #if NDTOP > 0
84 extern int dtopKBDGetc();
85 #endif
86 #if NSCC > 0
87 extern int sccGetc(), sccparam();
88 extern void sccPutc();
89 #endif
90 extern int KBDGetc();
91 extern void fbPutc();
92 extern struct consdev cn_tab;
93
94 /* Will scan from max to min, inclusive */
95 static int tc_max_slot = KN02_TC_MAX;
96 static int tc_min_slot = KN02_TC_MIN;
97 static u_int tc_slot_phys_base [TC_MAX_SLOTS] = {
98 /* use 3max for default values */
99 KN02_PHYS_TC_0_START, KN02_PHYS_TC_1_START,
100 KN02_PHYS_TC_2_START, KN02_PHYS_TC_3_START,
101 KN02_PHYS_TC_4_START, KN02_PHYS_TC_5_START,
102 KN02_PHYS_TC_6_START, KN02_PHYS_TC_7_START
103 };
104
105 /* the following is used externally (sysctl_hw) */
106 char machine[] = "DEC"; /* cpu "architecture" */
107 char cpu_model[30];
108
109 vm_map_t buffer_map;
110
111 /*
112 * Declare these as initialized data so we can patch them.
113 */
114 int nswbuf = 0;
115 #ifdef NBUF
116 int nbuf = NBUF;
117 #else
118 int nbuf = 0;
119 #endif
120 #ifdef BUFPAGES
121 int bufpages = BUFPAGES;
122 #else
123 int bufpages = 0;
124 #endif
125 int msgbufmapped = 0; /* set when safe to use msgbuf */
126 int maxmem; /* max memory per process */
127 int physmem; /* max supported memory, changes to actual */
128 int pmax_boardtype; /* Mother board type */
129 u_long le_iomem; /* 128K for lance chip via. ASIC */
130 u_long asc_iomem; /* and 7 * 8K buffers for the scsi */
131 u_long asic_base; /* Base address of I/O asic */
132 const struct callback *callv; /* pointer to PROM entry points */
133
134 void (*tc_enable_interrupt)();
135 extern int (*pmax_hardware_intr)();
136 void pmax_slot_hand_fill();
137 int kn02_intr(), kmin_intr(), xine_intr(), pmax_intr();
138 #ifdef DS5000_240
139 int kn03_intr();
140 #endif
141 extern int Mach_spl0(), Mach_spl1(), Mach_spl2(), Mach_spl3(), splhigh();
142 int (*Mach_splnet)() = splhigh;
143 int (*Mach_splbio)() = splhigh;
144 int (*Mach_splimp)() = splhigh;
145 int (*Mach_spltty)() = splhigh;
146 int (*Mach_splclock)() = splhigh;
147 int (*Mach_splstatclock)() = splhigh;
148 void (*tc_slot_hand_fill)();
149 extern volatile struct chiptime *Mach_clock_addr;
150 u_long kmin_tc3_imask, xine_tc3_imask;
151 #ifdef DS5000_240
152 u_long kn03_tc3_imask;
153 #endif
154 tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
155 static void asic_init();
156 extern void RemconsInit();
157 #ifdef DS5000
158 void kn02_enable_intr(), kn02_slot_hand_fill(),
159 kmin_enable_intr(), kmin_slot_hand_fill(),
160 xine_enable_intr(), xine_slot_hand_fill(),
161 tc_find_all_options();
162 #ifdef DS5000_240
163 void kn03_enable_intr(), kn03_slot_hand_fill();
164 #endif
165 #endif /* DS5000 */
166
167 /*
168 * safepri is a safe priority for sleep to set for a spin-wait
169 * during autoconfiguration or after a panic.
170 */
171 int safepri = PSL_LOWIPL;
172
173 struct user *proc0paddr;
174 struct proc nullproc; /* for use by swtch_exit() */
175
176 /*
177 * Do all the stuff that locore normally does before calling main().
178 * Process arguments passed to us by the prom monitor.
179 * Return the first page address following the system.
180 */
mach_init(argc,argv,code,cv)181 mach_init(argc, argv, code, cv)
182 int argc;
183 char *argv[];
184 u_int code;
185 const struct callback *cv;
186 {
187 register char *cp;
188 register int i;
189 register unsigned firstaddr;
190 register caddr_t v;
191 caddr_t start;
192 extern char edata[], end[];
193 extern char MachUTLBMiss[], MachUTLBMissEnd[];
194 extern char MachException[], MachExceptionEnd[];
195
196 /* clear the BSS segment */
197 v = (caddr_t)pmax_round_page(end);
198 bzero(edata, v - edata);
199
200 /* check for direct boot from DS5000 PROM */
201 if (argc > 0 && strcmp(argv[0], "boot") == 0) {
202 argc--;
203 argv++;
204 }
205
206 /* look at argv[0] and compute bootdev */
207 makebootdev(argv[0]);
208
209 /*
210 * Look at arguments passed to us and compute boothowto.
211 */
212 #ifdef GENERIC
213 boothowto = RB_SINGLE | RB_ASKNAME;
214 #else
215 boothowto = RB_SINGLE;
216 #endif
217 #ifdef KADB
218 boothowto |= RB_KDB;
219 #endif
220 if (argc > 1) {
221 for (i = 1; i < argc; i++) {
222 for (cp = argv[i]; *cp; cp++) {
223 switch (*cp) {
224 case 'a': /* autoboot */
225 boothowto &= ~RB_SINGLE;
226 break;
227
228 case 'd': /* use compiled in default root */
229 boothowto |= RB_DFLTROOT;
230 break;
231
232 case 'm': /* mini root present in memory */
233 boothowto |= RB_MINIROOT;
234 break;
235
236 case 'n': /* ask for names */
237 boothowto |= RB_ASKNAME;
238 break;
239
240 case 'N': /* don't ask for names */
241 boothowto &= ~RB_ASKNAME;
242 }
243 }
244 }
245 }
246
247 #ifdef MFS
248 /*
249 * Check to see if a mini-root was loaded into memory. It resides
250 * at the start of the next page just after the end of BSS.
251 */
252 if (boothowto & RB_MINIROOT) {
253 boothowto |= RB_DFLTROOT;
254 v += mfs_initminiroot(v);
255 }
256 #endif
257
258 /*
259 * Init mapping for u page(s) for proc[0], pm_tlbpid 1.
260 */
261 start = v;
262 curproc->p_addr = proc0paddr = (struct user *)v;
263 curproc->p_md.md_regs = proc0paddr->u_pcb.pcb_regs;
264 firstaddr = MACH_CACHED_TO_PHYS(v);
265 for (i = 0; i < UPAGES; i++) {
266 MachTLBWriteIndexed(i,
267 (UADDR + (i << PGSHIFT)) | (1 << VMMACH_TLB_PID_SHIFT),
268 curproc->p_md.md_upte[i] = firstaddr | PG_V | PG_M);
269 firstaddr += NBPG;
270 }
271 v += UPAGES * NBPG;
272 MachSetPID(1);
273
274 /*
275 * init nullproc for swtch_exit().
276 * init mapping for u page(s), pm_tlbpid 0
277 * This could be used for an idle process.
278 */
279 nullproc.p_addr = (struct user *)v;
280 nullproc.p_md.md_regs = nullproc.p_addr->u_pcb.pcb_regs;
281 bcopy("nullproc", nullproc.p_comm, sizeof("nullproc"));
282 for (i = 0; i < UPAGES; i++) {
283 nullproc.p_md.md_upte[i] = firstaddr | PG_V | PG_M;
284 firstaddr += NBPG;
285 }
286 v += UPAGES * NBPG;
287
288 /* clear pages for u areas */
289 bzero(start, v - start);
290
291 /*
292 * Copy down exception vector code.
293 */
294 if (MachUTLBMissEnd - MachUTLBMiss > 0x80)
295 panic("startup: UTLB code too large");
296 bcopy(MachUTLBMiss, (char *)MACH_UTLB_MISS_EXC_VEC,
297 MachUTLBMissEnd - MachUTLBMiss);
298 bcopy(MachException, (char *)MACH_GEN_EXC_VEC,
299 MachExceptionEnd - MachException);
300
301 /*
302 * Clear out the I and D caches.
303 */
304 MachConfigCache();
305 MachFlushCache();
306
307 /*
308 * Determine what model of computer we are running on.
309 */
310 if (code == DEC_PROM_MAGIC) {
311 callv = cv;
312 i = (*cv->getsysid)();
313 cp = "";
314 } else {
315 callv = &callvec;
316 if (cp = (*callv->getenv)("systype"))
317 i = atoi(cp);
318 else {
319 cp = "";
320 i = 0;
321 }
322 }
323 /* check for MIPS based platform */
324 if (((i >> 24) & 0xFF) != 0x82) {
325 printf("Unknown System type '%s' 0x%x\n", cp, i);
326 boot(RB_HALT | RB_NOSYNC);
327 }
328
329 /* check what model platform we are running on */
330 pmax_boardtype = ((i >> 16) & 0xff);
331 switch (pmax_boardtype) {
332 case DS_PMAX: /* DS3100 Pmax */
333 /*
334 * Set up interrupt handling and I/O addresses.
335 */
336 pmax_hardware_intr = pmax_intr;
337 Mach_splnet = Mach_spl1;
338 Mach_splbio = Mach_spl0;
339 Mach_splimp = Mach_spl1;
340 Mach_spltty = Mach_spl2;
341 Mach_splclock = Mach_spl3;
342 Mach_splstatclock = Mach_spl3;
343 Mach_clock_addr = (volatile struct chiptime *)
344 MACH_PHYS_TO_UNCACHED(KN01_SYS_CLOCK);
345 pmax_slot_hand_fill();
346 strcpy(cpu_model, "3100");
347 break;
348
349 #ifdef DS5000
350 case DS_3MAX: /* DS5000/200 3max */
351 {
352 volatile int *csr_addr =
353 (volatile int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
354
355 /*
356 * Enable ECC memory correction, turn off LEDs, and
357 * disable all TURBOchannel interrupts.
358 */
359 i = *csr_addr;
360 *csr_addr = (i & ~(KN02_CSR_WRESERVED | KN02_CSR_IOINTEN)) |
361 KN02_CSR_CORRECT | 0xff;
362
363 tc_slot_hand_fill = kn02_slot_hand_fill;
364 pmax_hardware_intr = kn02_intr;
365 tc_enable_interrupt = kn02_enable_intr;
366 Mach_splnet = Mach_spl0;
367 Mach_splbio = Mach_spl0;
368 Mach_splimp = Mach_spl0;
369 Mach_spltty = Mach_spl0;
370 Mach_splclock = Mach_spl1;
371 Mach_splstatclock = Mach_spl1;
372 Mach_clock_addr = (volatile struct chiptime *)
373 MACH_PHYS_TO_UNCACHED(KN02_SYS_CLOCK);
374
375 /*
376 * Probe the TURBOchannel to see what controllers are present.
377 */
378 tc_find_all_options();
379
380 /* clear any memory errors from probes */
381 *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0;
382 }
383 strcpy(cpu_model, "5000/200");
384 break;
385
386 case DS_3MIN: /* DS5000/1xx 3min */
387 tc_max_slot = KMIN_TC_MAX;
388 tc_min_slot = KMIN_TC_MIN;
389 tc_slot_phys_base[0] = KMIN_PHYS_TC_0_START;
390 tc_slot_phys_base[1] = KMIN_PHYS_TC_1_START;
391 tc_slot_phys_base[2] = KMIN_PHYS_TC_2_START;
392 asic_base = MACH_PHYS_TO_UNCACHED(KMIN_SYS_ASIC);
393 tc_slot_hand_fill = kmin_slot_hand_fill;
394 pmax_hardware_intr = kmin_intr;
395 tc_enable_interrupt = kmin_enable_intr;
396 kmin_tc3_imask = (KMIN_INTR_CLOCK | KMIN_INTR_PSWARN |
397 KMIN_INTR_TIMEOUT);
398
399 /*
400 * Since all the motherboard interrupts come through the
401 * I/O ASIC, it has to be turned off for all the spls and
402 * since we don't know what kinds of devices are in the
403 * turbochannel option slots, just splhigh().
404 */
405 Mach_splnet = splhigh;
406 Mach_splbio = splhigh;
407 Mach_splimp = splhigh;
408 Mach_spltty = splhigh;
409 Mach_splclock = splhigh;
410 Mach_splstatclock = splhigh;
411 Mach_clock_addr = (volatile struct chiptime *)
412 MACH_PHYS_TO_UNCACHED(KMIN_SYS_CLOCK);
413
414 /*
415 * Probe the TURBOchannel to see what controllers are present.
416 */
417 tc_find_all_options();
418
419 /*
420 * Initialize interrupts.
421 */
422 *(u_int *)ASIC_REG_IMSK(asic_base) = KMIN_IM0;
423 *(u_int *)ASIC_REG_INTR(asic_base) = 0;
424 /* clear any memory errors from probes */
425 *(unsigned *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0;
426 strcpy(cpu_model, "5000/1xx");
427 break;
428
429 case DS_MAXINE: /* DS5000/xx maxine */
430 tc_max_slot = XINE_TC_MAX;
431 tc_min_slot = XINE_TC_MIN;
432 tc_slot_phys_base[0] = XINE_PHYS_TC_0_START;
433 tc_slot_phys_base[1] = XINE_PHYS_TC_1_START;
434 asic_base = MACH_PHYS_TO_UNCACHED(XINE_SYS_ASIC);
435 tc_slot_hand_fill = xine_slot_hand_fill;
436 pmax_hardware_intr = xine_intr;
437 tc_enable_interrupt = xine_enable_intr;
438 Mach_splnet = Mach_spl3;
439 Mach_splbio = Mach_spl3;
440 Mach_splimp = Mach_spl3;
441 Mach_spltty = Mach_spl3;
442 Mach_splclock = Mach_spl1;
443 Mach_splstatclock = Mach_spl1;
444 Mach_clock_addr = (volatile struct chiptime *)
445 MACH_PHYS_TO_UNCACHED(XINE_SYS_CLOCK);
446
447 /*
448 * Probe the TURBOchannel to see what controllers are present.
449 */
450 tc_find_all_options();
451
452 /*
453 * Initialize interrupts.
454 */
455 *(u_int *)ASIC_REG_IMSK(asic_base) = XINE_IM0;
456 *(u_int *)ASIC_REG_INTR(asic_base) = 0;
457 /* clear any memory errors from probes */
458 *(unsigned *)MACH_PHYS_TO_UNCACHED(XINE_REG_TIMEOUT) = 0;
459 strcpy(cpu_model, "5000/25");
460 break;
461
462 #ifdef DS5000_240
463 case DS_3MAXPLUS: /* DS5000/240 3max+ UNTESTED!! */
464 tc_max_slot = KN03_TC_MAX;
465 tc_min_slot = KN03_TC_MIN;
466 tc_slot_phys_base[0] = KN03_PHYS_TC_0_START;
467 tc_slot_phys_base[1] = KN03_PHYS_TC_1_START;
468 tc_slot_phys_base[2] = KN03_PHYS_TC_2_START;
469 asic_base = MACH_PHYS_TO_UNCACHED(KN03_SYS_ASIC);
470 tc_slot_hand_fill = kn03_slot_hand_fill;
471 pmax_hardware_intr = kn03_intr;
472 tc_enable_interrupt = kn03_enable_intr;
473 kn03_tc3_imask = KN03_INTR_PSWARN;
474
475 Mach_splnet = Mach_spl0;
476 Mach_splbio = Mach_spl0;
477 Mach_splimp = Mach_spl0;
478 Mach_spltty = Mach_spl0;
479 Mach_splclock = Mach_spl1;
480 Mach_splstatclock = Mach_spl1;
481 Mach_clock_addr = (volatile struct chiptime *)
482 MACH_PHYS_TO_UNCACHED(KN03_SYS_CLOCK);
483
484 /*
485 * Probe the TURBOchannel to see what controllers are present.
486 */
487 tc_find_all_options();
488
489 /*
490 * Initialize interrupts.
491 */
492 *(u_int *)ASIC_REG_IMSK(asic_base) = KN03_IM0;
493 *(u_int *)ASIC_REG_INTR(asic_base) = 0;
494 /* clear any memory errors from probes */
495 *(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR) = 0;
496 strcpy(cpu_model, "5000/240");
497 break;
498 #endif /* DS5000_240 */
499 #endif /* DS5000 */
500
501 default:
502 printf("kernel not configured for systype 0x%x\n", i);
503 boot(RB_HALT | RB_NOSYNC);
504 }
505
506 /*
507 * Find out how much memory is available.
508 * Be careful to save and restore the original contents for msgbuf.
509 */
510 physmem = btoc(v - KERNBASE);
511 cp = (char *)MACH_PHYS_TO_UNCACHED(physmem << PGSHIFT);
512 while (cp < (char *)MACH_MAX_MEM_ADDR) {
513 if (badaddr(cp, 4))
514 break;
515 i = *(int *)cp;
516 *(int *)cp = 0xa5a5a5a5;
517 /*
518 * Data will persist on the bus if we read it right away.
519 * Have to be tricky here.
520 */
521 ((int *)cp)[4] = 0x5a5a5a5a;
522 MachEmptyWriteBuffer();
523 if (*(int *)cp != 0xa5a5a5a5)
524 break;
525 *(int *)cp = i;
526 cp += NBPG;
527 physmem++;
528 }
529
530 maxmem = physmem;
531
532 #if NLE > 0
533 /*
534 * Grab 128K at the top of physical memory for the lance chip
535 * on machines where it does dma through the I/O ASIC.
536 * It must be physically contiguous and aligned on a 128K boundary.
537 */
538 if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE ||
539 pmax_boardtype == DS_3MAXPLUS) {
540 maxmem -= btoc(128 * 1024);
541 le_iomem = (maxmem << PGSHIFT);
542 }
543 #endif /* NLE */
544 #if NASC > 0
545 /*
546 * Ditto for the scsi chip. There is probably a way to make asc.c
547 * do dma without these buffers, but it would require major
548 * re-engineering of the asc driver.
549 * They must be 8K in size and page aligned.
550 */
551 if (pmax_boardtype == DS_3MIN || pmax_boardtype == DS_MAXINE ||
552 pmax_boardtype == DS_3MAXPLUS) {
553 maxmem -= btoc(ASC_NCMD * 8192);
554 asc_iomem = (maxmem << PGSHIFT);
555 }
556 #endif /* NASC */
557
558 /*
559 * Initialize error message buffer (at end of core).
560 */
561 maxmem -= btoc(sizeof (struct msgbuf));
562 msgbufp = (struct msgbuf *)(MACH_PHYS_TO_CACHED(maxmem << PGSHIFT));
563 msgbufmapped = 1;
564
565 /*
566 * Allocate space for system data structures.
567 * The first available kernel virtual address is in "v".
568 * As pages of kernel virtual memory are allocated, "v" is incremented.
569 *
570 * These data structures are allocated here instead of cpu_startup()
571 * because physical memory is directly addressable. We don't have
572 * to map these into virtual address space.
573 */
574 start = v;
575
576 #define valloc(name, type, num) \
577 (name) = (type *)v; v = (caddr_t)((name)+(num))
578 #define valloclim(name, type, num, lim) \
579 (name) = (type *)v; v = (caddr_t)((lim) = ((name)+(num)))
580 valloc(cfree, struct cblock, nclist);
581 valloc(callout, struct callout, ncallout);
582 valloc(swapmap, struct map, nswapmap = maxproc * 2);
583 #ifdef SYSVSHM
584 valloc(shmsegs, struct shmid_ds, shminfo.shmmni);
585 #endif
586
587 /*
588 * Determine how many buffers to allocate.
589 * We allocate more buffer space than the BSD standard of
590 * using 10% of memory for the first 2 Meg, 5% of remaining.
591 * We just allocate a flat 10%. Ensure a minimum of 16 buffers.
592 * We allocate 1/2 as many swap buffer headers as file i/o buffers.
593 */
594 if (bufpages == 0)
595 bufpages = physmem / 10 / CLSIZE;
596 if (nbuf == 0) {
597 nbuf = bufpages;
598 if (nbuf < 16)
599 nbuf = 16;
600 }
601 if (nswbuf == 0) {
602 nswbuf = (nbuf / 2) &~ 1; /* force even */
603 if (nswbuf > 256)
604 nswbuf = 256; /* sanity */
605 }
606 valloc(swbuf, struct buf, nswbuf);
607 valloc(buf, struct buf, nbuf);
608
609 /*
610 * Clear allocated memory.
611 */
612 bzero(start, v - start);
613
614 /*
615 * Initialize the virtual memory system.
616 */
617 pmap_bootstrap((vm_offset_t)v);
618 }
619
620 /*
621 * Console initialization: called early on from main,
622 * before vm init or startup. Do enough configuration
623 * to choose and initialize a console.
624 */
consinit()625 consinit()
626 {
627 register int kbd, crt;
628 register char *oscon;
629
630 /*
631 * First get the "osconsole" environment variable.
632 */
633 oscon = (*callv->getenv)("osconsole");
634 crt = kbd = -1;
635 if (oscon && *oscon >= '0' && *oscon <= '9') {
636 kbd = *oscon - '0';
637 cn_tab.cn_screen = 0;
638 while (*++oscon) {
639 if (*oscon == ',')
640 cn_tab.cn_screen = 1;
641 else if (cn_tab.cn_screen &&
642 *oscon >= '0' && *oscon <= '9') {
643 crt = kbd;
644 kbd = *oscon - '0';
645 break;
646 }
647 }
648 }
649 if (pmax_boardtype == DS_PMAX && kbd == 1)
650 cn_tab.cn_screen = 1;
651 /*
652 * The boot program uses PMAX ROM entrypoints so the ROM sets
653 * osconsole to '1' like the PMAX.
654 */
655 if (pmax_boardtype == DS_3MAX && crt == -1 && kbd == 1) {
656 cn_tab.cn_screen = 1;
657 crt = 0;
658 kbd = 7;
659 }
660
661 /*
662 * First try the keyboard/crt cases then fall through to the
663 * remote serial lines.
664 */
665 if (cn_tab.cn_screen) {
666 switch (pmax_boardtype) {
667 case DS_PMAX:
668 #if NDC > 0 && NPM > 0
669 if (pminit()) {
670 cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT);
671 cn_tab.cn_getc = KBDGetc;
672 cn_tab.cn_kbdgetc = dcGetc;
673 cn_tab.cn_putc = fbPutc;
674 cn_tab.cn_disabled = 0;
675 return;
676 }
677 #endif /* NDC and NPM */
678 goto remcons;
679
680 case DS_MAXINE:
681 #if NDTOP > 0
682 if (kbd == 3) {
683 cn_tab.cn_dev = makedev(DTOPDEV, 0);
684 cn_tab.cn_getc = dtopKBDGetc;
685 cn_tab.cn_putc = fbPutc;
686 } else
687 #endif /* NDTOP */
688 goto remcons;
689 #if NXCFB > 0
690 if (crt == 3 && xcfbinit()) {
691 cn_tab.cn_disabled = 0;
692 return;
693 }
694 #endif /* XCFB */
695 break;
696
697 case DS_3MAX:
698 #if NDC > 0
699 if (kbd == 7) {
700 cn_tab.cn_dev = makedev(DCDEV, DCKBD_PORT);
701 cn_tab.cn_getc = KBDGetc;
702 cn_tab.cn_kbdgetc = dcGetc;
703 cn_tab.cn_putc = fbPutc;
704 } else
705 #endif /* NDC */
706 goto remcons;
707 break;
708
709 case DS_3MIN:
710 case DS_3MAXPLUS:
711 #if NSCC > 0
712 if (kbd == 3) {
713 cn_tab.cn_dev = makedev(SCCDEV, SCCKBD_PORT);
714 cn_tab.cn_getc = KBDGetc;
715 cn_tab.cn_kbdgetc = sccGetc;
716 cn_tab.cn_putc = fbPutc;
717 } else
718 #endif /* NSCC */
719 goto remcons;
720 break;
721
722 default:
723 goto remcons;
724 };
725
726 /*
727 * Check for a suitable turbochannel frame buffer.
728 */
729 if (tc_slot_info[crt].driver_name) {
730 #if NMFB > 0
731 if (strcmp(tc_slot_info[crt].driver_name, "mfb") == 0 &&
732 mfbinit(tc_slot_info[crt].k1seg_address)) {
733 cn_tab.cn_disabled = 0;
734 return;
735 }
736 #endif /* NMFB */
737 #if NCFB > 0
738 if (strcmp(tc_slot_info[crt].driver_name, "cfb") == 0 &&
739 cfbinit(tc_slot_info[crt].k1seg_address)) {
740 cn_tab.cn_disabled = 0;
741 return;
742 }
743 #endif /* NCFB */
744 printf("crt: %s not supported as console device\n",
745 tc_slot_info[crt].driver_name);
746 } else
747 printf("No crt console device in slot %d\n", crt);
748 }
749 remcons:
750 /*
751 * Configure a serial port as a remote console.
752 */
753 cn_tab.cn_screen = 0;
754 switch (pmax_boardtype) {
755 case DS_PMAX:
756 #if NDC > 0
757 if (kbd == 4)
758 cn_tab.cn_dev = makedev(DCDEV, DCCOMM_PORT);
759 else
760 cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT);
761 cn_tab.cn_getc = dcGetc;
762 cn_tab.cn_putc = dcPutc;
763 #endif /* NDC */
764 break;
765
766 case DS_3MAX:
767 #if NDC > 0
768 cn_tab.cn_dev = makedev(DCDEV, DCPRINTER_PORT);
769 cn_tab.cn_getc = dcGetc;
770 cn_tab.cn_putc = dcPutc;
771 #endif /* NDC */
772 break;
773
774 case DS_3MIN:
775 case DS_3MAXPLUS:
776 #if NSCC > 0
777 cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM3_PORT);
778 cn_tab.cn_getc = sccGetc;
779 cn_tab.cn_putc = sccPutc;
780 #endif /* NSCC */
781 break;
782
783 case DS_MAXINE:
784 #if NSCC > 0
785 cn_tab.cn_dev = makedev(SCCDEV, SCCCOMM2_PORT);
786 cn_tab.cn_getc = sccGetc;
787 cn_tab.cn_putc = sccPutc;
788 #endif /* NSCC */
789 break;
790 };
791 if (cn_tab.cn_dev == NODEV)
792 printf("Can't configure console!\n");
793 }
794
795 /*
796 * cpu_startup: allocate memory for variable-sized tables,
797 * initialize cpu, and do autoconfiguration.
798 */
cpu_startup()799 cpu_startup()
800 {
801 register unsigned i;
802 register caddr_t v;
803 int base, residual;
804 vm_offset_t minaddr, maxaddr;
805 vm_size_t size;
806 #ifdef DEBUG
807 extern int pmapdebug;
808 int opmapdebug = pmapdebug;
809
810 pmapdebug = 0;
811 #endif
812
813 /*
814 * Good {morning,afternoon,evening,night}.
815 */
816 printf(version);
817 printf("real mem = %d\n", ctob(physmem));
818
819 /*
820 * Allocate virtual address space for file I/O buffers.
821 * Note they are different than the array of headers, 'buf',
822 * and usually occupy more virtual memory than physical.
823 */
824 size = MAXBSIZE * nbuf;
825 buffer_map = kmem_suballoc(kernel_map, (vm_offset_t *)&buffers,
826 &maxaddr, size, TRUE);
827 minaddr = (vm_offset_t)buffers;
828 if (vm_map_find(buffer_map, vm_object_allocate(size), (vm_offset_t)0,
829 &minaddr, size, FALSE) != KERN_SUCCESS)
830 panic("startup: cannot allocate buffers");
831 base = bufpages / nbuf;
832 residual = bufpages % nbuf;
833 for (i = 0; i < nbuf; i++) {
834 vm_size_t curbufsize;
835 vm_offset_t curbuf;
836
837 /*
838 * First <residual> buffers get (base+1) physical pages
839 * allocated for them. The rest get (base) physical pages.
840 *
841 * The rest of each buffer occupies virtual space,
842 * but has no physical memory allocated for it.
843 */
844 curbuf = (vm_offset_t)buffers + i * MAXBSIZE;
845 curbufsize = CLBYTES * (i < residual ? base+1 : base);
846 vm_map_pageable(buffer_map, curbuf, curbuf+curbufsize, FALSE);
847 vm_map_simplify(buffer_map, curbuf);
848 }
849 /*
850 * Allocate a submap for exec arguments. This map effectively
851 * limits the number of processes exec'ing at any time.
852 */
853 exec_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
854 16 * NCARGS, TRUE);
855 /*
856 * Allocate a submap for physio
857 */
858 phys_map = kmem_suballoc(kernel_map, &minaddr, &maxaddr,
859 VM_PHYS_SIZE, TRUE);
860
861 /*
862 * Finally, allocate mbuf pool. Since mclrefcnt is an off-size
863 * we use the more space efficient malloc in place of kmem_alloc.
864 */
865 mclrefcnt = (char *)malloc(NMBCLUSTERS+CLBYTES/MCLBYTES,
866 M_MBUF, M_NOWAIT);
867 bzero(mclrefcnt, NMBCLUSTERS+CLBYTES/MCLBYTES);
868 mb_map = kmem_suballoc(kernel_map, (vm_offset_t *)&mbutl, &maxaddr,
869 VM_MBUF_SIZE, FALSE);
870 /*
871 * Initialize callouts
872 */
873 callfree = callout;
874 for (i = 1; i < ncallout; i++)
875 callout[i-1].c_next = &callout[i];
876 callout[i-1].c_next = NULL;
877
878 #ifdef DEBUG
879 pmapdebug = opmapdebug;
880 #endif
881 printf("avail mem = %d\n", ptoa(cnt.v_free_count));
882 printf("using %d buffers containing %d bytes of memory\n",
883 nbuf, bufpages * CLBYTES);
884 /*
885 * Set up CPU-specific registers, cache, etc.
886 */
887 initcpu();
888
889 /*
890 * Set up buffers, so they can be used to read disk labels.
891 */
892 bufinit();
893
894 /*
895 * Configure the system.
896 */
897 configure();
898 }
899
900 /*
901 * machine dependent system variables.
902 */
cpu_sysctl(name,namelen,oldp,oldlenp,newp,newlen,p)903 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
904 int *name;
905 u_int namelen;
906 void *oldp;
907 size_t *oldlenp;
908 void *newp;
909 size_t newlen;
910 struct proc *p;
911 {
912
913 /* all sysctl names at this level are terminal */
914 if (namelen != 1)
915 return (ENOTDIR); /* overloaded */
916
917 switch (name[0]) {
918 case CPU_CONSDEV:
919 return (sysctl_rdstruct(oldp, oldlenp, newp, &cn_tab.cn_dev,
920 sizeof cn_tab.cn_dev));
921 default:
922 return (EOPNOTSUPP);
923 }
924 /* NOTREACHED */
925 }
926
927 /*
928 * Set registers on exec.
929 * Clear all registers except sp, pc.
930 */
setregs(p,entry,retval)931 setregs(p, entry, retval)
932 register struct proc *p;
933 u_long entry;
934 register_t retval[2];
935 {
936 int sp = p->p_md.md_regs[SP];
937 extern struct proc *machFPCurProcPtr;
938
939 bzero((caddr_t)p->p_md.md_regs, (FSR + 1) * sizeof(int));
940 p->p_md.md_regs[SP] = sp;
941 p->p_md.md_regs[PC] = entry & ~3;
942 p->p_md.md_regs[PS] = PSL_USERSET;
943 p->p_md.md_flags & ~MDP_FPUSED;
944 if (machFPCurProcPtr == p)
945 machFPCurProcPtr = (struct proc *)0;
946 }
947
948 /*
949 * WARNING: code in locore.s assumes the layout shown for sf_signum
950 * thru sf_handler so... don't screw with them!
951 */
952 struct sigframe {
953 int sf_signum; /* signo for handler */
954 int sf_code; /* additional info for handler */
955 struct sigcontext *sf_scp; /* context ptr for handler */
956 sig_t sf_handler; /* handler addr for u_sigc */
957 struct sigcontext sf_sc; /* actual context */
958 };
959
960 #ifdef DEBUG
961 int sigdebug = 0;
962 int sigpid = 0;
963 #define SDB_FOLLOW 0x01
964 #define SDB_KSTACK 0x02
965 #define SDB_FPSTATE 0x04
966 #endif
967
968 /*
969 * Send an interrupt to process.
970 */
971 void
sendsig(catcher,sig,mask,code)972 sendsig(catcher, sig, mask, code)
973 sig_t catcher;
974 int sig, mask;
975 u_long code;
976 {
977 register struct proc *p = curproc;
978 register struct sigframe *fp;
979 register int *regs;
980 register struct sigacts *psp = p->p_sigacts;
981 int oonstack, fsize;
982 struct sigcontext ksc;
983 extern char sigcode[], esigcode[];
984
985 regs = p->p_md.md_regs;
986 oonstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
987 /*
988 * Allocate and validate space for the signal handler
989 * context. Note that if the stack is in data space, the
990 * call to grow() is a nop, and the copyout()
991 * will fail if the process has not already allocated
992 * the space with a `brk'.
993 */
994 fsize = sizeof(struct sigframe);
995 if ((psp->ps_flags & SAS_ALTSTACK) &&
996 (psp->ps_sigstk.ss_flags & SA_ONSTACK) == 0 &&
997 (psp->ps_sigonstack & sigmask(sig))) {
998 fp = (struct sigframe *)(psp->ps_sigstk.ss_base +
999 psp->ps_sigstk.ss_size - fsize);
1000 psp->ps_sigstk.ss_flags |= SA_ONSTACK;
1001 } else
1002 fp = (struct sigframe *)(regs[SP] - fsize);
1003 if ((unsigned)fp <= USRSTACK - ctob(p->p_vmspace->vm_ssize))
1004 (void)grow(p, (unsigned)fp);
1005 #ifdef DEBUG
1006 if ((sigdebug & SDB_FOLLOW) ||
1007 (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1008 printf("sendsig(%d): sig %d ssp %x usp %x scp %x\n",
1009 p->p_pid, sig, &oonstack, fp, &fp->sf_sc);
1010 #endif
1011 /*
1012 * Build the signal context to be used by sigreturn.
1013 */
1014 ksc.sc_onstack = oonstack;
1015 ksc.sc_mask = mask;
1016 ksc.sc_pc = regs[PC];
1017 ksc.sc_regs[ZERO] = 0xACEDBADE; /* magic number */
1018 bcopy((caddr_t)®s[1], (caddr_t)&ksc.sc_regs[1],
1019 sizeof(ksc.sc_regs) - sizeof(int));
1020 ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
1021 if (ksc.sc_fpused) {
1022 extern struct proc *machFPCurProcPtr;
1023
1024 /* if FPU has current state, save it first */
1025 if (p == machFPCurProcPtr)
1026 MachSaveCurFPState(p);
1027 bcopy((caddr_t)&p->p_md.md_regs[F0], (caddr_t)ksc.sc_fpregs,
1028 sizeof(ksc.sc_fpregs));
1029 }
1030 if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc))) {
1031 /*
1032 * Process has trashed its stack; give it an illegal
1033 * instruction to halt it in its tracks.
1034 */
1035 SIGACTION(p, SIGILL) = SIG_DFL;
1036 sig = sigmask(SIGILL);
1037 p->p_sigignore &= ~sig;
1038 p->p_sigcatch &= ~sig;
1039 p->p_sigmask &= ~sig;
1040 psignal(p, SIGILL);
1041 return;
1042 }
1043 /*
1044 * Build the argument list for the signal handler.
1045 */
1046 regs[A0] = sig;
1047 regs[A1] = code;
1048 regs[A2] = (int)&fp->sf_sc;
1049 regs[A3] = (int)catcher;
1050
1051 regs[PC] = (int)catcher;
1052 regs[SP] = (int)fp;
1053 /*
1054 * Signal trampoline code is at base of user stack.
1055 */
1056 regs[RA] = (int)PS_STRINGS - (esigcode - sigcode);
1057 #ifdef DEBUG
1058 if ((sigdebug & SDB_FOLLOW) ||
1059 (sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
1060 printf("sendsig(%d): sig %d returns\n",
1061 p->p_pid, sig);
1062 #endif
1063 }
1064
1065 /*
1066 * System call to cleanup state after a signal
1067 * has been taken. Reset signal mask and
1068 * stack state from context left by sendsig (above).
1069 * Return to previous pc and psl as specified by
1070 * context left by sendsig. Check carefully to
1071 * make sure that the user has not modified the
1072 * psl to gain improper priviledges or to cause
1073 * a machine fault.
1074 */
1075 /* ARGSUSED */
1076 sigreturn(p, uap, retval)
1077 struct proc *p;
1078 struct sigreturn_args /* {
1079 syscallarg(struct sigcontext *) sigcntxp;
1080 } */ *uap;
1081 register_t *retval;
1082 {
1083 register struct sigcontext *scp;
1084 register int *regs;
1085 struct sigcontext ksc;
1086 int error;
1087
1088 scp = SCARG(uap, sigcntxp);
1089 #ifdef DEBUG
1090 if (sigdebug & SDB_FOLLOW)
1091 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
1092 #endif
1093 regs = p->p_md.md_regs;
1094 /*
1095 * Test and fetch the context structure.
1096 * We grab it all at once for speed.
1097 */
1098 error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
1099 if (error || ksc.sc_regs[ZERO] != 0xACEDBADE) {
1100 #ifdef DEBUG
1101 if (!(sigdebug & SDB_FOLLOW))
1102 printf("sigreturn: pid %d, scp %x\n", p->p_pid, scp);
1103 printf(" old sp %x ra %x pc %x\n",
1104 regs[SP], regs[RA], regs[PC]);
1105 printf(" new sp %x ra %x pc %x err %d z %x\n",
1106 ksc.sc_regs[SP], ksc.sc_regs[RA], ksc.sc_regs[PC],
1107 error, ksc.sc_regs[ZERO]);
1108 #endif
1109 return (EINVAL);
1110 }
1111 scp = &ksc;
1112 /*
1113 * Restore the user supplied information
1114 */
1115 if (scp->sc_onstack & 01)
1116 p->p_sigacts->ps_sigstk.ss_flags |= SA_ONSTACK;
1117 else
1118 p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
1119 p->p_sigmask = scp->sc_mask &~ sigcantmask;
1120 regs[PC] = scp->sc_pc;
1121 bcopy((caddr_t)&scp->sc_regs[1], (caddr_t)®s[1],
1122 sizeof(scp->sc_regs) - sizeof(int));
1123 if (scp->sc_fpused)
1124 bcopy((caddr_t)scp->sc_fpregs, (caddr_t)&p->p_md.md_regs[F0],
1125 sizeof(scp->sc_fpregs));
1126 return (EJUSTRETURN);
1127 }
1128
1129 int waittime = -1;
1130
boot(howto)1131 boot(howto)
1132 register int howto;
1133 {
1134 struct proc *p = curproc; /* XXX */
1135
1136 /* take a snap shot before clobbering any registers */
1137 if (curproc)
1138 savectx(curproc->p_addr, 0);
1139
1140 #ifdef DEBUG
1141 if (panicstr)
1142 stacktrace();
1143 #endif
1144
1145 boothowto = howto;
1146 if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1147 register struct buf *bp;
1148 int iter, nbusy;
1149
1150 waittime = 0;
1151 (void) spl0();
1152 printf("syncing disks... ");
1153 /*
1154 * Release vnodes held by texts before sync.
1155 */
1156 if (panicstr == 0)
1157 vnode_pager_umount(NULL);
1158 #ifdef notdef
1159 #include "fd.h"
1160 #if NFD > 0
1161 fdshutdown();
1162 #endif
1163 #endif
1164 sync(p, (void *)NULL, (int *)NULL);
1165 /*
1166 * Unmount filesystems
1167 */
1168 if (panicstr == 0)
1169 vfs_unmountall();
1170
1171 for (iter = 0; iter < 20; iter++) {
1172 nbusy = 0;
1173 for (bp = &buf[nbuf]; --bp >= buf; )
1174 if ((bp->b_flags & (B_BUSY|B_INVAL)) == B_BUSY)
1175 nbusy++;
1176 if (nbusy == 0)
1177 break;
1178 printf("%d ", nbusy);
1179 DELAY(40000 * iter);
1180 }
1181 if (nbusy)
1182 printf("giving up\n");
1183 else
1184 printf("done\n");
1185 /*
1186 * If we've been adjusting the clock, the todr
1187 * will be out of synch; adjust it now.
1188 */
1189 resettodr();
1190 }
1191 (void) splhigh(); /* extreme priority */
1192 if (callv != &callvec) {
1193 if (howto & RB_HALT)
1194 (*callv->rex)('h');
1195 else {
1196 if (howto & RB_DUMP)
1197 dumpsys();
1198 (*callv->rex)('b');
1199 }
1200 } else if (howto & RB_HALT) {
1201 volatile void (*f)() = (volatile void (*)())DEC_PROM_REINIT;
1202
1203 (*f)(); /* jump back to prom monitor */
1204 } else {
1205 volatile void (*f)() = (volatile void (*)())DEC_PROM_AUTOBOOT;
1206
1207 if (howto & RB_DUMP)
1208 dumpsys();
1209 (*f)(); /* jump back to prom monitor and do 'auto' cmd */
1210 }
1211 /*NOTREACHED*/
1212 }
1213
1214 int dumpmag = (int)0x8fca0101; /* magic number for savecore */
1215 int dumpsize = 0; /* also for savecore */
1216 long dumplo = 0;
1217
dumpconf()1218 dumpconf()
1219 {
1220 int nblks;
1221
1222 dumpsize = physmem;
1223 if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
1224 nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
1225 if (dumpsize > btoc(dbtob(nblks - dumplo)))
1226 dumpsize = btoc(dbtob(nblks - dumplo));
1227 else if (dumplo == 0)
1228 dumplo = nblks - btodb(ctob(physmem));
1229 }
1230 /*
1231 * Don't dump on the first CLBYTES (why CLBYTES?)
1232 * in case the dump device includes a disk label.
1233 */
1234 if (dumplo < btodb(CLBYTES))
1235 dumplo = btodb(CLBYTES);
1236 }
1237
1238 /*
1239 * Doadump comes here after turning off memory management and
1240 * getting on the dump stack, either when called above, or by
1241 * the auto-restart code.
1242 */
dumpsys()1243 dumpsys()
1244 {
1245 int error;
1246
1247 msgbufmapped = 0;
1248 if (dumpdev == NODEV)
1249 return;
1250 /*
1251 * For dumps during autoconfiguration,
1252 * if dump device has already configured...
1253 */
1254 if (dumpsize == 0)
1255 dumpconf();
1256 if (dumplo < 0)
1257 return;
1258 printf("\ndumping to dev %x, offset %d\n", dumpdev, dumplo);
1259 printf("dump ");
1260 switch (error = (*bdevsw[major(dumpdev)].d_dump)(dumpdev)) {
1261
1262 case ENXIO:
1263 printf("device bad\n");
1264 break;
1265
1266 case EFAULT:
1267 printf("device not ready\n");
1268 break;
1269
1270 case EINVAL:
1271 printf("area improper\n");
1272 break;
1273
1274 case EIO:
1275 printf("i/o error\n");
1276 break;
1277
1278 default:
1279 printf("error %d\n", error);
1280 break;
1281
1282 case 0:
1283 printf("succeeded\n");
1284 }
1285 }
1286
1287 /*
1288 * Return the best possible estimate of the time in the timeval
1289 * to which tvp points. Unfortunately, we can't read the hardware registers.
1290 * We guarantee that the time will be greater than the value obtained by a
1291 * previous call.
1292 */
1293 void
microtime(tvp)1294 microtime(tvp)
1295 struct timeval *tvp;
1296 {
1297 int s = splclock();
1298 static struct timeval lasttime;
1299
1300 *tvp = time;
1301 #ifdef notdef
1302 tvp->tv_usec += clkread();
1303 while (tvp->tv_usec > 1000000) {
1304 tvp->tv_sec++;
1305 tvp->tv_usec -= 1000000;
1306 }
1307 #endif
1308 if (tvp->tv_sec == lasttime.tv_sec &&
1309 tvp->tv_usec <= lasttime.tv_usec &&
1310 (tvp->tv_usec = lasttime.tv_usec + 1) > 1000000) {
1311 tvp->tv_sec++;
1312 tvp->tv_usec -= 1000000;
1313 }
1314 lasttime = *tvp;
1315 splx(s);
1316 }
1317
initcpu()1318 initcpu()
1319 {
1320 register volatile struct chiptime *c;
1321 int i;
1322
1323 /* disable clock interrupts (until startrtclock()) */
1324 c = Mach_clock_addr;
1325 c->regb = REGB_DATA_MODE | REGB_HOURS_FORMAT;
1326 i = c->regc;
1327 spl0(); /* safe to turn interrupts on now */
1328 return (i);
1329 }
1330
1331 /*
1332 * Convert an ASCII string into an integer.
1333 */
1334 int
atoi(s)1335 atoi(s)
1336 char *s;
1337 {
1338 int c;
1339 unsigned base = 10, d;
1340 int neg = 0, val = 0;
1341
1342 if (s == 0 || (c = *s++) == 0)
1343 goto out;
1344
1345 /* skip spaces if any */
1346 while (c == ' ' || c == '\t')
1347 c = *s++;
1348
1349 /* parse sign, allow more than one (compat) */
1350 while (c == '-') {
1351 neg = !neg;
1352 c = *s++;
1353 }
1354
1355 /* parse base specification, if any */
1356 if (c == '0') {
1357 c = *s++;
1358 switch (c) {
1359 case 'X':
1360 case 'x':
1361 base = 16;
1362 break;
1363 case 'B':
1364 case 'b':
1365 base = 2;
1366 break;
1367 default:
1368 base = 8;
1369 }
1370 }
1371
1372 /* parse number proper */
1373 for (;;) {
1374 if (c >= '0' && c <= '9')
1375 d = c - '0';
1376 else if (c >= 'a' && c <= 'z')
1377 d = c - 'a' + 10;
1378 else if (c >= 'A' && c <= 'Z')
1379 d = c - 'A' + 10;
1380 else
1381 break;
1382 val *= base;
1383 val += d;
1384 c = *s++;
1385 }
1386 if (neg)
1387 val = -val;
1388 out:
1389 return val;
1390 }
1391
1392 /*
1393 * Fill in the pmax addresses by hand.
1394 */
1395 static struct pmax_address {
1396 char *pmax_name;
1397 char *pmax_addr;
1398 int pmax_pri;
1399 } pmax_addresses[] = {
1400 { "pm", (char *)MACH_PHYS_TO_CACHED(KN01_PHYS_FBUF_START), 3 },
1401 { "dc", (char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_DZ), 2 },
1402 { "le", (char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_LANCE), 1 },
1403 { "sii",(char *)MACH_PHYS_TO_UNCACHED(KN01_SYS_SII), 0 },
1404 { (char *)0, },
1405 };
1406
1407 void
pmax_slot_hand_fill()1408 pmax_slot_hand_fill()
1409 {
1410 register struct pmax_ctlr *cp;
1411 register struct driver *drp;
1412 register struct pmax_address *pmap;
1413
1414 /*
1415 * Find the device driver entry and fill in the address.
1416 */
1417 for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
1418 for (pmap = pmax_addresses; pmap->pmax_name; pmap++) {
1419 if (strcmp(drp->d_name, pmap->pmax_name))
1420 continue;
1421 if (cp->pmax_addr == (char *)QUES) {
1422 cp->pmax_addr = pmap->pmax_addr;
1423 cp->pmax_pri = pmap->pmax_pri;
1424 continue;
1425 }
1426 }
1427 }
1428 }
1429
1430 #ifdef DS5000
1431 /*
1432 * Mach Operating System
1433 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
1434 * All Rights Reserved.
1435 *
1436 * Permission to use, copy, modify and distribute this software and its
1437 * documentation is hereby granted, provided that both the copyright
1438 * notice and this permission notice appear in all copies of the
1439 * software, derivative works or modified versions, and any portions
1440 * thereof, and that both notices appear in supporting documentation.
1441 *
1442 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
1443 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1444 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1445 *
1446 * Carnegie Mellon requests users of this software to return to
1447 *
1448 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
1449 * School of Computer Science
1450 * Carnegie Mellon University
1451 * Pittsburgh PA 15213-3890
1452 *
1453 * any improvements or extensions that they make and grant Carnegie the
1454 * rights to redistribute these changes.
1455 */
1456
1457
1458 /*
1459 * Driver map: associates a device driver to an option type.
1460 * Drivers name are (arbitrarily) defined in each driver and
1461 * used in the various config tables.
1462 */
1463 struct drivers_map {
1464 char module_name[TC_ROM_LLEN]; /* from ROM, literally! */
1465 char *driver_name; /* in bus_??_init[] tables */
1466 } tc_drivers_map[] = {
1467 { "KN02 ", "dc"}, /* (*) 3max system board (with DC) */
1468 { "PMAD-AA ", "le"}, /* Ether */
1469 { "PMAZ-AA ", "asc"}, /* SCSI */
1470 { "PMAG-AA ", "mfb"}, /* Mono Frame Buffer */
1471 { "PMAG-BA ", "cfb"}, /* Color Frame Buffer */
1472 { "PMAGB-BA", "sfb"}, /* Smart Frame Buffer */
1473 { "PMAG-CA ", "ga"}, /* 2D graphic board */
1474 { "PMAG-DA ", "gq"}, /* 3D graphic board (LM) */
1475 { "PMAG-FA ", "gq"}, /* 3D graphic board (HE) */
1476 { "PMAG-DV ", "xcfb"}, /* (*) maxine Color Frame Buffer */
1477 { "Z8530 ", "scc"}, /* (*) 3min/maxine serial lines */
1478 { "ASIC ", "asic"}, /* (*) 3min/maxine DMA controller */
1479 { "XINE-FDC", "fdc"}, /* (*) maxine floppy controller */
1480 { "DTOP ", "dtop"}, /* (*) maxine desktop bus */
1481 { "AMD79c30", "isdn"}, /* (*) maxine ISDN chip */
1482 { "XINE-FRC", "frc"}, /* (*) maxine free-running counter */
1483 { "PMAF-AA ", "fza"}, /* slow FDDI */
1484 { "T3PKT ", "tt"}, /* DECWRL turbochannel T3 */
1485 { "T1D4PKT ", "ds"}, /* DECWRL turbochannel T1 */
1486 { "FORE_ATM", "fa"}, /* Fore t??-100 ATM */
1487 { "LoFi ", "lofi"}, /* DEC audio board */
1488 { "AV01A-AA", "lofi"}, /* DEC audio board */
1489 { "AV01B-AA", "lofi"}, /* DEC audio board */
1490 { "", 0} /* list end */
1491 };
1492
1493 /*
1494 * Identify an option on the TC. Looks at the mandatory
1495 * info in the option's ROM and checks it.
1496 */
1497 #ifdef DEBUG
1498 int tc_verbose = 0;
1499 #endif
1500
1501 static int
tc_identify_option(addr,slot,complain)1502 tc_identify_option(addr, slot, complain)
1503 tc_rommap_t *addr;
1504 tc_option_t *slot;
1505 int complain;
1506 {
1507 register int i;
1508 unsigned char width;
1509 char firmwr[TC_ROM_LLEN+1], vendor[TC_ROM_LLEN+1],
1510 module[TC_ROM_LLEN+1], host_type[TC_ROM_SLEN+1];
1511
1512 /*
1513 * We do not really use the 'width' info, but take advantage
1514 * of the restriction that the spec impose on the portion
1515 * of the ROM that maps between +0x3e0 and +0x470, which
1516 * is the only piece we need to look at.
1517 */
1518 width = addr->rom_width.value;
1519 switch (width) {
1520 case 1:
1521 case 2:
1522 case 4:
1523 break;
1524
1525 default:
1526 #ifdef DEBUG
1527 if (tc_verbose && complain)
1528 printf("%s (x%x) at x%x\n", "Invalid ROM width",
1529 width, addr);
1530 #endif
1531 return (0);
1532 }
1533
1534 if (addr->rom_stride.value != 4) {
1535 #ifdef DEBUG
1536 if (tc_verbose && complain)
1537 printf("%s (x%x) at x%x\n", "Invalid ROM stride",
1538 addr->rom_stride.value, addr);
1539 #endif
1540 return (0);
1541 }
1542
1543 if ((addr->test_data[0] != 0x55) ||
1544 (addr->test_data[4] != 0x00) ||
1545 (addr->test_data[8] != 0xaa) ||
1546 (addr->test_data[12] != 0xff)) {
1547 #ifdef DEBUG
1548 if (tc_verbose && complain)
1549 printf("%s x%x\n", "Test pattern failed, option at",
1550 addr);
1551 #endif
1552 return (0);
1553 }
1554
1555 for (i = 0; i < TC_ROM_LLEN; i++) {
1556 firmwr[i] = addr->firmware_rev[i].value;
1557 vendor[i] = addr->vendor_name[i].value;
1558 module[i] = addr->module_name[i].value;
1559 if (i >= TC_ROM_SLEN)
1560 continue;
1561 host_type[i] = addr->host_firmware_type[i].value;
1562 }
1563 firmwr[TC_ROM_LLEN] = vendor[TC_ROM_LLEN] =
1564 module[TC_ROM_LLEN] = host_type[TC_ROM_SLEN] = '\0';
1565
1566 #ifdef DEBUG
1567 if (tc_verbose)
1568 printf("%s %s '%s' at 0x%x\n %s %s %s '%s'\n %s %d %s %d %s\n",
1569 "Found a", vendor, module, addr,
1570 "Firmware rev.", firmwr,
1571 "diagnostics for a", host_type,
1572 "ROM size is", addr->rom_size.value << 3,
1573 "Kbytes, uses", addr->slot_size.value, "TC slot(s)");
1574 #endif
1575
1576 bcopy(module, slot->module_name, TC_ROM_LLEN);
1577 bcopy(vendor, slot->module_id, TC_ROM_LLEN);
1578 bcopy(firmwr, &slot->module_id[TC_ROM_LLEN], TC_ROM_LLEN);
1579 slot->slot_size = addr->slot_size.value;
1580 slot->rom_width = width;
1581
1582 return (1);
1583 }
1584
1585 /*
1586 * TURBOchannel autoconf procedure. Finds in one sweep what is
1587 * hanging on the bus and fills in the tc_slot_info array.
1588 * This is only the first part of the autoconf scheme, at this
1589 * time we are basically only looking for a graphics board to
1590 * use as system console (all workstations).
1591 */
1592
1593 void
tc_find_all_options()1594 tc_find_all_options()
1595 {
1596 register int i;
1597 u_long addr;
1598 int found;
1599 register tc_option_t *sl;
1600 struct drivers_map *map;
1601 register struct pmax_ctlr *cp;
1602 register struct driver *drp;
1603
1604 /*
1605 * Take a look at the bus
1606 */
1607 bzero(tc_slot_info, sizeof(tc_slot_info));
1608 for (i = tc_max_slot; i >= tc_min_slot;) {
1609 addr = MACH_PHYS_TO_UNCACHED(tc_slot_phys_base[i]);
1610 found = tc_probe_slot(addr, &tc_slot_info[i]);
1611
1612 if (found) {
1613 /*
1614 * Found a slot, make a note of it
1615 */
1616 tc_slot_info[i].present = 1;
1617 tc_slot_info[i].k1seg_address = addr;
1618 }
1619
1620 i -= tc_slot_info[i].slot_size;
1621 }
1622
1623 /*
1624 * Some slots (e.g. the system slot on 3max) might require
1625 * hand-filling. If so, do it now.
1626 */
1627 if (tc_slot_hand_fill)
1628 (*tc_slot_hand_fill) (tc_slot_info);
1629
1630 /*
1631 * Now for each alive slot see if we have a device driver that
1632 * handles it. This is done in "priority order", meaning that
1633 * always present devices are at higher slot numbers on all
1634 * current TC machines, and option slots are at lowest numbers.
1635 */
1636 for (i = TC_MAX_LOGICAL_SLOTS - 1; i >= 0; i--) {
1637 sl = &tc_slot_info[i];
1638 if (!sl->present)
1639 continue;
1640 found = FALSE;
1641 for (map = tc_drivers_map; map->driver_name; map++) {
1642 if (bcmp(sl->module_name, map->module_name, TC_ROM_LLEN))
1643 continue;
1644 sl->driver_name = map->driver_name;
1645 found = TRUE;
1646 break;
1647 }
1648 if (!found) {
1649 printf("%s %s %s\n",
1650 "Cannot associate a device driver to",
1651 sl->module_name, ". Will (try to) ignore it.");
1652 sl->present = 0;
1653 continue;
1654 }
1655
1656 /*
1657 * Find the device driver entry and fill in the address.
1658 */
1659 for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
1660 if (strcmp(drp->d_name, map->driver_name))
1661 continue;
1662 if (cp->pmax_alive)
1663 continue;
1664 if (cp->pmax_addr == (char *)QUES) {
1665 cp->pmax_addr = (char *)sl->k1seg_address;
1666 cp->pmax_pri = i;
1667 /*
1668 * Only enable interrupts if there is an
1669 * interrupt handler for it. (e.g., PMAG-BA
1670 * can't disable the vertical retrace interrupt
1671 * and we might want to ignore it).
1672 */
1673 if (drp->d_intr)
1674 (*tc_enable_interrupt)(i, 1);
1675 cp->pmax_alive = 1;
1676 break;
1677 }
1678 if (cp->pmax_addr != (char *)sl->k1seg_address) {
1679 cp->pmax_addr = (char *)QUES;
1680 printf("%s: device not at configued address (expected at %x, found at %x)\n",
1681 drp->d_name,
1682 cp->pmax_addr, sl->k1seg_address);
1683 }
1684 }
1685 }
1686 }
1687
1688 /*
1689 * Probe a slot in the TURBOchannel. Return TRUE if a valid option
1690 * is present, FALSE otherwise. A side-effect is to fill the slot
1691 * descriptor with the size of the option, whether it is
1692 * recognized or not.
1693 */
1694 int
tc_probe_slot(addr,slot)1695 tc_probe_slot(addr, slot)
1696 caddr_t addr;
1697 tc_option_t *slot;
1698 {
1699 int i;
1700 static unsigned tc_offset_rom[] = {
1701 TC_OFF_PROTO_ROM, TC_OFF_ROM
1702 };
1703 #define TC_N_OFFSETS sizeof(tc_offset_rom)/sizeof(unsigned)
1704
1705 slot->slot_size = 1;
1706
1707 for (i = 0; i < TC_N_OFFSETS; i++) {
1708 if (badaddr(addr + tc_offset_rom[i], 4))
1709 continue;
1710 /* complain only on last chance */
1711 if (tc_identify_option((tc_rommap_t *)(addr + tc_offset_rom[i]),
1712 slot, i == (TC_N_OFFSETS-1)))
1713 return (1);
1714 }
1715 return (0);
1716 #undef TC_N_OFFSETS
1717 }
1718
1719 /*
1720 * Enable/Disable interrupts for a TURBOchannel slot.
1721 */
1722 void
kn02_enable_intr(slotno,on)1723 kn02_enable_intr(slotno, on)
1724 register int slotno;
1725 int on;
1726 {
1727 register volatile int *p_csr =
1728 (volatile int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
1729 int csr;
1730 int s;
1731
1732 slotno = 1 << (slotno + KN02_CSR_IOINTEN_SHIFT);
1733 s = Mach_spl0();
1734 csr = *p_csr & ~(KN02_CSR_WRESERVED | 0xFF);
1735 if (on)
1736 *p_csr = csr | slotno;
1737 else
1738 *p_csr = csr & ~slotno;
1739 splx(s);
1740 }
1741
1742 /*
1743 * Object:
1744 * kmin_enable_intr EXPORTED function
1745 *
1746 * Enable/Disable interrupts from a TURBOchannel slot.
1747 *
1748 * We pretend we actually have 8 slots even if we really have
1749 * only 4: TCslots 0-2 maps to slots 0-2, TCslot3 maps to
1750 * slots 3-7 (see kmin_slot_hand_fill).
1751 */
1752 void
kmin_enable_intr(slotno,on)1753 kmin_enable_intr(slotno, on)
1754 register unsigned int slotno;
1755 int on;
1756 {
1757 register unsigned mask;
1758
1759 switch (slotno) {
1760 case 0:
1761 case 1:
1762 case 2:
1763 return;
1764 case KMIN_SCSI_SLOT:
1765 mask = (KMIN_INTR_SCSI | KMIN_INTR_SCSI_PTR_LOAD |
1766 KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E);
1767 break;
1768 case KMIN_LANCE_SLOT:
1769 mask = KMIN_INTR_LANCE;
1770 break;
1771 case KMIN_SCC0_SLOT:
1772 mask = KMIN_INTR_SCC_0;
1773 break;
1774 case KMIN_SCC1_SLOT:
1775 mask = KMIN_INTR_SCC_1;
1776 break;
1777 case KMIN_ASIC_SLOT:
1778 mask = KMIN_INTR_ASIC;
1779 break;
1780 default:
1781 return;
1782 }
1783 if (on)
1784 kmin_tc3_imask |= mask;
1785 else
1786 kmin_tc3_imask &= ~mask;
1787 }
1788
1789 /*
1790 * Object:
1791 * xine_enable_intr EXPORTED function
1792 *
1793 * Enable/Disable interrupts from a TURBOchannel slot.
1794 *
1795 * We pretend we actually have 11 slots even if we really have
1796 * only 3: TCslots 0-1 maps to slots 0-1, TCslot 2 is used for
1797 * the system (TCslot3), TCslot3 maps to slots 3-10
1798 * (see xine_slot_hand_fill).
1799 * Note that all these interrupts come in via the IMR.
1800 */
1801 void
xine_enable_intr(slotno,on)1802 xine_enable_intr(slotno, on)
1803 register unsigned int slotno;
1804 int on;
1805 {
1806 register unsigned mask;
1807
1808 switch (slotno) {
1809 case 0: /* a real slot, but */
1810 mask = XINE_INTR_TC_0;
1811 break;
1812 case 1: /* a real slot, but */
1813 mask = XINE_INTR_TC_1;
1814 break;
1815 case XINE_FLOPPY_SLOT:
1816 mask = XINE_INTR_FLOPPY;
1817 break;
1818 case XINE_SCSI_SLOT:
1819 mask = (XINE_INTR_SCSI | XINE_INTR_SCSI_PTR_LOAD |
1820 XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E);
1821 break;
1822 case XINE_LANCE_SLOT:
1823 mask = XINE_INTR_LANCE;
1824 break;
1825 case XINE_SCC0_SLOT:
1826 mask = XINE_INTR_SCC_0;
1827 break;
1828 case XINE_DTOP_SLOT:
1829 mask = XINE_INTR_DTOP_RX;
1830 break;
1831 case XINE_ISDN_SLOT:
1832 mask = XINE_INTR_ISDN;
1833 break;
1834 case XINE_ASIC_SLOT:
1835 mask = XINE_INTR_ASIC;
1836 break;
1837 default:
1838 return;/* ignore */
1839 }
1840 if (on)
1841 xine_tc3_imask |= mask;
1842 else
1843 xine_tc3_imask &= ~mask;
1844 }
1845
1846 #ifdef DS5000_240
1847 /*
1848 * UNTESTED!!
1849 * Object:
1850 * kn03_enable_intr EXPORTED function
1851 *
1852 * Enable/Disable interrupts from a TURBOchannel slot.
1853 *
1854 * We pretend we actually have 8 slots even if we really have
1855 * only 4: TCslots 0-2 maps to slots 0-2, TCslot3 maps to
1856 * slots 3-7 (see kn03_slot_hand_fill).
1857 */
1858 void
kn03_enable_intr(slotno,on)1859 kn03_enable_intr(slotno, on)
1860 register unsigned int slotno;
1861 int on;
1862 {
1863 register unsigned mask;
1864
1865 switch (slotno) {
1866 case 0:
1867 mask = KN03_INTR_TC_0;
1868 break;
1869 case 1:
1870 mask = KN03_INTR_TC_1;
1871 break;
1872 case 2:
1873 mask = KN03_INTR_TC_2;
1874 break;
1875 case KN03_SCSI_SLOT:
1876 mask = (KN03_INTR_SCSI | KN03_INTR_SCSI_PTR_LOAD |
1877 KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E);
1878 break;
1879 case KN03_LANCE_SLOT:
1880 mask = KN03_INTR_LANCE;
1881 break;
1882 case KN03_SCC0_SLOT:
1883 mask = KN03_INTR_SCC_0;
1884 break;
1885 case KN03_SCC1_SLOT:
1886 mask = KN03_INTR_SCC_1;
1887 break;
1888 case KN03_ASIC_SLOT:
1889 mask = KN03_INTR_ASIC;
1890 break;
1891 default:
1892 return;
1893 }
1894 if (on)
1895 kn03_tc3_imask |= mask;
1896 else
1897 kn03_tc3_imask &= ~mask;
1898 }
1899 #endif /* DS5000_240 */
1900
1901 /*
1902 * Object:
1903 * kn02_slot_hand_fill EXPORTED function
1904 *
1905 * Fill in by hand the info for TC slots that are non-standard.
1906 * This is basically just the system slot on a 3max, it does not
1907 * look to me like it follows the TC rules although some of the
1908 * required info is indeed there.
1909 *
1910 */
1911 void
kn02_slot_hand_fill(slot)1912 kn02_slot_hand_fill(slot)
1913 tc_option_t *slot;
1914 {
1915 slot[7].present = 1;
1916 slot[7].slot_size = 1;
1917 slot[7].rom_width = 1;
1918 #if unsafe
1919 bcopy(0xbffc0410, slot[7].module_name, TC_ROM_LLEN+1);
1920 #endif
1921 bcopy("KN02 ", slot[7].module_name, TC_ROM_LLEN+1);
1922 bcopy("DEC xxxx", slot[7].module_id, TC_ROM_LLEN+1);
1923 slot[7].k1seg_address = MACH_PHYS_TO_UNCACHED(KN02_SYS_DZ);
1924 }
1925
1926 /*
1927 * Object:
1928 * kmin_slot_hand_fill EXPORTED function
1929 *
1930 * Fill in by hand the info for TC slots that are non-standard.
1931 * This is the system slot on a 3min, which we think of as a
1932 * set of non-regular size TC slots.
1933 *
1934 */
1935 void
kmin_slot_hand_fill(slot)1936 kmin_slot_hand_fill(slot)
1937 tc_option_t *slot;
1938 {
1939 register int i;
1940
1941 for (i = KMIN_SCSI_SLOT; i < KMIN_ASIC_SLOT+1; i++) {
1942 slot[i].present = 1;
1943 slot[i].slot_size = 1;
1944 slot[i].rom_width = 1;
1945 slot[i].unit = 0;
1946 bcopy("DEC KMIN", slot[i].module_id, TC_ROM_LLEN+1);
1947 }
1948
1949 /* scsi */
1950 bcopy("PMAZ-AA ", slot[KMIN_SCSI_SLOT].module_name, TC_ROM_LLEN+1);
1951 slot[KMIN_SCSI_SLOT].k1seg_address =
1952 MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCSI);
1953
1954 /* lance */
1955 bcopy("PMAD-AA ", slot[KMIN_LANCE_SLOT].module_name, TC_ROM_LLEN+1);
1956 slot[KMIN_LANCE_SLOT].k1seg_address = 0;
1957
1958 /* scc */
1959 bcopy("Z8530 ", slot[KMIN_SCC0_SLOT].module_name, TC_ROM_LLEN+1);
1960 slot[KMIN_SCC0_SLOT].k1seg_address =
1961 MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_0);
1962
1963 slot[KMIN_SCC1_SLOT].unit = 1;
1964 bcopy("Z8530 ", slot[KMIN_SCC1_SLOT].module_name, TC_ROM_LLEN+1);
1965 slot[KMIN_SCC1_SLOT].k1seg_address =
1966 MACH_PHYS_TO_UNCACHED(KMIN_SYS_SCC_1);
1967
1968 /* asic */
1969 bcopy("ASIC ", slot[KMIN_ASIC_SLOT].module_name, TC_ROM_LLEN+1);
1970 slot[KMIN_ASIC_SLOT].k1seg_address =
1971 MACH_PHYS_TO_UNCACHED(KMIN_SYS_ASIC);
1972 asic_init(0);
1973 }
1974
1975 /*
1976 * Object:
1977 * xine_slot_hand_fill EXPORTED function
1978 *
1979 * Fill in by hand the info for TC slots that are non-standard.
1980 * This is the system slot on a 3min, which we think of as a
1981 * set of non-regular size TC slots.
1982 *
1983 */
1984 void
xine_slot_hand_fill(slot)1985 xine_slot_hand_fill(slot)
1986 tc_option_t *slot;
1987 {
1988 register int i;
1989
1990 for (i = XINE_FLOPPY_SLOT; i < XINE_FRC_SLOT+1; i++) {
1991 slot[i].present = 1;
1992 slot[i].slot_size = 1;
1993 slot[i].rom_width = 1;
1994 slot[i].unit = 0;
1995 bcopy("DEC XINE", slot[i].module_id, TC_ROM_LLEN+1);
1996 }
1997
1998 /* floppy */
1999 bcopy("XINE-FDC", slot[XINE_FLOPPY_SLOT].module_name, TC_ROM_LLEN+1);
2000 slot[XINE_FLOPPY_SLOT].k1seg_address =
2001 MACH_PHYS_TO_UNCACHED(XINE_SYS_FLOPPY);
2002
2003 /* scsi */
2004 bcopy("PMAZ-AA ", slot[XINE_SCSI_SLOT].module_name, TC_ROM_LLEN+1);
2005 slot[XINE_SCSI_SLOT].k1seg_address =
2006 MACH_PHYS_TO_UNCACHED(XINE_SYS_SCSI);
2007
2008 /* lance */
2009 bcopy("PMAD-AA ", slot[XINE_LANCE_SLOT].module_name, TC_ROM_LLEN+1);
2010 slot[XINE_LANCE_SLOT].k1seg_address =
2011 MACH_PHYS_TO_UNCACHED(XINE_SYS_LANCE);
2012
2013 /* scc */
2014 bcopy("Z8530 ", slot[XINE_SCC0_SLOT].module_name, TC_ROM_LLEN+1);
2015 slot[XINE_SCC0_SLOT].k1seg_address =
2016 MACH_PHYS_TO_UNCACHED(XINE_SYS_SCC_0);
2017
2018 /* Desktop */
2019 bcopy("DTOP ", slot[XINE_DTOP_SLOT].module_name, TC_ROM_LLEN+1);
2020 slot[XINE_DTOP_SLOT].k1seg_address =
2021 MACH_PHYS_TO_UNCACHED(XINE_SYS_DTOP+0x20000); /* why? */
2022
2023 /* ISDN */
2024 bcopy("AMD79c30", slot[XINE_ISDN_SLOT].module_name, TC_ROM_LLEN+1);
2025 slot[XINE_ISDN_SLOT].k1seg_address =
2026 MACH_PHYS_TO_UNCACHED(XINE_SYS_ISDN);
2027
2028 /* Video */
2029 bcopy("PMAG-DV ", slot[XINE_CFB_SLOT].module_name, TC_ROM_LLEN+1);
2030 slot[XINE_CFB_SLOT].k1seg_address =
2031 MACH_PHYS_TO_CACHED(XINE_PHYS_CFB_START);
2032
2033 /* asic */
2034 bcopy("ASIC ", slot[XINE_ASIC_SLOT].module_name, TC_ROM_LLEN+1);
2035 slot[XINE_ASIC_SLOT].k1seg_address =
2036 MACH_PHYS_TO_UNCACHED(XINE_SYS_ASIC);
2037
2038 /* free-running counter (high resolution mapped time) */
2039 bcopy("XINE-FRC", slot[XINE_FRC_SLOT].module_name, TC_ROM_LLEN+1);
2040 slot[XINE_FRC_SLOT].k1seg_address =
2041 MACH_PHYS_TO_UNCACHED(XINE_REG_FCTR);
2042 asic_init(1);
2043 }
2044
2045 #ifdef DS5000_240
2046 /*
2047 * UNTESTED!!
2048 * Object:
2049 * kn03_slot_hand_fill EXPORTED function
2050 *
2051 * Fill in by hand the info for TC slots that are non-standard.
2052 * This is the system slot on a 3max+, which we think of as a
2053 * set of non-regular size TC slots.
2054 *
2055 */
2056 void
kn03_slot_hand_fill(slot)2057 kn03_slot_hand_fill(slot)
2058 tc_option_t *slot;
2059 {
2060 register int i;
2061
2062 for (i = KN03_SCSI_SLOT; i < KN03_ASIC_SLOT+1; i++) {
2063 slot[i].present = 1;
2064 slot[i].slot_size = 1;
2065 slot[i].rom_width = 1;
2066 slot[i].unit = 0;
2067 bcopy("DEC KN03", slot[i].module_id, TC_ROM_LLEN+1);
2068 }
2069
2070 /* scsi */
2071 bcopy("PMAZ-AA ", slot[KN03_SCSI_SLOT].module_name, TC_ROM_LLEN+1);
2072 slot[KN03_SCSI_SLOT].k1seg_address =
2073 MACH_PHYS_TO_UNCACHED(KN03_SYS_SCSI);
2074
2075 /* lance */
2076 bcopy("PMAD-AA ", slot[KN03_LANCE_SLOT].module_name, TC_ROM_LLEN+1);
2077 slot[KN03_LANCE_SLOT].k1seg_address = 0;
2078
2079 /* scc */
2080 bcopy("Z8530 ", slot[KN03_SCC0_SLOT].module_name, TC_ROM_LLEN+1);
2081 slot[KN03_SCC0_SLOT].k1seg_address =
2082 MACH_PHYS_TO_UNCACHED(KN03_SYS_SCC_0);
2083
2084 slot[KN03_SCC1_SLOT].unit = 1;
2085 bcopy("Z8530 ", slot[KN03_SCC1_SLOT].module_name, TC_ROM_LLEN+1);
2086 slot[KN03_SCC1_SLOT].k1seg_address =
2087 MACH_PHYS_TO_UNCACHED(KN03_SYS_SCC_1);
2088
2089 /* asic */
2090 bcopy("ASIC ", slot[KN03_ASIC_SLOT].module_name, TC_ROM_LLEN+1);
2091 slot[KN03_ASIC_SLOT].k1seg_address =
2092 MACH_PHYS_TO_UNCACHED(KN03_SYS_ASIC);
2093 asic_init(0);
2094 }
2095 #endif /* DS5000_240 */
2096
2097 /*
2098 * Initialize the I/O asic
2099 */
2100 static void
asic_init(isa_maxine)2101 asic_init(isa_maxine)
2102 int isa_maxine;
2103 {
2104 volatile u_int *decoder;
2105
2106 /* These are common between 3min and maxine */
2107 decoder = (volatile u_int *)ASIC_REG_LANCE_DECODE(asic_base);
2108 *decoder = KMIN_LANCE_CONFIG;
2109 }
2110 #endif /* DS5000 */
2111