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