Strip down i386 PCI configuration space I/O to the bare minimum. A
[gpxe.git] / src / arch / i386 / core / pcibios.c
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@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 #include <stdint.h>
20 #include <gpxe/pci.h>
21 #include <pcibios.h>
22 #include <realmode.h>
23
24 /** @file
25  *
26  * PCI configuration space access via PCI BIOS
27  *
28  */
29
30 /**
31  * Determine maximum PCI bus number within system
32  *
33  * @ret max_bus         Maximum bus number
34  */
35 int pcibios_max_bus ( void ) {
36         int discard_a;
37         uint8_t max_bus;
38
39         REAL_EXEC ( rm_pcibios_check,
40                     "stc\n\t"
41                     "int $0x1a\n\t"
42                     "jnc 1f\n\t"
43                     "xorw %%cx, %%cx\n\t"
44                     "\n1:\n\t",
45                     2,
46                     OUT_CONSTRAINTS ( "=a" ( discard_a ), "=c" ( max_bus ) ),
47                     IN_CONSTRAINTS ( "a" ( PCIBIOS_INSTALLATION_CHECK >> 16 )),
48                     CLOBBER ( "ebx", "edx", "edi" ) );
49         
50         return max_bus;
51 }
52
53 /**
54  * Read configuration space via PCI BIOS
55  *
56  * @v pci       PCI device
57  * @v command   PCI BIOS command
58  * @v value     Value read
59  * @ret rc      Return status code
60  */
61 int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
62         int discard_b, discard_D;
63         int status;
64
65         REAL_EXEC ( rm_pcibios_read,
66                     "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                     4,
74                     OUT_CONSTRAINTS ( "=a" ( status ), "=b" ( discard_b ),
75                                       "=c" ( *value ), "=D" ( discard_D ) ),
76                     IN_CONSTRAINTS ( "a" ( command >> 16 ),
77                                      "b" ( ( pci->bus << 8 ) | pci->devfn ),
78                                      "D" ( command ) ),
79                     CLOBBER ( "edx" ) );
80         
81         return ( ( status >> 8 ) & 0xff );
82 }
83
84 /**
85  * Write configuration space via PCI BIOS
86  *
87  * @v pci       PCI device
88  * @v command   PCI BIOS command
89  * @v value     Value to be written
90  * @ret rc      Return status code
91  */
92 int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
93         int discard_b, discard_c, discard_D;
94         int status;
95
96         REAL_EXEC ( rm_pcibios_write,
97                     "stc\n\t"
98                     "int $0x1a\n\t"
99                     "jnc 1f\n\t"
100                     "movb $0xff, %%ah\n\t"
101                     "\n1:\n\t",
102                     4,
103                     OUT_CONSTRAINTS ( "=a" ( status ), "=b" ( discard_b ),
104                                       "=c" ( discard_c ), "=D" ( discard_D ) ),
105                     IN_CONSTRAINTS ( "a" ( command >> 16 ),
106                                      "b" ( ( pci->bus << 8 ) | pci->devfn ),
107                                      "c" ( value ), "D" ( command ) ),
108                     CLOBBER ( "edx" ) );
109         
110         return ( ( status >> 8 ) & 0xff );
111 }