1 /* $NetBSD: brdsetup.c,v 1.42 2023/12/20 15:29:07 thorpej 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 * My DS107e works much better with the 720 * default EXT_CLK_FREQ (33333333). 721 * --thorpej 722 */ 723 #if 0 724 if (1) /* 200 and 266MHz models */ 725 brd->extclk = 33164691; /* from Synology/Linux source */ 726 else /* 400MHz models XXX how to check? */ 727 brd->extclk = 33165343; 728 #endif 729 } 730 731 void 732 synobrdfix(struct brdprop *brd) 733 { 734 735 init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE); 736 /* beep, power LED on, status LED off */ 737 send_sat("247"); 738 } 739 740 #define SYNO_FAN_TIMEOUT 500 /* 500ms to turn the fan off */ 741 #define SYNO_DISK_DELAY 30 /* 30 seconds to power up 2nd disk */ 742 743 void 744 synopcifix(struct brdprop *brd) 745 { 746 static const char models207[4][7] = { 747 "???", "DS107e", "DS107", "DS207" 748 }; 749 static const char models209[2][7] = { 750 "DS109j", "DS209j" 751 }; 752 static const char models406[3][7] = { 753 "CS406e", "CS406", "RS406" 754 }; 755 static const char models407[4][7] = { 756 "???", "CS407e", "CS407", "RS407" 757 }; 758 extern struct btinfo_model bi_model; 759 const char *model_name; 760 unsigned cpld, version, flags; 761 uint8_t v, status; 762 int i; 763 764 /* 765 * Determine if a CPLD is present and whether is has 4-bit 766 * (models 107, 207, 209) or 8-bit (models 406, 407) registers. 767 * The register set repeats every 16 bytes. 768 */ 769 cpld = 0; 770 flags = 0; 771 version = 0; 772 model_name = NULL; 773 774 SYNOCPLD_WRITE(0, 0x00); /* LEDs blinking yellow (default) */ 775 v = SYNOCPLD_READ(0); 776 777 if (v != 0x00) { 778 v &= 0xf0; 779 if (v != 0x00 || (SYNOCPLD_READ(16 + 0) & 0xf0) != v) 780 goto cpld_done; 781 782 cpld4bits: 783 /* 4-bit registers assumed, make LEDs solid yellow */ 784 SYNOCPLD_WRITE(0, 0x50); 785 v = SYNOCPLD_READ(0) & 0xf0; 786 if (v != 0x50 || (SYNOCPLD_READ(32 + 0) & 0xf0) != v) 787 goto cpld_done; 788 789 v = SYNOCPLD_READ(2) & 0xf0; 790 if ((SYNOCPLD_READ(48 + 2) & 0xf0) != v) 791 goto cpld_done; 792 version = (v >> 4) & 7; 793 794 /* 795 * Try to determine whether it is a 207-style or 209-style 796 * CPLD register set, by turning the fan off and check if 797 * either bit 5 or bit 4 changes from 0 to 1 to indicate 798 * the fan is stopped. 799 */ 800 status = SYNOCPLD_READ(3) & 0xf0; 801 SYNOCPLD_WRITE(3, 0x00); /* fan off */ 802 803 for (i = 0; i < SYNO_FAN_TIMEOUT * 100; i++) { 804 delay(10); 805 v = SYNOCPLD_READ(3) & 0xf0; 806 if ((status & 0x20) == 0 && (v & 0x20) != 0) { 807 /* set x07 model */ 808 v = SYNOCPLD_READ(1) >> 6; 809 model_name = models207[v]; 810 cpld = BI_MODEL_CPLD207; 811 /* XXXX DS107v2/v3 have no thermal sensor */ 812 flags |= BI_MODEL_THERMAL; 813 break; 814 } 815 if ((status & 0x10) == 0 && (v & 0x10) != 0) { 816 /* set x09 model */ 817 v = SYNOCPLD_READ(1) >> 7; 818 model_name = models209[v]; 819 cpld = BI_MODEL_CPLD209; 820 if (v == 1) /* DS209j */ 821 flags |= BI_MODEL_THERMAL; 822 break; 823 } 824 /* XXX What about DS108j? Does it have a CPLD? */ 825 } 826 827 /* turn the fan on again */ 828 SYNOCPLD_WRITE(3, status); 829 830 if (i >= SYNO_FAN_TIMEOUT * 100) 831 goto cpld_done; /* timeout: no valid CPLD */ 832 } else { 833 if (SYNOCPLD_READ(16 + 0) != v) 834 goto cpld4bits; 835 836 /* 8-bit registers assumed, make LEDs solid yellow */ 837 SYNOCPLD_WRITE(0, 0x55); 838 v = SYNOCPLD_READ(0); 839 if (v != 0x55) 840 goto cpld4bits; /* try 4 bits instead */ 841 if (SYNOCPLD_READ(32 + 0) != v) 842 goto cpld_done; 843 844 v = SYNOCPLD_READ(2); 845 if (SYNOCPLD_READ(48 + 2) != v) 846 goto cpld_done; 847 version = v & 3; 848 849 if ((v & 0x0c) != 0x0c) { 850 /* set 406 model */ 851 model_name = models406[(v >> 2) & 3]; 852 cpld = BI_MODEL_CPLD406; 853 } else { 854 /* set 407 model */ 855 model_name = models407[v >> 6]; 856 cpld = BI_MODEL_CPLD407; 857 flags |= BI_MODEL_THERMAL; 858 } 859 } 860 861 printf("CPLD V%s%u detected for model %s\n", 862 cpld < BI_MODEL_CPLD406 ? "" : "1.", 863 version, model_name); 864 865 if (cpld == BI_MODEL_CPLD406 || cpld == BI_MODEL_CPLD407) { 866 /* 867 * CS/RS stations power-up their disks one after another. 868 * We have to watch over the current power state in a CPLD 869 * register, until all disks become available. 870 */ 871 do { 872 delay(1000 * 1000); 873 v = SYNOCPLD_READ(1); 874 printf("Power state: %02x\r", v); 875 } while (v != 0xff); 876 putchar('\n'); 877 } else if (model_name != NULL && model_name[2] == '2') { 878 /* 879 * DS207 and DS209 have a second SATA disk, which is started 880 * with several seconds delay, but no CPLD register to 881 * monitor the power state. So all we can do is to 882 * wait some more seconds during SATA-init. 883 * Also wait some seconds now, to make sure the first 884 * disk is ready after a cold start. 885 */ 886 sata_delay[1] = SYNO_DISK_DELAY; 887 delay(10 * 1024 * 1024); 888 } 889 890 cpld_done: 891 if (model_name != NULL) { 892 snprintf(bi_model.name, sizeof(bi_model.name), "%s", model_name); 893 bi_model.flags = cpld | version | flags; 894 } else 895 printf("No CPLD found. DS101/DS106.\n"); 896 } 897 898 void 899 synolaunch(struct brdprop *brd) 900 { 901 extern struct btinfo_model bi_model; 902 struct dkdev_ata *sata1, *sata2; 903 unsigned cpld; 904 905 cpld = bi_model.flags & BI_MODEL_CPLD_MASK; 906 907 if (cpld == BI_MODEL_CPLD406 || cpld == BI_MODEL_CPLD407) { 908 /* set drive LEDs for active disk drives on CS/RS models */ 909 sata1 = lata[0].drv; 910 sata2 = lata[1].drv; 911 SYNOCPLD_WRITE(0, (sata1->presense[0] ? 0x80 : 0xc0) | 912 (sata1->presense[1] ? 0x20 : 0x30) | 913 (sata2->presense[0] ? 0x08 : 0x0c) | 914 (sata2->presense[1] ? 0x02 : 0x03)); 915 } else if (cpld == BI_MODEL_CPLD207 || cpld == BI_MODEL_CPLD209) { 916 /* set drive LEDs for DS207 and DS209 models */ 917 sata1 = lata[0].drv; 918 SYNOCPLD_WRITE(0, (sata1->presense[0] ? 0x80 : 0xc0) | 919 (sata1->presense[1] ? 0x20 : 0x30)); 920 } 921 } 922 923 void 924 synoreset() 925 { 926 927 send_sat("C"); 928 /*NOTREACHED*/ 929 } 930 931 void 932 qnapbrdfix(struct brdprop *brd) 933 { 934 935 init_uart(uart2base, 19200, LCR_8BITS | LCR_PNONE); 936 /* beep, status LED red */ 937 send_sat("PW"); 938 } 939 940 void 941 qnapreset() 942 { 943 944 send_sat("f"); 945 /*NOTREACHED*/ 946 } 947 948 void 949 iomegabrdfix(struct brdprop *brd) 950 { 951 952 init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE); 953 /* LED flashing blue, fan auto, turn on at 50C, turn off at 45C */ 954 send_iomega('b', 'd', 2, 'a', 50, 45); 955 } 956 957 void 958 iomegareset() 959 { 960 961 send_iomega('g', 0, 0, 0, 0, 0); 962 /*NOTREACHED*/ 963 } 964 965 void 966 dlinkbrdfix(struct brdprop *brd) 967 { 968 969 init_uart(uart2base, 9600, LCR_8BITS | LCR_PNONE); 970 send_sat("SYN\n"); 971 send_sat("ZWO\n"); /* power LED solid on */ 972 } 973 974 void 975 nhnasbrdfix(struct brdprop *brd) 976 { 977 978 /* status LED off, USB-LEDs on, low-speed fan */ 979 NHGPIO_WRITE(0x04); 980 } 981 982 void 983 nhnasreset() 984 { 985 986 /* status LED on, assert system-reset to all devices */ 987 NHGPIO_WRITE(0x02); 988 delay(100000); 989 /*NOTREACHED*/ 990 } 991 992 void 993 kurot4brdfix(struct brdprop *brd) 994 { 995 996 init_uart(uart2base, 38400, LCR_8BITS | LCR_PEVEN); 997 } 998 999 void 1000 _rtt(void) 1001 { 1002 uint32_t msr; 1003 1004 netif_shutdown_all(); 1005 1006 if (brdprop->reset != NULL) 1007 (*brdprop->reset)(); 1008 else { 1009 msr = mfmsr(); 1010 msr &= ~PSL_EE; 1011 mtmsr(msr); 1012 asm volatile ("sync; isync"); 1013 asm volatile("mtspr %0,%1" : : "K"(81), "r"(0)); 1014 msr &= ~(PSL_ME | PSL_DR | PSL_IR); 1015 mtmsr(msr); 1016 asm volatile ("sync; isync"); 1017 run(0, 0, 0, 0, (void *)0xFFF00100); /* reset entry */ 1018 } 1019 __unreachable(); 1020 } 1021 1022 satime_t 1023 getsecs(void) 1024 { 1025 uint64_t tb = mftb(); 1026 1027 return (tb / ticks_per_sec); 1028 } 1029 1030 /* 1031 * Wait for about n microseconds (at least!). 1032 */ 1033 void 1034 delay(unsigned n) 1035 { 1036 uint64_t tb; 1037 uint32_t scratch, tbh, tbl; 1038 1039 tb = mftb(); 1040 tb += ((uint64_t)n * 1000 + ns_per_tick - 1) / ns_per_tick; 1041 tbh = tb >> 32; 1042 tbl = tb; 1043 asm volatile( 1044 "1: mftbu %0;" 1045 " cmpw %0,%1;" 1046 " blt 1b;" 1047 " bgt 2f;" 1048 " mftb %0;" 1049 " cmpw 0, %0,%2;" 1050 " blt 1b;" 1051 "2:" 1052 : "=&r"(scratch) 1053 : "r"(tbh), "r"(tbl) 1054 : "cc"); 1055 } 1056 1057 void 1058 _wb(uint32_t adr, uint32_t siz) 1059 { 1060 uint32_t bnd; 1061 1062 asm volatile("eieio" ::: "memory"); 1063 for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) 1064 asm volatile("dcbst 0,%0" :: "r"(adr) : "memory"); 1065 asm volatile("sync" ::: "memory"); 1066 } 1067 1068 void 1069 _wbinv(uint32_t adr, uint32_t siz) 1070 { 1071 uint32_t bnd; 1072 1073 asm volatile("eieio" ::: "memory"); 1074 for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) 1075 asm volatile("dcbf 0,%0" :: "r"(adr) : "memory"); 1076 asm volatile("sync"); 1077 } 1078 1079 void 1080 _inv(uint32_t adr, uint32_t siz) 1081 { 1082 uint32_t bnd, off; 1083 1084 off = adr & (dcache_line_size - 1); 1085 adr -= off; 1086 siz += off; 1087 asm volatile("eieio" ::: "memory"); 1088 if (off != 0) { 1089 /* wbinv() leading unaligned dcache line */ 1090 asm volatile("dcbf 0,%0" :: "r"(adr) : "memory"); 1091 if (siz < dcache_line_size) 1092 goto done; 1093 adr += dcache_line_size; 1094 siz -= dcache_line_size; 1095 } 1096 bnd = adr + siz; 1097 off = bnd & (dcache_line_size - 1); 1098 if (off != 0) { 1099 /* wbinv() trailing unaligned dcache line */ 1100 asm volatile("dcbf 0,%0" :: "r"(bnd) : "memory"); /* it's OK */ 1101 if (siz < dcache_line_size) 1102 goto done; 1103 siz -= off; 1104 } 1105 for (bnd = adr + siz; adr < bnd; adr += dcache_line_size) { 1106 /* inv() intermediate dcache lines if ever */ 1107 asm volatile("dcbi 0,%0" :: "r"(adr) : "memory"); 1108 } 1109 done: 1110 asm volatile("sync" ::: "memory"); 1111 } 1112 1113 static inline uint32_t 1114 mfmsr(void) 1115 { 1116 uint32_t msr; 1117 1118 asm volatile ("mfmsr %0" : "=r"(msr)); 1119 return msr; 1120 } 1121 1122 static inline void 1123 mtmsr(uint32_t msr) 1124 { 1125 asm volatile ("mtmsr %0" : : "r"(msr)); 1126 } 1127 1128 static inline uint32_t 1129 cputype(void) 1130 { 1131 uint32_t pvr; 1132 1133 asm volatile ("mfpvr %0" : "=r"(pvr)); 1134 return pvr >> 16; 1135 } 1136 1137 static inline uint64_t 1138 mftb(void) 1139 { 1140 uint32_t scratch; 1141 uint64_t tb; 1142 1143 asm ("1: mftbu %0; mftb %0+1; mftbu %1; cmpw %0,%1; bne 1b" 1144 : "=r"(tb), "=r"(scratch) :: "cc"); 1145 return tb; 1146 } 1147 1148 static void 1149 init_uart(unsigned base, unsigned speed, uint8_t lcr) 1150 { 1151 unsigned div; 1152 1153 div = busclock / speed / 16; 1154 UART_WRITE(base, LCR, 0x80); /* turn on DLAB bit */ 1155 UART_WRITE(base, FCR, 0x00); 1156 UART_WRITE(base, DMB, div >> 8); /* set speed */ 1157 UART_WRITE(base, DLB, div & 0xff); 1158 UART_WRITE(base, LCR, lcr); 1159 UART_WRITE(base, FCR, 0x07); /* FIFO on, TXRX FIFO reset */ 1160 UART_WRITE(base, IER, 0x00); /* make sure INT disabled */ 1161 } 1162 1163 /* talk to satellite processor */ 1164 static void 1165 send_sat(char *msg) 1166 { 1167 unsigned savedbase; 1168 1169 savedbase = uart1base; 1170 uart1base = uart2base; 1171 while (*msg) 1172 putchar(*msg++); 1173 uart1base = savedbase; 1174 } 1175 1176 #ifdef DEBUG 1177 static void 1178 iomega_debug(const char *txt, uint8_t buf[]) 1179 { 1180 int i; 1181 1182 printf("%s:", txt); 1183 for (i = 0; i < IOMEGA_PACKETSIZE; i++) 1184 printf(" %02x", buf[i]); 1185 putchar('\n'); 1186 } 1187 #endif /* DEBUG */ 1188 1189 static void 1190 send_iomega(int power, int led, int rate, int fan, int high, int low) 1191 { 1192 uint8_t buf[IOMEGA_PACKETSIZE]; 1193 unsigned i, savedbase; 1194 1195 savedbase = uart1base; 1196 uart1base = uart2base; 1197 1198 /* first flush the receive buffer */ 1199 again: 1200 while (tstchar()) 1201 (void)getchar(); 1202 delay(20000); 1203 if (tstchar()) 1204 goto again; 1205 /* 1206 * Now synchronize the transmitter by sending 0x00 1207 * until we receive a status reply. 1208 */ 1209 do { 1210 putchar(0); 1211 delay(50000); 1212 } while (!tstchar()); 1213 1214 for (i = 0; i < IOMEGA_PACKETSIZE; i++) 1215 buf[i] = getchar(); 1216 #ifdef DEBUG 1217 uart1base = savedbase; 1218 iomega_debug("68HC908 status", buf); 1219 uart1base = uart2base; 1220 #endif 1221 1222 /* send command */ 1223 buf[IOMEGA_POWER] = power; 1224 buf[IOMEGA_LED] = led; 1225 buf[IOMEGA_FLASH_RATE] = rate; 1226 buf[IOMEGA_FAN] = fan; 1227 buf[IOMEGA_HIGH_TEMP] = high; 1228 buf[IOMEGA_LOW_TEMP] = low; 1229 buf[IOMEGA_ID] = 7; /* host id */ 1230 buf[IOMEGA_CHECKSUM] = (buf[IOMEGA_POWER] + buf[IOMEGA_LED] + 1231 buf[IOMEGA_FLASH_RATE] + buf[IOMEGA_FAN] + 1232 buf[IOMEGA_HIGH_TEMP] + buf[IOMEGA_LOW_TEMP] + 1233 buf[IOMEGA_ID]) & 0x7f; 1234 #ifdef DEBUG 1235 uart1base = savedbase; 1236 iomega_debug("G2 sending", buf); 1237 uart1base = uart2base; 1238 #endif 1239 for (i = 0; i < IOMEGA_PACKETSIZE; i++) 1240 putchar(buf[i]); 1241 1242 /* receive the reply */ 1243 for (i = 0; i < IOMEGA_PACKETSIZE; i++) 1244 buf[i] = getchar(); 1245 #ifdef DEBUG 1246 uart1base = savedbase; 1247 iomega_debug("68HC908 reply", buf); 1248 uart1base = uart2base; 1249 #endif 1250 1251 if (buf[0] == '#') 1252 goto again; /* try again on error */ 1253 uart1base = savedbase; 1254 } 1255 1256 void 1257 putchar(int c) 1258 { 1259 unsigned timo, lsr; 1260 1261 if (c == '\n') 1262 putchar('\r'); 1263 1264 timo = 0x00100000; 1265 do { 1266 lsr = UART_READ(uart1base, LSR); 1267 } while (timo-- > 0 && (lsr & LSR_THRE) == 0); 1268 if (timo > 0) 1269 UART_WRITE(uart1base, THR, c); 1270 } 1271 1272 int 1273 getchar(void) 1274 { 1275 unsigned lsr; 1276 1277 do { 1278 lsr = UART_READ(uart1base, LSR); 1279 } while ((lsr & LSR_DRDY) == 0); 1280 return UART_READ(uart1base, RBR); 1281 } 1282 1283 int 1284 tstchar(void) 1285 { 1286 1287 return (UART_READ(uart1base, LSR) & LSR_DRDY) != 0; 1288 } 1289 1290 #define SAR_MASK 0x0ff00000 1291 #define SAR_SHIFT 20 1292 #define EAR_MASK 0x30000000 1293 #define EAR_SHIFT 28 1294 #define AR(v, s) ((((v) & SAR_MASK) >> SAR_SHIFT) << (s)) 1295 #define XR(v, s) ((((v) & EAR_MASK) >> EAR_SHIFT) << (s)) 1296 static void 1297 set_mem_bounds(unsigned tag, unsigned bk_en, ...) 1298 { 1299 unsigned mbst, mbxst, mben, mbxen; 1300 unsigned start, end; 1301 va_list ap; 1302 int i, sh; 1303 1304 va_start(ap, bk_en); 1305 mbst = mbxst = mben = mbxen = 0; 1306 1307 for (i = 0; i < 4; i++) { 1308 if ((bk_en & (1U << i)) != 0) { 1309 start = va_arg(ap, unsigned); 1310 end = va_arg(ap, unsigned); 1311 } else { 1312 start = 0x3ff00000; 1313 end = 0x3fffffff; 1314 } 1315 sh = i << 3; 1316 mbst |= AR(start, sh); 1317 mbxst |= XR(start, sh); 1318 mben |= AR(end, sh); 1319 mbxen |= XR(end, sh); 1320 } 1321 va_end(ap); 1322 1323 pcicfgwrite(tag, MPC106_MEMSTARTADDR1, mbst); 1324 pcicfgwrite(tag, MPC106_EXTMEMSTARTADDR1, mbxst); 1325 pcicfgwrite(tag, MPC106_MEMENDADDR1, mben); 1326 pcicfgwrite(tag, MPC106_EXTMEMENDADDR1, mbxen); 1327 pcicfgwrite(tag, MPC106_MEMEN, 1328 (pcicfgread(tag, MPC106_MEMEN) & ~0xff) | (bk_en & 0xff)); 1329 } 1330 1331 static unsigned 1332 mpc107memsize(void) 1333 { 1334 unsigned bankn, end, n, tag, val; 1335 1336 tag = pcimaketag(0, 0, 0); 1337 1338 if (brdtype == BRD_ENCOREPP1) { 1339 /* the brd's PPCBOOT looks to have erroneous values */ 1340 set_mem_bounds(tag, 1, 0x00000000, (128 << 20) - 1); 1341 } else if (brdtype == BRD_NH230NAS) { 1342 /* 1343 * PPCBoot sets the end address to 0x7ffffff, although the 1344 * board has just 64MB (0x3ffffff). 1345 */ 1346 set_mem_bounds(tag, 1, 0x00000000, 0x03ffffff); 1347 } 1348 1349 bankn = 0; 1350 val = pcicfgread(tag, MPC106_MEMEN); 1351 for (n = 0; n < 4; n++) { 1352 if ((val & (1U << n)) == 0) 1353 break; 1354 bankn = n; 1355 } 1356 bankn <<= 3; 1357 1358 val = pcicfgread(tag, MPC106_EXTMEMENDADDR1); 1359 end = ((val >> bankn) & 0x03) << 28; 1360 val = pcicfgread(tag, MPC106_MEMENDADDR1); 1361 end |= ((val >> bankn) & 0xff) << 20; 1362 end |= 0xfffff; 1363 1364 return (end + 1); /* assume the end address matches total amount */ 1365 } 1366 1367 struct fis_dir_entry { 1368 char name[16]; 1369 uint32_t startaddr; 1370 uint32_t loadaddr; 1371 uint32_t flashsize; 1372 uint32_t entryaddr; 1373 uint32_t filesize; 1374 char pad[256 - (16 + 5 * sizeof(uint32_t))]; 1375 }; 1376 1377 #define FIS_LOWER_LIMIT 0xfff00000 1378 1379 /* 1380 * Look for a Redboot-style Flash Image System FIS-directory and 1381 * return a pointer to the start address of the requested file. 1382 */ 1383 static void * 1384 redboot_fis_lookup(const char *filename) 1385 { 1386 static const char FISdirname[16] = { 1387 'F', 'I', 'S', ' ', 1388 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 0, 0, 0 1389 }; 1390 struct fis_dir_entry *dir; 1391 1392 /* 1393 * The FIS directory is usually in the last sector of the flash. 1394 * But we do not know the sector size (erase size), so start 1395 * at 0xffffff00 and scan backwards in steps of the FIS directory 1396 * entry size (0x100). 1397 */ 1398 for (dir = (struct fis_dir_entry *)0xffffff00; 1399 (uint32_t)dir >= FIS_LOWER_LIMIT; dir--) 1400 if (memcmp(dir->name, FISdirname, sizeof(FISdirname)) == 0) 1401 break; 1402 if ((uint32_t)dir < FIS_LOWER_LIMIT) { 1403 printf("No FIS directory found!\n"); 1404 return NULL; 1405 } 1406 1407 /* Now find filename by scanning the directory from beginning. */ 1408 dir = (struct fis_dir_entry *)dir->startaddr; 1409 while (dir->name[0] != 0xff && (uint32_t)dir < 0xffffff00) { 1410 if (strcmp(dir->name, filename) == 0) 1411 return (void *)dir->startaddr; /* found */ 1412 dir++; 1413 } 1414 printf("\"%s\" not found in FIS directory!\n", filename); 1415 return NULL; 1416 } 1417 1418 static void 1419 read_mac_string(uint8_t *mac, char *p) 1420 { 1421 int i; 1422 1423 for (i = 0; i < 6; i++, p += 3) 1424 *mac++ = read_hex(p); 1425 } 1426 1427 /* 1428 * Scan through the Flash memory and look for a string starting at 512 bytes 1429 * block boundaries, matching the format: xx:xx:xx:xx:xx:xx<NUL>, where "x" 1430 * are hexadecimal digits. 1431 * Read the first match as our MAC address. 1432 * The start address of the search, p, *must* be dividable by 512! 1433 * Return false when no suitable MAC string was found. 1434 */ 1435 static int 1436 find_mac_string(uint8_t *mac, char *p) 1437 { 1438 int i; 1439 1440 for (;;) { 1441 for (i = 0; i < 3 * 6; i += 3) { 1442 if (!isxdigit((unsigned)p[i]) || 1443 !isxdigit((unsigned)p[i + 1])) 1444 break; 1445 if ((i < 5 && p[i + 2] != ':') || 1446 (i >= 5 && p[i + 2] != '\0')) 1447 break; 1448 } 1449 if (i >= 6) { 1450 /* found a valid MAC address */ 1451 read_mac_string(mac, p); 1452 return 1; 1453 } 1454 if (p >= (char *)0xfffffe00) 1455 break; 1456 p += 0x200; 1457 } 1458 return 0; 1459 } 1460 1461 1462 /* 1463 * For cost saving reasons some NAS boxes lack SEEPROM for NIC's 1464 * ethernet address and keep it in their Flash memory instead. 1465 */ 1466 void 1467 read_mac_from_flash(uint8_t *mac) 1468 { 1469 uint8_t *p; 1470 1471 switch (brdtype) { 1472 case BRD_SYNOLOGY: 1473 p = redboot_fis_lookup("vendor"); 1474 if (p == NULL) 1475 break; 1476 memcpy(mac, p, 6); 1477 return; 1478 case BRD_DLINKDSM: 1479 read_mac_string(mac, (char *)0xfff0ff80); 1480 return; 1481 case BRD_QNAPTS: 1482 if (find_mac_string(mac, (char *)0xfff00000)) 1483 return; 1484 break; 1485 default: 1486 printf("Warning: This board has no known method defined " 1487 "to determine its MAC address!\n"); 1488 break; 1489 } 1490 1491 /* set to 00:00:00:00:00:00 in case of error */ 1492 memset(mac, 0, 6); 1493 } 1494 1495 #ifdef DEBUG 1496 void 1497 sat_write(char *p, int len) 1498 { 1499 unsigned savedbase; 1500 1501 savedbase = uart1base; 1502 uart1base = uart2base; 1503 while (len--) 1504 putchar(*p++); 1505 uart1base = savedbase; 1506 } 1507 1508 int 1509 sat_getch(void) 1510 { 1511 unsigned lsr; 1512 1513 do { 1514 lsr = UART_READ(uart2base, LSR); 1515 } while ((lsr & LSR_DRDY) == 0); 1516 return UART_READ(uart2base, RBR); 1517 } 1518 1519 int 1520 sat_tstch(void) 1521 { 1522 1523 return (UART_READ(uart2base, LSR) & LSR_DRDY) != 0; 1524 } 1525 #endif /* DEBUG */ 1526