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