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