iseries_reset_device.c

来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 197 行

C
197
字号
/************************************************************************//* File iSeries_reset_device.c created by Allan Trautman on Mar 21 2001.*//************************************************************************//* This code supports the pci interface on the IBM iSeries systems.     *//* Copyright (C) 20yy  <Allan H Trautman> <IBM Corp>                    *//*                                                                      *//* 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    *//* (at your option) 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.,                                      */ /* 59 Temple Place, Suite 330,                                          */ /* Boston, MA  02111-1307  USA                                          *//************************************************************************//* Change Activity:                                                     *//*   Created, March 20, 2001                                            *//*   April 30, 2001, Added return codes on functions.                   *//* End Change Activity                                                  *//************************************************************************/#include <linux/config.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/irq.h>/************************************************************************//* Arch specific's                                                      *//************************************************************************/#include <asm/io.h>#include <asm/iSeries/HvCallPci.h>#include <asm/iSeries/HvTypes.h>#include <asm/iSeries/mf.h>#include <asm/iSeries/iSeries_FlightRecorder.h>#include <asm/iSeries/iSeries_pci.h>#include "iSeries_pci.h"/************************************************************************//* Interface to Reset Device, see .h for parms and flavors.             *//************************************************************************/int  iSeries_Device_Reset_NoIrq(struct pci_dev* PciDev) {    return iSeries_Device_Reset(PciDev,0,0,1);}int  iSeries_Device_Reset_Generic(struct pci_dev* PciDev) {    return iSeries_Device_Reset(PciDev,0,0,0);}int  iSeries_Device_Reset(struct pci_dev* PciDev, int AssertTime, int DelayTime, int IrqState) {    int              RCode       = 0;    PciReqsSaveArea* RegSaveArea = NULL;    if(PciDev != 0) {	if(IrqState == 0) disable_irq(PciDev->irq);	RegSaveArea = iSeries_Device_SaveConfigRegs(PciDev);	if(RegSaveArea != NULL) {	    RCode  = iSeries_Device_ToggleReset(PciDev, AssertTime, DelayTime);	    if(RCode == 0) {		RCode = iSeries_Device_RestoreConfigRegs(RegSaveArea);	    }	}        else {            RCode = -1;        }	if(IrqState == 0) enable_irq(PciDev->irq);    }    return RCode;}/************************************************************************//* Interface to toggle the reset line                                   *//* Time is in .1 seconds, need for seconds.                             *//************************************************************************/int  iSeries_Device_ToggleReset(struct pci_dev* PciDev, int AssertTime, int DelayTime) {    unsigned long AssertDelay = AssertTime;    unsigned long WaitDelay   = DelayTime;    u16           Bus         = ISERIES_GET_LPAR_BUS(PciDev->bus->number);    u8            Slot        = ISERIES_DECODE_DEVICE(PciDev->devfn);    int           RCode       = 0;    /* Set defaults                                                     */    if(AssertTime < 5) AssertDelay = 5;        /* Default is .5 second  */    if(WaitDelay < 30) WaitDelay = 30;         /* Default is 3 seconds  */    /* Assert reset for time specified                                  */    AssertDelay  *= HZ;                       /* Convert to ticks.      */    AssertDelay  /= 10;                       /* Adjust to whole count  */    RCode  = HvCallPci_setSlotReset(Bus, 0x00, Slot, 1);    set_current_state(TASK_UNINTERRUPTIBLE);  /* Only Wait.             */    schedule_timeout(AssertDelay);            /* Sleep for the time     */    RCode += HvCallPci_setSlotReset(Bus, 0x00, Slot, 0);    /* Wait for device to reset                                         */    WaitDelay  *= HZ;                         /* Ticks                  */    WaitDelay  /= 10;                         /* Whole count            */    set_current_state(TASK_UNINTERRUPTIBLE);  /* Only Wait.             */    schedule_timeout(WaitDelay);              /* Sleep for the time     */    if(RCode == 0) {        sprintf(PciFrBuffer,"Slot Reset on Bus%3d, Device%3d!\n",Bus, Slot);    }    else {        sprintf(PciFrBuffer,"Slot Reset on Bus%3d, Device%3d Failed!  RCode: %04X\n",Bus, Slot, RCode);    }    ISERIES_PCI_FR_TIME(PciFrBuffer);    printk("PCI: %s\n",PciFrBuffer);    return RCode;}/************************************************************************//* Allocates space and save the config registers for a device.          *//************************************************************************//* Note: This does byte reads so the data may appear byte swapped       *//* when compared to read word or dword.                                 *//* The data returned is a structure and will be freed automatically on  *//* the restore of the data.  The is checking so if the save fails, the  *//* data will not be restore.  Yes I know, you are most likey toast.     *//************************************************************************/PciReqsSaveArea* iSeries_Device_SaveConfigRegs(struct pci_dev* DevPtr) {    int              Register    = 0;    struct pci_dev*  PciDev      = DevPtr;    PciReqsSaveArea* RegSaveArea = (PciReqsSaveArea*)kmalloc(sizeof(PciReqsSaveArea), GFP_KERNEL);    /*printk("PCI: Save Configuration Registers. 0x%08X\n",(int)RegSaveArea); */    if(RegSaveArea == 0) {	printk("PCI: Allocation failure in Save Configuration Registers.\n");    }    /********************************************************************/    /* Initialize Area.                                                 */    /********************************************************************/    else {	RegSaveArea->PciDev    = DevPtr;	RegSaveArea->Flags     = 0x01;	RegSaveArea->ByteCount = PCI_MAX_LAT+1;     /* Number of Bytes  */	RegSaveArea->RCode     = 0;	RegSaveArea->FailReg   = 0;	/****************************************************************/	/* Save All the Regs,  NOTE: restore skips the first 16 bytes.  */	/****************************************************************/	for(Register = 0;Register < RegSaveArea->ByteCount && RegSaveArea->RCode == 0; ++Register) {	    RegSaveArea->RCode = pci_read_config_byte(PciDev, Register, &RegSaveArea->Regs[Register]);	}	/* Check for error during the save.                             */	if(RegSaveArea->RCode != 0) {	    printk("PCI: I/O Failure in Save Configuration Registers. 0x%02X, 0x%04X\n",		                                              Register,RegSaveArea->RCode);	    RegSaveArea->Flags  |= 0x80;		/* Ouch Flag.           */	    RegSaveArea->FailReg = Register;	        /* Stuff this way       */	}    }    return  RegSaveArea;}/************************************************************************//* Restores the registers saved via the save function.  See the save    *//* function for details.                                                *//************************************************************************/int  iSeries_Device_RestoreConfigRegs(PciReqsSaveArea* SaveArea) {    int RCode = 0;    if(SaveArea == 0 || SaveArea->PciDev == 0 ||      (SaveArea->Flags & 0x80) == 0x80 || SaveArea->RCode != 0) {	printk("PCI: Invalid SaveArea passed to Restore Configuration Registers. 0x%08X\n",(int)SaveArea);        RCode = -1;    }    else {	int    Register;	struct pci_dev* PciDev = SaveArea->PciDev;        /***************************************************************/	/* Don't touch the Cmd or BIST regs, user must restore those.  */	/* Restore PCI_CACHE_LINE_SIZE & PCI_LATENCY_TIMER             */        /* Restore Saved Regs from 0x10 to 0x3F                        */        /***************************************************************/	pci_write_config_byte(PciDev, PCI_CACHE_LINE_SIZE, SaveArea->Regs[PCI_CACHE_LINE_SIZE]);	pci_write_config_byte(PciDev, PCI_LATENCY_TIMER,   SaveArea->Regs[PCI_LATENCY_TIMER]);	for(Register = PCI_BASE_ADDRESS_0; Register < SaveArea->ByteCount && SaveArea->RCode == 0; ++Register) {	    SaveArea->RCode = pci_write_config_byte(PciDev, Register, SaveArea->Regs[Register]);	}	if(SaveArea->RCode != 0) {	    printk("PCI: I/O Failure in Restore Configuration Registers %d, %02X\n",Register,SaveArea->RCode);	    SaveArea->FailReg = Register;	    RCode = SaveArea->RCode;	}	else {	    RCode = 0;	}	/***************************************************************/        /* Is the Auto Free Flag on                                    */        /***************************************************************/	if(SaveArea->Flags && 0x01 == 0x01 ) {	    /* printk("PCI: Auto Free Register Save Area.  0x%08X\n",(int)SaveArea); */	    kfree(SaveArea);	}    }    return RCode;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?