Home | History | Annotate | Line # | Download | only in altboot
brdsetup.c revision 1.30
      1 /* $NetBSD: brdsetup.c,v 1.30 2012/04/09 14:02:04 nisimura Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Tohru Nishimura.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/param.h>
     33 
     34 #include <powerpc/psl.h>
     35 #include <powerpc/oea/spr.h>
     36 
     37 #include <lib/libsa/stand.h>
     38 #include <lib/libsa/net.h>
     39 #include <lib/libkern/libkern.h>
     40 
     41 #include <machine/bootinfo.h>
     42 
     43 #include "globals.h"
     44 
     45 #define BRD_DECL(xxx) \
     46     void xxx ## setup(struct brdprop *); \
     47     void xxx ## brdfix(struct brdprop *); \
     48     void xxx ## pcifix(struct brdprop *); \
     49     void xxx ## reset(void)
     50 
     51 BRD_DECL(mot);
     52 BRD_DECL(enc);
     53 BRD_DECL(kuro);
     54 BRD_DECL(syno);
     55 BRD_DECL(qnap);
     56 BRD_DECL(iomega);
     57 BRD_DECL(dlink);
     58 BRD_DECL(nhnas);
     59 BRD_DECL(kurot4);
     60 
     61 static void brdfixup(void);
     62 static void setup(void);
     63 static void send_iomega(int, int, int, int, int, int);
     64 static inline uint32_t mfmsr(void);
     65 static inline void mtmsr(uint32_t);
     66 static inline uint32_t cputype(void);
     67 static inline u_quad_t mftb(void);
     68 static void init_uart(unsigned, unsigned, uint8_t);
     69 static void send_sat(char *);
     70 static unsigned mpc107memsize(void);
     71 
     72 /* UART registers */
     73 #define RBR		0
     74 #define THR		0
     75 #define DLB		0
     76 #define DMB		1
     77 #define IER		1
     78 #define FCR		2
     79 #define LCR		3
     80 #define  LCR_DLAB	0x80
     81 #define  LCR_PEVEN	0x18
     82 #define  LCR_PNONE	0x00
     83 #define  LCR_8BITS	0x03
     84 #define MCR		4
     85 #define  MCR_RTS	0x02
     86 #define  MCR_DTR	0x01
     87 #define LSR		5
     88 #define  LSR_THRE	0x20
     89 #define  LSR_DRDY	0x01
     90 #define DCR		0x11
     91 #define UART_READ(base, r)	in8(base + (r))
     92 #define UART_WRITE(base, r, v)	out8(base + (r), (v))
     93 
     94 /* MPC106 and MPC824x PCI bridge memory configuration */
     95 #define MPC106_MEMSTARTADDR1	0x80
     96 #define MPC106_EXTMEMSTARTADDR1	0x88
     97 #define MPC106_MEMENDADDR1	0x90
     98 #define MPC106_EXTMEMENDADDR1	0x98
     99 #define MPC106_MEMEN		0xa0
    100 
    101 /* Iomega StorCenter MC68HC908 microcontroller data packet */
    102 #define IOMEGA_POWER		0
    103 #define IOMEGA_LED		1
    104 #define IOMEGA_FLASH_RATE	2
    105 #define IOMEGA_FAN		3
    106 #define IOMEGA_HIGH_TEMP	4
    107 #define IOMEGA_LOW_TEMP		5
    108 #define IOMEGA_ID		6
    109 #define IOMEGA_CHECKSUM		7
    110 #define IOMEGA_PACKETSIZE	8
    111 
    112 /* NH230/231 GPIO */
    113 #define NHGPIO_WRITE(x)		*((uint8_t *)0x70000000) = x
    114 
    115 static struct brdprop brdlist[] = {
    116     {
    117 	"sandpoint",
    118 	"Sandpoint X3",
    119 	BRD_SANDPOINTX3,
    120 	0,
    121 	"com", 0x3f8, 115200,
    122 	motsetup, motbrdfix, motpcifix, NULL },
    123     {
    124 	"encpp1",
    125 	"EnCore PP1",
    126 	BRD_ENCOREPP1,
    127 	0,
    128 	"com", 0x3f8, 115200,
    129 	encsetup, encbrdfix, encpcifix, NULL },
    130     {
    131 	"kurobox",
    132 	"KuroBox",
    133 	BRD_KUROBOX,
    134 	0,
    135 	"eumb", 0x4600, 57600,
    136 	kurosetup, kurobrdfix, NULL, kuroreset },
    137     {
    138 	"synology",
    139 	"Synology DS",
    140 	BRD_SYNOLOGY,
    141 	0,
    142 	"eumb", 0x4500, 115200,
    143 	synosetup, synobrdfix, NULL, synoreset },
    144     {
    145 	"qnap",
    146 	"QNAP TS",
    147 	BRD_QNAPTS,
    148 	33164691,	/* Linux source says 33000000, but the Synology  */
    149 			/* clock value delivers a much better precision. */
    150 	"eumb", 0x4500, 115200,
    151 	NULL, qnapbrdfix, NULL, qnapreset },
    152     {
    153 	"iomega",
    154 	"IOMEGA StorCenter G2",
    155 	BRD_STORCENTER,
    156 	0,
    157 	"eumb", 0x4500, 115200,
    158 	NULL, iomegabrdfix, NULL, iomegareset },
    159     {
    160 	"dlink",
    161 	"D-Link DSM-G600",
    162 	BRD_DLINKDSM,
    163 	33000000,
    164 	"eumb", 0x4500, 9600,
    165 	NULL, dlinkbrdfix, NULL, NULL },
    166     {
    167 	"nhnas",
    168 	"Netronix NH-230/231",
    169 	BRD_NH230NAS,
    170 	33000000,
    171 	"eumb", 0x4500, 9600,
    172 	NULL, nhnasbrdfix, NULL, nhnasreset },
    173     {
    174 	"kurot4",
    175 	"KuroBox/T4",
    176 	BRD_KUROBOXT4,
    177 	32768000,
    178 	"eumb", 0x4600, 57600,
    179 	NULL, kurot4brdfix, NULL, NULL },
    180     {
    181 	"unknown",
    182 	"Unknown board",
    183 	BRD_UNKNOWN,
    184 	0,
    185 	"eumb", 0x4500, 115200,
    186 	NULL, NULL, NULL, NULL }, /* must be the last */
    187 };
    188 
    189 static struct brdprop *brdprop;
    190 static uint32_t ticks_per_sec, ns_per_tick;
    191 
    192 const unsigned dcache_line_size = 32;		/* 32B linesize */
    193 const unsigned dcache_range_size = 4 * 1024;	/* 16KB / 4-way */
    194 
    195 unsigned uart1base;	/* console */
    196 unsigned uart2base;	/* optional satellite processor */
    197 
    198 void brdsetup(void);	/* called by entry.S */
    199 
    200 void
    201 brdsetup(void)
    202 {
    203 	static uint8_t pci_to_memclk[] = {
    204 		30, 30, 10, 10, 20, 10, 10, 10,
    205 		10, 20, 20, 15, 20, 15, 20, 30,
    206 		30, 40, 15, 40, 20, 25, 20, 40,
    207 		25, 20, 10, 20, 15, 15, 20, 00
    208 	};
    209 	static uint8_t mem_to_cpuclk[] = {
    210 		25, 30, 45, 20, 20, 00, 10, 30,
    211 		30, 20, 45, 30, 25, 35, 30, 35,
    212 		20, 25, 20, 30, 35, 40, 40, 20,
    213 		30, 25, 40, 30, 30, 25, 35, 00
    214 	};
    215 	char *consname;
    216 	int consport;
    217 	uint32_t extclk;
    218 	unsigned pchb, pcib, dev11, dev12, dev13, dev15, dev16, val;
    219 	extern struct btinfo_memory bi_mem;
    220 	extern struct btinfo_console bi_cons;
    221 	extern struct btinfo_clock bi_clk;
    222 	extern struct btinfo_prodfamily bi_fam;
    223 
    224 	/*
    225 	 * CHRP specification "Map-B" BAT012 layout
    226 	 *   BAT0 0000-0000 (256MB) SDRAM
    227 	 *   BAT1 8000-0000 (256MB) PCI mem space
    228 	 *   BAT2 fc00-0000 (64MB)  EUMB, PCI I/O space, misc devs, flash
    229 	 *
    230 	 * EUMBBAR is at fc00-0000.
    231 	 */
    232 	pchb = pcimaketag(0, 0, 0);
    233 	pcicfgwrite(pchb, 0x78, 0xfc000000);
    234 
    235 	brdtype = BRD_UNKNOWN;
    236 	extclk = EXT_CLK_FREQ;	/* usually 33MHz */
    237 	busclock = 0;
    238 
    239 	dev11 = pcimaketag(0, 11, 0);
    240 	dev12 = pcimaketag(0, 12, 0);
    241 	dev13 = pcimaketag(0, 13, 0);
    242 	dev15 = pcimaketag(0, 15, 0);
    243 	dev16 = pcimaketag(0, 16, 0);
    244 
    245 	if (pcifinddev(0x10ad, 0x0565, &pcib) == 0) {
    246 		/* WinBond 553 southbridge at dev 11 */
    247 		brdtype = BRD_SANDPOINTX3;
    248 	}
    249 	else if (pcifinddev(0x1106, 0x0686, &pcib) == 0) {
    250 		/* VIA 686B southbridge at dev 22 */
    251 		brdtype = BRD_ENCOREPP1;
    252 	}
    253 	else if (PCI_CLASS(pcicfgread(dev11, PCI_CLASS_REG)) == PCI_CLASS_ETH) {
    254 		/* ADMtek AN985 (tlp) or RealTek 8169S (re) at dev 11 */
    255 		if (PCI_VENDOR(pcicfgread(dev12, PCI_ID_REG)) != 0x1095)
    256 			brdtype = BRD_KUROBOX;
    257 		else
    258 			brdtype = BRD_KUROBOXT4;
    259 	}
    260 	else if (PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x11ab) {
    261 		/* SKnet/Marvell (sk) at dev 15 */
    262 		brdtype = BRD_SYNOLOGY;
    263 	}
    264 	else if (PCI_VENDOR(pcicfgread(dev13, PCI_ID_REG)) == 0x1106) {
    265 		/* VIA 6410 (viaide) at dev 13 */
    266 		brdtype = BRD_STORCENTER;
    267 	}
    268 	else if (PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1191) {
    269 		/* ACARD ATP865 (acardide) at dev 16 */
    270 		brdtype = BRD_DLINKDSM;
    271 	}
    272 	else if (PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1283
    273 	    || PCI_VENDOR(pcicfgread(dev16, PCI_ID_REG)) == 0x1095) {
    274 		/* ITE (iteide) or SiI (satalink) at dev 16 */
    275 		brdtype = BRD_NH230NAS;
    276 	}
    277 	else if (PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x8086
    278 	    || PCI_VENDOR(pcicfgread(dev15, PCI_ID_REG)) == 0x10ec) {
    279 		/* Intel (wm) or RealTek (re) at dev 15 */
    280 		brdtype = BRD_QNAPTS;
    281 	}
    282 
    283 	brdprop = brd_lookup(brdtype);
    284 
    285 	/* brd dependent adjustments */
    286 	setup();
    287 
    288 	/* determine clock frequencies */
    289 	if (brdprop->extclk != 0)
    290 		extclk = brdprop->extclk;
    291 	if (busclock == 0) {
    292 		if (cputype() == MPC8245) {
    293 			/* PLL_CFG from PCI host bridge register 0xe2 */
    294 			val = pcicfgread(pchb, 0xe0);
    295 			busclock = (extclk *
    296 			    pci_to_memclk[(val >> 19) & 0x1f] + 10) / 10;
    297 			/* PLLRATIO from HID1 */
    298 			asm volatile ("mfspr %0,1009" : "=r"(val));
    299 			cpuclock = ((uint64_t)busclock *
    300 			    mem_to_cpuclk[val >> 27] + 10) / 10;
    301 		} else
    302 			busclock = 100000000;	/* 100MHz bus clock default */
    303 	}
    304 	ticks_per_sec = busclock >> 2;
    305 	ns_per_tick = 1000000000 / ticks_per_sec;
    306 
    307 	/* now prepare serial console */
    308 	consname = brdprop->consname;
    309 	consport = brdprop->consport;
    310 	if (strcmp(consname, "eumb") == 0) {
    311 		uart1base = 0xfc000000 + consport;	/* 0x4500, 0x4600 */
    312 		UART_WRITE(uart1base, DCR, 0x01);	/* enable DUART mode */
    313 		uart2base = uart1base ^ 0x0300;
    314 	} else
    315 		uart1base = 0xfe000000 + consport;	/* 0x3f8, 0x2f8 */
    316 
    317 	/* more brd adjustments */
    318 	brdfixup();
    319 
    320 	bi_mem.memsize = mpc107memsize();
    321 	snprintf(bi_cons.devname, sizeof(bi_cons.devname), consname);
    322 	bi_cons.addr = consport;
    323 	bi_cons.speed = brdprop->consspeed;
    324 	bi_clk.ticks_per_sec = ticks_per_sec;
    325 	snprintf(bi_fam.name, sizeof(bi_fam.name), brdprop->family);
    326 }
    327 
    328 struct brdprop *
    329 brd_lookup(int brd)
    330 {
    331 	u_int i;
    332 
    333 	for (i = 0; i < sizeof(brdlist)/sizeof(brdlist[0]); i++) {
    334 		if (brdlist[i].brdtype == brd)
    335 			return &brdlist[i];
    336 	}
    337 	return &brdlist[i - 1];
    338 }
    339 
    340 static void
    341 setup()
    342 {
    343 
    344 	if (brdprop->setup == NULL)
    345 		return;
    346 	(*brdprop->setup)(brdprop);
    347 }
    348 
    349 static void
    350 brdfixup()
    351 {
    352 
    353 	if (brdprop->brdfix == NULL)
    354 		return;
    355 	(*brdprop->brdfix)(brdprop);
    356 }
    357 
    358 void
    359 pcifixup()
    360 {
    361 
    362 	if (brdprop->pcifix == NULL)
    363 		return;
    364 	(*brdprop->pcifix)(brdprop);
    365 }
    366 
    367 void
    368 encsetup(struct brdprop *brd)
    369 {
    370 
    371 #ifdef COSNAME
    372 	brd->consname = CONSNAME;
    373 #endif
    374 #ifdef CONSPORT
    375 	brd->consport = CONSPORT;
    376 #endif
    377 #ifdef CONSSPEED
    378 	brd->consspeed = CONSSPEED;
    379 #endif
    380 }
    381 
    382 void
    383 encbrdfix(struct brdprop *brd)
    384 {
    385 	unsigned ac97, ide, pcib, pmgt, usb12, usb34, val;
    386 
    387 /*
    388  * VIA82C686B Southbridge
    389  *	0.22.0	1106.0686	PCI-ISA bridge
    390  *	0.22.1	1106.0571	IDE (viaide)
    391  *	0.22.2	1106.3038	USB 0/1 (uhci)
    392  *	0.22.3	1106.3038	USB 2/3 (uhci)
    393  *	0.22.4	1106.3057	power management
    394  *	0.22.5	1106.3058	AC97 (auvia)
    395  */
    396 	pcib  = pcimaketag(0, 22, 0);
    397 	ide   = pcimaketag(0, 22, 1);
    398 	usb12 = pcimaketag(0, 22, 2);
    399 	usb34 = pcimaketag(0, 22, 3);
    400 	pmgt  = pcimaketag(0, 22, 4);
    401 	ac97  = pcimaketag(0, 22, 5);
    402 
    403 #define	CFG(i,v) do { \
    404    *(volatile unsigned char *)(0xfe000000 + 0x3f0) = (i); \
    405    *(volatile unsigned char *)(0xfe000000 + 0x3f1) = (v); \
    406    } while (0)
    407 	val = pcicfgread(pcib, 0x84);
    408 	val |= (02 << 8);
    409 	pcicfgwrite(pcib, 0x84, val);
    410 	CFG(0xe2, 0x0f); /* use COM1/2, don't use FDC/LPT */
    411 	val = pcicfgread(pcib, 0x84);
    412 	val &= ~(02 << 8);
    413 	pcicfgwrite(pcib, 0x84, val);
    414 
    415 	/* route pin C to i8259 IRQ 5, pin D to 11 */
    416 	val = pcicfgread(pcib, 0x54);
    417 	val = (val & 0xff) | 0xb0500000; /* Dx CB Ax xS */
    418 	pcicfgwrite(pcib, 0x54, val);
    419 
    420 	/* enable EISA ELCR1 (0x4d0) and ELCR2 (0x4d1) */
    421 	val = pcicfgread(pcib, 0x44);
    422 	val = val | 0x20000000;
    423 	pcicfgwrite(pcib, 0x44, val);
    424 
    425 	/* select level trigger for IRQ 5/11 at ELCR1/2 */
    426 	*(volatile uint8_t *)0xfe0004d0 = 0x20; /* bit 5 */
    427 	*(volatile uint8_t *)0xfe0004d1 = 0x08; /* bit 11 */
    428 
    429 	/* USB and AC97 are hardwired with pin D and C */
    430 	val = pcicfgread(usb12, 0x3c) &~ 0xff;
    431 	val |= 11;
    432 	pcicfgwrite(usb12, 0x3c, val);
    433 	val = pcicfgread(usb34, 0x3c) &~ 0xff;
    434 	val |= 11;
    435 	pcicfgwrite(usb34, 0x3c, val);
    436 	val = pcicfgread(ac97, 0x3c) &~ 0xff;
    437 	val |= 5;
    438 	pcicfgwrite(ac97, 0x3c, val);
    439 }
    440 
    441 void
    442 encpcifix(struct brdprop *brd)
    443 {
    444 	unsigned ide, irq, net, pcib, steer, val;
    445 
    446 #define	STEER(v, b) (((v) & (b)) ? "edge" : "level")
    447 	pcib = pcimaketag(0, 22, 0);
    448 	ide  = pcimaketag(0, 22, 1);
    449 	net  = pcimaketag(0, 25, 0);
    450 
    451 	/*
    452 	 * //// VIA PIRQ ////
    453 	 * 0x57/56/55/54 - Dx CB Ax xS
    454 	 */
    455 	val = pcicfgread(pcib, 0x54);	/* Dx CB Ax xs */
    456 	steer = val & 0xf;
    457 	irq = (val >> 12) & 0xf;	/* 15:12 */
    458 	if (irq) {
    459 		printf("pin A -> irq %d, %s\n",
    460 			irq, STEER(steer, 0x1));
    461 	}
    462 	irq = (val >> 16) & 0xf;	/* 19:16 */
    463 	if (irq) {
    464 		printf("pin B -> irq %d, %s\n",
    465 			irq, STEER(steer, 0x2));
    466 	}
    467 	irq = (val >> 20) & 0xf;	/* 23:20 */
    468 	if (irq) {
    469 		printf("pin C -> irq %d, %s\n",
    470 			irq, STEER(steer, 0x4));
    471 	}
    472 	irq = (val >> 28);		/* 31:28 */
    473 	if (irq) {
    474 		printf("pin D -> irq %d, %s\n",
    475 			irq, STEER(steer, 0x8));
    476 	}
    477 #if 0
    478 	/*
    479 	 * //// IDE fixup ////
    480 	 * - "native mode" (ide 0x09)
    481 	 */
    482 
    483 	/* ide: 0x09 - programming interface; 1000'SsPp */
    484 	val = pcicfgread(ide, 0x08) & 0xffff00ff;
    485 	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
    486 
    487 	/* ide: 0x10-20 - leave them PCI memory space assigned */
    488 #else
    489 	/*
    490 	 * //// IDE fixup ////
    491 	 * - "compatiblity mode" (ide 0x09)
    492 	 * - remove PCI pin assignment (ide 0x3d)
    493 	 */
    494 
    495 	/* ide: 0x09 - programming interface; 1000'SsPp */
    496 	val = pcicfgread(ide, 0x08) & 0xffff00ff;
    497 	val |= (0x8a << 8);
    498 	pcicfgwrite(ide, 0x08, val);
    499 
    500 	/* ide: 0x10-20 */
    501 	/*
    502 	 * experiment shows writing ide: 0x09 changes these
    503 	 * register behaviour. The pcicfgwrite() above writes
    504 	 * 0x8a at ide: 0x09 to make sure legacy IDE.  Then
    505 	 * reading BAR0-3 is to return value 0s even though
    506 	 * pcisetup() has written range assignments.  Value
    507 	 * overwrite makes no effect. Having 0x8f for native
    508 	 * PCIIDE doesn't change register values and brings no
    509 	 * weirdness.
    510 	 */
    511 
    512 	/* ide: 0x3d/3c - turn off PCI pin */
    513 	val = pcicfgread(ide, 0x3c) & 0xffff00ff;
    514 	pcicfgwrite(ide, 0x3c, val);
    515 #endif
    516 	/*
    517 	 * //// USBx2, audio, and modem fixup ////
    518 	 * - disable USB #0 and #1 (pcib 0x48 and 0x85)
    519 	 * - disable AC97 audio and MC97 modem (pcib 0x85)
    520 	 */
    521 
    522 	/* pcib: 0x48 - disable USB #0 at function 2 */
    523 	val = pcicfgread(pcib, 0x48);
    524 	pcicfgwrite(pcib, 0x48, val | 04);
    525 
    526 	/* pcib: 0x85 - disable USB #1 at function 3 */
    527 	/* pcib: 0x85 - disable AC97/MC97 at function 5/6 */
    528 	val = pcicfgread(pcib, 0x84);
    529 	pcicfgwrite(pcib, 0x84, val | 0x1c00);
    530 
    531 	/*
    532 	 * //// fxp fixup ////
    533 	 * - use PCI pin A line 25 (fxp 0x3d/3c)
    534 	 */
    535 	/* 0x3d/3c - PCI pin/line */
    536 	val = pcicfgread(net, 0x3c) & 0xffff0000;
    537 	val |= (('A' - '@') << 8) | 25;
    538 	pcicfgwrite(net, 0x3c, val);
    539 }
    540 
    541 void
    542 motsetup(struct brdprop *brd)
    543 {
    544 
    545 #ifdef COSNAME
    546 	brd->consname = CONSNAME;
    547 #endif
    548 #ifdef CONSPORT
    549 	brd->consport = CONSPORT;
    550 #endif
    551 #ifdef CONSSPEED
    552 	brd->consspeed = CONSSPEED;
    553 #endif
    554 }
    555 
    556 void
    557 motbrdfix(struct brdprop *brd)
    558 {
    559 
    560 /*
    561  * WinBond/Symphony Lab 83C553 with PC87308 "SuperIO"
    562  *
    563  *	0.11.0	10ad.0565	PCI-ISA bridge
    564  *	0.11.1	10ad.0105	IDE (slide)
    565  */
    566 }
    567 
    568 void
    569 motpcifix(struct brdprop *brd)
    570 {
    571 	unsigned ide, net, pcib, steer, val;
    572 	int line;
    573 
    574 	pcib = pcimaketag(0, 11, 0);
    575 	ide  = pcimaketag(0, 11, 1);
    576 	net  = pcimaketag(0, 15, 0);
    577 
    578 	/*
    579 	 * //// WinBond PIRQ ////
    580 	 * 0x40 - bit 5 (0x20) indicates PIRQ presense
    581 	 * 0x60 - PIRQ interrupt routing steer
    582 	 */
    583 	if (pcicfgread(pcib, 0x40) & 0x20) {
    584 		steer = pcicfgread(pcib, 0x60);
    585 		if ((steer & 0x80808080) == 0x80808080)
    586 			printf("PIRQ[0-3] disabled\n");
    587 		else {
    588 			unsigned i, v = steer;
    589 			for (i = 0; i < 4; i++, v >>= 8) {
    590 				if ((v & 0x80) != 0 || (v & 0xf) == 0)
    591 					continue;
    592 				printf("PIRQ[%d]=%d\n", i, v & 0xf);
    593 				}
    594 			}
    595 		}
    596 #if 1
    597 	/*
    598 	 * //// IDE fixup -- case A ////
    599 	 * - "native PCI mode" (ide 0x09)
    600 	 * - don't use ISA IRQ14/15 (pcib 0x43)
    601 	 * - native IDE for both channels (ide 0x40)
    602 	 * - LEGIRQ bit 11 steers interrupt to pin C (ide 0x40)
    603 	 * - sign as PCI pin C line 11 (ide 0x3d/3c)
    604 	 */
    605 	/* ide: 0x09 - programming interface; 1000'SsPp */
    606 	val = pcicfgread(ide, 0x08);
    607 	val &= 0xffff00ff;
    608 	pcicfgwrite(ide, 0x08, val | (0x8f << 8));
    609 
    610 	/* pcib: 0x43 - IDE interrupt routing */
    611 	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
    612 	pcicfgwrite(pcib, 0x40, val);
    613 
    614 	/* pcib: 0x45/44 - PCI interrupt routing */
    615 	val = pcicfgread(pcib, 0x44) & 0xffff0000;
    616 	pcicfgwrite(pcib, 0x44, val);
    617 
    618 	/* ide: 0x41/40 - IDE channel */
    619 	val = pcicfgread(ide, 0x40) & 0xffff0000;
    620 	val |= (1 << 11) | 0x33; /* LEGIRQ turns on PCI interrupt */
    621 	pcicfgwrite(ide, 0x40, val);
    622 
    623 	/* ide: 0x3d/3c - use PCI pin C/line 11 */
    624 	val = pcicfgread(ide, 0x3c) & 0xffffff00;
    625 	val |= 11; /* pin designation is hardwired to pin A */
    626 	pcicfgwrite(ide, 0x3c, val);
    627 #else
    628 	/*
    629 	 * //// IDE fixup -- case B ////
    630 	 * - "compatiblity mode" (ide 0x09)
    631 	 * - IDE primary/secondary interrupt routing (pcib 0x43)
    632 	 * - PCI interrupt routing (pcib 0x45/44)
    633 	 * - no PCI pin/line assignment (ide 0x3d/3c)
    634 	 */
    635 	/* ide: 0x09 - programming interface; 1000'SsPp */
    636 	val = pcicfgread(ide, 0x08);
    637 	val &= 0xffff00ff;
    638 	pcicfgwrite(ide, 0x08, val | (0x8a << 8));
    639 
    640 	/* pcib: 0x43 - IDE interrupt routing */
    641 	val = pcicfgread(pcib, 0x40) & 0x00ffffff;
    642 	pcicfgwrite(pcib, 0x40, val | (0xee << 24));
    643 
    644 	/* ide: 0x45/44 - PCI interrupt routing */
    645 	val = pcicfgread(ide, 0x44) & 0xffff0000;
    646 	pcicfgwrite(ide, 0x44, val);
    647 
    648 	/* ide: 0x3d/3c - turn off PCI pin/line */
    649 	val = pcicfgread(ide, 0x3c) & 0xffff0000;
    650 	pcicfgwrite(ide, 0x3c, val);
    651 #endif
    652 
    653 	/*
    654 	 * //// fxp fixup ////
    655 	 * - use PCI pin A line 15 (fxp 0x3d/3c)
    656 	 */
    657 	val = pcicfgread(net, 0x3c) & 0xffff0000;
    658 	pcidecomposetag(net, NULL, &line, NULL);
    659 	val |= (('A' - '@') << 8) | line;
    660 	pcicfgwrite(net, 0x3c, val);
    661 }
    662 
    663 void
    664 kurosetup(struct brdprop *brd)
    665 {
    666 
    667 	if (PCI_VENDOR(pcicfgread(pcimaketag(0, 11, 0), PCI_ID_REG)) == 0x10ec)
    668 		brd->extclk = 32768000; /* decr 2457600Hz */
    669 	else
    670 		brd->extclk = 32521333; /* decr 2439100Hz */
    671 }
    672 
    673 void
    674 kurobrdfix(struct brdprop *brd)
    675 {
    676 
    677 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PEVEN);
    678 	/* Stop Watchdog */
    679 	send_sat("AAAAFFFFJJJJ>>>>VVVV>>>>ZZZZVVVVKKKK");
    680 }
    681 
    682 void
    683 kuroreset()
    684 {
    685 
    686 	send_sat("CCGG");
    687 	/*NOTREACHED*/
    688 }
    689 
    690 void
    691 synosetup(struct brdprop *brd)
    692 {
    693 
    694 	if (1) /* 200 and 266MHz models */
    695 		brd->extclk = 33164691; /* from Synology/Linux source */
    696 	else   /* 400MHz models XXX how to check? */
    697 		brd->extclk = 33165343;
    698 }
    699 
    700 void
    701 synobrdfix(struct brdprop *brd)
    702 {
    703 
    704 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
    705 	/* beep, power LED on, status LED off */
    706 	send_sat("247");
    707 }
    708 
    709 void
    710 synoreset()
    711 {
    712 
    713 	send_sat("C");
    714 	/*NOTREACHED*/
    715 }
    716 
    717 void
    718 qnapbrdfix(struct brdprop *brd)
    719 {
    720 
    721 	init_uart(uart2base, 19200, LCR_8BITS | LCR_PNONE);
    722 	/* beep, status LED red */
    723 	send_sat("PW");
    724 }
    725 
    726 void
    727 qnapreset()
    728 {
    729 
    730 	send_sat("f");
    731 	/*NOTREACHED*/
    732 }
    733 
    734 void
    735 iomegabrdfix(struct brdprop *brd)
    736 {
    737 
    738 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
    739 	/* LED flashing blue, fan auto, turn on at 50C, turn off at 45C */
    740 	send_iomega('b', 'd', 2, 'a', 50, 45);
    741 }
    742 
    743 void
    744 iomegareset()
    745 {
    746 
    747 	send_iomega('g', 0, 0, 0, 0, 0);
    748 	/*NOTREACHED*/
    749 }
    750 
    751 void
    752 dlinkbrdfix(struct brdprop *brd)
    753 {
    754 
    755 	init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE);
    756 	send_sat("SYN\n");
    757 	send_sat("ZWO\n");	/* power LED solid on */
    758 }
    759 
    760 void
    761 nhnasbrdfix(struct brdprop *brd)
    762 {
    763 
    764 	/* status LED off, USB-LEDs on, low-speed fan */
    765 	NHGPIO_WRITE(0x04);
    766 }
    767 
    768 void
    769 nhnasreset()
    770 {
    771 
    772 	/* status LED on, assert system-reset to all devices */
    773 	NHGPIO_WRITE(0x02);
    774 	delay(100000);
    775 	/*NOTREACHED*/
    776 }
    777 
    778 void
    779 kurot4brdfix(struct brdprop *brd)
    780 {
    781 
    782 	init_uart(uart2base, 38400, LCR_8BITS | LCR_PEVEN);
    783 }
    784 
    785 void
    786 _rtt(void)
    787 {
    788 	uint32_t msr;
    789 
    790 	netif_shutdown_all();
    791 
    792 	if (brdprop->reset != NULL)
    793 		(*brdprop->reset)();
    794 	else {
    795 		msr = mfmsr();
    796 		msr &= ~PSL_EE;
    797 		mtmsr(msr);
    798 		asm volatile ("sync; isync");
    799 		asm volatile("mtspr %0,%1" : : "K"(81), "r"(0));
    800 		msr &= ~(PSL_ME | PSL_DR | PSL_IR);
    801 		mtmsr(msr);
    802 		asm volatile ("sync; isync");
    803 		run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */
    804 	}
    805 	/*NOTREACHED*/
    806 }
    807 
    808 satime_t
    809 getsecs(void)
    810 {
    811 	u_quad_t tb = mftb();
    812 
    813 	return (tb / ticks_per_sec);
    814 }
    815 
    816 /*
    817  * Wait for about n microseconds (at least!).
    818  */
    819 void
    820 delay(u_int n)
    821 {
    822 	u_quad_t tb;
    823 	u_long scratch, tbh, tbl;
    824 
    825 	tb = mftb();
    826 	tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
    827 	tbh = tb >> 32;
    828 	tbl = tb;
    829 	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));
    830 }
    831 
    832 void
    833 _wb(uint32_t adr, uint32_t siz)
    834 {
    835 	uint32_t bnd;
    836 
    837 	asm volatile("eieio");
    838 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
    839 		asm volatile ("dcbst 0,%0" :: "r"(adr));
    840 	asm volatile ("sync");
    841 }
    842 
    843 void
    844 _wbinv(uint32_t adr, uint32_t siz)
    845 {
    846 	uint32_t bnd;
    847 
    848 	asm volatile("eieio");
    849 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
    850 		asm volatile ("dcbf 0,%0" :: "r"(adr));
    851 	asm volatile ("sync");
    852 }
    853 
    854 void
    855 _inv(uint32_t adr, uint32_t siz)
    856 {
    857 	uint32_t bnd, off;
    858 
    859 	off = adr & (dcache_line_size - 1);
    860 	adr -= off;
    861 	siz += off;
    862 	asm volatile ("eieio");
    863 	if (off != 0) {
    864 		/* wbinv() leading unaligned dcache line */
    865 		asm volatile ("dcbf 0,%0" :: "r"(adr));
    866 		if (siz < dcache_line_size)
    867 			goto done;
    868 		adr += dcache_line_size;
    869 		siz -= dcache_line_size;
    870 	}
    871 	bnd = adr + siz;
    872 	off = bnd & (dcache_line_size - 1);
    873 	if (off != 0) {
    874 		/* wbinv() trailing unaligned dcache line */
    875 		asm volatile ("dcbf 0,%0" :: "r"(bnd)); /* it's OK */
    876 		if (siz < dcache_line_size)
    877 			goto done;
    878 		siz -= off;
    879 	}
    880 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) {
    881 		/* inv() intermediate dcache lines if ever */
    882 		asm volatile ("dcbi 0,%0" :: "r"(adr));
    883 	}
    884   done:
    885 	asm volatile ("sync");
    886 }
    887 
    888 static inline uint32_t
    889 mfmsr(void)
    890 {
    891 	uint32_t msr;
    892 
    893 	asm volatile ("mfmsr %0" : "=r"(msr));
    894 	return msr;
    895 }
    896 
    897 static inline void
    898 mtmsr(uint32_t msr)
    899 {
    900 	asm volatile ("mtmsr %0" : : "r"(msr));
    901 }
    902 
    903 static inline uint32_t
    904 cputype(void)
    905 {
    906 	uint32_t pvr;
    907 
    908 	asm volatile ("mfpvr %0" : "=r"(pvr));
    909 	return pvr >> 16;
    910 }
    911 
    912 static inline u_quad_t
    913 mftb(void)
    914 {
    915 	u_long scratch;
    916 	u_quad_t tb;
    917 
    918 	asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b"
    919 	    : "=r"(tb), "=r"(scratch));
    920 	return tb;
    921 }
    922 
    923 static void
    924 init_uart(unsigned base, unsigned speed, uint8_t lcr)
    925 {
    926 	unsigned div;
    927 
    928 	div = busclock / speed / 16;
    929 	UART_WRITE(base, LCR, 0x80);		/* turn on DLAB bit */
    930 	UART_WRITE(base, FCR, 0x00);
    931 	UART_WRITE(base, DMB, div >> 8);	/* set speed */
    932 	UART_WRITE(base, DLB, div & 0xff);
    933 	UART_WRITE(base, LCR, lcr);
    934 	UART_WRITE(base, FCR, 0x07);		/* FIFO on, TXRX FIFO reset */
    935 	UART_WRITE(base, IER, 0x00);		/* make sure INT disabled */
    936 }
    937 
    938 /* talk to satellite processor */
    939 static void
    940 send_sat(char *msg)
    941 {
    942 	unsigned savedbase;
    943 
    944 	savedbase = uart1base;
    945 	uart1base = uart2base;
    946 	while (*msg)
    947 		putchar(*msg++);
    948 	uart1base = savedbase;
    949 }
    950 
    951 #ifdef DEBUG
    952 static void
    953 iomega_debug(const char *txt, uint8_t buf[])
    954 {
    955 	int i;
    956 
    957 	printf("%s:", txt);
    958 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
    959 		printf(" %02x", buf[i]);
    960 	putchar('\n');
    961 }
    962 #endif /* DEBUG */
    963 
    964 static void
    965 send_iomega(int power, int led, int rate, int fan, int high, int low)
    966 {
    967 	uint8_t buf[IOMEGA_PACKETSIZE];
    968 	unsigned i, savedbase;
    969 
    970 	savedbase = uart1base;
    971 	uart1base = uart2base;
    972 
    973 	/* first flush the receive buffer */
    974   again:
    975 	while (tstchar())
    976 		(void)getchar();
    977 	delay(20000);
    978 	if (tstchar())
    979 		goto again;
    980 	/*
    981 	 * Now synchronize the transmitter by sending 0x00
    982 	 * until we receive a status reply.
    983 	 */
    984 	do {
    985 		putchar(0);
    986 		delay(50000);
    987 	} while (!tstchar());
    988 
    989 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
    990 		buf[i] = getchar();
    991 #ifdef DEBUG
    992 	uart1base = savedbase;
    993 	iomega_debug("68HC908 status", buf);
    994 	uart1base = uart2base;
    995 #endif
    996 
    997 	/* send command */
    998 	buf[IOMEGA_POWER] = power;
    999 	buf[IOMEGA_LED] = led;
   1000 	buf[IOMEGA_FLASH_RATE] = rate;
   1001 	buf[IOMEGA_FAN] = fan;
   1002 	buf[IOMEGA_HIGH_TEMP] = high;
   1003 	buf[IOMEGA_LOW_TEMP] = low;
   1004 	buf[IOMEGA_ID] = 7;	/* host id */
   1005 	buf[IOMEGA_CHECKSUM] = (buf[IOMEGA_POWER] + buf[IOMEGA_LED] +
   1006 	    buf[IOMEGA_FLASH_RATE] + buf[IOMEGA_FAN] +
   1007 	    buf[IOMEGA_HIGH_TEMP] + buf[IOMEGA_LOW_TEMP] +
   1008 	    buf[IOMEGA_ID]) & 0x7f;
   1009 #ifdef DEBUG
   1010 	uart1base = savedbase;
   1011 	iomega_debug("G2 sending", buf);
   1012 	uart1base = uart2base;
   1013 #endif
   1014 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
   1015 		putchar(buf[i]);
   1016 
   1017 	/* receive the reply */
   1018 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
   1019 		buf[i] = getchar();
   1020 #ifdef DEBUG
   1021 	uart1base = savedbase;
   1022 	iomega_debug("68HC908 reply", buf);
   1023 	uart1base = uart2base;
   1024 #endif
   1025 
   1026 	if (buf[0] == '#')
   1027 		goto again;  /* try again on error */
   1028 	uart1base = savedbase;
   1029 }
   1030 
   1031 void
   1032 putchar(int c)
   1033 {
   1034 	unsigned timo, lsr;
   1035 
   1036 	if (c == '\n')
   1037 		putchar('\r');
   1038 
   1039 	timo = 0x00100000;
   1040 	do {
   1041 		lsr = UART_READ(uart1base, LSR);
   1042 	} while (timo-- > 0 && (lsr & LSR_THRE) == 0);
   1043 	if (timo > 0)
   1044 		UART_WRITE(uart1base, THR, c);
   1045 }
   1046 
   1047 int
   1048 getchar(void)
   1049 {
   1050 	unsigned lsr;
   1051 
   1052 	do {
   1053 		lsr = UART_READ(uart1base, LSR);
   1054 	} while ((lsr & LSR_DRDY) == 0);
   1055 	return UART_READ(uart1base, RBR);
   1056 }
   1057 
   1058 int
   1059 tstchar(void)
   1060 {
   1061 
   1062 	return (UART_READ(uart1base, LSR) & LSR_DRDY) != 0;
   1063 }
   1064 
   1065 #define SAR_MASK 0x0ff00000
   1066 #define SAR_SHIFT    20
   1067 #define EAR_MASK 0x30000000
   1068 #define EAR_SHIFT    28
   1069 #define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s))
   1070 #define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s))
   1071 static void
   1072 set_mem_bounds(unsigned tag, unsigned bk_en, ...)
   1073 {
   1074 	unsigned mbst, mbxst, mben, mbxen;
   1075 	unsigned start, end;
   1076 	va_list ap;
   1077 	int i, sh;
   1078 
   1079 	va_start(ap, bk_en);
   1080 	mbst = mbxst = mben = mbxen = 0;
   1081 
   1082 	for (i = 0; i < 4; i++) {
   1083 		if ((bk_en & (1U << i)) != 0) {
   1084 			start = va_arg(ap, unsigned);
   1085 			end = va_arg(ap, unsigned);
   1086 		} else {
   1087 			start = 0x3ff00000;
   1088 			end = 0x3fffffff;
   1089 		}
   1090 		sh = i << 3;
   1091 		mbst |= AR(start, sh);
   1092 		mbxst |= XR(start, sh);
   1093 		mben |= AR(end, sh);
   1094 		mbxen |= XR(end, sh);
   1095 	}
   1096 	va_end(ap);
   1097 
   1098 	pcicfgwrite(tag, MPC106_MEMSTARTADDR1, mbst);
   1099 	pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, mbxst);
   1100 	pcicfgwrite(tag, MPC106_MEMENDADDR1, mben);
   1101 	pcicfgwrite(tag, MPC106_EXTMEMENDADDR1,	mbxen);
   1102 	pcicfgwrite(tag, MPC106_MEMEN,
   1103 	    (pcicfgread(tag, MPC106_MEMEN) & ~0xff) | (bk_en & 0xff));
   1104 }
   1105 
   1106 static unsigned
   1107 mpc107memsize(void)
   1108 {
   1109 	unsigned bankn, end, n, tag, val;
   1110 
   1111 	tag = pcimaketag(0, 0, 0);
   1112 
   1113 	if (brdtype == BRD_ENCOREPP1) {
   1114 		/* the brd's PPCBOOT looks to have erroneous values */
   1115 		set_mem_bounds(tag, 1, 0x00000000, (128 << 20) - 1);
   1116 	} else if (brdtype == BRD_NH230NAS) {
   1117 		/*
   1118 		 * PPCBoot sets the end address to 0x7ffffff, although the
   1119 		 * board has just 64MB (0x3ffffff).
   1120 		 */
   1121 		set_mem_bounds(tag, 1, 0x00000000, 0x03ffffff);
   1122 	}
   1123 
   1124 	bankn = 0;
   1125 	val = pcicfgread(tag, MPC106_MEMEN);
   1126 	for (n = 0; n < 4; n++) {
   1127 		if ((val & (1U << n)) == 0)
   1128 			break;
   1129 		bankn = n;
   1130 	}
   1131 	bankn <<= 3;
   1132 
   1133 	val = pcicfgread(tag, MPC106_EXTMEMENDADDR1);
   1134 	end =  ((val >> bankn) & 0x03) << 28;
   1135 	val = pcicfgread(tag, MPC106_MEMENDADDR1);
   1136 	end |= ((val >> bankn) & 0xff) << 20;
   1137 	end |= 0xfffff;
   1138 
   1139 	return (end + 1); /* assume the end address matches total amount */
   1140 }
   1141 
   1142 struct fis_dir_entry {
   1143 	char		name[16];
   1144 	uint32_t	startaddr;
   1145 	uint32_t	loadaddr;
   1146 	uint32_t	flashsize;
   1147 	uint32_t	entryaddr;
   1148 	uint32_t	filesize;
   1149 	char		pad[256 - (16 + 5 * sizeof(uint32_t))];
   1150 };
   1151 
   1152 #define FIS_LOWER_LIMIT	0xfff00000
   1153 
   1154 /*
   1155  * Look for a Redboot-style Flash Image System FIS-directory and
   1156  * return a pointer to the start address of the requested file.
   1157  */
   1158 static void *
   1159 redboot_fis_lookup(const char *filename)
   1160 {
   1161 	static const char FISdirname[16] = {
   1162 	    'F', 'I', 'S', ' ',
   1163 	    'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0
   1164 	};
   1165 	struct fis_dir_entry *dir;
   1166 
   1167 	/*
   1168 	 * The FIS directory is usually in the last sector of the flash.
   1169 	 * But we do not know the sector size (erase size), so start
   1170 	 * at 0xffffff00 and scan backwards in steps of the FIS directory
   1171 	 * entry size (0x100).
   1172 	 */
   1173 	for (dir = (struct fis_dir_entry *)0xffffff00;
   1174 	    (uint32_t)dir >= FIS_LOWER_LIMIT; dir--)
   1175 		if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0)
   1176 			break;
   1177 	if ((uint32_t)dir < FIS_LOWER_LIMIT) {
   1178 		printf("No FIS directory found!\n");
   1179 		return NULL;
   1180 	}
   1181 
   1182 	/* Now find filename by scanning the directory from beginning. */
   1183 	dir = (struct fis_dir_entry *)dir->startaddr;
   1184 	while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) {
   1185 		if (strcmp(dir->name, filename) == 0)
   1186 			return (void *)dir->startaddr;	/* found */
   1187 		dir++;
   1188 	}
   1189 	printf("\"%s\" not found in FIS directory!\n", filename);
   1190 	return NULL;
   1191 }
   1192 
   1193 static void
   1194 read_mac_string(uint8_t *mac, char *p)
   1195 {
   1196 	int i;
   1197 
   1198 	for (i = 0; i < 6; i++, p += 3)
   1199 		*mac++ = read_hex(p);
   1200 }
   1201 
   1202 /*
   1203  * For cost saving reasons some NAS boxes lack SEEPROM for NIC's
   1204  * ethernet address and keep it in their Flash memory instead.
   1205  */
   1206 void
   1207 read_mac_from_flash(uint8_t *mac)
   1208 {
   1209 	uint8_t *p;
   1210 
   1211 	switch (brdtype) {
   1212 	case BRD_SYNOLOGY:
   1213 		p = redboot_fis_lookup("vendor");
   1214 		if (p == NULL)
   1215 			break;
   1216 		memcpy(mac, p, 6);
   1217 		return;
   1218 	case BRD_DLINKDSM:
   1219 		read_mac_string(mac, (char *)0xfff0ff80);
   1220 		return;
   1221 	default:
   1222 		printf("Warning: This board has no known method defined "
   1223 		    "to determine its MAC address!\n");
   1224 		break;
   1225 	}
   1226 
   1227 	/* set to 00:00:00:00:00:00 in case of error */
   1228 	memset(mac, 0, 6);
   1229 }
   1230 
   1231 #ifdef DEBUG
   1232 void
   1233 sat_write(char *p, int len)
   1234 {
   1235 	unsigned savedbase;
   1236 
   1237 	savedbase = uart1base;
   1238 	uart1base = uart2base;
   1239 	while (len--)
   1240 		putchar(*p++);
   1241 	uart1base = savedbase;
   1242 }
   1243 
   1244 int
   1245 sat_getch(void)
   1246 {
   1247 	unsigned lsr;
   1248 
   1249 	do {
   1250 		lsr = UART_READ(uart2base, LSR);
   1251 	} while ((lsr & LSR_DRDY) == 0);
   1252 	return UART_READ(uart2base, RBR);
   1253 }
   1254 
   1255 int
   1256 sat_tstch(void)
   1257 {
   1258 
   1259 	return (UART_READ(uart2base, LSR) & LSR_DRDY) != 0;
   1260 }
   1261 #endif /* DEBUG */
   1262