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

📄 pmc551.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        start_addr_lowbits = to & PMC551_ADDR_LOW_MASK;        end_addr_lowbits = end & PMC551_ADDR_LOW_MASK;        /* Only rewrite the first value if it doesn't match our current           values.  Most operations are on the same page as the previous           value, so this is a pretty good optimization. */        if (priv->curr_mem_map0_val !=                        (priv->mem_map0_base_val | start_addr_highbits)) {                priv->curr_mem_map0_val = (priv->mem_map0_base_val                                           | start_addr_highbits);                pci_write_config_dword ( priv->dev,                                         PMC551_PCI_MEM_MAP0,                                         priv->curr_mem_map0_val);        }        if (start_addr_highbits == end_addr_highbits) {                /* The whole thing fits within one access, so just one shot                   will do it. */                memcpy(priv->start + start_addr_lowbits,                       copyfrom,                       len);                copyfrom += len;        } else {                /* We have to do multiple writes to get all the data                   written. */                memcpy(priv->start + start_addr_lowbits,                       copyfrom,                       priv->aperture_size - start_addr_lowbits);                copyfrom += priv->aperture_size - start_addr_lowbits;                start_addr_highbits += priv->aperture_size;                while (start_addr_highbits != end_addr_highbits) {                        pci_write_config_dword ( priv->dev,                                                 PMC551_PCI_MEM_MAP0,                                                 (priv->mem_map0_base_val                                                  | start_addr_highbits));                        memcpy(priv->start,                               copyfrom,                               priv->aperture_size);                        copyfrom += priv->aperture_size;                        start_addr_highbits += priv->aperture_size;                        if (start_addr_highbits >= mtd->size) {                                /* Make sure we have the right value here. */                                priv->curr_mem_map0_val                                = (priv->mem_map0_base_val                                   | start_addr_highbits);                                goto out;                        }                }                priv->curr_mem_map0_val = (priv->mem_map0_base_val                                           | start_addr_highbits);                pci_write_config_dword ( priv->dev,                                         PMC551_PCI_MEM_MAP0,                                         priv->curr_mem_map0_val);                memcpy(priv->start,                       copyfrom,                       end_addr_lowbits);                copyfrom += end_addr_lowbits;        }out:        *retlen = copyfrom - buf;        return 0;}/* * Fixup routines for the V370PDC * PCI device ID 0x020011b0 * * This function basicly kick starts the DRAM oboard the card and gets it * ready to be used.  Before this is done the device reads VERY erratic, so * much that it can crash the Linux 2.2.x series kernels when a user cat's * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL * register.  FIXME: stop spinning on registers .. must implement a timeout * mechanism * returns the size of the memory region found. */static u32 fixup_pmc551 (struct pci_dev *dev){#ifdef CONFIG_MTD_PMC551_BUGFIX        u32 dram_data;#endif        u32 size, dcmd, cfg, dtmp;        u16 cmd, tmp, i;	u8 bcmd, counter;        /* Sanity Check */        if(!dev) {                return -ENODEV;        }	/*	 * Attempt to reset the card	 * FIXME: Stop Spinning registers	 */	counter=0;	/* unlock registers */	pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 );	/* read in old data */	pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd );	/* bang the reset line up and down for a few */	for(i=0;i<10;i++) {		counter=0;		bcmd &= ~0x80;		while(counter++ < 100) {			pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);		}		counter=0;		bcmd |= 0x80;		while(counter++ < 100) {			pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);		}	}	bcmd |= (0x40|0x20);	pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd);        /* 	 * Take care and turn off the memory on the device while we	 * tweak the configurations	 */        pci_read_config_word(dev, PCI_COMMAND, &cmd);        tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY);        pci_write_config_word(dev, PCI_COMMAND, tmp);	/*	 * Disable existing aperture before probing memory size	 */	pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd);        dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN);	pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp);	/*	 * Grab old BAR0 config so that we can figure out memory size	 * This is another bit of kludge going on.  The reason for the	 * redundancy is I am hoping to retain the original configuration	 * previously assigned to the card by the BIOS or some previous 	 * fixup routine in the kernel.  So we read the old config into cfg,	 * then write all 1's to the memory space, read back the result into	 * "size", and then write back all the old config.	 */	pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg );#ifndef CONFIG_MTD_PMC551_BUGFIX	pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 );	pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size );	pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );	size=~(size&PCI_BASE_ADDRESS_MEM_MASK)+1;#else        /*         * Get the size of the memory by reading all the DRAM size values         * and adding them up.         *         * KLUDGE ALERT: the boards we are using have invalid column and         * row mux values.  We fix them here, but this will break other         * memory configurations.         */        pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data);        size = PMC551_DRAM_BLK_GET_SIZE(dram_data);        dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);        dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);        pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data);        pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data);        size += PMC551_DRAM_BLK_GET_SIZE(dram_data);        dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);        dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);        pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data);        pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data);        size += PMC551_DRAM_BLK_GET_SIZE(dram_data);        dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);        dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);        pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data);        pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data);        size += PMC551_DRAM_BLK_GET_SIZE(dram_data);        dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5);        dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9);        pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data);        /*         * Oops .. something went wrong         */        if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) {                return -ENODEV;        }#endif /* CONFIG_MTD_PMC551_BUGFIX */	if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {                return -ENODEV;	}        /*         * Precharge Dram         */        pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 );        pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf );        /*         * Wait untill command has gone through         * FIXME: register spinning issue         */        do {	pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd );		if(counter++ > 100)break;        } while ( (PCI_COMMAND_IO) & cmd );        /*	 * Turn on auto refresh 	 * The loop is taken directly from Ramix's example code.  I assume that	 * this must be held high for some duration of time, but I can find no	 * documentation refrencing the reasons why.	 *          */        for ( i = 1; i<=8 ; i++) {                pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df);                /*                 * Make certain command has gone through                 * FIXME: register spinning issue                 */		counter=0;                do {	pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd);			if(counter++ > 100)break;                } while ( (PCI_COMMAND_IO) & cmd );        }        pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020);        pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff);        /*         * Wait until command completes         * FIXME: register spinning issue         */	counter=0;        do {	pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd);		if(counter++ > 100)break;        } while ( (PCI_COMMAND_IO) & cmd );        pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd);        dcmd |= 0x02000000;        pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd);        /*         * Check to make certain fast back-to-back, if not         * then set it so         */        pci_read_config_word( dev, PCI_STATUS, &cmd);        if((cmd&PCI_COMMAND_FAST_BACK) == 0) {                cmd |= PCI_COMMAND_FAST_BACK;                pci_write_config_word( dev, PCI_STATUS, cmd);        }        /*         * Check to make certain the DEVSEL is set correctly, this device         * has a tendancy to assert DEVSEL and TRDY when a write is performed         * to the memory when memory is read-only         */        if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) {                cmd &= ~PCI_STATUS_DEVSEL_MASK;                pci_write_config_word( dev, PCI_STATUS, cmd );        }        /*         * Set to be prefetchable and put everything back based on old cfg.	 * it's possible that the reset of the V370PDC nuked the original	 * settup         */        cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH;	pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg );        /*         * Turn PCI memory and I/O bus access back on         */        pci_write_config_word( dev, PCI_COMMAND,                               PCI_COMMAND_MEMORY | PCI_COMMAND_IO );#ifdef CONFIG_MTD_PMC551_DEBUG        /*         * Some screen fun         */        printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%lx\n",	       (size<1024)?size:(size<1048576)?size/1024:size/1024/1024,               (size<1024)?'B':(size<1048576)?'K':'M',	       size, ((dcmd&(0x1<<3)) == 0)?"non-":"",               PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK );        /*         * Check to see the state of the memory         */        pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd );        printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n"			  "pmc551: DRAM_BLK0 Size: %d at %d\n"

⌨️ 快捷键说明

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