Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 *	8260 specific stuff:
3
 *		Interrupt handling
4
 */
5
#include	"u.h"
6
#include	"../port/lib.h"
7
#include	"mem.h"
8
#include	"dat.h"
9
#include	"io.h"
10
#include	"fns.h"
11
#include	"m8260.h"
12
 
13
enum {
14
	Pin4 = BIT(4),
15
};
16
 
17
static union {
18
	struct {
19
		ulong	hi;
20
		ulong	lo;
21
	};
22
	uvlong		val;
23
} ticks;
24
 
25
struct {
26
	ulong	hi;
27
	ulong	lo;
28
} vec2mask[64]	= {
29
[0]	= {0,		0	},	/* Error, No interrupt */
30
[1]	= {0,		BIT(16)	},	/* I2C */
31
[2]	= {0,		BIT(17)	},	/* SPI */
32
[3]	= {0,		BIT(18)	},	/* Risc Timers */
33
[4]	= {0,		BIT(19)	},	/* SMC1 */
34
[5]	= {0,		BIT(20)	},	/* SMC2 */
35
[6]	= {0,		BIT(21)	},	/* IDMA1 */
36
[7]	= {0,		BIT(22)	},	/* IDMA2 */
37
[8]	= {0,		BIT(23)	},	/* IDMA3 */
38
[9]	= {0,		BIT(24)	},	/* IDMA4 */
39
[10]	= {0,		BIT(25)	},	/* SDMA */
40
[11]	= {0,		0	},	/* Reserved */
41
[12]	= {0,		BIT(27)	},	/* Timer1 */
42
[13]	= {0,		BIT(28)	},	/* Timer2 */
43
[14]	= {0,		BIT(29)	},	/* Timer3 */
44
[15]	= {0,		BIT(30)	},	/* Timer4 */
45
 
46
[16]	= {BIT(29),	0	},	/* TMCNT */
47
[17]	= {BIT(30),	0	},	/* PIT */
48
[18]	= {0,		0	},	/* Reserved */
49
[19]	= {BIT(17),	0	},	/* IRQ1 */
50
[20]	= {BIT(18),	0	},	/* IRQ2 */
51
[21]	= {BIT(19),	0	},	/* IRQ3 */
52
[22]	= {BIT(20),	0	},	/* IRQ4 */
53
[23]	= {BIT(21),	0	},	/* IRQ5 */
54
[24]	= {BIT(22),	0	},	/* IRQ6 */
55
[25]	= {BIT(23),	0	},	/* IRQ7 */
56
[26]	= {0,		0	},	/* Reserved */
57
[27]	= {0,		0	},	/* Reserved */
58
[28]	= {0,		0	},	/* Reserved */
59
[29]	= {0,		0	},	/* Reserved */
60
[30]	= {0,		0	},	/* Reserved */
61
[31]	= {0,		0	},	/* Reserved */
62
 
63
[32]	= {0,		BIT(0)	},	/* FCC1 */
64
[33]	= {0,		BIT(1)	},	/* FCC2 */
65
[34]	= {0,		BIT(2)	},	/* FCC3 */
66
[35]	= {0,		0	},	/* Reserved */
67
[36]	= {0,		BIT(4)	},	/* MCC1 */
68
[37]	= {0,		BIT(5)	},	/* MCC2 */
69
[38]	= {0,		0	},	/* Reserved */
70
[39]	= {0,		0	},	/* Reserved */
71
[40]	= {0,		BIT(8)	},	/* SCC1 */
72
[41]	= {0,		BIT(9)	},	/* SCC2 */
73
[42]	= {0,		BIT(10)	},	/* SCC3 */
74
[43]	= {0,		BIT(11)	},	/* SCC4 */
75
[44]	= {0,		0	},	/* Reserved */
76
[45]	= {0,		0	},	/* Reserved */
77
[46]	= {0,		0	},	/* Reserved */
78
[47]	= {0,		0	},	/* Reserved */
79
 
80
[48]	= {BIT(15),	0	},	/* PC15 */
81
[49]	= {BIT(14),	0	},	/* PC14 */
82
[50]	= {BIT(13),	0	},	/* PC13 */
83
[51]	= {BIT(12),	0	},	/* PC12 */
84
[52]	= {BIT(11),	0	},	/* PC11 */
85
[53]	= {BIT(10),	0	},	/* PC10 */
86
[54]	= {BIT(9),	0	},	/* PC9 */
87
[55]	= {BIT(8),	0	},	/* PC8 */
88
[56]	= {BIT(7),	0	},	/* PC7 */
89
[57]	= {BIT(6),	0	},	/* PC6 */
90
[58]	= {BIT(5),	0	},	/* PC5 */
91
[59]	= {BIT(4),	0	},	/* PC4 */
92
[60]	= {BIT(3),	0	},	/* PC3 */
93
[61]	= {BIT(2),	0	},	/* PC2 */
94
[62]	= {BIT(1),	0	},	/* PC1 */
95
[63]	= {BIT(0),	0	},	/* PC0 */
96
};
97
 
98
/* Blast memory layout:
99
 *	CS0: FE000000 -> FFFFFFFF (Flash)
100
 *	CS1: FC000000 -> FCFFFFFF (DSP hpi)
101
 *	CS2: 00000000 -> 03FFFFFF (60x sdram)
102
 *	CS3: 04000000 -> 04FFFFFF (FPGA)
103
 *	CS4: 05000000 -> 06FFFFFF (local bus sdram)
104
 *	CS5: 07000000 -> 0700FFFF (eeprom - not populated)
105
 *	CS6: E0000000 -> E0FFFFFF (FPGA - 64bits)
106
 *
107
 * Main Board memory layout:
108
 *	CS0: FE000000 -> FEFFFFFF (16 M FLASH)
109
 *	CS1: FC000000 -> FCFFFFFF (16 M DSP1)
110
 *	CS2: 00000000 -> 03FFFFFF (64 M SDRAM)
111
 *	CS3: 04000000 -> 04FFFFFF (16M DSP2)
112
 *	CS4: 05000000 -> 06FFFFFF (32 M Local SDRAM)
113
 *	CS5: 07000000 -> 0700FFFF (eeprom - not populated)
114
 *	CS6: unused
115
 *	CS7: E0000000 -> E0FFFFFF (16 M FPGA)
116
 */
117
 
118
IMM* iomem = (IMM*)IOMEM;
119
uchar etheraddr[6] = { 0x90, 0x85, 0x82, 0x32, 0x83, 0x00};
120
 
121
static Lock cpmlock;
122
 
123
void
124
machinit(void)
125
{
126
	ulong scmr;
127
	int pllmf;
128
	extern char* plan9inistr;
129
 
130
	memset(m, 0, sizeof(*m));
131
	m->cputype = getpvr()>>16;	/* pvr = 0x00810101 for the 8260 */
132
	m->imap = (Imap*)INTMEM;
133
 
134
	m->loopconst = 1096;
135
 
136
	/* Make sure Ethernet is disabled (boot code may have buffers allocated anywhere in memory) */
137
	iomem->fcc[0].gfmr &= ~(BIT(27)|BIT(26));
138
	iomem->fcc[1].gfmr &= ~(BIT(27)|BIT(26));
139
	iomem->fcc[2].gfmr &= ~(BIT(27)|BIT(26));
140
 
141
	/* Flashed CS configuration is wrong for DSP2.  It's set to 64 bits, should be 16 */
142
	iomem->bank[3].br = 0x04001001;	/* Set 16-bit port */
143
 
144
	/*
145
	 * FPGA is capable of doing 64-bit transfers.  To use these, set br to 0xe0000001.
146
	 * Currently we use 32-bit transfers, because the 8260 does not easily do 64-bit operations.
147
	 */
148
	iomem->bank[6].br = 0xe0001801;
149
	iomem->bank[6].or = 0xff000830;	/* Was 0xff000816 */
150
 
151
/*
152
 * All systems with rev. A.1 (0K26N) silicon had serious problems when doing
153
 * DMA transfers with data cache enabled (usually this shows when  using
154
 * one of the FCC's with some traffic on the ethernet).  Allocating FCC buffer
155
 * descriptors in main memory instead of DP ram solves this problem.
156
 */
157
 
158
	/* Guess at clocks based upon the PLL configuration from the
159
	 * power-on reset.
160
	 */
161
	scmr = iomem->scmr;
162
 
163
	/* The EST8260 is typically run using either 33 or 66 MHz
164
	 * external clock.  The configuration byte in the Flash will
165
	 * tell us which is configured.  The blast appears to be slightly
166
	 * overclocked at 72 MHz (if set to 66 MHz, the uart runs too fast)
167
	 */
168
 
169
	m->clkin = CLKIN;
170
 
171
	pllmf = scmr & 0xfff;
172
 
173
	/* This is arithmetic from the 8260 manual, section 9.4.1. */
174
 
175
	/* Collect the bits from the scmr.
176
	*/
177
	m->vco_out = m->clkin * (pllmf + 1);
178
	if (scmr & BIT(19))	/* plldf (division factor is 1 or 2) */
179
		m->vco_out >>= 1;
180
 
181
	m->cpmhz = m->vco_out >> 1;	/* cpm hz is half of vco_out */
182
	m->brghz = m->vco_out >> (2 * ((iomem->sccr & 0x3) + 1));
183
	m->bushz = m->vco_out / (((scmr & 0x00f00000) >> 20) + 1);
184
 
185
	/* Serial init sets BRG clock....I don't know how to compute
186
	 * core clock from core configuration, but I think I know the
187
	 * mapping....
188
	 */
189
	switch(scmr >> (31-7)){
190
	case 0x0a:
191
		m->cpuhz = m->clkin * 2;
192
		break;
193
	case 0x0b:
194
		m->cpuhz = (m->clkin >> 1) * 5;
195
		break;
196
	default:
197
	case 0x0d:
198
		m->cpuhz = m->clkin * 3;
199
		break;
200
	case 0x14:
201
		m->cpuhz = (m->clkin >> 1) * 7;
202
		break;
203
	case 0x1c:
204
		m->cpuhz = m->clkin * 4;
205
		break;
206
	}
207
 
208
	m->cyclefreq = m->bushz / 4;
209
 
210
/*	Expect:
211
	intfreq	133		m->cpuhz
212
	busfreq	33		m->bushz
213
	cpmfreq	99		m->cpmhz
214
	brgfreq	49.5		m->brghz
215
	vco		198
216
*/
217
 
218
	active.machs = 1;
219
	active.exiting = 0;
220
 
221
	putmsr(getmsr() | MSR_ME);
222
 
223
	/*
224
	 * turn on data cache before instruction cache;
225
	 * for some reason which I don't understand,
226
	 * you can't turn on both caches at once
227
	 */
228
	icacheenb();
229
	dcacheenb();
230
 
231
	kfpinit();
232
 
233
	/* Plan9.ini location in flash is FLASHMEM+PLAN9INI
234
	 * if PLAN9INI == ~0, it's not stored in flash or there is no flash
235
	 * if *cp == 0xff, flash memory is not initialized
236
	 */
237
	if (PLAN9INI == ~0 ||
238
	    (uchar)*(plan9inistr = (char*)(FLASHMEM+PLAN9INI)) == 0xff){
239
		/* No plan9.ini in flash */
240
		plan9inistr =
241
			"console=0\n"
242
			"ether0=type=fcc port=0 ea=00601d051dd8\n"
243
			"flash0=mem=0xfe000000\n"
244
			"fs=135.104.9.42\n"
245
			"auth=135.104.9.7\n"
246
			"authdom=cs.bell-labs.com\n"
247
			"sys=blast\n"
248
			"ntp=135.104.9.52\n";
249
	}
250
}
251
 
252
void
253
fpgareset(void)
254
{
255
	print("fpga reset\n");
256
 
257
	ioplock();
258
 
259
	iomem->port[1].pdat &= ~Pin4;	/* force reset signal to 0 */
260
	delay(100);
261
	iomem->port[1].pdat |= Pin4;		/* force reset signal back to one */
262
 
263
	iopunlock();
264
}
265
 
266
void
267
hwintrinit(void)
268
{
269
	iomem->sicr = 2 << 8;
270
	/* Write ones into most bits of the interrupt pending registers to clear interrupts */
271
	iomem->sipnr_h = ~7;
272
	iomem->sipnr_h = ~1;
273
	/* Clear the interrupt masks, thereby disabling all interrupts */
274
	iomem->simr_h = 0;
275
	iomem->simr_l = 0;
276
 
277
	iomem->sypcr &= ~2;	/* cause a machine check interrupt on memory timeout */
278
 
279
	/* Initialize fpga reset pin */
280
	iomem->port[1].pdir |= Pin4;		/* 1 is an output */
281
	iomem->port[1].ppar &= ~Pin4;
282
	iomem->port[1].pdat |= Pin4;		/* force reset signal back to one */
283
}
284
 
285
int
286
vectorenable(Vctl *v)
287
{
288
	ulong hi, lo;
289
 
290
	if (v->irq & ~0x3f){
291
		print("m8260enable: interrupt vector %d out of range\n", v->irq);
292
		return -1;
293
	}
294
	hi = vec2mask[v->irq].hi;
295
	lo = vec2mask[v->irq].lo;
296
	if (hi == 0 && lo == 0){
297
		print("m8260enable: nonexistent vector %d\n", v->irq);
298
		return -1;
299
	}
300
	ioplock();
301
	/* Clear the interrupt before enabling */
302
	iomem->sipnr_h |= hi;
303
	iomem->sipnr_l |= lo;
304
	/* Enable */
305
	iomem->simr_h |= hi;
306
	iomem->simr_l |= lo;
307
	iopunlock();
308
	return v->irq;
309
}
310
 
311
void
312
vectordisable(Vctl *v)
313
{
314
	ulong hi, lo;
315
 
316
	if (v->irq & ~0x3f){
317
		print("m8260disable: interrupt vector %d out of range\n", v->irq);
318
		return;
319
	}
320
	hi = vec2mask[v->irq].hi;
321
	lo = vec2mask[v->irq].lo;
322
	if (hi == 0 && lo == 0){
323
		print("m8260disable: nonexistent vector %d\n", v->irq);
324
		return;
325
	}
326
	ioplock();
327
	iomem->simr_h &= ~hi;
328
	iomem->simr_l &= ~lo;
329
	iopunlock();
330
}
331
 
332
int
333
intvec(void)
334
{
335
	return iomem->sivec >> 26;
336
}
337
 
338
void
339
intend(int vno)
340
{
341
	/* Clear interrupt */
342
	ioplock();
343
	iomem->sipnr_h |= vec2mask[vno].hi;
344
	iomem->sipnr_l |= vec2mask[vno].lo;
345
	iopunlock();
346
}
347
 
348
int
349
m8260eoi(int)
350
{
351
	return 0;
352
}
353
 
354
int
355
m8260isr(int)
356
{
357
	return 0;
358
}
359
 
360
void
361
flashprogpower(int)
362
{
363
}
364
 
365
enum {
366
	TgcrCas 			= 0x80,
367
	TgcrGm 			= 0x08,
368
	TgcrStp 			= 0x2,	/* There are two of these, timer-2 bits are bits << 4 */
369
	TgcrRst 			= 0x1,
370
 
371
	TmrIclkCasc		= 0x00<<1,
372
	TmrIclkIntclock	= 0x01<<1,
373
	TmrIclkIntclock16	= 0x02<<1,
374
	TmrIclkTin		= 0x03<<1,
375
	TmrCERising		= 0x1 << 6,
376
	TmrCEFalling		= 0x2 << 6,
377
	TmrCEAny		= 0x3 << 6,
378
	TmrFrr			= SBIT(12),
379
	TmrOri			= SBIT(11),
380
 
381
	TerRef			= SBIT(14),
382
	TerCap			= SBIT(15),
383
};
384
 
385
uvlong
386
fastticks(uvlong *hz)
387
{
388
	ulong count;
389
	static Lock fasttickslock;
390
 
391
	if (hz)
392
		*hz = m->clkin>>1;
393
	ilock(&fasttickslock);
394
	count = iomem->tcnl1;
395
	if (count < ticks.lo)
396
		ticks.hi += 1;
397
	ticks.lo = count;
398
	iunlock(&fasttickslock);
399
	return ticks.val;
400
}
401
 
402
ulong multiplier;
403
 
404
ulong
405
µs(void)
406
{
407
	uvlong x;
408
 
409
	if(multiplier == 0){
410
		multiplier = (uvlong)(1000000LL << 16) / m->cyclefreq;
411
		print("µs: multiplier %ld, cyclefreq %lld, shifter %d\n", multiplier, m->cyclefreq, 16);
412
	}
413
	cycles(&x);
414
	return (x*multiplier) >> 16;
415
}
416
 
417
void
418
timerset(Tval next)
419
{
420
	long offset;
421
	uvlong now;
422
	static int cnt;
423
 
424
	now = fastticks(nil);
425
	offset = next - now;
426
	if (offset < 2500)
427
		next = now + 2500;	/* 10000 instructions */
428
	else if (offset > m->clkin / HZ){
429
		print("too far in the future: offset %llux, now %llux\n", next, now);
430
		next = now + m->clkin / HZ;
431
	}
432
	iomem->trrl1 = next;
433
}
434
 
435
void
436
m8260timerintr(Ureg *u, void*)
437
{
438
	iomem->ter2 |= TerRef | TerCap;		/* Clear interrupt */
439
	timerintr(u, 0);
440
}
441
 
442
void
443
timerinit(void)
444
{
445
 
446
	iomem->tgcr1 = TgcrCas | TgcrGm;		/* cascade timers 1 & 2, normal gate mode */
447
	iomem->tcnl1 = 0;
448
	iomem->trrl1 = m->clkin / HZ;		/* first capture in 1/HZ seconds */
449
	iomem->tmr1 = TmrIclkCasc;
450
	iomem->tmr2 = TmrIclkIntclock | TmrOri;
451
	intrenable(13, m8260timerintr, nil, "timer");	/* Timer 2 interrupt is on 13 */
452
	iomem->tgcr1 |= TgcrRst << 4;
453
}
454
 
455
static void
456
addseg(char *name, ulong start, ulong length)
457
{
458
	Physseg segbuf;
459
 
460
	memset(&segbuf, 0, sizeof(segbuf));
461
	segbuf.attr = SG_PHYSICAL;
462
	kstrdup(&segbuf.name, name);
463
	segbuf.pa = start;
464
	segbuf.size = length;
465
	if (addphysseg(&segbuf) == -1) {
466
		print("addphysseg: %s\n", name);
467
		return;
468
	}
469
}
470
 
471
void
472
sharedseginit(void)
473
{
474
	int i, j;
475
	ulong base, size;
476
	char name[16], *a, *b, *s;
477
	static char *segnames[] = {
478
		"fpga",
479
		"dsp",
480
	};
481
 
482
	for (j = 0; j < nelem(segnames); j++){
483
		for (i = 0; i < 8; i++){
484
			snprint(name, sizeof name, "%s%d", segnames[j], i);
485
			if ((a = getconf(name)) == nil)
486
				continue;
487
			if ((b = strstr(a, "mem=")) == nil){
488
				print("blastseginit: %s: no base\n", name);
489
				continue;
490
			}
491
			b += 4;
492
			base = strtoul(b, nil, 0);
493
			if (base == 0){
494
				print("blastseginit: %s: bad base: %s\n", name, b);
495
				continue;
496
			}
497
			if ((s = strstr(a, "size=")) == nil){
498
				print("blastseginit: %s: no size\n", name);
499
				continue;
500
			}
501
			s += 5;
502
			size = strtoul(s, nil, 0);
503
			if (size == 0){
504
				print("blastseginit: %s: bad size: %s\n", name, s);
505
				continue;
506
			}
507
			addseg(name, base, size);
508
		}
509
	}
510
}
511
 
512
void
513
cpmop(int op, int dev, int mcn)
514
{
515
	ioplock();
516
	eieio();
517
	while(iomem->cpcr & 0x10000)
518
		eieio();
519
	iomem->cpcr = dev<<(31-10) | mcn<<(31-25) | op | 0x10000;
520
	eieio();
521
	while(iomem->cpcr & 0x10000)
522
		eieio();
523
	iopunlock();
524
}
525
 
526
/*
527
 * connect SCCx clocks in NSMI mode (x=1 for USB)
528
 */
529
void
530
sccnmsi(int x, int rcs, int tcs)
531
{
532
	ulong v;
533
	int sh;
534
 
535
	sh = (x-1)*8;	/* each SCCx field in sicr is 8 bits */
536
	v = (((rcs&7)<<3) | (tcs&7)) << sh;
537
	iomem->sicr = (iomem->sicr & ~(0xFF<<sh)) | v;
538
}
539
 
540
/*
541
 * lock the shared IO memory and return a reference to it
542
 */
543
void
544
ioplock(void)
545
{
546
	ilock(&cpmlock);
547
}
548
 
549
/*
550
 * release the lock on the shared IO memory
551
 */
552
void
553
iopunlock(void)
554
{
555
	eieio();
556
	iunlock(&cpmlock);
557
}
558
 
559
BD*
560
bdalloc(int n)
561
{
562
	static BD *palloc = ((Imap*)INTMEM)->bd;
563
	BD *p;
564
 
565
	p = palloc;
566
	if (palloc > ((Imap*)INTMEM)->bd + nelem(((Imap*)INTMEM)->bd)){
567
		print("bdalloc: out of BDs\n");
568
		return nil;
569
	}
570
	palloc += n;
571
	return p;
572
}
573
 
574
/*
575
 * Initialise receive and transmit buffer rings.  Only used for FCC
576
 * Ethernet now.
577
 *
578
 * Ioringinit will allocate the buffer descriptors in normal memory
579
 * and NOT in Dual-Ported Ram, as prescribed by the MPC8260
580
 * PowerQUICC II manual (Section 28.6).  When they are allocated
581
 * in DPram and the Dcache is enabled, the processor will hang.
582
 * This has been observed for the FCCs, it may or may not be true
583
 * for SCCs or DMA.
584
 * The SMC Uart buffer descriptors are not allocated here; (1) they
585
 * can ONLY be in DPram and (2) they are not configured as a ring.
586
 */
587
int
588
ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
589
{
590
	int i, x;
591
	static uchar *dpmallocaddr;
592
	static uchar *dpmallocend;
593
 
594
	if (dpmallocaddr == nil){
595
		dpmallocaddr = m->imap->dpram1;
596
		dpmallocend = dpmallocaddr + sizeof(m->imap->dpram1);
597
	}
598
	/* the ring entries must be aligned on sizeof(BD) boundaries */
599
	r->nrdre = nrdre;
600
	if(r->rdr == nil)
601
		r->rdr = xspanalloc(nrdre*sizeof(BD), 0, 8);
602
	if(r->rdr == nil)
603
		return -1;
604
	if(r->rrb == nil && bufsize){
605
		r->rrb = xspanalloc(nrdre*bufsize, 0, CACHELINESZ);
606
		if(r->rrb == nil)
607
			return -1;
608
	}
609
	x = bufsize ? PADDR(r->rrb) : 0;
610
	for(i = 0; i < nrdre; i++){
611
		r->rdr[i].length = 0;
612
		r->rdr[i].addr = x;
613
		r->rdr[i].status = BDEmpty|BDInt;
614
		x += bufsize;
615
	}
616
	r->rdr[i-1].status |= BDWrap;
617
	r->rdrx = 0;
618
 
619
	r->ntdre = ntdre;
620
	if(r->tdr == nil)
621
		r->tdr = xspanalloc(ntdre*sizeof(BD), 0, 8);
622
	if(r->txb == nil)
623
		r->txb = xspanalloc(ntdre*sizeof(Block*), 0, CACHELINESZ);
624
	if(r->tdr == nil || r->txb == nil)
625
		return -1;
626
	for(i = 0; i < ntdre; i++){
627
		r->txb[i] = nil;
628
		r->tdr[i].addr = 0;
629
		r->tdr[i].length = 0;
630
		r->tdr[i].status = 0;
631
	}
632
	r->tdr[i-1].status |= BDWrap;
633
	r->tdrh = 0;
634
	r->tdri = 0;
635
	r->ntq = 0;
636
	return 0;
637
}
638
 
639
void
640
trapinit(void)
641
{
642
	int i;
643
 
644
	/*
645
	 * set all exceptions to trap
646
	 */
647
	for(i = 0x0; i < 0x2000; i += 0x100)
648
		sethvec(i, trapvec);
649
 
650
	setmvec(0x1000, imiss, tlbvec);
651
	setmvec(0x1100, dmiss, tlbvec);
652
	setmvec(0x1200, dmiss, tlbvec);
653
 
654
/*	Useful for avoiding assembler miss handling:
655
	sethvec(0x1000, tlbvec);
656
	sethvec(0x1100, tlbvec);
657
	sethvec(0x1200, tlbvec);
658
/* */
659
	dcflush(KADDR(0), 0x2000);
660
	icflush(KADDR(0), 0x2000);
661
 
662
	putmsr(getmsr() & ~MSR_IP);
663
}
664
 
665
void
666
reboot(void*, void*, ulong)
667
{
668
	ulong *p;
669
	int x;
670
 
671
	p = (ulong*)0x90000000;
672
	x = splhi();
673
	iomem->sypcr |= 0xc0;
674
	print("iomem->sypcr = 0x%lux\n", iomem->sypcr);
675
	*p = 0;
676
	print("still alive\n");
677
	splx(x);
678
}