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(®ion, gdt, NGDT * sizeof(gdt[0]) - 1);
1766: lgdt(®ion);
1.264 mycroft 1767: #ifdef I586_CPU
1.275 mycroft 1768: setregion(®ion, pentium_idt, NIDT * sizeof(idt[0]) - 1);
1769: #else
1770: setregion(®ion, idt, NIDT * sizeof(idt[0]) - 1);
1771: #endif
1772: lidt(®ion);
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>