176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>. 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is free software; you can redistribute it and/or 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * modify it under the terms of the GNU General Public License as 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * published by the Free Software Foundation; either version 2 of the 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * License, or any later version. 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is distributed in the hope that it will be useful, but 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WITHOUT ANY WARRANTY; without even the implied warranty of 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * General Public License for more details. 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * You should have received a copy of the GNU General Public License 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * along with this program; if not, write to the Free Software 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1976d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER ); 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdint.h> 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/pci.h> 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/pcibackup.h> 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** @file 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * PCI configuration space backup and restoration 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Check PCI configuration space offset against exclusion list 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v pci PCI device 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v offset Offset within PCI configuration space 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v exclude PCI configuration space backup exclusion list, or NULL 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanpci_backup_excluded ( struct pci_device *pci, unsigned int offset, 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const uint8_t *exclude ) { 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! exclude ) 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( ; *exclude != PCI_CONFIG_BACKUP_EXCLUDE_END ; exclude++ ) { 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( offset == *exclude ) { 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( pci, "PCI %p skipping configuration offset " 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "%02x\n", pci, offset ); 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Back up PCI configuration space 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v pci PCI device 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v backup PCI configuration space backup 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v exclude PCI configuration space backup exclusion list, or NULL 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid pci_backup ( struct pci_device *pci, struct pci_config_backup *backup, 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const uint8_t *exclude ) { 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int offset; 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t *dword; 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( offset = 0, dword = backup->dwords ; offset < 0x100 ; 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman offset += sizeof ( *dword ) , dword++ ) { 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! pci_backup_excluded ( pci, offset, exclude ) ) 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci_read_config_dword ( pci, offset, dword ); 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Restore PCI configuration space 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v pci PCI device 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v backup PCI configuration space backup 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v exclude PCI configuration space backup exclusion list, or NULL 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid pci_restore ( struct pci_device *pci, struct pci_config_backup *backup, 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const uint8_t *exclude ) { 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int offset; 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint32_t *dword; 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( offset = 0, dword = backup->dwords ; offset < 0x100 ; 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman offset += sizeof ( *dword ) , dword++ ) { 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! pci_backup_excluded ( pci, offset, exclude ) ) 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pci_write_config_dword ( pci, offset, *dword ); 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 91