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