machdep.c revision 1.2 1 /* $NetBSD: machdep.c,v 1.2 2026/06/16 23:37:49 rkujawa Exp $ */
2
3 /*
4 * Copyright (c) 2012, 2014, 2024, 2026 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Radoslaw Kujawa.
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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /*
32 * Copyright 2001, 2002 Wasabi Systems, Inc.
33 * All rights reserved.
34 *
35 * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed for the NetBSD Project by
48 * Wasabi Systems, Inc.
49 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
50 * or promote products derived from this software without specific prior
51 * written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
64 */
65 /*
66 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
67 * Copyright (C) 1995, 1996 TooLs GmbH.
68 * All rights reserved.
69 *
70 * Redistribution and use in source and binary forms, with or without
71 * modification, are permitted provided that the following conditions
72 * are met:
73 * 1. Redistributions of source code must retain the above copyright
74 * notice, this list of conditions and the following disclaimer.
75 * 2. Redistributions in binary form must reproduce the above copyright
76 * notice, this list of conditions and the following disclaimer in the
77 * documentation and/or other materials provided with the distribution.
78 * 3. All advertising materials mentioning features or use of this software
79 * must display the following acknowledgement:
80 * This product includes software developed by TooLs GmbH.
81 * 4. The name of TooLs GmbH may not be used to endorse or promote products
82 * derived from this software without specific prior written permission.
83 *
84 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
85 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
86 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
87 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
88 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
89 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
90 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
91 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
92 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
93 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
94 */
95
96 /*
97 * Machine-dependent bootstrap for the ACube Sam460ex (AMCC 460EX).
98 *
99 * Modeled on evbppc/walnut/machdep.c and evbppc/obs405/obs600_machdep.c.
100 */
101
102 #include <sys/cdefs.h>
103 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.2 2026/06/16 23:37:49 rkujawa Exp $");
104
105 #include "opt_ddb.h"
106 #include "opt_sam460ex.h"
107
108 #include <sys/param.h>
109 #include <sys/boot_flag.h>
110 #include <sys/bus.h>
111 #include <sys/device.h>
112 #include <sys/kernel.h>
113 #include <sys/reboot.h>
114 #include <sys/sysctl.h>
115 #include <sys/systm.h>
116
117 #include <dev/cons.h>
118
119 #include <prop/proplib.h>
120
121 #include <machine/sam460ex.h>
122
123 #include <powerpc/spr.h>
124 #include <powerpc/ibm4xx/spr.h>
125
126 #include <powerpc/ibm4xx/amcc460ex.h>
127 #include <powerpc/ibm4xx/cpu.h>
128 #include <powerpc/ibm4xx/dcr4xx.h>
129 #include <powerpc/ibm4xx/tlb.h>
130
131 #include <powerpc/ibm4xx/pci_machdep.h>
132 #include <dev/pci/pciconf.h>
133 #include <dev/pci/pcivar.h>
134
135 #include "com.h"
136 #include "ukbd.h"
137 #if NUKBD > 0
138 #include <dev/usb/ukbdvar.h>
139 #endif
140 #if (NCOM > 0)
141 #include <sys/termios.h>
142 #include <powerpc/ibm4xx/dev/comopbvar.h>
143 #include <dev/ic/comreg.h>
144
145 #ifndef CONADDR
146 #define CONADDR AMCC460EX_UART0_BASE
147 #endif
148 #ifndef CONSPEED
149 #define CONSPEED B115200
150 #endif
151 #ifndef CONMODE
152 /* 8N1 */
153 #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8)
154 #endif
155 #endif /* NCOM */
156
157 #ifndef SAM460EX_MEMSIZE
158 #define SAM460EX_MEMSIZE (512 * 1024 * 1024)
159 #endif
160 #ifndef SAM460EX_CPU_FREQ
161 #define SAM460EX_CPU_FREQ (1150 * 1000 * 1000)
162 #endif
163 #ifndef SAM460EX_OPB_FREQ
164 #define SAM460EX_OPB_FREQ (115 * 1000 * 1000)
165 #endif
166
167 #define TLB_PG_SIZE (16 * 1024 * 1024)
168
169 /* Boot loader handoff, for later FDT parsing */
170 paddr_t sam460ex_fdt_pa;
171 uint32_t sam460ex_epapr_magic;
172
173 void initppc(vaddr_t, vaddr_t, paddr_t, uint32_t);
174
175 /*
176 * Polled early console on UART0.
177 * VA 0xef600300 covered by the locore.
178 */
179 static void
180 earlycons_putc(dev_t dev, int c)
181 {
182 volatile uint8_t *uart = (volatile uint8_t *)AMCC460EX_UART0_BASE;
183
184 while ((uart[5] & 0x20) == 0) /* LSR.THRE */
185 ;
186 uart[0] = c;
187 }
188
189 static int
190 earlycons_getc(dev_t dev)
191 {
192 volatile uint8_t *uart = (volatile uint8_t *)AMCC460EX_UART0_BASE;
193
194 while ((uart[5] & 0x01) == 0) /* LSR.DR */
195 ;
196 return uart[0];
197 }
198
199 static struct consdev earlycons = {
200 .cn_putc = earlycons_putc,
201 .cn_getc = earlycons_getc,
202 .cn_pollc = nullcnpollc,
203 .cn_dev = NODEV,
204 .cn_pri = CN_INTERNAL,
205 };
206
207 void
208 initppc(vaddr_t startkernel, vaddr_t endkernel, paddr_t fdt_pa,
209 uint32_t magic)
210 {
211 u_int memsize;
212 vaddr_t va;
213
214 cn_tab = &earlycons;
215
216 sam460ex_fdt_pa = fdt_pa;
217 sam460ex_epapr_magic = magic;
218
219 /* Disable all external interrupts */
220 mtdcr(DCR_UIC0_BASE + DCR_UIC_ER, 0);
221 mtdcr(DCR_UIC1_BASE + DCR_UIC_ER, 0);
222 mtdcr(DCR_UIC2_BASE + DCR_UIC_ER, 0);
223 mtdcr(DCR_UIC3_BASE + DCR_UIC_ER, 0);
224
225 memsize = SAM460EX_MEMSIZE;
226 #ifdef SAM460EX_FDT
227 if (sam460ex_fdt_parse(fdt_pa)) {
228 if (sam460ex_fdt_info.fi_memsize != 0)
229 memsize = sam460ex_fdt_info.fi_memsize;
230 } else
231 printf("sam460ex: no valid FDT at %#lx, using defaults\n",
232 (u_long)fdt_pa);
233 /* Record the value actually used so cpu_startup() agrees. */
234 sam460ex_fdt_info.fi_memsize = memsize;
235 #endif
236
237 /* Slots 0/1 hold the TS=0 identity entries pinned by locore */
238 ppc44x_tlb_boot_reserved(2);
239
240 /*
241 * locore TS=0 RAM identity entry covers the first 256MB
242 */
243 for (paddr_t pa = 0x10000000; pa < memsize; pa += 0x10000000)
244 ppc44x_tlb_reserve_ts0(pa);
245
246 /* Linear map kernel memory (TS=1, KERNEL_PID) */
247 for (va = 0; va < endkernel; va += TLB_PG_SIZE)
248 ppc4xx_tlb_reserve(va, va, TLB_PG_SIZE, TLB_EX);
249
250 /*
251 * Map the on-chip peripherals
252 */
253 ppc44x_tlb_reserve((uint64_t)AMCC460EX_OPB_PA_HIGH << 32 | 0xef000000,
254 0xef000000, TLB_PG_SIZE, TLB_I | TLB_G);
255
256 /*
257 * PCIX host bridge windows
258 */
259 for (va = 0; va < AMCC460EX_PCIX0_MEM_SIZE; va += TLB_PG_SIZE)
260 ppc44x_tlb_reserve(
261 (uint64_t)AMCC460EX_PCIX0_MEM_PLBA_H << 32 |
262 (AMCC460EX_PCIX0_MEM_BASE + va),
263 SAM460EX_PCIMEM_VA + va, TLB_PG_SIZE, TLB_I | TLB_G);
264 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIX0_IO_PA_HIGH << 32 |
265 AMCC460EX_PCIX0_IO_PLBA,
266 SAM460EX_PCIIO_VA, TLB_PG_SIZE, TLB_I | TLB_G);
267 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIX0_CFG_PA_HIGH << 32 |
268 (AMCC460EX_PCIX0_CFG_PLBA & ~(TLB_PG_SIZE - 1)),
269 SAM460EX_PCICFG_VA, TLB_PG_SIZE, TLB_I | TLB_G);
270
271 /*
272 * PCIe root complex windows
273 */
274 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 |
275 AMCC460EX_PCIE0_CFG_PLBA,
276 SAM460EX_PCIE0CFG_VA, TLB_PG_SIZE, TLB_I | TLB_G);
277 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_CFG_PA_HIGH << 32 |
278 AMCC460EX_PCIE1_CFG_PLBA,
279 SAM460EX_PCIE1CFG_VA, TLB_PG_SIZE, TLB_I | TLB_G);
280 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_MEM_PA_HIGH << 32 |
281 AMCC460EX_PCIE0_MEM_PLBA,
282 SAM460EX_PCIE0MEM_VA, TLB_PG_SIZE, TLB_I | TLB_G);
283 ppc44x_tlb_reserve((uint64_t)AMCC460EX_PCIE_MEM_PA_HIGH << 32 |
284 AMCC460EX_PCIE1_MEM_PLBA,
285 SAM460EX_PCIE1MEM_VA, TLB_PG_SIZE, TLB_I | TLB_G);
286
287 /*
288 * AHB peripherals (USB OTG/OHCI/EHCI) behind the PLB-AHB
289 * bridge.
290 */
291 ppc44x_tlb_reserve((uint64_t)AMCC460EX_AHB_PA_HIGH << 32 |
292 AMCC460EX_AHB_BASE,
293 SAM460EX_AHB_VA, TLB_PG_SIZE, TLB_I | TLB_G);
294
295 mtspr(SPR_TCR, 0); /* disable all timers */
296
297 ibm40x_memsize_init(memsize, startkernel);
298 ibm4xx_init(startkernel, endkernel, pic_ext_intr);
299
300 #ifdef DDB
301 if (boothowto & RB_KDB)
302 Debugger();
303 #endif
304 }
305
306 /*
307 * UART input clock for the console and com devices.
308 */
309 uint32_t
310 sam460ex_com_freq(void)
311 {
312
313 #ifdef SAM460EX_FDT
314 if (sam460ex_fdt_info.fi_uart_freq != 0)
315 return sam460ex_fdt_info.fi_uart_freq;
316 #endif
317 return AMCC460EX_COM_FREQ;
318 }
319
320 void
321 consinit(void)
322 {
323
324 #if (NCOM > 0)
325 com_opb_cnattach(sam460ex_com_freq(), CONADDR, CONSPEED, CONMODE);
326 #endif
327 }
328
329 /*
330 * Parse /chosen/bootargs.
331 */
332 static char bootspec_buf[64];
333
334 /* "console=fb" in bootargs makes the SM502 wsdisplay the console */
335 bool sam460ex_console_fb;
336
337 static void
338 parse_bootargs(const char *args)
339 {
340 const char *cp = args;
341
342 #define BA_DELIM(c) ((c) == ' ' || (c) == '"')
343 while (*cp != '\0') {
344 if (BA_DELIM(*cp)) {
345 cp++;
346 continue;
347 }
348 if (*cp == '-') {
349 for (cp++; *cp != '\0' && !BA_DELIM(*cp); cp++)
350 BOOT_FLAG(*cp, boothowto);
351 } else if (strncmp(cp, "root=", 5) == 0) {
352 char *bp = bootspec_buf;
353
354 for (cp += 5; *cp != '\0' && !BA_DELIM(*cp) &&
355 bp < &bootspec_buf[sizeof(bootspec_buf) - 1]; )
356 *bp++ = *cp++;
357 *bp = '\0';
358 if (bootspec_buf[0] != '\0') {
359 bootspec = bootspec_buf;
360 booted_method = "bootargs/root";
361 }
362 } else if (strncmp(cp, "console=fb", 10) == 0) {
363 sam460ex_console_fb = true;
364 cp += 10;
365 } else {
366 while (*cp != '\0' && !BA_DELIM(*cp))
367 cp++;
368 }
369 }
370 #undef BA_DELIM
371 }
372
373 /*
374 * Machine dependent startup code.
375 */
376 void
377 cpu_startup(void)
378 {
379 prop_number_t pn;
380 uint32_t cpu_freq = SAM460EX_CPU_FREQ;
381 uint32_t opb_freq = SAM460EX_OPB_FREQ;
382 uint32_t memsize = SAM460EX_MEMSIZE;
383
384 ibm4xx_cpu_startup("ACube Sam460ex (AMCC 460EX)");
385
386 #ifdef SAM460EX_FDT
387 /*
388 * The timebase runs at the CPU clock; "processor-frequency"
389 * feeds delay() and the DEC reload value.
390 */
391 if (sam460ex_fdt_info.fi_timebase_freq != 0)
392 cpu_freq = sam460ex_fdt_info.fi_timebase_freq;
393 else if (sam460ex_fdt_info.fi_cpu_freq != 0)
394 cpu_freq = sam460ex_fdt_info.fi_cpu_freq;
395 if (sam460ex_fdt_info.fi_opb_freq != 0)
396 opb_freq = sam460ex_fdt_info.fi_opb_freq;
397 if (sam460ex_fdt_info.fi_memsize != 0)
398 memsize = sam460ex_fdt_info.fi_memsize;
399 printf("sam460ex: fdt cpu %u Hz, opb %u Hz, uart %u Hz, mem %u MB\n",
400 cpu_freq, opb_freq, sam460ex_fdt_info.fi_uart_freq,
401 memsize / (1024 * 1024));
402 if (sam460ex_fdt_info.fi_bootargs != NULL) {
403 printf("bootargs: %s\n", sam460ex_fdt_info.fi_bootargs);
404 parse_bootargs(sam460ex_fdt_info.fi_bootargs);
405 }
406 #endif
407
408 #if NUKBD > 0
409 if (sam460ex_console_fb) {
410 ukbd_cnattach();
411 }
412 #endif
413
414 /*
415 * Set up the board props
416 */
417 board_info_init();
418
419 pn = prop_number_create_integer(cpu_freq);
420 KASSERT(pn != NULL);
421 if (prop_dictionary_set(board_properties, "processor-frequency",
422 pn) == false)
423 panic("setting processor-frequency");
424 prop_object_release(pn);
425
426 pn = prop_number_create_integer(opb_freq);
427 KASSERT(pn != NULL);
428 if (prop_dictionary_set(board_properties, "opb-frequency", pn) ==
429 false)
430 panic("setting opb-frequency");
431 prop_object_release(pn);
432
433 pn = prop_number_create_integer(memsize);
434 KASSERT(pn != NULL);
435 if (prop_dictionary_set(board_properties, "mem-size", pn) == false)
436 panic("setting mem-size");
437 prop_object_release(pn);
438
439 #ifdef SAM460EX_FDT
440 /*
441 * EMAC MAC addresses from the device tree filled by U-Boot
442 */
443 for (int i = 0; i < SAM460EX_NEMAC; i++) {
444 char propname[16];
445 prop_data_t pd;
446
447 if (!sam460ex_fdt_info.fi_enaddr_valid[i])
448 continue;
449 snprintf(propname, sizeof(propname), "emac%d-mac-addr", i);
450 pd = prop_data_create_data_nocopy(
451 sam460ex_fdt_info.fi_enaddr[i], 6);
452 KASSERT(pd != NULL);
453 if (prop_dictionary_set(board_properties, propname, pd) ==
454 false)
455 panic("setting %s", propname);
456 prop_object_release(pd);
457
458 snprintf(propname, sizeof(propname), "emac%d-mii-phy", i);
459 pn = prop_number_create_integer(i);
460 KASSERT(pn != NULL);
461 if (prop_dictionary_set(board_properties, propname, pn) ==
462 false)
463 panic("setting %s", propname);
464 prop_object_release(pn);
465 }
466 #endif
467
468 calc_delayconst();
469
470 /*
471 * Now that we have VM, malloc is OK
472 */
473 bus_space_mallocok();
474 fake_mapiodev = 0;
475 }
476
477 /*
478 * PCI interrupt routing and slot policy for the on-chip PLB-PCIX
479 * bridge (see powerpc/ibm4xx/pci/pcix.c).
480 *
481 * XXX: On the Sam460ex every PCI intr pin is wired to UIC1 bit 0?
482 */
483 int
484 ibm4xx_pci_bus_maxdevs(void *v, int busno)
485 {
486 return 16;
487 }
488
489 /*
490 * Board interrupt routing for the PCI-X slot. Unlike the AMCC Canyonlands
491 * design (where the SoC's external IRQ2 / UIC1 bit 0 is the PCI INT), the
492 * Sam460ex wire-ORs all PCI INTx through its FPGA onto UIC1 bit 3 = irq 35
493 */
494 #define SAM460EX_PCI_INTR_IRQ 32 /* TEMP, see above; correct value is 35? */
495
496 int
497 ibm4xx_pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
498 {
499 *ihp = SAM460EX_PCI_INTR_IRQ;
500 return 0;
501 }
502
503 void
504 ibm4xx_pci_conf_interrupt(void *v, int bus, int dev, int pin, int swiz,
505 int *iline)
506 {
507 *iline = SAM460EX_PCI_INTR_IRQ;
508 }
509
510 #define UIC_DUMP(n, base) \
511 blen += snprintf(buf + blen, sizeof(buf) - blen, \
512 "uic%d SR=%08x MSR=%08x ER=%08x PR=%08x TR=%08x\n", (n), \
513 (unsigned int)mfdcr((base) + DCR_UIC_SR), \
514 (unsigned int)mfdcr((base) + DCR_UIC_MSR), \
515 (unsigned int)mfdcr((base) + DCR_UIC_ER), \
516 (unsigned int)mfdcr((base) + DCR_UIC_PR), \
517 (unsigned int)mfdcr((base) + DCR_UIC_TR))
518
519 static int
520 sysctl_machdep_uicregs(SYSCTLFN_ARGS)
521 {
522 struct sysctlnode node;
523 char buf[400];
524 int blen = 0;
525
526 UIC_DUMP(0, DCR_UIC0_BASE);
527 UIC_DUMP(1, DCR_UIC1_BASE);
528 UIC_DUMP(2, DCR_UIC2_BASE);
529 UIC_DUMP(3, DCR_UIC3_BASE);
530
531 node = *rnode;
532 node.sysctl_data = buf;
533 node.sysctl_size = strlen(buf) + 1;
534 return sysctl_lookup(SYSCTLFN_CALL(&node));
535 }
536 #undef UIC_DUMP
537
538 SYSCTL_SETUP(sysctl_machdep_uicregs_setup, "sam460ex UIC register dump")
539 {
540
541 sysctl_createv(clog, 0, NULL, NULL,
542 CTLFLAG_PERMANENT | CTLFLAG_READONLY,
543 CTLTYPE_STRING, "uicregs",
544 SYSCTL_DESCR("UIC0-3 SR/MSR/ER/PR/TR (interrupt debug)"),
545 sysctl_machdep_uicregs, 0, NULL, 0,
546 CTL_MACHDEP, CTL_CREATE, CTL_EOL);
547 }
548
549