[BACK]Return to machdep.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / i386 / i386

Annotation of src/sys/arch/i386/i386/machdep.c, Revision 1.366

1.366   ! fvdl        1: /*     $NetBSD: machdep.c,v 1.365 1999/09/17 19:59:43 thorpej Exp $    */
1.231     thorpej     2:
                      3: /*-
1.277     thorpej     4:  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
1.231     thorpej     5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
1.316     mycroft     8:  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
                      9:  * Simulation Facility, NASA Ames Research Center.
1.231     thorpej    10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *     This product includes software developed by the NetBSD
                     22:  *     Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
1.125     cgd        39:
1.1       cgd        40: /*-
                     41:  * Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
                     42:  * All rights reserved.
                     43:  *
                     44:  * This code is derived from software contributed to Berkeley by
                     45:  * William Jolitz.
                     46:  *
                     47:  * Redistribution and use in source and binary forms, with or without
                     48:  * modification, are permitted provided that the following conditions
                     49:  * are met:
                     50:  * 1. Redistributions of source code must retain the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer.
                     52:  * 2. Redistributions in binary form must reproduce the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer in the
                     54:  *    documentation and/or other materials provided with the distribution.
                     55:  * 3. All advertising materials mentioning features or use of this software
                     56:  *    must display the following acknowledgement:
                     57:  *     This product includes software developed by the University of
                     58:  *     California, Berkeley and its contributors.
                     59:  * 4. Neither the name of the University nor the names of its contributors
                     60:  *    may be used to endorse or promote products derived from this software
                     61:  *    without specific prior written permission.
                     62:  *
                     63:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     64:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     65:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     66:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     67:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     68:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     69:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     70:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     71:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     72:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     73:  * SUCH DAMAGE.
                     74:  *
1.125     cgd        75:  *     @(#)machdep.c   7.4 (Berkeley) 6/3/91
1.1       cgd        76:  */
1.271     thorpej    77:
                     78: #include "opt_cputype.h"
1.309     jonathan   79: #include "opt_ddb.h"
1.272     thorpej    80: #include "opt_vm86.h"
1.274     thorpej    81: #include "opt_user_ldt.h"
1.310     jonathan   82: #include "opt_compat_netbsd.h"
1.327     bouyer     83: #include "opt_cpureset_delay.h"
1.333     christos   84: #include "opt_compat_svr4.h"
1.1       cgd        85:
1.59      mycroft    86: #include <sys/param.h>
                     87: #include <sys/systm.h>
                     88: #include <sys/signalvar.h>
                     89: #include <sys/kernel.h>
                     90: #include <sys/map.h>
                     91: #include <sys/proc.h>
                     92: #include <sys/user.h>
                     93: #include <sys/exec.h>
                     94: #include <sys/buf.h>
                     95: #include <sys/reboot.h>
                     96: #include <sys/conf.h>
                     97: #include <sys/file.h>
                     98: #include <sys/callout.h>
                     99: #include <sys/malloc.h>
                    100: #include <sys/mbuf.h>
                    101: #include <sys/msgbuf.h>
                    102: #include <sys/mount.h>
                    103: #include <sys/vnode.h>
1.92      mycroft   104: #include <sys/device.h>
1.204     thorpej   105: #include <sys/extent.h>
1.123     cgd       106: #include <sys/syscallargs.h>
1.291     thorpej   107: #include <sys/core.h>
                    108: #include <sys/kcore.h>
                    109: #include <machine/kcore.h>
1.57      cgd       110:
1.235     thorpej   111: #ifdef KGDB
                    112: #include <sys/kgdb.h>
                    113: #endif
                    114:
1.104     cgd       115: #include <dev/cons.h>
                    116:
1.59      mycroft   117: #include <vm/vm.h>
                    118: #include <vm/vm_kern.h>
                    119: #include <vm/vm_page.h>
1.31      cgd       120:
1.284     mrg       121: #include <uvm/uvm_extern.h>
                    122:
1.200     christos  123: #include <sys/sysctl.h>
                    124:
1.231     thorpej   125: #define _I386_BUS_DMA_PRIVATE
                    126: #include <machine/bus.h>
                    127:
1.59      mycroft   128: #include <machine/cpu.h>
                    129: #include <machine/cpufunc.h>
1.178     mycroft   130: #include <machine/gdt.h>
1.149     mycroft   131: #include <machine/pio.h>
1.59      mycroft   132: #include <machine/psl.h>
                    133: #include <machine/reg.h>
                    134: #include <machine/specialreg.h>
1.255     drochner  135: #include <machine/bootinfo.h>
1.43      brezak    136:
1.146     cgd       137: #include <dev/isa/isareg.h>
                    138: #include <dev/isa/isavar.h>
1.164     cgd       139: #include <dev/ic/i8042reg.h>
                    140: #include <dev/ic/mc146818reg.h>
1.158     cgd       141: #include <i386/isa/nvram.h>
1.43      brezak    142:
1.200     christos  143: #ifdef DDB
                    144: #include <machine/db_machdep.h>
                    145: #include <ddb/db_access.h>
                    146: #include <ddb/db_sym.h>
                    147: #include <ddb/db_extern.h>
                    148: #endif
                    149:
1.184     mycroft   150: #ifdef VM86
                    151: #include <machine/vm86.h>
                    152: #endif
                    153:
1.207     jtk       154: #include "apm.h"
1.258     jtk       155: #include "bioscall.h"
1.207     jtk       156:
1.259     jtk       157: #if NBIOSCALL > 0
                    158: #include <machine/bioscall.h>
                    159: #endif
                    160:
1.207     jtk       161: #if NAPM > 0
                    162: #include <machine/apmvar.h>
1.258     jtk       163: #endif
                    164:
1.59      mycroft   165: #include "isa.h"
1.231     thorpej   166: #include "isadma.h"
1.59      mycroft   167: #include "npx.h"
1.161     mycroft   168: #if NNPX > 0
                    169: extern struct proc *npxproc;
                    170: #endif
1.2       cgd       171:
1.296     drochner  172: #include "vga.h"
1.303     drochner  173: #include "pcdisplay.h"
                    174: #if (NVGA > 0) || (NPCDISPLAY > 0)
                    175: #include <dev/ic/mc6845reg.h>
                    176: #include <dev/ic/pcdisplayvar.h>
1.296     drochner  177: #if (NVGA > 0)
                    178: #include <dev/ic/vgareg.h>
                    179: #include <dev/ic/vgavar.h>
                    180: #endif
1.303     drochner  181: #if (NPCDISPLAY > 0)
                    182: #include <dev/isa/pcdisplayvar.h>
                    183: #endif
                    184: #endif
1.296     drochner  185:
                    186: #include "pckbc.h"
                    187: #if (NPCKBC > 0)
                    188: #include <dev/isa/pckbcvar.h>
                    189: #endif
                    190:
1.337     drochner  191: #include "pc.h"
                    192: #if (NPC > 0)
                    193: #include <machine/pccons.h>
                    194: #endif
                    195:
                    196: #include "vt.h"
                    197: #if (NVT > 0)
                    198: #include <i386/isa/pcvt/pcvt_cons.h>
                    199: #endif
                    200:
1.243     drochner  201: #include "com.h"
                    202: #if (NCOM > 0)
1.242     drochner  203: #include <sys/termios.h>
1.260     thorpej   204: #include <dev/ic/comreg.h>
                    205: #include <dev/ic/comvar.h>
1.242     drochner  206: #endif
                    207:
1.104     cgd       208: /* the following is used externally (sysctl_hw) */
                    209: char machine[] = "i386";               /* cpu "architecture" */
1.232     veego     210: char machine_arch[] = "i386";          /* machine == machine_arch */
1.104     cgd       211:
1.255     drochner  212: char bootinfo[BOOTINFO_MAXSIZE];
                    213:
1.343     fvdl      214: struct bi_devmatch *i386_alldisks = NULL;
                    215: int i386_ndisks = 0;
1.342     fvdl      216:
1.328     bouyer    217: #ifdef CPURESET_DELAY
                    218: int    cpureset_delay = CPURESET_DELAY;
                    219: #else
                    220: int     cpureset_delay = 2000; /* default to 2s */
                    221: #endif
                    222:
1.1       cgd       223:
1.59      mycroft   224: int    physmem;
1.163     cgd       225: int    dumpmem_low;
                    226: int    dumpmem_high;
1.59      mycroft   227: int    boothowto;
                    228: int    cpu_class;
1.366   ! fvdl      229: int    i386_fpu_present = 0;
1.59      mycroft   230:
1.314     thorpej   231: vaddr_t        msgbuf_vaddr;
                    232: paddr_t msgbuf_paddr;
                    233:
                    234: vaddr_t        idt_vaddr;
                    235: paddr_t        idt_paddr;
                    236:
1.264     mycroft   237: #ifdef I586_CPU
1.314     thorpej   238: vaddr_t        pentium_idt_vaddr;
1.264     mycroft   239: #endif
1.59      mycroft   240:
1.284     mrg       241: vm_map_t exec_map = NULL;
                    242: vm_map_t mb_map = NULL;
                    243: vm_map_t phys_map = NULL;
1.48      brezak    244:
1.203     mycroft   245: extern int biosbasemem, biosextmem;
1.314     thorpej   246: extern paddr_t avail_start, avail_end;
                    247: extern paddr_t hole_start, hole_end;
1.1       cgd       248:
1.204     thorpej   249: /*
1.205     thorpej   250:  * Extent maps to manage I/O and ISA memory hole space.  Allocate
                    251:  * storage for 8 regions in each, initially.  Later, ioport_malloc_safe
                    252:  * will indicate that it's safe to use malloc() to dynamically allocate
                    253:  * region descriptors.
1.213     thorpej   254:  *
                    255:  * N.B. At least two regions are _always_ allocated from the iomem
                    256:  * extent map; (0 -> ISA hole) and (end of ISA hole -> end of RAM).
                    257:  *
                    258:  * The extent maps are not static!  Machine-dependent ISA and EISA
                    259:  * routines need access to them for bus address space allocation.
1.204     thorpej   260:  */
1.211     thorpej   261: static long ioport_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
                    262: static long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
1.213     thorpej   263: struct extent *ioport_ex;
                    264: struct extent *iomem_ex;
1.298     mycroft   265: static int ioport_malloc_safe;
1.204     thorpej   266:
1.291     thorpej   267: /*
                    268:  * Size of memory segments, before any memory is stolen.
                    269:  */
                    270: phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX];
                    271: int    mem_cluster_cnt;
                    272:
                    273: int    cpu_dump __P((void));
                    274: int    cpu_dumpsize __P((void));
                    275: u_long cpu_dump_mempagecnt __P((void));
1.200     christos  276: void   dumpsys __P((void));
                    277: void   identifycpu __P((void));
1.314     thorpej   278: void   init386 __P((paddr_t));
1.255     drochner  279:
                    280: #ifndef CONSDEVNAME
                    281: #define CONSDEVNAME "pc"
                    282: #endif
1.256     drochner  283: #if (NCOM > 0)
1.245     drochner  284: #ifndef CONADDR
                    285: #define CONADDR 0x3f8
1.243     drochner  286: #endif
1.245     drochner  287: #ifndef CONSPEED
                    288: #define CONSPEED TTYDEF_SPEED
                    289: #endif
                    290: #ifndef CONMODE
                    291: #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
                    292: #endif
1.256     drochner  293: int comcnmode = CONMODE;
                    294: #endif /* NCOM */
1.255     drochner  295: struct btinfo_console default_consinfo = {
                    296:        {0, 0},
                    297:        CONSDEVNAME,
1.256     drochner  298: #if (NCOM > 0)
1.255     drochner  299:        CONADDR, CONSPEED
1.256     drochner  300: #else
                    301:        0, 0
                    302: #endif
1.255     drochner  303: };
1.200     christos  304: void   consinit __P((void));
1.255     drochner  305:
1.243     drochner  306: #ifdef KGDB
1.255     drochner  307: #ifndef KGDB_DEVNAME
                    308: #define KGDB_DEVNAME "com"
                    309: #endif
                    310: char kgdb_devname[] = KGDB_DEVNAME;
1.245     drochner  311: #if (NCOM > 0)
                    312: #ifndef KGDBADDR
                    313: #define KGDBADDR 0x3f8
                    314: #endif
1.255     drochner  315: int comkgdbaddr = KGDBADDR;
1.245     drochner  316: #ifndef KGDBRATE
                    317: #define KGDBRATE TTYDEF_SPEED
                    318: #endif
1.255     drochner  319: int comkgdbrate = KGDBRATE;
1.245     drochner  320: #ifndef KGDBMODE
                    321: #define KGDBMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
                    322: #endif
1.255     drochner  323: int comkgdbmode = KGDBMODE;
1.245     drochner  324: #endif /* NCOM */
1.243     drochner  325: void kgdb_port_init __P((void));
1.245     drochner  326: #endif /* KGDB */
1.255     drochner  327:
1.200     christos  328: #ifdef COMPAT_NOMID
                    329: static int exec_nomid  __P((struct proc *, struct exec_package *));
                    330: #endif
1.59      mycroft   331:
1.237     cgd       332: int    i386_mem_add_mapping __P((bus_addr_t, bus_size_t,
1.213     thorpej   333:            int, bus_space_handle_t *));
                    334:
1.317     thorpej   335: int    _bus_dmamap_load_buffer __P((bus_dma_tag_t, bus_dmamap_t, void *,
                    336:            bus_size_t, struct proc *, int, paddr_t *, int *, int));
1.277     thorpej   337:
1.267     bouyer    338: void cyrix6x86_cpu_setup __P((void));
                    339:
                    340: static __inline u_char
                    341: cyrix_read_reg(u_char reg)
                    342: {
                    343:        outb(0x22, reg);
                    344:        return inb(0x23);
                    345: }
                    346:
                    347: static __inline void
                    348: cyrix_write_reg(u_char reg, u_char data)
                    349: {
                    350:        outb(0x22, reg);
                    351:        outb(0x23, data);
                    352: }
                    353:
1.59      mycroft   354: /*
                    355:  * Machine-dependent startup code
                    356:  */
1.32      andrew    357: void
1.1       cgd       358: cpu_startup()
                    359: {
1.59      mycroft   360:        unsigned i;
                    361:        caddr_t v;
1.349     thorpej   362:        int sz, x;
1.314     thorpej   363:        vaddr_t minaddr, maxaddr;
                    364:        vsize_t size;
1.354     lukem     365:        char pbuf[9];
1.258     jtk       366: #if NBIOSCALL > 0
1.207     jtk       367:        extern int biostramp_image_size;
                    368:        extern u_char biostramp_image[];
                    369: #endif
1.1       cgd       370:
1.284     mrg       371:        /*
                    372:         * Initialize error message buffer (et end of core).
                    373:         */
1.354     lukem     374:        msgbuf_vaddr = uvm_km_valloc(kernel_map, i386_round_page(MSGBUFSIZE));
1.284     mrg       375:        if (msgbuf_vaddr == NULL)
                    376:                panic("failed to valloc msgbuf_vaddr");
1.359     thorpej   377:
1.284     mrg       378:        /* msgbuf_paddr was init'd in pmap */
                    379:        for (x = 0; x < btoc(MSGBUFSIZE); x++)
1.314     thorpej   380:                pmap_kenter_pa((vaddr_t)msgbuf_vaddr + x * NBPG,
1.356     thorpej   381:                    msgbuf_paddr + x * NBPG, VM_PROT_READ|VM_PROT_WRITE);
1.359     thorpej   382:
1.284     mrg       383:        initmsgbuf((caddr_t)msgbuf_vaddr, round_page(MSGBUFSIZE));
                    384:
1.210     christos  385:        printf(version);
1.16      cgd       386:        identifycpu();
1.267     bouyer    387:
1.354     lukem     388:        format_bytes(pbuf, sizeof(pbuf), ctob(physmem));
                    389:        printf("total memory = %s\n", pbuf);
1.1       cgd       390:
                    391:        /*
1.59      mycroft   392:         * Find out how much space we need, allocate it,
                    393:         * and then give everything true virtual addresses.
1.1       cgd       394:         */
1.354     lukem     395:        sz = (int)allocsys(NULL, NULL);
1.284     mrg       396:        if ((v = (caddr_t)uvm_km_zalloc(kernel_map, round_page(sz))) == 0)
                    397:                panic("startup: no room for tables");
1.354     lukem     398:        if (allocsys(v, NULL) - v != sz)
1.1       cgd       399:                panic("startup: table size inconsistency");
1.50      cgd       400:
1.36      cgd       401:        /*
1.284     mrg       402:         * Allocate virtual address space for the buffers.  The area
                    403:         * is not managed by the VM system.
1.36      cgd       404:         */
                    405:        size = MAXBSIZE * nbuf;
1.314     thorpej   406:        if (uvm_map(kernel_map, (vaddr_t *) &buffers, round_page(size),
1.284     mrg       407:                    NULL, UVM_UNKNOWN_OFFSET,
                    408:                    UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE,
                    409:                                UVM_ADV_NORMAL, 0)) != KERN_SUCCESS)
                    410:                panic("cpu_startup: cannot allocate VM for buffers");
1.314     thorpej   411:        minaddr = (vaddr_t)buffers;
1.54      cgd       412:        if ((bufpages / nbuf) >= btoc(MAXBSIZE)) {
                    413:                /* don't want to alloc more physical mem than needed */
                    414:                bufpages = btoc(MAXBSIZE) * nbuf;
                    415:        }
1.36      cgd       416:
1.268     thorpej   417:        /*
                    418:         * XXX We defer allocation of physical pages for buffers until
                    419:         * XXX after autoconfiguration has run.  We must do this because
                    420:         * XXX on system with large amounts of memory or with large
                    421:         * XXX user-configured buffer caches, the buffer cache will eat
                    422:         * XXX up all of the lower 16M of RAM.  This prevents ISA DMA
                    423:         * XXX maps from allocating bounce pages.
                    424:         *
                    425:         * XXX Note that nothing can use buffer cache buffers until after
                    426:         * XXX autoconfiguration completes!!
                    427:         *
                    428:         * XXX This is a hack, and needs to be replaced with a better
                    429:         * XXX solution!  --thorpej@netbsd.org, December 6, 1997
                    430:         */
1.41      cgd       431:
1.1       cgd       432:        /*
1.36      cgd       433:         * Allocate a submap for exec arguments.  This map effectively
                    434:         * limits the number of processes exec'ing at any time.
1.1       cgd       435:         */
1.284     mrg       436:        exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   437:                                   16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
1.59      mycroft   438:
1.1       cgd       439:        /*
                    440:         * Allocate a submap for physio
                    441:         */
1.284     mrg       442:        phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   443:                                   VM_PHYS_SIZE, 0, FALSE, NULL);
1.1       cgd       444:
                    445:        /*
1.229     thorpej   446:         * Finally, allocate mbuf cluster submap.
1.1       cgd       447:         */
1.334     thorpej   448:        mb_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
1.358     thorpej   449:            nmbclusters * mclbytes, VM_MAP_INTRSAFE, FALSE, NULL);
1.59      mycroft   450:
1.1       cgd       451:        /*
                    452:         * Initialize callouts
                    453:         */
                    454:        callfree = callout;
                    455:        for (i = 1; i < ncallout; i++)
                    456:                callout[i-1].c_next = &callout[i];
                    457:
1.284     mrg       458:        /*
                    459:         * XXX Buffer cache pages haven't yet been allocated, so
                    460:         * XXX we need to account for those pages when printing
                    461:         * XXX the amount of free memory.
                    462:         */
1.354     lukem     463:        format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free - bufpages));
                    464:        printf("avail memory = %s\n", pbuf);
                    465:        format_bytes(pbuf, sizeof(pbuf), bufpages * CLBYTES);
                    466:        printf("using %d buffers containing %s of memory\n", nbuf, pbuf);
1.1       cgd       467:
1.258     jtk       468: #if NBIOSCALL > 0
1.207     jtk       469:        /*
                    470:         * this should be caught at kernel build time, but put it here
                    471:         * in case someone tries to fake it out...
                    472:         */
                    473: #ifdef DIAGNOSTIC
                    474:        if (biostramp_image_size > NBPG)
                    475:            panic("biostramp_image_size too big: %x vs. %x\n",
                    476:                  biostramp_image_size, NBPG);
                    477: #endif
1.314     thorpej   478:        pmap_kenter_pa((vaddr_t)BIOSTRAMP_BASE, /* virtual */
                    479:                       (paddr_t)BIOSTRAMP_BASE, /* physical */
                    480:                       VM_PROT_ALL);            /* protection */
1.313     perry     481:        memcpy((caddr_t)BIOSTRAMP_BASE, biostramp_image, biostramp_image_size);
1.207     jtk       482: #ifdef DEBUG
1.258     jtk       483:        printf("biostramp installed @ %x\n", BIOSTRAMP_BASE);
1.207     jtk       484: #endif
                    485: #endif
1.263     mycroft   486:
1.348     thorpej   487:        /* Safe for i/o port allocation to use malloc now. */
1.204     thorpej   488:        ioport_malloc_safe = 1;
1.349     thorpej   489: }
                    490:
                    491: /*
                    492:  * Set up proc0's TSS and LDT.
                    493:  */
                    494: void
                    495: i386_proc0_tss_ldt_init()
                    496: {
                    497:        struct pcb *pcb;
                    498:        int x;
1.268     thorpej   499:
1.326     thorpej   500:        gdt_init();
                    501:        curpcb = pcb = &proc0.p_addr->u_pcb;
                    502:        pcb->pcb_flags = 0;
                    503:        pcb->pcb_tss.tss_ioopt =
                    504:            ((caddr_t)pcb->pcb_iomap - (caddr_t)&pcb->pcb_tss) << 16;
                    505:        for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
                    506:                pcb->pcb_iomap[x] = 0xffffffff;
                    507:
                    508:        pcb->pcb_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
                    509:        pcb->pcb_cr0 = rcr0();
                    510:        pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
                    511:        pcb->pcb_tss.tss_esp0 = (int)proc0.p_addr + USPACE - 16;
                    512:        tss_alloc(pcb);
                    513:
                    514:        ltr(pcb->pcb_tss_sel);
                    515:        lldt(pcb->pcb_ldt_sel);
                    516:
                    517:        proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_esp0 - 1;
                    518: }
                    519:
                    520: /*
                    521:  * XXX Finish up the deferred buffer cache allocation and initialization.
                    522:  */
                    523: void
                    524: i386_bufinit()
                    525: {
                    526:        int i, base, residual;
                    527:
1.268     thorpej   528:        base = bufpages / nbuf;
                    529:        residual = bufpages % nbuf;
                    530:        for (i = 0; i < nbuf; i++) {
1.314     thorpej   531:                vsize_t curbufsize;
                    532:                vaddr_t curbuf;
1.284     mrg       533:                struct vm_page *pg;
                    534:
                    535:                /*
                    536:                 * Each buffer has MAXBSIZE bytes of VM space allocated.  Of
                    537:                 * that MAXBSIZE space, we allocate and map (base+1) pages
                    538:                 * for the first "residual" buffers, and then we allocate
                    539:                 * "base" pages for the rest.
                    540:                 */
1.314     thorpej   541:                curbuf = (vaddr_t) buffers + (i * MAXBSIZE);
1.284     mrg       542:                curbufsize = CLBYTES * ((i < residual) ? (base+1) : base);
                    543:
                    544:                while (curbufsize) {
1.311     thorpej   545:                        /*
                    546:                         * Attempt to allocate buffers from the first
                    547:                         * 16M of RAM to avoid bouncing file system
                    548:                         * transfers.
                    549:                         */
1.350     chs       550:                        pg = uvm_pagealloc_strat(NULL, 0, NULL, 0,
1.311     thorpej   551:                            UVM_PGA_STRAT_FALLBACK, VM_FREELIST_FIRST16);
1.284     mrg       552:                        if (pg == NULL)
                    553:                                panic("cpu_startup: not enough memory for "
                    554:                                    "buffer cache");
                    555:                        pmap_kenter_pgs(curbuf, &pg, 1);
                    556:                        curbuf += PAGE_SIZE;
                    557:                        curbufsize -= PAGE_SIZE;
                    558:                }
1.268     thorpej   559:        }
                    560:
                    561:        /*
                    562:         * Set up buffers, so they can be used to read disk labels.
                    563:         */
                    564:        bufinit();
1.16      cgd       565: }
                    566:
1.104     cgd       567: /*
                    568:  * Info for CTL_HW
                    569:  */
                    570: char   cpu_model[120];
                    571: extern char version[];
                    572:
1.216     fvdl      573: /*
                    574:  * Note: these are just the ones that may not have a cpuid instruction.
                    575:  * We deal with the rest in a different way.
                    576:  */
                    577: struct cpu_nocpuid_nameclass i386_nocpuid_cpus[] = {
1.267     bouyer    578:        { CPUVENDOR_INTEL, "Intel", "386SX",    CPUCLASS_386,
                    579:                NULL},                          /* CPU_386SX */
                    580:        { CPUVENDOR_INTEL, "Intel", "386DX",    CPUCLASS_386,
                    581:                NULL},                          /* CPU_386   */
                    582:        { CPUVENDOR_INTEL, "Intel", "486SX",    CPUCLASS_486,
                    583:                NULL},                          /* CPU_486SX */
                    584:        { CPUVENDOR_INTEL, "Intel", "486DX",    CPUCLASS_486,
                    585:                NULL},                          /* CPU_486   */
                    586:        { CPUVENDOR_CYRIX, "Cyrix", "486DLC",   CPUCLASS_486,
                    587:                NULL},                          /* CPU_486DLC */
                    588:        { CPUVENDOR_CYRIX, "Cyrix", "6x86",             CPUCLASS_486,
                    589:                cyrix6x86_cpu_setup},   /* CPU_6x86 */
                    590:        { CPUVENDOR_NEXGEN,"NexGen","586",      CPUCLASS_386,
                    591:                NULL},                          /* CPU_NX586 */
1.216     fvdl      592: };
                    593:
                    594: const char *classnames[] = {
                    595:        "386",
                    596:        "486",
                    597:        "586",
                    598:        "686"
                    599: };
                    600:
                    601: const char *modifiers[] = {
                    602:        "",
                    603:        "OverDrive ",
                    604:        "Dual ",
                    605:        ""
1.18      cgd       606: };
                    607:
1.216     fvdl      608: struct cpu_cpuid_nameclass i386_cpuid_cpus[] = {
                    609:        {
                    610:                "GenuineIntel",
                    611:                CPUVENDOR_INTEL,
                    612:                "Intel",
                    613:                /* Family 4 */
                    614:                { {
                    615:                        CPUCLASS_486,
                    616:                        {
1.219     perry     617:                                "486DX", "486DX", "486SX", "486DX2", "486SL",
1.216     fvdl      618:                                "486SX2", 0, "486DX2 W/B Enhanced",
                    619:                                "486DX4", 0, 0, 0, 0, 0, 0, 0,
                    620:                                "486"           /* Default */
1.267     bouyer    621:                        },
                    622:                        NULL
1.216     fvdl      623:                },
                    624:                /* Family 5 */
                    625:                {
                    626:                        CPUCLASS_586,
                    627:                        {
1.361     tron      628:                                "Pentium (P5 A-step)", "Pentium (P5)",
                    629:                                "Pentium (P54C)", "Pentium (P24T)",
                    630:                                "Pentium/MMX", "Pentium", 0,
                    631:                                "Pentium (P54C)", "Pentium/MMX (Tillamook)",
                    632:                                0, 0, 0, 0, 0, 0, 0,
1.216     fvdl      633:                                "Pentium"       /* Default */
1.267     bouyer    634:                        },
                    635:                        NULL
1.216     fvdl      636:                },
                    637:                /* Family 6 */
                    638:                {
                    639:                        CPUCLASS_686,
                    640:                        {
1.361     tron      641:                                "Pentium Pro (A-step)", "Pentium Pro", 0,
                    642:                                "Pentium II (Klamath)", "Pentium Pro",
                    643:                                "Pentium II (Deschutes)",
1.340     fvdl      644:                                "Pentium II (Celeron)",
                    645:                                "Pentium III", 0, 0, 0, 0, 0, 0, 0, 0,
                    646:                                "Pentium Pro, II or III"        /* Default */
1.267     bouyer    647:                        },
                    648:                        NULL
1.216     fvdl      649:                } }
                    650:        },
                    651:        {
                    652:                "AuthenticAMD",
                    653:                CPUVENDOR_AMD,
                    654:                "AMD",
                    655:                /* Family 4 */
                    656:                { {
                    657:                        CPUCLASS_486,
                    658:                        {
                    659:                                0, 0, 0, "Am486DX2 W/T",
                    660:                                0, 0, 0, "Am486DX2 W/B",
                    661:                                "Am486DX4 W/T or Am5x86 W/T 150",
                    662:                                "Am486DX4 W/B or Am5x86 W/B 150", 0, 0,
                    663:                                0, 0, "Am5x86 W/T 133/160",
                    664:                                "Am5x86 W/B 133/160",
                    665:                                "Am486 or Am5x86"       /* Default */
                    666:                        },
1.267     bouyer    667:                        NULL
1.216     fvdl      668:                },
                    669:                /* Family 5 */
                    670:                {
                    671:                        CPUCLASS_586,
                    672:                        {
1.241     fvdl      673:                                "K5", "K5", "K5", "K5", 0, 0, "K6",
1.341     fvdl      674:                                "K6", "K6-2", "K6-III", 0, 0, 0, 0, 0, 0,
1.267     bouyer    675:                                "K5 or K6"              /* Default */
1.216     fvdl      676:                        },
1.267     bouyer    677:                        NULL
1.216     fvdl      678:                },
1.363     fvdl      679:                /* Family 6 */
1.216     fvdl      680:                {
                    681:                        CPUCLASS_686,
                    682:                        {
1.362     fvdl      683:                                0, "K7 (Athlon)", 0, 0, 0, 0, 0,
1.216     fvdl      684:                                0, 0, 0, 0, 0, 0, 0, 0, 0,
1.362     fvdl      685:                                "K7 (Athlon)"   /* Default */
1.216     fvdl      686:                        },
1.267     bouyer    687:                        NULL
1.216     fvdl      688:                } }
                    689:        },
                    690:        {
                    691:                "CyrixInstead",
                    692:                CPUVENDOR_CYRIX,
                    693:                "Cyrix",
                    694:                /* Family 4 */
                    695:                { {
                    696:                        CPUCLASS_486,
                    697:                        {
                    698:                                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    699:                                "486"           /* Default */
                    700:                        },
1.267     bouyer    701:                        NULL
1.216     fvdl      702:                },
                    703:                /* Family 5 */
                    704:                {
                    705:                        CPUCLASS_586,
                    706:                        {
                    707:                                0, 0, "6x86", 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    708:                                0, 0, 0, 0,
                    709:                                "6x86"          /* Default */
1.267     bouyer    710:                        },
                    711:                        cyrix6x86_cpu_setup
1.216     fvdl      712:                },
1.278     bouyer    713:                /* Family 6 */
1.216     fvdl      714:                {
                    715:                        CPUCLASS_686,
                    716:                        {
1.278     bouyer    717:                                "6x86MX", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    718:                                "6x86MX"                /* Default */
1.329     bad       719:                        },
                    720:                        NULL
                    721:                } }
                    722:        },
                    723:        {
                    724:                "CentaurHauls",
                    725:                CPUVENDOR_IDT,
                    726:                "IDT",
                    727:                /* Family 4, IDT never had any of these */
                    728:                { {
                    729:                        CPUCLASS_486,
                    730:                        {
                    731:                                0, 0, 0, 0, 0, 0, 0,
                    732:                                0, 0, 0, 0, 0, 0, 0, 0, 0,
                    733:                                "486 compatible"        /* Default */
                    734:                        },
                    735:                        NULL
                    736:                },
                    737:                /* Family 5 */
                    738:                {
                    739:                        CPUCLASS_586,
                    740:                        {
                    741:                                0, 0, 0, 0, "WinChip C6", 0, 0, 0,
                    742:                                0, 0, 0, 0, 0, 0, 0, 0,
                    743:                                "WinChip"               /* Default */
                    744:                        },
                    745:                        NULL
                    746:                },
                    747:                /* Family 6, not yet available from IDT */
                    748:                {
                    749:                        CPUCLASS_686,
                    750:                        {
                    751:                                0, 0, 0, 0, 0, 0, 0,
                    752:                                0, 0, 0, 0, 0, 0, 0, 0, 0,
                    753:                                "Pentium Pro compatible"        /* Default */
1.267     bouyer    754:                        },
                    755:                        NULL
1.216     fvdl      756:                } }
                    757:        }
                    758: };
                    759:
                    760: #define CPUDEBUG
                    761:
1.195     mycroft   762: void
1.267     bouyer    763: cyrix6x86_cpu_setup()
                    764: {
                    765:        /* set up various cyrix registers */
                    766:        /* Enable suspend on halt */
                    767:        cyrix_write_reg(0xc2, cyrix_read_reg(0xc2) | 0x08);
                    768:        /* enable access to ccr4/ccr5 */
                    769:        cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) | 0x10);
                    770:        /* cyrix's workaround  for the "coma bug" */
                    771:        cyrix_write_reg(0x31, cyrix_read_reg(0x31) | 0xf8);
                    772:        cyrix_write_reg(0x32, cyrix_read_reg(0x32) | 0x7f);
                    773:        cyrix_write_reg(0x33, cyrix_read_reg(0x33) & ~0xff);
                    774:        cyrix_write_reg(0x3c, cyrix_read_reg(0x3c) | 0x87);
                    775:        /* disable access to ccr4/ccr5 */
                    776:        cyrix_write_reg(0xC3, cyrix_read_reg(0xC3) & ~0x10);
                    777: }
                    778:
                    779: void
1.59      mycroft   780: identifycpu()
1.16      cgd       781: {
1.86      mycroft   782:        extern char cpu_vendor[];
1.216     fvdl      783:        extern int cpu_id;
                    784:        const char *name, *modifier, *vendorname;
                    785:        int class = CPUCLASS_386, vendor, i, max;
                    786:        int family, model, step, modif;
                    787:        struct cpu_cpuid_nameclass *cpup = NULL;
1.267     bouyer    788:        void (*cpu_setup) __P((void));
1.86      mycroft   789:
1.216     fvdl      790:        if (cpuid_level == -1) {
1.59      mycroft   791: #ifdef DIAGNOSTIC
1.216     fvdl      792:                if (cpu < 0 || cpu >=
                    793:                    (sizeof i386_nocpuid_cpus/sizeof(struct cpu_nocpuid_nameclass)))
                    794:                        panic("unknown cpu type %d\n", cpu);
                    795: #endif
                    796:                name = i386_nocpuid_cpus[cpu].cpu_name;
                    797:                vendor = i386_nocpuid_cpus[cpu].cpu_vendor;
                    798:                vendorname = i386_nocpuid_cpus[cpu].cpu_vendorname;
                    799:                class = i386_nocpuid_cpus[cpu].cpu_class;
1.267     bouyer    800:                cpu_setup = i386_nocpuid_cpus[cpu].cpu_setup;
1.216     fvdl      801:                modifier = "";
                    802:        } else {
                    803:                max = sizeof (i386_cpuid_cpus) / sizeof (i386_cpuid_cpus[0]);
                    804:                modif = (cpu_id >> 12) & 3;
                    805:                family = (cpu_id >> 8) & 15;
                    806:                if (family < CPU_MINFAMILY)
                    807:                        panic("identifycpu: strange family value");
                    808:                model = (cpu_id >> 4) & 15;
                    809:                step = cpu_id & 15;
                    810: #ifdef CPUDEBUG
                    811:                printf("cpu0: family %x model %x step %x\n", family, model,
                    812:                        step);
                    813: #endif
                    814:
                    815:                for (i = 0; i < max; i++) {
                    816:                        if (!strncmp(cpu_vendor,
                    817:                            i386_cpuid_cpus[i].cpu_id, 12)) {
                    818:                                cpup = &i386_cpuid_cpus[i];
                    819:                                break;
                    820:                        }
                    821:                }
                    822:
                    823:                if (cpup == NULL) {
                    824:                        vendor = CPUVENDOR_UNKNOWN;
                    825:                        if (cpu_vendor[0] != '\0')
                    826:                                vendorname = &cpu_vendor[0];
                    827:                        else
                    828:                                vendorname = "Unknown";
                    829:                        if (family > CPU_MAXFAMILY)
                    830:                                family = CPU_MAXFAMILY;
                    831:                        class = family - 3;
                    832:                        modifier = "";
                    833:                        name = "";
1.267     bouyer    834:                        cpu_setup = NULL;
1.216     fvdl      835:                } else {
                    836:                        vendor = cpup->cpu_vendor;
                    837:                        vendorname = cpup->cpu_vendorname;
                    838:                        modifier = modifiers[modif];
                    839:                        if (family > CPU_MAXFAMILY) {
                    840:                                family = CPU_MAXFAMILY;
                    841:                                model = CPU_DEFMODEL;
                    842:                        } else if (model > CPU_MAXMODEL)
                    843:                                model = CPU_DEFMODEL;
                    844:                        i = family - CPU_MINFAMILY;
                    845:                        name = cpup->cpu_family[i].cpu_models[model];
                    846:                        if (name == NULL)
                    847:                            name = cpup->cpu_family[i].cpu_models[CPU_DEFMODEL];
                    848:                        class = cpup->cpu_family[i].cpu_class;
1.267     bouyer    849:                        cpu_setup = cpup->cpu_family[i].cpu_setup;
1.216     fvdl      850:                }
1.104     cgd       851:        }
                    852:
1.241     fvdl      853:        sprintf(cpu_model, "%s %s%s (%s-class)", vendorname, modifier, name,
                    854:                classnames[class]);
1.216     fvdl      855:        printf("cpu0: %s\n", cpu_model);
                    856:
                    857:        cpu_class = class;
1.18      cgd       858:
1.16      cgd       859:        /*
                    860:         * Now that we have told the user what they have,
                    861:         * let them know if that machine type isn't configured.
                    862:         */
1.24      cgd       863:        switch (cpu_class) {
1.216     fvdl      864: #if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
1.100     mycroft   865: #error No CPU classes configured.
                    866: #endif
1.216     fvdl      867: #ifndef I686_CPU
                    868:        case CPUCLASS_686:
                    869:                printf("NOTICE: this kernel does not support Pentium Pro CPU class\n");
                    870: #ifdef I586_CPU
                    871:                printf("NOTICE: lowering CPU class to i586\n");
                    872:                cpu_class = CPUCLASS_586;
                    873:                break;
                    874: #endif
                    875: #endif
1.165     mycroft   876: #ifndef I586_CPU
1.118     mycroft   877:        case CPUCLASS_586:
1.210     christos  878:                printf("NOTICE: this kernel does not support Pentium CPU class\n");
1.165     mycroft   879: #ifdef I486_CPU
1.210     christos  880:                printf("NOTICE: lowering CPU class to i486\n");
1.118     mycroft   881:                cpu_class = CPUCLASS_486;
                    882:                break;
1.16      cgd       883: #endif
1.165     mycroft   884: #endif
                    885: #ifndef I486_CPU
1.18      cgd       886:        case CPUCLASS_486:
1.210     christos  887:                printf("NOTICE: this kernel does not support i486 CPU class\n");
1.165     mycroft   888: #ifdef I386_CPU
1.210     christos  889:                printf("NOTICE: lowering CPU class to i386\n");
1.118     mycroft   890:                cpu_class = CPUCLASS_386;
                    891:                break;
                    892: #endif
1.165     mycroft   893: #endif
                    894: #ifndef I386_CPU
1.118     mycroft   895:        case CPUCLASS_386:
1.210     christos  896:                printf("NOTICE: this kernel does not support i386 CPU class\n");
1.187     mycroft   897:                panic("no appropriate CPU class available");
1.59      mycroft   898: #endif
1.16      cgd       899:        default:
                    900:                break;
1.121     mycroft   901:        }
                    902:
1.267     bouyer    903:        /* configure the CPU if needed */
                    904:        if (cpu_setup != NULL)
                    905:                cpu_setup();
1.121     mycroft   906:        if (cpu == CPU_486DLC) {
                    907: #ifndef CYRIX_CACHE_WORKS
1.210     christos  908:                printf("WARNING: CYRIX 486DLC CACHE UNCHANGED.\n");
1.121     mycroft   909: #else
                    910: #ifndef CYRIX_CACHE_REALLY_WORKS
1.210     christos  911:                printf("WARNING: CYRIX 486DLC CACHE ENABLED IN HOLD-FLUSH MODE.\n");
1.121     mycroft   912: #else
1.210     christos  913:                printf("WARNING: CYRIX 486DLC CACHE ENABLED.\n");
1.121     mycroft   914: #endif
                    915: #endif
1.16      cgd       916:        }
1.147     mycroft   917:
1.216     fvdl      918: #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
1.147     mycroft   919:        /*
1.199     mycroft   920:         * On a 486 or above, enable ring 0 write protection.
1.147     mycroft   921:         */
                    922:        if (cpu_class >= CPUCLASS_486)
1.199     mycroft   923:                lcr0(rcr0() | CR0_WP);
1.147     mycroft   924: #endif
1.1       cgd       925: }
                    926:
1.104     cgd       927: /*
                    928:  * machine dependent system variables.
                    929:  */
1.195     mycroft   930: int
1.104     cgd       931: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
                    932:        int *name;
                    933:        u_int namelen;
                    934:        void *oldp;
                    935:        size_t *oldlenp;
                    936:        void *newp;
                    937:        size_t newlen;
                    938:        struct proc *p;
                    939: {
                    940:        dev_t consdev;
1.255     drochner  941:        struct btinfo_bootpath *bibp;
1.104     cgd       942:
                    943:        /* all sysctl names at this level are terminal */
                    944:        if (namelen != 1)
                    945:                return (ENOTDIR);               /* overloaded */
                    946:
                    947:        switch (name[0]) {
                    948:        case CPU_CONSDEV:
                    949:                if (cn_tab != NULL)
                    950:                        consdev = cn_tab->cn_dev;
                    951:                else
                    952:                        consdev = NODEV;
                    953:                return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
                    954:                    sizeof consdev));
1.215     fvdl      955:
                    956:        case CPU_BIOSBASEMEM:
                    957:                return (sysctl_rdint(oldp, oldlenp, newp, biosbasemem));
                    958:
                    959:        case CPU_BIOSEXTMEM:
                    960:                return (sysctl_rdint(oldp, oldlenp, newp, biosextmem));
                    961:
                    962:        case CPU_NKPDE:
                    963:                return (sysctl_rdint(oldp, oldlenp, newp, nkpde));
1.366   ! fvdl      964:
        !           965:        case CPU_FPU_PRESENT:
        !           966:                return (sysctl_rdint(oldp, oldlenp, newp, i386_fpu_present));
1.215     fvdl      967:
1.255     drochner  968:        case CPU_BOOTED_KERNEL:
                    969:                bibp = lookup_bootinfo(BTINFO_BOOTPATH);
                    970:                if(!bibp)
                    971:                        return(ENOENT); /* ??? */
                    972:                return (sysctl_rdstring(oldp, oldlenp, newp, bibp->bootpath));
1.343     fvdl      973:        case CPU_DISKINFO:
                    974:                if (i386_alldisks == NULL)
1.339     fvdl      975:                        return (ENOENT);
1.343     fvdl      976:                return (sysctl_rdstruct(oldp, oldlenp, newp, i386_alldisks,
                    977:                    sizeof (struct disklist) +
                    978:                        (i386_ndisks - 1) * sizeof (struct nativedisk_info)));
1.104     cgd       979:        default:
                    980:                return (EOPNOTSUPP);
                    981:        }
                    982:        /* NOTREACHED */
                    983: }
1.151     christos  984:
1.1       cgd       985: /*
                    986:  * Send an interrupt to process.
                    987:  *
                    988:  * Stack is set up to allow sigcode stored
                    989:  * in u. to call routine, followed by kcall
                    990:  * to sigreturn routine below.  After sigreturn
                    991:  * resets the signal mask, the stack, and the
                    992:  * frame pointer, it returns to the user
                    993:  * specified pc, psl.
                    994:  */
                    995: void
                    996: sendsig(catcher, sig, mask, code)
                    997:        sig_t catcher;
1.319     mycroft   998:        int sig;
                    999:        sigset_t *mask;
1.126     cgd      1000:        u_long code;
1.1       cgd      1001: {
1.298     mycroft  1002:        struct proc *p = curproc;
                   1003:        struct trapframe *tf;
1.82      ws       1004:        struct sigframe *fp, frame;
1.104     cgd      1005:        struct sigacts *psp = p->p_sigacts;
1.319     mycroft  1006:        int onstack;
1.1       cgd      1007:
1.319     mycroft  1008:        tf = p->p_md.md_regs;
1.135     christos 1009:
1.319     mycroft  1010:        /* Do we need to jump onto the signal stack? */
                   1011:        onstack =
                   1012:            (psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
                   1013:            (psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0;
1.135     christos 1014:
1.319     mycroft  1015:        /* Allocate space for the signal handler context. */
                   1016:        if (onstack)
1.301     kleink   1017:                fp = (struct sigframe *)((caddr_t)psp->ps_sigstk.ss_sp +
1.320     mycroft  1018:                                                  psp->ps_sigstk.ss_size);
1.319     mycroft  1019:        else
                   1020:                fp = (struct sigframe *)tf->tf_esp;
                   1021:        fp--;
1.1       cgd      1022:
1.319     mycroft  1023:        /* Build stack frame for signal trampoline. */
                   1024:        frame.sf_signum = sig;
1.82      ws       1025:        frame.sf_code = code;
                   1026:        frame.sf_scp = &fp->sf_sc;
                   1027:        frame.sf_handler = catcher;
                   1028:
1.319     mycroft  1029:        /* Save register context. */
1.157     mycroft  1030: #ifdef VM86
                   1031:        if (tf->tf_eflags & PSL_VM) {
                   1032:                frame.sf_sc.sc_gs = tf->tf_vm86_gs;
                   1033:                frame.sf_sc.sc_fs = tf->tf_vm86_fs;
                   1034:                frame.sf_sc.sc_es = tf->tf_vm86_es;
                   1035:                frame.sf_sc.sc_ds = tf->tf_vm86_ds;
1.196     mycroft  1036:                frame.sf_sc.sc_eflags = get_vflags(p);
1.157     mycroft  1037:        } else
                   1038: #endif
                   1039:        {
                   1040:                __asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs));
                   1041:                __asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs));
                   1042:                frame.sf_sc.sc_es = tf->tf_es;
                   1043:                frame.sf_sc.sc_ds = tf->tf_ds;
1.184     mycroft  1044:                frame.sf_sc.sc_eflags = tf->tf_eflags;
1.157     mycroft  1045:        }
1.184     mycroft  1046:        frame.sf_sc.sc_edi = tf->tf_edi;
                   1047:        frame.sf_sc.sc_esi = tf->tf_esi;
                   1048:        frame.sf_sc.sc_ebp = tf->tf_ebp;
                   1049:        frame.sf_sc.sc_ebx = tf->tf_ebx;
                   1050:        frame.sf_sc.sc_edx = tf->tf_edx;
                   1051:        frame.sf_sc.sc_ecx = tf->tf_ecx;
                   1052:        frame.sf_sc.sc_eax = tf->tf_eax;
                   1053:        frame.sf_sc.sc_eip = tf->tf_eip;
                   1054:        frame.sf_sc.sc_cs = tf->tf_cs;
                   1055:        frame.sf_sc.sc_esp = tf->tf_esp;
                   1056:        frame.sf_sc.sc_ss = tf->tf_ss;
1.319     mycroft  1057:        frame.sf_sc.sc_trapno = tf->tf_trapno;
                   1058:        frame.sf_sc.sc_err = tf->tf_err;
                   1059:
                   1060:        /* Save signal stack. */
                   1061:        frame.sf_sc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
                   1062:
                   1063:        /* Save signal mask. */
                   1064:        frame.sf_sc.sc_mask = *mask;
1.322     thorpej  1065:
                   1066: #ifdef COMPAT_13
                   1067:        /*
                   1068:         * XXX We always have to save an old style signal mask because
                   1069:         * XXX we might be delivering a signal to a process which will
                   1070:         * XXX escape from the signal in a non-standard way and invoke
                   1071:         * XXX sigreturn() directly.
                   1072:         */
                   1073:        native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
                   1074: #endif
1.1       cgd      1075:
1.87      mycroft  1076:        if (copyout(&frame, fp, sizeof(frame)) != 0) {
1.1       cgd      1077:                /*
                   1078:                 * Process has trashed its stack; give it an illegal
                   1079:                 * instruction to halt it in its tracks.
                   1080:                 */
1.93      mycroft  1081:                sigexit(p, SIGILL);
                   1082:                /* NOTREACHED */
1.1       cgd      1083:        }
                   1084:
1.73      mycroft  1085:        /*
1.59      mycroft  1086:         * Build context to run handler in.
                   1087:         */
1.185     mycroft  1088:        __asm("movl %w0,%%gs" : : "r" (GSEL(GUDATA_SEL, SEL_UPL)));
                   1089:        __asm("movl %w0,%%fs" : : "r" (GSEL(GUDATA_SEL, SEL_UPL)));
                   1090:        tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
                   1091:        tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
1.319     mycroft  1092:        tf->tf_eip = (int)psp->ps_sigcode;
1.185     mycroft  1093:        tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
1.198     mycroft  1094:        tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
1.185     mycroft  1095:        tf->tf_esp = (int)fp;
1.177     mycroft  1096:        tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
1.319     mycroft  1097:
                   1098:        /* Remember that we're now on the signal stack. */
                   1099:        if (onstack)
                   1100:                psp->ps_sigstk.ss_flags |= SS_ONSTACK;
1.1       cgd      1101: }
                   1102:
                   1103: /*
                   1104:  * System call to cleanup state after a signal
                   1105:  * has been taken.  Reset signal mask and
                   1106:  * stack state from context left by sendsig (above).
                   1107:  * Return to previous pc and psl as specified by
                   1108:  * context left by sendsig. Check carefully to
                   1109:  * make sure that the user has not modified the
1.110     mycroft  1110:  * psl to gain improper privileges or to cause
1.1       cgd      1111:  * a machine fault.
                   1112:  */
1.195     mycroft  1113: int
1.320     mycroft  1114: sys___sigreturn14(p, v, retval)
1.1       cgd      1115:        struct proc *p;
1.172     thorpej  1116:        void *v;
                   1117:        register_t *retval;
                   1118: {
1.320     mycroft  1119:        struct sys___sigreturn14_args /* {
1.123     cgd      1120:                syscallarg(struct sigcontext *) sigcntxp;
1.172     thorpej  1121:        } */ *uap = v;
1.82      ws       1122:        struct sigcontext *scp, context;
1.298     mycroft  1123:        struct trapframe *tf;
1.59      mycroft  1124:
1.27      cgd      1125:        /*
1.59      mycroft  1126:         * The trampoline code hands us the context.
                   1127:         * It is unsafe to keep track of it ourselves, in the event that a
                   1128:         * program jumps out of a signal handler.
1.27      cgd      1129:         */
1.123     cgd      1130:        scp = SCARG(uap, sigcntxp);
1.87      mycroft  1131:        if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
1.122     mycroft  1132:                return (EFAULT);
1.1       cgd      1133:
1.319     mycroft  1134:        /* Restore register context. */
                   1135:        tf = p->p_md.md_regs;
1.157     mycroft  1136: #ifdef VM86
                   1137:        if (context.sc_eflags & PSL_VM) {
                   1138:                tf->tf_vm86_gs = context.sc_gs;
                   1139:                tf->tf_vm86_fs = context.sc_fs;
                   1140:                tf->tf_vm86_es = context.sc_es;
                   1141:                tf->tf_vm86_ds = context.sc_ds;
1.196     mycroft  1142:                set_vflags(p, context.sc_eflags);
1.157     mycroft  1143:        } else
                   1144: #endif
                   1145:        {
1.196     mycroft  1146:                /*
                   1147:                 * Check for security violations.  If we're returning to
                   1148:                 * protected mode, the CPU will validate the segment registers
                   1149:                 * automatically and generate a trap on violations.  We handle
                   1150:                 * the trap, rather than doing all of the checking here.
                   1151:                 */
                   1152:                if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
                   1153:                    !USERMODE(context.sc_cs, context.sc_eflags))
                   1154:                        return (EINVAL);
                   1155:
1.157     mycroft  1156:                /* %fs and %gs were restored by the trampoline. */
                   1157:                tf->tf_es = context.sc_es;
                   1158:                tf->tf_ds = context.sc_ds;
1.184     mycroft  1159:                tf->tf_eflags = context.sc_eflags;
1.157     mycroft  1160:        }
1.184     mycroft  1161:        tf->tf_edi = context.sc_edi;
                   1162:        tf->tf_esi = context.sc_esi;
                   1163:        tf->tf_ebp = context.sc_ebp;
                   1164:        tf->tf_ebx = context.sc_ebx;
                   1165:        tf->tf_edx = context.sc_edx;
                   1166:        tf->tf_ecx = context.sc_ecx;
                   1167:        tf->tf_eax = context.sc_eax;
                   1168:        tf->tf_eip = context.sc_eip;
                   1169:        tf->tf_cs = context.sc_cs;
                   1170:        tf->tf_esp = context.sc_esp;
                   1171:        tf->tf_ss = context.sc_ss;
1.196     mycroft  1172:
1.319     mycroft  1173:        /* Restore signal stack. */
                   1174:        if (context.sc_onstack & SS_ONSTACK)
1.196     mycroft  1175:                p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
                   1176:        else
                   1177:                p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
1.319     mycroft  1178:
                   1179:        /* Restore signal mask. */
                   1180:        (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0);
1.72      mycroft  1181:
1.122     mycroft  1182:        return (EJUSTRETURN);
1.37      cgd      1183: }
                   1184:
1.1       cgd      1185: int    waittime = -1;
                   1186: struct pcb dumppcb;
                   1187:
1.32      andrew   1188: void
1.228     gwr      1189: cpu_reboot(howto, bootstr)
1.193     mycroft  1190:        int howto;
1.206     mrg      1191:        char *bootstr;
1.1       cgd      1192: {
                   1193:
1.106     mycroft  1194:        if (cold) {
1.193     mycroft  1195:                howto |= RB_HALT;
                   1196:                goto haltsys;
1.1       cgd      1197:        }
1.193     mycroft  1198:
1.106     mycroft  1199:        boothowto = howto;
1.193     mycroft  1200:        if ((howto & RB_NOSYNC) == 0 && waittime < 0) {
1.1       cgd      1201:                waittime = 0;
1.150     mycroft  1202:                vfs_shutdown();
1.59      mycroft  1203:                /*
                   1204:                 * If we've been adjusting the clock, the todr
                   1205:                 * will be out of synch; adjust it now.
                   1206:                 */
                   1207:                resettodr();
1.1       cgd      1208:        }
1.193     mycroft  1209:
                   1210:        /* Disable interrupts. */
1.1       cgd      1211:        splhigh();
1.193     mycroft  1212:
                   1213:        /* Do a dump if requested. */
                   1214:        if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
                   1215:                dumpsys();
                   1216:
                   1217: haltsys:
                   1218:        doshutdownhooks();
                   1219:
1.307     thorpej  1220:        if ((howto & RB_POWERDOWN) == RB_POWERDOWN) {
1.208     jtk      1221: #if NAPM > 0 && !defined(APM_NO_POWEROFF)
                   1222:                /* turn off, if we can.  But try to turn disk off and
                   1223:                 * wait a bit first--some disk drives are slow to clean up
                   1224:                 * and users have reported disk corruption.
                   1225:                 */
                   1226:                delay(500000);
                   1227:                apm_set_powstate(APM_DEV_DISK(0xff), APM_SYS_OFF);
                   1228:                delay(500000);
                   1229:                apm_set_powstate(APM_DEV_ALLDEVS, APM_SYS_OFF);
1.307     thorpej  1230:                printf("WARNING: powerdown failed!\n");
                   1231:                /*
                   1232:                 * RB_POWERDOWN implies RB_HALT... fall into it...
                   1233:                 */
1.208     jtk      1234: #endif
1.307     thorpej  1235:        }
                   1236:
                   1237:        if (howto & RB_HALT) {
1.210     christos 1238:                printf("\n");
                   1239:                printf("The operating system has halted.\n");
                   1240:                printf("Please press any key to reboot.\n\n");
1.300     drochner 1241:                cnpollc(1);     /* for proper keyboard command handling */
1.12      cgd      1242:                cngetc();
1.300     drochner 1243:                cnpollc(0);
1.1       cgd      1244:        }
1.193     mycroft  1245:
1.210     christos 1246:        printf("rebooting...\n");
1.328     bouyer   1247:        if (cpureset_delay > 0)
                   1248:                delay(cpureset_delay * 1000);
1.1       cgd      1249:        cpu_reset();
                   1250:        for(;;) ;
                   1251:        /*NOTREACHED*/
                   1252: }
                   1253:
1.116     gwr      1254: /*
                   1255:  * These variables are needed by /sbin/savecore
                   1256:  */
                   1257: u_long dumpmag = 0x8fca0101;   /* magic number */
                   1258: int    dumpsize = 0;           /* pages */
                   1259: long   dumplo = 0;             /* blocks */
                   1260:
                   1261: /*
1.291     thorpej  1262:  * cpu_dumpsize: calculate size of machine-dependent kernel core dump headers.
                   1263:  */
                   1264: int
                   1265: cpu_dumpsize()
                   1266: {
                   1267:        int size;
                   1268:
                   1269:        size = ALIGN(sizeof(kcore_seg_t)) + ALIGN(sizeof(cpu_kcore_hdr_t)) +
                   1270:            ALIGN(mem_cluster_cnt * sizeof(phys_ram_seg_t));
                   1271:        if (roundup(size, dbtob(1)) != dbtob(1))
                   1272:                return (-1);
                   1273:
                   1274:        return (1);
                   1275: }
                   1276:
                   1277: /*
                   1278:  * cpu_dump_mempagecnt: calculate the size of RAM (in pages) to be dumped.
                   1279:  */
                   1280: u_long
                   1281: cpu_dump_mempagecnt()
                   1282: {
                   1283:        u_long i, n;
                   1284:
                   1285:        n = 0;
                   1286:        for (i = 0; i < mem_cluster_cnt; i++)
                   1287:                n += atop(mem_clusters[i].size);
                   1288:        return (n);
                   1289: }
                   1290:
                   1291: /*
                   1292:  * cpu_dump: dump the machine-dependent kernel core dump headers.
                   1293:  */
                   1294: int
                   1295: cpu_dump()
                   1296: {
                   1297:        int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
                   1298:        char buf[dbtob(1)];
                   1299:        kcore_seg_t *segp;
                   1300:        cpu_kcore_hdr_t *cpuhdrp;
                   1301:        phys_ram_seg_t *memsegp;
                   1302:        int i;
                   1303:
                   1304:        dump = bdevsw[major(dumpdev)].d_dump;
                   1305:
1.313     perry    1306:        memset(buf, 0, sizeof buf);
1.291     thorpej  1307:        segp = (kcore_seg_t *)buf;
                   1308:        cpuhdrp = (cpu_kcore_hdr_t *)&buf[ALIGN(sizeof(*segp))];
                   1309:        memsegp = (phys_ram_seg_t *)&buf[ ALIGN(sizeof(*segp)) +
                   1310:            ALIGN(sizeof(*cpuhdrp))];
                   1311:
                   1312:        /*
                   1313:         * Generate a segment header.
                   1314:         */
                   1315:        CORE_SETMAGIC(*segp, KCORE_MAGIC, MID_MACHINE, CORE_CPU);
                   1316:        segp->c_size = dbtob(1) - ALIGN(sizeof(*segp));
                   1317:
                   1318:        /*
                   1319:         * Add the machine-dependent header info.
                   1320:         */
                   1321:        cpuhdrp->ptdpaddr = PTDpaddr;
                   1322:        cpuhdrp->nmemsegs = mem_cluster_cnt;
                   1323:
                   1324:        /*
                   1325:         * Fill in the memory segment descriptors.
                   1326:         */
                   1327:        for (i = 0; i < mem_cluster_cnt; i++) {
                   1328:                memsegp[i].start = mem_clusters[i].start;
                   1329:                memsegp[i].size = mem_clusters[i].size;
                   1330:        }
                   1331:
                   1332:        return (dump(dumpdev, dumplo, (caddr_t)buf, dbtob(1)));
                   1333: }
                   1334:
                   1335: /*
1.228     gwr      1336:  * This is called by main to set dumplo and dumpsize.
1.116     gwr      1337:  * Dumps always skip the first CLBYTES of disk space
                   1338:  * in case there might be a disk label stored there.
                   1339:  * If there is extra space, put dump at the end to
                   1340:  * reduce the chance that swapping trashes it.
                   1341:  */
                   1342: void
1.228     gwr      1343: cpu_dumpconf()
1.116     gwr      1344: {
1.291     thorpej  1345:        int nblks, dumpblks;    /* size of dump area */
1.116     gwr      1346:        int maj;
                   1347:
                   1348:        if (dumpdev == NODEV)
1.291     thorpej  1349:                goto bad;
1.116     gwr      1350:        maj = major(dumpdev);
                   1351:        if (maj < 0 || maj >= nblkdev)
                   1352:                panic("dumpconf: bad dumpdev=0x%x", dumpdev);
1.134     mycroft  1353:        if (bdevsw[maj].d_psize == NULL)
1.291     thorpej  1354:                goto bad;
1.134     mycroft  1355:        nblks = (*bdevsw[maj].d_psize)(dumpdev);
1.116     gwr      1356:        if (nblks <= ctod(1))
1.291     thorpej  1357:                goto bad;
1.116     gwr      1358:
1.291     thorpej  1359:        dumpblks = cpu_dumpsize();
                   1360:        if (dumpblks < 0)
                   1361:                goto bad;
                   1362:        dumpblks += ctod(cpu_dump_mempagecnt());
                   1363:
                   1364:        /* If dump won't fit (incl. room for possible label), punt. */
                   1365:        if (dumpblks > (nblks - ctod(1)))
                   1366:                goto bad;
                   1367:
                   1368:        /* Put dump at end of partition */
                   1369:        dumplo = nblks - dumpblks;
                   1370:
                   1371:        /* dumpsize is in page units, and doesn't include headers. */
                   1372:        dumpsize = cpu_dump_mempagecnt();
                   1373:        return;
1.116     gwr      1374:
1.291     thorpej  1375:  bad:
                   1376:        dumpsize = 0;
1.116     gwr      1377: }
                   1378:
1.1       cgd      1379: /*
                   1380:  * Doadump comes here after turning off memory management and
                   1381:  * getting on the dump stack, either when called above, or by
                   1382:  * the auto-restart code.
                   1383:  */
1.163     cgd      1384: #define BYTES_PER_DUMP  NBPG   /* must be a multiple of pagesize XXX small */
1.314     thorpej  1385: static vaddr_t dumpspace;
1.163     cgd      1386:
1.314     thorpej  1387: vaddr_t
1.163     cgd      1388: reserve_dumppages(p)
1.314     thorpej  1389:        vaddr_t p;
1.163     cgd      1390: {
                   1391:
                   1392:        dumpspace = p;
                   1393:        return (p + BYTES_PER_DUMP);
                   1394: }
                   1395:
1.32      andrew   1396: void
1.1       cgd      1397: dumpsys()
                   1398: {
1.291     thorpej  1399:        u_long totalbytesleft, bytes, i, n, memseg;
                   1400:        u_long maddr;
                   1401:        int psize;
1.163     cgd      1402:        daddr_t blkno;
                   1403:        int (*dump) __P((dev_t, daddr_t, caddr_t, size_t));
1.200     christos 1404:        int error;
1.193     mycroft  1405:
                   1406:        /* Save registers. */
                   1407:        savectx(&dumppcb);
1.1       cgd      1408:
1.293     thorpej  1409:        msgbufenabled = 0;      /* don't record dump msgs in msgbuf */
1.1       cgd      1410:        if (dumpdev == NODEV)
                   1411:                return;
1.163     cgd      1412:
                   1413:        /*
                   1414:         * For dumps during autoconfiguration,
                   1415:         * if dump device has already configured...
                   1416:         */
                   1417:        if (dumpsize == 0)
1.228     gwr      1418:                cpu_dumpconf();
1.330     jtk      1419:        if (dumplo <= 0 || dumpsize == 0) {
1.275     mycroft  1420:                printf("\ndump to dev %u,%u not possible\n", major(dumpdev),
                   1421:                    minor(dumpdev));
1.163     cgd      1422:                return;
1.275     mycroft  1423:        }
                   1424:        printf("\ndumping to dev %u,%u offset %ld\n", major(dumpdev),
                   1425:            minor(dumpdev), dumplo);
1.134     mycroft  1426:
1.163     cgd      1427:        psize = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
1.210     christos 1428:        printf("dump ");
1.163     cgd      1429:        if (psize == -1) {
1.210     christos 1430:                printf("area unavailable\n");
1.163     cgd      1431:                return;
                   1432:        }
                   1433:
                   1434: #if 0  /* XXX this doesn't work.  grr. */
                   1435:         /* toss any characters present prior to dump */
                   1436:        while (sget() != NULL); /*syscons and pccons differ */
                   1437: #endif
                   1438:
1.291     thorpej  1439:        if ((error = cpu_dump()) != 0)
                   1440:                goto err;
                   1441:
                   1442:        totalbytesleft = ptoa(cpu_dump_mempagecnt());
                   1443:        blkno = dumplo + cpu_dumpsize();
1.163     cgd      1444:        dump = bdevsw[major(dumpdev)].d_dump;
1.200     christos 1445:        error = 0;
1.291     thorpej  1446:
                   1447:        for (memseg = 0; memseg < mem_cluster_cnt; memseg++) {
                   1448:                maddr = mem_clusters[memseg].start;
                   1449:                bytes = mem_clusters[memseg].size;
                   1450:
                   1451:                for (i = 0; i < bytes; i += n, totalbytesleft -= n) {
                   1452:                        /* Print out how many MBs we have left to go. */
                   1453:                        if ((totalbytesleft % (1024*1024)) == 0)
                   1454:                                printf("%ld ", totalbytesleft / (1024 * 1024));
                   1455:
                   1456:                        /* Limit size for next transfer. */
                   1457:                        n = bytes - i;
                   1458:                        if (n > BYTES_PER_DUMP)
                   1459:                                n = BYTES_PER_DUMP;
                   1460:
                   1461:                        (void) pmap_map(dumpspace, maddr, maddr + n,
                   1462:                            VM_PROT_READ);
                   1463:
                   1464:                        error = (*dump)(dumpdev, blkno, (caddr_t)dumpspace, n);
                   1465:                        if (error)
                   1466:                                goto err;
1.163     cgd      1467:                        maddr += n;
1.291     thorpej  1468:                        blkno += btodb(n);              /* XXX? */
1.163     cgd      1469:
                   1470: #if 0  /* XXX this doesn't work.  grr. */
1.291     thorpej  1471:                        /* operator aborting dump? */
                   1472:                        if (sget() != NULL) {
                   1473:                                error = EINTR;
                   1474:                                break;
                   1475:                        }
                   1476: #endif
1.163     cgd      1477:                }
                   1478:        }
                   1479:
1.291     thorpej  1480:  err:
1.163     cgd      1481:        switch (error) {
1.1       cgd      1482:
                   1483:        case ENXIO:
1.210     christos 1484:                printf("device bad\n");
1.1       cgd      1485:                break;
                   1486:
                   1487:        case EFAULT:
1.210     christos 1488:                printf("device not ready\n");
1.1       cgd      1489:                break;
                   1490:
                   1491:        case EINVAL:
1.210     christos 1492:                printf("area improper\n");
1.1       cgd      1493:                break;
                   1494:
                   1495:        case EIO:
1.210     christos 1496:                printf("i/o error\n");
1.1       cgd      1497:                break;
                   1498:
                   1499:        case EINTR:
1.210     christos 1500:                printf("aborted from console\n");
1.1       cgd      1501:                break;
                   1502:
1.163     cgd      1503:        case 0:
1.210     christos 1504:                printf("succeeded\n");
1.163     cgd      1505:                break;
                   1506:
1.1       cgd      1507:        default:
1.210     christos 1508:                printf("error %d\n", error);
1.1       cgd      1509:                break;
                   1510:        }
1.210     christos 1511:        printf("\n\n");
1.163     cgd      1512:        delay(5000000);         /* 5 seconds */
1.1       cgd      1513: }
                   1514:
                   1515: /*
                   1516:  * Clear registers on exec
                   1517:  */
1.33      cgd      1518: void
1.251     mycroft  1519: setregs(p, pack, stack)
1.1       cgd      1520:        struct proc *p;
1.151     christos 1521:        struct exec_package *pack;
1.21      cgd      1522:        u_long stack;
1.1       cgd      1523: {
1.298     mycroft  1524:        struct pcb *pcb = &p->p_addr->u_pcb;
                   1525:        struct trapframe *tf;
1.1       cgd      1526:
1.161     mycroft  1527: #if NNPX > 0
                   1528:        /* If we were using the FPU, forget about it. */
                   1529:        if (npxproc == p)
1.166     mycroft  1530:                npxdrop();
1.161     mycroft  1531: #endif
1.166     mycroft  1532:
1.178     mycroft  1533: #ifdef USER_LDT
1.353     thorpej  1534:        pmap_ldt_cleanup(p);
1.178     mycroft  1535: #endif
                   1536:
1.167     mycroft  1537:        p->p_md.md_flags &= ~MDP_USEDFPU;
1.178     mycroft  1538:        pcb->pcb_flags = 0;
1.276     mycroft  1539:        pcb->pcb_savefpu.sv_env.en_cw = __NetBSD_NPXCW__;
1.59      mycroft  1540:
1.154     mycroft  1541:        tf = p->p_md.md_regs;
1.178     mycroft  1542:        __asm("movl %w0,%%gs" : : "r" (LSEL(LUDATA_SEL, SEL_UPL)));
                   1543:        __asm("movl %w0,%%fs" : : "r" (LSEL(LUDATA_SEL, SEL_UPL)));
1.154     mycroft  1544:        tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
                   1545:        tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
1.252     mycroft  1546:        tf->tf_edi = 0;
                   1547:        tf->tf_esi = 0;
1.154     mycroft  1548:        tf->tf_ebp = 0;
1.160     mycroft  1549:        tf->tf_ebx = (int)PS_STRINGS;
1.252     mycroft  1550:        tf->tf_edx = 0;
                   1551:        tf->tf_ecx = 0;
                   1552:        tf->tf_eax = 0;
1.154     mycroft  1553:        tf->tf_eip = pack->ep_entry;
                   1554:        tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
                   1555:        tf->tf_eflags = PSL_USERSET;
                   1556:        tf->tf_esp = stack;
                   1557:        tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
1.1       cgd      1558: }
                   1559:
                   1560: /*
1.55      brezak   1561:  * Initialize segments and descriptor tables
1.1       cgd      1562:  */
                   1563:
1.275     mycroft  1564: union  descriptor *idt, *gdt, *ldt;
                   1565: #ifdef I586_CPU
                   1566: union  descriptor *pentium_idt;
                   1567: #endif
1.178     mycroft  1568: extern  struct user *proc0paddr;
1.49      brezak   1569:
1.178     mycroft  1570: void
                   1571: setgate(gd, func, args, type, dpl)
                   1572:        struct gate_descriptor *gd;
                   1573:        void *func;
                   1574:        int args, type, dpl;
                   1575: {
1.1       cgd      1576:
1.178     mycroft  1577:        gd->gd_looffset = (int)func;
                   1578:        gd->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
                   1579:        gd->gd_stkcpy = args;
                   1580:        gd->gd_xx = 0;
                   1581:        gd->gd_type = type;
                   1582:        gd->gd_dpl = dpl;
                   1583:        gd->gd_p = 1;
                   1584:        gd->gd_hioffset = (int)func >> 16;
                   1585: }
                   1586:
                   1587: void
                   1588: setregion(rd, base, limit)
                   1589:        struct region_descriptor *rd;
                   1590:        void *base;
                   1591:        size_t limit;
                   1592: {
                   1593:
                   1594:        rd->rd_limit = (int)limit;
                   1595:        rd->rd_base = (int)base;
                   1596: }
1.1       cgd      1597:
1.174     mycroft  1598: void
                   1599: setsegment(sd, base, limit, type, dpl, def32, gran)
                   1600:        struct segment_descriptor *sd;
                   1601:        void *base;
                   1602:        size_t limit;
                   1603:        int type, dpl, def32, gran;
                   1604: {
1.1       cgd      1605:
1.174     mycroft  1606:        sd->sd_lolimit = (int)limit;
                   1607:        sd->sd_lobase = (int)base;
                   1608:        sd->sd_type = type;
                   1609:        sd->sd_dpl = dpl;
                   1610:        sd->sd_p = 1;
                   1611:        sd->sd_hilimit = (int)limit >> 16;
                   1612:        sd->sd_xx = 0;
                   1613:        sd->sd_def32 = def32;
                   1614:        sd->sd_gran = gran;
                   1615:        sd->sd_hibase = (int)base >> 24;
                   1616: }
1.1       cgd      1617:
                   1618: #define        IDTVEC(name)    __CONCAT(X, name)
1.299     mycroft  1619: typedef void (vector) __P((void));
                   1620: extern vector IDTVEC(syscall);
                   1621: extern vector IDTVEC(osyscall);
                   1622: extern vector *IDTVEC(exceptions)[];
1.333     christos 1623: #ifdef COMPAT_SVR4
                   1624: extern vector IDTVEC(svr4_fasttrap);
                   1625: #endif /* COMPAT_SVR4 */
1.1       cgd      1626:
1.59      mycroft  1627: void
1.43      brezak   1628: init386(first_avail)
1.314     thorpej  1629:        vaddr_t first_avail;
1.2       cgd      1630: {
1.132     mycroft  1631:        int x;
1.148     mycroft  1632:        struct region_descriptor region;
                   1633:        extern void consinit __P((void));
1.1       cgd      1634:
                   1635:        proc0.p_addr = proc0paddr;
1.284     mrg      1636:        curpcb = &proc0.p_addr->u_pcb;
1.275     mycroft  1637:
1.204     thorpej  1638:        /*
1.205     thorpej  1639:         * Initialize the I/O port and I/O mem extent maps.
                   1640:         * Note: we don't have to check the return value since
                   1641:         * creation of a fixed extent map will never fail (since
                   1642:         * descriptor storage has already been allocated).
1.213     thorpej  1643:         *
                   1644:         * N.B. The iomem extent manages _all_ physical addresses
                   1645:         * on the machine.  When the amount of RAM is found, the two
                   1646:         * extents of RAM are allocated from the map (0 -> ISA hole
                   1647:         * and end of ISA hole -> end of RAM).
1.204     thorpej  1648:         */
                   1649:        ioport_ex = extent_create("ioport", 0x0, 0xffff, M_DEVBUF,
1.212     fvdl     1650:            (caddr_t)ioport_ex_storage, sizeof(ioport_ex_storage),
1.211     thorpej  1651:            EX_NOCOALESCE|EX_NOWAIT);
1.213     thorpej  1652:        iomem_ex = extent_create("iomem", 0x0, 0xffffffff, M_DEVBUF,
1.212     fvdl     1653:            (caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
1.211     thorpej  1654:            EX_NOCOALESCE|EX_NOWAIT);
1.204     thorpej  1655:
1.84      cgd      1656:        consinit();     /* XXX SHOULD NOT BE DONE HERE */
1.1       cgd      1657:
1.213     thorpej  1658:        /*
                   1659:         * Allocate the physical addresses used by RAM from the iomem
                   1660:         * extent map.  This is done before the addresses are
                   1661:         * page rounded just to make sure we get them all.
                   1662:         */
1.275     mycroft  1663:        if (extent_alloc_region(iomem_ex, 0, biosbasemem * 1024, EX_NOWAIT)) {
1.213     thorpej  1664:                /* XXX What should we do? */
1.263     mycroft  1665:                printf("WARNING: CAN'T ALLOCATE BASE MEMORY FROM IOMEM EXTENT MAP!\n");
1.213     thorpej  1666:        }
1.275     mycroft  1667:        if (extent_alloc_region(iomem_ex, IOM_END, biosextmem * 1024,
                   1668:            EX_NOWAIT)) {
1.213     thorpej  1669:                /* XXX What should we do? */
                   1670:                printf("WARNING: CAN'T ALLOCATE EXTENDED MEMORY FROM IOMEM EXTENT MAP!\n");
                   1671:        }
                   1672:
1.231     thorpej  1673: #if NISADMA > 0
                   1674:        /*
                   1675:         * Some motherboards/BIOSes remap the 384K of RAM that would
                   1676:         * normally be covered by the ISA hole to the end of memory
                   1677:         * so that it can be used.  However, on a 16M system, this
                   1678:         * would cause bounce buffers to be allocated and used.
                   1679:         * This is not desirable behaviour, as more than 384K of
                   1680:         * bounce buffers might be allocated.  As a work-around,
                   1681:         * we round memory down to the nearest 1M boundary if
                   1682:         * we're using any isadma devices and the remapped memory
                   1683:         * is what puts us over 16M.
                   1684:         */
                   1685:        if (biosextmem > (15*1024) && biosextmem < (16*1024)) {
1.354     lukem    1686:                char pbuf[9];
                   1687:
                   1688:                format_bytes(pbuf, sizeof(pbuf), biosextmem - (15*1024));
                   1689:                printf("Warning: ignoring %s of remapped memory\n", pbuf);
1.231     thorpej  1690:                biosextmem = (15*1024);
                   1691:        }
                   1692: #endif
                   1693:
1.258     jtk      1694: #if NBIOSCALL > 0
1.295     drochner 1695:        avail_start = 3*NBPG;   /* save us a page for trampoline code and
                   1696:                                 one additional PT page! */
1.207     jtk      1697: #else
1.59      mycroft  1698:        avail_start = NBPG;     /* BIOS leaves data in low memory */
1.43      brezak   1699:                                /* and VM system doesn't work with phys 0 */
1.207     jtk      1700: #endif
1.275     mycroft  1701:        avail_end = IOM_END + trunc_page(biosextmem * 1024);
1.73      mycroft  1702:
1.275     mycroft  1703:        hole_start = trunc_page(biosbasemem * 1024);
                   1704:        /* we load right after the I/O hole; adjust hole_end to compensate */
                   1705:        hole_end = round_page(first_avail);
                   1706:
                   1707:        /* Call pmap initialization to make new kernel address space. */
1.314     thorpej  1708:        pmap_bootstrap((vaddr_t)atdevbase + IOM_SIZE);
1.2       cgd      1709:
1.295     drochner 1710: #if NBIOSCALL > 0
                   1711:        /* install page 2 (reserved above) as PT page for first 4M */
1.346     mycroft  1712:        pmap_enter(pmap_kernel(), (u_long)vtopte(0), 2*NBPG,
                   1713:            VM_PROT_READ|VM_PROT_WRITE, TRUE, VM_PROT_READ|VM_PROT_WRITE);
1.313     perry    1714:        memset(vtopte(0), 0, NBPG);  /* make sure it is clean before using */
1.295     drochner 1715: #endif
1.59      mycroft  1716:
1.346     mycroft  1717:        pmap_enter(pmap_kernel(), idt_vaddr, idt_paddr,
                   1718:            VM_PROT_READ|VM_PROT_WRITE, TRUE, VM_PROT_READ|VM_PROT_WRITE);
1.275     mycroft  1719:        idt = (union descriptor *)idt_vaddr;
                   1720: #ifdef I586_CPU
1.346     mycroft  1721:        pmap_enter(pmap_kernel(), pentium_idt_vaddr, idt_paddr,
                   1722:            VM_PROT_READ, TRUE, VM_PROT_READ);
1.275     mycroft  1723:        pentium_idt = (union descriptor *)pentium_idt_vaddr;
                   1724: #endif
                   1725:        gdt = idt + NIDT;
                   1726:        ldt = gdt + NGDT;
                   1727:
                   1728:
                   1729:        /* make gdt gates and memory segments */
                   1730:        setsegment(&gdt[GCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1);
                   1731:        setsegment(&gdt[GDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1);
                   1732:        setsegment(&gdt[GLDT_SEL].sd, ldt, NLDT * sizeof(ldt[0]) - 1,
                   1733:            SDT_SYSLDT, SEL_KPL, 0, 0);
                   1734:        setsegment(&gdt[GUCODE_SEL].sd, 0, i386_btop(VM_MAXUSER_ADDRESS) - 1,
                   1735:            SDT_MEMERA, SEL_UPL, 1, 1);
                   1736:        setsegment(&gdt[GUDATA_SEL].sd, 0, i386_btop(VM_MAXUSER_ADDRESS) - 1,
                   1737:            SDT_MEMRWA, SEL_UPL, 1, 1);
                   1738: #if NBIOSCALL > 0
                   1739:        /* bios trampoline GDT entries */
                   1740:        setsegment(&gdt[GBIOSCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 0,
                   1741:            0);
                   1742:        setsegment(&gdt[GBIOSDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 0,
                   1743:            0);
                   1744: #endif
                   1745:
                   1746:        /* make ldt gates and memory segments */
                   1747:        setgate(&ldt[LSYS5CALLS_SEL].gd, &IDTVEC(osyscall), 1,
                   1748:            SDT_SYS386CGT, SEL_UPL);
                   1749:        ldt[LUCODE_SEL] = gdt[GUCODE_SEL];
                   1750:        ldt[LUDATA_SEL] = gdt[GUDATA_SEL];
1.324     christos 1751:        ldt[LSOL26CALLS_SEL] = ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
1.275     mycroft  1752:
                   1753:        /* exceptions */
                   1754:        for (x = 0; x < 32; x++)
                   1755:                setgate(&idt[x].gd, IDTVEC(exceptions)[x], 0, SDT_SYS386TGT,
                   1756:                    (x == 3 || x == 4) ? SEL_UPL : SEL_KPL);
1.257     thorpej  1757:
1.275     mycroft  1758:        /* new-style interrupt gate for syscalls */
                   1759:        setgate(&idt[128].gd, &IDTVEC(syscall), 0, SDT_SYS386TGT, SEL_UPL);
1.333     christos 1760: #ifdef COMPAT_SVR4
                   1761:        setgate(&idt[0xd2].gd, &IDTVEC(svr4_fasttrap), 0, SDT_SYS386TGT,
                   1762:            SEL_UPL);
                   1763: #endif /* COMPAT_SVR4 */
1.264     mycroft  1764:
1.275     mycroft  1765:        setregion(&region, gdt, NGDT * sizeof(gdt[0]) - 1);
                   1766:        lgdt(&region);
1.264     mycroft  1767: #ifdef I586_CPU
1.275     mycroft  1768:        setregion(&region, pentium_idt, NIDT * sizeof(idt[0]) - 1);
                   1769: #else
                   1770:        setregion(&region, idt, NIDT * sizeof(idt[0]) - 1);
                   1771: #endif
                   1772:        lidt(&region);
1.264     mycroft  1773:
1.190     mycroft  1774:
                   1775: #ifdef DDB
1.308     tv       1776:        {
                   1777:                extern int end;
                   1778:                extern int *esym;
1.336     christos 1779:                struct btinfo_symtab *symtab;
1.308     tv       1780:
1.336     christos 1781:                symtab = lookup_bootinfo(BTINFO_SYMTAB);
                   1782:                if (symtab) {
                   1783:                        symtab->ssym += KERNBASE;
                   1784:                        symtab->esym += KERNBASE;
                   1785:                        ddb_init(symtab->nsym, (int *)symtab->ssym,
                   1786:                            (int *)symtab->esym);
                   1787:                }
                   1788:                else
                   1789:                        ddb_init(*(int *)&end, ((int *)&end) + 1, esym);
1.308     tv       1790:        }
1.190     mycroft  1791:        if (boothowto & RB_KDB)
                   1792:                Debugger();
                   1793: #endif
                   1794: #ifdef KGDB
1.243     drochner 1795:        kgdb_port_init();
1.235     thorpej  1796:        if (boothowto & RB_KDB) {
                   1797:                kgdb_debug_init = 1;
1.242     drochner 1798:                kgdb_connect(1);
1.235     thorpej  1799:        }
1.190     mycroft  1800: #endif
1.275     mycroft  1801:
                   1802: #if NISA > 0
                   1803:        isa_defaultirq();
                   1804: #endif
                   1805:
                   1806:        splraise(-1);
                   1807:        enable_intr();
                   1808:
                   1809:        /* number of pages of physmem addr space */
                   1810:        physmem = btoc(biosbasemem * 1024) + btoc(biosextmem * 1024);
1.291     thorpej  1811:
                   1812:        mem_clusters[0].start = 0;
                   1813:        mem_clusters[0].size  = trunc_page(biosbasemem * 1024);
                   1814:
                   1815:        mem_clusters[1].start = IOM_END;
                   1816:        mem_clusters[1].size  = trunc_page(biosextmem * 1024);
                   1817:
                   1818:        mem_cluster_cnt = 2;
1.275     mycroft  1819:
                   1820:        if (physmem < btoc(2 * 1024 * 1024)) {
                   1821:                printf("warning: too little memory available; "
                   1822:                       "have %d bytes, want %d bytes\n"
                   1823:                       "running in degraded mode\n"
                   1824:                       "press a key to confirm\n\n",
                   1825:                       ctob(physmem), 2*1024*1024);
                   1826:                cngetc();
                   1827:        }
1.1       cgd      1828: }
                   1829:
1.94      mycroft  1830: struct queue {
                   1831:        struct queue *q_next, *q_prev;
                   1832: };
                   1833:
1.1       cgd      1834: /*
1.73      mycroft  1835:  * insert an element into a queue
1.1       cgd      1836:  */
1.94      mycroft  1837: void
1.188     christos 1838: _insque(v1, v2)
                   1839:        void *v1;
                   1840:        void *v2;
1.94      mycroft  1841: {
1.298     mycroft  1842:        struct queue *elem = v1, *head = v2;
                   1843:        struct queue *next;
1.94      mycroft  1844:
                   1845:        next = head->q_next;
                   1846:        elem->q_next = next;
                   1847:        head->q_next = elem;
                   1848:        elem->q_prev = head;
                   1849:        next->q_prev = elem;
1.1       cgd      1850: }
                   1851:
                   1852: /*
                   1853:  * remove an element from a queue
                   1854:  */
1.94      mycroft  1855: void
1.188     christos 1856: _remque(v)
                   1857:        void *v;
1.94      mycroft  1858: {
1.298     mycroft  1859:        struct queue *elem = v;
                   1860:        struct queue *next, *prev;
1.94      mycroft  1861:
                   1862:        next = elem->q_next;
                   1863:        prev = elem->q_prev;
                   1864:        next->q_prev = prev;
                   1865:        prev->q_next = next;
                   1866:        elem->q_prev = 0;
1.1       cgd      1867: }
                   1868:
1.107     deraadt  1869: #ifdef COMPAT_NOMID
                   1870: static int
                   1871: exec_nomid(p, epp)
1.59      mycroft  1872:        struct proc *p;
                   1873:        struct exec_package *epp;
1.31      cgd      1874: {
1.59      mycroft  1875:        int error;
                   1876:        u_long midmag, magic;
                   1877:        u_short mid;
1.80      cgd      1878:        struct exec *execp = epp->ep_hdr;
1.31      cgd      1879:
1.80      cgd      1880:        /* check on validity of epp->ep_hdr performed by exec_out_makecmds */
                   1881:
                   1882:        midmag = ntohl(execp->a_midmag);
1.59      mycroft  1883:        mid = (midmag >> 16) & 0xffff;
                   1884:        magic = midmag & 0xffff;
                   1885:
                   1886:        if (magic == 0) {
1.80      cgd      1887:                magic = (execp->a_midmag & 0xffff);
1.59      mycroft  1888:                mid = MID_ZERO;
                   1889:        }
                   1890:
                   1891:        midmag = mid << 16 | magic;
                   1892:
                   1893:        switch (midmag) {
                   1894:        case (MID_ZERO << 16) | ZMAGIC:
                   1895:                /*
                   1896:                 * 386BSD's ZMAGIC format:
                   1897:                 */
1.202     christos 1898:                error = exec_aout_prep_oldzmagic(p, epp);
1.59      mycroft  1899:                break;
                   1900:
                   1901:        case (MID_ZERO << 16) | QMAGIC:
                   1902:                /*
                   1903:                 * BSDI's QMAGIC format:
                   1904:                 * same as new ZMAGIC format, but with different magic number
                   1905:                 */
                   1906:                error = exec_aout_prep_zmagic(p, epp);
                   1907:                break;
                   1908:
1.202     christos 1909:        case (MID_ZERO << 16) | NMAGIC:
                   1910:                /*
                   1911:                 * BSDI's NMAGIC format:
                   1912:                 * same as NMAGIC format, but with different magic number
                   1913:                 * and with text starting at 0.
                   1914:                 */
                   1915:                error = exec_aout_prep_oldnmagic(p, epp);
                   1916:                break;
                   1917:
                   1918:        case (MID_ZERO << 16) | OMAGIC:
                   1919:                /*
                   1920:                 * BSDI's OMAGIC format:
                   1921:                 * same as OMAGIC format, but with different magic number
                   1922:                 * and with text starting at 0.
                   1923:                 */
                   1924:                error = exec_aout_prep_oldomagic(p, epp);
                   1925:                break;
                   1926:
1.59      mycroft  1927:        default:
                   1928:                error = ENOEXEC;
                   1929:        }
                   1930:
                   1931:        return error;
1.107     deraadt  1932: }
1.31      cgd      1933: #endif
1.107     deraadt  1934:
                   1935: /*
                   1936:  * cpu_exec_aout_makecmds():
                   1937:  *     cpu-dependent a.out format hook for execve().
                   1938:  *
                   1939:  * Determine of the given exec package refers to something which we
                   1940:  * understand and, if so, set up the vmcmds for it.
                   1941:  *
                   1942:  * On the i386, old (386bsd) ZMAGIC binaries and BSDI QMAGIC binaries
                   1943:  * if COMPAT_NOMID is given as a kernel option.
                   1944:  */
                   1945: int
                   1946: cpu_exec_aout_makecmds(p, epp)
                   1947:        struct proc *p;
                   1948:        struct exec_package *epp;
                   1949: {
                   1950:        int error = ENOEXEC;
                   1951:
                   1952: #ifdef COMPAT_NOMID
                   1953:        if ((error = exec_nomid(p, epp)) == 0)
                   1954:                return error;
                   1955: #endif /* ! COMPAT_NOMID */
                   1956:
                   1957:        return error;
1.31      cgd      1958: }
1.84      cgd      1959:
1.255     drochner 1960: void *
                   1961: lookup_bootinfo(type)
                   1962: int type;
                   1963: {
                   1964:        struct btinfo_common *help;
                   1965:        int n = *(int*)bootinfo;
                   1966:        help = (struct btinfo_common *)(bootinfo + sizeof(int));
                   1967:        while(n--) {
                   1968:                if(help->type == type)
                   1969:                        return(help);
                   1970:                help = (struct btinfo_common *)((char*)help + help->len);
                   1971:        }
                   1972:        return(0);
                   1973: }
                   1974:
1.84      cgd      1975: /*
                   1976:  * consinit:
                   1977:  * initialize the system console.
1.94      mycroft  1978:  * XXX - shouldn't deal with this initted thing, but then,
1.84      cgd      1979:  * it shouldn't be called from init386 either.
                   1980:  */
                   1981: void
                   1982: consinit()
                   1983: {
1.255     drochner 1984:        struct btinfo_console *consinfo;
1.94      mycroft  1985:        static int initted;
                   1986:
                   1987:        if (initted)
                   1988:                return;
                   1989:        initted = 1;
1.243     drochner 1990:
1.255     drochner 1991: #ifndef CONS_OVERRIDE
                   1992:        consinfo = lookup_bootinfo(BTINFO_CONSOLE);
1.296     drochner 1993:        if (!consinfo)
1.255     drochner 1994: #endif
                   1995:                consinfo = &default_consinfo;
                   1996:
1.303     drochner 1997: #if (NPC > 0) || (NVT > 0) || (NVGA > 0) || (NPCDISPLAY > 0)
1.296     drochner 1998:        if (!strcmp(consinfo->devname, "pc")) {
                   1999: #if (NVGA > 0)
                   2000:                if (!vga_cnattach(I386_BUS_SPACE_IO, I386_BUS_SPACE_MEM,
                   2001:                                  -1, 1))
                   2002:                        goto dokbd;
                   2003: #endif
1.303     drochner 2004: #if (NPCDISPLAY > 0)
                   2005:                if (!pcdisplay_cnattach(I386_BUS_SPACE_IO, I386_BUS_SPACE_MEM))
                   2006:                        goto dokbd;
                   2007: #endif
1.243     drochner 2008: #if (NPC > 0) || (NVT > 0)
1.245     drochner 2009:                pccnattach();
1.296     drochner 2010: #endif
                   2011:                if (0) goto dokbd; /* XXX stupid gcc */
                   2012: dokbd:
                   2013: #if (NPCKBC > 0)
                   2014:                pckbc_cnattach(I386_BUS_SPACE_IO, PCKBC_KBD_SLOT);
                   2015: #endif
1.243     drochner 2016:                return;
                   2017:        }
1.303     drochner 2018: #endif /* PC | VT | VGA | PCDISPLAY */
1.243     drochner 2019: #if (NCOM > 0)
1.296     drochner 2020:        if (!strcmp(consinfo->devname, "com")) {
1.245     drochner 2021:                bus_space_tag_t tag = I386_BUS_SPACE_IO;
                   2022:
1.296     drochner 2023:                if (comcnattach(tag, consinfo->addr, consinfo->speed,
                   2024:                                COM_FREQ, comcnmode))
1.255     drochner 2025:                        panic("can't init serial console @%x", consinfo->addr);
1.243     drochner 2026:
                   2027:                return;
                   2028:        }
                   2029: #endif
1.255     drochner 2030:        panic("invalid console device %s", consinfo->devname);
1.243     drochner 2031: }
                   2032:
1.296     drochner 2033: #if (NPCKBC > 0) && (NPCKBD == 0)
                   2034: /*
                   2035:  * glue code to support old console code with the
                   2036:  * mi keyboard controller driver
                   2037:  */
                   2038: int
                   2039: pckbc_machdep_cnattach(kbctag, kbcslot)
                   2040:        pckbc_tag_t kbctag;
                   2041:        pckbc_slot_t kbcslot;
                   2042: {
1.337     drochner 2043: #if (NPC > 0) && (NPCCONSKBD > 0)
1.296     drochner 2044:        return (pcconskbd_cnattach(kbctag, kbcslot));
                   2045: #else
                   2046:        return (ENXIO);
                   2047: #endif
                   2048: }
                   2049: #endif
                   2050:
1.243     drochner 2051: #ifdef KGDB
                   2052: void
                   2053: kgdb_port_init()
                   2054: {
                   2055: #if (NCOM > 0)
1.245     drochner 2056:        if(!strcmp(kgdb_devname, "com")) {
                   2057:                bus_space_tag_t tag = I386_BUS_SPACE_IO;
1.243     drochner 2058:
1.253     is       2059:                com_kgdb_attach(tag, comkgdbaddr, comkgdbrate, COM_FREQ,
                   2060:                    comkgdbmode);
1.243     drochner 2061:        }
                   2062: #endif
1.149     mycroft  2063: }
1.243     drochner 2064: #endif
1.149     mycroft  2065:
                   2066: void
                   2067: cpu_reset()
                   2068: {
                   2069:
1.224     mycroft  2070:        disable_intr();
                   2071:
1.227     mycroft  2072:        /*
                   2073:         * The keyboard controller has 4 random output pins, one of which is
                   2074:         * connected to the RESET pin on the CPU in many PCs.  We tell the
                   2075:         * keyboard controller to pulse this line a couple of times.
                   2076:         */
1.273     drochner 2077:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226     mycroft  2078:        delay(100000);
1.273     drochner 2079:        outb(IO_KBD + KBCMDP, KBC_PULSE0);
1.226     mycroft  2080:        delay(100000);
1.149     mycroft  2081:
                   2082:        /*
1.224     mycroft  2083:         * Try to cause a triple fault and watchdog reset by making the IDT
                   2084:         * invalid and causing a fault.
1.149     mycroft  2085:         */
1.313     perry    2086:        memset((caddr_t)idt, 0, NIDT * sizeof(idt[0]));
1.224     mycroft  2087:        __asm __volatile("divl %0,%1" : : "q" (0), "a" (0));
1.149     mycroft  2088:
1.224     mycroft  2089: #if 0
1.149     mycroft  2090:        /*
                   2091:         * Try to cause a triple fault and watchdog reset by unmapping the
1.224     mycroft  2092:         * entire address space and doing a TLB flush.
1.149     mycroft  2093:         */
1.313     perry    2094:        memset((caddr_t)PTD, 0, NBPG);
1.149     mycroft  2095:        pmap_update();
1.224     mycroft  2096: #endif
1.149     mycroft  2097:
                   2098:        for (;;);
1.194     cgd      2099: }
                   2100:
                   2101: int
1.244     cgd      2102: i386_memio_map(t, bpa, size, flags, bshp)
1.213     thorpej  2103:        bus_space_tag_t t;
                   2104:        bus_addr_t bpa;
                   2105:        bus_size_t size;
1.244     cgd      2106:        int flags;
1.213     thorpej  2107:        bus_space_handle_t *bshp;
1.194     cgd      2108: {
1.213     thorpej  2109:        int error;
                   2110:        struct extent *ex;
                   2111:
                   2112:        /*
                   2113:         * Pick the appropriate extent map.
                   2114:         */
1.244     cgd      2115:        if (t == I386_BUS_SPACE_IO) {
                   2116:                if (flags & BUS_SPACE_MAP_LINEAR)
                   2117:                        return (EOPNOTSUPP);
1.213     thorpej  2118:                ex = ioport_ex;
1.244     cgd      2119:        } else if (t == I386_BUS_SPACE_MEM)
1.213     thorpej  2120:                ex = iomem_ex;
1.239     cgd      2121:        else
1.237     cgd      2122:                panic("i386_memio_map: bad bus space tag");
1.205     thorpej  2123:
                   2124:        /*
                   2125:         * Before we go any further, let's make sure that this
1.213     thorpej  2126:         * region is available.
                   2127:         */
                   2128:        error = extent_alloc_region(ex, bpa, size,
                   2129:            EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
                   2130:        if (error)
                   2131:                return (error);
                   2132:
                   2133:        /*
                   2134:         * For I/O space, that's all she wrote.
                   2135:         */
                   2136:        if (t == I386_BUS_SPACE_IO) {
                   2137:                *bshp = bpa;
                   2138:                return (0);
                   2139:        }
                   2140:
1.296     drochner 2141:        if (bpa >= IOM_BEGIN && (bpa + size) <= IOM_END) {
                   2142:                *bshp = (bus_space_handle_t)ISA_HOLE_VADDR(bpa);
                   2143:                return(0);
                   2144:        }
                   2145:
1.213     thorpej  2146:        /*
                   2147:         * For memory space, map the bus physical address to
                   2148:         * a kernel virtual address.
                   2149:         */
1.244     cgd      2150:        error = i386_mem_add_mapping(bpa, size,
                   2151:                (flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
1.213     thorpej  2152:        if (error) {
                   2153:                if (extent_free(ex, bpa, size, EX_NOWAIT |
                   2154:                    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
1.237     cgd      2155:                        printf("i386_memio_map: pa 0x%lx, size 0x%lx\n",
1.213     thorpej  2156:                            bpa, size);
1.237     cgd      2157:                        printf("i386_memio_map: can't free region\n");
1.213     thorpej  2158:                }
                   2159:        }
                   2160:
                   2161:        return (error);
                   2162: }
                   2163:
                   2164: int
1.244     cgd      2165: _i386_memio_map(t, bpa, size, flags, bshp)
1.237     cgd      2166:        bus_space_tag_t t;
                   2167:        bus_addr_t bpa;
                   2168:        bus_size_t size;
1.244     cgd      2169:        int flags;
1.237     cgd      2170:        bus_space_handle_t *bshp;
                   2171: {
                   2172:
                   2173:        /*
                   2174:         * For I/O space, just fill in the handle.
                   2175:         */
                   2176:        if (t == I386_BUS_SPACE_IO) {
1.244     cgd      2177:                if (flags & BUS_SPACE_MAP_LINEAR)
                   2178:                        return (EOPNOTSUPP);
1.237     cgd      2179:                *bshp = bpa;
                   2180:                return (0);
                   2181:        }
                   2182:
                   2183:        /*
                   2184:         * For memory space, map the bus physical address to
                   2185:         * a kernel virtual address.
                   2186:         */
1.244     cgd      2187:        return (i386_mem_add_mapping(bpa, size,
                   2188:            (flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp));
1.237     cgd      2189: }
                   2190:
                   2191: int
1.244     cgd      2192: i386_memio_alloc(t, rstart, rend, size, alignment, boundary, flags,
1.213     thorpej  2193:     bpap, bshp)
                   2194:        bus_space_tag_t t;
                   2195:        bus_addr_t rstart, rend;
1.214     thorpej  2196:        bus_size_t size, alignment, boundary;
1.244     cgd      2197:        int flags;
1.213     thorpej  2198:        bus_addr_t *bpap;
                   2199:        bus_space_handle_t *bshp;
                   2200: {
                   2201:        struct extent *ex;
                   2202:        u_long bpa;
                   2203:        int error;
                   2204:
                   2205:        /*
                   2206:         * Pick the appropriate extent map.
                   2207:         */
1.244     cgd      2208:        if (t == I386_BUS_SPACE_IO) {
                   2209:                if (flags & BUS_SPACE_MAP_LINEAR)
                   2210:                        return (EOPNOTSUPP);
1.213     thorpej  2211:                ex = ioport_ex;
1.244     cgd      2212:        } else if (t == I386_BUS_SPACE_MEM)
1.213     thorpej  2213:                ex = iomem_ex;
1.239     cgd      2214:        else
1.237     cgd      2215:                panic("i386_memio_alloc: bad bus space tag");
1.213     thorpej  2216:
                   2217:        /*
                   2218:         * Sanity check the allocation against the extent's boundaries.
                   2219:         */
                   2220:        if (rstart < ex->ex_start || rend > ex->ex_end)
1.237     cgd      2221:                panic("i386_memio_alloc: bad region start/end");
1.213     thorpej  2222:
                   2223:        /*
                   2224:         * Do the requested allocation.
                   2225:         */
                   2226:        error = extent_alloc_subregion(ex, rstart, rend, size, alignment,
1.286     cgd      2227:            boundary,
                   2228:            EX_FAST | EX_NOWAIT | (ioport_malloc_safe ?  EX_MALLOCOK : 0),
                   2229:            &bpa);
1.213     thorpej  2230:
                   2231:        if (error)
                   2232:                return (error);
                   2233:
                   2234:        /*
                   2235:         * For I/O space, that's all she wrote.
                   2236:         */
                   2237:        if (t == I386_BUS_SPACE_IO) {
                   2238:                *bshp = *bpap = bpa;
                   2239:                return (0);
                   2240:        }
                   2241:
                   2242:        /*
                   2243:         * For memory space, map the bus physical address to
                   2244:         * a kernel virtual address.
                   2245:         */
1.244     cgd      2246:        error = i386_mem_add_mapping(bpa, size,
                   2247:            (flags & BUS_SPACE_MAP_CACHEABLE) != 0, bshp);
1.213     thorpej  2248:        if (error) {
                   2249:                if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
                   2250:                    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
1.237     cgd      2251:                        printf("i386_memio_alloc: pa 0x%lx, size 0x%lx\n",
1.213     thorpej  2252:                            bpa, size);
1.237     cgd      2253:                        printf("i386_memio_alloc: can't free region\n");
1.213     thorpej  2254:                }
1.205     thorpej  2255:        }
1.194     cgd      2256:
1.213     thorpej  2257:        *bpap = bpa;
                   2258:
                   2259:        return (error);
                   2260: }
                   2261:
                   2262: int
1.237     cgd      2263: i386_mem_add_mapping(bpa, size, cacheable, bshp)
1.213     thorpej  2264:        bus_addr_t bpa;
                   2265:        bus_size_t size;
                   2266:        int cacheable;
                   2267:        bus_space_handle_t *bshp;
                   2268: {
                   2269:        u_long pa, endpa;
1.314     thorpej  2270:        vaddr_t va;
1.283     thorpej  2271:        pt_entry_t *pte;
1.213     thorpej  2272:
1.194     cgd      2273:        pa = i386_trunc_page(bpa);
1.230     perry    2274:        endpa = i386_round_page(bpa + size);
1.201     thorpej  2275:
                   2276: #ifdef DIAGNOSTIC
                   2277:        if (endpa <= pa)
1.237     cgd      2278:                panic("i386_mem_add_mapping: overflow");
1.201     thorpej  2279: #endif
1.194     cgd      2280:
1.284     mrg      2281:        va = uvm_km_valloc(kernel_map, endpa - pa);
1.213     thorpej  2282:        if (va == 0)
                   2283:                return (ENOMEM);
                   2284:
                   2285:        *bshp = (bus_space_handle_t)(va + (bpa & PGOFSET));
1.194     cgd      2286:
                   2287:        for (; pa < endpa; pa += NBPG, va += NBPG) {
1.357     thorpej  2288:                pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE);
1.283     thorpej  2289:
                   2290:                /*
                   2291:                 * PG_N doesn't exist on 386's, so we assume that
                   2292:                 * the mainboard has wired up device space non-cacheable
                   2293:                 * on those machines.
1.248     thorpej  2294:                 */
1.283     thorpej  2295:                if (cpu_class != CPUCLASS_386) {
                   2296:                        pte = kvtopte(va);
                   2297:                        if (cacheable)
                   2298:                                *pte &= ~PG_N;
                   2299:                        else
                   2300:                                *pte |= PG_N;
1.284     mrg      2301:                        pmap_update_pg(va);
1.283     thorpej  2302:                }
1.205     thorpej  2303:        }
1.194     cgd      2304:
1.205     thorpej  2305:        return 0;
1.194     cgd      2306: }
                   2307:
                   2308: void
1.237     cgd      2309: i386_memio_unmap(t, bsh, size)
1.213     thorpej  2310:        bus_space_tag_t t;
                   2311:        bus_space_handle_t bsh;
                   2312:        bus_size_t size;
                   2313: {
                   2314:        struct extent *ex;
                   2315:        u_long va, endva;
                   2316:        bus_addr_t bpa;
                   2317:
                   2318:        /*
                   2319:         * Find the correct extent and bus physical address.
                   2320:         */
1.239     cgd      2321:        if (t == I386_BUS_SPACE_IO) {
1.213     thorpej  2322:                ex = ioport_ex;
                   2323:                bpa = bsh;
1.239     cgd      2324:        } else if (t == I386_BUS_SPACE_MEM) {
1.213     thorpej  2325:                ex = iomem_ex;
1.296     drochner 2326:
                   2327:                if (bsh >= atdevbase &&
                   2328:                    (bsh + size) <= (atdevbase + IOM_SIZE)) {
                   2329:                        bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
                   2330:                        goto ok;
                   2331:                }
                   2332:
1.213     thorpej  2333:                va = i386_trunc_page(bsh);
1.230     perry    2334:                endva = i386_round_page(bsh + size);
1.201     thorpej  2335:
                   2336: #ifdef DIAGNOSTIC
1.213     thorpej  2337:                if (endva <= va)
1.237     cgd      2338:                        panic("i386_memio_unmap: overflow");
1.201     thorpej  2339: #endif
                   2340:
1.360     thorpej  2341:                (void) pmap_extract(pmap_kernel(), va, &bpa);
                   2342:                bpa += (bsh & PGOFSET);
1.213     thorpej  2343:
                   2344:                /*
                   2345:                 * Free the kernel virtual mapping.
                   2346:                 */
1.284     mrg      2347:                uvm_km_free(kernel_map, va, endva - va);
1.239     cgd      2348:        } else
1.237     cgd      2349:                panic("i386_memio_unmap: bad bus space tag");
1.205     thorpej  2350:
1.296     drochner 2351: ok:
1.213     thorpej  2352:        if (extent_free(ex, bpa, size,
                   2353:            EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
1.237     cgd      2354:                printf("i386_memio_unmap: %s 0x%lx, size 0x%lx\n",
1.213     thorpej  2355:                    (t == I386_BUS_SPACE_IO) ? "port" : "pa", bpa, size);
1.237     cgd      2356:                printf("i386_memio_unmap: can't free region\n");
1.213     thorpej  2357:        }
1.204     thorpej  2358: }
                   2359:
1.213     thorpej  2360: void
1.237     cgd      2361: i386_memio_free(t, bsh, size)
1.213     thorpej  2362:        bus_space_tag_t t;
                   2363:        bus_space_handle_t bsh;
                   2364:        bus_size_t size;
1.204     thorpej  2365: {
                   2366:
1.237     cgd      2367:        /* i386_memio_unmap() does all that we need to do. */
                   2368:        i386_memio_unmap(t, bsh, size);
1.204     thorpej  2369: }
                   2370:
1.213     thorpej  2371: int
1.237     cgd      2372: i386_memio_subregion(t, bsh, offset, size, nbshp)
1.213     thorpej  2373:        bus_space_tag_t t;
                   2374:        bus_space_handle_t bsh;
                   2375:        bus_size_t offset, size;
                   2376:        bus_space_handle_t *nbshp;
1.204     thorpej  2377: {
                   2378:
1.213     thorpej  2379:        *nbshp = bsh + offset;
1.231     thorpej  2380:        return (0);
                   2381: }
                   2382:
                   2383: /*
                   2384:  * Common function for DMA map creation.  May be called by bus-specific
                   2385:  * DMA map creation functions.
                   2386:  */
                   2387: int
                   2388: _bus_dmamap_create(t, size, nsegments, maxsegsz, boundary, flags, dmamp)
                   2389:        bus_dma_tag_t t;
                   2390:        bus_size_t size;
                   2391:        int nsegments;
                   2392:        bus_size_t maxsegsz;
                   2393:        bus_size_t boundary;
                   2394:        int flags;
                   2395:        bus_dmamap_t *dmamp;
                   2396: {
                   2397:        struct i386_bus_dmamap *map;
                   2398:        void *mapstore;
                   2399:        size_t mapsize;
                   2400:
                   2401:        /*
                   2402:         * Allocate and initialize the DMA map.  The end of the map
                   2403:         * is a variable-sized array of segments, so we allocate enough
                   2404:         * room for them in one shot.
                   2405:         *
                   2406:         * Note we don't preserve the WAITOK or NOWAIT flags.  Preservation
                   2407:         * of ALLOCNOW notifies others that we've reserved these resources,
                   2408:         * and they are not to be freed.
                   2409:         *
                   2410:         * The bus_dmamap_t includes one bus_dma_segment_t, hence
                   2411:         * the (nsegments - 1).
                   2412:         */
                   2413:        mapsize = sizeof(struct i386_bus_dmamap) +
                   2414:            (sizeof(bus_dma_segment_t) * (nsegments - 1));
1.289     thorpej  2415:        if ((mapstore = malloc(mapsize, M_DMAMAP,
1.231     thorpej  2416:            (flags & BUS_DMA_NOWAIT) ? M_NOWAIT : M_WAITOK)) == NULL)
                   2417:                return (ENOMEM);
                   2418:
1.313     perry    2419:        memset(mapstore, 0, mapsize);
1.231     thorpej  2420:        map = (struct i386_bus_dmamap *)mapstore;
                   2421:        map->_dm_size = size;
                   2422:        map->_dm_segcnt = nsegments;
                   2423:        map->_dm_maxsegsz = maxsegsz;
                   2424:        map->_dm_boundary = boundary;
1.325     thorpej  2425:        map->_dm_bounce_thresh = t->_bounce_thresh;
1.231     thorpej  2426:        map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
1.280     thorpej  2427:        map->dm_mapsize = 0;            /* no valid mappings */
                   2428:        map->dm_nsegs = 0;
1.231     thorpej  2429:
                   2430:        *dmamp = map;
                   2431:        return (0);
                   2432: }
                   2433:
                   2434: /*
                   2435:  * Common function for DMA map destruction.  May be called by bus-specific
                   2436:  * DMA map destruction functions.
                   2437:  */
                   2438: void
                   2439: _bus_dmamap_destroy(t, map)
                   2440:        bus_dma_tag_t t;
                   2441:        bus_dmamap_t map;
                   2442: {
                   2443:
1.289     thorpej  2444:        free(map, M_DMAMAP);
1.231     thorpej  2445: }
                   2446:
                   2447: /*
                   2448:  * Common function for loading a DMA map with a linear buffer.  May
                   2449:  * be called by bus-specific DMA map load functions.
                   2450:  */
                   2451: int
                   2452: _bus_dmamap_load(t, map, buf, buflen, p, flags)
                   2453:        bus_dma_tag_t t;
                   2454:        bus_dmamap_t map;
                   2455:        void *buf;
                   2456:        bus_size_t buflen;
                   2457:        struct proc *p;
                   2458:        int flags;
                   2459: {
1.314     thorpej  2460:        paddr_t lastaddr;
1.277     thorpej  2461:        int seg, error;
1.231     thorpej  2462:
                   2463:        /*
                   2464:         * Make sure that on error condition we return "no valid mappings".
                   2465:         */
1.280     thorpej  2466:        map->dm_mapsize = 0;
1.231     thorpej  2467:        map->dm_nsegs = 0;
                   2468:
1.234     thorpej  2469:        if (buflen > map->_dm_size)
                   2470:                return (EINVAL);
                   2471:
1.277     thorpej  2472:        seg = 0;
1.317     thorpej  2473:        error = _bus_dmamap_load_buffer(t, map, buf, buflen, p, flags,
                   2474:            &lastaddr, &seg, 1);
1.280     thorpej  2475:        if (error == 0) {
                   2476:                map->dm_mapsize = buflen;
1.277     thorpej  2477:                map->dm_nsegs = seg + 1;
1.280     thorpej  2478:        }
1.277     thorpej  2479:        return (error);
1.231     thorpej  2480: }
                   2481:
                   2482: /*
                   2483:  * Like _bus_dmamap_load(), but for mbufs.
                   2484:  */
                   2485: int
1.277     thorpej  2486: _bus_dmamap_load_mbuf(t, map, m0, flags)
1.231     thorpej  2487:        bus_dma_tag_t t;
                   2488:        bus_dmamap_t map;
1.277     thorpej  2489:        struct mbuf *m0;
1.231     thorpej  2490:        int flags;
                   2491: {
1.314     thorpej  2492:        paddr_t lastaddr;
1.277     thorpej  2493:        int seg, error, first;
                   2494:        struct mbuf *m;
                   2495:
                   2496:        /*
                   2497:         * Make sure that on error condition we return "no valid mappings."
                   2498:         */
1.280     thorpej  2499:        map->dm_mapsize = 0;
1.277     thorpej  2500:        map->dm_nsegs = 0;
                   2501:
                   2502: #ifdef DIAGNOSTIC
                   2503:        if ((m0->m_flags & M_PKTHDR) == 0)
                   2504:                panic("_bus_dmamap_load_mbuf: no packet header");
                   2505: #endif
                   2506:
                   2507:        if (m0->m_pkthdr.len > map->_dm_size)
                   2508:                return (EINVAL);
1.231     thorpej  2509:
1.277     thorpej  2510:        first = 1;
                   2511:        seg = 0;
                   2512:        error = 0;
                   2513:        for (m = m0; m != NULL && error == 0; m = m->m_next) {
1.317     thorpej  2514:                error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len,
                   2515:                    NULL, flags, &lastaddr, &seg, first);
1.277     thorpej  2516:                first = 0;
                   2517:        }
1.280     thorpej  2518:        if (error == 0) {
                   2519:                map->dm_mapsize = m0->m_pkthdr.len;
1.277     thorpej  2520:                map->dm_nsegs = seg + 1;
1.280     thorpej  2521:        }
1.277     thorpej  2522:        return (error);
1.231     thorpej  2523: }
                   2524:
                   2525: /*
                   2526:  * Like _bus_dmamap_load(), but for uios.
                   2527:  */
                   2528: int
                   2529: _bus_dmamap_load_uio(t, map, uio, flags)
                   2530:        bus_dma_tag_t t;
                   2531:        bus_dmamap_t map;
                   2532:        struct uio *uio;
                   2533:        int flags;
                   2534: {
1.314     thorpej  2535:        paddr_t lastaddr;
1.312     thorpej  2536:        int seg, i, error, first;
                   2537:        bus_size_t minlen, resid;
                   2538:        struct proc *p = NULL;
                   2539:        struct iovec *iov;
                   2540:        caddr_t addr;
                   2541:
                   2542:        /*
                   2543:         * Make sure that on error condition we return "no valid mappings."
                   2544:         */
                   2545:        map->dm_mapsize = 0;
                   2546:        map->dm_nsegs = 0;
                   2547:
                   2548:        resid = uio->uio_resid;
                   2549:        iov = uio->uio_iov;
                   2550:
                   2551:        if (uio->uio_segflg == UIO_USERSPACE) {
                   2552:                p = uio->uio_procp;
                   2553: #ifdef DIAGNOSTIC
                   2554:                if (p == NULL)
                   2555:                        panic("_bus_dmamap_load_uio: USERSPACE but no proc");
                   2556: #endif
                   2557:        }
                   2558:
                   2559:        first = 1;
                   2560:        seg = 0;
                   2561:        error = 0;
                   2562:        for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
                   2563:                /*
                   2564:                 * Now at the first iovec to load.  Load each iovec
                   2565:                 * until we have exhausted the residual count.
                   2566:                 */
1.323     thorpej  2567:                minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
                   2568:                addr = (caddr_t)iov[i].iov_base;
1.231     thorpej  2569:
1.317     thorpej  2570:                error = _bus_dmamap_load_buffer(t, map, addr, minlen,
                   2571:                    p, flags, &lastaddr, &seg, first);
1.312     thorpej  2572:                first = 0;
                   2573:
                   2574:                resid -= minlen;
                   2575:        }
                   2576:        if (error == 0) {
                   2577:                map->dm_mapsize = uio->uio_resid;
                   2578:                map->dm_nsegs = seg + 1;
                   2579:        }
                   2580:        return (error);
1.231     thorpej  2581: }
                   2582:
                   2583: /*
                   2584:  * Like _bus_dmamap_load(), but for raw memory allocated with
                   2585:  * bus_dmamem_alloc().
                   2586:  */
                   2587: int
                   2588: _bus_dmamap_load_raw(t, map, segs, nsegs, size, flags)
                   2589:        bus_dma_tag_t t;
                   2590:        bus_dmamap_t map;
                   2591:        bus_dma_segment_t *segs;
                   2592:        int nsegs;
                   2593:        bus_size_t size;
                   2594:        int flags;
                   2595: {
                   2596:
                   2597:        panic("_bus_dmamap_load_raw: not implemented");
                   2598: }
                   2599:
                   2600: /*
                   2601:  * Common function for unloading a DMA map.  May be called by
                   2602:  * bus-specific DMA map unload functions.
                   2603:  */
                   2604: void
                   2605: _bus_dmamap_unload(t, map)
                   2606:        bus_dma_tag_t t;
                   2607:        bus_dmamap_t map;
                   2608: {
                   2609:
                   2610:        /*
                   2611:         * No resources to free; just mark the mappings as
                   2612:         * invalid.
                   2613:         */
1.280     thorpej  2614:        map->dm_mapsize = 0;
1.231     thorpej  2615:        map->dm_nsegs = 0;
                   2616: }
                   2617:
                   2618: /*
                   2619:  * Common function for DMA map synchronization.  May be called
                   2620:  * by bus-specific DMA map synchronization functions.
                   2621:  */
                   2622: void
1.282     thorpej  2623: _bus_dmamap_sync(t, map, offset, len, ops)
1.231     thorpej  2624:        bus_dma_tag_t t;
                   2625:        bus_dmamap_t map;
1.282     thorpej  2626:        bus_addr_t offset;
                   2627:        bus_size_t len;
1.281     thorpej  2628:        int ops;
1.231     thorpej  2629: {
                   2630:
                   2631:        /* Nothing to do here. */
                   2632: }
                   2633:
                   2634: /*
                   2635:  * Common function for DMA-safe memory allocation.  May be called
                   2636:  * by bus-specific DMA memory allocation functions.
                   2637:  */
                   2638: int
                   2639: _bus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags)
                   2640:        bus_dma_tag_t t;
                   2641:        bus_size_t size, alignment, boundary;
                   2642:        bus_dma_segment_t *segs;
                   2643:        int nsegs;
                   2644:        int *rsegs;
                   2645:        int flags;
                   2646: {
                   2647:
                   2648:        return (_bus_dmamem_alloc_range(t, size, alignment, boundary,
                   2649:            segs, nsegs, rsegs, flags, 0, trunc_page(avail_end)));
                   2650: }
                   2651:
                   2652: /*
                   2653:  * Common function for freeing DMA-safe memory.  May be called by
                   2654:  * bus-specific DMA memory free functions.
                   2655:  */
                   2656: void
                   2657: _bus_dmamem_free(t, segs, nsegs)
                   2658:        bus_dma_tag_t t;
                   2659:        bus_dma_segment_t *segs;
                   2660:        int nsegs;
                   2661: {
                   2662:        vm_page_t m;
                   2663:        bus_addr_t addr;
                   2664:        struct pglist mlist;
                   2665:        int curseg;
                   2666:
                   2667:        /*
                   2668:         * Build a list of pages to free back to the VM system.
                   2669:         */
                   2670:        TAILQ_INIT(&mlist);
                   2671:        for (curseg = 0; curseg < nsegs; curseg++) {
                   2672:                for (addr = segs[curseg].ds_addr;
                   2673:                    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
                   2674:                    addr += PAGE_SIZE) {
                   2675:                        m = PHYS_TO_VM_PAGE(addr);
                   2676:                        TAILQ_INSERT_TAIL(&mlist, m, pageq);
                   2677:                }
                   2678:        }
                   2679:
1.284     mrg      2680:        uvm_pglistfree(&mlist);
1.231     thorpej  2681: }
                   2682:
                   2683: /*
                   2684:  * Common function for mapping DMA-safe memory.  May be called by
                   2685:  * bus-specific DMA memory map functions.
                   2686:  */
                   2687: int
                   2688: _bus_dmamem_map(t, segs, nsegs, size, kvap, flags)
                   2689:        bus_dma_tag_t t;
                   2690:        bus_dma_segment_t *segs;
                   2691:        int nsegs;
                   2692:        size_t size;
                   2693:        caddr_t *kvap;
                   2694:        int flags;
                   2695: {
1.314     thorpej  2696:        vaddr_t va;
1.231     thorpej  2697:        bus_addr_t addr;
1.290     thorpej  2698:        int curseg;
1.231     thorpej  2699:
                   2700:        size = round_page(size);
1.247     thorpej  2701:
1.290     thorpej  2702:        va = uvm_km_valloc(kernel_map, size);
1.247     thorpej  2703:
1.231     thorpej  2704:        if (va == 0)
                   2705:                return (ENOMEM);
                   2706:
                   2707:        *kvap = (caddr_t)va;
                   2708:
                   2709:        for (curseg = 0; curseg < nsegs; curseg++) {
                   2710:                for (addr = segs[curseg].ds_addr;
                   2711:                    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
                   2712:                    addr += NBPG, va += NBPG, size -= NBPG) {
                   2713:                        if (size == 0)
                   2714:                                panic("_bus_dmamem_map: size botch");
                   2715:                        pmap_enter(pmap_kernel(), va, addr,
1.355     thorpej  2716:                            VM_PROT_READ | VM_PROT_WRITE, TRUE,
                   2717:                            VM_PROT_READ | VM_PROT_WRITE);
1.231     thorpej  2718:                }
                   2719:        }
                   2720:
                   2721:        return (0);
                   2722: }
                   2723:
                   2724: /*
                   2725:  * Common function for unmapping DMA-safe memory.  May be called by
                   2726:  * bus-specific DMA memory unmapping functions.
                   2727:  */
                   2728: void
                   2729: _bus_dmamem_unmap(t, kva, size)
                   2730:        bus_dma_tag_t t;
                   2731:        caddr_t kva;
                   2732:        size_t size;
                   2733: {
                   2734:
                   2735: #ifdef DIAGNOSTIC
                   2736:        if ((u_long)kva & PGOFSET)
                   2737:                panic("_bus_dmamem_unmap");
                   2738: #endif
                   2739:
                   2740:        size = round_page(size);
1.284     mrg      2741:
1.314     thorpej  2742:        uvm_km_free(kernel_map, (vaddr_t)kva, size);
1.231     thorpej  2743: }
                   2744:
                   2745: /*
                   2746:  * Common functin for mmap(2)'ing DMA-safe memory.  May be called by
                   2747:  * bus-specific DMA mmap(2)'ing functions.
                   2748:  */
                   2749: int
                   2750: _bus_dmamem_mmap(t, segs, nsegs, off, prot, flags)
                   2751:        bus_dma_tag_t t;
                   2752:        bus_dma_segment_t *segs;
                   2753:        int nsegs, off, prot, flags;
                   2754: {
1.250     thorpej  2755:        int i;
1.231     thorpej  2756:
1.250     thorpej  2757:        for (i = 0; i < nsegs; i++) {
                   2758: #ifdef DIAGNOSTIC
                   2759:                if (off & PGOFSET)
                   2760:                        panic("_bus_dmamem_mmap: offset unaligned");
                   2761:                if (segs[i].ds_addr & PGOFSET)
                   2762:                        panic("_bus_dmamem_mmap: segment unaligned");
                   2763:                if (segs[i].ds_len & PGOFSET)
                   2764:                        panic("_bus_dmamem_mmap: segment size not multiple"
                   2765:                            " of page size");
                   2766: #endif
                   2767:                if (off >= segs[i].ds_len) {
                   2768:                        off -= segs[i].ds_len;
                   2769:                        continue;
                   2770:                }
                   2771:
                   2772:                return (i386_btop((caddr_t)segs[i].ds_addr + off));
                   2773:        }
                   2774:
                   2775:        /* Page not found. */
                   2776:        return (-1);
1.231     thorpej  2777: }
                   2778:
                   2779: /**********************************************************************
                   2780:  * DMA utility functions
                   2781:  **********************************************************************/
1.277     thorpej  2782:
                   2783: /*
                   2784:  * Utility function to load a linear buffer.  lastaddrp holds state
                   2785:  * between invocations (for multiple-buffer loads).  segp contains
                   2786:  * the starting segment on entrace, and the ending segment on exit.
                   2787:  * first indicates if this is the first invocation of this function.
                   2788:  */
                   2789: int
1.317     thorpej  2790: _bus_dmamap_load_buffer(t, map, buf, buflen, p, flags, lastaddrp, segp, first)
                   2791:        bus_dma_tag_t t;
1.277     thorpej  2792:        bus_dmamap_t map;
                   2793:        void *buf;
                   2794:        bus_size_t buflen;
                   2795:        struct proc *p;
                   2796:        int flags;
1.314     thorpej  2797:        paddr_t *lastaddrp;
1.277     thorpej  2798:        int *segp;
                   2799:        int first;
                   2800: {
                   2801:        bus_size_t sgsize;
1.304     bouyer   2802:        bus_addr_t curaddr, lastaddr, baddr, bmask;
1.314     thorpej  2803:        vaddr_t vaddr = (vaddr_t)buf;
1.277     thorpej  2804:        int seg;
                   2805:        pmap_t pmap;
                   2806:
                   2807:        if (p != NULL)
                   2808:                pmap = p->p_vmspace->vm_map.pmap;
                   2809:        else
                   2810:                pmap = pmap_kernel();
                   2811:
                   2812:        lastaddr = *lastaddrp;
1.304     bouyer   2813:        bmask  = ~(map->_dm_boundary - 1);
1.277     thorpej  2814:
1.304     bouyer   2815:        for (seg = *segp; buflen > 0 ; ) {
1.277     thorpej  2816:                /*
                   2817:                 * Get the physical address for this segment.
                   2818:                 */
1.360     thorpej  2819:                (void) pmap_extract(pmap, vaddr, &curaddr);
1.306     thorpej  2820:
                   2821:                /*
                   2822:                 * If we're beyond the bounce threshold, notify
                   2823:                 * the caller.
                   2824:                 */
1.325     thorpej  2825:                if (map->_dm_bounce_thresh != 0 &&
                   2826:                    curaddr >= map->_dm_bounce_thresh)
1.306     thorpej  2827:                        return (EINVAL);
1.277     thorpej  2828:
                   2829:                /*
                   2830:                 * Compute the segment size, and adjust counts.
                   2831:                 */
                   2832:                sgsize = NBPG - ((u_long)vaddr & PGOFSET);
                   2833:                if (buflen < sgsize)
                   2834:                        sgsize = buflen;
1.305     thorpej  2835:
                   2836:                /*
                   2837:                 * Make sure we don't cross any boundaries.
                   2838:                 */
1.304     bouyer   2839:                if (map->_dm_boundary > 0) {
1.305     thorpej  2840:                        baddr = (curaddr + map->_dm_boundary) & bmask;
1.304     bouyer   2841:                        if (sgsize > (baddr - curaddr))
                   2842:                                sgsize = (baddr - curaddr);
                   2843:                }
1.277     thorpej  2844:
                   2845:                /*
                   2846:                 * Insert chunk into a segment, coalescing with
                   2847:                 * previous segment if possible.
                   2848:                 */
                   2849:                if (first) {
                   2850:                        map->dm_segs[seg].ds_addr = curaddr;
                   2851:                        map->dm_segs[seg].ds_len = sgsize;
                   2852:                        first = 0;
                   2853:                } else {
                   2854:                        if (curaddr == lastaddr &&
                   2855:                            (map->dm_segs[seg].ds_len + sgsize) <=
1.304     bouyer   2856:                             map->_dm_maxsegsz &&
1.305     thorpej  2857:                            (map->_dm_boundary == 0 ||
1.304     bouyer   2858:                             (map->dm_segs[seg].ds_addr & bmask) ==
                   2859:                             (curaddr & bmask)))
1.277     thorpej  2860:                                map->dm_segs[seg].ds_len += sgsize;
                   2861:                        else {
1.305     thorpej  2862:                                if (++seg >= map->_dm_segcnt)
1.304     bouyer   2863:                                        break;
1.277     thorpej  2864:                                map->dm_segs[seg].ds_addr = curaddr;
                   2865:                                map->dm_segs[seg].ds_len = sgsize;
                   2866:                        }
                   2867:                }
                   2868:
                   2869:                lastaddr = curaddr + sgsize;
                   2870:                vaddr += sgsize;
                   2871:                buflen -= sgsize;
                   2872:        }
                   2873:
                   2874:        *segp = seg;
                   2875:        *lastaddrp = lastaddr;
                   2876:
                   2877:        /*
                   2878:         * Did we fit?
                   2879:         */
                   2880:        if (buflen != 0)
                   2881:                return (EFBIG);         /* XXX better return value here? */
                   2882:        return (0);
                   2883: }
1.231     thorpej  2884:
                   2885: /*
                   2886:  * Allocate physical memory from the given physical address range.
                   2887:  * Called by DMA-safe memory allocation methods.
                   2888:  */
                   2889: int
                   2890: _bus_dmamem_alloc_range(t, size, alignment, boundary, segs, nsegs, rsegs,
                   2891:     flags, low, high)
                   2892:        bus_dma_tag_t t;
                   2893:        bus_size_t size, alignment, boundary;
                   2894:        bus_dma_segment_t *segs;
                   2895:        int nsegs;
                   2896:        int *rsegs;
                   2897:        int flags;
1.314     thorpej  2898:        paddr_t low;
                   2899:        paddr_t high;
1.231     thorpej  2900: {
1.314     thorpej  2901:        paddr_t curaddr, lastaddr;
1.231     thorpej  2902:        vm_page_t m;
                   2903:        struct pglist mlist;
                   2904:        int curseg, error;
                   2905:
                   2906:        /* Always round the size. */
                   2907:        size = round_page(size);
                   2908:
                   2909:        /*
                   2910:         * Allocate pages from the VM system.
                   2911:         */
                   2912:        TAILQ_INIT(&mlist);
1.284     mrg      2913:        error = uvm_pglistalloc(size, low, high, alignment, boundary,
                   2914:            &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
1.231     thorpej  2915:        if (error)
                   2916:                return (error);
                   2917:
                   2918:        /*
                   2919:         * Compute the location, size, and number of segments actually
                   2920:         * returned by the VM code.
                   2921:         */
                   2922:        m = mlist.tqh_first;
                   2923:        curseg = 0;
                   2924:        lastaddr = segs[curseg].ds_addr = VM_PAGE_TO_PHYS(m);
                   2925:        segs[curseg].ds_len = PAGE_SIZE;
                   2926:        m = m->pageq.tqe_next;
                   2927:
                   2928:        for (; m != NULL; m = m->pageq.tqe_next) {
                   2929:                curaddr = VM_PAGE_TO_PHYS(m);
                   2930: #ifdef DIAGNOSTIC
                   2931:                if (curaddr < low || curaddr >= high) {
                   2932:                        printf("vm_page_alloc_memory returned non-sensical"
                   2933:                            " address 0x%lx\n", curaddr);
                   2934:                        panic("_bus_dmamem_alloc_range");
                   2935:                }
                   2936: #endif
                   2937:                if (curaddr == (lastaddr + PAGE_SIZE))
                   2938:                        segs[curseg].ds_len += PAGE_SIZE;
                   2939:                else {
                   2940:                        curseg++;
                   2941:                        segs[curseg].ds_addr = curaddr;
                   2942:                        segs[curseg].ds_len = PAGE_SIZE;
                   2943:                }
                   2944:                lastaddr = curaddr;
                   2945:        }
                   2946:
                   2947:        *rsegs = curseg + 1;
                   2948:
1.213     thorpej  2949:        return (0);
1.45      cgd      2950: }

CVSweb <webmaster@jp.NetBSD.org>