~ubuntu-branches/ubuntu/edgy/hwinfo/edgy

« back to all changes in this revision

Viewing changes to src/smp/smp.c

  • Committer: Bazaar Package Importer
  • Author(s): James Vega
  • Date: 2006-09-28 20:56:06 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20060928205606-bgxl69hts04xbx51
Tags: 13.4-1
* New upstream version.
* Switch from dbs to quilt
  - Revamp debian/rules
  - Add quilt and remove dbs from Build-Depends in debian/control
* Remove reference to hwscan(8) from manpage. (closes: #388245)
* Re-wrote manpage from scratch.  Drop docbook-to-man from Build-Depends.
* Remove NEWS.Debian since it is no longer applicable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
[_Anarchy_(alan@lightning.swansea.uk.linux.org)] you should do one check
 
3
   though - if the board seems to be SMP and the CPU in /proc/cpuinfo is non
 
4
   intel dont install an SMP kernel - thats a dual pentium board with a cyrix
 
5
   or similar single cpu in it
 
6
*/
 
7
 
 
8
 
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <unistd.h>
 
12
#include <fcntl.h>
 
13
#include <sys/mman.h>
 
14
#include <string.h>
 
15
#include <errno.h>
 
16
 
 
17
#ifdef __i386__
 
18
#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')
 
19
 
 
20
struct intel_mp_floating
 
21
{
 
22
        char mpf_signature[4];          /* "_MP_"                       */
 
23
        unsigned long mpf_physptr;      /* Configuration table address  */
 
24
        unsigned char mpf_length;       /* Our length (paragraphs)      */
 
25
        unsigned char mpf_specification;/* Specification version        */
 
26
        unsigned char mpf_checksum;     /* Checksum (makes sum 0)       */
 
27
        unsigned char mpf_feature1;     /* Standard or configuration ?  */
 
28
        unsigned char mpf_feature2;     /* Bit7 set for IMCR|PIC        */
 
29
        unsigned char mpf_feature3;     /* Unused (0)                   */
 
30
        unsigned char mpf_feature4;     /* Unused (0)                   */
 
31
        unsigned char mpf_feature5;     /* Unused (0)                   */
 
32
};
 
33
 
 
34
struct mp_config_table
 
35
{
 
36
        char mpc_signature[4];
 
37
#define MPC_SIGNATURE "PCMP"
 
38
        unsigned short mpc_length;      /* Size of table */
 
39
        char  mpc_spec;                 /* 0x01 */
 
40
        char  mpc_checksum;
 
41
        char  mpc_oem[8];
 
42
        char  mpc_productid[12];
 
43
        unsigned long mpc_oemptr;       /* 0 if not present */
 
44
        unsigned short mpc_oemsize;     /* 0 if not present */
 
45
        unsigned short mpc_oemcount;
 
46
        unsigned long mpc_lapic;        /* APIC address */
 
47
        unsigned long reserved;
 
48
};
 
49
 
 
50
/* Followed by entries */
 
51
 
 
52
#define MP_PROCESSOR    0
 
53
#define MP_BUS          1
 
54
#define MP_IOAPIC       2
 
55
#define MP_INTSRC       3
 
56
#define MP_LINTSRC      4
 
57
 
 
58
struct mpc_config_processor
 
59
{
 
60
        unsigned char mpc_type;
 
61
        unsigned char mpc_apicid;       /* Local APIC number */
 
62
        unsigned char mpc_apicver;      /* Its versions */
 
63
        unsigned char mpc_cpuflag;
 
64
#define CPU_ENABLED             1       /* Processor is available */
 
65
#define CPU_BOOTPROCESSOR       2       /* Processor is the BP */
 
66
        unsigned long mpc_cpufeature;           
 
67
#define CPU_STEPPING_MASK 0x0F
 
68
#define CPU_MODEL_MASK  0xF0
 
69
#define CPU_FAMILY_MASK 0xF00
 
70
        unsigned long mpc_featureflag;  /* CPUID feature value */
 
71
        unsigned long mpc_reserved[2];
 
72
};
 
73
 
 
74
struct mpc_config_bus
 
75
{
 
76
        unsigned char mpc_type;
 
77
        unsigned char mpc_busid;
 
78
        unsigned char mpc_bustype[6] __attribute((packed));
 
79
};
 
80
 
 
81
#define BUSTYPE_EISA    "EISA"
 
82
#define BUSTYPE_ISA     "ISA"
 
83
#define BUSTYPE_INTERN  "INTERN"        /* Internal BUS */
 
84
#define BUSTYPE_MCA     "MCA"
 
85
#define BUSTYPE_VL      "VL"            /* Local bus */
 
86
#define BUSTYPE_PCI     "PCI"
 
87
#define BUSTYPE_PCMCIA  "PCMCIA"
 
88
 
 
89
/* We don't understand the others */
 
90
 
 
91
struct mpc_config_ioapic
 
92
{
 
93
        unsigned char mpc_type;
 
94
        unsigned char mpc_apicid;
 
95
        unsigned char mpc_apicver;
 
96
        unsigned char mpc_flags;
 
97
#define MPC_APIC_USABLE         0x01
 
98
        unsigned long mpc_apicaddr;
 
99
};
 
100
 
 
101
struct mpc_config_intsrc
 
102
{
 
103
        unsigned char mpc_type;
 
104
        unsigned char mpc_irqtype;
 
105
        unsigned short mpc_irqflag;
 
106
        unsigned char mpc_srcbus;
 
107
        unsigned char mpc_srcbusirq;
 
108
        unsigned char mpc_dstapic;
 
109
        unsigned char mpc_dstirq;
 
110
};
 
111
 
 
112
#define MP_INT_VECTORED         0
 
113
#define MP_INT_NMI              1
 
114
#define MP_INT_SMI              2
 
115
#define MP_INT_EXTINT           3
 
116
 
 
117
#define MP_IRQDIR_DEFAULT       0
 
118
#define MP_IRQDIR_HIGH          1
 
119
#define MP_IRQDIR_LOW           3
 
120
 
 
121
 
 
122
struct mpc_config_intlocal
 
123
{
 
124
        unsigned char mpc_type;
 
125
        unsigned char mpc_irqtype;
 
126
        unsigned short mpc_irqflag;
 
127
        unsigned char mpc_srcbusid;
 
128
        unsigned char mpc_srcbusirq;
 
129
        unsigned char mpc_destapic;     
 
130
#define MP_APIC_ALL     0xFF
 
131
        unsigned char mpc_destapiclint;
 
132
};
 
133
 
 
134
 
 
135
/*
 
136
 *      Default configurations
 
137
 *
 
138
 *      1       2 CPU ISA 82489DX
 
139
 *      2       2 CPU EISA 82489DX no IRQ 8 or timer chaining
 
140
 *      3       2 CPU EISA 82489DX
 
141
 *      4       2 CPU MCA 82489DX
 
142
 *      5       2 CPU ISA+PCI
 
143
 *      6       2 CPU EISA+PCI
 
144
 *      7       2 CPU MCA+PCI
 
145
 */
 
146
 
 
147
 
 
148
static int smp_found_config=0;
 
149
 
 
150
/*
 
151
 *      Checksum an MP configuration block.
 
152
 */
 
153
 
 
154
static int mpf_checksum(unsigned char *mp, int len)
 
155
{
 
156
        int sum=0;
 
157
        while(len--)
 
158
                sum+=*mp++;
 
159
        return sum&0xFF;
 
160
}
 
161
 
 
162
static int do_smp_scan_config(unsigned long *bp, unsigned long length)
 
163
{
 
164
        struct intel_mp_floating *mpf;
 
165
 
 
166
/*
 
167
        if (sizeof(*mpf)!=16)
 
168
                logMessage("Error: MPF size\n");
 
169
*/
 
170
 
 
171
        while (length>0)
 
172
        {
 
173
                if (*bp==SMP_MAGIC_IDENT)
 
174
                {
 
175
                        mpf=(struct intel_mp_floating *)bp;
 
176
                        if (mpf->mpf_length==1 &&
 
177
                                !mpf_checksum((unsigned char *)bp,16) &&
 
178
                                (mpf->mpf_specification == 1
 
179
                                 || mpf->mpf_specification == 4) )
 
180
                        {
 
181
                                /*logMessage("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
 
182
                                if (mpf->mpf_feature2&(1<<7))
 
183
                                        logMessage("    IMCR and PIC compatibility mode.\n");
 
184
                                else
 
185
                                        logMessage("    Virtual Wire compatibility mode.\n");
 
186
*/
 
187
                                smp_found_config=1;
 
188
                                return 1;
 
189
                        }
 
190
                }
 
191
                bp+=4;
 
192
                length-=16;
 
193
        }
 
194
 
 
195
        return 0;
 
196
}
 
197
 
 
198
static int smp_scan_config(int mem_fd, unsigned long base,
 
199
                           unsigned long length)
 
200
{
 
201
        void *p;
 
202
        int o;
 
203
        
 
204
        o=base&0xFFF;
 
205
        base-=o;
 
206
        length+=o;
 
207
        
 
208
        p=mmap(0, (length+4095)&0xFFFFF000,  PROT_READ, MAP_SHARED, 
 
209
                mem_fd, (base&0xFFFF0000));
 
210
        if(p==MAP_FAILED)
 
211
        {
 
212
                /*logMessage("SMP Probe error: mmap: %s", strerror(errno));*/
 
213
                return 1;
 
214
        }       
 
215
        do_smp_scan_config(p+o, length-o);
 
216
        munmap(p, (length+4095)&0xFFFFF000);
 
217
        return 0;
 
218
}
 
219
 
 
220
static int intelDetectSMP(void)
 
221
{
 
222
        int mem_fd;
 
223
        
 
224
        mem_fd=open("/dev/mem", O_RDONLY);
 
225
        
 
226
        if(mem_fd==-1)
 
227
        {
 
228
                /*logMessage("Error detecting SMP: /dev/mem: %s", strerror(errno));*/
 
229
        }
 
230
        
 
231
        /*
 
232
         * FIXME: Linux assumes you have 640K of base ram..
 
233
         * this continues the error...
 
234
         *
 
235
         * 1) Scan the bottom 1K for a signature
 
236
         * 2) Scan the top 1K of base RAM
 
237
         * 3) Scan the 64K of bios
 
238
         */
 
239
        if (!smp_scan_config(mem_fd, 0x0, 0x400) &&
 
240
            !smp_scan_config(mem_fd, 639*0x400,0x400) &&
 
241
            !smp_scan_config(mem_fd, 0xF0000,0x10000)) {
 
242
#if 0
 
243
 
 
244
                /*
 
245
                 * If it is an SMP machine we should know now, unless the
 
246
                 * configuration is in an EISA/MCA bus machine with an
 
247
                 * extended bios data area. 
 
248
                 *
 
249
                 * there is a real-mode segmented pointer pointing to the
 
250
                 * 4K EBDA area at 0x40E, calculate and scan it here.
 
251
                 *
 
252
                 * NOTE! There are Linux loaders that will corrupt the EBDA
 
253
                 * area, and as such this kind of SMP config may be less
 
254
                 * trustworthy, simply because the SMP table may have been
 
255
                 * stomped on during early boot. These loaders are buggy and
 
256
                 * should be fixed.
 
257
                 */
 
258
                unsigned int address;
 
259
 
 
260
                address = *(unsigned short *)phys_to_virt(0x40E);
 
261
                address<<=4;
 
262
                smp_scan_config(mem_fd, address, 0x1000);
 
263
                if (smp_found_config)
 
264
                        /*logMessage("WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");*/
 
265
#endif                  
 
266
        }
 
267
/*
 
268
        if(smp_found_config)
 
269
                logMessage("Detected SMP capable motherboard\n");
 
270
        else
 
271
                logMessage("Detected non SMP capable motherboard\n");
 
272
*/
 
273
        return smp_found_config;
 
274
}
 
275
 
 
276
int detectSMP(void)
 
277
{
 
278
    static int isSMP = -1;
 
279
 
 
280
    if (isSMP != -1)
 
281
        return isSMP;
 
282
 
 
283
    return isSMP = intelDetectSMP();
 
284
}
 
285
        
 
286
#endif /* __i386__ */