mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-14 14:55:41 +00:00
Fix something that's been bugging me for a long time: move the CPU
type identification code out of machdep.c and into a new file of its own. Hopefully other grot can be moved out of machdep.c as well (by other people) into more descriptively-named files.
This commit is contained in:
parent
090d3c2832
commit
b184bc75f3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=17014
277
sys/amd64/amd64/identcpu.c
Normal file
277
sys/amd64/amd64/identcpu.c
Normal file
@ -0,0 +1,277 @@
|
||||
/*-
|
||||
* Copyright (c) 1992 Terrence R. Lambert.
|
||||
* Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/devconf.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/clock.h>
|
||||
#include <machine/specialreg.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <machine/devconf.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
/* XXX - should be in header file */
|
||||
extern void i486_bzero __P((void *, size_t));
|
||||
extern void i586_bzero __P((void *, size_t));
|
||||
extern void i686_bzero __P((void *, size_t));
|
||||
|
||||
void identifycpu(void); /* XXX should be in different header file */
|
||||
void earlysetcpuclass(void);
|
||||
|
||||
int cpu_class = CPUCLASS_386; /* least common denominator */
|
||||
char machine[] = "i386";
|
||||
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
|
||||
|
||||
static char cpu_model[128];
|
||||
SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "");
|
||||
|
||||
struct kern_devconf kdc_cpu0 = {
|
||||
0, 0, 0, /* filled in by dev_attach */
|
||||
"cpu", 0, { MDDT_CPU },
|
||||
0, 0, 0, CPU_EXTERNALLEN,
|
||||
0, /* CPU has no parent */
|
||||
0, /* no parentdata */
|
||||
DC_BUSY, /* the CPU is always busy */
|
||||
cpu_model, /* no sense in duplication */
|
||||
DC_CLS_CPU /* class */
|
||||
};
|
||||
|
||||
static struct cpu_nameclass i386_cpus[] = {
|
||||
{ "Intel 80286", CPUCLASS_286 }, /* CPU_286 */
|
||||
{ "i386SX", CPUCLASS_386 }, /* CPU_386SX */
|
||||
{ "i386DX", CPUCLASS_386 }, /* CPU_386 */
|
||||
{ "i486SX", CPUCLASS_486 }, /* CPU_486SX */
|
||||
{ "i486DX", CPUCLASS_486 }, /* CPU_486 */
|
||||
{ "Pentium", CPUCLASS_586 }, /* CPU_586 */
|
||||
{ "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */
|
||||
{ "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */
|
||||
};
|
||||
|
||||
void
|
||||
identifycpu(void)
|
||||
{
|
||||
cpu_class = i386_cpus[cpu].cpu_class;
|
||||
printf("CPU: ");
|
||||
strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model);
|
||||
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
if (!strcmp(cpu_vendor,"GenuineIntel")) {
|
||||
if ((cpu_id & 0xf00) > 3) {
|
||||
cpu_model[0] = '\0';
|
||||
|
||||
switch (cpu_id & 0x3000) {
|
||||
case 0x1000:
|
||||
strcpy(cpu_model, "Overdrive ");
|
||||
break;
|
||||
case 0x2000:
|
||||
strcpy(cpu_model, "Dual ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cpu_id & 0xf00) {
|
||||
case 0x400:
|
||||
strcat(cpu_model, "i486 ");
|
||||
break;
|
||||
case 0x500:
|
||||
strcat(cpu_model, "Pentium"); /* nb no space */
|
||||
break;
|
||||
case 0x600:
|
||||
strcat(cpu_model, "Pentium Pro");
|
||||
break;
|
||||
default:
|
||||
strcat(cpu_model, "unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cpu_id & 0xff0) {
|
||||
case 0x400:
|
||||
strcat(cpu_model, "DX"); break;
|
||||
case 0x410:
|
||||
strcat(cpu_model, "DX"); break;
|
||||
case 0x420:
|
||||
strcat(cpu_model, "SX"); break;
|
||||
case 0x430:
|
||||
strcat(cpu_model, "DX2"); break;
|
||||
case 0x440:
|
||||
strcat(cpu_model, "SL"); break;
|
||||
case 0x450:
|
||||
strcat(cpu_model, "SX2"); break;
|
||||
case 0x470:
|
||||
strcat(cpu_model, "DX2 Write-Back Enhanced");
|
||||
break;
|
||||
case 0x480:
|
||||
strcat(cpu_model, "DX4"); break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
printf("%s (", cpu_model);
|
||||
switch(cpu_class) {
|
||||
case CPUCLASS_286:
|
||||
printf("286");
|
||||
break;
|
||||
#if defined(I386_CPU)
|
||||
case CPUCLASS_386:
|
||||
printf("386");
|
||||
break;
|
||||
#endif
|
||||
#if defined(I486_CPU)
|
||||
case CPUCLASS_486:
|
||||
printf("486");
|
||||
bzero = i486_bzero;
|
||||
break;
|
||||
#endif
|
||||
#if defined(I586_CPU)
|
||||
case CPUCLASS_586:
|
||||
printf("%d.%02d-MHz ",
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100,
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100);
|
||||
printf("586");
|
||||
break;
|
||||
#endif
|
||||
#if defined(I686_CPU)
|
||||
case CPUCLASS_686:
|
||||
printf("%d.%02d-MHz ",
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100,
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100);
|
||||
printf("686");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("unknown"); /* will panic below... */
|
||||
}
|
||||
printf("-class CPU)\n");
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
if(*cpu_vendor)
|
||||
printf(" Origin = \"%s\"",cpu_vendor);
|
||||
if(cpu_id)
|
||||
printf(" Id = 0x%lx",cpu_id);
|
||||
|
||||
if (!strcmp(cpu_vendor, "GenuineIntel")) {
|
||||
printf(" Stepping=%ld", cpu_id & 0xf);
|
||||
if (cpu_high > 0) {
|
||||
/*
|
||||
* Here we should probably set up flags indicating
|
||||
* whether or not various features are available.
|
||||
* The interesting ones are probably VME, PSE, PAE,
|
||||
* and PGE. The code already assumes without bothering
|
||||
* to check that all CPUs >= Pentium have a TSC and
|
||||
* MSRs.
|
||||
*/
|
||||
printf("\n Features=0x%b", cpu_feature,
|
||||
"\020"
|
||||
"\001FPU"
|
||||
"\002VME"
|
||||
"\003DE"
|
||||
"\004PSE"
|
||||
"\005TSC"
|
||||
"\006MSR"
|
||||
"\007PAE"
|
||||
"\010MCE"
|
||||
"\011CX8"
|
||||
"\012APIC"
|
||||
"\013<b10>"
|
||||
"\014<b11>"
|
||||
"\015MTRR"
|
||||
"\016PGE"
|
||||
"\017MCA"
|
||||
"\020CMOV"
|
||||
);
|
||||
}
|
||||
}
|
||||
/* Avoid ugly blank lines: only print newline when we have to. */
|
||||
if (*cpu_vendor || cpu_id)
|
||||
printf("\n");
|
||||
#endif
|
||||
#ifdef I686_CPU
|
||||
/*
|
||||
* XXX - Do PPro CPUID level=2 stuff here?
|
||||
*/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now that we have told the user what they have,
|
||||
* let them know if that machine type isn't configured.
|
||||
*/
|
||||
switch (cpu_class) {
|
||||
case CPUCLASS_286: /* a 286 should not make it this far, anyway */
|
||||
#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
|
||||
#error This kernel is not configured for one of the supported CPUs
|
||||
#endif
|
||||
#if !defined(I386_CPU)
|
||||
case CPUCLASS_386:
|
||||
#endif
|
||||
#if !defined(I486_CPU)
|
||||
case CPUCLASS_486:
|
||||
#endif
|
||||
#if !defined(I586_CPU)
|
||||
case CPUCLASS_586:
|
||||
#endif
|
||||
#if !defined(I686_CPU)
|
||||
case CPUCLASS_686:
|
||||
#endif
|
||||
panic("CPU class not configured");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dev_attach(&kdc_cpu0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called specifically to set up cpu_class before
|
||||
* startrtclock() uses it. Probably this should be rearranged so that
|
||||
* startrtclock() doesn't need to run until after identifycpu() has been
|
||||
* called. Another alternative formulation would be for this routine
|
||||
* to do all the identification work, and make identifycpu() into a
|
||||
* printing-only routine.
|
||||
*/
|
||||
void
|
||||
earlysetcpuclass(void)
|
||||
{
|
||||
cpu_class = i386_cpus[cpu].cpu_class;
|
||||
}
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.192 1996/06/08 11:03:01 bde Exp $
|
||||
* $Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp $
|
||||
*/
|
||||
|
||||
#include "npx.h"
|
||||
@ -123,31 +123,12 @@ extern int ptrace_single_step __P((struct proc *p));
|
||||
extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data));
|
||||
extern void dblfault_handler __P((void));
|
||||
|
||||
extern void i486_bzero __P((void *, size_t));
|
||||
extern void i586_bzero __P((void *, size_t));
|
||||
extern void i686_bzero __P((void *, size_t));
|
||||
extern void identifycpu(void); /* XXX header file */
|
||||
extern void earlysetcpuclass(void); /* same header file */
|
||||
|
||||
static void cpu_startup __P((void *));
|
||||
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
|
||||
|
||||
static void identifycpu(void);
|
||||
|
||||
char machine[] = "i386";
|
||||
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
|
||||
|
||||
static char cpu_model[128];
|
||||
SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "");
|
||||
|
||||
struct kern_devconf kdc_cpu0 = {
|
||||
0, 0, 0, /* filled in by dev_attach */
|
||||
"cpu", 0, { MDDT_CPU },
|
||||
0, 0, 0, CPU_EXTERNALLEN,
|
||||
0, /* CPU has no parent */
|
||||
0, /* no parentdata */
|
||||
DC_BUSY, /* the CPU is always busy */
|
||||
cpu_model, /* no sense in duplication */
|
||||
DC_CLS_CPU /* class */
|
||||
};
|
||||
|
||||
#ifndef PANIC_REBOOT_WAIT_TIME
|
||||
#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
|
||||
@ -203,8 +184,6 @@ vm_offset_t phys_avail[10];
|
||||
/* must be 2 less so 0 0 can signal end of chunks */
|
||||
#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2)
|
||||
|
||||
int cpu_class = CPUCLASS_386; /* smallest common denominator */
|
||||
|
||||
static void dumpsys __P((void));
|
||||
static void setup_netisrs __P((struct linker_set *)); /* XXX declare elsewhere */
|
||||
|
||||
@ -244,9 +223,12 @@ cpu_startup(dummy)
|
||||
* Good {morning,afternoon,evening,night}.
|
||||
*/
|
||||
printf(version);
|
||||
cpu_class = i386_cpus[cpu].cpu_class;
|
||||
earlysetcpuclass();
|
||||
startrtclock();
|
||||
identifycpu();
|
||||
#ifdef PERFMON
|
||||
perfmon_init();
|
||||
#endif
|
||||
printf("real memory = %d (%dK bytes)\n", ptoa(Maxmem), ptoa(Maxmem) / 1024);
|
||||
/*
|
||||
* Display any holes after the first chunk of extended memory.
|
||||
@ -485,176 +467,6 @@ setup_netisrs(ls)
|
||||
}
|
||||
}
|
||||
|
||||
static struct cpu_nameclass i386_cpus[] = {
|
||||
{ "Intel 80286", CPUCLASS_286 }, /* CPU_286 */
|
||||
{ "i386SX", CPUCLASS_386 }, /* CPU_386SX */
|
||||
{ "i386DX", CPUCLASS_386 }, /* CPU_386 */
|
||||
{ "i486SX", CPUCLASS_486 }, /* CPU_486SX */
|
||||
{ "i486DX", CPUCLASS_486 }, /* CPU_486 */
|
||||
{ "Pentium", CPUCLASS_586 }, /* CPU_586 */
|
||||
{ "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */
|
||||
{ "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */
|
||||
};
|
||||
|
||||
static void
|
||||
identifycpu()
|
||||
{
|
||||
printf("CPU: ");
|
||||
strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model);
|
||||
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
if (!strcmp(cpu_vendor,"GenuineIntel")) {
|
||||
if ((cpu_id & 0xf00) > 3) {
|
||||
cpu_model[0] = '\0';
|
||||
|
||||
switch (cpu_id & 0x3000) {
|
||||
case 0x1000:
|
||||
strcpy(cpu_model, "Overdrive ");
|
||||
break;
|
||||
case 0x2000:
|
||||
strcpy(cpu_model, "Dual ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cpu_id & 0xf00) {
|
||||
case 0x400:
|
||||
strcat(cpu_model, "i486 ");
|
||||
break;
|
||||
case 0x500:
|
||||
strcat(cpu_model, "Pentium"); /* nb no space */
|
||||
break;
|
||||
case 0x600:
|
||||
strcat(cpu_model, "Pentium Pro");
|
||||
break;
|
||||
default:
|
||||
strcat(cpu_model, "unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cpu_id & 0xff0) {
|
||||
case 0x400:
|
||||
strcat(cpu_model, "DX"); break;
|
||||
case 0x410:
|
||||
strcat(cpu_model, "DX"); break;
|
||||
case 0x420:
|
||||
strcat(cpu_model, "SX"); break;
|
||||
case 0x430:
|
||||
strcat(cpu_model, "DX2"); break;
|
||||
case 0x440:
|
||||
strcat(cpu_model, "SL"); break;
|
||||
case 0x450:
|
||||
strcat(cpu_model, "SX2"); break;
|
||||
case 0x470:
|
||||
strcat(cpu_model, "DX2 Write-Back Enhanced");
|
||||
break;
|
||||
case 0x480:
|
||||
strcat(cpu_model, "DX4"); break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
printf("%s (", cpu_model);
|
||||
switch(cpu_class) {
|
||||
case CPUCLASS_286:
|
||||
printf("286");
|
||||
break;
|
||||
#if defined(I386_CPU)
|
||||
case CPUCLASS_386:
|
||||
printf("386");
|
||||
break;
|
||||
#endif
|
||||
#if defined(I486_CPU)
|
||||
case CPUCLASS_486:
|
||||
printf("486");
|
||||
bzero = i486_bzero;
|
||||
break;
|
||||
#endif
|
||||
#if defined(I586_CPU)
|
||||
case CPUCLASS_586:
|
||||
printf("%d.%02d-MHz ",
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100,
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100);
|
||||
printf("586");
|
||||
break;
|
||||
#endif
|
||||
#if defined(I686_CPU)
|
||||
case CPUCLASS_686:
|
||||
printf("%d.%02d-MHz ",
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100,
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100);
|
||||
printf("686");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("unknown"); /* will panic below... */
|
||||
}
|
||||
printf("-class CPU)\n");
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
if(*cpu_vendor)
|
||||
printf(" Origin = \"%s\"",cpu_vendor);
|
||||
if(cpu_id)
|
||||
printf(" Id = 0x%lx",cpu_id);
|
||||
|
||||
if (!strcmp(cpu_vendor, "GenuineIntel")) {
|
||||
printf(" Stepping=%ld", cpu_id & 0xf);
|
||||
if (cpu_high > 0) {
|
||||
printf("\n Features=0x%b", cpu_feature,
|
||||
"\020"
|
||||
"\001FPU"
|
||||
"\002VME"
|
||||
"\003DE"
|
||||
"\004PSE"
|
||||
"\005TSC"
|
||||
"\006MSR"
|
||||
"\007PAE"
|
||||
"\010MCE"
|
||||
"\011CX8"
|
||||
"\012APIC"
|
||||
"\013<b10>"
|
||||
"\014<b11>"
|
||||
"\015MTRR"
|
||||
"\016PGE"
|
||||
"\017MCA"
|
||||
"\020CMOV"
|
||||
);
|
||||
}
|
||||
}
|
||||
/* Avoid ugly blank lines: only print newline when we have to. */
|
||||
if (*cpu_vendor || cpu_id)
|
||||
printf("\n");
|
||||
#endif
|
||||
/*
|
||||
* Now that we have told the user what they have,
|
||||
* let them know if that machine type isn't configured.
|
||||
*/
|
||||
switch (cpu_class) {
|
||||
case CPUCLASS_286: /* a 286 should not make it this far, anyway */
|
||||
#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
|
||||
#error This kernel is not configured for one of the supported CPUs
|
||||
#endif
|
||||
#if !defined(I386_CPU)
|
||||
case CPUCLASS_386:
|
||||
#endif
|
||||
#if !defined(I486_CPU)
|
||||
case CPUCLASS_486:
|
||||
#endif
|
||||
#if !defined(I586_CPU)
|
||||
case CPUCLASS_586:
|
||||
#endif
|
||||
#if !defined(I686_CPU)
|
||||
case CPUCLASS_686:
|
||||
#endif
|
||||
panic("CPU class not configured");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef PERFMON
|
||||
perfmon_init();
|
||||
#endif
|
||||
dev_attach(&kdc_cpu0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an interrupt to process.
|
||||
*
|
||||
|
@ -1,7 +1,7 @@
|
||||
# This file tells config what files go into building a kernel,
|
||||
# files marked standard are always included.
|
||||
#
|
||||
# $Id: files.i386,v 1.136 1996/06/07 22:26:59 nate Exp $
|
||||
# $Id: files.i386,v 1.137 1996/07/05 18:49:01 jhay Exp $
|
||||
#
|
||||
aic7xxx_asm optional ahc device-driver \
|
||||
dependency "$S/dev/aic7xxx/aic7xxx_asm.c" \
|
||||
@ -41,6 +41,7 @@ i386/i386/db_disasm.c optional ddb
|
||||
i386/i386/db_interface.c optional ddb
|
||||
i386/i386/db_trace.c optional ddb
|
||||
i386/i386/exception.s standard
|
||||
i386/i386/identcpu.c standard
|
||||
i386/i386/in_cksum.c optional inet
|
||||
# locore.s needs to be handled in Makefile to put it first. Otherwise it's
|
||||
# now normal.
|
||||
|
@ -1,7 +1,7 @@
|
||||
# This file tells config what files go into building a kernel,
|
||||
# files marked standard are always included.
|
||||
#
|
||||
# $Id: files.i386,v 1.136 1996/06/07 22:26:59 nate Exp $
|
||||
# $Id: files.i386,v 1.137 1996/07/05 18:49:01 jhay Exp $
|
||||
#
|
||||
aic7xxx_asm optional ahc device-driver \
|
||||
dependency "$S/dev/aic7xxx/aic7xxx_asm.c" \
|
||||
@ -41,6 +41,7 @@ i386/i386/db_disasm.c optional ddb
|
||||
i386/i386/db_interface.c optional ddb
|
||||
i386/i386/db_trace.c optional ddb
|
||||
i386/i386/exception.s standard
|
||||
i386/i386/identcpu.c standard
|
||||
i386/i386/in_cksum.c optional inet
|
||||
# locore.s needs to be handled in Makefile to put it first. Otherwise it's
|
||||
# now normal.
|
||||
|
277
sys/i386/i386/identcpu.c
Normal file
277
sys/i386/i386/identcpu.c
Normal file
@ -0,0 +1,277 @@
|
||||
/*-
|
||||
* Copyright (c) 1992 Terrence R. Lambert.
|
||||
* Copyright (c) 1982, 1987, 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* William Jolitz.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/devconf.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/reg.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/clock.h>
|
||||
#include <machine/specialreg.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <machine/devconf.h>
|
||||
#include <machine/md_var.h>
|
||||
|
||||
/* XXX - should be in header file */
|
||||
extern void i486_bzero __P((void *, size_t));
|
||||
extern void i586_bzero __P((void *, size_t));
|
||||
extern void i686_bzero __P((void *, size_t));
|
||||
|
||||
void identifycpu(void); /* XXX should be in different header file */
|
||||
void earlysetcpuclass(void);
|
||||
|
||||
int cpu_class = CPUCLASS_386; /* least common denominator */
|
||||
char machine[] = "i386";
|
||||
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
|
||||
|
||||
static char cpu_model[128];
|
||||
SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "");
|
||||
|
||||
struct kern_devconf kdc_cpu0 = {
|
||||
0, 0, 0, /* filled in by dev_attach */
|
||||
"cpu", 0, { MDDT_CPU },
|
||||
0, 0, 0, CPU_EXTERNALLEN,
|
||||
0, /* CPU has no parent */
|
||||
0, /* no parentdata */
|
||||
DC_BUSY, /* the CPU is always busy */
|
||||
cpu_model, /* no sense in duplication */
|
||||
DC_CLS_CPU /* class */
|
||||
};
|
||||
|
||||
static struct cpu_nameclass i386_cpus[] = {
|
||||
{ "Intel 80286", CPUCLASS_286 }, /* CPU_286 */
|
||||
{ "i386SX", CPUCLASS_386 }, /* CPU_386SX */
|
||||
{ "i386DX", CPUCLASS_386 }, /* CPU_386 */
|
||||
{ "i486SX", CPUCLASS_486 }, /* CPU_486SX */
|
||||
{ "i486DX", CPUCLASS_486 }, /* CPU_486 */
|
||||
{ "Pentium", CPUCLASS_586 }, /* CPU_586 */
|
||||
{ "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */
|
||||
{ "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */
|
||||
};
|
||||
|
||||
void
|
||||
identifycpu(void)
|
||||
{
|
||||
cpu_class = i386_cpus[cpu].cpu_class;
|
||||
printf("CPU: ");
|
||||
strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model);
|
||||
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
if (!strcmp(cpu_vendor,"GenuineIntel")) {
|
||||
if ((cpu_id & 0xf00) > 3) {
|
||||
cpu_model[0] = '\0';
|
||||
|
||||
switch (cpu_id & 0x3000) {
|
||||
case 0x1000:
|
||||
strcpy(cpu_model, "Overdrive ");
|
||||
break;
|
||||
case 0x2000:
|
||||
strcpy(cpu_model, "Dual ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cpu_id & 0xf00) {
|
||||
case 0x400:
|
||||
strcat(cpu_model, "i486 ");
|
||||
break;
|
||||
case 0x500:
|
||||
strcat(cpu_model, "Pentium"); /* nb no space */
|
||||
break;
|
||||
case 0x600:
|
||||
strcat(cpu_model, "Pentium Pro");
|
||||
break;
|
||||
default:
|
||||
strcat(cpu_model, "unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cpu_id & 0xff0) {
|
||||
case 0x400:
|
||||
strcat(cpu_model, "DX"); break;
|
||||
case 0x410:
|
||||
strcat(cpu_model, "DX"); break;
|
||||
case 0x420:
|
||||
strcat(cpu_model, "SX"); break;
|
||||
case 0x430:
|
||||
strcat(cpu_model, "DX2"); break;
|
||||
case 0x440:
|
||||
strcat(cpu_model, "SL"); break;
|
||||
case 0x450:
|
||||
strcat(cpu_model, "SX2"); break;
|
||||
case 0x470:
|
||||
strcat(cpu_model, "DX2 Write-Back Enhanced");
|
||||
break;
|
||||
case 0x480:
|
||||
strcat(cpu_model, "DX4"); break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
printf("%s (", cpu_model);
|
||||
switch(cpu_class) {
|
||||
case CPUCLASS_286:
|
||||
printf("286");
|
||||
break;
|
||||
#if defined(I386_CPU)
|
||||
case CPUCLASS_386:
|
||||
printf("386");
|
||||
break;
|
||||
#endif
|
||||
#if defined(I486_CPU)
|
||||
case CPUCLASS_486:
|
||||
printf("486");
|
||||
bzero = i486_bzero;
|
||||
break;
|
||||
#endif
|
||||
#if defined(I586_CPU)
|
||||
case CPUCLASS_586:
|
||||
printf("%d.%02d-MHz ",
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100,
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100);
|
||||
printf("586");
|
||||
break;
|
||||
#endif
|
||||
#if defined(I686_CPU)
|
||||
case CPUCLASS_686:
|
||||
printf("%d.%02d-MHz ",
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100,
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100);
|
||||
printf("686");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("unknown"); /* will panic below... */
|
||||
}
|
||||
printf("-class CPU)\n");
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
if(*cpu_vendor)
|
||||
printf(" Origin = \"%s\"",cpu_vendor);
|
||||
if(cpu_id)
|
||||
printf(" Id = 0x%lx",cpu_id);
|
||||
|
||||
if (!strcmp(cpu_vendor, "GenuineIntel")) {
|
||||
printf(" Stepping=%ld", cpu_id & 0xf);
|
||||
if (cpu_high > 0) {
|
||||
/*
|
||||
* Here we should probably set up flags indicating
|
||||
* whether or not various features are available.
|
||||
* The interesting ones are probably VME, PSE, PAE,
|
||||
* and PGE. The code already assumes without bothering
|
||||
* to check that all CPUs >= Pentium have a TSC and
|
||||
* MSRs.
|
||||
*/
|
||||
printf("\n Features=0x%b", cpu_feature,
|
||||
"\020"
|
||||
"\001FPU"
|
||||
"\002VME"
|
||||
"\003DE"
|
||||
"\004PSE"
|
||||
"\005TSC"
|
||||
"\006MSR"
|
||||
"\007PAE"
|
||||
"\010MCE"
|
||||
"\011CX8"
|
||||
"\012APIC"
|
||||
"\013<b10>"
|
||||
"\014<b11>"
|
||||
"\015MTRR"
|
||||
"\016PGE"
|
||||
"\017MCA"
|
||||
"\020CMOV"
|
||||
);
|
||||
}
|
||||
}
|
||||
/* Avoid ugly blank lines: only print newline when we have to. */
|
||||
if (*cpu_vendor || cpu_id)
|
||||
printf("\n");
|
||||
#endif
|
||||
#ifdef I686_CPU
|
||||
/*
|
||||
* XXX - Do PPro CPUID level=2 stuff here?
|
||||
*/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now that we have told the user what they have,
|
||||
* let them know if that machine type isn't configured.
|
||||
*/
|
||||
switch (cpu_class) {
|
||||
case CPUCLASS_286: /* a 286 should not make it this far, anyway */
|
||||
#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
|
||||
#error This kernel is not configured for one of the supported CPUs
|
||||
#endif
|
||||
#if !defined(I386_CPU)
|
||||
case CPUCLASS_386:
|
||||
#endif
|
||||
#if !defined(I486_CPU)
|
||||
case CPUCLASS_486:
|
||||
#endif
|
||||
#if !defined(I586_CPU)
|
||||
case CPUCLASS_586:
|
||||
#endif
|
||||
#if !defined(I686_CPU)
|
||||
case CPUCLASS_686:
|
||||
#endif
|
||||
panic("CPU class not configured");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dev_attach(&kdc_cpu0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is called specifically to set up cpu_class before
|
||||
* startrtclock() uses it. Probably this should be rearranged so that
|
||||
* startrtclock() doesn't need to run until after identifycpu() has been
|
||||
* called. Another alternative formulation would be for this routine
|
||||
* to do all the identification work, and make identifycpu() into a
|
||||
* printing-only routine.
|
||||
*/
|
||||
void
|
||||
earlysetcpuclass(void)
|
||||
{
|
||||
cpu_class = i386_cpus[cpu].cpu_class;
|
||||
}
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.192 1996/06/08 11:03:01 bde Exp $
|
||||
* $Id: machdep.c,v 1.193 1996/06/18 01:22:04 bde Exp $
|
||||
*/
|
||||
|
||||
#include "npx.h"
|
||||
@ -123,31 +123,12 @@ extern int ptrace_single_step __P((struct proc *p));
|
||||
extern int ptrace_write_u __P((struct proc *p, vm_offset_t off, int data));
|
||||
extern void dblfault_handler __P((void));
|
||||
|
||||
extern void i486_bzero __P((void *, size_t));
|
||||
extern void i586_bzero __P((void *, size_t));
|
||||
extern void i686_bzero __P((void *, size_t));
|
||||
extern void identifycpu(void); /* XXX header file */
|
||||
extern void earlysetcpuclass(void); /* same header file */
|
||||
|
||||
static void cpu_startup __P((void *));
|
||||
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL)
|
||||
|
||||
static void identifycpu(void);
|
||||
|
||||
char machine[] = "i386";
|
||||
SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0, "");
|
||||
|
||||
static char cpu_model[128];
|
||||
SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD, cpu_model, 0, "");
|
||||
|
||||
struct kern_devconf kdc_cpu0 = {
|
||||
0, 0, 0, /* filled in by dev_attach */
|
||||
"cpu", 0, { MDDT_CPU },
|
||||
0, 0, 0, CPU_EXTERNALLEN,
|
||||
0, /* CPU has no parent */
|
||||
0, /* no parentdata */
|
||||
DC_BUSY, /* the CPU is always busy */
|
||||
cpu_model, /* no sense in duplication */
|
||||
DC_CLS_CPU /* class */
|
||||
};
|
||||
|
||||
#ifndef PANIC_REBOOT_WAIT_TIME
|
||||
#define PANIC_REBOOT_WAIT_TIME 15 /* default to 15 seconds */
|
||||
@ -203,8 +184,6 @@ vm_offset_t phys_avail[10];
|
||||
/* must be 2 less so 0 0 can signal end of chunks */
|
||||
#define PHYS_AVAIL_ARRAY_END ((sizeof(phys_avail) / sizeof(vm_offset_t)) - 2)
|
||||
|
||||
int cpu_class = CPUCLASS_386; /* smallest common denominator */
|
||||
|
||||
static void dumpsys __P((void));
|
||||
static void setup_netisrs __P((struct linker_set *)); /* XXX declare elsewhere */
|
||||
|
||||
@ -244,9 +223,12 @@ cpu_startup(dummy)
|
||||
* Good {morning,afternoon,evening,night}.
|
||||
*/
|
||||
printf(version);
|
||||
cpu_class = i386_cpus[cpu].cpu_class;
|
||||
earlysetcpuclass();
|
||||
startrtclock();
|
||||
identifycpu();
|
||||
#ifdef PERFMON
|
||||
perfmon_init();
|
||||
#endif
|
||||
printf("real memory = %d (%dK bytes)\n", ptoa(Maxmem), ptoa(Maxmem) / 1024);
|
||||
/*
|
||||
* Display any holes after the first chunk of extended memory.
|
||||
@ -485,176 +467,6 @@ setup_netisrs(ls)
|
||||
}
|
||||
}
|
||||
|
||||
static struct cpu_nameclass i386_cpus[] = {
|
||||
{ "Intel 80286", CPUCLASS_286 }, /* CPU_286 */
|
||||
{ "i386SX", CPUCLASS_386 }, /* CPU_386SX */
|
||||
{ "i386DX", CPUCLASS_386 }, /* CPU_386 */
|
||||
{ "i486SX", CPUCLASS_486 }, /* CPU_486SX */
|
||||
{ "i486DX", CPUCLASS_486 }, /* CPU_486 */
|
||||
{ "Pentium", CPUCLASS_586 }, /* CPU_586 */
|
||||
{ "Cy486DLC", CPUCLASS_486 }, /* CPU_486DLC */
|
||||
{ "Pentium Pro", CPUCLASS_686 }, /* CPU_686 */
|
||||
};
|
||||
|
||||
static void
|
||||
identifycpu()
|
||||
{
|
||||
printf("CPU: ");
|
||||
strncpy(cpu_model, i386_cpus[cpu].cpu_name, sizeof cpu_model);
|
||||
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
if (!strcmp(cpu_vendor,"GenuineIntel")) {
|
||||
if ((cpu_id & 0xf00) > 3) {
|
||||
cpu_model[0] = '\0';
|
||||
|
||||
switch (cpu_id & 0x3000) {
|
||||
case 0x1000:
|
||||
strcpy(cpu_model, "Overdrive ");
|
||||
break;
|
||||
case 0x2000:
|
||||
strcpy(cpu_model, "Dual ");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cpu_id & 0xf00) {
|
||||
case 0x400:
|
||||
strcat(cpu_model, "i486 ");
|
||||
break;
|
||||
case 0x500:
|
||||
strcat(cpu_model, "Pentium"); /* nb no space */
|
||||
break;
|
||||
case 0x600:
|
||||
strcat(cpu_model, "Pentium Pro");
|
||||
break;
|
||||
default:
|
||||
strcat(cpu_model, "unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cpu_id & 0xff0) {
|
||||
case 0x400:
|
||||
strcat(cpu_model, "DX"); break;
|
||||
case 0x410:
|
||||
strcat(cpu_model, "DX"); break;
|
||||
case 0x420:
|
||||
strcat(cpu_model, "SX"); break;
|
||||
case 0x430:
|
||||
strcat(cpu_model, "DX2"); break;
|
||||
case 0x440:
|
||||
strcat(cpu_model, "SL"); break;
|
||||
case 0x450:
|
||||
strcat(cpu_model, "SX2"); break;
|
||||
case 0x470:
|
||||
strcat(cpu_model, "DX2 Write-Back Enhanced");
|
||||
break;
|
||||
case 0x480:
|
||||
strcat(cpu_model, "DX4"); break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
printf("%s (", cpu_model);
|
||||
switch(cpu_class) {
|
||||
case CPUCLASS_286:
|
||||
printf("286");
|
||||
break;
|
||||
#if defined(I386_CPU)
|
||||
case CPUCLASS_386:
|
||||
printf("386");
|
||||
break;
|
||||
#endif
|
||||
#if defined(I486_CPU)
|
||||
case CPUCLASS_486:
|
||||
printf("486");
|
||||
bzero = i486_bzero;
|
||||
break;
|
||||
#endif
|
||||
#if defined(I586_CPU)
|
||||
case CPUCLASS_586:
|
||||
printf("%d.%02d-MHz ",
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100,
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100);
|
||||
printf("586");
|
||||
break;
|
||||
#endif
|
||||
#if defined(I686_CPU)
|
||||
case CPUCLASS_686:
|
||||
printf("%d.%02d-MHz ",
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) / 100,
|
||||
((100 * i586_ctr_rate) >> I586_CTR_RATE_SHIFT) % 100);
|
||||
printf("686");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
printf("unknown"); /* will panic below... */
|
||||
}
|
||||
printf("-class CPU)\n");
|
||||
#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
|
||||
if(*cpu_vendor)
|
||||
printf(" Origin = \"%s\"",cpu_vendor);
|
||||
if(cpu_id)
|
||||
printf(" Id = 0x%lx",cpu_id);
|
||||
|
||||
if (!strcmp(cpu_vendor, "GenuineIntel")) {
|
||||
printf(" Stepping=%ld", cpu_id & 0xf);
|
||||
if (cpu_high > 0) {
|
||||
printf("\n Features=0x%b", cpu_feature,
|
||||
"\020"
|
||||
"\001FPU"
|
||||
"\002VME"
|
||||
"\003DE"
|
||||
"\004PSE"
|
||||
"\005TSC"
|
||||
"\006MSR"
|
||||
"\007PAE"
|
||||
"\010MCE"
|
||||
"\011CX8"
|
||||
"\012APIC"
|
||||
"\013<b10>"
|
||||
"\014<b11>"
|
||||
"\015MTRR"
|
||||
"\016PGE"
|
||||
"\017MCA"
|
||||
"\020CMOV"
|
||||
);
|
||||
}
|
||||
}
|
||||
/* Avoid ugly blank lines: only print newline when we have to. */
|
||||
if (*cpu_vendor || cpu_id)
|
||||
printf("\n");
|
||||
#endif
|
||||
/*
|
||||
* Now that we have told the user what they have,
|
||||
* let them know if that machine type isn't configured.
|
||||
*/
|
||||
switch (cpu_class) {
|
||||
case CPUCLASS_286: /* a 286 should not make it this far, anyway */
|
||||
#if !defined(I386_CPU) && !defined(I486_CPU) && !defined(I586_CPU) && !defined(I686_CPU)
|
||||
#error This kernel is not configured for one of the supported CPUs
|
||||
#endif
|
||||
#if !defined(I386_CPU)
|
||||
case CPUCLASS_386:
|
||||
#endif
|
||||
#if !defined(I486_CPU)
|
||||
case CPUCLASS_486:
|
||||
#endif
|
||||
#if !defined(I586_CPU)
|
||||
case CPUCLASS_586:
|
||||
#endif
|
||||
#if !defined(I686_CPU)
|
||||
case CPUCLASS_686:
|
||||
#endif
|
||||
panic("CPU class not configured");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef PERFMON
|
||||
perfmon_init();
|
||||
#endif
|
||||
dev_attach(&kdc_cpu0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an interrupt to process.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user