adjust_pci_device unconditionally enables both memory and I/O space access, which may not be necessary. There was also no way to revert the device back to the original state.
This commit adds two new functions. enable_pci_device gives drivers finer control over how the PCI device is initialized and disable_pci_device is the shutdown path counterpart. Signed-off-by: Ladi Prosek <lpro...@redhat.com> Suggested-by: Michael S. Tsirkin <m...@redhat.com> --- src/drivers/bus/pci.c | 41 +++++++++++++++++++++++++++++++++++------ src/include/ipxe/pci.h | 2 ++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/drivers/bus/pci.c b/src/drivers/bus/pci.c index 6fbedd9..bdff2b9 100644 --- a/src/drivers/bus/pci.c +++ b/src/drivers/bus/pci.c @@ -143,16 +143,32 @@ static void pci_read_bases ( struct pci_device *pci ) { * * @v pci PCI device * - * Set device to be a busmaster in case BIOS neglected to do so. Also - * adjust PCI latency timer to a reasonable value, 32. + * Set device to be a busmaster in case BIOS neglected to do so. Enable + * both memory and I/O space access. Also adjust PCI latency timer to a + * reasonable value, 32. */ void adjust_pci_device ( struct pci_device *pci ) { + enable_pci_device ( pci, + PCI_COMMAND_MASTER | PCI_COMMAND_MEM | + PCI_COMMAND_IO ); +} + +/** + * Enable PCI device + * + * @v pci PCI device + * @v flags PCI command flags to enable + * @ret old_flags Original PCI command flags + * + * Enable device in case BIOS neglected to do so. Also adjust PCI latency + * timer to a reasonable value, 32. + */ +unsigned enable_pci_device ( struct pci_device *pci, unsigned flags ) { unsigned short new_command, pci_command; unsigned char pci_latency; pci_read_config_word ( pci, PCI_COMMAND, &pci_command ); - new_command = ( pci_command | PCI_COMMAND_MASTER | - PCI_COMMAND_MEM | PCI_COMMAND_IO ); + new_command = ( pci_command | flags ); if ( pci_command != new_command ) { DBGC ( pci, PCI_FMT " device not enabled by BIOS! Updating " "PCI command %04x->%04x\n", @@ -160,12 +176,25 @@ void adjust_pci_device ( struct pci_device *pci ) { pci_write_config_word ( pci, PCI_COMMAND, new_command ); } - pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency); + pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency ); if ( pci_latency < 32 ) { DBGC ( pci, PCI_FMT " latency timer is unreasonably low at " "%d. Setting to 32.\n", PCI_ARGS ( pci ), pci_latency ); - pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32); + pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32 ); } + return pci_command; +} + +/** + * Disable PCI device + * + * @v pci PCI device + * @v old_flags Flags to restore, returned from enable_pci_device + * + * Restore device to state it had before we enabled it. + */ +void disable_pci_device ( struct pci_device *pci, unsigned old_flags ) { + pci_write_config_word ( pci, PCI_COMMAND, old_flags ); } /** diff --git a/src/include/ipxe/pci.h b/src/include/ipxe/pci.h index 0c6bc7e..3c613c2 100644 --- a/src/include/ipxe/pci.h +++ b/src/include/ipxe/pci.h @@ -278,6 +278,8 @@ struct pci_driver { PCI_FUNC ( (pci)->busdevfn ) extern void adjust_pci_device ( struct pci_device *pci ); +extern unsigned enable_pci_device ( struct pci_device *pci, unsigned flags ); +extern void disable_pci_device ( struct pci_device *pci, unsigned flags ); extern unsigned long pci_bar_start ( struct pci_device *pci, unsigned int reg ); extern int pci_read_config ( struct pci_device *pci ); -- 2.5.5 _______________________________________________ ipxe-devel mailing list ipxe-devel@lists.ipxe.org https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel