⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smp-imps.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
    {      /*  XXXXX  add OS-specific setup for secondary CPUs here */      imps_num_cpus++;    }}static voidadd_bus (imps_bus * bus){  char str[8];  memmove (str, bus->bus_type, 6);  str[6] = 0;  KERNEL_PRINT (("  Bus id %d is %s\n", bus->id, str));  /*  XXXXX  add OS-specific code here */}static voidadd_ioapic (imps_ioapic * ioapic){  KERNEL_PRINT (("  I/O APIC id %d ver %d, address: 0x%x  ",		 ioapic->id, ioapic->ver, ioapic->addr));  if (!(ioapic->flags & IMPS_FLAG_ENABLED))    {      KERNEL_PRINT (("DISABLED\n"));      return;    }  KERNEL_PRINT (("\n"));  /*  XXXXX  add OS-specific code here */}static voidimps_read_config_table (unsigned start, int count){  while (count-- > 0)    {      switch (*((unsigned char *) start))	{	case IMPS_BCT_PROCESSOR:	  add_processor ((imps_processor *) start);	  start += 12;		/* 20 total */	  break;	case IMPS_BCT_BUS:	  add_bus ((imps_bus *) start);	  break;	case IMPS_BCT_IOAPIC:	  add_ioapic ((imps_ioapic *) start);	  break;#if 0				/*  XXXXX  uncomment this if "add_io_interrupt" is implemented */	case IMPS_BCT_IO_INTERRUPT:	  add_io_interrupt ((imps_interrupt *) start);	  break;#endif#if 0				/*  XXXXX  uncomment this if "add_local_interrupt" is implemented */	case IMPS_BCT_LOCAL_INTERRUPT:	  add_local_interupt ((imps_interrupt *) start);	  break;#endif	default:	  break;	}      start += 8;    }}static intimps_bad_bios (imps_fps * fps_ptr){  int sum;  imps_cth *local_cth_ptr  = (imps_cth *) PHYS_TO_VIRTUAL (fps_ptr->cth_ptr);  if (fps_ptr->feature_info[0] > IMPS_FPS_DEFAULT_MAX)    {      KERNEL_PRINT (("    Invalid MP System Configuration type %d\n",		     fps_ptr->feature_info[0]));      return 1;    }  if (fps_ptr->cth_ptr)    {      sum = get_checksum ((unsigned) local_cth_ptr,			  local_cth_ptr->base_length);      if (local_cth_ptr->sig != IMPS_CTH_SIGNATURE || sum)	{	  KERNEL_PRINT			(("    Bad MP Config Table sig 0x%x and/or checksum 0x%x\n",			(unsigned) (fps_ptr->cth_ptr), sum));	  return 1;	}      if (local_cth_ptr->spec_rev != fps_ptr->spec_rev)	{	  KERNEL_PRINT (("    Bad MP Config Table sub-revision # %d\n", local_cth_ptr->spec_rev));	  return 1;	}      if (local_cth_ptr->extended_length)	{	  sum = (get_checksum (((unsigned) local_cth_ptr)			       + local_cth_ptr->base_length,			       local_cth_ptr->extended_length)		 + local_cth_ptr->extended_checksum) & 0xFF;	  if (sum)	    {	      KERNEL_PRINT			    (("    Bad Extended MP Config Table checksum 0x%x\n", sum));	      return 1;	    }	}    }  else if (!fps_ptr->feature_info[0])    {      KERNEL_PRINT (("    Missing configuration information\n"));      return 1;    }  return 0;}static voidimps_read_bios (imps_fps * fps_ptr){  int apicid;  unsigned cth_start, cth_count;  imps_cth *local_cth_ptr  = (imps_cth *) PHYS_TO_VIRTUAL (fps_ptr->cth_ptr);  char *str_ptr;  KERNEL_PRINT (("Intel MultiProcessor Spec 1.%d BIOS support detected\n",		 fps_ptr->spec_rev));  /*   *  Do all checking of errors which would definitely   *  lead to failure of the SMP boot here.   */  if (imps_bad_bios (fps_ptr))    {      KERNEL_PRINT (("    Disabling MPS support\n"));      return;    }  if (fps_ptr->feature_info[1] & IMPS_FPS_IMCRP_BIT)    {      str_ptr = "IMCR and PIC";    }  else    {      str_ptr = "Virtual Wire";    }  if (fps_ptr->cth_ptr)    {      imps_lapic_addr = local_cth_ptr->lapic_addr;    }  else    {      imps_lapic_addr = LAPIC_ADDR_DEFAULT;    }  KERNEL_PRINT		(("    APIC config: \"%s mode\"    Local APIC address: 0x%x\n",		 str_ptr, imps_lapic_addr));  imps_lapic_addr = PHYS_TO_VIRTUAL (imps_lapic_addr);  /*   *  Setup primary CPU.   */  apicid = IMPS_LAPIC_READ (LAPIC_SPIV);  IMPS_LAPIC_WRITE (LAPIC_SPIV, apicid | LAPIC_SPIV_ENABLE_APIC);  imps_any_new_apics = IMPS_LAPIC_READ (LAPIC_VER) & 0xF0;  apicid = IMPS_APIC_ID (IMPS_LAPIC_READ (LAPIC_ID));  imps_cpu_apic_map[0] = apicid;  imps_apic_cpu_map[apicid] = 0;  if (fps_ptr->cth_ptr)    {      char str1[16], str2[16];      memcpy (str1, local_cth_ptr->oem_id, 8);      str1[8] = 0;      memcpy (str2, local_cth_ptr->prod_id, 12);      str2[12] = 0;      KERNEL_PRINT (("  OEM id: %s  Product id: %s\n", str1, str2));      cth_start = ((unsigned) local_cth_ptr) + sizeof (imps_cth);      cth_count = local_cth_ptr->entry_count;    }  else    {      *((volatile unsigned *) IOAPIC_ADDR_DEFAULT) = IOAPIC_ID;      defconfig.ioapic.id	= IMPS_APIC_ID (*((volatile unsigned *)			  (IOAPIC_ADDR_DEFAULT + IOAPIC_RW)));      *((volatile unsigned *) IOAPIC_ADDR_DEFAULT) = IOAPIC_VER;      defconfig.ioapic.ver	= APIC_VERSION (*((volatile unsigned *)			  (IOAPIC_ADDR_DEFAULT + IOAPIC_RW)));      defconfig.proc[apicid].flags	= IMPS_FLAG_ENABLED | IMPS_CPUFLAG_BOOT;      defconfig.proc[!apicid].flags = IMPS_FLAG_ENABLED;      imps_num_cpus = 2;      if (fps_ptr->feature_info[0] == 1	  || fps_ptr->feature_info[0] == 5)	{	  memcpy (defconfig.bus[0].bus_type, "ISA   ", 6);	}      if (fps_ptr->feature_info[0] == 4	  || fps_ptr->feature_info[0] == 7)	{	  memcpy (defconfig.bus[0].bus_type, "MCA   ", 6);	}      if (fps_ptr->feature_info[0] > 4)	{	  defconfig.proc[0].apic_ver = 0x10;	  defconfig.proc[1].apic_ver = 0x10;	  defconfig.bus[1].type = IMPS_BCT_BUS;	}      if (fps_ptr->feature_info[0] == 2)	{	  defconfig.intin[2].type = 255;	  defconfig.intin[13].type = 255;	}      if (fps_ptr->feature_info[0] == 7)	{	  defconfig.intin[0].type = 255;	}      cth_start = (unsigned) &defconfig;      cth_count = DEF_ENTRIES;    }  imps_read_config_table (cth_start, cth_count);  /* %%%%% ESB read extended entries here */  imps_enabled = 1;}/* *  Given a region to check, this actually looks for the "MP Floating *  Pointer Structure".  The return value indicates if the correct *  signature and checksum for a floating pointer structure of the *  appropriate spec revision was found.  If so, then do not search *  further. * *  NOTE:  The memory scan will always be in the bottom 1 MB. * *  This function presumes that "start" will always be aligned to a 16-bit *  boundary. * *  Function finished. */static intimps_scan (unsigned start, unsigned length){  IMPS_DEBUG_PRINT (("Scanning from 0x%x for %d bytes\n",		     start, length));  while (length > 0)    {      imps_fps *fps_ptr = (imps_fps *) PHYS_TO_VIRTUAL (start);      if (fps_ptr->sig == IMPS_FPS_SIGNATURE	  && fps_ptr->length == 1	  && (fps_ptr->spec_rev == 1 || fps_ptr->spec_rev == 4)	  && !get_checksum (start, 16))	{	  IMPS_DEBUG_PRINT (("Found MP Floating Structure Pointer at %x\n", start));	  imps_read_bios (fps_ptr);	  return 1;	}      length -= 16;      start += 16;    }  return 0;}/* *  This is the primary function for probing for MPS compatible hardware *  and BIOS information.  Call this during the early stages of OS startup, *  before memory can be messed up. * *  The probe looks for the "MP Floating Pointer Structure" at locations *  listed at the top of page 4-2 of the spec. * *  Environment requirements from the OS to run: * *   (1) : A non-linear virtual to physical memory mapping is probably OK, *	     as (I think) the structures all fall within page boundaries, *	     but a linear mapping is recommended.  Currently assumes that *	     the mapping will remain identical over time (which should be *	     OK since it only accesses memory which shouldn't be munged *	     by the OS anyway). *   (2) : The OS only consumes memory which the BIOS says is OK to use, *	     and not any of the BIOS standard areas (the areas 0x400 to *	     0x600, the EBDA, 0xE0000 to 0xFFFFF, and unreported physical *	     RAM).  Sometimes a small amount of physical RAM is not *	     reported by the BIOS, to be used to store MPS and other *	     information. *   (3) : It must be possible to read the CMOS. *   (4) : There must be between 512K and 640K of lower memory (this is a *	     sanity check). * *  Function finished. */intimps_probe (void){  /*   *  Determine possible address of the EBDA   */  unsigned ebda_addr = *((unsigned short *)			 PHYS_TO_VIRTUAL (EBDA_SEG_ADDR)) << 4;  /*   *  Determine amount of installed lower memory (not *available*   *  lower memory).   *   *  NOTE:  This should work reliably as long as we verify the   *         machine is at least a system that could possibly have   *         MPS compatibility to begin with.   */  unsigned mem_lower = ((CMOS_READ_BYTE (CMOS_BASE_MEMORY + 1) << 8)			| CMOS_READ_BYTE (CMOS_BASE_MEMORY)) << 10;#ifdef IMPS_DEBUG  imps_enabled = 0;  imps_num_cpus = 1;#endif  /*   *  Sanity check : if this isn't reasonable, it is almost impossibly   *    unlikely to be an MPS compatible machine, so return failure.   */  if (mem_lower < 512 * 1024 || mem_lower > 640 * 1024)    {      return 0;    }  if (ebda_addr > mem_lower - 1024      || ebda_addr + *((unsigned char *) PHYS_TO_VIRTUAL (ebda_addr))      * 1024 > mem_lower)    {      ebda_addr = 0;    }  if (((ebda_addr && imps_scan (ebda_addr, 1024))       || (!ebda_addr && imps_scan (mem_lower - 1024, 1024))       || imps_scan (0xF0000, 0x10000)) && imps_enabled)    {      return 1;    }  /*   *  If no BIOS info on MPS hardware is found, then return failure.   */  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -