1 /* $NetBSD: machdep.c,v 1.11 2002/09/25 22:21:07 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1986, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah $Hdr: machdep.c 1.74 92/12/20$ 41 * 42 * @(#)machdep.c 8.10 (Berkeley) 4/20/94 43 */ 44 45 #include "opt_bufcache.h" 46 #include "opt_ddb.h" 47 #include "opt_kgdb.h" 48 #include "opt_compat_hpux.h" 49 #include "opt_compat_netbsd.h" 50 #include "opt_sysv.h" 51 52 #include <sys/param.h> 53 #include <sys/systm.h> 54 #include <sys/buf.h> 55 #include <sys/callout.h> 56 #include <sys/conf.h> 57 #include <sys/exec.h> 58 #include <sys/file.h> 59 #include <sys/ioctl.h> 60 #include <sys/kernel.h> 61 #include <sys/malloc.h> 62 #include <sys/mbuf.h> 63 #include <sys/mount.h> 64 #include <sys/msgbuf.h> 65 #include <sys/proc.h> 66 #include <sys/reboot.h> 67 #include <sys/signalvar.h> 68 #include <sys/syscallargs.h> 69 #include <sys/tty.h> 70 #include <sys/user.h> 71 #include <sys/vnode.h> 72 #ifdef SYSVMSG 73 #include <sys/msg.h> 74 #endif 75 #ifdef SYSVSEM 76 #include <sys/sem.h> 77 #endif 78 #ifdef SYSVSHM 79 #include <sys/shm.h> 80 #endif 81 #include <sys/kgdb.h> 82 83 #include <machine/db_machdep.h> 84 #include <ddb/db_sym.h> 85 #include <ddb/db_extern.h> 86 87 #include <machine/autoconf.h> 88 #include <machine/cpu.h> 89 #include <machine/reg.h> 90 #include <machine/psl.h> 91 #include <machine/pte.h> 92 93 #define MAXMEM 64*1024 /* XXX - from cmap.h */ 94 95 #include <uvm/uvm_extern.h> 96 97 #include <sys/sysctl.h> 98 #include <sys/device.h> 99 #include <dev/cons.h> 100 #include <dev/ic/z8530reg.h> 101 #include <machine/z8530var.h> 102 #include <cesfic/dev/zsvar.h> 103 104 105 /* the following is used externally (sysctl_hw) */ 106 char machine[] = MACHINE; /* cpu "architecture" */ 107 108 /* Our exported CPU info; we can have only one. */ 109 struct cpu_info cpu_info_store; 110 111 struct vm_map *exec_map = NULL; 112 struct vm_map *mb_map = NULL; 113 struct vm_map *phys_map = NULL; 114 115 extern vaddr_t virtual_avail; 116 117 /* 118 * Declare these as initialized data so we can patch them. 119 */ 120 caddr_t msgbufaddr; 121 /*int maxmem;*/ /* max memory per process */ 122 int physmem = MAXMEM; /* max supported memory, changes to actual */ 123 /* 124 * safepri is a safe priority for sleep to set for a spin-wait 125 * during autoconfiguration or after a panic. 126 */ 127 int safepri = PSL_LOWIPL; 128 129 extern u_int lowram; 130 131 void fic_init __P((void)); 132 133 /* prototypes for local functions */ 134 void identifycpu __P((void)); 135 void dumpmem __P((int *, int, int)); 136 char *hexstr __P((int, int)); 137 138 /* functions called from locore.s */ 139 void dumpsys __P((void)); 140 void straytrap __P((int, u_short)); 141 void nmihand __P((struct frame)); 142 143 int delay_divisor; /* delay constant */ 144 145 extern void sicinit __P((void*)); 146 147 void fic_init() 148 { 149 int i; 150 151 extern paddr_t avail_start, avail_end; 152 153 boothowto = RB_SINGLE; /* XXX for now */ 154 boothowto |= RB_KDB; /* XXX for now */ 155 156 delay_divisor = 30; /* XXX */ 157 158 /* 159 * Tell the VM system about available physical memory. The 160 * fic uses one segment. 161 */ 162 uvm_page_physload(atop(avail_start), atop(avail_end), 163 atop(avail_start), atop(avail_end), VM_FREELIST_DEFAULT); 164 165 /* 166 * map and init interrupt controller 167 */ 168 physaccess((void*)virtual_avail, (void*)0x44000000, NBPG, PG_RW|PG_CI); 169 sicinit((void*)virtual_avail); 170 virtual_avail += NBPG; 171 172 /* 173 * Initialize error message buffer (at end of core). 174 * avail_end was pre-decremented in pmap_bootstrap to compensate. 175 */ 176 for (i = 0; i < btoc(MSGBUFSIZE); i++) 177 pmap_enter(pmap_kernel(), (vm_offset_t)msgbufaddr + i * NBPG, 178 avail_end + i * NBPG, VM_PROT_READ|VM_PROT_WRITE, 179 VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED); 180 initmsgbuf(msgbufaddr, m68k_round_page(MSGBUFSIZE)); 181 } 182 183 int 184 zs_check_kgdb(cs, dev) 185 struct zs_chanstate *cs; 186 int dev; 187 { 188 189 if((boothowto & RB_KDB) && (dev == makedev(10, 0))) 190 return (1); 191 return (0); 192 } 193 194 void zs_kgdb_cnputc __P((dev_t, int)); 195 void zs_kgdb_cnputc(dev, c) 196 dev_t dev; 197 int c; 198 { 199 zscnputc(dev, c); 200 } 201 int zs_kgdb_cngetc __P((dev_t)); 202 int zs_kgdb_cngetc(dev) 203 dev_t dev; 204 { 205 return (zscngetc(dev)); 206 } 207 208 /* 209 * Console initialization: called early on from main, 210 * before vm init or startup. Do enough configuration 211 * to choose and initialize a console. 212 */ 213 extern void sic_enable_int __P((int, int, int, int, int)); 214 void 215 consinit() 216 { 217 218 /* 219 * Initialize the console before we print anything out. 220 */ 221 physaccess((void*)virtual_avail, (void*)0x58000000, NBPG, PG_RW|PG_CI); 222 zs_cnattach((void*)virtual_avail); 223 virtual_avail += NBPG; 224 225 #ifdef KGDB 226 kgdb_dev = 1; 227 kgdb_attach((void*)zscngetc, (void*)zscnputc, (void *)0); 228 229 if (boothowto & RB_KDB) { 230 kgdb_connect(1); 231 zscons.cn_putc = zs_kgdb_cnputc; 232 zscons.cn_getc = zs_kgdb_cngetc; 233 } 234 #endif 235 #ifdef DDB 236 ddb_init(0, 0, 0); 237 if (boothowto & RB_KDB) 238 Debugger(); 239 #endif 240 sic_enable_int(39, 2, 1, 7, 0); /* NMI */ 241 } 242 243 /* 244 * cpu_startup: allocate memory for variable-sized tables, 245 * initialize cpu, and do autoconfiguration. 246 */ 247 void 248 cpu_startup() 249 { 250 extern char *etext; 251 caddr_t v; 252 int i, base, residual; 253 vaddr_t minaddr, maxaddr; 254 vsize_t size; 255 #ifdef DEBUG 256 extern int pmapdebug; 257 int opmapdebug = pmapdebug; 258 259 pmapdebug = 0; 260 #endif 261 262 /* 263 * Good {morning,afternoon,evening,night}. 264 */ 265 printf(version); 266 identifycpu(); 267 printf("real mem = %d\n", ctob(physmem)); 268 269 /* 270 * Find out how much space we need, allocate it, 271 * and the give everything true virtual addresses. 272 */ 273 size = (vm_size_t)allocsys(NULL, NULL); 274 if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(size))) == 0) 275 panic("startup: no room for tables"); 276 if ((allocsys(v, NULL) - v) != size) 277 panic("startup: talbe size inconsistency"); 278 279 /* 280 * Now allocate buffers proper. They are different than the above 281 * in that they usually occupy more virtual memory than physical. 282 */ 283 size = MAXBSIZE * nbuf; 284 if (uvm_map(kernel_map, (vm_offset_t *) &buffers, round_page(size), 285 NULL, UVM_UNKNOWN_OFFSET, 0, 286 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 287 UVM_ADV_NORMAL, 0)) != 0) 288 panic("startup: cannot allocate VM for buffers"); 289 minaddr = (vm_offset_t)buffers; 290 base = bufpages / nbuf; 291 residual = bufpages % nbuf; 292 for (i = 0; i < nbuf; i++) { 293 vm_size_t curbufsize; 294 vm_offset_t curbuf; 295 struct vm_page *pg; 296 297 /* 298 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 299 * that MAXBSIZE space, we allocate and map (base+1) pages 300 * for the first "residual" buffers, and then we allocate 301 * "base" pages for the rest. 302 */ 303 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 304 curbufsize = NBPG * ((i < residual) ? (base+1) : base); 305 306 while (curbufsize) { 307 pg = uvm_pagealloc(NULL, 0, NULL, 0); 308 if (pg == NULL) 309 panic("cpu_startup: not enough memory for " 310 "buffer cache"); 311 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 312 VM_PROT_READ|VM_PROT_WRITE); 313 curbuf += PAGE_SIZE; 314 curbufsize -= PAGE_SIZE; 315 } 316 } 317 318 /* 319 * Allocate a submap for exec arguments. This map effectively 320 * limits the number of processes exec'ing at any time. 321 */ 322 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 323 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 324 325 /* 326 * Allocate a submap for physio 327 */ 328 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 329 VM_PHYS_SIZE, 0, FALSE, NULL); 330 331 /* 332 * Finally, allocate mbuf cluster submap. 333 */ 334 mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 335 nmbclusters * mclbytes, VM_MAP_INTRSAFE, 336 FALSE, NULL); 337 338 #ifdef DEBUG 339 pmapdebug = opmapdebug; 340 #endif 341 printf("avail mem = %ld\n", ptoa(uvmexp.free)); 342 printf("using %u buffers containing %d bytes of memory\n", 343 nbuf, bufpages * NBPG); 344 345 /* 346 * Tell the VM system that writing to kernel text isn't allowed. 347 * If we don't, we might end up COW'ing the text segment! 348 */ 349 if (uvm_map_protect(kernel_map, KERNBASE, m68k_round_page(&etext), 350 UVM_PROT_READ|UVM_PROT_EXEC, TRUE) != 0) 351 panic("can't protect kernel text"); 352 353 /* 354 * Set up buffers, so they can be used to read disk labels. 355 */ 356 bufinit(); 357 } 358 359 /* 360 * Set registers on exec. 361 * XXX Should clear registers except sp, pc, 362 * but would break init; should be fixed soon. 363 */ 364 void 365 setregs(p, pack, stack) 366 struct proc *p; 367 struct exec_package *pack; 368 u_long stack; 369 { 370 struct frame *frame = (struct frame *)p->p_md.md_regs; 371 372 frame->f_sr = PSL_USERSET; 373 frame->f_pc = pack->ep_entry & ~1; 374 frame->f_regs[D0] = 0; 375 frame->f_regs[D1] = 0; 376 frame->f_regs[D2] = 0; 377 frame->f_regs[D3] = 0; 378 frame->f_regs[D4] = 0; 379 frame->f_regs[D5] = 0; 380 frame->f_regs[D6] = 0; 381 frame->f_regs[D7] = 0; 382 frame->f_regs[A0] = 0; 383 frame->f_regs[A1] = 0; 384 frame->f_regs[A2] = (int)p->p_psstr; 385 frame->f_regs[A3] = 0; 386 frame->f_regs[A4] = 0; 387 frame->f_regs[A5] = 0; 388 frame->f_regs[A6] = 0; 389 frame->f_regs[SP] = stack; 390 391 /* restore a null state frame */ 392 p->p_addr->u_pcb.pcb_fpregs.fpf_null = 0; 393 if (fputype) 394 m68881_restore(&p->p_addr->u_pcb.pcb_fpregs); 395 } 396 397 /* 398 * Info for CTL_HW 399 */ 400 char cpu_model[] = "FIC8234"; 401 402 void 403 identifycpu() 404 { 405 printf("%s\n", cpu_model); 406 printf("delay constant: %d\n", delay_divisor); 407 } 408 409 /* 410 * machine dependent system variables. 411 */ 412 int 413 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 414 int *name; 415 u_int namelen; 416 void *oldp; 417 size_t *oldlenp; 418 void *newp; 419 size_t newlen; 420 struct proc *p; 421 { 422 dev_t consdev; 423 424 /* all sysctl names at this level are terminal */ 425 if (namelen != 1) 426 return (ENOTDIR); /* overloaded */ 427 428 switch (name[0]) { 429 case CPU_CONSDEV: 430 if (cn_tab != NULL) 431 consdev = cn_tab->cn_dev; 432 else 433 consdev = NODEV; 434 return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev, 435 sizeof consdev)); 436 default: 437 return (EOPNOTSUPP); 438 } 439 /* NOTREACHED */ 440 } 441 442 443 #define SS_RTEFRAME 1 444 #define SS_FPSTATE 2 445 #define SS_USERREGS 4 446 447 struct sigstate { 448 int ss_flags; /* which of the following are valid */ 449 struct frame ss_frame; /* original exception frame */ 450 struct fpframe ss_fpstate; /* 68881/68882 state info */ 451 }; 452 453 int waittime = -1; 454 455 void 456 cpu_reboot(howto, bootstr) 457 int howto; 458 char *bootstr; 459 { 460 461 #if __GNUC__ /* XXX work around lame compiler problem (gcc 2.7.2) */ 462 (void)&howto; 463 #endif 464 /* take a snap shot before clobbering any registers */ 465 if (curproc && curproc->p_addr) 466 savectx(&curproc->p_addr->u_pcb); 467 468 /* If system is cold, just halt. */ 469 if (cold) { 470 howto |= RB_HALT; 471 goto haltsys; 472 } 473 474 boothowto = howto; 475 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 476 waittime = 0; 477 vfs_shutdown(); 478 /* 479 * If we've been adjusting the clock, the todr 480 * will be out of synch; adjust it now. 481 */ 482 resettodr(); 483 } 484 485 /* Disable interrupts. */ 486 splhigh(); 487 488 /* If rebooting and a dump is requested do it. */ 489 if (howto & RB_DUMP) 490 dumpsys(); 491 492 haltsys: 493 /* Run any shutdown hooks. */ 494 doshutdownhooks(); 495 496 #if defined(PANICWAIT) && !defined(DDB) 497 if ((howto & RB_HALT) == 0 && panicstr) { 498 printf("hit any key to reboot...\n"); 499 (void)cngetc(); 500 printf("\n"); 501 } 502 #endif 503 504 /* Finally, halt/reboot the system. */ 505 if (howto & RB_HALT) { 506 printf("System halted. Hit any key to reboot.\n\n"); 507 (void)cngetc(); 508 } 509 510 printf("rebooting...\n"); 511 DELAY(1000000); 512 doboot(); 513 /*NOTREACHED*/ 514 } 515 516 /* 517 * These variables are needed by /sbin/savecore 518 */ 519 u_int32_t dumpmag = 0x8fca0101; /* magic number */ 520 int dumpsize = 0; /* pages */ 521 long dumplo = 0; /* blocks */ 522 523 /* 524 * This is called by main to set dumplo and dumpsize. 525 * Dumps always skip the first CLBYTES of disk space 526 * in case there might be a disk label stored there. 527 * If there is extra space, put dump at the end to 528 * reduce the chance that swapping trashes it. 529 */ 530 void 531 cpu_dumpconf() 532 { 533 const struct bdevsw *bdev; 534 int nblks; /* size of dump area */ 535 536 if (dumpdev == NODEV) 537 return; 538 bdev = bdevsw_lookup(dumpdev); 539 if (bdev == NULL) 540 panic("dumpconf: bad dumpdev=0x%x", dumpdev); 541 if (bdev->d_psize == NULL) 542 return; 543 nblks = (*bdev->d_psize)(dumpdev); 544 if (nblks <= ctod(1)) 545 return; 546 547 /* 548 * XXX include the final RAM page which is not included in physmem. 549 */ 550 dumpsize = physmem + 1; 551 552 /* Always skip the first CLBYTES, in case there is a label there. */ 553 if (dumplo < ctod(1)) 554 dumplo = ctod(1); 555 556 /* Put dump at end of partition, and make it fit. */ 557 if (dumpsize > dtoc(nblks - dumplo)) 558 dumpsize = dtoc(nblks - dumplo); 559 if (dumplo < nblks - ctod(dumpsize)) 560 dumplo = nblks - ctod(dumpsize); 561 } 562 563 /* 564 * Dump physical memory onto the dump device. Called by doadump() 565 * in locore.s or by cpu_reboot() here in machdep.c 566 */ 567 void 568 dumpsys() 569 { 570 const struct bdevsw *bdev; 571 daddr_t blkno; /* current block to write */ 572 /* dump routine */ 573 int (*dump) __P((dev_t, daddr_t, caddr_t, size_t)); 574 int pg; /* page being dumped */ 575 vm_offset_t maddr; /* PA being dumped */ 576 int error; /* error code from (*dump)() */ 577 578 /* Don't put dump messages in msgbuf. */ 579 msgbufmapped = 0; 580 581 /* Make sure dump device is valid. */ 582 if (dumpdev == NODEV) 583 return; 584 bdev = bdevsw_lookup(dumpdev); 585 if (bdev == NULL) 586 return; 587 if (dumpsize == 0) { 588 cpu_dumpconf(); 589 if (dumpsize == 0) 590 return; 591 } 592 if (dumplo < 0) 593 return; 594 dump = bdev->d_dump; 595 blkno = dumplo; 596 597 printf("\ndumping to dev 0x%x, offset %ld\n", dumpdev, dumplo); 598 599 printf("dump "); 600 maddr = lowram; 601 for (pg = 0; pg < dumpsize; pg++) { 602 #define NPGMB (1024*1024/NBPG) 603 /* print out how many MBs we have dumped */ 604 if (pg && (pg % NPGMB) == 0) 605 printf("%d ", pg / NPGMB); 606 #undef NPGMB 607 pmap_enter(pmap_kernel(), (vm_offset_t)vmmap, maddr, 608 VM_PROT_READ, VM_PROT_READ|PMAP_WIRED); 609 610 error = (*dump)(dumpdev, blkno, vmmap, NBPG); 611 switch (error) { 612 case 0: 613 maddr += NBPG; 614 blkno += btodb(NBPG); 615 break; 616 617 case ENXIO: 618 printf("device bad\n"); 619 return; 620 621 case EFAULT: 622 printf("device not ready\n"); 623 return; 624 625 case EINVAL: 626 printf("area improper\n"); 627 return; 628 629 case EIO: 630 printf("i/o error\n"); 631 return; 632 633 case EINTR: 634 printf("aborted from console\n"); 635 return; 636 637 default: 638 printf("error %d\n", error); 639 return; 640 } 641 } 642 printf("succeeded\n"); 643 } 644 645 void 646 straytrap(pc, evec) 647 int pc; 648 u_short evec; 649 { 650 printf("unexpected trap (vector offset %x) from %x\n", 651 evec & 0xFFF, pc); 652 } 653 654 /* XXX should change the interface, and make one badaddr() function */ 655 656 int *nofault; 657 658 int 659 badaddr(addr) 660 caddr_t addr; 661 { 662 int i; 663 label_t faultbuf; 664 665 nofault = (int *) &faultbuf; 666 if (setjmp((label_t *)nofault)) { 667 nofault = (int *) 0; 668 return (1); 669 } 670 i = *(volatile short *)addr; 671 nofault = (int *) 0; 672 return (0); 673 } 674 675 int 676 badbaddr(addr) 677 caddr_t addr; 678 { 679 int i; 680 label_t faultbuf; 681 682 nofault = (int *) &faultbuf; 683 if (setjmp((label_t *)nofault)) { 684 nofault = (int *) 0; 685 return (1); 686 } 687 i = *(volatile char *)addr; 688 nofault = (int *) 0; 689 return (0); 690 } 691 692 #ifdef PANICBUTTON 693 /* 694 * Declare these so they can be patched. 695 */ 696 int panicbutton = 1; /* non-zero if panic buttons are enabled */ 697 int candbdiv = 2; /* give em half a second (hz / candbdiv) */ 698 699 void candbtimer __P((void *)); 700 701 int crashandburn; 702 703 void 704 candbtimer(arg) 705 void *arg; 706 { 707 708 crashandburn = 0; 709 } 710 #endif /* PANICBUTTON */ 711 712 static int innmihand; /* simple mutex */ 713 714 /* 715 * Level 7 interrupts can be caused by the keyboard or parity errors. 716 */ 717 void 718 nmihand(frame) 719 struct frame frame; 720 { 721 722 /* Prevent unwanted recursion. */ 723 if (innmihand) 724 return; 725 innmihand = 1; 726 727 printf("NMI\n"); 728 #if defined(DDB) || defined(KGDB) 729 Debugger(); 730 #endif 731 732 innmihand = 0; 733 } 734 735 736 /* 737 * cpu_exec_aout_makecmds(): 738 * cpu-dependent a.out format hook for execve(). 739 * 740 * Determine of the given exec package refers to something which we 741 * understand and, if so, set up the vmcmds for it. 742 * 743 * XXX what are the special cases for the hp300? 744 * XXX why is this COMPAT_NOMID? was something generating 745 * hp300 binaries with an a_mid of 0? i thought that was only 746 * done on little-endian machines... -- cgd 747 */ 748 int 749 cpu_exec_aout_makecmds(p, epp) 750 struct proc *p; 751 struct exec_package *epp; 752 { 753 #if defined(COMPAT_NOMID) || defined(COMPAT_44) 754 u_long midmag, magic; 755 u_short mid; 756 int error; 757 struct exec *execp = epp->ep_hdr; 758 759 midmag = ntohl(execp->a_midmag); 760 mid = (midmag >> 16) & 0xffff; 761 magic = midmag & 0xffff; 762 763 midmag = mid << 16 | magic; 764 765 switch (midmag) { 766 #ifdef COMPAT_NOMID 767 case (MID_ZERO << 16) | ZMAGIC: 768 error = exec_aout_prep_oldzmagic(p, epp); 769 return (error); 770 #endif 771 #ifdef COMPAT_44 772 case (MID_HP300 << 16) | ZMAGIC: 773 error = exec_aout_prep_oldzmagic(p, epp); 774 return (error); 775 #endif 776 } 777 #endif /* !(defined(COMPAT_NOMID) || defined(COMPAT_44)) */ 778 779 return ENOEXEC; 780 } 781