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

📄 pcilow.c

📁 PCI总线在DOS操作系统下的驱动程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>

#include "typedef.h"
#include "low.h"
#include "pci.h"

extern struct resource ioport_resource;
extern struct resource iomem_resource;

#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \
	(0x80000000 | ((unsigned long)bus * 65536L) | (((unsigned long)dev) * 2048L) \
	| (((unsigned long)fn) * 256L) | (reg & ~3))

extern int pci_bios_present;
	
extern unsigned short pci_probe;
	
extern short pcibios_last_bus;
extern struct pci_bus *pci_root_bus;
extern struct pci_ops *pci_root_ops;	

extern long (*pci_config_read)(long seg, long bus, long dev, long fn, long reg, long len, u32 *value);
extern long (*pci_config_write)(long seg, long bus, long dev, long fn, long reg, long len, u32 value);

long pci_conf1_read (long seg, long bus, long dev, long fn, long reg, long len, u32 *value)
{
	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
		return -EINVAL;

	outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);

	switch (len) {
	case 1:
		*value = inb(0xCFC + (unsigned short)(reg & 3));
		break;
	case 2:
		*value = inw(0xCFC + (unsigned short)(reg & 2));
		break;
	case 4:
		*value = inl(0xCFC);
		break;
	}

	return 0;
}

long pci_conf1_write (long seg, long bus, long dev, long fn, long reg, long len, u32 value)
{
	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 
		return -EINVAL;

	outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8);

	switch (len) {
	case 1:
		outb((u8)value, 0xCFC + (unsigned short)(reg & 3));
		break;
	case 2:
		outw((u16)value, 0xCFC + (unsigned short)(reg & 2));
		break;
	case 4:
		outl((u32)value, 0xCFC);
		break;
	}

	return 0;
}

long pci_conf1_read_config_byte(struct pci_dev *dev, long where, u8 *value)
{
	int result; 
	u32 data;

	if (!value) 
		return -EINVAL;

	result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 1, &data);

	*value = (u8)data;

	return result;
}

long pci_conf1_read_config_word(struct pci_dev *dev, long where, u16 *value)
{
	int result; 
	u32 data;

	if (!value) 
		return -EINVAL;

	result = pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 2, &data);

	*value = (u16)data;

	return result;
}

long pci_conf1_read_config_dword(struct pci_dev *dev, long where, u32 *value)
{
	if (!value) 
		return -EINVAL;

	return pci_conf1_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 4, value);
}

long pci_conf1_write_config_byte(struct pci_dev *dev, long where, u8 value)
{
	return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 1, value);
}

long pci_conf1_write_config_word(struct pci_dev *dev, long where, u16 value)
{
	return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 2, value);
}

long pci_conf1_write_config_dword(struct pci_dev *dev, long where, u32 value)
{
	return pci_conf1_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 4, value);
}

extern struct pci_ops pci_direct_conf1;

#define PCI_CONF2_ADDRESS(dev, reg)	(u16)(0xC000 | (dev << 8) | reg)

long pci_conf2_read (long seg, long bus, long dev, long fn, long reg, long len, u32 *value)
{
	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
		return -EINVAL;

	if (dev & 0x10) 
		return DEVICE_NOT_FOUND;

	outb((u8)(0xF0 | (fn << 1)), 0xCF8);
	outb((u8)bus, 0xCFA);

	switch (len) {
	case 1:
		*value = inb(PCI_CONF2_ADDRESS(dev, reg));
		break;
	case 2:
		*value = inw(PCI_CONF2_ADDRESS(dev, reg));
		break;
	case 4:
		*value = inl(PCI_CONF2_ADDRESS(dev, reg));
		break;
	}

	outb (0, 0xCF8);

	return 0;
}

long pci_conf2_write (long seg, long bus, long dev, long fn, long reg, long len, u32 value)
{
	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 
		return -EINVAL;

	if (dev & 0x10) 
		return DEVICE_NOT_FOUND;

	outb((u8)(0xF0 | (fn << 1)), 0xCF8);
	outb((u8)bus, 0xCFA);

	switch (len) {
	case 1:
		outb ((u8)value, PCI_CONF2_ADDRESS(dev, reg));
		break;
	case 2:
		outw ((u16)value, PCI_CONF2_ADDRESS(dev, reg));
		break;
	case 4:
		outl ((u32)value, PCI_CONF2_ADDRESS(dev, reg));
		break;
	}

	outb (0, 0xCF8);    

	return 0;
}

long pci_conf2_read_config_byte(struct pci_dev *dev, long where, u8 *value)
{
	int result; 
	u32 data;
	result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 1, &data);
	*value = (u8)data;
	return result;
}

long pci_conf2_read_config_word(struct pci_dev *dev, long where, u16 *value)
{
	int result; 
	u32 data;
	result = pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 2, &data);
	*value = (u16)data;
	return result;
}

long pci_conf2_read_config_dword(struct pci_dev *dev, long where, u32 *value)
{
	return pci_conf2_read(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 4, value);
}

long pci_conf2_write_config_byte(struct pci_dev *dev, long where, u8 value)
{
	return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 1, value);
}

long pci_conf2_write_config_word(struct pci_dev *dev, long where, u16 value)
{
	return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 2, value);
}

long pci_conf2_write_config_dword(struct pci_dev *dev, long where, u32 value)
{
	return pci_conf2_write(0, dev->bus->number, PCI_SLOT(dev->devfn), 
		PCI_FUNC(dev->devfn), where, 4, value);
}

extern struct pci_ops pci_direct_conf2;

long pci_bios_read (long seg, long bus, long dev, long fn, long reg, long len, 
	u32 *value)
{
	unsigned short result = 0;
	unsigned long temp = ((bus << 8) | (dev << 3) | fn);

	if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
		return -EINVAL;
		
	_asm push es
	_asm push si
	
	switch (len)
	{
		case 1:
			_asm les si,value
			_asm mov bx,temp
			_asm mov di,reg
			_asm mov ah,PCI_FUNCTION_ID
			_asm mov al,READ_CONFIG_BYTE
			_asm int 1ah
			_asm mov result,ax
			_asm jc read_fail1
			_asm cmp ah,SUCCESSFUL
			_asm jnz read_fail1
			_asm mov es:[si],cl

		read_fail1:
			
			break;
		case 2:
			_asm les si,value
			_asm mov bx,temp
			_asm mov di,reg
			_asm mov ah,PCI_FUNCTION_ID
			_asm mov al,READ_CONFIG_WORD
			_asm int 1ah
			_asm mov result,ax
			_asm jc read_fail2
			_asm cmp ah,SUCCESSFUL
			_asm jnz read_fail2
			_asm mov es:[si],cx

		read_fail2:
			
			break;
			
		case 4:
			_asm les si,value
			_asm mov bx,temp
			_asm mov di,reg
			_asm mov ah,PCI_FUNCTION_ID
			_asm mov al,READ_CONFIG_WORD
			_asm int 1ah
			_asm mov result,ax
			_asm jc read_fail3
			_asm cmp ah,SUCCESSFUL
			_asm jnz read_fail3
			_asm mov es:[si],cx
			_asm mov ah,PCI_FUNCTION_ID
			_asm mov al,READ_CONFIG_WORD
			_asm add di,2
			_asm int 1ah
			_asm mov result,ax
			_asm jc read_fail3
			_asm cmp ah,SUCCESSFUL
			_asm jnz read_fail3
			_asm mov es:[si + 2],cx

		read_fail3:

			break;
									
	};

	_asm pop si
	_asm pop es
		
	return (long)((result & 0xff00) >> 8);
}		

long pci_bios_write (long seg, long bus, long dev, long fn, long reg, long len, 
	u32 value)
{
	unsigned long result = 0;
	unsigned short temp = ((bus << 8) | (dev << 3) | fn);

	if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) 
		return -EINVAL;
	
	switch(len)
	{
		case 1:
			_asm mov bx,temp
			_asm mov di,reg
			_asm mov ah,PCI_FUNCTION_ID
			_asm mov al,WRITE_CONFIG_BYTE		
			_asm mov cl,value
			_asm int 1ah
			_asm mov result,ax
			_asm jc write_fail1
			_asm cmp ah,SUCCESSFUL
			_asm jnz write_fail1

		write_fail1:
			
			break;
		case 2:
			_asm mov bx,temp
			_asm mov di,reg
			_asm mov ah,PCI_FUNCTION_ID
			_asm mov al,WRITE_CONFIG_WORD
			_asm mov cx,value
			_asm int 1ah
			_asm mov result,ax
			_asm jc write_fail2
			_asm cmp ah,SUCCESSFUL
			_asm jnz write_fail2

		write_fail2:

			break;
		case 4:
			_asm mov bx,temp

⌨️ 快捷键说明

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