pci.c

来自「适合KS8695X」· C语言 代码 · 共 903 行 · 第 1/2 页

C
903
字号
    mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
				      MAP_SHARED, mem_fd, RomBase | _bus_base());
#else
    mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
				      MAP_SHARED, mem_fd, RomBase);
#endif
    if (pciP != CurrentPci) {
      enablePci = PciRead32(0x4,pciP->Slot.l);
      PciWrite32(0x4,enablePci | 0x2,pciP->Slot.l);
    }

#ifdef PRINT_PCI
    dprint((unsigned long)ptr,0x30);
#endif
    while ( *ptr == 0x55 && *(ptr+1) == 0xAA) {
	unsigned short data_off = *(ptr+0x18) | (*(ptr+0x19)<< 8);
	unsigned char *data = ptr + data_off;
	unsigned char type;
	int i;

	if (*data!='P' || *(data+1)!='C' || *(data+2)!='I' || *(data+3)!='R') {
	    break;
	}
	type = *(data + 0x14);
	P_printf("data segment in BIOS: 0x%x, type: 0x%x ",data_off,type);

	if (type != 0)  { /* not PC-AT image: find next one */
	    unsigned int image_length;
	    unsigned char indicator = *(data + 0x15);
	    if (indicator & 0x80) /* last image */
		break;
	    image_length = (*(data + 0x10)
			    | (*(data + 0x11) << 8)) << 9;
	    P_printf("data image length: 0x%x, ind: 0x%x\n",
		     image_length,indicator);
	    ptr = ptr + image_length;
	    continue;
	}
	/* OK, we have a PC Image */
	length = (*(ptr + 2) << 9);
	P_printf("BIOS length: 0x%x\n",length);
	scratch = (unsigned char *)malloc(length);
	/* don't use memcpy() here: Reading from bus! */
	for (i=0;i<length;i++)
	    *(scratch + i)=*(ptr + i);
	break;
    }

    if (pciP != CurrentPci)
      PciWrite32(0x4,enablePci,pciP->Slot.l);

    /* unmap/close/disable PCI bios mem */
    munmap(mem, biosSize);
    close(mem_fd);
    /* disable and restore mapping */
    writePci(pciP->Slot.l | 0x30, pciP->RomBase & ~(CARD32)1);

    if (scratch && length) {
	memcpy((unsigned char *)V_BIOS, scratch, length);
	free(scratch);
    }

    restoreMem(pciP);
    return length;
}

CARD32
findPci(CARD16 slotBX)
{
    CARD32 slot = slotBX << 8;

    if (slot == (CurrentPci->Slot.l & ~PCI_EN))
	return (CurrentPci->Slot.l | PCI_EN);
    else {
#if !SHOW_ALL_DEV
	PciBusPtr pBus = CurrentPci->pBus;
	while (pBus) {
	  /*      fprintf(stderr,"slot: 0x%x  bridge: 0x%x\n",slot, pBus->Slot.l); */
	    if (slot == (pBus->Slot.l & ~PCI_EN))
		return pBus->Slot.l | PCI_EN;
	    pBus = pBus->next;
	}
#else
	PciStructPtr pPci = PciStruct;
	while (pPci) {
	  /*fprintf(stderr,"slot: 0x%x  bridge: 0x%x\n",slot, pPci->Slot.l); */
	    if (slot == (pPci->Slot.l & ~PCI_EN))
		return pPci->Slot.l | PCI_EN;
	    pPci = pPci->next;
	}
#endif
    }
    return 0;
}

CARD16
pciSlotBX(PciStructPtr pPci)
{
    return (CARD16)((pPci->Slot.l >> 8) & 0xFFFF);
}

PciStructPtr
findPciDevice(CARD16 vendorID, CARD16 deviceID, char n)
{
    PciStructPtr pPci = CurrentPci;
    n++;

    while (pPci)  {
	if ((pPci->VendorID == vendorID) && (pPci->DeviceID == deviceID)) {
	if (!(--n)) break;
	}
    pPci = pPci->next;
    }
    return pPci;
}

PciStructPtr
findPciClass(CARD8 intf, CARD8 subClass, CARD16 class, char n)
{
    PciStructPtr pPci = CurrentPci;
    n++;

    while (pPci)  {
	if ((pPci->Interface == intf) && (pPci->SubClass == subClass)
	 && (pPci->BaseClass == class)) {
	if (!(--n)) break;
	}
    pPci = pPci->next;
    }
    return pPci;
}

static void
readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func, CARD32 *reg)
{
    CARD32   config_cmd = PCI_EN | (bus<<16) |
      (dev<<11) | (func<<8);
    int i;

    for (i = 0; i<64;i+=4) {
#ifdef __alpha__
	reg[i] = axpPciCfgRead(config_cmd | i);
#else
	outl(PCI_MODE1_ADDRESS_REG, config_cmd | i);
	reg[i] = inl(PCI_MODE1_DATA_REG);
#endif

#ifdef V86BIOS_DEBUG
	P_printf("0x%lx\n",reg[i]);
#endif
    }
}

static int
checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func)
{
    CARD32    config_cmd = PCI_EN | (bus<<16) |
      (dev<<11) | (func<<8);
    CARD32 reg;
#ifdef __alpha__
	reg = axpPciCfgRead(config_cmd);
#else
	outl(PCI_MODE1_ADDRESS_REG, config_cmd);
	reg = inl(PCI_MODE1_DATA_REG);
#endif
    if (reg != 0xFFFFFFFF)
	return 1;
    else
	return 0;
}

static int
checkSlotCfg2(CARD32 bus, int dev)
{
    CARD32 val;

    outb(PCI_MODE2_ENABLE_REG, 0xF1);
    outb(PCI_MODE2_FORWARD_REG, bus);
    val = inl(dev << 8);
    outb(PCI_MODE2_FORWARD_REG, 0x00);
    outb(PCI_MODE2_ENABLE_REG, 0x00);
    if (val == 0xFFFFFFFF)
	return 0;
    if (val == 0xF0F0F0F0)
	return 0;
    return 1;
}

static void
readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg)
{
    int i;

    outb(PCI_MODE2_ENABLE_REG, 0xF1);
    outb(PCI_MODE2_FORWARD_REG, bus);
    for (i = 0; i<64;i+=4) {
	reg[i] = inl((dev << 8) + i);
#ifdef V86BIOS_DEBUG
	P_printf("0x%lx\n",reg[i]);
#endif
    }
    outb(PCI_MODE2_ENABLE_REG, 0x00);
}

static CARD8
interpretConfigSpace(CARD32 *reg, int busidx, CARD8 dev, CARD8 func)
{
    CARD32 config_cmd;
    CARD16 vendor, device;
    CARD8 baseclass, subclass;
    CARD8 primary, secondary;
    CARD8 header, interface;
    int i;

    config_cmd = PCI_EN | busidx<<16 |
	(dev<<11) | (func<<8);

    for (i = 0x10; i < 0x28; i+=4) {
	if (IS_MEM32(reg[i]))
	    if ((reg[i] & 0xFFFFFFF0) < pciMinMemReg)
		pciMinMemReg = (reg[i] & 0xFFFFFFF0);
#ifdef __alpha__
	if (IS_MEM64(reg[i])) {
		unsigned long addr = reg[i] |
	      (unsigned long)(reg[i+4]) << 32;
	    if ((addr & ~0xfL) < pciMinMemReg)
		pciMinMemReg = (addr & ~0xfL);
	    i+=4;
	}
#endif
    }
    vendor = reg[0] & 0xFFFF;
    device = reg[0] >> 16;
    P_printf("bus: %i card: %i func %i reg0: 0x%x ", busidx,dev,func,reg[0]);
    baseclass = reg[8] >> 24;
    subclass = (reg[8] >> 16) & 0xFF;
    interface = (reg[8] >> 8) & 0xFF;

    header = (reg[0x0c] >> 16) & 0xff;
    P_printf("bc 0x%x, sub 0x%x, if 0x%x, hdr 0x%x\n",
	     baseclass,subclass,interface,header);
    if (BRIDGE_CLASS(baseclass)) {
	if (BRIDGE_PCI_CLASS(subclass)) {
	    PciBusPtr pbp = malloc(sizeof(PciBusRec));
	    P_printf("Pci-Pci Bridge found; ");
	    primary = reg[0x18] & 0xFF;
	    secondary = (reg[0x18] >> 8) & 0xFF;
	    P_printf("primary: 0x%x secondary: 0x%x\n",
		     primary,secondary);
	    pbp->bctl = reg[0x3c];
	    pbp->primary = primary;
	    pbp->secondary = secondary;
	    pbp->Slot.l = config_cmd;
	    pbp->next = PciBuses;
	    PciBuses = pbp;
	    numbus++;
	} else if (BRIDGE_HOST_CLASS(subclass)
		   && (hostbridges++ > 1)) {
	    numbus++;
	}
    } else if (VIDEO_CLASS(baseclass,subclass)) {
	PciStructPtr pcp = malloc(sizeof(PciStructRec));
	P_printf("Display adapter found\n");
	pcp->RomBase = reg[0x30];
	pcp->cmd_st = reg[4];
	pcp->active = (reg[4] & 0x03) == 3 ? 1 : 0;
	pcp->VendorID = vendor;
	pcp->DeviceID = device;
	pcp->Interface = interface;
	pcp->BaseClass = baseclass;
	pcp->SubClass = subclass;
	pcp->Slot.l = config_cmd;
	pcp->bus = busidx;
	pcp->dev = dev;
	pcp->func = func;
	pcp->next = PciStruct;
	PciStruct = pcp;
    }
    if ((func == 0)
	&& ((header & PCI_MULTIFUNC_DEV) == 0))
	func = 8;
    else
	func++;
    return func;
}

static CARD32 remapMEM_val;
static int remapMEM_num;

static int /* map it on some other video device */
remapMem(PciStructPtr pciP, int num, CARD32 size)
{
    PciStructPtr pciPtr = PciStruct;
    int i;
    CARD32 org;
    CARD32 val;
    CARD32 size_n;

    org = PciRead32(num + 0x10,pciP->Slot.l);

    while (pciPtr) {
	for (i = 0; i < 20; i=i+4) {

	    val = PciRead32(i + 0x10,pciPtr->Slot.l);
	    /* don't map it on itself */
	    if ((org & 0xfffffff0) == (val & 0xfffffff0))
		continue;
	    if (val && !(val & 1))
		PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l);
	    else
		continue;
	    size_n = PciRead32(i + 0x10,pciPtr->Slot.l);
	    PciWrite32(i + 0x10,val,pciPtr->Slot.l);
	    size_n = ~(CARD32)(size_n  & 0xfffffff0) + 1;

	    if (size_n >= size) {
		PciWrite32(num + 0x10,val,pciP->Slot.l);
		return 1;
	    }
	}
	pciPtr = pciPtr->next;
    }
    /* last resort: try to go below lowest PCI mem address */
    val = ((pciMinMemReg & ~(CARD32)(size - 1)) - size);
    if (val > 0x7fffffff) {
	PciWrite32(num + 0x10,val, pciP->Slot.l);
	return 1;
    }

    return 0;
}

static void
restoreMem(PciStructPtr pciP)
{
    if (remapMEM_val == 0) return;
    PciWrite32(remapMEM_num + 0x10,remapMEM_val,pciP->Slot.l);
    return;
}

static CARD32
findBIOSMap(PciStructPtr pciP, CARD32 *biosSize)
{
    PciStructPtr pciPtr = PciStruct;
    int i;
    CARD32 val;
    CARD32 size;

    PciWrite32(0x30,0xffffffff,pciP->Slot.l);
    *biosSize = PciRead32(0x30,pciP->Slot.l);
    P_printf("bios size: 0x%x\n",*biosSize);
    PciWrite32(0x30,pciP->RomBase,pciP->Slot.l);
    *biosSize = ~(*biosSize & 0xFFFFFF00) + 1;
    P_printf("bios size masked: 0x%x\n",*biosSize);
    if (*biosSize > (1024 * 1024 * 16)) {
      *biosSize = 1024 * 1024 * 16;
      P_printf("fixing broken BIOS size: 0x%x\n",*biosSize);
    }
    while (pciPtr) {
	if (pciPtr->bus != pciP->bus) {
	    pciPtr = pciPtr->next;
	    continue;
	}
	for (i = 0; i < 20; i=i+4) {

	    val = PciRead32(i + 0x10,pciPtr->Slot.l);
	    if (!(val & 1))

	    PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l);
	    else
		continue;
	    size = PciRead32(i + 0x10,pciPtr->Slot.l);
	    PciWrite32(i + 0x10,val,pciPtr->Slot.l);
	    size = ~(CARD32)(size & 0xFFFFFFF0) + 1;
#ifdef V86_BIOS_DEBUG
	    P_printf("size: 0x%x\n",size);
#endif
	    if (size >= *biosSize) {
		if (pciP == pciPtr) { /* if same device remap ram*/
		    if (!(remapMem(pciP,i,size)))
			continue;
		    remapMEM_val = val;
		    remapMEM_num = i;
		} else {
		    remapMEM_val = 0;
		}
		return val & 0xFFFFFF00;
	    }
	}
	pciPtr = pciPtr->next;
    }
    remapMEM_val = 0;
    /* very last resort */
    if (pciP->bus == 0 && (pciMinMemReg > *biosSize))
      return (pciMinMemReg - size) & ~(size - 1);

    return 0;
}

int
cfg1out(CARD16 addr, CARD32 val)
{
  if (addr == 0xCF8) {
    PciCfg1Addr = val;
    return 1;
  } else if (addr == 0xCFC) {
    writePci(PciCfg1Addr, val);
    return 1;
  }
  return 0;
}

int
cfg1in(CARD16 addr, CARD32 *val)
{
  if (addr == 0xCF8) {
    *val = PciCfg1Addr;
    return 1;
  } else if (addr == 0xCFC) {
    *val = readPci(PciCfg1Addr);
    return 1;
  }
  return 0;
}

void
list_pci(void)
{
    PciStructPtr pci = PciList;

    while (pci) {
    printf("[0x%x:0x%x:0x%x] vendor: 0x%4.4x dev: 0x%4.4x class: 0x%4.4x"
	   " subclass: 0x%4.4x\n",pci->bus,pci->dev,pci->func,
	   pci->VendorID,pci->DeviceID,pci->BaseClass,pci->SubClass);
    pci = pci->next;
    }
}

PciStructPtr
findPciByIDs(int bus, int dev, int func)
{
  PciStructPtr pciP = PciList;

  while (pciP) {
    if (pciP->bus == bus && pciP->dev == dev && pciP->func == func)
      return pciP;
    pciP = pciP->next;
  }
  return NULL;
}

⌨️ 快捷键说明

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