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