does not work yet.. sorry :-( git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1119 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
		
			
				
	
	
		
			156 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * pcibios code from linuxbios
 | |
|  */
 | |
| 
 | |
| #include <pci.h>
 | |
| #undef __KERNEL__
 | |
| #include <io.h>
 | |
| 
 | |
| void printk(const char *fmt, ...);
 | |
| 
 | |
| #define printk_debug printk
 | |
| #define printk_err printk
 | |
| 
 | |
| enum {
 | |
| 	CHECK = 0xb001,
 | |
| 	FINDDEV = 0xb102,
 | |
| 	READCONFBYTE = 0xb108,
 | |
| 	READCONFWORD = 0xb109,
 | |
| 	READCONFDWORD = 0xb10a,
 | |
| 	WRITECONFBYTE = 0xb10b,
 | |
| 	WRITECONFWORD = 0xb10c,
 | |
| 	WRITECONFDWORD = 0xb10d
 | |
| };
 | |
| 
 | |
| // errors go in AH. Just set these up so that word assigns
 | |
| // will work. KISS. 
 | |
| enum {
 | |
| 	PCIBIOS_NODEV = 0x8600,
 | |
| 	PCIBIOS_BADREG = 0x8700
 | |
| };
 | |
| 
 | |
| int
 | |
| pcibios(
 | |
| 	unsigned long *pedi, 
 | |
| 	unsigned long *pesi,
 | |
| 	unsigned long *pebp, 
 | |
| 	unsigned long *pesp, 
 | |
| 	unsigned long *pebx, 
 | |
| 	unsigned long *pedx, 
 | |
| 	unsigned long *pecx, 
 | |
| 	unsigned long *peax, 
 | |
| 	unsigned long *pflags
 | |
| 	) {
 | |
| 	unsigned long edi = *pedi;
 | |
| 	unsigned long esi = *pesi;
 | |
| 	unsigned long ebp = *pebp;
 | |
| 	unsigned long esp = *pesp;
 | |
| 	unsigned long ebx = *pebx;
 | |
| 	unsigned long edx = *pedx;
 | |
| 	unsigned long ecx = *pecx;
 | |
| 	unsigned long eax = *peax;
 | |
| 	unsigned long flags = *pflags;
 | |
| 	unsigned short func = (unsigned short) eax;
 | |
| 	int retval = -1;
 | |
| 	unsigned short devid, vendorid, devfn;
 | |
| 	short devindex; /* Use short to get rid of gabage in upper half of 32-bit register */
 | |
| 	unsigned char bus;
 | |
| 	struct pci_dev *dev;
 | |
| 
 | |
| 	switch(func) {
 | |
| 	case  CHECK:
 | |
| 		*pedx = 0x4350;
 | |
| 		*pecx = 0x2049;
 | |
| 		retval = 0;
 | |
| 		break;
 | |
| 	case FINDDEV:
 | |
| 	{
 | |
| 		devid = *pecx;
 | |
| 		vendorid = *pedx;
 | |
| 		devindex = *pesi;
 | |
| 		dev = 0;
 | |
| 		while ((dev = pci_find_device(vendorid, devid, dev))) {
 | |
| 			if (devindex <= 0)
 | |
| 				break;
 | |
| 			devindex--;
 | |
| 		}
 | |
| 		if (dev) {
 | |
| 			unsigned short busdevfn;
 | |
| 			*peax = 0;
 | |
| 				// busnum is an unsigned char;
 | |
| 				// devfn is an int, so we mask it off. 
 | |
| 			busdevfn = (dev->bus << 8)
 | |
| 					| (dev->devfn & 0xff);
 | |
| 			printk_debug("0x%x: return 0x%x\n", func, busdevfn);
 | |
| 			*pebx = busdevfn;
 | |
| 			retval = 0;
 | |
| 		} else {
 | |
| 			*peax = PCIBIOS_NODEV;
 | |
| 			retval = -1;
 | |
| 		}
 | |
| 	}
 | |
| 	break;
 | |
| 	case READCONFDWORD:
 | |
| 	case READCONFWORD:
 | |
| 	case READCONFBYTE:
 | |
| 	case WRITECONFDWORD:
 | |
| 	case WRITECONFWORD:
 | |
| 	case WRITECONFBYTE:
 | |
| 	{
 | |
| 		unsigned int dword;
 | |
| 		unsigned short word;
 | |
| 		unsigned char byte;
 | |
| 		unsigned char reg;
 | |
| 		
 | |
| 		devfn = *pebx & 0xff;
 | |
| 		bus = *pebx >> 8;
 | |
| 		reg = *pedi;
 | |
| 		dev = pci_find_slot(bus, devfn);
 | |
| 		if (! dev) {
 | |
| 			printk_debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn);
 | |
| 			// idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
 | |
| 			*peax = PCIBIOS_BADREG;
 | |
| 			retval = -1;
 | |
| 		}
 | |
| 	switch(func) {
 | |
| 		case READCONFBYTE:
 | |
| 			retval = pci_read_config_byte(dev, reg, &byte);
 | |
| 			*pecx = byte;
 | |
| 			break;
 | |
| 		case READCONFWORD:
 | |
| 			retval = pci_read_config_word(dev, reg, &word);
 | |
| 			*pecx = word;
 | |
| 			break;
 | |
| 		case READCONFDWORD:
 | |
| 			retval = pci_read_config_dword(dev, reg, &dword);
 | |
| 			*pecx = dword;
 | |
| 			break;
 | |
| 		case WRITECONFBYTE:
 | |
| 			byte = *pecx;
 | |
|                         retval = pci_write_config_byte(dev, reg, byte);
 | |
| 			break;
 | |
| 		case WRITECONFWORD:
 | |
| 			word = *pecx;
 | |
|                         retval = pci_write_config_word(dev, reg, word);
 | |
| 			break;
 | |
| 		case WRITECONFDWORD:
 | |
| 			word = *pecx;
 | |
|                         retval = pci_write_config_dword(dev, reg, dword);
 | |
| 			break;
 | |
|                 }
 | |
| 			
 | |
| 		if (retval) 
 | |
| 			retval = PCIBIOS_BADREG;
 | |
| 		printk_debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n", func, bus, devfn, reg, *pecx);
 | |
| 		*peax = 0;
 | |
| 		retval = 0;
 | |
| 	}
 | |
| 	break;
 | |
| 	default:
 | |
| 		printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n",  func);
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	return retval;
 | |
| } 
 |