root/arch/i386/kernel/setup.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. setup_arch
  2. i486model
  3. i586model
  4. i686model
  5. getmodel
  6. get_cpuinfo

   1 /*
   2  *  linux/arch/i386/kernel/setup.c
   3  *
   4  *  Copyright (C) 1995  Linus Torvalds
   5  */
   6 
   7 /*
   8  * This file handles the architecture-dependent parts of initialization
   9  */
  10 
  11 #include <linux/errno.h>
  12 #include <linux/sched.h>
  13 #include <linux/kernel.h>
  14 #include <linux/mm.h>
  15 #include <linux/stddef.h>
  16 #include <linux/unistd.h>
  17 #include <linux/ptrace.h>
  18 #include <linux/malloc.h>
  19 #include <linux/ldt.h>
  20 #include <linux/user.h>
  21 #include <linux/a.out.h>
  22 #include <linux/tty.h>
  23 #include <linux/ioport.h>
  24 #include <linux/delay.h>
  25 #include <linux/config.h>
  26 #ifdef CONFIG_APM
  27 #include <linux/apm_bios.h>
  28 #endif
  29 #ifdef CONFIG_BLK_DEV_RAM
  30 #include <linux/blk.h>
  31 #endif
  32 #include <asm/segment.h>
  33 #include <asm/system.h>
  34 #include <asm/smp.h>
  35 
  36 /*
  37  * Tell us the machine setup..
  38  */
  39 char hard_math = 0;             /* set by kernel/head.S */
  40 char x86 = 0;                   /* set by kernel/head.S to 3..6 */
  41 char x86_model = 0;             /* set by kernel/head.S */
  42 char x86_mask = 0;              /* set by kernel/head.S */
  43 int x86_capability = 0;         /* set by kernel/head.S */
  44 int fdiv_bug = 0;               /* set if Pentium(TM) with FP bug */
  45 int have_cpuid = 0;             /* set if CPUID instruction works */
  46 
  47 char x86_vendor_id[13] = "unknown";
  48 
  49 char ignore_irq13 = 0;          /* set if exception 16 works */
  50 char wp_works_ok = -1;          /* set if paging hardware honours WP */ 
  51 char hlt_works_ok = 1;          /* set if the "hlt" instruction works */
  52 
  53 /*
  54  * Bus types ..
  55  */
  56 int EISA_bus = 0;
  57 
  58 /*
  59  * Setup options
  60  */
  61 struct drive_info_struct { char dummy[32]; } drive_info;
  62 struct screen_info screen_info;
  63 #ifdef CONFIG_APM
  64 struct apm_bios_info apm_bios_info;
  65 #endif
  66 
  67 unsigned char aux_device_present;
  68 
  69 #ifdef CONFIG_BLK_DEV_RAM
  70 extern int rd_doload;           /* 1 = load ramdisk, 0 = don't load */
  71 extern int rd_prompt;           /* 1 = prompt for ramdisk, 0 = don't prompt */
  72 extern int rd_image_start;      /* starting block # of image */
  73 #endif
  74 
  75 extern int root_mountflags;
  76 extern int _etext, _edata, _end;
  77 
  78 extern char empty_zero_page[PAGE_SIZE];
  79 
  80 /*
  81  * This is set up by the setup-routine at boot-time
  82  */
  83 #define PARAM   empty_zero_page
  84 #define EXT_MEM_K (*(unsigned short *) (PARAM+2))
  85 #ifdef CONFIG_APM
  86 #define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+64))
  87 #endif
  88 #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
  89 #define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
  90 #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
  91 #define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
  92 #define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
  93 #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
  94 #define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
  95 #define KERNEL_START (*(unsigned long *) (PARAM+0x214))
  96 #define INITRD_START (*(unsigned long *) (PARAM+0x218))
  97 #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
  98 #define COMMAND_LINE ((char *) (PARAM+2048))
  99 #define COMMAND_LINE_SIZE 256
 100 
 101 #define RAMDISK_IMAGE_START_MASK        0x07FF
 102 #define RAMDISK_PROMPT_FLAG             0x8000
 103 #define RAMDISK_LOAD_FLAG               0x4000  
 104 
 105 static char command_line[COMMAND_LINE_SIZE] = { 0, };
 106        char saved_command_line[COMMAND_LINE_SIZE];
 107 
 108 void setup_arch(char **cmdline_p,
     /* [previous][next][first][last][top][bottom][index][help] */
 109         unsigned long * memory_start_p, unsigned long * memory_end_p)
 110 {
 111         unsigned long memory_start, memory_end;
 112         char c = ' ', *to = command_line, *from = COMMAND_LINE;
 113         int len = 0;
 114         static unsigned char smptrap=0;
 115 
 116         if(smptrap==1)
 117         {
 118                 return;
 119         }
 120         smptrap=1;
 121 
 122         ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
 123         drive_info = DRIVE_INFO;
 124         screen_info = SCREEN_INFO;
 125 #ifdef CONFIG_APM
 126         apm_bios_info = APM_BIOS_INFO;
 127 #endif
 128         aux_device_present = AUX_DEVICE_INFO;
 129         memory_end = (1<<20) + (EXT_MEM_K<<10);
 130         memory_end &= PAGE_MASK;
 131 #ifdef CONFIG_BLK_DEV_RAM
 132         rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
 133         rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
 134         rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 135 #endif
 136 #ifdef CONFIG_MAX_16M
 137         if (memory_end > 16*1024*1024)
 138                 memory_end = 16*1024*1024;
 139 #endif
 140         if (!MOUNT_ROOT_RDONLY)
 141                 root_mountflags &= ~MS_RDONLY;
 142         memory_start = (unsigned long) &_end;
 143         init_task.mm->start_code = TASK_SIZE;
 144         init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext;
 145         init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata;
 146         init_task.mm->brk = TASK_SIZE + (unsigned long) &_end;
 147 
 148         /* Save unparsed command line copy for /proc/cmdline */
 149         memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
 150         saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 151 
 152         for (;;) {
 153                 /*
 154                  * "mem=nopentium" disables the 4MB page tables.
 155                  * "mem=XXX[kKmM]" overrides the BIOS-reported
 156                  * memory size
 157                  */
 158                 if (c == ' ' && *(const unsigned long *)from == *(const unsigned long *)"mem=") {
 159                         if (to != command_line) to--;
 160                         if (!memcmp(from+4, "nopentium", 9)) {
 161                                 from += 9+4;
 162                                 x86_capability &= ~8;
 163                         } else {
 164                                 memory_end = simple_strtoul(from+4, &from, 0);
 165                                 if ( *from == 'K' || *from == 'k' ) {
 166                                         memory_end = memory_end << 10;
 167                                         from++;
 168                                 } else if ( *from == 'M' || *from == 'm' ) {
 169                                         memory_end = memory_end << 20;
 170                                         from++;
 171                                 }
 172                         }
 173                 }
 174                 c = *(from++);
 175                 if (!c)
 176                         break;
 177                 if (COMMAND_LINE_SIZE <= ++len)
 178                         break;
 179                 *(to++) = c;
 180         }
 181         *to = '\0';
 182         *cmdline_p = command_line;
 183         *memory_start_p = memory_start;
 184         *memory_end_p = memory_end;
 185 
 186 #ifdef CONFIG_BLK_DEV_INITRD
 187         if (LOADER_TYPE) {
 188                 initrd_start = INITRD_START;
 189                 initrd_end = INITRD_START+INITRD_SIZE;
 190                 if (initrd_end > memory_end) {
 191                         printk("initrd extends beyond end of memory "
 192                             "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
 193                             initrd_end,memory_end);
 194                         initrd_start = 0;
 195                 }
 196         }
 197 #endif
 198 
 199         /* request io space for devices used on all i[345]86 PC'S */
 200         request_region(0x00,0x20,"dma1");
 201         request_region(0x40,0x20,"timer");
 202         request_region(0x80,0x20,"dma page reg");
 203         request_region(0xc0,0x20,"dma2");
 204         request_region(0xf0,0x10,"npu");
 205 }
 206 
 207 static const char * i486model(unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209         static const char *model[] = {
 210                 "0", "DX","SX","DX/2","4","SX/2","6","DX/2-WB","DX/4","DX/4-WB"
 211         };
 212         if (nr < sizeof(model)/sizeof(char *))
 213                 return model[nr];
 214         return NULL;
 215 }
 216 
 217 static const char * i586model(unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 218 {
 219         static const char *model[] = {
 220                 "0", "Pentium 60/66","Pentium 75+","OverDrive PODP5V83"
 221         };
 222         if (nr < sizeof(model)/sizeof(char *))
 223                 return model[nr];
 224         return NULL;
 225 }
 226 
 227 static const char * i686model(unsigned int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229         static const char *model[] = {
 230                 "PPro A-step", "Pentium Pro"
 231         };
 232         if (nr < sizeof(model)/sizeof(char *))
 233                 return model[nr];
 234         return NULL;
 235 }
 236 
 237 static const char * getmodel(int x86, int model)
     /* [previous][next][first][last][top][bottom][index][help] */
 238 {
 239         const char *p = NULL;
 240         static char nbuf[12];
 241         switch (x86) {
 242                 case 4:
 243                         p = i486model(model);
 244                         break;
 245                 case 5:
 246                         p = i586model(model);
 247                         break;
 248                 case 6:
 249                         p = i686model(model);
 250                         break;
 251         }
 252         if (p)
 253                 return p;
 254 
 255         sprintf(nbuf, "%d", model);
 256         return nbuf;
 257 }
 258 
 259 int get_cpuinfo(char * buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 260 {
 261         int i, len = 0;
 262         static const char *x86_cap_flags[] = {
 263                 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
 264                 "cx8", "apic", "10", "11", "mtrr", "pge", "mca", "cmov",
 265                 "16", "17", "18", "19", "20", "21", "22", "mmx",
 266                 "24", "25", "26", "27", "28", "29", "30", "31"
 267         };
 268         
 269 #ifdef __SMP__
 270         int n;
 271 
 272 #define CD(X)           (cpu_data[n].X)
 273 /* SMP has the wrong name for loops_per_sec */
 274 #define loops_per_sec   udelay_val
 275 #define CPUN n
 276 
 277         for ( n = 0 ; n < 32 ; n++ ) {
 278                 if ( cpu_present_map & (1<<n) ) {
 279                         if (len) buffer[len++] = '\n'; 
 280 
 281 #else
 282 #define CD(X) (X)
 283 #define CPUN 0
 284 #endif
 285 
 286                         len += sprintf(buffer+len,"processor\t: %d\n"
 287                                        "cpu\t\t: %c86\n"
 288                                        "model\t\t: %s\n"
 289                                        "vendor_id\t: %s\n",
 290                                        CPUN,
 291                                        CD(x86)+'0',
 292                                        CD(have_cpuid) ? 
 293                                          getmodel(CD(x86), CD(x86_model)) :
 294                                          "unknown",
 295                                        CD(x86_vendor_id));
 296         
 297                         if (CD(x86_mask))
 298                                 len += sprintf(buffer+len,
 299                                                "stepping\t: %d\n",
 300                                                CD(x86_mask));
 301                         else
 302                                 len += sprintf(buffer+len, 
 303                                                "stepping\t: unknown\n");
 304         
 305                         len += sprintf(buffer+len,
 306                                        "fdiv_bug\t: %s\n"
 307                                        "hlt_bug\t\t: %s\n"
 308                                        "fpu\t\t: %s\n"
 309                                        "fpu_exception\t: %s\n"
 310                                        "cpuid\t\t: %s\n"
 311                                        "wp\t\t: %s\n"
 312                                        "flags\t\t:",
 313                                        CD(fdiv_bug) ? "yes" : "no",
 314                                        CD(hlt_works_ok) ? "no" : "yes",
 315                                        CD(hard_math) ? "yes" : "no",
 316                                        (CD(hard_math) && ignore_irq13)
 317                                          ? "yes" : "no",
 318                                        CD(have_cpuid) ? "yes" : "no",
 319                                        CD(wp_works_ok) ? "yes" : "no");
 320         
 321                         for ( i = 0 ; i < 32 ; i++ ) {
 322                                 if ( CD(x86_capability) & (1 << i) ) {
 323                                         len += sprintf(buffer+len, " %s",
 324                                                        x86_cap_flags[i]);
 325                                 }
 326                         }
 327                         len += sprintf(buffer+len,
 328                                        "\nbogomips:\t: %lu.%02lu\n",
 329                                        CD(loops_per_sec)/500000,
 330                                        (CD(loops_per_sec)/5000) % 100);
 331 #ifdef __SMP__
 332                 }
 333         }
 334 #endif
 335         return len;
 336 }

/* [previous][next][first][last][top][bottom][index][help] */