Home | History | Annotate | Line # | Download | only in altboot
brdsetup.c revision 1.23
      1 /* $NetBSD: brdsetup.c,v 1.23 2011/11/12 23:52:54 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 void 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 50C, turn off at 45C */
    698 	send_iomega('b', 'd', 2, 'a', 50, 45);
    699 }
    700 
    701 void
    702 iomegareset()
    703 {
    704 
    705 	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 void
    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(50000);
    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 	buf[IOMEGA_POWER] = power;
    939 	buf[IOMEGA_LED] = led;
    940 	buf[IOMEGA_FLASH_RATE] = rate;
    941 	buf[IOMEGA_FAN] = fan;
    942 	buf[IOMEGA_HIGH_TEMP] = high;
    943 	buf[IOMEGA_LOW_TEMP] = low;
    944 	buf[IOMEGA_ID] = 7;	/* host id */
    945 	buf[IOMEGA_CHECKSUM] = (buf[IOMEGA_POWER] + buf[IOMEGA_LED] +
    946 	    buf[IOMEGA_FLASH_RATE] + buf[IOMEGA_FAN] +
    947 	    buf[IOMEGA_HIGH_TEMP] + buf[IOMEGA_LOW_TEMP] +
    948 	    buf[IOMEGA_ID]) & 0x7f;
    949 #ifdef DEBUG
    950 	uart1base = savedbase;
    951 	iomega_debug("G2 sending", buf);
    952 	uart1base = uart2base;
    953 #endif
    954 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
    955 		putchar(buf[i]);
    956 
    957 	/* receive the reply */
    958 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
    959 		buf[i] = getchar();
    960 #ifdef DEBUG
    961 	uart1base = savedbase;
    962 	iomega_debug("68HC908 reply", buf);
    963 	uart1base = uart2base;
    964 #endif
    965 
    966 	if (buf[0] == '#')
    967 		goto again;  /* try again on error */
    968 	uart1base = savedbase;
    969 }
    970 
    971 void
    972 putchar(int c)
    973 {
    974 	unsigned timo, lsr;
    975 
    976 	if (c == '\n')
    977 		putchar('\r');
    978 
    979 	timo = 0x00100000;
    980 	do {
    981 		lsr = UART_READ(uart1base, LSR);
    982 	} while (timo-- > 0 && (lsr & LSR_THRE) == 0);
    983 	if (timo > 0)
    984 		UART_WRITE(uart1base, THR, c);
    985 }
    986 
    987 int
    988 getchar(void)
    989 {
    990 	unsigned lsr;
    991 
    992 	do {
    993 		lsr = UART_READ(uart1base, LSR);
    994 	} while ((lsr & LSR_DRDY) == 0);
    995 	return UART_READ(uart1base, RBR);
    996 }
    997 
    998 int
    999 tstchar(void)
   1000 {
   1001 
   1002 	return (UART_READ(uart1base, LSR) & LSR_DRDY) != 0;
   1003 }
   1004 
   1005 unsigned
   1006 mpc107memsize()
   1007 {
   1008 	unsigned bankn, end, n, tag, val;
   1009 
   1010 	tag = pcimaketag(0, 0, 0);
   1011 
   1012 	if (brdtype == BRD_ENCOREPP1) {
   1013 		/* the brd's PPCBOOT looks to have erroneous values */
   1014 		unsigned tbl[] = {
   1015 #define MPC106_MEMSTARTADDR1	0x80
   1016 #define MPC106_EXTMEMSTARTADDR1	0x88
   1017 #define MPC106_MEMENDADDR1	0x90
   1018 #define MPC106_EXTMEMENDADDR1	0x98
   1019 #define MPC106_MEMEN		0xa0
   1020 #define	BK0_S	0x00000000
   1021 #define	BK0_E	(128 << 20) - 1
   1022 #define BK1_S	0x3ff00000
   1023 #define BK1_E	0x3fffffff
   1024 #define BK2_S	0x3ff00000
   1025 #define BK2_E	0x3fffffff
   1026 #define BK3_S	0x3ff00000
   1027 #define BK3_E	0x3fffffff
   1028 #define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s))
   1029 #define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s))
   1030 #define SAR_MASK 0x0ff00000
   1031 #define SAR_SHIFT    20
   1032 #define EAR_MASK 0x30000000
   1033 #define EAR_SHIFT    28
   1034 		AR(BK0_S, 0) | AR(BK1_S, 8) | AR(BK2_S, 16) | AR(BK3_S, 24),
   1035 		XR(BK0_S, 0) | XR(BK1_S, 8) | XR(BK2_S, 16) | XR(BK3_S, 24),
   1036 		AR(BK0_E, 0) | AR(BK1_E, 8) | AR(BK2_E, 16) | AR(BK3_E, 24),
   1037 		XR(BK0_E, 0) | XR(BK1_E, 8) | XR(BK2_E, 16) | XR(BK3_E, 24),
   1038 		};
   1039 		tag = pcimaketag(0, 0, 0);
   1040 		pcicfgwrite(tag, MPC106_MEMSTARTADDR1, tbl[0]);
   1041 		pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, tbl[1]);
   1042 		pcicfgwrite(tag, MPC106_MEMENDADDR1, tbl[2]);
   1043 		pcicfgwrite(tag, MPC106_EXTMEMENDADDR1,	tbl[3]);
   1044 		pcicfgwrite(tag, MPC106_MEMEN, 1);
   1045 	}
   1046 
   1047 	bankn = 0;
   1048 	val = pcicfgread(tag, MPC106_MEMEN);
   1049 	for (n = 0; n < 4; n++) {
   1050 		if ((val & (1U << n)) == 0)
   1051 			break;
   1052 		bankn = n;
   1053 	}
   1054 	bankn = bankn * 8;
   1055 
   1056 	val = pcicfgread(tag, MPC106_EXTMEMENDADDR1);
   1057 	end =  ((val >> bankn) & 0x03) << 28;
   1058 	val = pcicfgread(tag, MPC106_MEMENDADDR1);
   1059 	end |= ((val >> bankn) & 0xff) << 20;
   1060 	end |= 0xfffff;
   1061 
   1062 	return (end + 1); /* assume the end address matches total amount */
   1063 }
   1064 
   1065 struct fis_dir_entry {
   1066 	char		name[16];
   1067 	uint32_t	startaddr;
   1068 	uint32_t	loadaddr;
   1069 	uint32_t	flashsize;
   1070 	uint32_t	entryaddr;
   1071 	uint32_t	filesize;
   1072 	char		pad[256 - (16 + 5 * sizeof(uint32_t))];
   1073 };
   1074 
   1075 #define FIS_LOWER_LIMIT	0xfff00000
   1076 
   1077 /*
   1078  * Look for a Redboot-style Flash Image System FIS-directory and
   1079  * return a pointer to the start address of the requested file.
   1080  */
   1081 static void *
   1082 redboot_fis_lookup(const char *filename)
   1083 {
   1084 	static const char FISdirname[16] = {
   1085 	    'F', 'I', 'S', ' ',
   1086 	    'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0
   1087 	};
   1088 	struct fis_dir_entry *dir;
   1089 
   1090 	/*
   1091 	 * The FIS directory is usually in the last sector of the flash.
   1092 	 * But we do not know the sector size (erase size), so start
   1093 	 * at 0xffffff00 and scan backwards in steps of the FIS directory
   1094 	 * entry size (0x100).
   1095 	 */
   1096 	for (dir = (struct fis_dir_entry *)0xffffff00;
   1097 	    (uint32_t)dir >= FIS_LOWER_LIMIT; dir--)
   1098 		if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0)
   1099 			break;
   1100 	if ((uint32_t)dir < FIS_LOWER_LIMIT) {
   1101 		printf("No FIS directory found!\n");
   1102 		return NULL;
   1103 	}
   1104 
   1105 	/* Now find filename by scanning the directory from beginning. */
   1106 	dir = (struct fis_dir_entry *)dir->startaddr;
   1107 	while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) {
   1108 		if (strcmp(dir->name, filename) == 0)
   1109 			return (void *)dir->startaddr;	/* found */
   1110 		dir++;
   1111 	}
   1112 	printf("\"%s\" not found in FIS directory!\n", filename);
   1113 	return NULL;
   1114 }
   1115 
   1116 static void
   1117 read_mac_string(uint8_t *mac, char *p)
   1118 {
   1119 	int i;
   1120 
   1121 	for (i = 0; i < 6; i++, p += 3)
   1122 		*mac++ = read_hex(p);
   1123 }
   1124 
   1125 /*
   1126  * For cost saving reasons some NAS boxes lack SEEPROM for NIC's
   1127  * ethernet address and keep it in their Flash memory instead.
   1128  */
   1129 void
   1130 read_mac_from_flash(uint8_t *mac)
   1131 {
   1132 	uint8_t *p;
   1133 
   1134 	switch (brdtype) {
   1135 	case BRD_SYNOLOGY:
   1136 		p = redboot_fis_lookup("vendor");
   1137 		if (p == NULL)
   1138 			break;
   1139 		memcpy(mac, p, 6);
   1140 		return;
   1141 	case BRD_DLINKDSM:
   1142 		read_mac_string(mac, (char *)0xfff0ff80);
   1143 		return;
   1144 	default:
   1145 		printf("Warning: This board has no known method defined "
   1146 		    "to determine its MAC address!\n");
   1147 		break;
   1148 	}
   1149 
   1150 	/* set to 00:00:00:00:00:00 in case of error */
   1151 	memset(mac, 0, 6);
   1152 }
   1153 
   1154 #ifdef DEBUG
   1155 void
   1156 sat_write(char *p, int len)
   1157 {
   1158 	unsigned savedbase;
   1159 
   1160 	savedbase = uart1base;
   1161 	uart1base = uart2base;
   1162 	while (len--)
   1163 		putchar(*p++);
   1164 	uart1base = savedbase;
   1165 }
   1166 
   1167 int
   1168 sat_getch(void)
   1169 {
   1170 	unsigned lsr;
   1171 
   1172 	do {
   1173 		lsr = UART_READ(uart2base, LSR);
   1174 	} while ((lsr & LSR_DRDY) == 0);
   1175 	return UART_READ(uart2base, RBR);
   1176 }
   1177 
   1178 int
   1179 sat_tstch(void)
   1180 {
   1181 
   1182 	return (UART_READ(uart2base, LSR) & LSR_DRDY) != 0;
   1183 }
   1184 #endif /* DEBUG */
   1185