Home | History | Annotate | Line # | Download | only in altboot
brdsetup.c revision 1.29
      1 /* $NetBSD: brdsetup.c,v 1.29 2012/04/09 13:26:37 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 	0,
    178 	"eumb", 0x4600, 57600,
    179 	kurot4setup, 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 kurot4setup(struct brdprop *brd)
    780 {
    781 
    782 	if (PCI_VENDOR(pcicfgread(pcimaketag(0, 11, 0), PCI_ID_REG)) == 0x10ec)
    783 		brd->extclk = 32768000; /* decr 2457600Hz */
    784 	else
    785 		brd->extclk = 32521333; /* decr 2439100Hz */
    786 }
    787 
    788 void
    789 kurot4brdfix(struct brdprop *brd)
    790 {
    791 
    792 	init_uart(uart2base, 38400, LCR_8BITS | LCR_PEVEN);
    793 }
    794 
    795 void
    796 _rtt(void)
    797 {
    798 	uint32_t msr;
    799 
    800 	netif_shutdown_all();
    801 
    802 	if (brdprop->reset != NULL)
    803 		(*brdprop->reset)();
    804 	else {
    805 		msr = mfmsr();
    806 		msr &= ~PSL_EE;
    807 		mtmsr(msr);
    808 		asm volatile ("sync; isync");
    809 		asm volatile("mtspr %0,%1" : : "K"(81), "r"(0));
    810 		msr &= ~(PSL_ME | PSL_DR | PSL_IR);
    811 		mtmsr(msr);
    812 		asm volatile ("sync; isync");
    813 		run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */
    814 	}
    815 	/*NOTREACHED*/
    816 }
    817 
    818 satime_t
    819 getsecs(void)
    820 {
    821 	u_quad_t tb = mftb();
    822 
    823 	return (tb / ticks_per_sec);
    824 }
    825 
    826 /*
    827  * Wait for about n microseconds (at least!).
    828  */
    829 void
    830 delay(u_int n)
    831 {
    832 	u_quad_t tb;
    833 	u_long scratch, tbh, tbl;
    834 
    835 	tb = mftb();
    836 	tb += (n * 1000 + ns_per_tick - 1) / ns_per_tick;
    837 	tbh = tb >> 32;
    838 	tbl = tb;
    839 	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));
    840 }
    841 
    842 void
    843 _wb(uint32_t adr, uint32_t siz)
    844 {
    845 	uint32_t bnd;
    846 
    847 	asm volatile("eieio");
    848 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
    849 		asm volatile ("dcbst 0,%0" :: "r"(adr));
    850 	asm volatile ("sync");
    851 }
    852 
    853 void
    854 _wbinv(uint32_t adr, uint32_t siz)
    855 {
    856 	uint32_t bnd;
    857 
    858 	asm volatile("eieio");
    859 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size)
    860 		asm volatile ("dcbf 0,%0" :: "r"(adr));
    861 	asm volatile ("sync");
    862 }
    863 
    864 void
    865 _inv(uint32_t adr, uint32_t siz)
    866 {
    867 	uint32_t bnd, off;
    868 
    869 	off = adr & (dcache_line_size - 1);
    870 	adr -= off;
    871 	siz += off;
    872 	asm volatile ("eieio");
    873 	if (off != 0) {
    874 		/* wbinv() leading unaligned dcache line */
    875 		asm volatile ("dcbf 0,%0" :: "r"(adr));
    876 		if (siz < dcache_line_size)
    877 			goto done;
    878 		adr += dcache_line_size;
    879 		siz -= dcache_line_size;
    880 	}
    881 	bnd = adr + siz;
    882 	off = bnd & (dcache_line_size - 1);
    883 	if (off != 0) {
    884 		/* wbinv() trailing unaligned dcache line */
    885 		asm volatile ("dcbf 0,%0" :: "r"(bnd)); /* it's OK */
    886 		if (siz < dcache_line_size)
    887 			goto done;
    888 		siz -= off;
    889 	}
    890 	for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) {
    891 		/* inv() intermediate dcache lines if ever */
    892 		asm volatile ("dcbi 0,%0" :: "r"(adr));
    893 	}
    894   done:
    895 	asm volatile ("sync");
    896 }
    897 
    898 static inline uint32_t
    899 mfmsr(void)
    900 {
    901 	uint32_t msr;
    902 
    903 	asm volatile ("mfmsr %0" : "=r"(msr));
    904 	return msr;
    905 }
    906 
    907 static inline void
    908 mtmsr(uint32_t msr)
    909 {
    910 	asm volatile ("mtmsr %0" : : "r"(msr));
    911 }
    912 
    913 static inline uint32_t
    914 cputype(void)
    915 {
    916 	uint32_t pvr;
    917 
    918 	asm volatile ("mfpvr %0" : "=r"(pvr));
    919 	return pvr >> 16;
    920 }
    921 
    922 static inline u_quad_t
    923 mftb(void)
    924 {
    925 	u_long scratch;
    926 	u_quad_t tb;
    927 
    928 	asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b"
    929 	    : "=r"(tb), "=r"(scratch));
    930 	return tb;
    931 }
    932 
    933 static void
    934 init_uart(unsigned base, unsigned speed, uint8_t lcr)
    935 {
    936 	unsigned div;
    937 
    938 	div = busclock / speed / 16;
    939 	UART_WRITE(base, LCR, 0x80);		/* turn on DLAB bit */
    940 	UART_WRITE(base, FCR, 0x00);
    941 	UART_WRITE(base, DMB, div >> 8);	/* set speed */
    942 	UART_WRITE(base, DLB, div & 0xff);
    943 	UART_WRITE(base, LCR, lcr);
    944 	UART_WRITE(base, FCR, 0x07);		/* FIFO on, TXRX FIFO reset */
    945 	UART_WRITE(base, IER, 0x00);		/* make sure INT disabled */
    946 }
    947 
    948 /* talk to satellite processor */
    949 static void
    950 send_sat(char *msg)
    951 {
    952 	unsigned savedbase;
    953 
    954 	savedbase = uart1base;
    955 	uart1base = uart2base;
    956 	while (*msg)
    957 		putchar(*msg++);
    958 	uart1base = savedbase;
    959 }
    960 
    961 #ifdef DEBUG
    962 static void
    963 iomega_debug(const char *txt, uint8_t buf[])
    964 {
    965 	int i;
    966 
    967 	printf("%s:", txt);
    968 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
    969 		printf(" %02x", buf[i]);
    970 	putchar('\n');
    971 }
    972 #endif /* DEBUG */
    973 
    974 static void
    975 send_iomega(int power, int led, int rate, int fan, int high, int low)
    976 {
    977 	uint8_t buf[IOMEGA_PACKETSIZE];
    978 	unsigned i, savedbase;
    979 
    980 	savedbase = uart1base;
    981 	uart1base = uart2base;
    982 
    983 	/* first flush the receive buffer */
    984   again:
    985 	while (tstchar())
    986 		(void)getchar();
    987 	delay(20000);
    988 	if (tstchar())
    989 		goto again;
    990 	/*
    991 	 * Now synchronize the transmitter by sending 0x00
    992 	 * until we receive a status reply.
    993 	 */
    994 	do {
    995 		putchar(0);
    996 		delay(50000);
    997 	} while (!tstchar());
    998 
    999 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
   1000 		buf[i] = getchar();
   1001 #ifdef DEBUG
   1002 	uart1base = savedbase;
   1003 	iomega_debug("68HC908 status", buf);
   1004 	uart1base = uart2base;
   1005 #endif
   1006 
   1007 	/* send command */
   1008 	buf[IOMEGA_POWER] = power;
   1009 	buf[IOMEGA_LED] = led;
   1010 	buf[IOMEGA_FLASH_RATE] = rate;
   1011 	buf[IOMEGA_FAN] = fan;
   1012 	buf[IOMEGA_HIGH_TEMP] = high;
   1013 	buf[IOMEGA_LOW_TEMP] = low;
   1014 	buf[IOMEGA_ID] = 7;	/* host id */
   1015 	buf[IOMEGA_CHECKSUM] = (buf[IOMEGA_POWER] + buf[IOMEGA_LED] +
   1016 	    buf[IOMEGA_FLASH_RATE] + buf[IOMEGA_FAN] +
   1017 	    buf[IOMEGA_HIGH_TEMP] + buf[IOMEGA_LOW_TEMP] +
   1018 	    buf[IOMEGA_ID]) & 0x7f;
   1019 #ifdef DEBUG
   1020 	uart1base = savedbase;
   1021 	iomega_debug("G2 sending", buf);
   1022 	uart1base = uart2base;
   1023 #endif
   1024 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
   1025 		putchar(buf[i]);
   1026 
   1027 	/* receive the reply */
   1028 	for (i = 0; i < IOMEGA_PACKETSIZE; i++)
   1029 		buf[i] = getchar();
   1030 #ifdef DEBUG
   1031 	uart1base = savedbase;
   1032 	iomega_debug("68HC908 reply", buf);
   1033 	uart1base = uart2base;
   1034 #endif
   1035 
   1036 	if (buf[0] == '#')
   1037 		goto again;  /* try again on error */
   1038 	uart1base = savedbase;
   1039 }
   1040 
   1041 void
   1042 putchar(int c)
   1043 {
   1044 	unsigned timo, lsr;
   1045 
   1046 	if (c == '\n')
   1047 		putchar('\r');
   1048 
   1049 	timo = 0x00100000;
   1050 	do {
   1051 		lsr = UART_READ(uart1base, LSR);
   1052 	} while (timo-- > 0 && (lsr & LSR_THRE) == 0);
   1053 	if (timo > 0)
   1054 		UART_WRITE(uart1base, THR, c);
   1055 }
   1056 
   1057 int
   1058 getchar(void)
   1059 {
   1060 	unsigned lsr;
   1061 
   1062 	do {
   1063 		lsr = UART_READ(uart1base, LSR);
   1064 	} while ((lsr & LSR_DRDY) == 0);
   1065 	return UART_READ(uart1base, RBR);
   1066 }
   1067 
   1068 int
   1069 tstchar(void)
   1070 {
   1071 
   1072 	return (UART_READ(uart1base, LSR) & LSR_DRDY) != 0;
   1073 }
   1074 
   1075 #define SAR_MASK 0x0ff00000
   1076 #define SAR_SHIFT    20
   1077 #define EAR_MASK 0x30000000
   1078 #define EAR_SHIFT    28
   1079 #define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s))
   1080 #define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s))
   1081 static void
   1082 set_mem_bounds(unsigned tag, unsigned bk_en, ...)
   1083 {
   1084 	unsigned mbst, mbxst, mben, mbxen;
   1085 	unsigned start, end;
   1086 	va_list ap;
   1087 	int i, sh;
   1088 
   1089 	va_start(ap, bk_en);
   1090 	mbst = mbxst = mben = mbxen = 0;
   1091 
   1092 	for (i = 0; i < 4; i++) {
   1093 		if ((bk_en & (1U << i)) != 0) {
   1094 			start = va_arg(ap, unsigned);
   1095 			end = va_arg(ap, unsigned);
   1096 		} else {
   1097 			start = 0x3ff00000;
   1098 			end = 0x3fffffff;
   1099 		}
   1100 		sh = i << 3;
   1101 		mbst |= AR(start, sh);
   1102 		mbxst |= XR(start, sh);
   1103 		mben |= AR(end, sh);
   1104 		mbxen |= XR(end, sh);
   1105 	}
   1106 	va_end(ap);
   1107 
   1108 	pcicfgwrite(tag, MPC106_MEMSTARTADDR1, mbst);
   1109 	pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, mbxst);
   1110 	pcicfgwrite(tag, MPC106_MEMENDADDR1, mben);
   1111 	pcicfgwrite(tag, MPC106_EXTMEMENDADDR1,	mbxen);
   1112 	pcicfgwrite(tag, MPC106_MEMEN,
   1113 	    (pcicfgread(tag, MPC106_MEMEN) & ~0xff) | (bk_en & 0xff));
   1114 }
   1115 
   1116 static unsigned
   1117 mpc107memsize(void)
   1118 {
   1119 	unsigned bankn, end, n, tag, val;
   1120 
   1121 	tag = pcimaketag(0, 0, 0);
   1122 
   1123 	if (brdtype == BRD_ENCOREPP1) {
   1124 		/* the brd's PPCBOOT looks to have erroneous values */
   1125 		set_mem_bounds(tag, 1, 0x00000000, (128 << 20) - 1);
   1126 	} else if (brdtype == BRD_NH230NAS) {
   1127 		/*
   1128 		 * PPCBoot sets the end address to 0x7ffffff, although the
   1129 		 * board has just 64MB (0x3ffffff).
   1130 		 */
   1131 		set_mem_bounds(tag, 1, 0x00000000, 0x03ffffff);
   1132 	}
   1133 
   1134 	bankn = 0;
   1135 	val = pcicfgread(tag, MPC106_MEMEN);
   1136 	for (n = 0; n < 4; n++) {
   1137 		if ((val & (1U << n)) == 0)
   1138 			break;
   1139 		bankn = n;
   1140 	}
   1141 	bankn <<= 3;
   1142 
   1143 	val = pcicfgread(tag, MPC106_EXTMEMENDADDR1);
   1144 	end =  ((val >> bankn) & 0x03) << 28;
   1145 	val = pcicfgread(tag, MPC106_MEMENDADDR1);
   1146 	end |= ((val >> bankn) & 0xff) << 20;
   1147 	end |= 0xfffff;
   1148 
   1149 	return (end + 1); /* assume the end address matches total amount */
   1150 }
   1151 
   1152 struct fis_dir_entry {
   1153 	char		name[16];
   1154 	uint32_t	startaddr;
   1155 	uint32_t	loadaddr;
   1156 	uint32_t	flashsize;
   1157 	uint32_t	entryaddr;
   1158 	uint32_t	filesize;
   1159 	char		pad[256 - (16 + 5 * sizeof(uint32_t))];
   1160 };
   1161 
   1162 #define FIS_LOWER_LIMIT	0xfff00000
   1163 
   1164 /*
   1165  * Look for a Redboot-style Flash Image System FIS-directory and
   1166  * return a pointer to the start address of the requested file.
   1167  */
   1168 static void *
   1169 redboot_fis_lookup(const char *filename)
   1170 {
   1171 	static const char FISdirname[16] = {
   1172 	    'F', 'I', 'S', ' ',
   1173 	    'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0
   1174 	};
   1175 	struct fis_dir_entry *dir;
   1176 
   1177 	/*
   1178 	 * The FIS directory is usually in the last sector of the flash.
   1179 	 * But we do not know the sector size (erase size), so start
   1180 	 * at 0xffffff00 and scan backwards in steps of the FIS directory
   1181 	 * entry size (0x100).
   1182 	 */
   1183 	for (dir = (struct fis_dir_entry *)0xffffff00;
   1184 	    (uint32_t)dir >= FIS_LOWER_LIMIT; dir--)
   1185 		if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0)
   1186 			break;
   1187 	if ((uint32_t)dir < FIS_LOWER_LIMIT) {
   1188 		printf("No FIS directory found!\n");
   1189 		return NULL;
   1190 	}
   1191 
   1192 	/* Now find filename by scanning the directory from beginning. */
   1193 	dir = (struct fis_dir_entry *)dir->startaddr;
   1194 	while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) {
   1195 		if (strcmp(dir->name, filename) == 0)
   1196 			return (void *)dir->startaddr;	/* found */
   1197 		dir++;
   1198 	}
   1199 	printf("\"%s\" not found in FIS directory!\n", filename);
   1200 	return NULL;
   1201 }
   1202 
   1203 static void
   1204 read_mac_string(uint8_t *mac, char *p)
   1205 {
   1206 	int i;
   1207 
   1208 	for (i = 0; i < 6; i++, p += 3)
   1209 		*mac++ = read_hex(p);
   1210 }
   1211 
   1212 /*
   1213  * For cost saving reasons some NAS boxes lack SEEPROM for NIC's
   1214  * ethernet address and keep it in their Flash memory instead.
   1215  */
   1216 void
   1217 read_mac_from_flash(uint8_t *mac)
   1218 {
   1219 	uint8_t *p;
   1220 
   1221 	switch (brdtype) {
   1222 	case BRD_SYNOLOGY:
   1223 		p = redboot_fis_lookup("vendor");
   1224 		if (p == NULL)
   1225 			break;
   1226 		memcpy(mac, p, 6);
   1227 		return;
   1228 	case BRD_DLINKDSM:
   1229 		read_mac_string(mac, (char *)0xfff0ff80);
   1230 		return;
   1231 	default:
   1232 		printf("Warning: This board has no known method defined "
   1233 		    "to determine its MAC address!\n");
   1234 		break;
   1235 	}
   1236 
   1237 	/* set to 00:00:00:00:00:00 in case of error */
   1238 	memset(mac, 0, 6);
   1239 }
   1240 
   1241 #ifdef DEBUG
   1242 void
   1243 sat_write(char *p, int len)
   1244 {
   1245 	unsigned savedbase;
   1246 
   1247 	savedbase = uart1base;
   1248 	uart1base = uart2base;
   1249 	while (len--)
   1250 		putchar(*p++);
   1251 	uart1base = savedbase;
   1252 }
   1253 
   1254 int
   1255 sat_getch(void)
   1256 {
   1257 	unsigned lsr;
   1258 
   1259 	do {
   1260 		lsr = UART_READ(uart2base, LSR);
   1261 	} while ((lsr & LSR_DRDY) == 0);
   1262 	return UART_READ(uart2base, RBR);
   1263 }
   1264 
   1265 int
   1266 sat_tstch(void)
   1267 {
   1268 
   1269 	return (UART_READ(uart2base, LSR) & LSR_DRDY) != 0;
   1270 }
   1271 #endif /* DEBUG */
   1272