xref: /netbsd-src/sys/arch/sandpoint/stand/altboot/brdsetup.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /* $NetBSD: brdsetup.c,v 1.22 2011/11/07 21:11:55 phx Exp $ */
2 
3 /*-
4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Tohru Nishimura.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/param.h>
33 
34 #include <powerpc/psl.h>
35 #include <powerpc/oea/spr.h>
36 
37 #include <lib/libsa/stand.h>
38 #include <lib/libsa/net.h>
39 #include <lib/libkern/libkern.h>
40 
41 #include <machine/bootinfo.h>
42 
43 #include "globals.h"
44 
45 #define BRD_DECL(xxx) \
46     void xxx ## setup(struct brdprop *); \
47     void xxx ## brdfix(struct brdprop *); \
48     void xxx ## pcifix(struct brdprop *); \
49     void xxx ## reset(void)
50 
51 BRD_DECL(mot);
52 BRD_DECL(enc);
53 BRD_DECL(kuro);
54 BRD_DECL(syno);
55 BRD_DECL(qnap);
56 BRD_DECL(iomega);
57 BRD_DECL(dlink);
58 BRD_DECL(nhnas);
59 
60 static struct brdprop brdlist[] = {
61     {
62 	"sandpoint",
63 	"Sandpoint X3",
64 	BRD_SANDPOINTX3,
65 	0,
66 	"com", 0x3f8, 115200,
67 	motsetup, motbrdfix, motpcifix, NULL },
68     {
69 	"encpp1",
70 	"EnCore PP1",
71 	BRD_ENCOREPP1,
72 	0,
73 	"com", 0x3f8, 115200,
74 	encsetup, encbrdfix, encpcifix, NULL },
75     {
76 	"kurobox",
77 	"KuroBox",
78 	BRD_KUROBOX,
79 	32768000,
80 	"eumb", 0x4600, 57600,
81 	kurosetup, kurobrdfix, NULL, NULL },
82     {
83 	"synology",
84 	"Synology DS",
85 	BRD_SYNOLOGY,
86 	33164691,	/* from Synology/Linux source            */
87 			/* XXX should be 33165343 for the CS-406 */
88 	"eumb", 0x4500, 115200,
89 	NULL, synobrdfix, NULL, synoreset },
90     {
91 	"qnap",
92 	"QNAP TS",
93 	BRD_QNAPTS,
94 	33164691,	/* Linux source says 33000000, but the Synology  */
95 			/* clock value delivers a much better precision. */
96 	"eumb", 0x4500, 115200,
97 	NULL, qnapbrdfix, NULL, qnapreset },
98     {
99 	"iomega",
100 	"IOMEGA StorCenter G2",
101 	BRD_STORCENTER,
102 	0,
103 	"eumb", 0x4500, 115200,
104 	NULL, iomegabrdfix, NULL, iomegareset },
105     {
106 	"dlink",
107 	"D-Link DSM-G600",
108 	BRD_DLINKDSM,
109 	33000000,
110 	"eumb", 0x4500, 9600,
111 	NULL, dlinkbrdfix, NULL, NULL },
112     {
113 	"nhnas",
114 	"Netronics NH230/231",
115 	BRD_NH230NAS,
116 	0,
117 	"eumb", 0x4500, 9600,
118 	NULL, nhnasbrdfix, NULL, NULL },
119     {
120 	"unknown",
121 	"Unknown board",
122 	BRD_UNKNOWN,
123 	0,
124 	"eumb", 0x4500, 115200,
125 	NULL, NULL, NULL, NULL }, /* must be the last */
126 };
127 
128 /* Iomega StorCenter MC68HC908 microcontroller data packet */
129 #define IOMEGA_POWER		0
130 #define IOMEGA_LED		1
131 #define IOMEGA_FLASH_RATE	2
132 #define IOMEGA_FAN		3
133 #define IOMEGA_HIGH_TEMP	4
134 #define IOMEGA_LOW_TEMP		5
135 #define IOMEGA_ID		6
136 #define IOMEGA_CHECKSUM		7
137 #define IOMEGA_PACKETSIZE	8
138 
139 static struct brdprop *brdprop;
140 static uint32_t ticks_per_sec, ns_per_tick;
141 
142 static void brdfixup(void);
143 static void setup(void);
144 static int send_iomega(int, int, int, int, int, int);
145 static inline uint32_t mfmsr(void);
146 static inline void mtmsr(uint32_t);
147 static inline uint32_t cputype(void);
148 static inline u_quad_t mftb(void);
149 static void init_uart(unsigned, unsigned, uint8_t);
150 static void send_sat(char *);
151 
152 const unsigned dcache_line_size = 32;		/* 32B linesize */
153 const unsigned dcache_range_size = 4 * 1024;	/* 16KB / 4-way */
154 
155 unsigned uart1base;	/* console */
156 unsigned uart2base;	/* optional satellite processor */
157 #define RBR		0
158 #define THR		0
159 #define DLB		0
160 #define DMB		1
161 #define IER		1
162 #define FCR		2
163 #define LCR		3
164 #define  LCR_DLAB	0x80
165 #define  LCR_PEVEN	0x18
166 #define  LCR_PNONE	0x00
167 #define  LCR_8BITS	0x03
168 #define MCR		4
169 #define  MCR_RTS	0x02
170 #define  MCR_DTR	0x01
171 #define LSR		5
172 #define  LSR_THRE	0x20
173 #define  LSR_DRDY	0x01
174 #define DCR		0x11
175 #define UART_READ(base, r)	in8(base + (r))
176 #define UART_WRITE(base, r, v)	out8(base + (r), (v))
177 
178 void brdsetup(void);	/* called by entry.S */
179 
180 void
181 brdsetup(void)
182 {
183 	static uint8_t pci_to_memclk[] = {
184 		30, 30, 10, 10, 20, 10, 10, 10,
185 		10, 20, 20, 15, 20, 15, 20, 30,
186 		30, 40, 15, 40, 20, 25, 20, 40,
187 		25, 20, 10, 20, 15, 15, 20, 00
188 	};
189 	static uint8_t mem_to_cpuclk[] = {
190 		25, 30, 45, 20, 20, 00, 10, 30,
191 		30, 20, 45, 30, 25, 35, 30, 35,
192 		20, 25, 20, 30, 35, 40, 40, 20,
193 		30, 25, 40, 30, 30, 25, 35, 00
194 	};
195 	char *consname;
196 	int consport;
197 	uint32_t extclk;
198 	unsigned pchb, pcib, dev11, dev13, dev15, dev16, val;
199 	extern struct btinfo_memory bi_mem;
200 	extern struct btinfo_console bi_cons;
201 	extern struct btinfo_clock bi_clk;
202 	extern struct btinfo_prodfamily bi_fam;
203 
204 	/*
205 	 * CHRP specification "Map-B" BAT012 layout
206 	 *   BAT0 0000-0000 (256MB) SDRAM
207 	 *   BAT1 8000-0000 (256MB) PCI mem space
208 	 *   BAT2 fc00-0000 (64MB)  EUMB, PCI I/O space, misc devs, flash
209 	 *
210 	 * EUMBBAR is at fc00-0000.
211 	 */
212 	pchb = pcimaketag(0, 0, 0);
213 	pcicfgwrite(pchb, 0x78, 0xfc000000);
214 
215 	brdtype = BRD_UNKNOWN;
216 	extclk = EXT_CLK_FREQ;	/* usually 33MHz */
217 	busclock = 0;
218 
219 	dev11 = pcimaketag(0, 11, 0);
220 	dev13 = pcimaketag(0, 13, 0);
221 	dev15 = pcimaketag(0, 15, 0);
222 	dev16 = pcimaketag(0, 16, 0);
223 
224 	if (pcifinddev(0x10ad, 0x0565, &pcib) == 0) {
225 		/* WinBond 553 southbridge at dev 11 */
226 		brdtype = BRD_SANDPOINTX3;
227 	}
228 	else if (pcifinddev(0x1106, 0x0686, &pcib) == 0) {
229 		/* VIA 686B southbridge at dev 22 */
230 		brdtype = BRD_ENCOREPP1;
231 	}
232 	else if (PCI_CLASS(pcicfgread(dev11, PCI_CLASS_REG)) == PCI_CLASS_ETH) {
233 		/* ADMtek AN985 (tlp) or RealTek 8169S (re) at dev 11 */
234 		brdtype = BRD_KUROBOX;
235 	}
236 	else if (PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x11ab) {
237 		/* SKnet/Marvell (sk) at dev 15 */
238 		brdtype = BRD_SYNOLOGY;
239 	}
240 	else if (PCI_VENDOR(pcicfgread(dev13, PCI_ID_REG)) == 0x1106) {
241 		/* VIA 6410 (viaide) at dev 13 */
242 		brdtype = BRD_STORCENTER;
243 	}
244 	else if (PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1191) {
245 		/* ACARD ATP865 (acardide) at dev 16 */
246 		brdtype = BRD_DLINKDSM;
247 	}
248 	else if (PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1283
249 	    || PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1095) {
250 		/* ITE (iteide) or SiI (satalink) at dev 16 */
251 		brdtype = BRD_NH230NAS;
252 	}
253 	else if (PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x8086
254 	    || PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x10ec) {
255 		/* Intel (wm) or RealTek (re) at dev 15 */
256 		brdtype = BRD_QNAPTS;
257 	}
258 
259 	brdprop = brd_lookup(brdtype);
260 
261 	/* brd dependent adjustments */
262 	setup();
263 
264 	/* determine clock frequencies */
265 	if (brdprop->extclk != 0)
266 		extclk = brdprop->extclk;
267 	if (busclock == 0) {
268 		if (cputype() == MPC8245) {
269 			/* PLL_CFG from PCI host bridge register 0xe2 */
270 			val = pcicfgread(pchb, 0xe0);
271 			busclock = (extclk *
272 			    pci_to_memclk[(val >> 19) & 0x1f] + 10) / 10;
273 			/* PLLRATIO from HID1 */
274 			asm volatile ("mfspr %0,1009" : "=r"(val));
275 			cpuclock = ((uint64_t)busclock *
276 			    mem_to_cpuclk[val >> 27] + 10) / 10;
277 		} else
278 			busclock = 100000000;	/* 100MHz bus clock default */
279 	}
280 	ticks_per_sec = busclock >> 2;
281 	ns_per_tick = 1000000000 / ticks_per_sec;
282 
283 	/* now prepare serial console */
284 	consname = brdprop->consname;
285 	consport = brdprop->consport;
286 	if (strcmp(consname, "eumb") == 0) {
287 		uart1base = 0xfc000000 + consport;	/* 0x4500, 0x4600 */
288 		UART_WRITE(uart1base, DCR, 0x01);	/* enable DUART mode */
289 		uart2base = uart1base ^ 0x0300;
290 	} else
291 		uart1base = 0xfe000000 + consport;	/* 0x3f8, 0x2f8 */
292 
293 	/* more brd adjustments */
294 	brdfixup();
295 
296 	bi_mem.memsize = mpc107memsize();
297 	snprintf(bi_cons.devname, sizeof(bi_cons.devname), consname);
298 	bi_cons.addr = consport;
299 	bi_cons.speed = brdprop->consspeed;
300 	bi_clk.ticks_per_sec = ticks_per_sec;
301 	snprintf(bi_fam.name, sizeof(bi_fam.name), brdprop->family);
302 }
303 
304 struct brdprop *
305 brd_lookup(int brd)
306 {
307 	u_int i;
308 
309 	for (i = 0; i < sizeof(brdlist)/sizeof(brdlist[0]); i++) {
310 		if (brdlist[i].brdtype == brd)
311 			return &brdlist[i];
312 	}
313 	return &brdlist[i - 1];
314 }
315 
316 static void
317 setup()
318 {
319 
320 	if (brdprop->setup == NULL)
321 		return;
322 	(*brdprop->setup)(brdprop);
323 }
324 
325 static void
326 brdfixup()
327 {
328 
329 	if (brdprop->brdfix == NULL)
330 		return;
331 	(*brdprop->brdfix)(brdprop);
332 }
333 
334 void
335 pcifixup()
336 {
337 
338 	if (brdprop->pcifix == NULL)
339 		return;
340 	(*brdprop->pcifix)(brdprop);
341 }
342 
343 void
344 encsetup(struct brdprop *brd)
345 {
346 
347 #ifdef COSNAME
348 	brd->consname = CONSNAME;
349 #endif
350 #ifdef CONSPORT
351 	brd->consport = CONSPORT;
352 #endif
353 #ifdef CONSSPEED
354 	brd->consspeed = CONSSPEED;
355 #endif
356 }
357 
358 void
359 encbrdfix(struct brdprop *brd)
360 {
361 	unsigned ac97, ide, pcib, pmgt, usb12, usb34, val;
362 
363 /*
364  * VIA82C686B Southbridge
365  *	0.22.0	1106.0686	PCI-ISA bridge
366  *	0.22.1	1106.0571	IDE (viaide)
367  *	0.22.2	1106.3038	USB 0/1 (uhci)
368  *	0.22.3	1106.3038	USB 2/3 (uhci)
369  *	0.22.4	1106.3057	power management
370  *	0.22.5	1106.3058	AC97 (auvia)
371  */
372 	pcib  = pcimaketag(0, 22, 0);
373 	ide   = pcimaketag(0, 22, 1);
374 	usb12 = pcimaketag(0, 22, 2);
375 	usb34 = pcimaketag(0, 22, 3);
376 	pmgt  = pcimaketag(0, 22, 4);
377 	ac97  = pcimaketag(0, 22, 5);
378 
379 #define	CFG(i,v) do { \
380    *(volatile unsigned char *)(0xfe000000 + 0x3f0) = (i); \
381    *(volatile unsigned char *)(0xfe000000 + 0x3f1) = (v); \
382    } while (0)
383 	val = pcicfgread(pcib, 0x84);
384 	val |= (02 << 8);
385 	pcicfgwrite(pcib, 0x84, val);
386 	CFG(0xe2, 0x0f); /* use COM1/2, don't use FDC/LPT */
387 	val = pcicfgread(pcib, 0x84);
388 	val &= ~(02 << 8);
389 	pcicfgwrite(pcib, 0x84, val);
390 
391 	/* route pin C to i8259 IRQ 5, pin D to 11 */
392 	val = pcicfgread(pcib, 0x54);
393 	val = (val & 0xff) | 0xb0500000; /* Dx CB Ax xS */
394 	pcicfgwrite(pcib, 0x54, val);
395 
396 	/* enable EISA ELCR1 (0x4d0) and ELCR2 (0x4d1) */
397 	val = pcicfgread(pcib, 0x44);
398 	val = val | 0x20000000;
399 	pcicfgwrite(pcib, 0x44, val);
400 
401 	/* select level trigger for IRQ 5/11 at ELCR1/2 */
402 	*(volatile uint8_t *)0xfe0004d0 = 0x20; /* bit 5 */
403 	*(volatile uint8_t *)0xfe0004d1 = 0x08; /* bit 11 */
404 
405 	/* USB and AC97 are hardwired with pin D and C */
406 	val = pcicfgread(usb12, 0x3c) &~ 0xff;
407 	val |= 11;
408 	pcicfgwrite(usb12, 0x3c, val);
409 	val = pcicfgread(usb34, 0x3c) &~ 0xff;
410 	val |= 11;
411 	pcicfgwrite(usb34, 0x3c, val);
412 	val = pcicfgread(ac97, 0x3c) &~ 0xff;
413 	val |= 5;
414 	pcicfgwrite(ac97, 0x3c, val);
415 }
416 
417 void
418 encpcifix(struct brdprop *brd)
419 {
420 	unsigned ide, irq, net, pcib, steer, val;
421 
422 #define	STEER(v, b) (((v) & (b)) ? "edge" : "level")
423 	pcib = pcimaketag(0, 22, 0);
424 	ide  = pcimaketag(0, 22, 1);
425 	net  = pcimaketag(0, 25, 0);
426 
427 	/*
428 	 * //// VIA PIRQ ////
429 	 * 0x57/56/55/54 - Dx CB Ax xS
430 	 */
431 	val = pcicfgread(pcib, 0x54);	/* Dx CB Ax xs */
432 	steer = val & 0xf;
433 	irq = (val >> 12) & 0xf;	/* 15:12 */
434 	if (irq) {
435 		printf("pin A -> irq %d, %s\n",
436 			irq, STEER(steer, 0x1));
437 	}
438 	irq = (val >> 16) & 0xf;	/* 19:16 */
439 	if (irq) {
440 		printf("pin B -> irq %d, %s\n",
441 			irq, STEER(steer, 0x2));
442 	}
443 	irq = (val >> 20) & 0xf;	/* 23:20 */
444 	if (irq) {
445 		printf("pin C -> irq %d, %s\n",
446 			irq, STEER(steer, 0x4));
447 	}
448 	irq = (val >> 28);		/* 31:28 */
449 	if (irq) {
450 		printf("pin D -> irq %d, %s\n",
451 			irq, STEER(steer, 0x8));
452 	}
453 #if 0
454 	/*
455 	 * //// IDE fixup ////
456 	 * - "native mode" (ide 0x09)
457 	 */
458 
459 	/* ide: 0x09 - programming interface; 1000'SsPp */
460 	val = pcicfgread(ide, 0x08) & 0xffff00ff;
461 	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
462 
463 	/* ide: 0x10-20 - leave them PCI memory space assigned */
464 #else
465 	/*
466 	 * //// IDE fixup ////
467 	 * - "compatiblity mode" (ide 0x09)
468 	 * - remove PCI pin assignment (ide 0x3d)
469 	 */
470 
471 	/* ide: 0x09 - programming interface; 1000'SsPp */
472 	val = pcicfgread(ide, 0x08) & 0xffff00ff;
473 	val |= (0x8a << 8);
474 	pcicfgwrite(ide, 0x08, val);
475 
476 	/* ide: 0x10-20 */
477 	/*
478 	 * experiment shows writing ide: 0x09 changes these
479 	 * register behaviour. The pcicfgwrite() above writes
480 	 * 0x8a at ide: 0x09 to make sure legacy IDE.  Then
481 	 * reading BAR0-3 is to return value 0s even though
482 	 * pcisetup() has written range assignments.  Value
483 	 * overwrite makes no effect. Having 0x8f for native
484 	 * PCIIDE doesn't change register values and brings no
485 	 * weirdness.
486 	 */
487 
488 	/* ide: 0x3d/3c - turn off PCI pin */
489 	val = pcicfgread(ide, 0x3c) & 0xffff00ff;
490 	pcicfgwrite(ide, 0x3c, val);
491 #endif
492 	/*
493 	 * //// USBx2, audio, and modem fixup ////
494 	 * - disable USB #0 and #1 (pcib 0x48 and 0x85)
495 	 * - disable AC97 audio and MC97 modem (pcib 0x85)
496 	 */
497 
498 	/* pcib: 0x48 - disable USB #0 at function 2 */
499 	val = pcicfgread(pcib, 0x48);
500 	pcicfgwrite(pcib, 0x48, val | 04);
501 
502 	/* pcib: 0x85 - disable USB #1 at function 3 */
503 	/* pcib: 0x85 - disable AC97/MC97 at function 5/6 */
504 	val = pcicfgread(pcib, 0x84);
505 	pcicfgwrite(pcib, 0x84, val | 0x1c00);
506 
507 	/*
508 	 * //// fxp fixup ////
509 	 * - use PCI pin A line 25 (fxp 0x3d/3c)
510 	 */
511 	/* 0x3d/3c - PCI pin/line */
512 	val = pcicfgread(net, 0x3c) & 0xffff0000;
513 	val |= (('A' - '@') << 8) | 25;
514 	pcicfgwrite(net, 0x3c, val);
515 }
516 
517 void
518 motsetup(struct brdprop *brd)
519 {
520 
521 #ifdef COSNAME
522 	brd->consname = CONSNAME;
523 #endif
524 #ifdef CONSPORT
525 	brd->consport = CONSPORT;
526 #endif
527 #ifdef CONSSPEED
528 	brd->consspeed = CONSSPEED;
529 #endif
530 }
531 
532 void
533 motbrdfix(struct brdprop *brd)
534 {
535 
536 /*
537  * WinBond/Symphony Lab 83C553 with PC87308 "SuperIO"
538  *
539  *	0.11.0	10ad.0565	PCI-ISA bridge
540  *	0.11.1	10ad.0105	IDE (slide)
541  */
542 }
543 
544 void
545 motpcifix(struct brdprop *brd)
546 {
547 	unsigned ide, net, pcib, steer, val;
548 	int line;
549 
550 	pcib = pcimaketag(0, 11, 0);
551 	ide  = pcimaketag(0, 11, 1);
552 	net  = pcimaketag(0, 15, 0);
553 
554 	/*
555 	 * //// WinBond PIRQ ////
556 	 * 0x40 - bit 5 (0x20) indicates PIRQ presense
557 	 * 0x60 - PIRQ interrupt routing steer
558 	 */
559 	if (pcicfgread(pcib, 0x40) & 0x20) {
560 		steer = pcicfgread(pcib, 0x60);
561 		if ((steer & 0x80808080) == 0x80808080)
562 			printf("PIRQ[0-3] disabled\n");
563 		else {
564 			unsigned i, v = steer;
565 			for (i = 0; i < 4; i++, v >>= 8) {
566 				if ((v & 0x80) != 0 || (v & 0xf) == 0)
567 					continue;
568 				printf("PIRQ[%d]=%d\n", i, v & 0xf);
569 				}
570 			}
571 		}
572 #if 1
573 	/*
574 	 * //// IDE fixup -- case A ////
575 	 * - "native PCI mode" (ide 0x09)
576 	 * - don't use ISA IRQ14/15 (pcib 0x43)
577 	 * - native IDE for both channels (ide 0x40)
578 	 * - LEGIRQ bit 11 steers interrupt to pin C (ide 0x40)
579 	 * - sign as PCI pin C line 11 (ide 0x3d/3c)
580 	 */
581 	/* ide: 0x09 - programming interface; 1000'SsPp */
582 	val = pcicfgread(ide, 0x08);
583 	val &= 0xffff00ff;
584 	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
585 
586 	/* pcib: 0x43 - IDE interrupt routing */
587 	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
588 	pcicfgwrite(pcib, 0x40, val);
589 
590 	/* pcib: 0x45/44 - PCI interrupt routing */
591 	val = pcicfgread(pcib, 0x44) & 0xffff0000;
592 	pcicfgwrite(pcib, 0x44, val);
593 
594 	/* ide: 0x41/40 - IDE channel */
595 	val = pcicfgread(ide, 0x40) & 0xffff0000;
596 	val |= (1 << 11) | 0x33; /* LEGIRQ turns on PCI interrupt */
597 	pcicfgwrite(ide, 0x40, val);
598 
599 	/* ide: 0x3d/3c - use PCI pin C/line 11 */
600 	val = pcicfgread(ide, 0x3c) & 0xffffff00;
601 	val |= 11; /* pin designation is hardwired to pin A */
602 	pcicfgwrite(ide, 0x3c, val);
603 #else
604 	/*
605 	 * //// IDE fixup -- case B ////
606 	 * - "compatiblity mode" (ide 0x09)
607 	 * - IDE primary/secondary interrupt routing (pcib 0x43)
608 	 * - PCI interrupt routing (pcib 0x45/44)
609 	 * - no PCI pin/line assignment (ide 0x3d/3c)
610 	 */
611 	/* ide: 0x09 - programming interface; 1000'SsPp */
612 	val = pcicfgread(ide, 0x08);
613 	val &= 0xffff00ff;
614 	pcicfgwrite(ide, 0x08, val | (0x8a << 8));
615 
616 	/* pcib: 0x43 - IDE interrupt routing */
617 	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
618 	pcicfgwrite(pcib, 0x40, val | (0xee << 24));
619 
620 	/* ide: 0x45/44 - PCI interrupt routing */
621 	val = pcicfgread(ide, 0x44) & 0xffff0000;
622 	pcicfgwrite(ide, 0x44, val);
623 
624 	/* ide: 0x3d/3c - turn off PCI pin/line */
625 	val = pcicfgread(ide, 0x3c) & 0xffff0000;
626 	pcicfgwrite(ide, 0x3c, val);
627 #endif
628 
629 	/*
630 	 * //// fxp fixup ////
631 	 * - use PCI pin A line 15 (fxp 0x3d/3c)
632 	 */
633 	val = pcicfgread(net, 0x3c) & 0xffff0000;
634 	pcidecomposetag(net, NULL, &line, NULL);
635 	val |= (('A' - '@') << 8) | line;
636 	pcicfgwrite(net, 0x3c, val);
637 }
638 
639 void
640 kurosetup(struct brdprop *brd)
641 {
642 
643 	if (PCI_VENDOR(pcicfgread(pcimaketag(0, 11, 0), PCI_ID_REG)) == 0x10ec)
644 		brd->extclk = 32768000; /* decr 2457600Hz */
645 	else
646 		brd->extclk = 32521333; /* decr 2439100Hz */
647 }
648 
649 void
650 kurobrdfix(struct brdprop *brd)
651 {
652 
653 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PEVEN);
654 	/* Stop Watchdog */
655 	send_sat("AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK");
656 }
657 
658 void
659 synobrdfix(struct brdprop *brd)
660 {
661 
662 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
663 	/* beep, power LED on, status LED off */
664 	send_sat("247");
665 }
666 
667 void
668 synoreset()
669 {
670 
671 	send_sat("C");
672 	/*NOTREACHED*/
673 }
674 
675 void
676 qnapbrdfix(struct brdprop *brd)
677 {
678 
679 	init_uart(uart2base, 19200, LCR_8BITS | LCR_PNONE);
680 	/* beep, status LED red */
681 	send_sat("PW");
682 }
683 
684 void
685 qnapreset()
686 {
687 
688 	send_sat("f");
689 	/*NOTREACHED*/
690 }
691 
692 void
693 iomegabrdfix(struct brdprop *brd)
694 {
695 
696 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
697 	/* LED flashing blue, fan auto, turn on at 60C, turn off at 50C */
698 	(void)send_iomega('b', 'd', 2, 'a', 60, 50);
699 }
700 
701 void
702 iomegareset()
703 {
704 
705 	(void)send_iomega('g', 0, 0, 0, 0, 0);
706 	/*NOTREACHED*/
707 }
708 
709 void
710 dlinkbrdfix(struct brdprop *brd)
711 {
712 
713 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
714 	send_sat("SYN\n");
715 	send_sat("ZWO\n");	/* power LED solid on */
716 }
717 
718 void
719 nhnasbrdfix(struct brdprop *brd)
720 {
721 
722 	/* illuminate LEDs */
723 }
724 
725 void
726 _rtt(void)
727 {
728 	uint32_t msr;
729 
730 	netif_shutdown_all();
731 
732 	if (brdprop->reset != NULL)
733 		(*brdprop->reset)();
734 	else {
735 		msr = mfmsr();
736 		msr &= ~PSL_EE;
737 		mtmsr(msr);
738 		asm volatile ("sync; isync");
739 		asm volatile("mtspr %0,%1" : : "K"(81), "r"(0));
740 		msr &= ~(PSL_ME | PSL_DR | PSL_IR);
741 		mtmsr(msr);
742 		asm volatile ("sync; isync");
743 		run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */
744 	}
745 	/*NOTREACHED*/
746 }
747 
748 satime_t
749 getsecs(void)
750 {
751 	u_quad_t tb = mftb();
752 
753 	return (tb / ticks_per_sec);
754 }
755 
756 /*
757  * Wait for about n microseconds (at least!).
758  */
759 void
760 delay(u_int n)
761 {
762 	u_quad_t tb;
763 	u_long scratch, tbh, tbl;
764 
765 	tb = mftb();
766 	tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
767 	tbh = tb >> 32;
768 	tbl = tb;
769 	asm volatile ("1: mftbu %0; cmpw %0,%1; blt 1b; bgt 2f; mftb %0; cmpw 0, %0,%2; blt 1b; 2:" : "=&r"(scratch) : "r"(tbh), "r"(tbl));
770 }
771 
772 void
773 _wb(uint32_t adr, uint32_t siz)
774 {
775 	uint32_t bnd;
776 
777 	asm volatile("eieio");
778 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
779 		asm volatile ("dcbst 0,%0" :: "r"(adr));
780 	asm volatile ("sync");
781 }
782 
783 void
784 _wbinv(uint32_t adr, uint32_t siz)
785 {
786 	uint32_t bnd;
787 
788 	asm volatile("eieio");
789 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
790 		asm volatile ("dcbf 0,%0" :: "r"(adr));
791 	asm volatile ("sync");
792 }
793 
794 void
795 _inv(uint32_t adr, uint32_t siz)
796 {
797 	uint32_t bnd, off;
798 
799 	off = adr & (dcache_line_size - 1);
800 	adr -= off;
801 	siz += off;
802 	asm volatile ("eieio");
803 	if (off != 0) {
804 		/* wbinv() leading unaligned dcache line */
805 		asm volatile ("dcbf 0,%0" :: "r"(adr));
806 		if (siz < dcache_line_size)
807 			goto done;
808 		adr += dcache_line_size;
809 		siz -= dcache_line_size;
810 	}
811 	bnd = adr + siz;
812 	off = bnd & (dcache_line_size - 1);
813 	if (off != 0) {
814 		/* wbinv() trailing unaligned dcache line */
815 		asm volatile ("dcbf 0,%0" :: "r"(bnd)); /* it's OK */
816 		if (siz < dcache_line_size)
817 			goto done;
818 		siz -= off;
819 	}
820 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) {
821 		/* inv() intermediate dcache lines if ever */
822 		asm volatile ("dcbi 0,%0" :: "r"(adr));
823 	}
824   done:
825 	asm volatile ("sync");
826 }
827 
828 static inline uint32_t
829 mfmsr(void)
830 {
831 	uint32_t msr;
832 
833 	asm volatile ("mfmsr %0" : "=r"(msr));
834 	return msr;
835 }
836 
837 static inline void
838 mtmsr(uint32_t msr)
839 {
840 	asm volatile ("mtmsr %0" : : "r"(msr));
841 }
842 
843 static inline uint32_t
844 cputype(void)
845 {
846 	uint32_t pvr;
847 
848 	asm volatile ("mfpvr %0" : "=r"(pvr));
849 	return pvr >> 16;
850 }
851 
852 static inline u_quad_t
853 mftb(void)
854 {
855 	u_long scratch;
856 	u_quad_t tb;
857 
858 	asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b"
859 	    : "=r"(tb), "=r"(scratch));
860 	return tb;
861 }
862 
863 static void
864 init_uart(unsigned base, unsigned speed, uint8_t lcr)
865 {
866 	unsigned div;
867 
868 	div = busclock / speed / 16;
869 	UART_WRITE(base, LCR, 0x80);		/* turn on DLAB bit */
870 	UART_WRITE(base, FCR, 0x00);
871 	UART_WRITE(base, DMB, div >> 8);	/* set speed */
872 	UART_WRITE(base, DLB, div & 0xff);
873 	UART_WRITE(base, LCR, lcr);
874 	UART_WRITE(base, FCR, 0x07);		/* FIFO on, TXRX FIFO reset */
875 	UART_WRITE(base, IER, 0x00);		/* make sure INT disabled */
876 }
877 
878 /* talk to satellite processor */
879 static void
880 send_sat(char *msg)
881 {
882 	unsigned savedbase;
883 
884 	savedbase = uart1base;
885 	uart1base = uart2base;
886 	while (*msg)
887 		putchar(*msg++);
888 	uart1base = savedbase;
889 }
890 
891 #ifdef DEBUG
892 static void
893 iomega_debug(const char *txt, uint8_t buf[])
894 {
895 	int i;
896 
897 	printf("%s:", txt);
898 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
899 		printf(" %02x", buf[i]);
900 	putchar('\n');
901 }
902 #endif /* DEBUG */
903 
904 static int
905 send_iomega(int power, int led, int rate, int fan, int high, int low)
906 {
907 	uint8_t buf[IOMEGA_PACKETSIZE];
908 	unsigned i, savedbase;
909 
910 	savedbase = uart1base;
911 	uart1base = uart2base;
912 
913 	/* first flush the receive buffer */
914   again:
915 	while (tstchar())
916 		(void)getchar();
917 	delay(20000);
918 	if (tstchar())
919 		goto again;
920 	/*
921 	 * Now synchronize the transmitter by sending 0x00
922 	 * until we receive a status reply.
923 	 */
924 	do {
925 		putchar(0);
926 		delay(25000);
927 	} while (!tstchar());
928 
929 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
930 		buf[i] = getchar();
931 #ifdef DEBUG
932 	uart1base = savedbase;
933 	iomega_debug("68HC908 status", buf);
934 	uart1base = uart2base;
935 #endif
936 
937 	/* send command */
938 	if (power >= 0)
939 		buf[IOMEGA_POWER] = power;
940 	if (led >= 0)
941 		buf[IOMEGA_LED] = led;
942 	if (rate >= 0)
943 		buf[IOMEGA_FLASH_RATE] = rate;
944 	if (fan >= 0)
945 		buf[IOMEGA_FAN] = fan;
946 	if (high >= 0)
947 		buf[IOMEGA_HIGH_TEMP] = high;
948 	if (low >= 0)
949 		buf[IOMEGA_LOW_TEMP] = low;
950 	buf[IOMEGA_ID] = 7;	/* host id */
951 	buf[IOMEGA_CHECKSUM] = (buf[IOMEGA_POWER] + buf[IOMEGA_LED] +
952 	    buf[IOMEGA_FLASH_RATE] + buf[IOMEGA_FAN] +
953 	    buf[IOMEGA_HIGH_TEMP] + buf[IOMEGA_LOW_TEMP] +
954 	    buf[IOMEGA_ID]) & 0x7f;
955 #ifdef DEBUG
956 	uart1base = savedbase;
957 	iomega_debug("G2 sending", buf);
958 	uart1base = uart2base;
959 #endif
960 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
961 		putchar(buf[i]);
962 
963 	/* receive the reply */
964 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
965 		buf[i] = getchar();
966 
967 	uart1base = savedbase;
968 #ifdef DEBUG
969 	iomega_debug("68HC908 reply", buf);
970 #endif
971 	return buf[0] != '#';  /* error? */
972 }
973 
974 void
975 putchar(int c)
976 {
977 	unsigned timo, lsr;
978 
979 	if (c == '\n')
980 		putchar('\r');
981 
982 	timo = 0x00100000;
983 	do {
984 		lsr = UART_READ(uart1base, LSR);
985 	} while (timo-- > 0 && (lsr & LSR_THRE) == 0);
986 	if (timo > 0)
987 		UART_WRITE(uart1base, THR, c);
988 }
989 
990 int
991 getchar(void)
992 {
993 	unsigned lsr;
994 
995 	do {
996 		lsr = UART_READ(uart1base, LSR);
997 	} while ((lsr & LSR_DRDY) == 0);
998 	return UART_READ(uart1base, RBR);
999 }
1000 
1001 int
1002 tstchar(void)
1003 {
1004 
1005 	return (UART_READ(uart1base, LSR) & LSR_DRDY) != 0;
1006 }
1007 
1008 unsigned
1009 mpc107memsize()
1010 {
1011 	unsigned bankn, end, n, tag, val;
1012 
1013 	tag = pcimaketag(0, 0, 0);
1014 
1015 	if (brdtype == BRD_ENCOREPP1) {
1016 		/* the brd's PPCBOOT looks to have erroneous values */
1017 		unsigned tbl[] = {
1018 #define MPC106_MEMSTARTADDR1	0x80
1019 #define MPC106_EXTMEMSTARTADDR1	0x88
1020 #define MPC106_MEMENDADDR1	0x90
1021 #define MPC106_EXTMEMENDADDR1	0x98
1022 #define MPC106_MEMEN		0xa0
1023 #define	BK0_S	0x00000000
1024 #define	BK0_E	(128 << 20) - 1
1025 #define BK1_S	0x3ff00000
1026 #define BK1_E	0x3fffffff
1027 #define BK2_S	0x3ff00000
1028 #define BK2_E	0x3fffffff
1029 #define BK3_S	0x3ff00000
1030 #define BK3_E	0x3fffffff
1031 #define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s))
1032 #define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s))
1033 #define SAR_MASK 0x0ff00000
1034 #define SAR_SHIFT    20
1035 #define EAR_MASK 0x30000000
1036 #define EAR_SHIFT    28
1037 		AR(BK0_S, 0) | AR(BK1_S, 8) | AR(BK2_S, 16) | AR(BK3_S, 24),
1038 		XR(BK0_S, 0) | XR(BK1_S, 8) | XR(BK2_S, 16) | XR(BK3_S, 24),
1039 		AR(BK0_E, 0) | AR(BK1_E, 8) | AR(BK2_E, 16) | AR(BK3_E, 24),
1040 		XR(BK0_E, 0) | XR(BK1_E, 8) | XR(BK2_E, 16) | XR(BK3_E, 24),
1041 		};
1042 		tag = pcimaketag(0, 0, 0);
1043 		pcicfgwrite(tag, MPC106_MEMSTARTADDR1, tbl[0]);
1044 		pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, tbl[1]);
1045 		pcicfgwrite(tag, MPC106_MEMENDADDR1, tbl[2]);
1046 		pcicfgwrite(tag, MPC106_EXTMEMENDADDR1,	tbl[3]);
1047 		pcicfgwrite(tag, MPC106_MEMEN, 1);
1048 	}
1049 
1050 	bankn = 0;
1051 	val = pcicfgread(tag, MPC106_MEMEN);
1052 	for (n = 0; n < 4; n++) {
1053 		if ((val & (1U << n)) == 0)
1054 			break;
1055 		bankn = n;
1056 	}
1057 	bankn = bankn * 8;
1058 
1059 	val = pcicfgread(tag, MPC106_EXTMEMENDADDR1);
1060 	end =  ((val >> bankn) & 0x03) << 28;
1061 	val = pcicfgread(tag, MPC106_MEMENDADDR1);
1062 	end |= ((val >> bankn) & 0xff) << 20;
1063 	end |= 0xfffff;
1064 
1065 	return (end + 1); /* assume the end address matches total amount */
1066 }
1067 
1068 struct fis_dir_entry {
1069 	char		name[16];
1070 	uint32_t	startaddr;
1071 	uint32_t	loadaddr;
1072 	uint32_t	flashsize;
1073 	uint32_t	entryaddr;
1074 	uint32_t	filesize;
1075 	char		pad[256 - (16 + 5 * sizeof(uint32_t))];
1076 };
1077 
1078 #define FIS_LOWER_LIMIT	0xfff00000
1079 
1080 /*
1081  * Look for a Redboot-style Flash Image System FIS-directory and
1082  * return a pointer to the start address of the requested file.
1083  */
1084 static void *
1085 redboot_fis_lookup(const char *filename)
1086 {
1087 	static const char FISdirname[16] = {
1088 	    'F', 'I', 'S', ' ',
1089 	    'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0
1090 	};
1091 	struct fis_dir_entry *dir;
1092 
1093 	/*
1094 	 * The FIS directory is usually in the last sector of the flash.
1095 	 * But we do not know the sector size (erase size), so start
1096 	 * at 0xffffff00 and scan backwards in steps of the FIS directory
1097 	 * entry size (0x100).
1098 	 */
1099 	for (dir = (struct fis_dir_entry *)0xffffff00;
1100 	    (uint32_t)dir >= FIS_LOWER_LIMIT; dir--)
1101 		if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0)
1102 			break;
1103 	if ((uint32_t)dir < FIS_LOWER_LIMIT) {
1104 		printf("No FIS directory found!\n");
1105 		return NULL;
1106 	}
1107 
1108 	/* Now find filename by scanning the directory from beginning. */
1109 	dir = (struct fis_dir_entry *)dir->startaddr;
1110 	while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) {
1111 		if (strcmp(dir->name, filename) == 0)
1112 			return (void *)dir->startaddr;	/* found */
1113 		dir++;
1114 	}
1115 	printf("\"%s\" not found in FIS directory!\n", filename);
1116 	return NULL;
1117 }
1118 
1119 static void
1120 read_mac_string(uint8_t *mac, char *p)
1121 {
1122 	int i;
1123 
1124 	for (i = 0; i < 6; i++, p += 3)
1125 		*mac++ = read_hex(p);
1126 }
1127 
1128 /*
1129  * For cost saving reasons some NAS boxes lack SEEPROM for NIC's
1130  * ethernet address and keep it in their Flash memory instead.
1131  */
1132 void
1133 read_mac_from_flash(uint8_t *mac)
1134 {
1135 	uint8_t *p;
1136 
1137 	switch (brdtype) {
1138 	case BRD_SYNOLOGY:
1139 		p = redboot_fis_lookup("vendor");
1140 		if (p == NULL)
1141 			break;
1142 		memcpy(mac, p, 6);
1143 		return;
1144 	case BRD_DLINKDSM:
1145 		read_mac_string(mac, (char *)0xfff0ff80);
1146 		return;
1147 	default:
1148 		printf("Warning: This board has no known method defined "
1149 		    "to determine its MAC address!\n");
1150 		break;
1151 	}
1152 
1153 	/* set to 00:00:00:00:00:00 in case of error */
1154 	memset(mac, 0, 6);
1155 }
1156 
1157 #ifdef DEBUG
1158 void
1159 sat_write(char *p, int len)
1160 {
1161 	unsigned savedbase;
1162 
1163 	savedbase = uart1base;
1164 	uart1base = uart2base;
1165 	while (len--)
1166 		putchar(*p++);
1167 	uart1base = savedbase;
1168 }
1169 
1170 int
1171 sat_getch(void)
1172 {
1173 	unsigned lsr;
1174 
1175 	do {
1176 		lsr = UART_READ(uart2base, LSR);
1177 	} while ((lsr & LSR_DRDY) == 0);
1178 	return UART_READ(uart2base, RBR);
1179 }
1180 
1181 int
1182 sat_tstch(void)
1183 {
1184 
1185 	return (UART_READ(uart2base, LSR) & LSR_DRDY) != 0;
1186 }
1187 #endif /* DEBUG */
1188