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

📄 pci.c

📁 ucos_ii基础上加上网络功能
💻 C
字号:
/* 
 * $Id: pci.c,v 1.5 2002/02/07 01:08:53 linfusheng Exp $
 */

#include "includes.h"
#include "pci.h"
#include "pci_ids.h"

static struct pci_device pci_device_list[MAX_PCI_DEVICE_LIST];
int pci_device_num = 0;

/*#define	DEBUG	1*/

#define  PCIBIOS_SUCCESSFUL                0x00

/*
 * Functions for accessing PCI configuration space with type 1 accesses
 */

#define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))

int pcibios_read_config_byte(unsigned long  bus, unsigned long  device_fn,
			       unsigned long  where, unsigned char *value)
{
    UCOS_OUTD(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    *value = UCOS_INB(0xCFC + (where&3));
    return PCIBIOS_SUCCESSFUL;
}

int pcibios_read_config_word (unsigned long  bus,
    unsigned long  device_fn, unsigned long  where, unsigned short *value)
{
    UCOS_OUTD(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    *value = UCOS_INW(0xCFC + (where&2));
    return PCIBIOS_SUCCESSFUL;
}

int pcibios_read_config_dword (unsigned long  bus, unsigned long  device_fn,
				 unsigned long  where, unsigned long  *value)
{
    UCOS_OUTD(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    *value = UCOS_IND(0xCFC);
    return PCIBIOS_SUCCESSFUL;
}

int pcibios_write_config_byte (unsigned long  bus, unsigned long  device_fn,
				 unsigned long  where, unsigned char value)
{
    UCOS_OUTD(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    UCOS_OUTB(value, 0xCFC + (where&3));
    return PCIBIOS_SUCCESSFUL;
}

int pcibios_write_config_word (unsigned long  bus, unsigned long  device_fn,
				 unsigned long  where, unsigned short value)
{
    UCOS_OUTD(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    UCOS_OUTW(value, 0xCFC + (where&2));
    return PCIBIOS_SUCCESSFUL;
}

int pcibios_write_config_dword (unsigned long  bus, unsigned long  device_fn,
				 unsigned long  where, unsigned long value)
{
    UCOS_OUTD(CONFIG_CMD(bus,device_fn,where), 0xCF8);
    UCOS_OUTD(value, 0xCFC);
    return PCIBIOS_SUCCESSFUL;
}

#undef CONFIG_CMD


void read_PCI_config(struct pci_config_data *cfg,
		     unsigned long bus,
		     unsigned long device_fn)
{
	unsigned long i;
	DWORD *l = (DWORD *)cfg;
	for (i = 0 ; i < sizeof(struct pci_config_data)/sizeof(DWORD) ; i++) {
		pcibios_read_config_dword(bus,device_fn,i*sizeof(DWORD),&l[i]);
    }
}


void init_pci_bus(void)
{
	unsigned long devfn,  bus;
	unsigned char hdr_type = 0;
	unsigned short vendor, device;
	unsigned short reg;
	unsigned long l;
	unsigned long ioaddr;

	/* Scan all PCI buses, until we find our card.
	 * We could be smart only scan the required busses but that
	 * is error prone, and tricky.
	 * By scanning all possible pci busses in order we should find
	 * our card eventually.
	 */
	for (bus = 0; bus < 0xff; bus ++) {
		for (devfn = 0; devfn < 0xff; devfn ++) {
                        struct pci_device *pcidevice_ptr = &pci_device_list[pci_device_num];

			if (PCI_FUNC (devfn) == 0)
				pcibios_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
			else if (!(hdr_type & 0x80))	/* not a multi-function device */
				continue;
			pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l);
			/* some broken boards return 0 if a slot is empty: */
			if (l == 0xffffffff || l == 0x00000000) {
				hdr_type = 0;
				continue;
			}

			vendor = (unsigned short)(l & 0xffff);
			device = (unsigned short) ((l >> 16) & 0xffff);



			pcidevice_ptr->vendor = vendor;
			pcidevice_ptr->device = device;
			pcidevice_ptr->devfn = devfn;
			pcidevice_ptr->bus = bus;

			// Get 256 byte config space
			read_PCI_config(&pcidevice_ptr->U.config_data,bus,devfn);

			// Lookup ioaddr from five baseaddr
			for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
				pcibios_read_config_dword(bus, devfn, reg, &ioaddr);

				if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0 || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0)
					continue;
				/* Strip the I/O address out of the returned value */
				ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
				break;
			 }
			 pcidevice_ptr->ioaddr = (unsigned short)(ioaddr & 0xffff);
			 pcidevice_ptr->membase =  pcidevice_ptr->U.config_data.U.nonbridge.base_address1 ;
			 pcidevice_ptr->irq = pcidevice_ptr->U.config_data.U.nonbridge.interrupt_line;
			 pci_device_num ++;
		}
	}
}


void disp_pci_config(struct pci_config_data *pci_config)
{
	debug_print("command register: %04x \r\n",pci_config->command_reg);
	debug_print("status register: %04x \r\n",pci_config->status_reg);
	debug_print("interrupt line : %d \r\n",pci_config->U.nonbridge.interrupt_line);
	debug_print("subclass: %02x(%d) ",pci_config->subclass,pci_config->subclass);
	debug_print("classcode:%02x(%d) ",pci_config->classcode,pci_config->classcode);
	debug_print("\r\n");
	debug_print("baseaddr(0-5): ");
	debug_print("%08lx ",pci_config->U.nonbridge.base_address0);
	debug_print("%08lx ",pci_config->U.nonbridge.base_address1);
	debug_print("%08lx ",pci_config->U.nonbridge.base_address2);

	debug_print("%08lx ",pci_config->U.nonbridge.base_address3);
	debug_print("%08lx ",pci_config->U.nonbridge.base_address4);
	debug_print("%08lx ",pci_config->U.nonbridge.base_address5);
	debug_print("\r\n");

	return;
}
void dump_pci_device(void)
{
	int i;
	for( i = 0 ; i < pci_device_num ; i ++) {
		unsigned short pci_command = 0,new_command = 0;
		debug_print("device[%d]: %s \r\n",i,pci_device_list[i].name);
		debug_print("ioaddr = %04x memory address = %08lx \r\n",
						pci_device_list[i].ioaddr,
						pci_device_list[i].membase);

//		debug_print_buf("pci config data",pci_device_list[i].U.raw,256);
		disp_pci_config(&pci_device_list[i].U.config_data);

	}
}

struct pci_device *
lookup_pci_device(unsigned short vendor,unsigned short device)
{
	int i;
	struct pci_device *prev_device = NULL;
	struct pci_device *first_device = NULL;
	if(vendor == 0 || device == 0 )
			return NULL;
	for( i = 0 ; i < pci_device_num ; i ++) {
		if(pci_device_list[i].vendor == vendor &&
			pci_device_list[i].device == device) {
			if(first_device == NULL)
				first_device = &pci_device_list[i];
			if(prev_device)
				prev_device->next = &pci_device_list[i];
			prev_device = &pci_device_list[i];
		 }
	}
	return first_device;
}
/* 
 * $Log: pci.c,v $
 * Revision 1.5  2002/02/07 01:08:53  linfusheng
 * update
 *
 * Revision 1.4  2002/02/06 02:16:25  linfusheng
 * update
 *
 * Revision 1.3  2002/01/28 01:13:52  linfusheng
 * update
 *
 * Revision 1.2  2002/01/28 00:46:25  linfusheng
 * update
 *
 */

⌨️ 快捷键说明

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