⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpqfctsinit.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
  // from Linux Scsi (e.g. ceated a SEST entry) and it  // got lost somehow.  If we can't find any reference  // to the passed pointer, we can only presume it  // got completed as far as our driver is concerned.  // If we found it, we will try to abort it through  // common mechanism.  If FC ABTS is successful (ACC)  // or is rejected (RJT) by target, we will call  // Scsi "done" quickly.  Otherwise, the ABTS will timeout  // and we'll call "done" later.  // Search the SEST exchanges for a matching Cmnd ptr.  for( i=0; i< TACH_SEST_LEN; i++)  {    if( Exchanges->fcExchange[i].Cmnd == Cmnd )    {            // found it!      printk(" x_ID %Xh, type %Xh\n", i, Exchanges->fcExchange[i].type);      Exchanges->fcExchange[i].status = INITIATOR_ABORT; // seconds default      Exchanges->fcExchange[i].timeOut = 10; // seconds default (changed later)      // Since we need to immediately return the aborted Cmnd to Scsi       // upper layers, we can't make future reference to any of it's       // fields (e.g the Nexus).      cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &i);      break;    }  }  if( i >= TACH_SEST_LEN ) // didn't find Cmnd ptr in chip's SEST?  {    // now search our non-SEST buffers (i.e. Cmnd waiting to    // start on the HBA or waiting to complete with error for retry).        // first check BadTargetCmnd    for( i=0; i< CPQFCTS_MAX_TARGET_ID; i++)    {       if( cpqfcHBAdata->BadTargetCmnd[i] == Cmnd )      {        cpqfcHBAdata->BadTargetCmnd[i] = NULL;	printk("in BadTargetCmnd Q\n");	goto Done; // exit      }    }    // if not found above...    for( i=0; i < CPQFCTS_REQ_QUEUE_LEN; i++)    {      if( cpqfcHBAdata->LinkDnCmnd[i] == Cmnd )       {	cpqfcHBAdata->LinkDnCmnd[i] = NULL;	printk("in LinkDnCmnd Q\n");	goto Done;      }    }    for( i=0; i< CPQFCTS_REQ_QUEUE_LEN; i++)    {    // find spare slot      if( cpqfcHBAdata->BoardLockCmnd[i] == Cmnd )      {        cpqfcHBAdata->BoardLockCmnd[i] = NULL;	printk("in BoardLockCmnd Q\n");	goto Done;      }    }        Cmnd->result = DID_ERROR <<16;  // Hmmm...    printk("Not found! ");//    panic("_abort");  }  Done:  //    panic("_abort");  LEAVE("cpqfcTS_abort");  return 0;  // (see scsi.h)}    // To be done...	int cpqfcTS_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags){  int return_status = SUCCESS;  ENTER("cpqfcTS_reset");              LEAVE("cpqfcTS_reset");  return return_status;}    /* This function determines the bios parameters for a given   harddisk. These tend to be numbers that are made up by the   host adapter.  Parameters:   size, device number, list (heads, sectors,cylinders).   (from hosts.h)*/int cpqfcTS_biosparam(Disk *disk, kdev_t n, int ip[]){  int size = disk->capacity;    ENTER("cpqfcTS_biosparam");  ip[0] = 64;  ip[1] = 32;  ip[2] = size >> 11;    if( ip[2] > 1024 )  {    ip[0] = 255;    ip[1] = 63;    ip[2] = size / (ip[0] * ip[1]);  }  LEAVE("cpqfcTS_biosparam");  return 0;}    void cpqfcTS_intr_handler( int irq, 		void *dev_id, 		struct pt_regs *regs){  unsigned long flags, InfLoopBrk=0;  struct Scsi_Host *HostAdapter = dev_id;  CPQFCHBA *cpqfcHBA = (CPQFCHBA *)HostAdapter->hostdata;  int MoreMessages = 1; // assume we have something to do  UCHAR IntPending;    ENTER("intr_handler");  spin_lock_irqsave( &io_request_lock, flags);  // is this our INT?  IntPending = readb( cpqfcHBA->fcChip.Registers.INTPEND.address);  // broken boards can generate messages forever, so  // prevent the infinite loop#define INFINITE_IMQ_BREAK 10000  if( IntPending )  {        // mask our HBA interrupts until we handle it...    writeb( 0, cpqfcHBA->fcChip.Registers.INTEN.address);    if( IntPending & 0x4) // "INT" - Tach wrote to IMQ    {      while( (++InfLoopBrk < INFINITE_IMQ_BREAK) && (MoreMessages ==1) )       {        MoreMessages = CpqTsProcessIMQEntry( HostAdapter); // ret 0 when done      }      if( InfLoopBrk >= INFINITE_IMQ_BREAK )      {        printk("WARNING: Compaq FC adapter generating excessive INTs -REPLACE\n");        printk("or investigate alternate causes (e.g. physical FC layer)\n");      }      else  // working normally - re-enable INTs and continue        writeb( 0x1F, cpqfcHBA->fcChip.Registers.INTEN.address);        }  // (...ProcessIMQEntry() clears INT by writing IMQ consumer)    else  // indications of errors or problems...          // these usually indicate critical system hardware problems.    {      if( IntPending & 0x10 )  	printk(" cpqfcTS adapter external memory parity error detected\n");      if( IntPending & 0x8 )  	printk(" cpqfcTS adapter PCI master address crossed 45-bit boundary\n");      if( IntPending & 0x2 )	printk(" cpqfcTS adapter DMA error detected\n");      if( IntPending & 0x1 )  	printk(" cpqfcTS adapter PCI error detected\n");    }        }  spin_unlock_irqrestore( &io_request_lock, flags);  LEAVE("intr_handler");}int cpqfcTSDecodeGBICtype( PTACHYON fcChip, char cErrorString[]){        // Verify GBIC type (if any) and correct Tachyon Port State Machine        // (GBIC) module definition is:        // GPIO1, GPIO0, GPIO4 for MD2, MD1, MD0.  The input states appear        // to be inverted -- i.e., a setting of 111 is read when there is NO        // GBIC present.  The Module Def (MD) spec says 000 is "no GBIC"        // Hard code the bit states to detect Copper,         // Long wave (single mode), Short wave (multi-mode), and absent GBIC  ULONG ulBuff;  sprintf( cErrorString, "\nGBIC detected: ");  ulBuff = fcChip->Registers.TYstatus.value & 0x13;   switch( ulBuff )  {  case 0x13:  // GPIO4, GPIO1, GPIO0 = 111; no GBIC!    sprintf( &cErrorString[ strlen( cErrorString)],            "NONE! ");    return FALSE;                             case 0x11:   // Copper GBIC detected    sprintf( &cErrorString[ strlen( cErrorString)],            "Copper. ");    break;  case 0x10:   // Long-wave (single mode) GBIC detected    sprintf( &cErrorString[ strlen( cErrorString)],        "Long-wave. ");    break;  case 0x1:    // Short-wave (multi mode) GBIC detected    sprintf( &cErrorString[ strlen( cErrorString)],        "Short-wave. ");    break;  default:     // unknown GBIC - presumably it will work (?)    sprintf( &cErrorString[ strlen( cErrorString)],            "Unknown. ");              break;  }  // end switch GBIC detection  return TRUE;}int cpqfcTSGetLPSM( PTACHYON fcChip, char cErrorString[]){  // Tachyon's Frame Manager LPSM in LinkDown state?  // (For non-loop port, check PSM instead.)  // return string with state and FALSE is Link Down  int LinkUp;  if( fcChip->Registers.FMstatus.value & 0x80 )     LinkUp = FALSE;  else    LinkUp = TRUE;  sprintf( &cErrorString[ strlen( cErrorString)],    " LPSM %Xh ",      (fcChip->Registers.FMstatus.value >>4) & 0xf );  switch( fcChip->Registers.FMstatus.value & 0xF0)  {                    // bits set in LPSM    case 0x10:      sprintf( &cErrorString[ strlen( cErrorString)], "ARB");      break;    case 0x20:      sprintf( &cErrorString[ strlen( cErrorString)], "ARBwon");      break;    case 0x30:      sprintf( &cErrorString[ strlen( cErrorString)], "OPEN");      break;    case 0x40:      sprintf( &cErrorString[ strlen( cErrorString)], "OPENed");      break;    case 0x50:      sprintf( &cErrorString[ strlen( cErrorString)], "XmitCLS");      break;    case 0x60:      sprintf( &cErrorString[ strlen( cErrorString)], "RxCLS");      break;    case 0x70:      sprintf( &cErrorString[ strlen( cErrorString)], "Xfer");      break;    case 0x80:      sprintf( &cErrorString[ strlen( cErrorString)], "Init");      break;    case 0x90:      sprintf( &cErrorString[ strlen( cErrorString)], "O-IInitFin");      break;    case 0xa0:      sprintf( &cErrorString[ strlen( cErrorString)], "O-IProtocol");      break;    case 0xb0:      sprintf( &cErrorString[ strlen( cErrorString)], "O-ILipRcvd");      break;    case 0xc0:      sprintf( &cErrorString[ strlen( cErrorString)], "HostControl");      break;    case 0xd0:      sprintf( &cErrorString[ strlen( cErrorString)], "LoopFail");      break;    case 0xe0:      sprintf( &cErrorString[ strlen( cErrorString)], "Offline");      break;    case 0xf0:      sprintf( &cErrorString[ strlen( cErrorString)], "OldPort");      break;    case 0:    default:      sprintf( &cErrorString[ strlen( cErrorString)], "Monitor");      break;  }  return LinkUp;}#include "linux/malloc.h"// Dynamic memory allocation alignment routines// HP's Tachyon Fibre Channel Controller chips require// certain memory queues and register pointers to be aligned// on various boundaries, usually the size of the Queue in question.// Alignment might be on 2, 4, 8, ... or even 512 byte boundaries.// Since most O/Ss don't allow this (usually only Cache aligned -// 32-byte boundary), these routines provide generic alignment (after// O/S allocation) at any boundary, and store the original allocated// pointer for deletion (O/S free function).  Typically, we expect// these functions to only be called at HBA initialization and// removal time (load and unload times)// ALGORITHM notes:// Memory allocation varies by compiler and platform.  In the worst case,// we are only assured BYTE allignment, but in the best case, we can// request allocation on any desired boundary.  Our strategy: pad the// allocation request size (i.e. waste memory) so that we are assured// of passing desired boundary near beginning of contiguous space, then// mask out lower address bits.// We define the following algorithm://   allocBoundary - compiler/platform specific address alignment//                   in number of bytes (default is single byte; i.e. 1)//   n_alloc       - number of bytes application wants @ aligned address//   ab            - alignment boundary, in bytes (e.g. 4, 32, ...)//   t_alloc       - total allocation needed to ensure desired boundary//   mask          - to clear least significant address bits for boundary//   Compute://   t_alloc = n_alloc + (ab - allocBoundary)//   allocate t_alloc bytes @ alloc_address//   mask =  NOT (ab - 1)//       (e.g. if ab=32  _0001 1111  -> _1110 0000//   aligned_address = alloc_address & mask//   set n_alloc bytes to 0//   return aligned_address (NULL if failed)//// If u32_AlignedAddress is non-zero, then search for BaseAddress (stored// from previous allocation).  If found, invoke call to FREE the memory.// Return NULL if BaseAddress not found// we need about 8 allocations per HBA.  Figuring at most 10 HBAs per server// size the dynamic_mem array at 80.void* fcMemManager( ALIGNED_MEM *dynamic_mem, ULONG n_alloc, ULONG ab,                   ULONG u32_AlignedAddress){  USHORT allocBoundary=1;   // compiler specific - worst case 1                                  // best case - replace malloc() call                                  // with function that allocates exactly                                  // at desired boundary  unsigned long ulAddress;  ULONG t_alloc, i;  void *alloc_address = 0;  // def. error code / address not found  LONG mask;                // must be 32-bits wide!  ENTER("fcMemManager");  if( u32_AlignedAddress )          // are we freeing existing memory?  {//    printk(" freeing AlignedAddress %Xh\n", u32_AlignedAddress);    for( i=0; i<DYNAMIC_ALLOCATIONS; i++) // look for the base address    {//    printk("dynamic_mem[%u].AlignedAddress %lX\n", i, dynamic_mem[i].AlignedAddress);      if( dynamic_mem[i].AlignedAddress == u32_AlignedAddress )      {        alloc_address = dynamic_mem[i].BaseAllocated; // 'success' status        kfree( dynamic_mem[i].BaseAllocated);  // return pages to kernel        dynamic_mem[i].BaseAllocated = 0;   // clear for next use        dynamic_mem[i].AlignedAddress = 0;        break;                        // quit for loop; done      }    }  }  else if( n_alloc )                   // want new memory?  {    t_alloc = n_alloc + (ab - allocBoundary); // pad bytes for alignment//    printk("kmalloc() for Tach alignment: %ld bytes\n", t_alloc);    alloc_address =                  // total bytes (NumberOfBytes)      kmalloc( t_alloc, GFP_KERNEL); // allow thread block to free pages                                   // now mask off least sig. bits of address    if( alloc_address )           // (only if non-NULL)    {                                  // find place to store ptr, so we                                  // can free it later...      for( i=0; i<DYNAMIC_ALLOCATIONS; i++) // look for free slot      {        if( dynamic_mem[i].BaseAllocated == 0) // take 1st available        {          dynamic_mem[i].BaseAllocated = alloc_address;// address from O/S          break;        }      }      mask = (LONG)(ab - 1);            // mask all low-order bits      mask = ~mask;                            // invert bits      ulAddress = (unsigned long)alloc_address;            ulAddress += (ab - allocBoundary);    // add the alignment bytes-                                            // then truncate address...      alloc_address = (void*)(ulAddress & mask);            dynamic_mem[i].AlignedAddress = 	(ULONG)(ulAddress & mask); // 32bit Tach address      memset( alloc_address, 0, n_alloc );  // clear new memory    }    else  // O/S dynamic mem alloc failed!      alloc_address = 0;  // (for debugging breakpt)  }  LEAVE("fcMemManager");  return alloc_address;  // good (or NULL) address}#ifdef MODULEScsi_Host_Template driver_template = CPQFCTS;#include "scsi_module.c"#endif

⌨️ 快捷键说明

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