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