1 /* $NetBSD: machdep.c,v 1.70 2024/03/05 14:15:35 thorpej Exp $ */ 2 3 /* 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.70 2024/03/05 14:15:35 thorpej Exp $"); 36 37 #include "opt_compat_netbsd.h" 38 #include "opt_ddb.h" 39 #include "opt_interrupt.h" 40 #include "opt_modular.h" 41 42 #include <sys/param.h> 43 #include <sys/buf.h> 44 #include <sys/bus.h> 45 #include <sys/conf.h> 46 #include <sys/device.h> 47 #include <sys/exec.h> 48 #include <sys/extent.h> 49 #include <sys/intr.h> 50 #include <sys/kernel.h> 51 #include <sys/ksyms.h> 52 #include <sys/mbuf.h> 53 #include <sys/module.h> 54 #include <sys/mount.h> 55 #include <sys/msgbuf.h> 56 #include <sys/proc.h> 57 #include <sys/reboot.h> 58 #include <sys/syscallargs.h> 59 #include <sys/sysctl.h> 60 #include <sys/syslog.h> 61 #include <sys/systm.h> 62 63 #include <uvm/uvm_extern.h> 64 65 #include <machine/powerpc.h> 66 #include <machine/bootinfo.h> 67 68 #include <powerpc/pmap.h> 69 #include <powerpc/trap.h> 70 71 #include <powerpc/oea/bat.h> 72 #include <powerpc/openpic.h> 73 #include <powerpc/pic/picvar.h> 74 75 #ifdef DDB 76 #include <powerpc/db_machdep.h> 77 #include <ddb/db_extern.h> 78 #endif 79 80 #include <dev/cons.h> 81 #include <sys/termios.h> 82 83 #include "com.h" 84 #if (NCOM > 0) 85 #include <dev/ic/comreg.h> 86 #include <dev/ic/comvar.h> 87 #endif 88 89 #include "com_eumb.h" 90 #if (NCOM_EUMB > 0) 91 #include <sandpoint/sandpoint/eumbvar.h> 92 #endif 93 94 #include "pcib.h" 95 #include "ksyms.h" 96 97 char bootinfo[BOOTINFO_MAXSIZE]; 98 void (*md_reboot)(int); 99 100 void initppc(u_int, u_int, u_int, void *); 101 void consinit(void); 102 void sandpoint_bus_space_init(void); 103 size_t mpc107memsize(void); 104 105 /* we support single chunk of memory */ 106 struct mem_region physmemr[2], availmemr[2]; 107 108 paddr_t avail_end; 109 struct pic_ops *isa_pic = NULL; 110 extern int primary_pic; 111 112 #if NKSYMS || defined(DDB) || defined(MODULAR) 113 extern void *startsym, *endsym; 114 #endif 115 116 #if 1 117 extern struct consdev kcomcons; 118 #endif 119 120 void 121 initppc(u_int startkernel, u_int endkernel, u_int args, void *btinfo) 122 { 123 extern u_long ticks_per_sec, ns_per_tick; 124 struct btinfo_magic *bi_magic = btinfo; 125 struct btinfo_memory *meminfo; 126 struct btinfo_clock *clockinfo; 127 size_t memsize; 128 u_long ticks; 129 130 if ((unsigned)btinfo != 0 && (unsigned)btinfo < startkernel 131 && bi_magic->magic == BOOTINFO_MAGIC) 132 memcpy(bootinfo, btinfo, sizeof(bootinfo)); 133 else 134 args = RB_SINGLE; /* boot via S-record loader */ 135 136 meminfo = lookup_bootinfo(BTINFO_MEMORY); 137 if (meminfo) 138 memsize = meminfo->memsize & ~PGOFSET; 139 else 140 memsize = mpc107memsize(); 141 physmemr[0].start = 0; 142 physmemr[0].size = memsize; 143 physmemr[1].size = 0; 144 availmemr[0].start = (endkernel + PGOFSET) & ~PGOFSET; 145 availmemr[0].size = memsize - availmemr[0].start; 146 availmemr[1].size = 0; 147 avail_end = physmemr[0].start + physmemr[0].size; /* XXX */ 148 149 clockinfo = lookup_bootinfo(BTINFO_CLOCK); 150 if (clockinfo) 151 ticks = clockinfo->ticks_per_sec; 152 else { 153 ticks = 1000000000; /* 100 MHz */ 154 ticks /= 4; /* 4 cycles per DEC tick */ 155 } 156 ticks_per_sec = ticks; 157 ns_per_tick = 1000000000 / ticks_per_sec; 158 159 /* 160 * boothowto 161 */ 162 boothowto = args; 163 164 /* 165 * Now setup fixed bat registers 166 * We setup a pair of BAT to have "Map B" layout, one for the 167 * PCI memory space, another to cover many; MPC107/MPC824x EUMB, 168 * ISA mem, PCI/ISA I/O, PCI configuration, PCI interrupt 169 * acknowledge and flash/ROM space. 170 */ 171 oea_batinit( 172 0x80000000, BAT_BL_256M, /* SANDPOINT_BUS_SPACE_MEM */ 173 0xfc000000, BAT_BL_64M, /* _EUMB|_IO */ 174 0x70000000, BAT_BL_8M, /* only for NH230 board control */ 175 0); 176 177 /* Install vectors and interrupt handler */ 178 oea_init(NULL); 179 180 #if 1 /* bumpy ride in pre-dawn time, for people knows what he/she is doing */ 181 cn_tab = &kcomcons; 182 (*cn_tab->cn_init)(&kcomcons); 183 184 #if NKSYMS || defined(DDB) || defined(MODULAR) 185 ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 186 #endif 187 #ifdef DDB 188 if (boothowto & RB_KDB) 189 Debugger(); 190 #endif 191 #endif 192 193 /* Initialize bus_space */ 194 sandpoint_bus_space_init(); 195 196 /* Initialize the console */ 197 consinit(); 198 199 uvm_md_init(); 200 201 /* Initialize pmap module */ 202 pmap_bootstrap(startkernel, endkernel); 203 204 #if 0 /* NKSYMS || defined(DDB) || defined(MODULAR) */ 205 ksyms_addsyms_elf((int)((u_int)endsym - (u_int)startsym), startsym, endsym); 206 #endif 207 } 208 209 void 210 mem_regions(struct mem_region **mem, struct mem_region **avail) 211 { 212 213 *mem = physmemr; 214 *avail = availmemr; 215 } 216 217 /* 218 * Machine dependent startup code. 219 */ 220 void 221 cpu_startup(void) 222 { 223 struct btinfo_prodfamily *bi_fam; 224 struct btinfo_model *bi_model; 225 char prod_name[32]; 226 char *model; 227 void *baseaddr; 228 int msr; 229 230 /* 231 * Do common startup. 232 */ 233 bi_fam = lookup_bootinfo(BTINFO_PRODFAMILY); 234 bi_model = lookup_bootinfo(BTINFO_MODEL); 235 if (bi_fam != NULL) { 236 snprintf(prod_name, sizeof(prod_name), "%s %s", bi_fam->name, 237 bi_model != NULL ? bi_model->name : ""); 238 model = prod_name; 239 } else 240 model = NULL; 241 oea_startup(model); 242 243 /* 244 * Prepare EPIC and install external interrupt handler. 245 * 0..15 used by South bridge i8259 PIC if exists. 246 * 16..39/41 EPIC interrupts, 24 source or 26 source. 247 */ 248 baseaddr = (void *)(SANDPOINT_BUS_SPACE_EUMB + 0x40000); 249 pic_init(); 250 251 #ifdef PIC_I8259 252 isa_pic = setup_i8259(); 253 (void)setup_mpcpic(baseaddr); 254 primary_pic = 1; 255 /* 256 * set up i8259 as a cascade on EPIC irq 0. 257 * XXX exceptional SP2 has 17 258 */ 259 intr_establish_xname(16, IST_LEVEL, IPL_HIGH, pic_handle_intr, isa_pic, 260 "i8259"); 261 #else 262 mpcpic_reserv16(); 263 (void)setup_mpcpic(baseaddr); 264 primary_pic = 0; 265 #endif 266 267 oea_install_extint(pic_ext_intr); 268 269 /* 270 * Now that we have VM, malloc()s are OK in bus_space. 271 */ 272 bus_space_mallocok(); 273 274 /* 275 * Now allow hardware interrupts. 276 */ 277 splraise(-1); 278 __asm volatile ("mfmsr %0; ori %0,%0,%1; mtmsr %0" 279 : "=r"(msr) 280 : "K"(PSL_EE)); 281 } 282 283 #if (NPCIB > 0) 284 struct btinfo_console bi_cons = { { 0, 0 }, "com", 0x3f8, 38400 }; 285 #else 286 struct btinfo_console bi_cons = { { 0, 0 }, "eumb", 0x4600, 57600 }; 287 #endif 288 289 /* 290 * lookup_bootinfo: 291 * Look up information in bootinfo of boot loader. 292 */ 293 void * 294 lookup_bootinfo(int type) 295 { 296 struct btinfo_common *bt; 297 struct btinfo_common *help = (struct btinfo_common *)bootinfo; 298 299 if (help->next == 0) 300 return (NULL); /* bootinfo[] was not made */ 301 do { 302 bt = help; 303 if (bt->type == type) 304 return (help); 305 help = (struct btinfo_common *)((char*)help + bt->next); 306 } while (bt->next && 307 (size_t)help < (size_t)bootinfo + BOOTINFO_MAXSIZE); 308 309 return (NULL); 310 } 311 312 /* 313 * consinit 314 * Initialize system console. 315 */ 316 void 317 consinit(void) 318 { 319 struct btinfo_console *bi; 320 static int initted; 321 322 if (initted) 323 return; 324 initted = 1; 325 326 bi = lookup_bootinfo(BTINFO_CONSOLE); 327 if (bi == NULL) 328 bi = &bi_cons; 329 330 #if (NCOM > 0) 331 if (strcmp(bi->devname, "com") == 0) { 332 bus_space_tag_t tag = &genppc_isa_io_space_tag; 333 if (comcnattach(tag, bi->addr, bi->speed, 334 COM_FREQ, COM_TYPE_NORMAL, 335 ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8))) 336 panic("can't init com serial console"); 337 return; 338 } 339 #endif 340 #if (NCOM_EUMB > 0) 341 if (strcmp(bi->devname, "eumb") == 0) { 342 bus_space_tag_t tag = &sandpoint_eumb_space_tag; 343 extern u_long ticks_per_sec; 344 345 if (eumbcnattach(tag, bi->addr, bi->speed, 346 4 * ticks_per_sec, COM_TYPE_NORMAL, 347 ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8))) 348 panic("can't init eumb serial console"); 349 return; 350 } 351 #endif 352 panic("console device missing -- serial console not in kernel"); 353 /* Of course, this is moot if there is no console... */ 354 } 355 356 /* 357 * Halt or reboot the machine after syncing/dumping according to howto. 358 */ 359 void 360 cpu_reboot(int howto, char *what) 361 { 362 extern void jump_to_ppc_reset_entry(void); /* from locore.S */ 363 static int syncing; 364 register_t msr; 365 366 boothowto = howto; 367 if ((howto & RB_NOSYNC) == 0 && syncing == 0) { 368 syncing = 1; 369 vfs_shutdown(); /* sync */ 370 } 371 372 /* Disable intr */ 373 /* splhigh(); */ 374 375 /* Do dump if requested */ 376 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 377 oea_dumpsys(); 378 379 doshutdownhooks(); 380 381 pmf_system_shutdown(boothowto); 382 383 if ((howto & RB_POWERDOWN) == RB_HALT) { 384 printf("\n"); 385 printf("The operating system has halted.\n"); 386 printf("Please press any key to reboot.\n\n"); 387 cnpollc(1); /* for proper keyboard command handling */ 388 cngetc(); 389 cnpollc(0); 390 howto = RB_AUTOBOOT; 391 } 392 393 if (md_reboot != NULL) 394 (*md_reboot)(howto); 395 396 /* 397 * No reboot method defined. So we disable the MMU and jump 398 * through the firmware's reset vector. 399 */ 400 msr = mfmsr(); 401 msr &= ~PSL_EE; 402 mtmsr(msr); 403 __asm volatile("mtspr %0,%1" : : "K"(81), "r"(0)); 404 msr &= ~(PSL_ME | PSL_DR | PSL_IR); 405 mtmsr(msr); 406 jump_to_ppc_reset_entry(); 407 for (;;); 408 } 409 410 #ifdef MODULAR 411 void 412 module_init_md(void) 413 { 414 struct btinfo_modulelist *module; 415 struct bi_modulelist_entry *bi, *biend; 416 417 module = lookup_bootinfo(BTINFO_MODULELIST); 418 if (module == NULL) 419 return; 420 bi = (struct bi_modulelist_entry *)(module + 1); 421 biend = bi + module->num; 422 while (bi < biend) { 423 printf("module %s at 0x%08x size %x\n", 424 bi->kmod, bi->base, bi->len); 425 /* module_prime(bi->kmod, (void *)bi->base, bi->len); */ 426 bi += 1; 427 } 428 } 429 #endif /* MODULAR */ 430 431 struct powerpc_bus_space sandpoint_io_space_tag = { 432 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE, 433 0xfe000000, 0x00000000, 0x00c00000, 434 }; 435 struct powerpc_bus_space genppc_isa_io_space_tag = { 436 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_IO_TYPE, 437 0xfe000000, 0x00000000, 0x00010000, 438 }; 439 struct powerpc_bus_space sandpoint_mem_space_tag = { 440 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 441 0x00000000, 0x80000000, 0xfc000000, 442 }; 443 struct powerpc_bus_space genppc_isa_mem_space_tag = { 444 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 445 0x00000000, 0xfd000000, 0xfe000000, 446 }; 447 struct powerpc_bus_space sandpoint_eumb_space_tag = { 448 _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE, 449 0xfc000000, 0x00000000, 0x00100000, 450 }; 451 struct powerpc_bus_space sandpoint_flash_space_tag = { 452 _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE, 453 0x00000000, 0xff000000, 0xffffffff, 454 }; 455 struct powerpc_bus_space sandpoint_nhgpio_space_tag = { 456 _BUS_SPACE_BIG_ENDIAN|_BUS_SPACE_MEM_TYPE, 457 0x70000000, 0x00000000, 0x00001000, 458 }; 459 460 static char ex_storage[7][EXTENT_FIXED_STORAGE_SIZE(8)] 461 __attribute__((aligned(8))); 462 463 void 464 sandpoint_bus_space_init(void) 465 { 466 int error; 467 468 error = bus_space_init(&sandpoint_io_space_tag, "ioport", 469 ex_storage[0], sizeof(ex_storage[0])); 470 if (error) 471 panic("sandpoint_bus_space_init: can't init io tag"); 472 473 error = extent_alloc_region(sandpoint_io_space_tag.pbs_extent, 474 0x10000, 0x7fffff, EX_NOWAIT); 475 if (error) 476 panic("sandpoint_bus_space_init: can't block out reserved I/O" 477 " space 0x10000-0x7fffff: error=%d", error); 478 479 error = bus_space_init(&sandpoint_mem_space_tag, "iomem", 480 ex_storage[1], sizeof(ex_storage[1])); 481 if (error) 482 panic("sandpoint_bus_space_init: can't init mem tag"); 483 484 error = bus_space_init(&genppc_isa_io_space_tag, "isa-ioport", 485 ex_storage[2], sizeof(ex_storage[2])); 486 if (error) 487 panic("sandpoint_bus_space_init: can't init isa io tag"); 488 489 error = bus_space_init(&genppc_isa_mem_space_tag, "isa-iomem", 490 ex_storage[3], sizeof(ex_storage[3])); 491 if (error) 492 panic("sandpoint_bus_space_init: can't init isa mem tag"); 493 494 error = bus_space_init(&sandpoint_eumb_space_tag, "eumb", 495 ex_storage[4], sizeof(ex_storage[4])); 496 if (error) 497 panic("sandpoint_bus_space_init: can't init eumb tag"); 498 499 error = bus_space_init(&sandpoint_flash_space_tag, "flash", 500 ex_storage[5], sizeof(ex_storage[5])); 501 if (error) 502 panic("sandpoint_bus_space_init: can't init flash tag"); 503 504 /* NH230/231 only: extended ROM space at 0x70000000 for GPIO */ 505 error = bus_space_init(&sandpoint_nhgpio_space_tag, "nh23x-gpio", 506 ex_storage[6], sizeof(ex_storage[6])); 507 if (error) 508 panic("sandpoint_bus_space_init: can't init nhgpio tag"); 509 } 510 511 #define MPC107_EUMBBAR 0x78 /* Eumb base address */ 512 #define MPC107_MEMENDADDR1 0x90 /* Memory ending address 1 */ 513 #define MPC107_EXTMEMENDADDR1 0x98 /* Extd. memory ending address 1 */ 514 #define MPC107_MEMEN 0xa0 /* Memory enable */ 515 516 size_t 517 mpc107memsize(void) 518 { 519 /* 520 * assumptions here; 521 * - first 4 sets of SDRAM controlling register have been 522 * set right in the ascending order. 523 * - total SDRAM size is the last valid SDRAM address +1. 524 */ 525 unsigned val, n, bankn, end; 526 527 out32rb(0xfec00000, (1U<<31) | MPC107_MEMEN); 528 val = in32rb(0xfee00000); 529 if ((val & 0xf) == 0) 530 return 32 * 1024 * 1024; /* eeh? */ 531 532 bankn = 0; 533 for (n = 0; n < 4; n++) { 534 if ((val & (1U << n)) == 0) 535 break; 536 bankn = n; 537 } 538 bankn = bankn * 8; 539 540 /* the format is "00 xx xxxxxxxx << 20" */ 541 out32rb(0xfec00000, (1U<<31) | MPC107_EXTMEMENDADDR1); /* bit 29:28 */ 542 val = in32rb(0xfee00000); 543 end = ((val >> bankn) & 0x03) << 28; 544 out32rb(0xfec00000, (1U<<31) | MPC107_MEMENDADDR1); /* bit 27:20 */ 545 val = in32rb(0xfee00000); 546 end |= ((val >> bankn) & 0xff) << 20; 547 end |= 0xfffff; /* bit 19:00 */ 548 549 return (end + 1); /* recognize this as the amount of SDRAM */ 550 } 551 552 /* XXX XXX debug purpose only XXX XXX */ 553 554 static dev_type_cninit(kcomcninit); 555 static dev_type_cngetc(kcomcngetc); 556 static dev_type_cnputc(kcomcnputc); 557 static dev_type_cnpollc(kcomcnpollc); 558 559 struct consdev kcomcons = { 560 NULL, kcomcninit, kcomcngetc, kcomcnputc, kcomcnpollc, NULL, 561 NULL, NULL, NODEV, CN_NORMAL 562 }; 563 564 #define THR 0 565 #define RBR 0 566 #define LSR 5 567 #define LSR_THRE 0x20 568 #define UART_READ(r) *(volatile char *)(uartbase + (r)) 569 #define UART_WRITE(r, v) *(volatile char *)(uartbase + (r)) = (v) 570 #define LSR_RFE 0x80 571 #define LSR_TXEMPTY 0x20 572 #define LSR_BE 0x10 573 #define LSR_FE 0x08 574 #define LSR_PE 0x04 575 #define LSR_OE 0x02 576 #define LSR_RXREADY 0x01 577 #define LSR_ANYE (LSR_OE|LSR_PE|LSR_FE|LSR_BE) 578 579 static unsigned uartbase = 0xfe0003f8; 580 581 static void 582 kcomcninit(struct consdev *cn) 583 { 584 struct btinfo_console *bi = lookup_bootinfo(BTINFO_CONSOLE); 585 586 if (bi == NULL) 587 bi = &bi_cons; 588 if (strcmp(bi->devname, "com") == 0) 589 uartbase = 0xfe000000 + bi->addr; 590 else if (strcmp(bi->devname, "eumb") == 0) 591 uartbase = 0xfc000000 + bi->addr; 592 /* 593 * we do not touch UART operating parameters since bootloader 594 * is supposed to have done well. 595 */ 596 } 597 598 static int 599 kcomcngetc(dev_t dev) 600 { 601 unsigned lsr; 602 int s, c; 603 604 s = splserial(); 605 #if 1 606 do { 607 lsr = UART_READ(LSR); 608 } while ((lsr & LSR_ANYE) || (lsr & LSR_RXREADY) == 0); 609 #else 610 again: 611 do { 612 lsr = UART_READ(LSR); 613 } while ((lsr & LSR_RXREADY) == 0); 614 if (lsr & (LSR_BE | LSR_FE | LSR_PE)) { 615 (void)UART_READ(RBR); 616 goto again; 617 } 618 #endif 619 c = UART_READ(RBR); 620 splx(s); 621 return c & 0xff; 622 } 623 624 static void 625 kcomcnputc(dev_t dev, int c) 626 { 627 unsigned lsr, timo; 628 int s; 629 630 s = splserial(); 631 timo = 150000; 632 do { 633 lsr = UART_READ(LSR); 634 } while (timo-- > 0 && (lsr & LSR_TXEMPTY) == 0); 635 if (timo > 0) 636 UART_WRITE(THR, c); 637 splx(s); 638 } 639 640 static void 641 kcomcnpollc(dev_t dev, int on) 642 { 643 } 644 645 SYSCTL_SETUP(sysctl_machdep_prodfamily, "sysctl machdep prodfamily") 646 { 647 const struct sysctlnode *mnode, *node; 648 struct btinfo_prodfamily *pfam; 649 650 pfam = lookup_bootinfo(BTINFO_PRODFAMILY); 651 if (pfam != NULL) { 652 sysctl_createv(NULL, 0, NULL, &mnode, 653 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL, 654 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL); 655 656 sysctl_createv(NULL, 0, &mnode, &node, 657 CTLFLAG_PERMANENT, CTLTYPE_STRING, "prodfamily", 658 SYSCTL_DESCR("Board family name."), 659 NULL, 0, pfam->name, 0, 660 CTL_CREATE, CTL_EOL); 661 } 662 } 663