cciss.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,278 行 · 第 1/5 页
C
2,278 行
switch(c->err_info->CommandStatus) { case CMD_TARGET_STATUS: printk(KERN_WARNING "cciss: cmd %p has " " completed with errors\n", c); if( c->err_info->ScsiStatus) { printk(KERN_WARNING "cciss: cmd %p " "has SCSI Status = %x\n", c, c->err_info->ScsiStatus); } break; case CMD_DATA_UNDERRUN: case CMD_DATA_OVERRUN: /* expected for inquire and report lun commands */ break; case CMD_INVALID: printk(KERN_WARNING "cciss: Cmd %p is " "reported invalid\n", c); return_status = IO_ERROR; break; case CMD_PROTOCOL_ERR: printk(KERN_WARNING "cciss: cmd %p has " "protocol error \n", c); return_status = IO_ERROR; break;case CMD_HARDWARE_ERR: printk(KERN_WARNING "cciss: cmd %p had " " hardware error\n", c); return_status = IO_ERROR; break; case CMD_CONNECTION_LOST: printk(KERN_WARNING "cciss: cmd %p had " "connection lost\n", c); return_status = IO_ERROR; break; case CMD_ABORTED: printk(KERN_WARNING "cciss: cmd %p was " "aborted\n", c); return_status = IO_ERROR; break; case CMD_ABORT_FAILED: printk(KERN_WARNING "cciss: cmd %p reports " "abort failed\n", c); return_status = IO_ERROR; break; case CMD_UNSOLICITED_ABORT: printk(KERN_WARNING "cciss%d: unsolicited abort %p\n", ctlr, c); if (c->retry_count < MAX_CMD_RETRIES) { printk(KERN_WARNING "cciss%d: retrying %p\n", ctlr, c); c->retry_count++; /* erase the old error information */ memset(c->err_info, 0, sizeof(ErrorInfo_struct)); return_status = IO_OK; INIT_COMPLETION(wait); goto resend_cmd2; } return_status = IO_ERROR; break; default: printk(KERN_WARNING "cciss: cmd %p returned " "unknown status %x\n", c, c->err_info->CommandStatus); return_status = IO_ERROR; } } /* unlock the buffers from DMA */ pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val, size, PCI_DMA_BIDIRECTIONAL); cmd_free(h, c, 0); return(return_status);}static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq, unsigned int total_size, unsigned int block_size, InquiryData_struct *inq_buff, drive_info_struct *drv){ int return_code; memset(inq_buff, 0, sizeof(InquiryData_struct)); if (withirq) return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1, TYPE_CMD); else return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1, NULL, TYPE_CMD); if (return_code == IO_OK) { if(inq_buff->data_byte[8] == 0xFF) { printk(KERN_WARNING "cciss: reading geometry failed, volume " "does not support reading geometry\n"); drv->block_size = block_size; drv->nr_blocks = total_size; drv->heads = 255; drv->sectors = 32; // Sectors per track drv->cylinders = total_size / 255 / 32; } else { unsigned int t; drv->block_size = block_size; drv->nr_blocks = total_size; drv->heads = inq_buff->data_byte[6]; drv->sectors = inq_buff->data_byte[7]; drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8; drv->cylinders += inq_buff->data_byte[5]; drv->raid_level = inq_buff->data_byte[8]; t = drv->heads * drv->sectors; if (t > 1) { drv->cylinders = total_size/t; } } } else { /* Get geometry failed */ printk(KERN_WARNING "cciss: reading geometry failed, " "continuing with default geometry\n"); drv->block_size = block_size; drv->nr_blocks = total_size; drv->heads = 255; drv->sectors = 32; // Sectors per track drv->cylinders = total_size / 255 / 32; } printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", drv->heads, drv->sectors, drv->cylinders);}static voidcciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, int withirq, unsigned int *total_size, unsigned int *block_size){ int return_code; memset(buf, 0, sizeof(*buf)); if (withirq) return_code = sendcmd_withirq(CCISS_READ_CAPACITY, ctlr, buf, sizeof(*buf), 1, logvol, 0, TYPE_CMD); else return_code = sendcmd(CCISS_READ_CAPACITY, ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL, TYPE_CMD); if (return_code == IO_OK) { *total_size = be32_to_cpu(*((__be32 *) &buf->total_size[0]))+1; *block_size = be32_to_cpu(*((__be32 *) &buf->block_size[0])); } else { /* read capacity command failed */ printk(KERN_WARNING "cciss: read capacity failed\n"); *total_size = 0; *block_size = BLOCK_SIZE; } printk(KERN_INFO " blocks= %u block_size= %d\n", *total_size, *block_size); return;}static int register_new_disk(ctlr_info_t *h){ struct gendisk *disk; int ctlr = h->ctlr; int i; int num_luns; int logvol; int new_lun_found = 0; int new_lun_index = 0; int free_index_found = 0; int free_index = 0; ReportLunData_struct *ld_buff = NULL; ReadCapdata_struct *size_buff = NULL; InquiryData_struct *inq_buff = NULL; int return_code; int listlength = 0; __u32 lunid = 0; unsigned int block_size; unsigned int total_size; if (!capable(CAP_SYS_RAWIO)) return -EPERM; /* if we have no space in our disk array left to add anything */ if( h->num_luns >= CISS_MAX_LUN) return -EINVAL; ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL); if (ld_buff == NULL) goto mem_msg; memset(ld_buff, 0, sizeof(ReportLunData_struct)); size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); if (size_buff == NULL) goto mem_msg; inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); if (inq_buff == NULL) goto mem_msg; return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD); if( return_code == IO_OK) { // printk("LUN Data\n--------------------------\n"); listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24; listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16; listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8; listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]); } else /* reading number of logical volumes failed */ { printk(KERN_WARNING "cciss: report logical volume" " command failed\n"); listlength = 0; goto free_err; } num_luns = listlength / 8; // 8 bytes pre entry if (num_luns > CISS_MAX_LUN) { num_luns = CISS_MAX_LUN; }#ifdef CCISS_DEBUG printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0], ld_buff->LUNListLength[1], ld_buff->LUNListLength[2], ld_buff->LUNListLength[3], num_luns);#endif for(i=0; i< num_luns; i++) { int j; int lunID_found = 0; lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24; lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16; lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8; lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); /* check to see if this is a new lun */ for(j=0; j <= h->highest_lun; j++) {#ifdef CCISS_DEBUG printk("Checking %d %x against %x\n", j,h->drv[j].LunID, lunid);#endif /* CCISS_DEBUG */ if (h->drv[j].LunID == lunid) { lunID_found = 1; break; } } if( lunID_found == 1) continue; else { /* It is the new lun we have been looking for */#ifdef CCISS_DEBUG printk("new lun found at %d\n", i);#endif /* CCISS_DEBUG */ new_lun_index = i; new_lun_found = 1; break; } } if (!new_lun_found) { printk(KERN_WARNING "cciss: New Logical Volume not found\n"); goto free_err; } /* Now find the free index */ for(i=0; i <CISS_MAX_LUN; i++) {#ifdef CCISS_DEBUG printk("Checking Index %d\n", i);#endif /* CCISS_DEBUG */ if(h->drv[i].LunID == 0) {#ifdef CCISS_DEBUG printk("free index found at %d\n", i);#endif /* CCISS_DEBUG */ free_index_found = 1; free_index = i; break; } } if (!free_index_found) { printk(KERN_WARNING "cciss: unable to find free slot for disk\n"); goto free_err; } logvol = free_index; h->drv[logvol].LunID = lunid; /* there could be gaps in lun numbers, track hightest */ if(h->highest_lun < lunid) h->highest_lun = logvol; cciss_read_capacity(ctlr, logvol, size_buff, 1, &total_size, &block_size); cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size, inq_buff, &h->drv[logvol]); h->drv[logvol].usage_count = 0; ++h->num_luns; /* setup partitions per disk */ disk = h->gendisk[logvol]; set_capacity(disk, h->drv[logvol].nr_blocks); add_disk(disk);freeret: kfree(ld_buff); kfree(size_buff); kfree(inq_buff); return (logvol);mem_msg: printk(KERN_ERR "cciss: out of memory\n");free_err: logvol = -1; goto freeret;}/* * Wait polling for a command to complete. * The memory mapped FIFO is polled for the completion. * Used only at init time, interrupts from the HBA are disabled. */static unsigned long pollcomplete(int ctlr){ unsigned long done; int i; /* Wait (up to 20 seconds) for a command to complete */ for (i = 20 * HZ; i > 0; i--) { done = hba[ctlr]->access.command_completed(hba[ctlr]); if (done == FIFO_EMPTY) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1); } else return (done); } /* Invalid address to tell caller we ran out of time */ return 1;}/* * Send a command to the controller, and wait for it to complete. * Only used at init time. */static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num, /* 0: address the controller, 1: address logical volume log_unit, 2: periph device address is scsi3addr */ unsigned int log_unit, __u8 page_code, unsigned char *scsi3addr, int cmd_type){ CommandList_struct *c; int i; unsigned long complete; ctlr_info_t *info_p= hba[ctlr]; u64bit buff_dma_handle; int status; if ((c = cmd_alloc(info_p, 1)) == NULL) { printk(KERN_WARNING "cciss: unable to get memory"); return(IO_ERROR); } status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num, log_unit, page_code, scsi3addr, cmd_type); if (status != IO_OK) { cmd_free(info_p, c, 1); return status; }resend_cmd1: /* * Disable interrupt */#ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss: turning intr off\n");#endif /* CCISS_DEBUG */ info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); /* Make sure there is room in the command FIFO */ /* Actually it should be completely empty at this time. */ for (i = 200000; i > 0; i--) { /* if fifo isn't full go */ if (!(info_p->access.fifo_full(info_p))) { break; } udelay(10); printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full," " waiting!\n", ctlr); } /* * Send the cmd */ info_p->access.submit_command(info_p, c); complete = pollcomplete(ctlr);#ifdef CCISS_DEBUG printk(KERN_DEBUG "cciss: command completed\n");#endif /* CCISS_DEBUG */ if (complete != 1) { if ( (complete & CISS_ERROR_BIT) && (complete & ~CISS_ERROR_BIT) == c->busaddr) { /* if data overrun or underun on Report command ignore it */ if (((c->Request.CDB[0] == CISS_REPORT_LOG) || (c->Request.CDB[0] == CISS_REPORT_PHYS) || (c->Request.CDB[0] == CISS_INQUIRY)) && ((c->err_info->CommandStatus == CMD_DATA_OVERRUN) || (c->err_info->CommandStatus == CMD_DATA_UNDERRUN) )) { complete = c->busaddr; } else { if (c->err_info->CommandStatus == CMD_UNSOLICITED_ABORT) { printk(KERN_WARNING "cciss%d: " "unsolicited abort %p\n", ctlr, c); if (c->retry_count < MAX_CMD_RETRIES) { printk(KERN_WARNING "cciss%d: retrying %p\n", ctlr, c); c->retry_count++; /* erase the old error */ /* information */ memset(c->err_info, 0, sizeof(ErrorInfo_struct)); goto resend_cmd1; } else { printk(KERN_WARNING "cciss%d: retried %p too " "many times\n", ctlr, c); status = IO_ERROR; goto cleanup1; } } printk(KERN_WARNING "ciss ciss%d: sendcmd" " Error %x \n", ctlr, c->err_info->CommandStatus); printk(KERN_WARNING "ciss ciss%d: sendcmd" " offensive info\n" " size %x\n num %x value %x\n", ctlr, c->err_info->MoreErrInfo.Invalid_Cmd.offense_size, c->err_info->MoreErrInfo.Invalid_Cmd.offense_num, c->err_info->MoreErrInfo.Invalid_Cmd.offense_value); status = IO_ERROR; goto cleanup1; } } if (complete != c->busaddr) { printk( KERN_WARNING "cciss cciss%d: SendCmd " "Invalid command list address returned! (%lx)\n",
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?