1 /* 2 * Copyright (C) 2006 Michael Brown <mbrown (at) fensystems.co.uk>. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19 FILE_LICENCE ( GPL2_OR_LATER ); 20 21 #include <stdint.h> 22 #include <gpxe/pci.h> 23 #include <realmode.h> 24 25 /** @file 26 * 27 * PCI configuration space access via PCI BIOS 28 * 29 */ 30 31 /** 32 * Determine maximum PCI bus number within system 33 * 34 * @ret max_bus Maximum bus number 35 */ 36 static int pcibios_max_bus ( void ) { 37 int discard_a, discard_D; 38 uint8_t max_bus; 39 40 __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" 41 "int $0x1a\n\t" 42 "jnc 1f\n\t" 43 "xorw %%cx, %%cx\n\t" 44 "\n1:\n\t" ) 45 : "=c" ( max_bus ), "=a" ( discard_a ), 46 "=D" ( discard_D ) 47 : "a" ( PCIBIOS_INSTALLATION_CHECK >> 16 ), 48 "D" ( 0 ) 49 : "ebx", "edx" ); 50 51 return max_bus; 52 } 53 54 /** 55 * Read configuration space via PCI BIOS 56 * 57 * @v pci PCI device 58 * @v command PCI BIOS command 59 * @v value Value read 60 * @ret rc Return status code 61 */ 62 int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){ 63 int discard_b, discard_D; 64 int status; 65 66 __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" 67 "int $0x1a\n\t" 68 "jnc 1f\n\t" 69 "xorl %%eax, %%eax\n\t" 70 "decl %%eax\n\t" 71 "movl %%eax, %%ecx\n\t" 72 "\n1:\n\t" ) 73 : "=a" ( status ), "=b" ( discard_b ), 74 "=c" ( *value ), "=D" ( discard_D ) 75 : "a" ( command >> 16 ), "D" ( command ), 76 "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) ) 77 : "edx" ); 78 79 return ( ( status >> 8 ) & 0xff ); 80 } 81 82 /** 83 * Write configuration space via PCI BIOS 84 * 85 * @v pci PCI device 86 * @v command PCI BIOS command 87 * @v value Value to be written 88 * @ret rc Return status code 89 */ 90 int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){ 91 int discard_b, discard_c, discard_D; 92 int status; 93 94 __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" 95 "int $0x1a\n\t" 96 "jnc 1f\n\t" 97 "movb $0xff, %%ah\n\t" 98 "\n1:\n\t" ) 99 : "=a" ( status ), "=b" ( discard_b ), 100 "=c" ( discard_c ), "=D" ( discard_D ) 101 : "a" ( command >> 16 ), "D" ( command ), 102 "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) ), 103 "c" ( value ) 104 : "edx" ); 105 106 return ( ( status >> 8 ) & 0xff ); 107 } 108 109 PROVIDE_PCIAPI ( pcbios, pci_max_bus, pcibios_max_bus ); 110 PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte ); 111 PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word ); 112 PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_dword ); 113 PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte ); 114 PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word ); 115 PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword ); 116