龙芯2k1000-pmon(8)- _pci_businit---1

这个部分没有分析过,先试试看,按照代码执行的顺序,现在应该是这个位置来了。

1. 直入主题吧,tgt_devinit函数

2.  _pci_businit (int init),init的参数值是1

void
_pci_businit (int init)
{
	char *v;

	tgt_putchar('P');
	v = getenv("pciverbose");
    tgt_putchar('1');
	if (v) {
	    _pciverbose = atol(v);
	}
    tgt_putchar('2');

	/* intialise the PCI bridge */
	if (/*init*/ 1) {
		SBD_DISPLAY ("PCIH", CHKPNT_PCIH);
		init = _pci_hwinit (init, &def_bus_iot, &def_bus_memt);
		pci_roots = init;
		SBD_DISPLAY ("PCIH", CHKPNT_PCIH);
		if (init < 1)
			return;
	}
	SBD_DISPLAY ("PCID", 0);
	if(monarch_mode) {
		int i;
		struct pci_device *pb;

                if (_pciverbose) {
			printf("setting up %d bus\n", init);
		}
		for(i = 0, pb = _pci_head; i < pci_roots; i++, pb = pb->next) {
			pb->bridge.pribus_num = i?++_pci_nbus:_pci_nbus;
			_pci_scan_dev(pb, pb->bridge.pribus_num, 0, init);   //参数2:0,0,1
		}
        	_setup_pcibuses(init);
	}
}

这个函数我把它分成3个部分吧。分别就是最外层的3个if

2.1 第一个if 获得环境变量pciverbose,这个就是控制pci打印信息的。

如果不想有打印信息,设置pciverbose 为0,如果需要调试信息,设置大于0,默认值好像是5.

 不配置的时候,环境变量默认就是5,这时候在pmon启动阶段是会打印详细信息的

 这样的好处就是不用重新编译程序,就可以控制pci的信息,挺好的。修改环境变量的值就好。

2.2  第二个if ,条件为1,必须执行

好像写init似乎也没毛病。呵呵!!,但是里面有一个init的判断,小于1,返回。

 这个块里面,两条打印语句PCIH,

一个函数 _pci_hwinit,参数,1,两个全局变量的地址。

 结构体也简单,两个32位的无符号数。(先放这吧,可能后面要用到)

一个全局变量,pci_roots = init ,就是1了。指的是cpu出来有pci总线的条数。

2.3 _pci_hwinit 函数

这个函数非常奇怪的是没有使用传进来的两个参数:iot和memt

这个函数初始化了struct pci_deice和struct pci_bus两个这样结构。

同时这两个结构赋值给全局指针变量_pci_head 和 _pci_bushead,这也分别是这两个链表的第一个元素。全局变量就是链表的头指针。

还有几个全局变量:bus_dmamap_tag 似乎是DMA相关的一些操作的集合。(函数指针)

                                bus_dmamap_tag._dmamap_offs = 0;  //可能是指偏移地址。

                                pci_probe_only 由环境变量设置,环境变量无设置时为0

                                _pci_bus[]; struct pci_deice指针数组,大小16个元素。 这里已经使用了0这个下标元素

                                _max_pci_bus : 指定_pci_bus的下标,这里由0增加为1.

                                /*set pci base0 address and window size*/
                                   pci_local_mem_pci_base = 0x0; //似乎是个偏移地址??

/****************************/
/*initial PCI               */
/****************************/

int
_pci_hwinit(initialise, iot, memt)
	int initialise;
	bus_space_tag_t iot;
	bus_space_tag_t memt;
{
	/*pcireg_t stat;*/
	struct pci_device *pd;
	struct pci_bus *pb;
	int newcfg=0;
	char *env;
	SBD_DISPLAY ("HW-0", 0);
	if(getenv("newcfg"))newcfg=1;  //根据环境变量取值

	if ((env = getenv("pci_probe_only")))   //环境变量取值
	  pci_probe_only = strtoul(env, 0, 0);

	if (!initialise) {   //参数为1,不成立。
		return(0);
	}
	SBD_DISPLAY ("HW-1", 0);

	/*
	 *  Allocate and initialize PCI bus heads.
	 */

	/*
	 * PCI Bus 0
	 */
	pd = pmalloc(sizeof(struct pci_device)); //分配空间
	pb = pmalloc(sizeof(struct pci_bus));    //分配空间
	if(pd == NULL || pb == NULL) {
		printf("pci: can't alloc memory. pci not initialized\n");
		return(-1);
	}
	SBD_DISPLAY ("HW-2", 0);
	//对结构体进行初始化,这是pd,device设备
	pd->pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;
	pd->pa.pa_iot = pmalloc(sizeof(bus_space_tag_t));
	pd->pa.pa_iot->bus_reverse = 1;
	pd->pa.pa_iot->bus_base = BONITO_PCIIO_BASE_VA;    //0xbfd0,0000,所有的io都在这1M的空间内
	pd->pa.pa_memt = pmalloc(sizeof(bus_space_tag_t));
	pd->pa.pa_memt->bus_reverse = 1;
	pd->pa.pa_memt->bus_base = 0xc0000000;
	pd->pa.pa_dmat = &bus_dmamap_tag;
	pd->bridge.secbus = pb;
	_pci_head = pd;           //全局变量保存这个结构体的首地址
	SBD_DISPLAY ("HW-3", 0);

	if(pci_probe_only)
	{
		pb->minpcimemaddr  = 0x40100000;
		pb->nextpcimemaddr = 0x80000000;
	}
	else
	{
		pb->minpcimemaddr  = 0x10000000;
		pb->nextpcimemaddr = 0x18000000;
	}

	pb->minpciioaddr   = PCI_IO_SPACE_BASE+0x0004000;
	pb->nextpciioaddr  = PCI_IO_SPACE_BASE+ BONITO_PCIIO_SIZE; // 0 + 0x0200_0000
	pb->pci_mem_base   = BONITO_PCILO_BASE_VA;
	pb->pci_io_base    = BONITO_PCIIO_BASE_VA;
#if 0 //low pci mem base
	pd->pa.pa_memt->bus_base = 0xa0000000;
	pb->minpcimemaddr  = 0x10000000;
	pb->nextpcimemaddr = 0x17ffffff;
	pb->minpciioaddr   = 0x18000000;
	pb->nextpciioaddr  = 0x1800ffff;
	pb->pci_mem_base   = 0x10000000;
	pb->pci_io_base    = 0x18100000;
#endif
	pb->max_lat = 255;
	pb->fast_b2b = 1;
	pb->prefetch = 1;
	pb->bandwidth = 4000000;
	pb->ndev = 1;
	_pci_bushead = pb;
	_pci_bus[_max_pci_bus++] = pd;

	SBD_DISPLAY ("HW-5", 0);
	
	bus_dmamap_tag._dmamap_offs = 0;

	/*set pci base0 address and window size*/
	pci_local_mem_pci_base = 0x0;

	return(1);
}

宏定义 PCI_IO_SPACE_BASE 为0

BONITO_PCILO_BASE_VA 为0xb000,0000

BONITO_PCIIO_BASE_VA 为0xbfd0,0000

2.4 第三个if块,这里调用的函数比较复杂,到下次的内容再分析函数吧。

 因为pci_roots = 1所以for循环执行了一次。即i=0

_pci_scan_dev 。这个函数的功能就是枚举pci总线上的所有的设备(包括pci桥片)。

特别说明一下,需要了解一些pci的基本知识。我之前也是没接触过,现在大概知道了一点概念,所以我分析的也不一定正确。请各位多多指教。

第一次调用的时候,第一个参数就是刚刚初始化的struct pci_bus的头指针,第二个参数总线号,现在是0,第三个参数0,第四个参数1.

 这里对device做循环。

_pci_query_dev 还需要进一步分析。

_setup_pcibuses(init):这个函数功能是分配带宽并处理空间申请。(后面再看吧。挖个坑先)。

2.5 _pci_query_dev函数

static void
_pci_query_dev (struct pci_device *dev, int bus, int device, int initialise)
{
	pcitag_t tag;
	pcireg_t id;
	pcireg_t misc;

	tag = _pci_make_tag(bus, device, 0);
	if (!_pci_canscan (tag))
		return;

	if (_pciverbose >= 2)
		_pci_bdfprintf (bus, device, -1, "probe...");
#if defined(LOONGSON_2G5536)||defined(LOONGSON_2G1A) || defined(LOONGSON_2F1A) || defined(LOONGSON_2K)
	id = _pci_conf_read(tag, PCI_ID_REG);   //读id寄存器

	if (_pciverbose >= 2) {
		PRINTF ("2222completed\n");   //打印这里
	}
#else  //else 不执行
#ifdef CONFIG_LSI_9260
	if ((bus == 2 && device == 0) ||(bus == 3 && device == 0) ||
			(bus == 4 && device == 0))
			delay(2000000);
#endif
	delay(1000);  //fix that the correct id sometimes can not read;
	id = _pci_conf_read(tag, PCI_ID_REG);

	if (_pciverbose >= 2) {
		PRINTF ("completed\n");
	}

	if((bus == 2) && (device ==0))
	{
		if(PCI_VENDOR(id) != 0x1002 && (PCI_PRODUCT(id) != 0x9615))
		  printf("pcie-slot device: vendor:%x product:%x\n",PCI_VENDOR(id),PCI_PRODUCT(id));
	}

#if defined(USE_BMC)
        if (PCI_VENDOR(id) == 0x1a03 && PCI_PRODUCT(id) == 0x2000)
        {
                printf("AST2050's VGA discover !!!!!!!!!!!!!!\n");
        }
#endif
#endif    //else 不执行
	if (id == 0 || id == 0xffffffff) {    //没有读到id就返回了。说明没有挂载设备
		return;
	}
	misc = _pci_conf_read(tag, PCI_BHLC_REG);   //读misc寄存器(地址0xc)

	if (PCI_HDRTYPE_MULTIFN(misc)) {   //根据读取的值判断是否为多功能设备
		int function;
		for (function = 0; function < 8; function++) {   //从0开始枚举
			tag = _pci_make_tag(bus, device, function);
			id = _pci_conf_read(tag, PCI_ID_REG);
			if (id == 0 || id == 0xffffffff) {
				//return;
				continue;
			}
			_pci_query_dev_func (dev, tag, initialise);   //初始化结构体,并加入到列表中
		}
	}
	else {   //不是多功能设备
		_pci_query_dev_func (dev, tag, initialise);
	}
}

#else ....#endif  那一段是没有执行的,所以实际代码也不多。

_pci_query_dev_func 函数是关键。

2.6 _pci_query_dev_func 函数

这个函数本身可以递归了。

参数:dev 一般就是 pci_device 的结构体指针了。第一次调用的时候是那个链表的头部_pci_head.

         tag 由bus,device,func组合的一个数字

        initialise  1 。

2.6.1 根据读取设备的数据,初始化结构体(struct pci_device)。

	printf("03-16 dev = %p tag = %#x\n",dev,tag);
    class = _pci_conf_read(tag, PCI_CLASS_REG);   //读取class寄存器(0x8),用于区分是桥还是设备
    id = _pci_conf_read(tag, PCI_ID_REG);  //读出id,包含厂家信息

    if (_pciverbose) {   //打印信息
        int supported;
        char devinfo[256];
        _pci_devinfo(id, class, &supported, devinfo);
        _pci_tagprintf (tag, "%s\n", devinfo);
    }

    pd = pmalloc(sizeof(struct pci_device));
    if(pd == NULL) {
        PRINTF ("pci: can't alloc memory for device\n");
        return;
    }

    _pci_break_tag (tag, &bus, &device, &function);  //把tag分解为bus,device,function
	//printf("2022-03-16 bus = %d device = %d func = %d\n",bus, device, function);
    pd->pa.pa_bus = bus;    //结构体初始化,设备所在的总线号
    pd->pa.pa_device = device;   //设备所在的设备号
    pd->pa.pa_function = function;   //设备所在的功能号
    pd->pa.pa_tag = tag;    //tag也一起保存起来
    pd->pa.pa_id = id;     //id也保存
    pd->pa.pa_class = class;  //class也保存
    pd->pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;   //使能标志
    pd->pa.pa_iot = dev->pa.pa_iot;  //指向同一个位置,
    pd->pa.pa_memt = dev->pa.pa_memt; //指向同一个位置,
    pd->pa.pa_dmat = dev->pa.pa_dmat; //指向同一个位置,
    pd->parent = dev;	//父节点
    pd->pcibus = dev->bridge.secbus;  //指向同一个位置,头节点是指向bus0,
    pb = pd->pcibus;   //bus指针 ,头节点是指向bus0
    _pci_device_insert(dev, pd);   //加入到链表中

    /*
     * Calculated Interrupt routing
     */
    _pci_setupIntRouting(pd);   //计算中断路由。。。暂时放一边

    /*
     *  Shut off device if we initialize from non reset.
     */
    stat = _pci_conf_read(tag, PCI_COMMAND_STATUS_REG);  //读命令寄存器(0x4)
    stat &= ~(PCI_COMMAND_MASTER_ENABLE |
          PCI_COMMAND_IO_ENABLE |
          PCI_COMMAND_MEM_ENABLE);    //去掉某些位(bit0,1,2)。
#ifdef USE_SM502_UART0
    if(device!=14)
    {
#endif
        _pci_conf_write(tag, PCI_COMMAND_STATUS_REG, stat);    //写回
#ifdef USE_SM502_UART0
    }
#endif
    pd->stat = stat;

    /* do all devices support fast back-to-back */   //以下根据命令寄存器的值进一步初始化,注意设置的是pb
    if ((stat & PCI_STATUS_BACKTOBACK_SUPPORT) == 0) {
        pb->fast_b2b = 0;  /* no, sorry */  //连续传输,一个设备不支持,总线就不支持
    }

    /* do all devices run at 66 MHz */
    if ((stat & PCI_STATUS_66MHZ_SUPPORT) == 0) {
        pb->freq66 = 0;   /* no, sorry */  //一个设备不支持,总线就不支持
    }

    /* find slowest devsel */
    x = stat & PCI_STATUS_DEVSEL_MASK;
    if (x > pb->devsel) {
        pb->devsel = x;  //x:0表示快速,1表示中等速度,2表示慢速设备
    }

    /* Funny looking code which deals with any 32bit read only cfg... */  //根据寄存器的值,设置结构体
    bparam = _pci_conf_read(tag, (PCI_MINGNT & ~0x3));
    pd->min_gnt = 0xff & (bparam >> ((PCI_MINGNT & 3) * 8));
    bparam = _pci_conf_read(tag, (PCI_MAXLAT & ~0x3));
    pd->max_lat = 0xff & (bparam >> ((PCI_MAXLAT & 3) * 8));

    if (pd->min_gnt != 0 || pd->max_lat != 0) {
        /* find largest minimum grant time of all devices */
        if (pd->min_gnt != 0 && pd->min_gnt > pb->min_gnt) {
            pb->min_gnt = pd->min_gnt;
        }
    
        /* find smallest maximum latency time of all devices */
        if (pd->max_lat != 0 && pd->max_lat < pb->max_lat) {
                pb->max_lat = pd->max_lat;
        }
    
        /* subtract our min on-bus time per second from bus bandwidth */
        if (initialise) {
            pb->bandwidth -= pd->min_gnt * 4000000 / (pd->min_gnt + pd->max_lat);
        }
    }

    /* Map interrupt to interrupt line (software function only) */   //读取寄存器中中断相关设置
    bparam = _pci_conf_read(tag, PCI_INTERRUPT_REG);
    bparam &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
    bparam |= ((_pci_getIntRouting(pd) & 0xff) << PCI_INTERRUPT_LINE_SHIFT);
    _pci_conf_write(tag, PCI_INTERRUPT_REG, bparam);

2.6.2 对pci桥的特殊处理,还有IDE硬盘的处理

IDE硬盘处理就不继续向后执行了,但是桥的话,还将继续初始化。

    /*
     * Check to see if device is a PCI Bridge
     */
    if (PCI_ISCLASS(class, PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_PCI)) {
        struct pci_device *pcidev;
        struct pci_win *pm_mem = NULL;
        struct pci_win *pm_io = NULL;
        struct pci_win *pm;
        pcireg_t tmp;
        isbridge = 1;

		printf("2022-03-15 device is a PCI Bridge\n");

        pd->bridge.pribus_num = bus;
#if 1
	_pci_nbus = pci_get_busno(pd, _pci_nbus);    //获得pci总线号,这里不是连续的
	pd->bridge.secbus_num  = _pci_nbus;
#else
        pd->bridge.secbus_num =  ++_pci_nbus;
#endif
        /* Set it temperary to same as secondary bus number */
        pd->bridge.subbus_num =  pd->bridge.secbus_num;  //桥,设置所在的总线号

        tmp = _pci_conf_read(tag, PCI_PRIBUS_1);  //设置桥的编号信息
        tmp &= 0xff000000;
        tmp |= pd->bridge.pribus_num;
        tmp |= pd->bridge.secbus_num << 8;
        tmp |= pd->bridge.subbus_num << 16;
        _pci_conf_write(tag, PCI_PRIBUS_1, tmp);

        /* Update sub bus number */
        for(pcidev = dev; pcidev != NULL; pcidev = pcidev->parent) {    //把自己的总线号更新到父桥的最大总线号
            //printf("pcidev = 0x%x\n", pcidev);
            pcidev->bridge.subbus_num = pd->bridge.secbus_num;
            tmp = _pci_conf_read(pcidev->pa.pa_tag, PCI_PRIBUS_1);
            tmp &= 0xff00ffff;
            tmp |= pd->bridge.secbus_num << 16;
	    if(pcidev->parent)
		    _pci_conf_write(pcidev->pa.pa_tag, PCI_PRIBUS_1, tmp);
        }

        pd->bridge.secbus = pmalloc(sizeof(struct pci_bus));   //新的总线结构体
        if(pd->bridge.secbus == NULL) {
            PRINTF ("pci: can't alloc memory for new pci bus\n");
            return;
        }
		//初始化新的结构体
        pd->bridge.secbus->max_lat = 255;
        pd->bridge.secbus->fast_b2b = 1;
        pd->bridge.secbus->prefetch = 1;
        pd->bridge.secbus->freq66 = 1;
        pd->bridge.secbus->bandwidth = 4000000;    //64M
        pd->bridge.secbus->ndev = 1;
        pd->bridge.secbus->bus = pd->bridge.secbus_num;

        _pci_bus_insert(pd->bridge.secbus);   //插入到总线链表末尾
        {
            extern  struct pci_device *_pci_bus[];
            extern int _max_pci_bus;
            _pci_bus[_max_pci_bus++] = pd;  //数组增加,下标值加1
        }

		set_pcie_port_type(pd);   //....

        /* Scan secondary bus of the bridge */
        _pci_scan_dev(pd, pd->bridge.secbus_num, 0, initialise);  //开始递归搜索

        /*
         * Sum up the address space needed by secondary side of bridge
         */
        if(pm_io == NULL) {
            pm_io = pmalloc(sizeof(struct pci_win));
            if(pm_io == NULL) {
                PRINTF ("pci: can't alloc memory for pci memory window\n");
                return;
            }
            pm_io->device = pd;
            pm_io->reg = PCI_IOBASEL_1;
            pm_io->flags = PCI_MAPREG_TYPE_IO;
        }

        if(pm_mem == NULL) {
            pm_mem = pmalloc(sizeof(struct pci_win));
            if(pm_mem == NULL) {
                PRINTF ("pci: can't alloc memory for pci memory window\n");
                return;
            }

            pm_mem->device = pd;
            pm_mem->reg = PCI_MEMBASE_1;
            pm_mem->flags = PCI_MAPREG_MEM_TYPE_32BIT;
        }

        /* Sum up I/O Space needed */
        {
            int max=0;
            for(pm = pd->bridge.iospace; pm != NULL; pm = pm->next) {
                if(max < pm->align)
                    max = pm->align;
                pm_io->size += pm->size;
            }
            pm_io->size = (pm_io->size + max -1) & ~(max-1);
            if(max < 0x1000) max = 0x1000;
            pd->bridge.io_mask = ~(max-1);
            pm_io->align = max;

        }
        /* Sum up Memory Space needed */
        {
            int max = 0;
            for(pm = pd->bridge.memspace; pm != NULL; pm = pm->next) {
                    if(max < pm->align)
                        max = pm->align;
                pm_mem->size += pm->size;
            }
            pm_mem->size = (pm_mem->size + max -1) & ~(max-1);
            if(max<0x100000) max = 0x100000;
            pd->bridge.mem_mask = ~(max-1);
            pm_mem->align = max;
        }

        if(pm_io) {
            /* Round to minimum granularity requierd for a bridge */
            pm_io->size = _pci_roundup(pm_io->size, 0x1000);
            _insertsort_window(&pd->parent->bridge.iospace, pm_io);
        }
        if(pm_mem) {
            /* Round to minimum granularity requierd for a bridge */
            pm_mem->size = _pci_roundup(pm_mem->size, 0x100000);
            _insertsort_window(&pd->parent->bridge.memspace,pm_mem);
        }
    }
    else if (PCI_ISCLASS(class, PCI_CLASS_MASS_STORAGE, PCI_SUBCLASS_MASS_STORAGE_IDE) &&
        dev->bridge.secbus->minpciioaddr == 0) {
        /*
         * There is no need to setup memory regions for IDE storage devices
         * but only if PCI/ISA I/O space is accessables
         */
        return;

    } 

2.6.3 继续桥和设备的初始化部分,根据bar计算存储类型和空间

   //set BAR for this dev
    {
        int skipnext = 0;
#if defined(LOONGSON_2K) || defined(LS7A)
	/* skip bus 0, device 0, function 0 */
	if (pd->pa.pa_tag != 0 && !PCI_ISCLASS(class, PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_PCI)) {
		pcie_write_mps(pd);
		pcie_write_mrrs(pd);
	}
#endif
        for (reg = PCI_MAPREG_START; reg < (isbridge ? PCI_MAPREG_PPB_END : PCI_MAPREG_END); reg += 4) {
            struct pci_win *pm;

            if (skipnext) {   //对于64位的memspace ,跳过一个寄存器
                skipnext = 0;
                continue;
            }

            old = _pci_conf_read(tag, reg);  //for循环内,reg不断变化,返回的值也是不同的
            _pci_conf_write(tag, reg, 0xfffffffe);
            mask = _pci_conf_read(tag, reg);
            _pci_conf_write(tag, reg, old);   //返回的mask用来判断分配什么类型空间。

			//有些寄存器mask为0,表示不需要分配,直接跳过
            if (mask == 0 || mask == 0xffffffff) {
                continue;
            }
			
            if (_pciverbose >= 3) {
                _pci_tagprintf (tag, "reg 0x%x = 0x%x\n", reg, mask);
            }

            if (PCI_MAPREG_TYPE(mask) == PCI_MAPREG_TYPE_IO) {   //最低位为1,表示io空间
                //for IO bar, device is free to hardwire high 16 bits to zero, here we mask high 16 bits to all 1
                //for convenience of size calculation
                mask |= 0xffff0000;
                pm = pmalloc(sizeof(struct pci_win));
                if(pm == NULL) {
                    PRINTF ("pci: can't alloc memory for pci memory window\n");
                    return;
                }

                pm->device = pd;
                pm->reg = reg;   //起始地址?
                pm->flags = PCI_MAPREG_TYPE_IO;
                pm->size = -(PCI_MAPREG_IO_ADDR(mask));
                pm->align = pm->size;
                _insertsort_window(&pd->parent->bridge.iospace, pm);
				printf("03-16 iospace size = 0x%x reg = 0x%x\n",pm->size,reg);
            }
            else {   //内存空间
                switch (PCI_MAPREG_MEM_TYPE(mask)) {
                case PCI_MAPREG_MEM_TYPE_32BIT:
                case PCI_MAPREG_MEM_TYPE_32BIT_1M:
                    break;
                case PCI_MAPREG_MEM_TYPE_64BIT:
                    _pci_conf_write(tag, reg + 4, 0x0);
					printf("03-16 PCI_MAPREG_MEM_TYPE_64BIT\n");
                    skipnext = 1;  //两个32位当一个,接下的那个32位也用了
                    break;
                default:
                    _pci_tagprintf (tag, "reserved mapping type 0x%x\n",
                          PCI_MAPREG_MEM_TYPE(mask));
                    continue;
                }

                if  (!PCI_MAPREG_MEM_PREFETCHABLE(mask)) {
                    pb->prefetch = 0;
                }

                pm = pmalloc(sizeof(struct pci_win));
                if(pm == NULL) {
                    PRINTF ("pci: can't alloc memory for pci memory window\n");
                    return;
                }

                pm->device = pd;
                pm->reg = reg;
                pm->flags = PCI_MAPREG_MEM_TYPE_32BIT;
                pm->size = -(PCI_MAPREG_MEM_ADDR(mask));
                pm->align = pm->size;
                _insertsort_window(&pd->parent->bridge.memspace, pm);  //插入到有序的链表中
				printf("03-16 memspace size = 0x%x reg = 0x%x\n",pm->size,reg);
            }
        }

		printf("03-16 end for\n");
		{  //扩展存储空间,一般没有使用到。
            /* Finally check for Expansion ROM */
            reg = isbridge ? PCI_MAPREG_PPB_ROM : PCI_MAPREG_ROM;
            old = _pci_conf_read(tag, reg);
            _pci_conf_write(tag, reg, 0xfffffffe);
            mask = _pci_conf_read(tag, reg);
            _pci_conf_write(tag, reg, old);

			printf("03-16-2 reg 0x%x = 0x%x\n", reg, mask);
            if (mask != 0 && mask != 0xffffffff) {
                struct pci_win *pm;
				
                if (_pciverbose >= 3) {
                    _pci_tagprintf (tag, "reg 0x%x = 0x%x\n", reg, mask);
                }

                pm = pmalloc(sizeof(struct pci_win));
                if(pm == NULL) {
                    PRINTF ("pci: can't alloc memory for pci memory window\n");
                    return;
                }
                pm->device = pd;
                pm->reg = reg;
                pm->size = -(PCI_MAPREG_ROM_ADDR(mask));
                pm->align = pm->size;   //记录了空间的大小
                _insertsort_window(&pd->parent->bridge.memspace, pm);   //插入到有序的链表中
            }
        }
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大智兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值