cpqfctsinit.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,099 行 · 第 1/5 页
C
2,099 行
static char buf[300]; CPQFCHBA *cpqfcHBA; int BusSpeed, BusWidth; // get the pointer to our Scsi layer HBA buffer cpqfcHBA = (CPQFCHBA *)HostAdapter->hostdata; BusWidth = (cpqfcHBA->fcChip.Registers.PCIMCTR &0x4) > 0 ? 64 : 32; if( cpqfcHBA->fcChip.Registers.TYconfig.value & 0x80000000) BusSpeed = 66; else BusSpeed = 33; sprintf(buf, "%s: WWN %08X%08X\n on PCI bus %d device 0x%02x irq %d IObaseL 0x%x, MEMBASE 0x%x\nPCI bus width %d bits, bus speed %d MHz\nFCP-SCSI Driver v%d.%d.%d", cpqfcHBA->fcChip.Name, cpqfcHBA->fcChip.Registers.wwn_hi, cpqfcHBA->fcChip.Registers.wwn_lo, cpqfcHBA->PciDev->bus->number, cpqfcHBA->PciDev->device, HostAdapter->irq, cpqfcHBA->fcChip.Registers.IOBaseL, cpqfcHBA->fcChip.Registers.MemBase, BusWidth, BusSpeed, VER_MAJOR, VER_MINOR, VER_SUBMINOR); cpqfcTSDecodeGBICtype( &cpqfcHBA->fcChip, &buf[ strlen(buf)]); cpqfcTSGetLPSM( &cpqfcHBA->fcChip, &buf[ strlen(buf)]); return buf;}//// /proc/scsi support. The following routines allow us to do 'normal'// sprintf like calls to return the currently requested piece (buflenght// chars, starting at bufoffset) of the file. Although procfs allows for// a 1 Kb bytes overflow after te supplied buffer, I consider it bad // programming to use it to make programming a little simpler. This piece// of coding is borrowed from ncr53c8xx.c with some modifications //struct info_str{ char *buffer; // Pointer to output buffer int buflength; // It's length int bufoffset; // File offset corresponding with buf[0] int buffillen; // Current filled length int filpos; // Current file offset};static void copy_mem_info(struct info_str *info, char *data, int datalen){ if (info->filpos < info->bufoffset) { // Current offset before buffer offset if (info->filpos + datalen <= info->bufoffset) { info->filpos += datalen; // Discard if completely before buffer return; } else { // Partial copy, set to begin data += (info->bufoffset - info->filpos); datalen -= (info->bufoffset - info->filpos); info->filpos = info->bufoffset; } } info->filpos += datalen; // Update current offset if (info->buffillen == info->buflength) // Buffer full, discard return; if (info->buflength - info->buffillen < datalen) // Overflows buffer ? datalen = info->buflength - info->buffillen; memcpy(info->buffer + info->buffillen, data, datalen); info->buffillen += datalen;}static int copy_info(struct info_str *info, char *fmt, ...){ va_list args; char buf[400]; int len; va_start(args, fmt); len = vsprintf(buf, fmt, args); va_end(args); copy_mem_info(info, buf, len); return len;}// Routine to get data for /proc RAM filesystem//int cpqfcTS_proc_info (struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int inout){ struct scsi_cmnd *DumCmnd; struct scsi_device *ScsiDev; int Chan, Targ, i; struct info_str info; CPQFCHBA *cpqfcHBA; PTACHYON fcChip; PFC_LOGGEDIN_PORT pLoggedInPort; char buf[81]; if (inout) return -EINVAL; // get the pointer to our Scsi layer HBA buffer cpqfcHBA = (CPQFCHBA *)host->hostdata; fcChip = &cpqfcHBA->fcChip; *start = buffer; info.buffer = buffer; info.buflength = length; info.bufoffset = offset; info.filpos = 0; info.buffillen = 0; copy_info(&info, "Driver version = %d.%d.%d", VER_MAJOR, VER_MINOR, VER_SUBMINOR); cpqfcTSDecodeGBICtype( &cpqfcHBA->fcChip, &buf[0]); cpqfcTSGetLPSM( &cpqfcHBA->fcChip, &buf[ strlen(buf)]); copy_info(&info, "%s\n", buf); #define DISPLAY_WWN_INFO#ifdef DISPLAY_WWN_INFO ScsiDev = scsi_get_host_dev (host); if (!ScsiDev) return -ENOMEM; DumCmnd = scsi_get_command (ScsiDev, GFP_KERNEL); if (!DumCmnd) { scsi_free_host_dev (ScsiDev); return -ENOMEM; } copy_info(&info, "WWN database: (\"port_id: 000000\" means disconnected)\n"); for ( Chan=0; Chan <= host->max_channel; Chan++) { DumCmnd->device->channel = Chan; for (Targ=0; Targ <= host->max_id; Targ++) { DumCmnd->device->id = Targ; if ((pLoggedInPort = fcFindLoggedInPort( fcChip, DumCmnd, // search Scsi Nexus 0, // DON'T search list for FC port id NULL, // DON'T search list for FC WWN NULL))){ // DON'T care about end of list copy_info(&info, "Host: scsi%d Channel: %02d TargetId: %02d -> WWN: ", host->host_no, Chan, Targ); for( i=3; i>=0; i--) // copy the LOGIN port's WWN copy_info(&info, "%02X", pLoggedInPort->u.ucWWN[i]); for( i=7; i>3; i--) // copy the LOGIN port's WWN copy_info(&info, "%02X", pLoggedInPort->u.ucWWN[i]); copy_info(&info, " port_id: %06X\n", pLoggedInPort->port_id); } } } scsi_put_command (DumCmnd); scsi_free_host_dev (ScsiDev);#endif // Unfortunately, the proc_info buffer isn't big enough// for everything we would like...// For FC stats, compile this and turn off WWN stuff above //#define DISPLAY_FC_STATS#ifdef DISPLAY_FC_STATS// get the Fibre Channel statistics { int DeltaSecs = (jiffies - cpqfcHBA->fcStatsTime) / HZ; int days,hours,minutes,secs; days = DeltaSecs / (3600*24); // days hours = (DeltaSecs% (3600*24)) / 3600; // hours minutes = (DeltaSecs%3600 /60); // minutes secs = DeltaSecs%60; // secscopy_info( &info, "Fibre Channel Stats (time dd:hh:mm:ss %02u:%02u:%02u:%02u\n", days, hours, minutes, secs); } cpqfcHBA->fcStatsTime = jiffies; // (for next delta) copy_info( &info, " LinkUp %9u LinkDown %u\n", fcChip->fcStats.linkUp, fcChip->fcStats.linkDown); copy_info( &info, " Loss of Signal %9u Loss of Sync %u\n", fcChip->fcStats.LossofSignal, fcChip->fcStats.LossofSync); copy_info( &info, " Discarded Frames %9u Bad CRC Frame %u\n", fcChip->fcStats.Dis_Frm, fcChip->fcStats.Bad_CRC); copy_info( &info, " TACH LinkFailTX %9u TACH LinkFailRX %u\n", fcChip->fcStats.linkFailTX, fcChip->fcStats.linkFailRX); copy_info( &info, " TACH RxEOFa %9u TACH Elastic Store %u\n", fcChip->fcStats.Rx_EOFa, fcChip->fcStats.e_stores); copy_info( &info, " BufferCreditWait %9uus TACH FM Inits %u\n", fcChip->fcStats.BB0_Timer*10, fcChip->fcStats.FMinits ); copy_info( &info, " FC-2 Timeouts %9u FC-2 Logouts %u\n", fcChip->fcStats.timeouts, fcChip->fcStats.logouts); copy_info( &info, " FC-2 Aborts %9u FC-4 Aborts %u\n", fcChip->fcStats.FC2aborted, fcChip->fcStats.FC4aborted); // clear the counters cpqfcTSClearLinkStatusCounters( fcChip);#endif return info.buffillen;}#if DEBUG_CMNDUCHAR *ScsiToAscii( UCHAR ScsiCommand){/*++Routine Description: Converts a SCSI command to a text string for debugging purposes.Arguments: ScsiCommand -- hex value SCSI CommandReturn Value: An ASCII, null-terminated string if found, else returns NULL.Original code from M. McGowen, Compaq--*/ switch (ScsiCommand) { case 0x00: return( "Test Unit Ready" ); case 0x01: return( "Rezero Unit or Rewind" ); case 0x02: return( "Request Block Address" ); case 0x03: return( "Requese Sense" ); case 0x04: return( "Format Unit" ); case 0x05: return( "Read Block Limits" ); case 0x07: return( "Reassign Blocks" ); case 0x08: return( "Read (6)" ); case 0x0a: return( "Write (6)" ); case 0x0b: return( "Seek (6)" ); case 0x12: return( "Inquiry" ); case 0x15: return( "Mode Select (6)" ); case 0x16: return( "Reserve" ); case 0x17: return( "Release" ); case 0x1a: return( "ModeSen(6)" ); case 0x1b: return( "Start/Stop Unit" ); case 0x1c: return( "Receive Diagnostic Results" ); case 0x1d: return( "Send Diagnostic" ); case 0x25: return( "Read Capacity" ); case 0x28: return( "Read (10)" ); case 0x2a: return( "Write (10)" ); case 0x2b: return( "Seek (10)" ); case 0x2e: return( "Write and Verify" ); case 0x2f: return( "Verify" ); case 0x34: return( "Pre-Fetch" ); case 0x35: return( "Synchronize Cache" ); case 0x37: return( "Read Defect Data (10)" ); case 0x3b: return( "Write Buffer" ); case 0x3c: return( "Read Buffer" ); case 0x3e: return( "Read Long" ); case 0x3f: return( "Write Long" ); case 0x41: return( "Write Same" ); case 0x4c: return( "Log Select" ); case 0x4d: return( "Log Sense" ); case 0x56: return( "Reserve (10)" ); case 0x57: return( "Release (10)" ); case 0xa0: return( "ReportLuns" ); case 0xb7: return( "Read Defect Data (12)" ); case 0xca: return( "Peripheral Device Addressing SCSI Passthrough" ); case 0xcb: return( "Compaq Array Firmware Passthrough" ); default: return( NULL ); }} // end ScsiToAscii()void cpqfcTS_print_scsi_cmd(Scsi_Cmnd * cmd){printk("cpqfcTS: (%s) chnl 0x%02x, trgt = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", ScsiToAscii( cmd->cmnd[0]), cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);if( cmd->cmnd[0] == 0) // Test Unit Ready?{ int i; printk("Cmnd->request_bufflen = 0x%X, ->use_sg = %d, ->bufflen = %d\n", cmd->request_bufflen, cmd->use_sg, cmd->bufflen); printk("Cmnd->request_buffer = %p, ->sglist_len = %d, ->buffer = %p\n", cmd->request_buffer, cmd->sglist_len, cmd->buffer); for (i = 0; i < cmd->cmd_len; i++) printk("0x%02x ", cmd->cmnd[i]); printk("\n");}}#endif /* DEBUG_CMND */static void QueCmndOnBoardLock( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd){ int i; for( i=0; i< CPQFCTS_REQ_QUEUE_LEN; i++) { // find spare slot if( cpqfcHBAdata->BoardLockCmnd[i] == NULL ) { cpqfcHBAdata->BoardLockCmnd[i] = Cmnd;// printk(" BoardLockCmnd[%d] %p Queued, chnl/target/lun %d/%d/%d\n",// i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun); break; } } if( i >= CPQFCTS_REQ_QUEUE_LEN) { printk(" cpqfcTS WARNING: Lost Cmnd %p on BoardLock Q full!", Cmnd); }}static void QueLinkDownCmnd( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?