console.c revision 8010:71d56cc8c657
1
2
3/* ******************************************
4 * SimOS SRM  Console
5 *
6 * Derived from Lance Berc's SRM console
7 * for the SRC XXM�Machine
8 * ******************************************/
9
10
11typedef unsigned long long uint64_t;
12typedef unsigned long long uint64;
13typedef unsigned int uint32_t;
14typedef unsigned int uint32;
15
16#define CONSOLE
17#include "alpha_access.h"
18
19#if 0
20#include "new_aouthdr.h"
21#include "srcmax.h"
22#endif
23
24/* from ../h */
25#include "lib.h"
26#include "rpb.h"
27#include "cserve.h"
28
29#define CONS_INT_TX   0x01  /* interrupt enable / state bits */
30#define CONS_INT_RX   0x02
31
32#define KSEG   0xfffffc0000000000
33#define K1BASE 0xfffffc8000000000
34#define KSEG_TO_PHYS(x)(((ul)x) & ~KSEG)
35
36#ifdef TSUNAMI
37#define ALPHA_ACCESS_BASE 0xfffffd0200000000
38#elif TLASER
39#define ALPHA_ACCESS_BASE 0xfffffc8000a00000
40#else
41#error TSUNAMI/TLASER not defined.
42#endif
43
44#define PHYS_TO_K1(_x) (K1BASE|(_x))
45
46#define AOUT_LOAD_ADDR (KSEG|0xf000)
47
48#define ROUNDUP8(x) ((ul)(((ul)x)+7) & ~7)
49#define ROUNDUP128(x) ((ul)(((ul)x)+127) & ~127)
50#define ROUNDUP8K(x) ((ul)(((ul)(x))+8191) & ~8191)
51
52#define FIRST(x)  ((((ul)(x)) >> 33) & 0x3ff)
53#define SECOND(x) ((((ul)(x)) >> 23) & 0x3ff)
54#define THIRD(x) ((((ul)(x)) >> 13) & 0x3ff)
55#define THIRD_XXX(x)  ((((ul)(x)) >> 13) & 0xfff)
56#define PFN(x)  ((((ul)(x) & ~KSEG) >> 13))
57
58/* Kernel write | kernel read | valid */
59#define KPTE(x) ((ul)((((ul)(x)) << 32) | 0x1101))
60
61#define HWRPB_PAGES 16
62#define MDT_BITMAP_PAGES  4
63
64#define CSERVE_K_JTOKERN       0x18
65
66#define NUM_KERNEL_THIRD (4)
67
68#define printf_lock(args...)  \
69    do { \
70    SpinLock(&theLock); \
71    printf(args); \
72    SpinUnlock(&theLock); \
73    } while (0)
74
75
76static unixBoot(int go, int argc, char **argv);
77void jToPal(ul bootadr);
78void SlaveLoop(int cpu);
79
80
81struct AlphaAccess simosConf;
82
83/* **************************************************************
84 * Console callbacks use VMS calling conventions
85 * read AXP manual, 2-64.
86 * ***************************************************************/
87typedef struct OpenVMSFunc {
88   long dummy;
89   long func;
90}OpenVMSFunc;
91
92OpenVMSFunc callbackFunc, fixupFunc;
93
94
95
96
97ul theLock;
98
99
100extern void SpinLock(ul *lock);
101#define SpinUnlock(_x) *(_x) = 0;
102
103struct _kernel_params {
104   char *bootadr;
105   ul rpb_percpu;
106   ul free_pfn;
107   ul argc;
108   ul argv;
109   ul envp; /* NULL */
110};
111
112
113extern consoleCallback[];
114extern consoleFixup[];
115long CallBackDispatcher();
116long CallBackFixup();
117
118/*
119 * simos console output
120 */
121
122void InitConsole(void)
123{
124#if 0
125   CDR->intr_status =(DevRegister)(DEV_CNSLE_RX_INTR |DEV_CNSLE_TX_INTR);
126#endif
127}
128
129char GetChar()
130{
131   struct AlphaAccess *k1Conf = (struct AlphaAccess *)(ALPHA_ACCESS_BASE);
132   return k1Conf->inputChar;
133}
134
135void PutChar(char c)
136{
137#if 0
138   CDR->data = c;
139#endif
140#if 0
141   *(int*) PHYS_TO_K1(SLOT_D_COM1<<5) = c;
142#endif
143   struct AlphaAccess *k1Conf = (struct AlphaAccess *)(ALPHA_ACCESS_BASE);
144   k1Conf->outputChar = c;
145
146}
147
148
149int
150passArgs(int argc)
151{ return 0; }
152
153int
154main(int argc, char **argv)
155{
156   int x,i;
157   struct AlphaAccess *k1Conf = (struct AlphaAccess *)(ALPHA_ACCESS_BASE);
158   ui *k1ptr,*ksegptr;
159
160
161   InitConsole();
162   printf_lock("M5 console\n");
163   /*
164    * get configuration from backdoor
165    */
166   simosConf.last_offset = k1Conf->last_offset;
167   printf_lock("Got Configuration %d \n",simosConf.last_offset);
168
169    simosConf.last_offset = k1Conf->last_offset;
170    simosConf.version = k1Conf->version;
171    simosConf.numCPUs = k1Conf->numCPUs;
172    simosConf.intrClockFrequency = k1Conf->intrClockFrequency;
173    simosConf.cpuClock = k1Conf->cpuClock;
174    simosConf.mem_size = k1Conf->mem_size;
175    simosConf.kernStart = k1Conf->kernStart;
176    simosConf.kernEnd = k1Conf->kernEnd;
177    simosConf.entryPoint = k1Conf->entryPoint;
178    simosConf.diskUnit = k1Conf->diskUnit;
179    simosConf.diskCount = k1Conf->diskCount;
180    simosConf.diskPAddr = k1Conf->diskPAddr;
181    simosConf.diskBlock = k1Conf->diskBlock;
182    simosConf.diskOperation = k1Conf->diskOperation;
183    simosConf.outputChar = k1Conf->outputChar;
184    simosConf.inputChar = k1Conf->inputChar;
185    simosConf.bootStrapImpure = k1Conf->bootStrapImpure;
186    simosConf.bootStrapCPU = k1Conf->bootStrapCPU;
187
188   if (simosConf.version != ALPHA_ACCESS_VERSION)  {
189      panic("Console version mismatch. Console expects %d. has %d \n",
190            ALPHA_ACCESS_VERSION,simosConf.version);
191   }
192
193
194   /*
195    * setup arguments to kernel
196    */
197   unixBoot(1,argc,argv);
198
199   x = *(volatile int *)(K1BASE-4);
200   while(1) continue;
201   return x;
202}
203
204/*
205 * BOOTING
206 */
207struct rpb xxm_rpb = {
208   NULL,		/* 000: physical self-reference */
209   ((long)'H') | (((long)'W') << 8) | (((long)'R') << 16) |
210   ((long)'P' << 24) | (((long)'B') << 32),  /* 008: contains string "HWRPB" */
211   6,			/* 010: HWRPB version number */
212   /* the byte count is wrong, but who needs it? - lance */
213   0,			/* 018: bytes in RPB perCPU CTB CRB MEDSC */
214   0,			/* 020: primary cpu id */
215   8192,		/* 028: page size in bytes */
216   43,		/* 030: number of phys addr bits */
217   127,		/* 038: max valid ASN */
218   {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1'},	/* 040: system serial num: 10 ascii chars */
219#ifdef undef
220/* To be legitimate, the following system type and variation are correct for the XXM.
221   But there are too many #ifdefs etc to deal with in Unix, so we tell the kernel
222   that we're an Avanti, which is similar enough.
223   */
224   31,		/* 050: system type - XXM is now in the Alpha SRM */
225   (1 << 10) | (2<<1),/* 058: system variation - XXM w/EV5 & embeded console */
226#endif
227#if 0
228   0x12,		/* 050: system type - masquarade as some random 21064 */
229#endif
230   0, /* OVERRIDDEN */
231   (1<<10),		/* 058: system variation OVERRIDDEN */
232   'c'|('o'<<8)|('o'<<16)|('l'<< 24),		/* 060: system revision */
233   1024*4096,		/* 068: scaled interval clock intr freq  OVERRIDEN*/
234   0,			/* 070: cycle counter frequency */
235   0x200000000,	/* 078: virtual page table base */
236   0,			/* 080: reserved */
237   0,			/* 088: offset to translation buffer hint */
238   1,			/* 090: number of processor slots OVERRIDDEN*/
239   sizeof(struct rpb_percpu),	/* 098: per-cpu slot size. OVERRIDDEN */
240   0,			/* 0A0: offset to per_cpu slots */
241   1,			/* 0A8: number of CTBs */
242#ifdef bugnion_gone
243   sizeof(struct rpb_ctb),	/* 0B0: bytes in largest CTB */
244#else
245   sizeof(struct ctb_tt),
246#endif
247   0,			/* 0B8: offset to CTB (cons term block) */
248   0,			/* 0C0: offset to CRB (cons routine block) */
249   0,			/* 0C8: offset to memory descriptor table */
250   0,			/* 0D0: offset to config data block */
251   0,			/* 0D8: offset to FRU table */
252   0,			/* 0E0: virt addr of save term routine */
253   0,			/* 0E8: proc value for save term routine */
254   0,			/* 0F0: virt addr of restore term routine */
255   0,			/* 0F8: proc value for restore term routine */
256   0,			/* 100: virt addr of CPU restart routine */
257   0,			/* 108: proc value for CPU restart routine */
258   0,			/* 110: used to determine presence of kdebug */
259   0,			/* 118: reserved for hardware */
260/* the checksum is wrong, but who needs it? - lance */
261   0,			/* 120: checksum of prior entries in rpb */
262   0,			/* 128: receive ready bitmask */
263   0,			/* 130: transmit ready bitmask */
264   0,			/* 138: Dynamic System Recog. offset */
265};
266
267ul xxm_tbb[] = { 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e,
268                 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e};
269
270struct rpb_percpu xxm_rpb_percpu = {
271   {0,0,0,0,0,0,1,{0,0},{0,0,0,0,0,0,0,0}},				/* 000: boot/restart HWPCB */
272   (STATE_PA | STATE_PP | STATE_CV | STATE_PV | STATE_PMV | STATE_PL), 	/* 080: per-cpu state bits */
273   0xc000,				/* 088: palcode memory length */
274   0x2000,				/* 090: palcode scratch length */
275   0x4000,				/* 098: phys addr of palcode mem space */
276   0x2000,				/* 0A0: phys addr of palcode scratch space */
277   (2 << 16) | (5 << 8) | 1,		/* 0A8: PALcode rev required */
278   11 | (2L  << 32),				/* 0B0: processor type */
279   7,					/* 0B8: processor variation */
280   'M'|('5'<<8)|('A'<<16)|('0'<<24),	/* 0C0: processor revision */
281   {'M','5','/','A','l','p','h','a','0','0','0','0','0','0','0','0'},	/* 0C8: proc serial num: 10 ascii chars */
282   0,					/* 0D8: phys addr of logout area */
283   0,					/* 0E0: length in bytes of logout area */
284   0,					/* 0E8: halt pcb base */
285   0,					/* 0F0: halt pc */
286   0,					/* 0F8: halt ps */
287   0,					/* 100: halt arg list (R25) */
288   0,					/* 108: halt return address (R26) */
289   0,					/* 110: halt procedure value (R27) */
290   0,		       			/* 118: reason for halt */
291   0,		       			/* 120: for software */
292   {0},				/* 128: inter-console communications buffer */
293   {1,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0},	/* 1D0: PALcode revs available */
294   0					/* 250: reserved for arch use */
295/* the dump stack grows from the end of the rpb page not to reach here */
296};
297
298struct _xxm_rpb_mdt {
299   long   rpb_checksum;	/* 000: checksum of entire mem desc table */
300   long   rpb_impaddr;		/* 008: PA of implementation dep info */
301   long   rpb_numcl;		/* 010: number of clusters */
302   struct rpb_cluster rpb_cluster[3];	/* first instance of a cluster */
303};
304
305struct _xxm_rpb_mdt xxm_rpb_mdt = {
306   0,		/* 000: checksum of entire mem desc table */
307   0,		/* 008: PA of implementation dep info */
308   0,		/* 010: number of clusters */
309   {{	0,		/* 000: starting PFN of this cluster */
310        0,		/* 008: count of PFNs in this cluster */
311        0,		/* 010: count of tested PFNs in cluster */
312        0,		/* 018: va of bitmap */
313        0,		/* 020: pa of bitmap */
314        0,		/* 028: checksum of bitmap */
315        1		/* 030: usage of cluster */
316   },
317    {   0,		/* 000: starting PFN of this cluster */
318        0,		/* 008: count of PFNs in this cluster */
319        0,		/* 010: count of tested PFNs in cluster */
320        0,		/* 018: va of bitmap */
321        0,		/* 020: pa of bitmap */
322        0,		/* 028: checksum of bitmap */
323        0		/* 030: usage of cluster */
324    },
325    {   0,		/* 000: starting PFN of this cluster */
326        0,		/* 008: count of PFNs in this cluster */
327        0,		/* 010: count of tested PFNs in cluster */
328        0,		/* 018: va of bitmap */
329        0,		/* 020: pa of bitmap */
330        0,		/* 028: checksum of bitmap */
331        0		/* 030: usage of cluster */
332    }}
333};
334
335/* constants for slotinfo bus_type subfield */
336#define SLOTINFO_TC	0
337#define SLOTINFO_ISA	1
338#define SLOTINFO_EISA	2
339#define SLOTINFO_PCI	3
340
341struct rpb_ctb xxm_rpb_ctb = {
342   CONS_DZ,	/* 000: console type */
343   0,		/* 008: console unit */
344   0,		/* 010: reserved */
345   0		/* 018: byte length of device dep portion */
346};
347
348/* we don't do any fixup (aka relocate the console) - we hope */
349struct rpb_crb xxm_rpb_crb = {
350   0,		/* va of call-back dispatch rtn */
351   0,		/* pa of call-back dispatch rtn */
352   0,		/* va of call-back fixup rtn */
353   0,		/* pa of call-back fixup rtn */
354   0,		/* number of entries in phys/virt map */
355   0		/* Number of pages to be mapped */
356};
357
358struct _rpb_name {
359   unsigned long length;
360   char name[16];
361};
362
363extern struct _rpb_name xxm_name;
364
365struct rpb_dsr xxm_rpb_dsr = {
366   0,
367   0,
368   0,
369};
370
371struct _rpb_name xxm_name = {
372   16,
373   {'D','E','C',' ','S','R','C',' ','X','X','M',' ','D','G','C',0},
374};
375
376/* XXM has one LURT entry - 1050 is for workstations, 1100 is servers (and is needed for CXX) */
377long xxm_lurt[10] = { 9, 12, -1, -1, -1, -1, -1, -1, 1100, 1100 };
378
379ul unix_boot_mem;
380unsigned long bootadr;
381#if 0
382unsigned long  aout_bss_addr, aout_bss_size, aout_entry, aout_text_start, aout_data_addr;
383#endif
384char **kargv;
385int kargc;
386ul free_pfn;
387struct rpb_percpu *rpb_percpu;
388
389
390#define MAX_CPUS 32
391
392ul bootStrapImpure[MAX_CPUS];
393
394
395char *unix_boot_alloc(int pages)
396{
397   char *ret = (char *) unix_boot_mem;
398   unix_boot_mem += (pages * 8192);
399   return ret;
400}
401
402ul *first = 0;
403ul *third_rpb = 0;
404ul *reservedFixup = 0;
405
406int strcpy(char *dst, char *src);
407
408struct rpb *rpb;
409
410unixBoot(int go, int argc, char **argv)
411{
412   ul *second,  *third_kernel, ptr, *tbb, size, *percpu_logout;
413   unsigned char *mdt_bitmap;
414   long *lp1, *lp2, sum;
415   int i, cl;
416   int kern_first_page;
417   int mem_size = simosConf.mem_size;
418
419   int mem_pages = mem_size / 8192, cons_pages;
420   ul kernel_bytes, ksp, kernel_end, *unix_kernel_stack, bss, ksp_bottom, ksp_top;
421   struct rpb_ctb *rpb_ctb;
422   struct ctb_tt *ctb_tt;
423   struct rpb_dsr *rpb_dsr;
424   struct rpb_crb *rpb_crb;
425   struct _xxm_rpb_mdt *rpb_mdt;
426   int *rpb_lurt;
427   char *rpb_name;
428   ul nextPtr;
429
430   printf_lock( "memsize %x pages %x \n",mem_size,mem_pages);
431
432
433
434#ifdef notnow
435   if (unixArgs()) return;
436#endif
437
438   /* Allocate:
439    *   two pages for the HWRPB
440    *   five page table pages:
441    *     1: First level page table
442    *     1: Second level page table
443    *     1: Third level page table for HWRPB
444    *     2: Third level page table for kernel (for up to 16MB)
445    * set up the page tables
446    * load the kernel at the physical address 0x230000
447    * build the HWRPB
448    *   set up memory descriptor table to give up the
449    *   physical memory between the end of the page
450    *   tables and the start of the kernel
451    * enable kseg addressing
452    * jump to the kernel
453    */
454
455   unix_boot_mem = ROUNDUP8K(&_end);
456
457   printf_lock("First free page after ROM 0x%x\n", unix_boot_mem);
458
459   rpb = (struct rpb *) unix_boot_alloc( HWRPB_PAGES);
460
461   mdt_bitmap =  (unsigned char *) unix_boot_alloc(MDT_BITMAP_PAGES);
462   first = (ul *)unix_boot_alloc(1);
463   second = (ul *)unix_boot_alloc(1);
464   third_rpb = (ul *)unix_boot_alloc(1);
465   reservedFixup = (ul*) unix_boot_alloc(1);
466   third_kernel = (ul *)unix_boot_alloc(NUM_KERNEL_THIRD);
467   percpu_logout = (ul*)unix_boot_alloc(1);
468
469
470   cons_pages = KSEG_TO_PHYS(unix_boot_mem) / 8192;
471
472   /* Set up the page tables */
473   bzero((char *)first, 8192);
474   bzero((char *)second, 8192);
475   bzero((char *)reservedFixup,8192);
476   bzero((char *)third_rpb, HWRPB_PAGES * 8192);
477   bzero((char *)third_kernel, 8192 * NUM_KERNEL_THIRD);
478
479   first[0] = KPTE(PFN(second));
480   first[1] = KPTE(PFN(first)); /* Region 3 */
481
482   second[SECOND(0x10000000)] = KPTE(PFN(third_rpb));	/* Region 0 */
483
484   for (i=0;i<NUM_KERNEL_THIRD;i++) {
485      second[SECOND(0x20000000)+i] = KPTE(PFN(third_kernel)+i);	/* Region 1 */
486   }
487   second[SECOND(0x40000000)] = KPTE(PFN(second));	/* Region 2 */
488
489
490   {
491
492      /* For some obscure reason, Dec Unix's database read
493       * from /etc/sysconfigtab is written to this fixed
494       * mapped memory location. Go figure, since it is
495       * not initialized by the console. Maybe it is
496       * to look at the database from the console
497       * after a boot/crash.
498       *
499       * Black magic to estimate the max size. SEGVs on overflow
500       * bugnion
501       */
502
503#define DATABASE_BASE           0x20000000
504#ifdef not_not
505#define DATABASE_END            0x20230000 /* don't need all that */
506#endif
507
508#define DATABASE_END            0x20020000
509
510      int i;
511      ul *dbPage = (ul*)unix_boot_alloc(1);
512      second[SECOND(DATABASE_BASE)] = KPTE(PFN(dbPage));
513      for (i=DATABASE_BASE; i <DATABASE_END ; i+= 8096) {
514         ul *db = (ul*)unix_boot_alloc(1);
515         dbPage[THIRD(i)] = KPTE(PFN(db));
516      }
517   }
518
519   /* Region 0 */
520   /* Map the HWRPB */
521   for (i = 0; i < HWRPB_PAGES; i++) third_rpb[i] = KPTE(PFN(rpb) + i);
522
523   /* Map the MDT bitmap table */
524   for (i=0;i<MDT_BITMAP_PAGES;i++) {
525      third_rpb[HWRPB_PAGES+i] = KPTE(PFN(mdt_bitmap)+i);
526   }
527
528   /* Protect the PAL pages */
529   for (i = 1; i < PFN(first); i++) third_rpb[HWRPB_PAGES + MDT_BITMAP_PAGES + i] = KPTE(i);
530
531   /* Set up third_kernel after it's loaded, when we know where it is */
532
533#ifdef original__xxm
534   if (unixLoadKernel(AOUT_LOAD_ADDR, argv[1]) == -1) return;
535   aoutfixup(AOUT_LOAD_ADDR);
536#else
537   /* aoutfixup(simosConf.kernelFileHdr); */
538#endif
539#if 0
540   bss = aout_bss_addr;
541
542   kern_first_page = (KSEG_TO_PHYS(aout_text_start) / 8192);
543   kernel_end = ksp_top = ROUNDUP8K(aout_bss_addr + aout_bss_size);
544   bootadr = aout_entry;
545#endif
546
547   kern_first_page = (KSEG_TO_PHYS(simosConf.kernStart)/8192);
548   kernel_end = ksp_top = ROUNDUP8K(simosConf.kernEnd);
549   bootadr = simosConf.entryPoint;
550
551
552   printf_lock("HWRPB 0x%x l1pt 0x%x l2pt 0x%x l3pt_rpb 0x%x l3pt_kernel 0x%x l2reserv 0x%x\n",
553          rpb, first, second, third_rpb, third_kernel,reservedFixup);
554   if (kernel_end - simosConf.kernStart > (0x800000*NUM_KERNEL_THIRD)) {
555      printf_lock("Kernel is more than 8MB 0x%x - 0x%x = 0x%x\n",
556             kernel_end, simosConf.kernStart,
557             kernel_end -simosConf.kernStart );
558      panic("kernel too big\n");
559
560   }
561   /* Map the kernel's pages into the third level of region 2 */
562
563   for (ptr = simosConf.kernStart; ptr < kernel_end; ptr += 8192) {
564
565      third_kernel[THIRD_XXX(ptr)] = KPTE(PFN(ptr));
566   }
567   /* blow 2 pages of phys mem for guards since it maintains 1-to-1 mapping */
568   ksp = ksp_top + (3 * 8192);
569   if (ksp - simosConf.kernStart > (0x800000*NUM_KERNEL_THIRD)) {
570      printf_lock("Kernel stack pushd us over 8MB\n");
571      panic("ksp too big\n");
572   }
573   if (THIRD_XXX((ul)ksp_top) >  NUM_KERNEL_THIRD * 1024) {
574      panic("increase NUM_KERNEL_THIRD, and change THIRD_XXX\n");
575   }
576   ptr = (ul) ksp_top;
577   bzero((char *)ptr, 8192 * 2);
578   third_kernel[THIRD_XXX(ptr)] = 0;			/* Stack Guard Page */
579   ptr += 8192;
580   third_kernel[THIRD_XXX(ptr)] = KPTE(PFN(ptr));	/* Kernel Stack Pages */
581   ptr += 8192;
582   third_kernel[THIRD_XXX(ptr)] = KPTE(PFN(ptr));
583   ptr += 8192;
584   third_kernel[THIRD_XXX(ptr)] = 0;			/* Stack Guard Page */
585
586   /* put argv into the bottom of the stack - argv starts at 1 because
587    * the command thatr got us here (i.e. "unixboot) is in argv[0].
588    */
589   ksp -= 8;			/* Back up one longword */
590   ksp -= argc * sizeof(char *);	/* Make room for argv */
591   kargv = (char **) ksp;
592   for (i = 1; i < argc; i++) {	/* Copy arguments to stack */
593      ksp -= ((strlen(argv[i]) + 1) + 7) & ~0x7;
594      kargv[i-1] = (char *) ksp;
595      strcpy(kargv[i-1], argv[i]);
596   }
597   kargc = i - 1;
598   kargv[kargc] = NULL;		/* just to be sure; doesn't seem to be used */
599   ksp -= sizeof(char *);	/* point above last arg for no real reason */
600
601   free_pfn = PFN(ptr);
602
603   bcopy((char *)&xxm_rpb, (char *)rpb, sizeof(struct rpb));
604
605   rpb->rpb_selfref = (struct rpb *) KSEG_TO_PHYS(rpb);
606   rpb->rpb_string = 0x0000004250525748;
607
608   tbb = (ul *) (((char *) rpb) + ROUNDUP8(sizeof(struct rpb)));
609   rpb->rpb_trans_off = (ul)tbb - (ul)rpb;
610   bcopy((char *)xxm_tbb, (char *)tbb, sizeof(xxm_tbb));
611
612
613   /*
614    * rpb_counter. Use to determine timeouts in OS.
615    * XXX must be patched after a checkpoint restore (I guess)
616    */
617
618   printf_lock("CPU Clock at %d MHz IntrClockFrequency=%d \n", simosConf.cpuClock,simosConf.intrClockFrequency);
619   rpb->rpb_counter = simosConf.cpuClock * 1000 * 1000;
620
621   /*
622    * By definition, the rpb_clock is scaled by 4096 (in hz)
623    */
624   rpb->rpb_clock = simosConf.intrClockFrequency * 4096;
625
626
627
628   /*
629    * Per CPU Slots. Multiprocessor support.
630    */
631   {
632      int i;
633      int size = ROUNDUP128(sizeof(struct rpb_percpu));
634
635      printf_lock("Booting with %d processor(s) \n",simosConf.numCPUs);
636
637      rpb->rpb_numprocs = simosConf.numCPUs;
638      rpb->rpb_slotsize = size;
639      rpb_percpu = (struct rpb_percpu *)
640         ROUNDUP128(((ul) tbb) +(sizeof(xxm_tbb)));
641
642      rpb->rpb_percpu_off = (ul)rpb_percpu - (ul)rpb;
643
644      for (i=0;i<simosConf.numCPUs;i++) {
645         struct rpb_percpu *thisCPU = (struct rpb_percpu*)
646            ((ul)rpb_percpu + size*i);
647
648         bzero((char *)thisCPU, size);
649         bcopy((char *)&xxm_rpb_percpu,
650               (char *)thisCPU,
651               sizeof(struct rpb_percpu));
652
653         thisCPU->rpb_pcb.rpb_ksp = ksp;
654         thisCPU->rpb_pcb.rpb_ptbr = PFN(first);
655
656         thisCPU->rpb_logout = KSEG_TO_PHYS(percpu_logout);
657         thisCPU->rpb_logout_len = 8192;
658
659/*  thisCPU->rpb_pcb.rpb_ptbr = PFN(second);*/
660
661         printf_lock("KSP: 0x%x PTBR 0x%x\n", thisCPU->rpb_pcb.rpb_ksp, thisCPU->rpb_pcb.rpb_ptbr);
662
663         if (i) {
664            bootStrapImpure[i] = (ul)unix_boot_alloc(1);
665         }
666
667      }
668
669      nextPtr = (ul)rpb_percpu + size*simosConf.numCPUs;
670   }
671
672   /*
673    * Console Terminal Block
674    */
675
676
677      rpb_ctb = (struct rpb_ctb *) nextPtr;
678      ctb_tt = (struct ctb_tt*) rpb_ctb;
679
680      rpb->rpb_ctb_off = ((ul)rpb_ctb) - (ul)rpb;
681      rpb->rpb_ctb_size  = sizeof(struct rpb_ctb);
682
683   bzero((char *)rpb_ctb, sizeof(struct ctb_tt));
684
685#ifdef original_xxm
686   if (tga_slot == -1)
687      rpb_ctb->rpb_type = CONS_DZ;
688  else {
689    rpb_ctb->rpb_type = CONS_GRPH;
690    rpb_ctb->rpb_unit = (SLOTINFO_PCI << 16) | (0 << 8) | tga_slot;
691  }
692#else
693  rpb_ctb->rpb_type = CONS_DZ;
694#endif
695
696  rpb_ctb->rpb_length = sizeof(ctb_tt)-sizeof(rpb_ctb);
697
698  /*
699   * uart initizliation
700   */
701  ctb_tt->ctb_csr = 0;
702  ctb_tt->ctb_tivec = 0x6c0;  /* matches tlaser pal code */
703  ctb_tt->ctb_rivec = 0x680;  /* matches tlaser pal code */
704  ctb_tt->ctb_baud = 9600;
705  ctb_tt->ctb_put_sts = 0;
706  ctb_tt->ctb_get_sts = 0;
707
708
709  rpb_crb = (struct rpb_crb *) (((ul)rpb_ctb) + sizeof(struct ctb_tt));
710  rpb->rpb_crb_off = ((ul)rpb_crb) - (ul)rpb;
711
712  bzero((char *)rpb_crb, sizeof(struct rpb_crb));
713  /*
714   * console callback stuff (simos)
715   */
716
717  rpb_crb->rpb_num = 1;
718  rpb_crb->rpb_mapped_pages = HWRPB_PAGES;
719  rpb_crb->rpb_map[0].rpb_virt = 0x10000000;
720  rpb_crb->rpb_map[0].rpb_phys = KSEG_TO_PHYS(((ul)rpb) & ~0x1fff);
721  rpb_crb->rpb_map[0].rpb_pgcount = HWRPB_PAGES;
722
723
724  printf_lock("Console Callback at 0x%x, fixup at 0x%x, crb offset: 0x%x\n",
725          rpb_crb->rpb_va_disp,
726          rpb_crb->rpb_va_fixup,
727          rpb->rpb_crb_off);
728
729  rpb_mdt = (struct _xxm_rpb_mdt *) (((ul)rpb_crb) + sizeof(struct rpb_crb));
730  rpb->rpb_mdt_off = (ul)rpb_mdt - (ul)rpb;
731  bcopy((char *)&xxm_rpb_mdt, (char *)rpb_mdt, sizeof(struct _xxm_rpb_mdt));
732
733
734  cl = 0;
735#ifdef undef
736  /* Until Digital Unix can handle it, account all pages below the kernel
737   * as "console" memory. */
738  rpb_mdt->rpb_cluster[cl].rpb_pfncount = cons_pages;
739#endif
740  rpb_mdt->rpb_cluster[cl].rpb_pfncount = kern_first_page;
741  cl++;
742
743  rpb_mdt->rpb_cluster[cl].rpb_pfn = kern_first_page;
744  rpb_mdt->rpb_cluster[cl].rpb_pfncount = mem_pages - kern_first_page;
745  rpb_mdt->rpb_cluster[cl].rpb_pfntested=rpb_mdt->rpb_cluster[cl].rpb_pfncount;
746  rpb_mdt->rpb_cluster[cl].rpb_pa = KSEG_TO_PHYS(mdt_bitmap);
747  rpb_mdt->rpb_cluster[cl].rpb_va = 0x10000000 + HWRPB_PAGES * 8192;
748  cl++;
749
750#ifdef undef
751  /* The stupid Unix kernel needs to have all mdt clusters in ascending
752   * order, and the last cluster is used to compute the top of memory.
753   * It can't make use of memory between the console and the kernel.
754   */
755  rpb_mdt->rpb_cluster[cl].rpb_pfn = cons_pages;
756  rpb_mdt->rpb_cluster[cl].rpb_pfncount = kern_first_page - cons_pages;
757  rpb_mdt->rpb_cluster[cl].rpb_pfntested=rpb_mdt->rpb_cluster[cl].rpb_pfncount;
758  rpb_mdt->rpb_cluster[cl].rpb_pa = KSEG_TO_PHYS(mdt_bitmap);
759  rpb_mdt->rpb_cluster[cl].rpb_va = 0x10000000 + HWRPB_PAGES * 8192;
760  cl++;
761#endif
762
763  rpb_mdt->rpb_numcl = cl;
764
765  for (i = 0; i < cl; i++)
766    printf_lock("Memory cluster %d [%d - %d]\n", i, rpb_mdt->rpb_cluster[i].rpb_pfn, rpb_mdt->rpb_cluster[i].rpb_pfncount);
767
768
769
770  /* Checksum the rpb for good luck */
771  sum = 0;
772  lp1 = (long *)&rpb_mdt->rpb_impaddr;
773  lp2 = (long *)&rpb_mdt->rpb_cluster[cl];
774  while (lp1 < lp2) sum += *lp1++;
775  rpb_mdt->rpb_checksum = sum;
776
777  /* XXX should checksum the cluster descriptors */
778
779  bzero((char *)mdt_bitmap, MDT_BITMAP_PAGES * 8192);
780  for (i = 0; i < mem_pages/8; i++) ((unsigned char *)mdt_bitmap)[i] = 0xff;
781
782  printf_lock("Initalizing mdt_bitmap addr 0x%x mem_pages %x \n",
783         (long)mdt_bitmap,(long)mem_pages);
784
785  xxm_rpb.rpb_config_off = 0;
786  xxm_rpb.rpb_fru_off = 0;
787
788  rpb_dsr = (struct rpb_dsr *) (((ul)rpb_mdt) + sizeof(struct _xxm_rpb_mdt));
789  rpb->rpb_dsr_off = ((ul)rpb_dsr) - (ul)rpb;
790  bzero((char *)rpb_dsr, sizeof(struct rpb_dsr));
791  rpb_dsr->rpb_smm = 1578; /* Official XXM SMM number as per SRM */
792  rpb_dsr->rpb_smm = 1089; /* Official Alcor SMM number as per SRM */
793
794  rpb_lurt = (int *) ROUNDUP8(((ul)rpb_dsr) + sizeof(struct rpb_dsr));
795  rpb_dsr->rpb_lurt_off = ((ul) rpb_lurt) - (ul) rpb_dsr;
796  bcopy((char *)xxm_lurt, (char *)rpb_lurt, sizeof(xxm_lurt));
797
798  rpb_name = (char *) ROUNDUP8(((ul)rpb_lurt) + sizeof(xxm_lurt));
799  rpb_dsr->rpb_sysname_off = ((ul) rpb_name) - (ul) rpb_dsr;
800#define THENAME "             M5/Alpha       "
801  sum = sizeof(THENAME);
802  bcopy(THENAME, rpb_name, sum);
803  *(ul *)rpb_name = sizeof(THENAME); /* put in length field */
804
805  /* calculate size of rpb */
806  rpb->rpb_size = ((ul) &rpb_name[sum]) - (ul)rpb;
807
808  if (rpb->rpb_size > 8192*HWRPB_PAGES) {
809     panic("HWRPB_PAGES=%d too small for HWRPB !!! \n");
810  }
811
812
813 {
814     ul *ptr = (ul*)((char*)rpb_dsr + sizeof(struct rpb_dsr ));
815     rpb_crb->rpb_pa_disp = KSEG_TO_PHYS(ptr);
816     rpb_crb->rpb_va_disp = 0x10000000 + (((ul)ptr - (ul)rpb) & (0x2000*HWRPB_PAGES-1));
817     printf_lock("ConsoleDispatch at virt %x phys %x val %x\n",
818             rpb_crb->rpb_va_disp,
819            rpb_crb->rpb_pa_disp,
820            consoleCallback);
821     *ptr++ = 0;
822     *ptr++ = (ul) consoleCallback;
823     rpb_crb->rpb_pa_fixup = KSEG_TO_PHYS(ptr);
824     rpb_crb->rpb_va_fixup = 0x10000000 + (((ul)ptr - (ul)rpb) & (0x2000*HWRPB_PAGES-1));
825     *ptr++ = 0;
826
827     *ptr++ = (ul) consoleFixup;
828  }
829
830
831  /* Checksum the rpb for good luck */
832  sum = 0;
833  lp1 = (long *)rpb;
834  lp2 = &rpb->rpb_checksum;
835  while (lp1 < lp2)
836    sum += *lp1++;
837  *lp2 = sum;
838
839
840  /*
841   * MP bootstrap
842   */
843
844  {
845     int i;
846     for (i=1;i<simosConf.numCPUs;i++) {
847        volatile struct AlphaAccess *k1Conf = (volatile struct AlphaAccess *)
848           (ALPHA_ACCESS_BASE);
849        printf_lock("Bootstraping CPU %d with sp=0x%x \n",
850               i,bootStrapImpure[i]);
851        k1Conf->bootStrapImpure = bootStrapImpure[i];
852        k1Conf->bootStrapCPU = i;
853     }
854  }
855
856  /*
857   * Make sure that we are not stepping on the kernel
858   */
859  if ((ul)unix_boot_mem >= (ul)simosConf.kernStart) {
860     panic("CONSOLE: too much memory. Smashing kernel  \n");
861  } else {
862     printf_lock("unix_boot_mem ends at %x \n",unix_boot_mem);
863  }
864
865
866#ifdef undef
867#define CSERVE_K_JTOKERN	0x18
868  cServe(bootadr, (ul) rpb_percpu, CSERVE_K_JTOKERN, free_pfn);
869#endif
870
871  if (go) JToKern(bootadr, rpb_percpu, free_pfn, kargc, kargv, NULL);
872}
873
874
875#if 0
876aoutfixup(char *p)
877{
878  int i;
879  unsigned long rem, len, off, dst;
880
881
882  struct new_aouthdr *ao = (struct new_aouthdr *) &p[NEW_FILHSZ];
883#if 0
884  struct scnhdr *s = (struct scnhdr *) &p[FILHSZ + AOUTHSZ];
885  struct scnhdr *t, *d, *b;
886  printf("aoutfixup: %d sections \n",fh->f_nscns);
887#endif
888
889
890  aout_text_start = ((ul)ao->text_start_hi<<32) + ao->text_start;
891  aout_data_addr = ((ul)ao->data_start_hi<<32) + ao->data_start;
892  aout_bss_addr = ((ul)ao->bss_start_hi<<32) + ao->bss_start;
893  aout_bss_size = ((ul)ao->bsize_hi<<32) +  ao->bsize;
894  aout_entry = ((ul)ao->entry_hi<<32) + ao->entry;
895
896  printf("_text 0x%16x %8d @ %08d\n", aout_text_start, ao->tsize,0 /* t->s_scnptr*/);
897  printf("_data 0x%16x %8d @ %08d\n", aout_data_addr, ao->dsize,0/* d->s_scnptr*/);
898  printf("_bss  0x%16x %8d\n", aout_bss_addr,  ao->bsize);
899  printf("entry 0x%16x\n", aout_entry);
900#if 0
901  for (i = 0; i < fh->f_nscns; i++) {
902     printf("section %d %s \n",i,s[i].s_name);
903    if (!strcmp(s[i].s_name, ".text")) t = &s[i];
904    else if (!strcmp(s[i].s_name, ".data")) d = &s[i];
905    else if (!strcmp(s[i].s_name, ".bss")) b = &s[i];
906  }
907  bcopy(&p[t->s_scnptr], (char *)ao->text_start, ao->tsize);
908  bcopy(&p[d->s_scnptr], (char *)ao->data_start, ao->dsize);
909#endif
910}
911#endif
912
913extern ui palJToKern[];
914
915JToKern(bootadr, rpb_percpu, free_pfn, k_argc, k_argv, envp)
916char * bootadr;
917ul rpb_percpu;
918ul free_pfn;
919ul k_argc;
920char **k_argv;
921char **envp;
922{
923  struct _kernel_params *kernel_params = (struct _kernel_params *) KSEG;
924  int i;
925
926  printf_lock("k_argc = %d ", k_argc);
927  for (i = 0; i < k_argc; i++) {
928    printf_lock("'%s' ", k_argv[i]);
929  }
930  printf_lock("\n");
931
932/*  rpb_percpu |= 0xfffffc0000000000;*/
933  kernel_params->bootadr = bootadr;
934  kernel_params->rpb_percpu = KSEG_TO_PHYS(rpb_percpu);
935  kernel_params->free_pfn = free_pfn;
936  kernel_params->argc = k_argc;
937  kernel_params->argv = (ul)k_argv;
938  kernel_params->envp = (ul)envp;
939  printf_lock("jumping to kernel at 0x%x, (PCBB 0x%x pfn %d)\n", bootadr, rpb_percpu, free_pfn);
940  jToPal(KSEG_TO_PHYS((ul)palJToKern));
941  printf_lock("returned from jToPal. Looping\n");
942  while(1) continue;
943}
944
945
946void jToPal(ul bootadr)
947{
948  cServe(bootadr, 0, CSERVE_K_JTOPAL);
949
950/*
951 * Make sure that floating point is enabled incase
952 * it was disabled by the user program.
953 */
954  wrfen(1);
955}
956
957
958int strcpy(char *dst, char *src)
959{
960   int i=0;
961   while(*src) {
962      *dst++ = *src++;
963      i++;
964   }
965   return i;
966}
967
968
969
970
971/* *****************************************
972 * Console I/O
973 * ******************************************/
974
975int numOpenDevices = 11;
976struct {
977   char name[128];
978} deviceState[32];
979
980#define BOOTDEVICE_NAME "SCSI 1 0 0 1 100 0"
981
982void
983DeviceOperation(long op, long channel, long count, long address, long block)
984{
985   struct AlphaAccess *k1Conf = (struct AlphaAccess *)
986      (ALPHA_ACCESS_BASE);
987
988   long pAddr;
989
990#if 0
991   printf("Console::DeviceRead count=0x%x address=0x%x block=0x%x\n",
992          count,address,block);
993#endif
994
995   if (strcmp(deviceState[channel].name, BOOTDEVICE_NAME )) {
996      panic("DeviceRead: only implemented for root disk \n");
997   }
998   pAddr = KSEG_TO_PHYS(address);
999   if (pAddr + count > simosConf.mem_size) {
1000      panic("DeviceRead: request out of range \n");
1001   }
1002
1003   k1Conf->diskCount = count;
1004   k1Conf->diskPAddr = pAddr;
1005   k1Conf->diskBlock = block;
1006   k1Conf->diskOperation = op; /* launch */
1007}
1008
1009
1010
1011/* *************************************************************************
1012 * SimoS Console callbacks
1013 * **************************************************/
1014
1015/* AXP manual 2-31 */
1016#define CONSCB_GETC 0x1
1017#define CONSCB_PUTS 0x2
1018#define CONSCB_RESET_TERM 0x3
1019#define CONSCB_SET_TERM_INT 0x4
1020#define CONSCB_SET_TERM_CTL 0x5
1021#define CONSCB_PROCESS_KEY 0x6
1022#define CONSCB_OPEN_CONSOLE 0x7
1023#define CONSCB_CLOSE_CONSOLE 0x8
1024
1025#define CONSCB_OPEN 0x10
1026#define CONSCB_CLOSE 0x11
1027#define CONSCB_READ 0x13
1028
1029#define CONSCB_GETENV 0x22
1030
1031/* AXP manual 2-26 */
1032#define	ENV_AUTO_ACTION		0X01
1033#define	ENV_BOOT_DEV		0X02
1034#define	ENV_BOOTDEF_DEV		0X03
1035#define	ENV_BOOTED_DEV		0X04
1036#define	ENV_BOOT_FILE		0X05
1037#define	ENV_BOOTED_FILE		0X06
1038#define	ENV_BOOT_OSFLAGS	0X07
1039#define	ENV_BOOTED_OSFLAGS	0X08
1040#define	ENV_BOOT_RESET		0X09
1041#define	ENV_DUMP_DEV		0X0A
1042#define	ENV_ENABLE_AUDIT	0X0B
1043#define	ENV_LICENSE		0X0C
1044#define	ENV_CHAR_SET		0X0D
1045#define	ENV_LANGUAGE		0X0E
1046#define	ENV_TTY_DEV		0X0F
1047#define	ENV_SCSIID		0X42
1048#define	ENV_SCSIFAST		0X43
1049#define	ENV_COM1_BAUD		0X44
1050#define	ENV_COM1_MODEM		0X45
1051#define	ENV_COM1_FLOW		0X46
1052#define	ENV_COM1_MISC		0X47
1053#define	ENV_COM2_BAUD		0X48
1054#define	ENV_COM2_MODEM		0X49
1055#define	ENV_COM2_FLOW		0X4A
1056#define	ENV_COM2_MISC		0X4B
1057#define	ENV_PASSWORD		0X4C
1058#define	ENV_SECURE		0X4D
1059#define	ENV_LOGFAIL		0X4E
1060#define	ENV_SRM2DEV_ID		0X4F
1061
1062#define MAX_ENVLEN 32
1063
1064char	env_auto_action[MAX_ENVLEN]	= "BOOT";
1065char	env_boot_dev[MAX_ENVLEN]	= "";
1066char	env_bootdef_dev[MAX_ENVLEN]	= "";
1067char	env_booted_dev[MAX_ENVLEN]	= BOOTDEVICE_NAME;
1068char	env_boot_file[MAX_ENVLEN]	= "";
1069char	env_booted_file[MAX_ENVLEN]	= "";
1070char	env_boot_osflags[MAX_ENVLEN]	= "";
1071char	env_booted_osflags[MAX_ENVLEN]	= "";
1072char	env_boot_reset[MAX_ENVLEN]	= "";
1073char	env_dump_dev[MAX_ENVLEN]	= "";
1074char	env_enable_audit[MAX_ENVLEN]	= "";
1075char	env_license[MAX_ENVLEN]		= "";
1076char	env_char_set[MAX_ENVLEN]	= "";
1077char	env_language[MAX_ENVLEN]	= "";
1078char	env_tty_dev[MAX_ENVLEN]		= "0";
1079char	env_scsiid[MAX_ENVLEN]		= "";
1080char	env_scsifast[MAX_ENVLEN]	= "";
1081char	env_com1_baud[MAX_ENVLEN]	= "";
1082char	env_com1_modem[MAX_ENVLEN]	= "";
1083char	env_com1_flow[MAX_ENVLEN]	= "";
1084char	env_com1_misc[MAX_ENVLEN]	= "";
1085char	env_com2_baud[MAX_ENVLEN]	= "";
1086char	env_com2_modem[MAX_ENVLEN]	= "";
1087char	env_com2_flow[MAX_ENVLEN]	= "";
1088char	env_com2_misc[MAX_ENVLEN]	= "";
1089char	env_password[MAX_ENVLEN]	= "";
1090char	env_secure[MAX_ENVLEN]		= "";
1091char	env_logfail[MAX_ENVLEN]		= "";
1092char	env_srm2dev_id[MAX_ENVLEN]	= "";
1093
1094#define MAX_ENV_INDEX 100
1095char *env_ptr[MAX_ENV_INDEX] =
1096{
1097    0,					/* 0x00 */
1098    env_auto_action,			/* 0x01 */
1099    env_boot_dev,			/* 0x02 */
1100    env_bootdef_dev,			/* 0x03 */
1101    env_booted_dev,			/* 0x04 */
1102    env_boot_file,			/* 0x05 */
1103    env_booted_file,			/* 0x06 */
1104    env_boot_osflags,			/* 0x07 */
1105    env_booted_osflags,			/* 0x08 */
1106    env_boot_reset,			/* 0x09 */
1107    env_dump_dev,			/* 0x0A */
1108    env_enable_audit,			/* 0x0B */
1109    env_license,			/* 0x0C */
1110    env_char_set,			/* 0x0D */
1111    (char *)&env_language,		/* 0x0E */
1112    env_tty_dev,			/* 0x0F */
1113    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,	/* 0x10 - 0x1F */
1114    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,	/* 0x20 - 0x2F */
1115    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,	/* 0x30 - 0x3F */
1116    0,					/* 0x40 */
1117    0,					/* 0x41 */
1118    env_scsiid,				/* 0x42 */
1119    env_scsifast,			/* 0x43 */
1120    env_com1_baud,			/* 0x44 */
1121    env_com1_modem,			/* 0x45 */
1122    env_com1_flow,			/* 0x46 */
1123    env_com1_misc,			/* 0x47 */
1124    env_com2_baud,			/* 0x48 */
1125    env_com2_modem,			/* 0x49 */
1126    env_com2_flow,			/* 0x4A */
1127    env_com2_misc,			/* 0x4B */
1128    env_password,			/* 0x4C */
1129    env_secure,				/* 0x4D */
1130    env_logfail,			/* 0x4E */
1131    env_srm2dev_id,			/* 0x4F */
1132    0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,	/* 0x50 - 0x5F */
1133    0,					/* 0x60 */
1134    0,					/* 0x61 */
1135    0,					/* 0x62 */
1136    0,					/* 0x63 */
1137};
1138
1139long
1140CallBackDispatcher(long a0, long a1, long a2, long a3, long a4)
1141{
1142   long i;
1143   switch (a0) {
1144   case CONSCB_GETC:
1145     return GetChar();
1146
1147   case CONSCB_PUTS:
1148      for(i = 0; i < a3; i++)
1149         PutChar(*((char *)a2+i));
1150      return a3;
1151
1152   case CONSCB_GETENV:
1153     if (a1 >= 0 && a1 < MAX_ENV_INDEX && env_ptr[a1] != 0 && *env_ptr[a1]) {
1154         i = strcpy((char*)a2, env_ptr[a1]);
1155     } else {
1156         strcpy((char*)a2, "");
1157         i = (long)0xc000000000000000;
1158         if (a1 >= 0 && a1 < MAX_ENV_INDEX)
1159             printf_lock("GETENV unsupported option %d (0x%x)\n", a1, a1);
1160         else
1161             printf_lock("GETENV unsupported option %s\n", a1);
1162     }
1163
1164     if (i > a3)
1165         panic("CONSCB_GETENV overwrote buffer\n");
1166     return i;
1167
1168   case CONSCB_OPEN:
1169      bcopy((char*)a1,deviceState[numOpenDevices].name,a2);
1170      deviceState[numOpenDevices].name[a2] = '\0';
1171      printf_lock("CONSOLE OPEN : %s --> success \n",
1172             deviceState[numOpenDevices].name);
1173      return numOpenDevices++;
1174
1175   case CONSCB_READ:
1176      DeviceOperation(a0,a1,a2,a3,a4);
1177      break;
1178
1179   case CONSCB_CLOSE:
1180      break;
1181   case CONSCB_OPEN_CONSOLE:
1182      printf_lock("CONSOLE OPEN\n");
1183      return 0; /* success */
1184      break; /* not rearched */
1185   case CONSCB_CLOSE_CONSOLE:
1186      printf_lock("CONSOLE CLOSE\n");
1187      return 0; /* success */
1188      break; /* not reached */
1189
1190   default:
1191      panic("cher (%x,%x,%x,%x)\n", a0, a1, a2, a3);
1192   }
1193
1194   return 0;
1195}
1196
1197long CallBackFixup(int a0, int a1, int a2)
1198{
1199   long temp;
1200   /* Linux uses r8 for the current pointer (pointer to data structure
1201      contating info about currently running process). It is set when the
1202      kernel starts and is expected to remain there... Problem is that the
1203      unlike the kernel, the console does not prevent the assembler from
1204      using r8. So here is a work around. So far this has only been a problem
1205      in CallBackFixup() but any other call back functions could cause a problem
1206      at some point */
1207
1208   /* save off the current pointer to a temp variable */
1209   asm("bis $8, $31, %0" : "=r" (temp));
1210
1211   /* call original code */
1212   printf_lock("CallbackFixup %x %x, t7=%x\n",a0,a1,temp);
1213
1214   /* restore the current pointer */
1215   asm("bis %0, $31, $8" : : "r" (temp) : "$8");
1216
1217#if 0
1218  if (first[FIRST(a1)]==0) {
1219      first[FIRST(a1)] = KPTE(PFN(reservedFixup));
1220   } else {
1221      panic("CallBakcfixup\n");
1222   }
1223   second[SECOND(a1)] = KPTE(PFN(third_rpb));	/* Region 0 */
1224   printf("Fixup: FISRT(a1)=0x%x SECOND(a1)=0x%x THIRD(a1)=0x%x\n",
1225          FIRST(a1),SECOND(a1),THIRD(a1));
1226
1227#endif
1228   return 0;
1229}
1230
1231
1232
1233
1234
1235void SlaveCmd(int cpu, struct rpb_percpu *my_rpb)
1236{
1237/*   extern void palJToSlave[]; */
1238   extern unsigned int palJToSlave[];
1239
1240   printf_lock("Slave CPU %d console command %s", cpu,my_rpb->rpb_iccb.iccb_rxbuf);
1241
1242   my_rpb->rpb_state |= STATE_BIP;
1243   my_rpb->rpb_state &= ~STATE_RC;
1244
1245   printf_lock("SlaveCmd: restart %x %x vptb %x my_rpb %x my_rpb_phys %x\n",
1246          rpb->rpb_restart,
1247          rpb->rpb_restart_pv,
1248          rpb->rpb_vptb, my_rpb,
1249          KSEG_TO_PHYS(my_rpb));
1250
1251   cServe(KSEG_TO_PHYS((ul)palJToSlave),
1252          (ul)rpb->rpb_restart,
1253          CSERVE_K_JTOPAL,
1254          rpb->rpb_restart_pv,
1255          rpb->rpb_vptb,
1256          KSEG_TO_PHYS(my_rpb));
1257
1258   panic("SlaveCmd returned \n");
1259}
1260
1261void SlaveLoop( int cpu)
1262{
1263   int size = ROUNDUP128(sizeof(struct rpb_percpu));
1264   struct rpb_percpu *my_rpb = (struct rpb_percpu*)
1265      ((ul)rpb_percpu + size*cpu);
1266
1267   if (cpu==0) {
1268      panic("CPU�0 entering slaveLoop. Reenetering the console. HOSED \n");
1269   } else {
1270      printf_lock("Entering slaveloop for cpu %d my_rpb=%x \n",cpu,my_rpb);
1271   }
1272
1273   // swap the processors context to the one in the
1274   // rpb_percpu struct very carefully (i.e. no stack usage)
1275   // so that linux knows which processor ends up in __smp_callin
1276   // and we don't trash any data is the process
1277   SlaveSpin(cpu,my_rpb,&my_rpb->rpb_iccb.iccb_rxlen);
1278}
1279