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