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