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