Home | History | Annotate | Line # | Download | only in altboot
brdsetup.c revision 1.36
      1 /* $NetBSD: brdsetup.c,v 1.36 2015/09/30 14:14:32 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 ## launch(struct brdprop *); \
     50     void xxx ## reset(void)
     51 
     52 BRD_DECL(mot);
     53 BRD_DECL(enc);
     54 BRD_DECL(kuro);
     55 BRD_DECL(syno);
     56 BRD_DECL(qnap);
     57 BRD_DECL(iomega);
     58 BRD_DECL(dlink);
     59 BRD_DECL(nhnas);
     60 BRD_DECL(kurot4);
     61 
     62 static void brdfixup(void);
     63 static void setup(void);
     64 static void send_iomega(int, int, int, int, int, int);
     65 static inline uint32_t mfmsr(void);
     66 static inline void mtmsr(uint32_t);
     67 static inline uint32_t cputype(void);
     68 static inline u_quad_t mftb(void);
     69 static void init_uart(unsigned, unsigned, uint8_t);
     70 static void send_sat(char *);
     71 static unsigned mpc107memsize(void);
     72 
     73 /* UART registers */
     74 #define RBR		0
     75 #define THR		0
     76 #define DLB		0
     77 #define DMB		1
     78 #define IER		1
     79 #define FCR		2
     80 #define LCR		3
     81 #define  LCR_DLAB	0x80
     82 #define  LCR_PEVEN	0x18
     83 #define  LCR_PNONE	0x00
     84 #define  LCR_8BITS	0x03
     85 #define MCR		4
     86 #define  MCR_RTS	0x02
     87 #define  MCR_DTR	0x01
     88 #define LSR		5
     89 #define  LSR_THRE	0x20
     90 #define  LSR_DRDY	0x01
     91 #define DCR		0x11
     92 #define UART_READ(base, r)	in8(base + (r))
     93 #define UART_WRITE(base, r, v)	out8(base + (r), (v))
     94 
     95 /* MPC106 and MPC824x PCI bridge memory configuration */
     96 #define MPC106_MEMSTARTADDR1	0x80
     97 #define MPC106_EXTMEMSTARTADDR1	0x88
     98 #define MPC106_MEMENDADDR1	0x90
     99 #define MPC106_EXTMEMENDADDR1	0x98
    100 #define MPC106_MEMEN		0xa0
    101 
    102 /* Iomega StorCenter MC68HC908 microcontroller data packet */
    103 #define IOMEGA_POWER		0
    104 #define IOMEGA_LED		1
    105 #define IOMEGA_FLASH_RATE	2
    106 #define IOMEGA_FAN		3
    107 #define IOMEGA_HIGH_TEMP	4
    108 #define IOMEGA_LOW_TEMP		5
    109 #define IOMEGA_ID		6
    110 #define IOMEGA_CHECKSUM		7
    111 #define IOMEGA_PACKETSIZE	8
    112 
    113 /* NH230/231 GPIO */
    114 #define NHGPIO_WRITE(x)		*((volatile uint8_t *)0x70000000) = (x)
    115 
    116 /* Synology CPLD (2007 and newer models) */
    117 #define SYNOCPLD_READ(r)	*((volatile uint8_t *)0xff000000 + (r))
    118 #define SYNOCPLD_WRITE(r,x)	do { \
    119     *((volatile uint8_t *)0xff000000 + (r)) = (x); \
    120     delay(10); \
    121     } while(0)
    122 
    123 static struct brdprop brdlist[] = {
    124     {
    125 	"sandpoint",
    126 	"Sandpoint X3",
    127 	BRD_SANDPOINTX3,
    128 	0,
    129 	"com", 0x3f8, 115200,
    130 	motsetup, motbrdfix, motpcifix, NULL, NULL },
    131     {
    132 	"encpp1",
    133 	"EnCore PP1",
    134 	BRD_ENCOREPP1,
    135 	0,
    136 	"com", 0x3f8, 115200,
    137 	encsetup, encbrdfix, encpcifix, NULL, NULL },
    138     {
    139 	"kurobox",
    140 	"KuroBox",
    141 	BRD_KUROBOX,
    142 	0,
    143 	"eumb", 0x4600, 57600,
    144 	kurosetup, kurobrdfix, NULL, NULL, kuroreset },
    145     {
    146 	"synology",
    147 	"Synology CS/DS/RS",
    148 	BRD_SYNOLOGY,
    149 	0,
    150 	"eumb", 0x4500, 115200,
    151 	synosetup, synobrdfix, synopcifix, synolaunch, synoreset },
    152     {
    153 	"qnap",
    154 	"QNAP TS",
    155 	BRD_QNAPTS,
    156 	33164691,	/* Linux source says 33000000, but the Synology  */
    157 			/* clock value delivers a much better precision. */
    158 	"eumb", 0x4500, 115200,
    159 	NULL, qnapbrdfix, NULL, NULL, qnapreset },
    160     {
    161 	"iomega",
    162 	"IOMEGA StorCenter G2",
    163 	BRD_STORCENTER,
    164 	0,
    165 	"eumb", 0x4500, 115200,
    166 	NULL, iomegabrdfix, NULL, NULL, iomegareset },
    167     {
    168 	"dlink",
    169 	"D-Link DSM-G600",
    170 	BRD_DLINKDSM,
    171 	33000000,
    172 	"eumb", 0x4500, 9600,
    173 	NULL, dlinkbrdfix, NULL, NULL, NULL },
    174     {
    175 	"nhnas",
    176 	"Netronix NH-230/231",
    177 	BRD_NH230NAS,
    178 	33000000,
    179 	"eumb", 0x4500, 9600,
    180 	NULL, nhnasbrdfix, NULL, NULL, nhnasreset },
    181     {
    182 	"kurot4",
    183 	"KuroBox/T4",
    184 	BRD_KUROBOXT4,
    185 	32768000,
    186 	"eumb", 0x4600, 57600,
    187 	NULL, kurot4brdfix, NULL, NULL, NULL },
    188     {
    189 	"unknown",
    190 	"Unknown board",
    191 	BRD_UNKNOWN,
    192 	0,
    193 	"eumb", 0x4500, 115200,
    194 	NULL, NULL, NULL, NULL, NULL }, /* must be the last */
    195 };
    196 
    197 static struct brdprop *brdprop;
    198 static uint32_t ticks_per_sec, ns_per_tick;
    199 
    200 const unsigned dcache_line_size = 32;		/* 32B linesize */
    201 const unsigned dcache_range_size = 4 * 1024;	/* 16KB / 4-way */
    202 
    203 unsigned uart1base;	/* console */
    204 unsigned uart2base;	/* optional satellite processor */
    205 
    206 void brdsetup(void);	/* called by entry.S */
    207 
    208 void
    209 brdsetup(void)
    210 {
    211 	static uint8_t pci_to_memclk[] = {
    212 		30, 30, 10, 10, 20, 10, 10, 10,
    213 		10, 20, 20, 15, 20, 15, 20, 30,
    214 		30, 40, 15, 40, 20, 25, 20, 40,
    215 		25, 20, 10, 20, 15, 15, 20, 00
    216 	};
    217 	static uint8_t mem_to_cpuclk[] = {
    218 		25, 30, 45, 20, 20, 00, 10, 30,
    219 		30, 20, 45, 30, 25, 35, 30, 35,
    220 		20, 25, 20, 30, 35, 40, 40, 20,
    221 		30, 25, 40, 30, 30, 25, 35, 00
    222 	};
    223 	char *consname;
    224 	int consport;
    225 	uint32_t extclk;
    226 	unsigned pchb, pcib, dev11, dev12, dev13, dev15, dev16, val;
    227 	extern struct btinfo_memory bi_mem;
    228 	extern struct btinfo_console bi_cons;
    229 	extern struct btinfo_clock bi_clk;
    230 	extern struct btinfo_prodfamily bi_fam;
    231 
    232 	/*
    233 	 * CHRP specification "Map-B" BAT012 layout
    234 	 *   BAT0 0000-0000 (256MB) SDRAM
    235 	 *   BAT1 8000-0000 (256MB) PCI mem space
    236 	 *   BAT2 fc00-0000 (64MB)  EUMB, PCI I/O space, misc devs, flash
    237 	 *
    238 	 * EUMBBAR is at fc00-0000.
    239 	 */
    240 	pchb = pcimaketag(0, 0, 0);
    241 	pcicfgwrite(pchb, 0x78, 0xfc000000);
    242 
    243 	brdtype = BRD_UNKNOWN;
    244 	extclk = EXT_CLK_FREQ;	/* usually 33MHz */
    245 	busclock = 0;
    246 
    247 	dev11 = pcimaketag(0, 11, 0);
    248 	dev12 = pcimaketag(0, 12, 0);
    249 	dev13 = pcimaketag(0, 13, 0);
    250 	dev15 = pcimaketag(0, 15, 0);
    251 	dev16 = pcimaketag(0, 16, 0);
    252 
    253 	if (pcifinddev(0x10ad, 0x0565, &pcib) == 0) {
    254 		/* WinBond 553 southbridge at dev 11 */
    255 		brdtype = BRD_SANDPOINTX3;
    256 	}
    257 	else if (pcifinddev(0x1106, 0x0686, &pcib) == 0) {
    258 		/* VIA 686B southbridge at dev 22 */
    259 		brdtype = BRD_ENCOREPP1;
    260 	}
    261 	else if (PCI_CLASS(pcicfgread(dev11, PCI_CLASS_REG)) == PCI_CLASS_ETH) {
    262 		/* ADMtek AN985 (tlp) or RealTek 8169S (re) at dev 11 */
    263 		if (PCI_VENDOR(pcicfgread(dev12, PCI_ID_REG)) != 0x1095)
    264 			brdtype = BRD_KUROBOX;
    265 		else
    266 			brdtype = BRD_KUROBOXT4;
    267 	}
    268 	else if (PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x11ab) {
    269 		/* SKnet/Marvell (sk) at dev 15 */
    270 		brdtype = BRD_SYNOLOGY;
    271 	}
    272 	else if (PCI_VENDOR(pcicfgread(dev13, PCI_ID_REG)) == 0x1106) {
    273 		/* VIA 6410 (viaide) at dev 13 */
    274 		brdtype = BRD_STORCENTER;
    275 	}
    276 	else if (PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1191) {
    277 		/* ACARD ATP865 (acardide) at dev 16 */
    278 		brdtype = BRD_DLINKDSM;
    279 	}
    280 	else if (PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1283
    281 	    || PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1095) {
    282 		/* ITE (iteide) or SiI (satalink) at dev 16 */
    283 		brdtype = BRD_NH230NAS;
    284 	}
    285 	else if (PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x8086
    286 	    || PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x10ec) {
    287 		/* Intel (wm) or RealTek (re) at dev 15 */
    288 		brdtype = BRD_QNAPTS;
    289 	}
    290 
    291 	brdprop = brd_lookup(brdtype);
    292 
    293 	/* brd dependent adjustments */
    294 	setup();
    295 
    296 	/* determine clock frequencies */
    297 	if (brdprop->extclk != 0)
    298 		extclk = brdprop->extclk;
    299 	if (busclock == 0) {
    300 		if (cputype() == MPC8245) {
    301 			/* PLL_CFG from PCI host bridge register 0xe2 */
    302 			val = pcicfgread(pchb, 0xe0);
    303 			busclock = (extclk *
    304 			    pci_to_memclk[(val >> 19) & 0x1f] + 10) / 10;
    305 			/* PLLRATIO from HID1 */
    306 			asm volatile ("mfspr %0,1009" : "=r"(val));
    307 			cpuclock = ((uint64_t)busclock *
    308 			    mem_to_cpuclk[val >> 27] + 10) / 10;
    309 		} else
    310 			busclock = 100000000;	/* 100MHz bus clock default */
    311 	}
    312 	ticks_per_sec = busclock >> 2;
    313 	ns_per_tick = 1000000000 / ticks_per_sec;
    314 
    315 	/* now prepare serial console */
    316 	consname = brdprop->consname;
    317 	consport = brdprop->consport;
    318 	if (strcmp(consname, "eumb") == 0) {
    319 		uart1base = 0xfc000000 + consport;	/* 0x4500, 0x4600 */
    320 		UART_WRITE(uart1base, DCR, 0x01);	/* enable DUART mode */
    321 		uart2base = uart1base ^ 0x0300;
    322 	} else
    323 		uart1base = 0xfe000000 + consport;	/* 0x3f8, 0x2f8 */
    324 
    325 	/* more brd adjustments */
    326 	brdfixup();
    327 
    328 	bi_mem.memsize = mpc107memsize();
    329 	snprintf(bi_cons.devname, sizeof(bi_cons.devname), "%s", consname);
    330 	bi_cons.addr = consport;
    331 	bi_cons.speed = brdprop->consspeed;
    332 	bi_clk.ticks_per_sec = ticks_per_sec;
    333 	snprintf(bi_fam.name, sizeof(bi_fam.name), "%s", brdprop->family);
    334 }
    335 
    336 struct brdprop *
    337 brd_lookup(int brd)
    338 {
    339 	u_int i;
    340 
    341 	for (i = 0; i < sizeof(brdlist)/sizeof(brdlist[0]); i++) {
    342 		if (brdlist[i].brdtype == brd)
    343 			return &brdlist[i];
    344 	}
    345 	return &brdlist[i - 1];
    346 }
    347 
    348 static void
    349 setup()
    350 {
    351 
    352 	if (brdprop->setup == NULL)
    353 		return;
    354 	(*brdprop->setup)(brdprop);
    355 }
    356 
    357 static void
    358 brdfixup()
    359 {
    360 
    361 	if (brdprop->brdfix == NULL)
    362 		return;
    363 	(*brdprop->brdfix)(brdprop);
    364 }
    365 
    366 void
    367 pcifixup()
    368 {
    369 
    370 	if (brdprop->pcifix == NULL)
    371 		return;
    372 	(*brdprop->pcifix)(brdprop);
    373 }
    374 
    375 void
    376 launchfixup()
    377 {
    378 
    379 	if (brdprop->launch == NULL)
    380 		return;
    381 	(*brdprop->launch)(brdprop);
    382 }
    383 
    384 void
    385 encsetup(struct brdprop *brd)
    386 {
    387 
    388 #ifdef COSNAME
    389 	brd->consname = CONSNAME;
    390 #endif
    391 #ifdef CONSPORT
    392 	brd->consport = CONSPORT;
    393 #endif
    394 #ifdef CONSSPEED
    395 	brd->consspeed = CONSSPEED;
    396 #endif
    397 }
    398 
    399 void
    400 encbrdfix(struct brdprop *brd)
    401 {
    402 	unsigned ac97, ide, pcib, pmgt, usb12, usb34, val;
    403 
    404 /*
    405  * VIA82C686B Southbridge
    406  *	0.22.0	1106.0686	PCI-ISA bridge
    407  *	0.22.1	1106.0571	IDE (viaide)
    408  *	0.22.2	1106.3038	USB 0/1 (uhci)
    409  *	0.22.3	1106.3038	USB 2/3 (uhci)
    410  *	0.22.4	1106.3057	power management
    411  *	0.22.5	1106.3058	AC97 (auvia)
    412  */
    413 	pcib  = pcimaketag(0, 22, 0);
    414 	ide   = pcimaketag(0, 22, 1);
    415 	usb12 = pcimaketag(0, 22, 2);
    416 	usb34 = pcimaketag(0, 22, 3);
    417 	pmgt  = pcimaketag(0, 22, 4);
    418 	ac97  = pcimaketag(0, 22, 5);
    419 
    420 #define	CFG(i,v) do { \
    421    *(volatile unsigned char *)(0xfe000000 + 0x3f0) = (i); \
    422    *(volatile unsigned char *)(0xfe000000 + 0x3f1) = (v); \
    423    } while (0)
    424 	val = pcicfgread(pcib, 0x84);
    425 	val |= (02 << 8);
    426 	pcicfgwrite(pcib, 0x84, val);
    427 	CFG(0xe2, 0x0f); /* use COM1/2, don't use FDC/LPT */
    428 	val = pcicfgread(pcib, 0x84);
    429 	val &= ~(02 << 8);
    430 	pcicfgwrite(pcib, 0x84, val);
    431 
    432 	/* route pin C to i8259 IRQ 5, pin D to 11 */
    433 	val = pcicfgread(pcib, 0x54);
    434 	val = (val & 0xff) | 0xb0500000; /* Dx CB Ax xS */
    435 	pcicfgwrite(pcib, 0x54, val);
    436 
    437 	/* enable EISA ELCR1 (0x4d0) and ELCR2 (0x4d1) */
    438 	val = pcicfgread(pcib, 0x44);
    439 	val = val | 0x20000000;
    440 	pcicfgwrite(pcib, 0x44, val);
    441 
    442 	/* select level trigger for IRQ 5/11 at ELCR1/2 */
    443 	*(volatile uint8_t *)0xfe0004d0 = 0x20; /* bit 5 */
    444 	*(volatile uint8_t *)0xfe0004d1 = 0x08; /* bit 11 */
    445 
    446 	/* USB and AC97 are hardwired with pin D and C */
    447 	val = pcicfgread(usb12, 0x3c) &~ 0xff;
    448 	val |= 11;
    449 	pcicfgwrite(usb12, 0x3c, val);
    450 	val = pcicfgread(usb34, 0x3c) &~ 0xff;
    451 	val |= 11;
    452 	pcicfgwrite(usb34, 0x3c, val);
    453 	val = pcicfgread(ac97, 0x3c) &~ 0xff;
    454 	val |= 5;
    455 	pcicfgwrite(ac97, 0x3c, val);
    456 
    457 	(void) pcicfgread(ide, 0x08);
    458 	(void) pcicfgread(pmgt, 0x08);
    459 }
    460 
    461 void
    462 encpcifix(struct brdprop *brd)
    463 {
    464 	unsigned ide, irq, net, pcib, steer, val;
    465 
    466 #define	STEER(v, b) (((v) & (b)) ? "edge" : "level")
    467 	pcib = pcimaketag(0, 22, 0);
    468 	ide  = pcimaketag(0, 22, 1);
    469 	net  = pcimaketag(0, 25, 0);
    470 
    471 	/*
    472 	 * //// VIA PIRQ ////
    473 	 * 0x57/56/55/54 - Dx CB Ax xS
    474 	 */
    475 	val = pcicfgread(pcib, 0x54);	/* Dx CB Ax xs */
    476 	steer = val & 0xf;
    477 	irq = (val >> 12) & 0xf;	/* 15:12 */
    478 	if (irq) {
    479 		printf("pin A -> irq %d, %s\n",
    480 			irq, STEER(steer, 0x1));
    481 	}
    482 	irq = (val >> 16) & 0xf;	/* 19:16 */
    483 	if (irq) {
    484 		printf("pin B -> irq %d, %s\n",
    485 			irq, STEER(steer, 0x2));
    486 	}
    487 	irq = (val >> 20) & 0xf;	/* 23:20 */
    488 	if (irq) {
    489 		printf("pin C -> irq %d, %s\n",
    490 			irq, STEER(steer, 0x4));
    491 	}
    492 	irq = (val >> 28);		/* 31:28 */
    493 	if (irq) {
    494 		printf("pin D -> irq %d, %s\n",
    495 			irq, STEER(steer, 0x8));
    496 	}
    497 #if 0
    498 	/*
    499 	 * //// IDE fixup ////
    500 	 * - "native mode" (ide 0x09)
    501 	 */
    502 
    503 	/* ide: 0x09 - programming interface; 1000'SsPp */
    504 	val = pcicfgread(ide, 0x08) & 0xffff00ff;
    505 	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
    506 
    507 	/* ide: 0x10-20 - leave them PCI memory space assigned */
    508 #else
    509 	/*
    510 	 * //// IDE fixup ////
    511 	 * - "compatiblity mode" (ide 0x09)
    512 	 * - remove PCI pin assignment (ide 0x3d)
    513 	 */
    514 
    515 	/* ide: 0x09 - programming interface; 1000'SsPp */
    516 	val = pcicfgread(ide, 0x08) & 0xffff00ff;
    517 	val |= (0x8a << 8);
    518 	pcicfgwrite(ide, 0x08, val);
    519 
    520 	/* ide: 0x10-20 */
    521 	/*
    522 	 * experiment shows writing ide: 0x09 changes these
    523 	 * register behaviour. The pcicfgwrite() above writes
    524 	 * 0x8a at ide: 0x09 to make sure legacy IDE.  Then
    525 	 * reading BAR0-3 is to return value 0s even though
    526 	 * pcisetup() has written range assignments.  Value
    527 	 * overwrite makes no effect. Having 0x8f for native
    528 	 * PCIIDE doesn't change register values and brings no
    529 	 * weirdness.
    530 	 */
    531 
    532 	/* ide: 0x3d/3c - turn off PCI pin */
    533 	val = pcicfgread(ide, 0x3c) & 0xffff00ff;
    534 	pcicfgwrite(ide, 0x3c, val);
    535 #endif
    536 	/*
    537 	 * //// USBx2, audio, and modem fixup ////
    538 	 * - disable USB #0 and #1 (pcib 0x48 and 0x85)
    539 	 * - disable AC97 audio and MC97 modem (pcib 0x85)
    540 	 */
    541 
    542 	/* pcib: 0x48 - disable USB #0 at function 2 */
    543 	val = pcicfgread(pcib, 0x48);
    544 	pcicfgwrite(pcib, 0x48, val | 04);
    545 
    546 	/* pcib: 0x85 - disable USB #1 at function 3 */
    547 	/* pcib: 0x85 - disable AC97/MC97 at function 5/6 */
    548 	val = pcicfgread(pcib, 0x84);
    549 	pcicfgwrite(pcib, 0x84, val | 0x1c00);
    550 
    551 	/*
    552 	 * //// fxp fixup ////
    553 	 * - use PCI pin A line 25 (fxp 0x3d/3c)
    554 	 */
    555 	/* 0x3d/3c - PCI pin/line */
    556 	val = pcicfgread(net, 0x3c) & 0xffff0000;
    557 	val |= (('A' - '@') << 8) | 25;
    558 	pcicfgwrite(net, 0x3c, val);
    559 }
    560 
    561 void
    562 motsetup(struct brdprop *brd)
    563 {
    564 
    565 #ifdef COSNAME
    566 	brd->consname = CONSNAME;
    567 #endif
    568 #ifdef CONSPORT
    569 	brd->consport = CONSPORT;
    570 #endif
    571 #ifdef CONSSPEED
    572 	brd->consspeed = CONSSPEED;
    573 #endif
    574 }
    575 
    576 void
    577 motbrdfix(struct brdprop *brd)
    578 {
    579 
    580 /*
    581  * WinBond/Symphony Lab 83C553 with PC87308 "SuperIO"
    582  *
    583  *	0.11.0	10ad.0565	PCI-ISA bridge
    584  *	0.11.1	10ad.0105	IDE (slide)
    585  */
    586 }
    587 
    588 void
    589 motpcifix(struct brdprop *brd)
    590 {
    591 	unsigned ide, net, pcib, steer, val;
    592 	int line;
    593 
    594 	pcib = pcimaketag(0, 11, 0);
    595 	ide  = pcimaketag(0, 11, 1);
    596 	net  = pcimaketag(0, 15, 0);
    597 
    598 	/*
    599 	 * //// WinBond PIRQ ////
    600 	 * 0x40 - bit 5 (0x20) indicates PIRQ presense
    601 	 * 0x60 - PIRQ interrupt routing steer
    602 	 */
    603 	if (pcicfgread(pcib, 0x40) & 0x20) {
    604 		steer = pcicfgread(pcib, 0x60);
    605 		if ((steer & 0x80808080) == 0x80808080)
    606 			printf("PIRQ[0-3] disabled\n");
    607 		else {
    608 			unsigned i, v = steer;
    609 			for (i = 0; i < 4; i++, v >>= 8) {
    610 				if ((v & 0x80) != 0 || (v & 0xf) == 0)
    611 					continue;
    612 				printf("PIRQ[%d]=%d\n", i, v & 0xf);
    613 				}
    614 			}
    615 		}
    616 #if 1
    617 	/*
    618 	 * //// IDE fixup -- case A ////
    619 	 * - "native PCI mode" (ide 0x09)
    620 	 * - don't use ISA IRQ14/15 (pcib 0x43)
    621 	 * - native IDE for both channels (ide 0x40)
    622 	 * - LEGIRQ bit 11 steers interrupt to pin C (ide 0x40)
    623 	 * - sign as PCI pin C line 11 (ide 0x3d/3c)
    624 	 */
    625 	/* ide: 0x09 - programming interface; 1000'SsPp */
    626 	val = pcicfgread(ide, 0x08);
    627 	val &= 0xffff00ff;
    628 	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
    629 
    630 	/* pcib: 0x43 - IDE interrupt routing */
    631 	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
    632 	pcicfgwrite(pcib, 0x40, val);
    633 
    634 	/* pcib: 0x45/44 - PCI interrupt routing */
    635 	val = pcicfgread(pcib, 0x44) & 0xffff0000;
    636 	pcicfgwrite(pcib, 0x44, val);
    637 
    638 	/* ide: 0x41/40 - IDE channel */
    639 	val = pcicfgread(ide, 0x40) & 0xffff0000;
    640 	val |= (1 << 11) | 0x33; /* LEGIRQ turns on PCI interrupt */
    641 	pcicfgwrite(ide, 0x40, val);
    642 
    643 	/* ide: 0x3d/3c - use PCI pin C/line 11 */
    644 	val = pcicfgread(ide, 0x3c) & 0xffffff00;
    645 	val |= 11; /* pin designation is hardwired to pin A */
    646 	pcicfgwrite(ide, 0x3c, val);
    647 #else
    648 	/*
    649 	 * //// IDE fixup -- case B ////
    650 	 * - "compatiblity mode" (ide 0x09)
    651 	 * - IDE primary/secondary interrupt routing (pcib 0x43)
    652 	 * - PCI interrupt routing (pcib 0x45/44)
    653 	 * - no PCI pin/line assignment (ide 0x3d/3c)
    654 	 */
    655 	/* ide: 0x09 - programming interface; 1000'SsPp */
    656 	val = pcicfgread(ide, 0x08);
    657 	val &= 0xffff00ff;
    658 	pcicfgwrite(ide, 0x08, val | (0x8a << 8));
    659 
    660 	/* pcib: 0x43 - IDE interrupt routing */
    661 	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
    662 	pcicfgwrite(pcib, 0x40, val | (0xee << 24));
    663 
    664 	/* ide: 0x45/44 - PCI interrupt routing */
    665 	val = pcicfgread(ide, 0x44) & 0xffff0000;
    666 	pcicfgwrite(ide, 0x44, val);
    667 
    668 	/* ide: 0x3d/3c - turn off PCI pin/line */
    669 	val = pcicfgread(ide, 0x3c) & 0xffff0000;
    670 	pcicfgwrite(ide, 0x3c, val);
    671 #endif
    672 
    673 	/*
    674 	 * //// fxp fixup ////
    675 	 * - use PCI pin A line 15 (fxp 0x3d/3c)
    676 	 */
    677 	val = pcicfgread(net, 0x3c) & 0xffff0000;
    678 	pcidecomposetag(net, NULL, &line, NULL);
    679 	val |= (('A' - '@') << 8) | line;
    680 	pcicfgwrite(net, 0x3c, val);
    681 }
    682 
    683 void
    684 kurosetup(struct brdprop *brd)
    685 {
    686 
    687 	if (PCI_VENDOR(pcicfgread(pcimaketag(0, 11, 0), PCI_ID_REG)) == 0x10ec)
    688 		brd->extclk = 32768000; /* decr 2457600Hz */
    689 	else
    690 		brd->extclk = 32521333; /* decr 2439100Hz */
    691 }
    692 
    693 void
    694 kurobrdfix(struct brdprop *brd)
    695 {
    696 
    697 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PEVEN);
    698 	/* Stop Watchdog */
    699 	send_sat("AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK");
    700 }
    701 
    702 void
    703 kuroreset()
    704 {
    705 
    706 	send_sat("CCGG");
    707 	/*NOTREACHED*/
    708 }
    709 
    710 void
    711 synosetup(struct brdprop *brd)
    712 {
    713 
    714 	if (1) /* 200 and 266MHz models */
    715 		brd->extclk = 33164691; /* from Synology/Linux source */
    716 	else   /* 400MHz models XXX how to check? */
    717 		brd->extclk = 33165343;
    718 }
    719 
    720 void
    721 synobrdfix(struct brdprop *brd)
    722 {
    723 
    724 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
    725 	/* beep, power LED on, status LED off */
    726 	send_sat("247");
    727 }
    728 
    729 #define SYNO_FAN_TIMEOUT	500	/* 500ms to turn the fan off */
    730 #define SYNO_DISK_DELAY		30	/* 30 seconds to power up 2nd disk */
    731 
    732 void
    733 synopcifix(struct brdprop *brd)
    734 {
    735 	static const char models207[4][7] = {
    736 		"???", "DS107e", "DS107", "DS207"
    737 	};
    738 	static const char models209[2][7] = {
    739 		"DS109j", "DS209j"
    740 	};
    741 	static const char models406[3][7] = {
    742 		"CS406e", "CS406", "RS406"
    743 	};
    744 	static const char models407[4][7] = {
    745 		"???", "CS407e", "CS407", "RS407"
    746 	};
    747 	extern struct btinfo_model bi_model;
    748 	const char *model_name;
    749 	unsigned cpld, version, flags;
    750 	uint8_t v, status;
    751 	int i;
    752 
    753 	/*
    754 	 * Determine if a CPLD is present and whether is has 4-bit
    755 	 * (models 107, 207, 209)  or 8-bit (models 406, 407) registers.
    756 	 * The register set repeats every 16 bytes.
    757 	 */
    758 	cpld = 0;
    759 	flags = 0;
    760 	version = 0;
    761 	model_name = NULL;
    762 
    763 	SYNOCPLD_WRITE(0, 0x00);	/* LEDs blinking yellow (default) */
    764 	v = SYNOCPLD_READ(0);
    765 
    766 	if (v != 0x00) {
    767 		v &= 0xf0;
    768 		if (v != 0x00 || (SYNOCPLD_READ(16 + 0) & 0xf0) != v)
    769 			goto cpld_done;
    770 
    771   cpld4bits:
    772 		/* 4-bit registers assumed, make LEDs solid yellow */
    773 		SYNOCPLD_WRITE(0, 0x50);
    774 		v = SYNOCPLD_READ(0) & 0xf0;
    775 		if (v != 0x50 || (SYNOCPLD_READ(32 + 0) & 0xf0) != v)
    776 			goto cpld_done;
    777 
    778 		v = SYNOCPLD_READ(2) & 0xf0;
    779 		if ((SYNOCPLD_READ(48 + 2) & 0xf0) != v)
    780 			goto cpld_done;
    781 		version = (v >> 4) & 7;
    782 
    783 		/*
    784 		 * Try to determine whether it is a 207-style or 209-style
    785 		 * CPLD register set, by turning the fan off and check if
    786 		 * either bit 5 or bit 4 changes from 0 to 1 to indicate
    787 		 * the fan is stopped.
    788 		 */
    789 		status = SYNOCPLD_READ(3) & 0xf0;
    790 		SYNOCPLD_WRITE(3, 0x00);	/* fan off */
    791 
    792 		for (i = 0; i < SYNO_FAN_TIMEOUT * 100; i++) {
    793 			delay(10);
    794 			v = SYNOCPLD_READ(3) & 0xf0;
    795 			if ((status & 0x20) == 0 && (v & 0x20) != 0) {
    796 				/* set x07 model */
    797 				v = SYNOCPLD_READ(1) >> 6;
    798 				model_name = models207[v];
    799 				cpld = BI_MODEL_CPLD207;
    800 				/* XXXX DS107v2/v3 have no thermal sensor */
    801 				flags |= BI_MODEL_THERMAL;
    802 				break;
    803 			}
    804 			if ((status & 0x10) == 0 && (v & 0x10) != 0) {
    805 				/* set x09 model */
    806 				v = SYNOCPLD_READ(1) >> 7;
    807 				model_name = models209[v];
    808 				cpld = BI_MODEL_CPLD209;
    809 				if (v == 1)	/* DS209j */
    810 					flags |= BI_MODEL_THERMAL;
    811 				break;
    812 			}
    813 			/* XXX What about DS108j? Does it have a CPLD? */
    814 		}
    815 
    816 		/* turn the fan on again */
    817 		SYNOCPLD_WRITE(3, status);
    818 
    819 		if (i >= SYNO_FAN_TIMEOUT * 100)
    820 			goto cpld_done;		/* timeout: no valid CPLD */
    821 	} else {
    822 		if (SYNOCPLD_READ(16 + 0) != v)
    823 			goto cpld4bits;
    824 
    825 		/* 8-bit registers assumed, make LEDs solid yellow */
    826 		SYNOCPLD_WRITE(0, 0x55);
    827 		v = SYNOCPLD_READ(0);
    828 		if (v != 0x55)
    829 			goto cpld4bits;		/* try 4 bits instead */
    830 		if (SYNOCPLD_READ(32 + 0) != v)
    831 			goto cpld_done;
    832 
    833 		v = SYNOCPLD_READ(2);
    834 		if (SYNOCPLD_READ(48 + 2) != v)
    835 			goto cpld_done;
    836 		version = v & 3;
    837 
    838 		if ((v & 0x0c) != 0x0c) {
    839 			/* set 406 model */
    840 			model_name = models406[(v >> 2) & 3];
    841 			cpld = BI_MODEL_CPLD406;
    842 		} else {
    843 			/* set 407 model */
    844 			model_name = models407[v >> 6];
    845 			cpld = BI_MODEL_CPLD407;
    846 			flags |= BI_MODEL_THERMAL;
    847 		}
    848 	}
    849 
    850 	printf("CPLD V%s%u detected for model %s\n",
    851 	    cpld < BI_MODEL_CPLD406 ? "" : "1.",
    852 	    version, model_name);
    853 
    854 	if (cpld ==  BI_MODEL_CPLD406 || cpld ==  BI_MODEL_CPLD407) {
    855 		/*
    856 		 * CS/RS stations power-up their disks one after another.
    857 		 * We have to watch over the current power state in a CPLD
    858 		 * register, until all disks become available.
    859 		 */
    860 		do {
    861 			delay(1000 * 1000);
    862 			v = SYNOCPLD_READ(1);
    863 			printf("Power state: %02x\r", v);
    864 		} while (v != 0xff);
    865 		putchar('\n');
    866 	} else if (model_name != NULL && model_name[2] == '2') {
    867 		/*
    868 		 * DS207 and DS209 have a second SATA disk, which is started
    869 		 * with several seconds delay, but no CPLD register to
    870 		 * monitor the power state. So all we can do is to
    871 		 * wait some more seconds during SATA-init.
    872 		 */
    873 		sata_delay[1] = SYNO_DISK_DELAY;
    874 	}
    875 
    876   cpld_done:
    877 	if (model_name != NULL) {
    878 		snprintf(bi_model.name, sizeof(bi_model.name), "%s", model_name);
    879 		bi_model.flags = cpld | version | flags;
    880 	} else
    881 		printf("No CPLD found. DS101/DS106.\n");
    882 }
    883 
    884 void
    885 synolaunch(struct brdprop *brd)
    886 {
    887 	extern struct btinfo_model bi_model;
    888 	struct dkdev_ata *sata1, *sata2;
    889 	unsigned cpld;
    890 
    891 	cpld = bi_model.flags & BI_MODEL_CPLD_MASK;
    892 
    893 	if (cpld ==  BI_MODEL_CPLD406 || cpld ==  BI_MODEL_CPLD407) {
    894 		/* set drive LEDs for active disk drives on CS/RS models */
    895 		sata1 = lata[0].drv;
    896 		sata2 = lata[1].drv;
    897 		SYNOCPLD_WRITE(0, (sata1->presense[0] ? 0x80 : 0xc0) |
    898 		    (sata1->presense[1] ? 0x20 : 0x30) |
    899 		    (sata2->presense[0] ? 0x08 : 0x0c) |
    900 		    (sata2->presense[1] ? 0x02 : 0x03));
    901 	} else if (cpld ==  BI_MODEL_CPLD207 || cpld ==  BI_MODEL_CPLD209) {
    902 		/* set drive LEDs for DS207 and DS209 models */
    903 		sata1 = lata[0].drv;
    904 		SYNOCPLD_WRITE(0, (sata1->presense[0] ? 0x80 : 0xc0) |
    905 		    (sata1->presense[1] ? 0x20 : 0x30));
    906 	}
    907 }
    908 
    909 void
    910 synoreset()
    911 {
    912 
    913 	send_sat("C");
    914 	/*NOTREACHED*/
    915 }
    916 
    917 void
    918 qnapbrdfix(struct brdprop *brd)
    919 {
    920 
    921 	init_uart(uart2base, 19200, LCR_8BITS | LCR_PNONE);
    922 	/* beep, status LED red */
    923 	send_sat("PW");
    924 }
    925 
    926 void
    927 qnapreset()
    928 {
    929 
    930 	send_sat("f");
    931 	/*NOTREACHED*/
    932 }
    933 
    934 void
    935 iomegabrdfix(struct brdprop *brd)
    936 {
    937 
    938 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
    939 	/* LED flashing blue, fan auto, turn on at 50C, turn off at 45C */
    940 	send_iomega('b', 'd', 2, 'a', 50, 45);
    941 }
    942 
    943 void
    944 iomegareset()
    945 {
    946 
    947 	send_iomega('g', 0, 0, 0, 0, 0);
    948 	/*NOTREACHED*/
    949 }
    950 
    951 void
    952 dlinkbrdfix(struct brdprop *brd)
    953 {
    954 
    955 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
    956 	send_sat("SYN\n");
    957 	send_sat("ZWO\n");	/* power LED solid on */
    958 }
    959 
    960 void
    961 nhnasbrdfix(struct brdprop *brd)
    962 {
    963 
    964 	/* status LED off, USB-LEDs on, low-speed fan */
    965 	NHGPIO_WRITE(0x04);
    966 }
    967 
    968 void
    969 nhnasreset()
    970 {
    971 
    972 	/* status LED on, assert system-reset to all devices */
    973 	NHGPIO_WRITE(0x02);
    974 	delay(100000);
    975 	/*NOTREACHED*/
    976 }
    977 
    978 void
    979 kurot4brdfix(struct brdprop *brd)
    980 {
    981 
    982 	init_uart(uart2base, 38400, LCR_8BITS | LCR_PEVEN);
    983 }
    984 
    985 void
    986 _rtt(void)
    987 {
    988 	uint32_t msr;
    989 
    990 	netif_shutdown_all();
    991 
    992 	if (brdprop->reset != NULL)
    993 		(*brdprop->reset)();
    994 	else {
    995 		msr = mfmsr();
    996 		msr &= ~PSL_EE;
    997 		mtmsr(msr);
    998 		asm volatile ("sync; isync");
    999 		asm volatile("mtspr %0,%1" : : "K"(81), "r"(0));
   1000 		msr &= ~(PSL_ME | PSL_DR | PSL_IR);
   1001 		mtmsr(msr);
   1002 		asm volatile ("sync; isync");
   1003 		run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */
   1004 	}
   1005 	__unreachable();
   1006 }
   1007 
   1008 satime_t
   1009 getsecs(void)
   1010 {
   1011 	u_quad_t tb = mftb();
   1012 
   1013 	return (tb / ticks_per_sec);
   1014 }
   1015 
   1016 /*
   1017  * Wait for about n microseconds (at least!).
   1018  */
   1019 void
   1020 delay(u_int n)
   1021 {
   1022 	u_quad_t tb;
   1023 	u_long scratch, tbh, tbl;
   1024 
   1025 	tb = mftb();
   1026 	tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
   1027 	tbh = tb >> 32;
   1028 	tbl = tb;
   1029 	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));
   1030 }
   1031 
   1032 void
   1033 _wb(uint32_t adr, uint32_t siz)
   1034 {
   1035 	uint32_t bnd;
   1036 
   1037 	asm volatile("eieio");
   1038 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
   1039 		asm volatile ("dcbst 0,%0" :: "r"(adr));
   1040 	asm volatile ("sync");
   1041 }
   1042 
   1043 void
   1044 _wbinv(uint32_t adr, uint32_t siz)
   1045 {
   1046 	uint32_t bnd;
   1047 
   1048 	asm volatile("eieio");
   1049 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
   1050 		asm volatile ("dcbf 0,%0" :: "r"(adr));
   1051 	asm volatile ("sync");
   1052 }
   1053 
   1054 void
   1055 _inv(uint32_t adr, uint32_t siz)
   1056 {
   1057 	uint32_t bnd, off;
   1058 
   1059 	off = adr & (dcache_line_size - 1);
   1060 	adr -= off;
   1061 	siz += off;
   1062 	asm volatile ("eieio");
   1063 	if (off != 0) {
   1064 		/* wbinv() leading unaligned dcache line */
   1065 		asm volatile ("dcbf 0,%0" :: "r"(adr));
   1066 		if (siz < dcache_line_size)
   1067 			goto done;
   1068 		adr += dcache_line_size;
   1069 		siz -= dcache_line_size;
   1070 	}
   1071 	bnd = adr + siz;
   1072 	off = bnd & (dcache_line_size - 1);
   1073 	if (off != 0) {
   1074 		/* wbinv() trailing unaligned dcache line */
   1075 		asm volatile ("dcbf 0,%0" :: "r"(bnd)); /* it's OK */
   1076 		if (siz < dcache_line_size)
   1077 			goto done;
   1078 		siz -= off;
   1079 	}
   1080 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) {
   1081 		/* inv() intermediate dcache lines if ever */
   1082 		asm volatile ("dcbi 0,%0" :: "r"(adr));
   1083 	}
   1084   done:
   1085 	asm volatile ("sync");
   1086 }
   1087 
   1088 static inline uint32_t
   1089 mfmsr(void)
   1090 {
   1091 	uint32_t msr;
   1092 
   1093 	asm volatile ("mfmsr %0" : "=r"(msr));
   1094 	return msr;
   1095 }
   1096 
   1097 static inline void
   1098 mtmsr(uint32_t msr)
   1099 {
   1100 	asm volatile ("mtmsr %0" : : "r"(msr));
   1101 }
   1102 
   1103 static inline uint32_t
   1104 cputype(void)
   1105 {
   1106 	uint32_t pvr;
   1107 
   1108 	asm volatile ("mfpvr %0" : "=r"(pvr));
   1109 	return pvr >> 16;
   1110 }
   1111 
   1112 static inline u_quad_t
   1113 mftb(void)
   1114 {
   1115 	u_long scratch;
   1116 	u_quad_t tb;
   1117 
   1118 	asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b"
   1119 	    : "=r"(tb), "=r"(scratch));
   1120 	return tb;
   1121 }
   1122 
   1123 static void
   1124 init_uart(unsigned base, unsigned speed, uint8_t lcr)
   1125 {
   1126 	unsigned div;
   1127 
   1128 	div = busclock / speed / 16;
   1129 	UART_WRITE(base, LCR, 0x80);		/* turn on DLAB bit */
   1130 	UART_WRITE(base, FCR, 0x00);
   1131 	UART_WRITE(base, DMB, div >> 8);	/* set speed */
   1132 	UART_WRITE(base, DLB, div & 0xff);
   1133 	UART_WRITE(base, LCR, lcr);
   1134 	UART_WRITE(base, FCR, 0x07);		/* FIFO on, TXRX FIFO reset */
   1135 	UART_WRITE(base, IER, 0x00);		/* make sure INT disabled */
   1136 }
   1137 
   1138 /* talk to satellite processor */
   1139 static void
   1140 send_sat(char *msg)
   1141 {
   1142 	unsigned savedbase;
   1143 
   1144 	savedbase = uart1base;
   1145 	uart1base = uart2base;
   1146 	while (*msg)
   1147 		putchar(*msg++);
   1148 	uart1base = savedbase;
   1149 }
   1150 
   1151 #ifdef DEBUG
   1152 static void
   1153 iomega_debug(const char *txt, uint8_t buf[])
   1154 {
   1155 	int i;
   1156 
   1157 	printf("%s:", txt);
   1158 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
   1159 		printf(" %02x", buf[i]);
   1160 	putchar('\n');
   1161 }
   1162 #endif /* DEBUG */
   1163 
   1164 static void
   1165 send_iomega(int power, int led, int rate, int fan, int high, int low)
   1166 {
   1167 	uint8_t buf[IOMEGA_PACKETSIZE];
   1168 	unsigned i, savedbase;
   1169 
   1170 	savedbase = uart1base;
   1171 	uart1base = uart2base;
   1172 
   1173 	/* first flush the receive buffer */
   1174   again:
   1175 	while (tstchar())
   1176 		(void)getchar();
   1177 	delay(20000);
   1178 	if (tstchar())
   1179 		goto again;
   1180 	/*
   1181 	 * Now synchronize the transmitter by sending 0x00
   1182 	 * until we receive a status reply.
   1183 	 */
   1184 	do {
   1185 		putchar(0);
   1186 		delay(50000);
   1187 	} while (!tstchar());
   1188 
   1189 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
   1190 		buf[i] = getchar();
   1191 #ifdef DEBUG
   1192 	uart1base = savedbase;
   1193 	iomega_debug("68HC908 status", buf);
   1194 	uart1base = uart2base;
   1195 #endif
   1196 
   1197 	/* send command */
   1198 	buf[IOMEGA_POWER] = power;
   1199 	buf[IOMEGA_LED] = led;
   1200 	buf[IOMEGA_FLASH_RATE] = rate;
   1201 	buf[IOMEGA_FAN] = fan;
   1202 	buf[IOMEGA_HIGH_TEMP] = high;
   1203 	buf[IOMEGA_LOW_TEMP] = low;
   1204 	buf[IOMEGA_ID] = 7;	/* host id */
   1205 	buf[IOMEGA_CHECKSUM] = (buf[IOMEGA_POWER] + buf[IOMEGA_LED] +
   1206 	    buf[IOMEGA_FLASH_RATE] + buf[IOMEGA_FAN] +
   1207 	    buf[IOMEGA_HIGH_TEMP] + buf[IOMEGA_LOW_TEMP] +
   1208 	    buf[IOMEGA_ID]) & 0x7f;
   1209 #ifdef DEBUG
   1210 	uart1base = savedbase;
   1211 	iomega_debug("G2 sending", buf);
   1212 	uart1base = uart2base;
   1213 #endif
   1214 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
   1215 		putchar(buf[i]);
   1216 
   1217 	/* receive the reply */
   1218 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
   1219 		buf[i] = getchar();
   1220 #ifdef DEBUG
   1221 	uart1base = savedbase;
   1222 	iomega_debug("68HC908 reply", buf);
   1223 	uart1base = uart2base;
   1224 #endif
   1225 
   1226 	if (buf[0] == '#')
   1227 		goto again;  /* try again on error */
   1228 	uart1base = savedbase;
   1229 }
   1230 
   1231 void
   1232 putchar(int c)
   1233 {
   1234 	unsigned timo, lsr;
   1235 
   1236 	if (c == '\n')
   1237 		putchar('\r');
   1238 
   1239 	timo = 0x00100000;
   1240 	do {
   1241 		lsr = UART_READ(uart1base, LSR);
   1242 	} while (timo-- > 0 && (lsr & LSR_THRE) == 0);
   1243 	if (timo > 0)
   1244 		UART_WRITE(uart1base, THR, c);
   1245 }
   1246 
   1247 int
   1248 getchar(void)
   1249 {
   1250 	unsigned lsr;
   1251 
   1252 	do {
   1253 		lsr = UART_READ(uart1base, LSR);
   1254 	} while ((lsr & LSR_DRDY) == 0);
   1255 	return UART_READ(uart1base, RBR);
   1256 }
   1257 
   1258 int
   1259 tstchar(void)
   1260 {
   1261 
   1262 	return (UART_READ(uart1base, LSR) & LSR_DRDY) != 0;
   1263 }
   1264 
   1265 #define SAR_MASK 0x0ff00000
   1266 #define SAR_SHIFT    20
   1267 #define EAR_MASK 0x30000000
   1268 #define EAR_SHIFT    28
   1269 #define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s))
   1270 #define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s))
   1271 static void
   1272 set_mem_bounds(unsigned tag, unsigned bk_en, ...)
   1273 {
   1274 	unsigned mbst, mbxst, mben, mbxen;
   1275 	unsigned start, end;
   1276 	va_list ap;
   1277 	int i, sh;
   1278 
   1279 	va_start(ap, bk_en);
   1280 	mbst = mbxst = mben = mbxen = 0;
   1281 
   1282 	for (i = 0; i < 4; i++) {
   1283 		if ((bk_en & (1U << i)) != 0) {
   1284 			start = va_arg(ap, unsigned);
   1285 			end = va_arg(ap, unsigned);
   1286 		} else {
   1287 			start = 0x3ff00000;
   1288 			end = 0x3fffffff;
   1289 		}
   1290 		sh = i << 3;
   1291 		mbst |= AR(start, sh);
   1292 		mbxst |= XR(start, sh);
   1293 		mben |= AR(end, sh);
   1294 		mbxen |= XR(end, sh);
   1295 	}
   1296 	va_end(ap);
   1297 
   1298 	pcicfgwrite(tag, MPC106_MEMSTARTADDR1, mbst);
   1299 	pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, mbxst);
   1300 	pcicfgwrite(tag, MPC106_MEMENDADDR1, mben);
   1301 	pcicfgwrite(tag, MPC106_EXTMEMENDADDR1,	mbxen);
   1302 	pcicfgwrite(tag, MPC106_MEMEN,
   1303 	    (pcicfgread(tag, MPC106_MEMEN) & ~0xff) | (bk_en & 0xff));
   1304 }
   1305 
   1306 static unsigned
   1307 mpc107memsize(void)
   1308 {
   1309 	unsigned bankn, end, n, tag, val;
   1310 
   1311 	tag = pcimaketag(0, 0, 0);
   1312 
   1313 	if (brdtype == BRD_ENCOREPP1) {
   1314 		/* the brd's PPCBOOT looks to have erroneous values */
   1315 		set_mem_bounds(tag, 1, 0x00000000, (128 << 20) - 1);
   1316 	} else if (brdtype == BRD_NH230NAS) {
   1317 		/*
   1318 		 * PPCBoot sets the end address to 0x7ffffff, although the
   1319 		 * board has just 64MB (0x3ffffff).
   1320 		 */
   1321 		set_mem_bounds(tag, 1, 0x00000000, 0x03ffffff);
   1322 	}
   1323 
   1324 	bankn = 0;
   1325 	val = pcicfgread(tag, MPC106_MEMEN);
   1326 	for (n = 0; n < 4; n++) {
   1327 		if ((val & (1U << n)) == 0)
   1328 			break;
   1329 		bankn = n;
   1330 	}
   1331 	bankn <<= 3;
   1332 
   1333 	val = pcicfgread(tag, MPC106_EXTMEMENDADDR1);
   1334 	end =  ((val >> bankn) & 0x03) << 28;
   1335 	val = pcicfgread(tag, MPC106_MEMENDADDR1);
   1336 	end |= ((val >> bankn) & 0xff) << 20;
   1337 	end |= 0xfffff;
   1338 
   1339 	return (end + 1); /* assume the end address matches total amount */
   1340 }
   1341 
   1342 struct fis_dir_entry {
   1343 	char		name[16];
   1344 	uint32_t	startaddr;
   1345 	uint32_t	loadaddr;
   1346 	uint32_t	flashsize;
   1347 	uint32_t	entryaddr;
   1348 	uint32_t	filesize;
   1349 	char		pad[256 - (16 + 5 * sizeof(uint32_t))];
   1350 };
   1351 
   1352 #define FIS_LOWER_LIMIT	0xfff00000
   1353 
   1354 /*
   1355  * Look for a Redboot-style Flash Image System FIS-directory and
   1356  * return a pointer to the start address of the requested file.
   1357  */
   1358 static void *
   1359 redboot_fis_lookup(const char *filename)
   1360 {
   1361 	static const char FISdirname[16] = {
   1362 	    'F', 'I', 'S', ' ',
   1363 	    'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0
   1364 	};
   1365 	struct fis_dir_entry *dir;
   1366 
   1367 	/*
   1368 	 * The FIS directory is usually in the last sector of the flash.
   1369 	 * But we do not know the sector size (erase size), so start
   1370 	 * at 0xffffff00 and scan backwards in steps of the FIS directory
   1371 	 * entry size (0x100).
   1372 	 */
   1373 	for (dir = (struct fis_dir_entry *)0xffffff00;
   1374 	    (uint32_t)dir >= FIS_LOWER_LIMIT; dir--)
   1375 		if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0)
   1376 			break;
   1377 	if ((uint32_t)dir < FIS_LOWER_LIMIT) {
   1378 		printf("No FIS directory found!\n");
   1379 		return NULL;
   1380 	}
   1381 
   1382 	/* Now find filename by scanning the directory from beginning. */
   1383 	dir = (struct fis_dir_entry *)dir->startaddr;
   1384 	while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) {
   1385 		if (strcmp(dir->name, filename) == 0)
   1386 			return (void *)dir->startaddr;	/* found */
   1387 		dir++;
   1388 	}
   1389 	printf("\"%s\" not found in FIS directory!\n", filename);
   1390 	return NULL;
   1391 }
   1392 
   1393 static void
   1394 read_mac_string(uint8_t *mac, char *p)
   1395 {
   1396 	int i;
   1397 
   1398 	for (i = 0; i < 6; i++, p += 3)
   1399 		*mac++ = read_hex(p);
   1400 }
   1401 
   1402 /*
   1403  * Scan through the Flash memory and look for a string starting at 512 bytes
   1404  * block boundaries, matching the format: xx:xx:xx:xx:xx:xx<NUL>, where "x"
   1405  * are hexadecimal digits.
   1406  * Read the first match as our MAC address.
   1407  * The start address of the search, p, *must* be dividable by 512!
   1408  * Return false when no suitable MAC string was found.
   1409  */
   1410 static int
   1411 find_mac_string(uint8_t *mac, char *p)
   1412 {
   1413 	int i;
   1414 
   1415 	for (;;) {
   1416 		for (i = 0; i < 3 * 6; i += 3) {
   1417 			if (!isxdigit((unsigned)p[i]) ||
   1418 			    !isxdigit((unsigned)p[i + 1]))
   1419 				break;
   1420 			if ((i < 5 && p[i + 2] != ':') ||
   1421 			    (i >= 5 && p[i + 2] != '\0'))
   1422 				break;
   1423 		}
   1424 		if (i >= 6) {
   1425 			/* found a valid MAC address */
   1426 			read_mac_string(mac, p);
   1427 			return 1;
   1428 		}
   1429 		if (p >= (char *)0xfffffe00)
   1430 			break;
   1431 		p += 0x200;
   1432 	}
   1433 	return 0;
   1434 }
   1435 
   1436 
   1437 /*
   1438  * For cost saving reasons some NAS boxes lack SEEPROM for NIC's
   1439  * ethernet address and keep it in their Flash memory instead.
   1440  */
   1441 void
   1442 read_mac_from_flash(uint8_t *mac)
   1443 {
   1444 	uint8_t *p;
   1445 
   1446 	switch (brdtype) {
   1447 	case BRD_SYNOLOGY:
   1448 		p = redboot_fis_lookup("vendor");
   1449 		if (p == NULL)
   1450 			break;
   1451 		memcpy(mac, p, 6);
   1452 		return;
   1453 	case BRD_DLINKDSM:
   1454 		read_mac_string(mac, (char *)0xfff0ff80);
   1455 		return;
   1456 	case BRD_QNAPTS:
   1457 		if (find_mac_string(mac, (char *)0xfff00000))
   1458 			return;
   1459 		break;
   1460 	default:
   1461 		printf("Warning: This board has no known method defined "
   1462 		    "to determine its MAC address!\n");
   1463 		break;
   1464 	}
   1465 
   1466 	/* set to 00:00:00:00:00:00 in case of error */
   1467 	memset(mac, 0, 6);
   1468 }
   1469 
   1470 #ifdef DEBUG
   1471 void
   1472 sat_write(char *p, int len)
   1473 {
   1474 	unsigned savedbase;
   1475 
   1476 	savedbase = uart1base;
   1477 	uart1base = uart2base;
   1478 	while (len--)
   1479 		putchar(*p++);
   1480 	uart1base = savedbase;
   1481 }
   1482 
   1483 int
   1484 sat_getch(void)
   1485 {
   1486 	unsigned lsr;
   1487 
   1488 	do {
   1489 		lsr = UART_READ(uart2base, LSR);
   1490 	} while ((lsr & LSR_DRDY) == 0);
   1491 	return UART_READ(uart2base, RBR);
   1492 }
   1493 
   1494 int
   1495 sat_tstch(void)
   1496 {
   1497 
   1498 	return (UART_READ(uart2base, LSR) & LSR_DRDY) != 0;
   1499 }
   1500 #endif /* DEBUG */
   1501