From 8a4ccebec91717500bc0de867fc2ead7187657fa Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Sun, 12 Oct 2008 12:50:44 +0100 Subject: [pci] Formalise the PCI I/O API --- src/arch/i386/core/pcibios.c | 106 ----------------------- src/arch/i386/core/pcidirect.c | 8 +- src/arch/i386/include/bits/pci_io.h | 13 +++ src/arch/i386/include/gpxe/pcibios.h | 133 +++++++++++++++++++++++++++++ src/arch/i386/include/gpxe/pcidirect.h | 139 +++++++++++++++++++++++++++++++ src/arch/i386/include/pci_io.h | 35 -------- src/arch/i386/include/pcibios.h | 122 --------------------------- src/arch/i386/include/pcidirect.h | 126 ---------------------------- src/arch/i386/interface/pcbios/pcibios.c | 113 +++++++++++++++++++++++++ src/config/defaults/pcbios.h | 2 +- src/config/ioapi.h | 3 + src/include/gpxe/pci.h | 2 +- src/include/gpxe/pci_io.h | 121 +++++++++++++++++++++++++++ 13 files changed, 531 insertions(+), 392 deletions(-) delete mode 100644 src/arch/i386/core/pcibios.c create mode 100644 src/arch/i386/include/bits/pci_io.h create mode 100644 src/arch/i386/include/gpxe/pcibios.h create mode 100644 src/arch/i386/include/gpxe/pcidirect.h delete mode 100644 src/arch/i386/include/pci_io.h delete mode 100644 src/arch/i386/include/pcibios.h delete mode 100644 src/arch/i386/include/pcidirect.h create mode 100644 src/arch/i386/interface/pcbios/pcibios.c create mode 100644 src/include/gpxe/pci_io.h (limited to 'src') diff --git a/src/arch/i386/core/pcibios.c b/src/arch/i386/core/pcibios.c deleted file mode 100644 index 1c93e4be9..000000000 --- a/src/arch/i386/core/pcibios.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2006 Michael Brown . - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include - -/** @file - * - * PCI configuration space access via PCI BIOS - * - */ - -/** - * Determine maximum PCI bus number within system - * - * @ret max_bus Maximum bus number - */ -int pcibios_max_bus ( void ) { - int discard_a, discard_D; - uint8_t max_bus; - - __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" - "int $0x1a\n\t" - "jnc 1f\n\t" - "xorw %%cx, %%cx\n\t" - "\n1:\n\t" ) - : "=c" ( max_bus ), "=a" ( discard_a ), - "=D" ( discard_D ) - : "a" ( PCIBIOS_INSTALLATION_CHECK >> 16 ), - "D" ( 0 ) - : "ebx", "edx" ); - - return max_bus; -} - -/** - * Read configuration space via PCI BIOS - * - * @v pci PCI device - * @v command PCI BIOS command - * @v value Value read - * @ret rc Return status code - */ -int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){ - int discard_b, discard_D; - int status; - - __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" - "int $0x1a\n\t" - "jnc 1f\n\t" - "xorl %%eax, %%eax\n\t" - "decl %%eax\n\t" - "movl %%eax, %%ecx\n\t" - "\n1:\n\t" ) - : "=a" ( status ), "=b" ( discard_b ), - "=c" ( *value ), "=D" ( discard_D ) - : "a" ( command >> 16 ), "D" ( command ), - "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) ) - : "edx" ); - - return ( ( status >> 8 ) & 0xff ); -} - -/** - * Write configuration space via PCI BIOS - * - * @v pci PCI device - * @v command PCI BIOS command - * @v value Value to be written - * @ret rc Return status code - */ -int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){ - int discard_b, discard_c, discard_D; - int status; - - __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" - "int $0x1a\n\t" - "jnc 1f\n\t" - "movb $0xff, %%ah\n\t" - "\n1:\n\t" ) - : "=a" ( status ), "=b" ( discard_b ), - "=c" ( discard_c ), "=D" ( discard_D ) - : "a" ( command >> 16 ), "D" ( command ), - "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) ), - "c" ( value ) - : "edx" ); - - return ( ( status >> 8 ) & 0xff ); -} diff --git a/src/arch/i386/core/pcidirect.c b/src/arch/i386/core/pcidirect.c index 2ed8c2ad0..fec2e3c18 100644 --- a/src/arch/i386/core/pcidirect.c +++ b/src/arch/i386/core/pcidirect.c @@ -17,7 +17,6 @@ */ #include -#include /** @file * @@ -36,3 +35,10 @@ void pcidirect_prepare ( struct pci_device *pci, int where ) { ( where & ~3 ) ), PCIDIRECT_CONFIG_ADDRESS ); } +PROVIDE_PCIAPI_INLINE ( direct, pci_max_bus ); +PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_byte ); +PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_word ); +PROVIDE_PCIAPI_INLINE ( direct, pci_read_config_dword ); +PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_byte ); +PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_word ); +PROVIDE_PCIAPI_INLINE ( direct, pci_write_config_dword ); diff --git a/src/arch/i386/include/bits/pci_io.h b/src/arch/i386/include/bits/pci_io.h new file mode 100644 index 000000000..0fbb439db --- /dev/null +++ b/src/arch/i386/include/bits/pci_io.h @@ -0,0 +1,13 @@ +#ifndef _BITS_PCI_IO_H +#define _BITS_PCI_IO_H + +/** @file + * + * i386-specific PCI I/O API implementations + * + */ + +#include +#include + +#endif /* _BITS_PCI_IO_H */ diff --git a/src/arch/i386/include/gpxe/pcibios.h b/src/arch/i386/include/gpxe/pcibios.h new file mode 100644 index 000000000..b86f5abd4 --- /dev/null +++ b/src/arch/i386/include/gpxe/pcibios.h @@ -0,0 +1,133 @@ +#ifndef _GPXE_PCIBIOS_H +#define _GPXE_PCIBIOS_H + +#include + +/** @file + * + * PCI configuration space access via PCI BIOS + * + */ + +#ifdef PCIAPI_PCBIOS +#define PCIAPI_PREFIX_pcbios +#else +#define PCIAPI_PREFIX_pcbios __pcbios_ +#endif + +struct pci_device; + +#define PCIBIOS_INSTALLATION_CHECK 0xb1010000 +#define PCIBIOS_READ_CONFIG_BYTE 0xb1080000 +#define PCIBIOS_READ_CONFIG_WORD 0xb1090000 +#define PCIBIOS_READ_CONFIG_DWORD 0xb10a0000 +#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b0000 +#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c0000 +#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d0000 + +extern int pcibios_read ( struct pci_device *pci, uint32_t command, + uint32_t *value ); +extern int pcibios_write ( struct pci_device *pci, uint32_t command, + uint32_t value ); + +/** + * Read byte from PCI configuration space via PCI BIOS + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value read + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( pcbios, pci_read_config_byte ) ( struct pci_device *pci, + unsigned int where, + uint8_t *value ) { + uint32_t tmp; + int rc; + + rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_BYTE | where, &tmp ); + *value = tmp; + return rc; +} + +/** + * Read word from PCI configuration space via PCI BIOS + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value read + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( pcbios, pci_read_config_word ) ( struct pci_device *pci, + unsigned int where, + uint16_t *value ) { + uint32_t tmp; + int rc; + + rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_WORD | where, &tmp ); + *value = tmp; + return rc; +} + +/** + * Read dword from PCI configuration space via PCI BIOS + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value read + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( pcbios, pci_read_config_dword ) ( struct pci_device *pci, + unsigned int where, + uint32_t *value ) { + return pcibios_read ( pci, PCIBIOS_READ_CONFIG_DWORD | where, value ); +} + +/** + * Write byte to PCI configuration space via PCI BIOS + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value to be written + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( pcbios, pci_write_config_byte ) ( struct pci_device *pci, + unsigned int where, + uint8_t value ) { + return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_BYTE | where, value ); +} + +/** + * Write word to PCI configuration space via PCI BIOS + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value to be written + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( pcbios, pci_write_config_word ) ( struct pci_device *pci, + unsigned int where, + uint16_t value ) { + return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_WORD | where, value ); +} + +/** + * Write dword to PCI configuration space via PCI BIOS + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value to be written + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( pcbios, pci_write_config_dword ) ( struct pci_device *pci, + unsigned int where, + uint32_t value ) { + return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_DWORD | where, value); +} + +#endif /* _GPXE_PCIBIOS_H */ diff --git a/src/arch/i386/include/gpxe/pcidirect.h b/src/arch/i386/include/gpxe/pcidirect.h new file mode 100644 index 000000000..fe433c6f2 --- /dev/null +++ b/src/arch/i386/include/gpxe/pcidirect.h @@ -0,0 +1,139 @@ +#ifndef _PCIDIRECT_H +#define _PCIDIRECT_H + +#include +#include + +#ifdef PCIAPI_DIRECT +#define PCIAPI_PREFIX_direct +#else +#define PCIAPI_PREFIX_direct __direct_ +#endif + +/** @file + * + * PCI configuration space access via Type 1 accesses + * + */ + +#define PCIDIRECT_CONFIG_ADDRESS 0xcf8 +#define PCIDIRECT_CONFIG_DATA 0xcfc + +struct pci_device; + +extern void pcidirect_prepare ( struct pci_device *pci, int where ); + +/** + * Determine maximum PCI bus number within system + * + * @ret max_bus Maximum bus number + */ +static inline __always_inline int +PCIAPI_INLINE ( direct, pci_max_bus ) ( void ) { + /* No way to work this out via Type 1 accesses */ + return 0xff; +} + +/** + * Read byte from PCI configuration space via Type 1 access + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value read + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( direct, pci_read_config_byte ) ( struct pci_device *pci, + unsigned int where, + uint8_t *value ) { + pcidirect_prepare ( pci, where ); + *value = inb ( PCIDIRECT_CONFIG_DATA + ( where & 3 ) ); + return 0; +} + +/** + * Read word from PCI configuration space via Type 1 access + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value read + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( direct, pci_read_config_word ) ( struct pci_device *pci, + unsigned int where, + uint16_t *value ) { + pcidirect_prepare ( pci, where ); + *value = inw ( PCIDIRECT_CONFIG_DATA + ( where & 2 ) ); + return 0; +} + +/** + * Read dword from PCI configuration space via Type 1 access + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value read + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( direct, pci_read_config_dword ) ( struct pci_device *pci, + unsigned int where, + uint32_t *value ) { + pcidirect_prepare ( pci, where ); + *value = inl ( PCIDIRECT_CONFIG_DATA ); + return 0; +} + +/** + * Write byte to PCI configuration space via Type 1 access + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value to be written + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( direct, pci_write_config_byte ) ( struct pci_device *pci, + unsigned int where, + uint8_t value ) { + pcidirect_prepare ( pci, where ); + outb ( value, PCIDIRECT_CONFIG_DATA + ( where & 3 ) ); + return 0; +} + +/** + * Write word to PCI configuration space via Type 1 access + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value to be written + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( direct, pci_write_config_word ) ( struct pci_device *pci, + unsigned int where, + uint16_t value ) { + pcidirect_prepare ( pci, where ); + outw ( value, PCIDIRECT_CONFIG_DATA + ( where & 2 ) ); + return 0; +} + +/** + * Write dword to PCI configuration space via Type 1 access + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value to be written + * @ret rc Return status code + */ +static inline __always_inline int +PCIAPI_INLINE ( direct, pci_write_config_dword ) ( struct pci_device *pci, + unsigned int where, + uint32_t value ) { + pcidirect_prepare ( pci, where ); + outl ( value, PCIDIRECT_CONFIG_DATA ); + return 0; +} + +#endif /* _PCIDIRECT_H */ diff --git a/src/arch/i386/include/pci_io.h b/src/arch/i386/include/pci_io.h deleted file mode 100644 index 4888d5574..000000000 --- a/src/arch/i386/include/pci_io.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _PCI_IO_H -#define _PCI_IO_H - -#include -#include - -/** @file - * - * i386 PCI configuration space access - * - * We have two methods of PCI configuration space access: the PCI BIOS - * and direct Type 1 accesses. Selecting between them is via the - * compile-time switch -DCONFIG_PCI_DIRECT. - * - */ - -#if CONFIG_PCI_DIRECT -#define pci_max_bus pcidirect_max_bus -#define pci_read_config_byte pcidirect_read_config_byte -#define pci_read_config_word pcidirect_read_config_word -#define pci_read_config_dword pcidirect_read_config_dword -#define pci_write_config_byte pcidirect_write_config_byte -#define pci_write_config_word pcidirect_write_config_word -#define pci_write_config_dword pcidirect_write_config_dword -#else /* CONFIG_PCI_DIRECT */ -#define pci_max_bus pcibios_max_bus -#define pci_read_config_byte pcibios_read_config_byte -#define pci_read_config_word pcibios_read_config_word -#define pci_read_config_dword pcibios_read_config_dword -#define pci_write_config_byte pcibios_write_config_byte -#define pci_write_config_word pcibios_write_config_word -#define pci_write_config_dword pcibios_write_config_dword -#endif /* CONFIG_PCI_DIRECT */ - -#endif /* _PCI_IO_H */ diff --git a/src/arch/i386/include/pcibios.h b/src/arch/i386/include/pcibios.h deleted file mode 100644 index 3d08d135b..000000000 --- a/src/arch/i386/include/pcibios.h +++ /dev/null @@ -1,122 +0,0 @@ -#ifndef _PCIBIOS_H -#define _PCIBIOS_H - -#include - -/** @file - * - * PCI configuration space access via PCI BIOS - * - */ - -struct pci_device; - -#define PCIBIOS_INSTALLATION_CHECK 0xb1010000 -#define PCIBIOS_READ_CONFIG_BYTE 0xb1080000 -#define PCIBIOS_READ_CONFIG_WORD 0xb1090000 -#define PCIBIOS_READ_CONFIG_DWORD 0xb10a0000 -#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b0000 -#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c0000 -#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d0000 - -extern int pcibios_max_bus ( void ); -extern int pcibios_read ( struct pci_device *pci, uint32_t command, - uint32_t *value ); -extern int pcibios_write ( struct pci_device *pci, uint32_t command, - uint32_t value ); - -/** - * Read byte from PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcibios_read_config_byte ( struct pci_device *pci, unsigned int where, - uint8_t *value ) { - uint32_t tmp; - int rc; - - rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_BYTE | where, &tmp ); - *value = tmp; - return rc; -} - -/** - * Read word from PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcibios_read_config_word ( struct pci_device *pci, unsigned int where, - uint16_t *value ) { - uint32_t tmp; - int rc; - - rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_WORD | where, &tmp ); - *value = tmp; - return rc; -} - -/** - * Read dword from PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcibios_read_config_dword ( struct pci_device *pci, unsigned int where, - uint32_t *value ) { - return pcibios_read ( pci, PCIBIOS_READ_CONFIG_DWORD | where, value ); -} - -/** - * Write byte to PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcibios_write_config_byte ( struct pci_device *pci, unsigned int where, - uint8_t value ) { - return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_BYTE | where, value ); -} - -/** - * Write word to PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcibios_write_config_word ( struct pci_device *pci, unsigned int where, - uint16_t value ) { - return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_WORD | where, value ); -} - -/** - * Write dword to PCI configuration space via PCI BIOS - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcibios_write_config_dword ( struct pci_device *pci, unsigned int where, - uint32_t value ) { - return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_DWORD | where, value); -} - -#endif /* _PCIBIOS_H */ diff --git a/src/arch/i386/include/pcidirect.h b/src/arch/i386/include/pcidirect.h deleted file mode 100644 index c333424df..000000000 --- a/src/arch/i386/include/pcidirect.h +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef _PCIDIRECT_H -#define _PCIDIRECT_H - -#include -#include - -/** @file - * - * PCI configuration space access via Type 1 accesses - * - */ - -#define PCIDIRECT_CONFIG_ADDRESS 0xcf8 -#define PCIDIRECT_CONFIG_DATA 0xcfc - -struct pci_device; - -extern void pcidirect_prepare ( struct pci_device *pci, int where ); - -/** - * Determine maximum PCI bus number within system - * - * @ret max_bus Maximum bus number - */ -static inline int pcidirect_max_bus ( void ) { - /* No way to work this out via Type 1 accesses */ - return 0xff; -} - -/** - * Read byte from PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcidirect_read_config_byte ( struct pci_device *pci, unsigned int where, - uint8_t *value ) { - pcidirect_prepare ( pci, where ); - *value = inb ( PCIDIRECT_CONFIG_DATA + ( where & 3 ) ); - return 0; -} - -/** - * Read word from PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcidirect_read_config_word ( struct pci_device *pci, unsigned int where, - uint16_t *value ) { - pcidirect_prepare ( pci, where ); - *value = inw ( PCIDIRECT_CONFIG_DATA + ( where & 2 ) ); - return 0; -} - -/** - * Read dword from PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value read - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcidirect_read_config_dword ( struct pci_device *pci, unsigned int where, - uint32_t *value ) { - pcidirect_prepare ( pci, where ); - *value = inl ( PCIDIRECT_CONFIG_DATA ); - return 0; -} - -/** - * Write byte to PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcidirect_write_config_byte ( struct pci_device *pci, unsigned int where, - uint8_t value ) { - pcidirect_prepare ( pci, where ); - outb ( value, PCIDIRECT_CONFIG_DATA + ( where & 3 ) ); - return 0; -} - -/** - * Write word to PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcidirect_write_config_word ( struct pci_device *pci, unsigned int where, - uint16_t value ) { - pcidirect_prepare ( pci, where ); - outw ( value, PCIDIRECT_CONFIG_DATA + ( where & 2 ) ); - return 0; -} - -/** - * Write dword to PCI configuration space via Type 1 access - * - * @v pci PCI device - * @v where Location within PCI configuration space - * @v value Value to be written - * @ret rc Return status code - */ -static inline __attribute__ (( always_inline )) int -pcidirect_write_config_dword ( struct pci_device *pci, unsigned int where, - uint32_t value ) { - pcidirect_prepare ( pci, where ); - outl ( value, PCIDIRECT_CONFIG_DATA ); - return 0; -} - -#endif /* _PCIDIRECT_H */ diff --git a/src/arch/i386/interface/pcbios/pcibios.c b/src/arch/i386/interface/pcbios/pcibios.c new file mode 100644 index 000000000..81b4fd3c0 --- /dev/null +++ b/src/arch/i386/interface/pcbios/pcibios.c @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2006 Michael Brown . + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +/** @file + * + * PCI configuration space access via PCI BIOS + * + */ + +/** + * Determine maximum PCI bus number within system + * + * @ret max_bus Maximum bus number + */ +static int pcibios_max_bus ( void ) { + int discard_a, discard_D; + uint8_t max_bus; + + __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" + "int $0x1a\n\t" + "jnc 1f\n\t" + "xorw %%cx, %%cx\n\t" + "\n1:\n\t" ) + : "=c" ( max_bus ), "=a" ( discard_a ), + "=D" ( discard_D ) + : "a" ( PCIBIOS_INSTALLATION_CHECK >> 16 ), + "D" ( 0 ) + : "ebx", "edx" ); + + return max_bus; +} + +/** + * Read configuration space via PCI BIOS + * + * @v pci PCI device + * @v command PCI BIOS command + * @v value Value read + * @ret rc Return status code + */ +int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){ + int discard_b, discard_D; + int status; + + __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" + "int $0x1a\n\t" + "jnc 1f\n\t" + "xorl %%eax, %%eax\n\t" + "decl %%eax\n\t" + "movl %%eax, %%ecx\n\t" + "\n1:\n\t" ) + : "=a" ( status ), "=b" ( discard_b ), + "=c" ( *value ), "=D" ( discard_D ) + : "a" ( command >> 16 ), "D" ( command ), + "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) ) + : "edx" ); + + return ( ( status >> 8 ) & 0xff ); +} + +/** + * Write configuration space via PCI BIOS + * + * @v pci PCI device + * @v command PCI BIOS command + * @v value Value to be written + * @ret rc Return status code + */ +int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){ + int discard_b, discard_c, discard_D; + int status; + + __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" + "int $0x1a\n\t" + "jnc 1f\n\t" + "movb $0xff, %%ah\n\t" + "\n1:\n\t" ) + : "=a" ( status ), "=b" ( discard_b ), + "=c" ( discard_c ), "=D" ( discard_D ) + : "a" ( command >> 16 ), "D" ( command ), + "b" ( PCI_BUSDEVFN ( pci->bus, pci->devfn ) ), + "c" ( value ) + : "edx" ); + + return ( ( status >> 8 ) & 0xff ); +} + +PROVIDE_PCIAPI ( pcbios, pci_max_bus, pcibios_max_bus ); +PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte ); +PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word ); +PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_dword ); +PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte ); +PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word ); +PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword ); diff --git a/src/config/defaults/pcbios.h b/src/config/defaults/pcbios.h index 193871f16..df6e93ce2 100644 --- a/src/config/defaults/pcbios.h +++ b/src/config/defaults/pcbios.h @@ -8,7 +8,7 @@ */ #define IOAPI_X86 - +#define PCIAPI_PCBIOS #define CONSOLE_PCBIOS #endif /* CONFIG_DEFAULTS_PCBIOS_H */ diff --git a/src/config/ioapi.h b/src/config/ioapi.h index 28c4f7bac..7726a0f01 100644 --- a/src/config/ioapi.h +++ b/src/config/ioapi.h @@ -9,4 +9,7 @@ #include +//#undef PCIAPI_PCBIOS /* Access via PCI BIOS */ +//#define PCIAPI_DIRECT /* Direct access via Type 1 accesses */ + #endif /* CONFIG_IOAPI_H */ diff --git a/src/include/gpxe/pci.h b/src/include/gpxe/pci.h index 907215748..1ccdb100b 100644 --- a/src/include/gpxe/pci.h +++ b/src/include/gpxe/pci.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include "pci_ids.h" /* diff --git a/src/include/gpxe/pci_io.h b/src/include/gpxe/pci_io.h new file mode 100644 index 000000000..db50939df --- /dev/null +++ b/src/include/gpxe/pci_io.h @@ -0,0 +1,121 @@ +#ifndef _GPXE_PCI_IO_H +#define _GPXE_PCI_IO_H + +/** @file + * + * PCI I/O API + * + */ + +#include +#include +#include + +/** + * Calculate static inline PCI I/O API function name + * + * @v _prefix Subsystem prefix + * @v _api_func API function + * @ret _subsys_func Subsystem API function + */ +#define PCIAPI_INLINE( _subsys, _api_func ) \ + SINGLE_API_INLINE ( PCIAPI_PREFIX_ ## _subsys, _api_func ) + +/** + * Provide a PCI I/O API implementation + * + * @v _prefix Subsystem prefix + * @v _api_func API function + * @v _func Implementing function + */ +#define PROVIDE_PCIAPI( _subsys, _api_func, _func ) \ + PROVIDE_SINGLE_API ( PCIAPI_PREFIX_ ## _subsys, _api_func, _func ) + +/** + * Provide a static inline PCI I/O API implementation + * + * @v _prefix Subsystem prefix + * @v _api_func API function + */ +#define PROVIDE_PCIAPI_INLINE( _subsys, _api_func ) \ + PROVIDE_SINGLE_API_INLINE ( PCIAPI_PREFIX_ ## _subsys, _api_func ) + +/* Include all architecture-independent I/O API headers */ + +/* Include all architecture-dependent I/O API headers */ +#include + +/** + * Determine maximum PCI bus number within system + * + * @ret max_bus Maximum bus number + */ +int pci_max_bus ( void ); + +/** + * Read byte from PCI configuration space + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value read + * @ret rc Return status code + */ +int pci_read_config_byte ( struct pci_device *pci, unsigned int where, + uint8_t *value ); + +/** + * Read 16-bit word from PCI configuration space + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value read + * @ret rc Return status code + */ +int pci_read_config_word ( struct pci_device *pci, unsigned int where, + uint16_t *value ); + +/** + * Read 32-bit dword from PCI configuration space + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value read + * @ret rc Return status code + */ +int pci_read_config_dword ( struct pci_device *pci, unsigned int where, + uint32_t *value ); + +/** + * Write byte to PCI configuration space + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value to be written + * @ret rc Return status code + */ +int pci_write_config_byte ( struct pci_device *pci, unsigned int where, + uint8_t value ); + +/** + * Write 16-bit word to PCI configuration space + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value to be written + * @ret rc Return status code + */ +int pci_write_config_word ( struct pci_device *pci, unsigned int where, + uint16_t value ); + +/** + * Write 32-bit dword to PCI configuration space + * + * @v pci PCI device + * @v where Location within PCI configuration space + * @v value Value to be written + * @ret rc Return status code + */ +int pci_write_config_dword ( struct pci_device *pci, unsigned int where, + uint32_t value ); + +#endif /* _GPXE_PCI_IO_H */ -- cgit v1.2.3-55-g7522