📄 cciss.c
字号:
ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL); if (ld_buff == NULL) { printk(KERN_ERR "cciss: out of memory\n"); return; } memset(ld_buff, 0, sizeof(ReportLunData_struct)); size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); if (size_buff == NULL) { printk(KERN_ERR "cciss: out of memory\n"); kfree(ld_buff); return; } inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); if (inq_buff == NULL) { printk(KERN_ERR "cciss: out of memory\n"); kfree(ld_buff); kfree(size_buff); return; } /* Get the firmware version */ return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, sizeof(InquiryData_struct), 0, 0 ,0 ); if (return_code == IO_OK) { hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32]; hba[cntl_num]->firm_ver[1] = inq_buff->data_byte[33]; hba[cntl_num]->firm_ver[2] = inq_buff->data_byte[34]; hba[cntl_num]->firm_ver[3] = inq_buff->data_byte[35]; } else /* send command failed */ { printk(KERN_WARNING "cciss: unable to determine firmware" " version of controller\n"); } /* Get the number of logical volumes */ return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff, sizeof(ReportLunData_struct), 0, 0, 0 ); if( return_code == IO_OK) {#ifdef CCISS_DEBUG printk("LUN Data\n--------------------------\n");#endif /* CCISS_DEBUG */ 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; } hba[cntl_num]->num_luns = listlength / 8; // 8 bytes pre entry if (hba[cntl_num]->num_luns > CISS_MAX_LUN) { printk(KERN_ERR "ciss: only %d number of logical volumes supported\n", CISS_MAX_LUN); hba[cntl_num]->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], hba[cntl_num]->num_luns);#endif /* CCISS_DEBUG */ for(i=0; i< hba[cntl_num]->num_luns ; i++) { 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]); hba[cntl_num]->drv[i].LunID = lunid;#ifdef CCISS_DEBUG printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i, ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID);#endif /* CCISS_DEBUG */ memset(size_buff, 0, sizeof(ReadCapdata_struct)); return_code = sendcmd(CCISS_READ_CAPACITY, cntl_num, size_buff, sizeof( ReadCapdata_struct), 1, i, 0 ); if (return_code == IO_OK) { total_size = (0xff & (unsigned int)(size_buff->total_size[0])) << 24; total_size |= (0xff & (unsigned int)(size_buff->total_size[1])) << 16; total_size |= (0xff & (unsigned int)(size_buff->total_size[2])) << 8; total_size |= (0xff & (unsigned int) (size_buff->total_size[3])); total_size++; // command returns highest block address block_size = (0xff & (unsigned int)(size_buff->block_size[0])) << 24; block_size |= (0xff & (unsigned int)(size_buff->block_size[1])) << 16; block_size |= (0xff & (unsigned int)(size_buff->block_size[2])) << 8; block_size |= (0xff & (unsigned int)(size_buff->block_size[3])); } else /* read capacity command failed */ { printk(KERN_WARNING "cciss: read capacity failed\n"); total_size = block_size = 0; } printk(KERN_INFO " blocks= %d block_size= %d\n", total_size, block_size); /* Execute the command to read the disk geometry */ memset(inq_buff, 0, sizeof(InquiryData_struct)); return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, sizeof(InquiryData_struct), 1, i ,0xC1 ); 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"); hba[cntl_num]->drv[i].block_size = block_size; hba[cntl_num]->drv[i].nr_blocks = total_size; hba[cntl_num]->drv[i].heads = 255; hba[cntl_num]->drv[i].sectors = 32; // Sectors per track hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32; } else { hba[cntl_num]->drv[i].block_size = block_size; hba[cntl_num]->drv[i].nr_blocks = total_size; hba[cntl_num]->drv[i].heads = inq_buff->data_byte[6]; hba[cntl_num]->drv[i].sectors = inq_buff->data_byte[7]; hba[cntl_num]->drv[i].cylinders = (inq_buff->data_byte[4] & 0xff) << 8; hba[cntl_num]->drv[i].cylinders += inq_buff->data_byte[5]; } } else /* Get geometry failed */ { printk(KERN_WARNING "cciss: reading geometry failed, continuing with default geometry\n"); hba[cntl_num]->drv[i].block_size = block_size; hba[cntl_num]->drv[i].nr_blocks = total_size; hba[cntl_num]->drv[i].heads = 255; hba[cntl_num]->drv[i].sectors = 32; // Sectors per track hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32; } printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n", hba[cntl_num]->drv[i].heads, hba[cntl_num]->drv[i].sectors, hba[cntl_num]->drv[i].cylinders); } kfree(ld_buff); kfree(size_buff);} /* Function to find the first free pointer into our hba[] array *//* Returns -1 if no free entries are left. */static int alloc_cciss_hba(void){ int i; for(i=0; i< MAX_CTLR; i++) { if (hba[i] == NULL) { hba[i] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL); if(hba[i]==NULL) { printk(KERN_ERR "cciss: out of memory.\n"); return (-1); } return (i); } } printk(KERN_WARNING "cciss: This driver supports a maximum" " of 8 controllers.\n"); return(-1);}static void free_hba(int i){ kfree(hba[i]); hba[i]=NULL;}/* * This is it. Find all the controllers and register them. I really hate * stealing all these major device numbers. * returns the number of block devices registered. */static int __init cciss_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){ request_queue_t *q; int i; int j; printk(KERN_DEBUG "cciss: Device 0x%x has been found at" " bus %d dev %d func %d\n", pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); i = alloc_cciss_hba(); if( i < 0 ) return (-1); memset(hba[i], 0, sizeof(ctlr_info_t)); if (cciss_pci_init(hba[i], pdev) != 0) { free_hba(i); return (-1); } sprintf(hba[i]->devname, "cciss%d", i); hba[i]->ctlr = i; hba[i]->pdev = pdev; if( register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops)) { printk(KERN_ERR "cciss: Unable to get major number " "%d for %s\n", MAJOR_NR+i, hba[i]->devname); free_hba(i); return(-1); } /* make sure the board interrupts are off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); if( request_irq(hba[i]->intr, do_cciss_intr, SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) { printk(KERN_ERR "ciss: Unable to get irq %d for %s\n", hba[i]->intr, hba[i]->devname); unregister_blkdev( MAJOR_NR+i, hba[i]->devname); free_hba(i); return(-1); } hba[i]->cmd_pool_bits = (__u32*)kmalloc( ((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL); hba[i]->cmd_pool = (CommandList_struct *)pci_alloc_consistent( hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), &(hba[i]->cmd_pool_dhandle)); hba[i]->errinfo_pool = (ErrorInfo_struct *)pci_alloc_consistent( hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), &(hba[i]->errinfo_pool_dhandle)); if((hba[i]->cmd_pool_bits == NULL) || (hba[i]->cmd_pool == NULL) || (hba[i]->errinfo_pool == NULL)) { if(hba[i]->cmd_pool_bits) kfree(hba[i]->cmd_pool_bits); if(hba[i]->cmd_pool) pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); if(hba[i]->errinfo_pool) pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); free_irq(hba[i]->intr, hba[i]); unregister_blkdev(MAJOR_NR+i, hba[i]->devname); free_hba(i); printk( KERN_ERR "cciss: out of memory"); return(-1); } /* Initialize the pdev driver private data. have it point to hba[i]. */ pci_set_drvdata(pdev, hba[i]); /* command and error info recs zeroed out before they are used */ memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32));#ifdef CCISS_DEBUG printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i);#endif /* CCISS_DEBUG */ cciss_getgeometry(i); /* Turn the interrupts on so we can service requests */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); cciss_procinit(i); q = BLK_DEFAULT_QUEUE(MAJOR_NR + i); q->queuedata = hba[i]; blk_init_queue(q, do_cciss_request); blk_queue_headactive(q, 0); /* fill in the other Kernel structs */ blksize_size[MAJOR_NR+i] = hba[i]->blocksizes; hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes; read_ahead[MAJOR_NR+i] = READ_AHEAD; /* Set the pointers to queue functions */ q->back_merge_fn = cpq_back_merge_fn; q->front_merge_fn = cpq_front_merge_fn; q->merge_requests_fn = cpq_merge_requests_fn; /* Fill in the gendisk data */ hba[i]->gendisk.major = MAJOR_NR + i; hba[i]->gendisk.major_name = "cciss"; hba[i]->gendisk.minor_shift = NWD_SHIFT; hba[i]->gendisk.max_p = MAX_PART; hba[i]->gendisk.part = hba[i]->hd; hba[i]->gendisk.sizes = hba[i]->sizes; hba[i]->gendisk.nr_real = hba[i]->num_luns; /* Get on the disk list */ add_gendisk(&(hba[i]->gendisk)); cciss_geninit(i); for(j=0; j<NWD; j++) register_disk(&(hba[i]->gendisk), MKDEV(MAJOR_NR+i, j <<4), MAX_PART, &cciss_fops, hba[i]->drv[j].nr_blocks); return(1);}static void __devexit cciss_remove_one (struct pci_dev *pdev){ ctlr_info_t *tmp_ptr; int i; if (pci_get_drvdata(pdev) == NULL) { printk( KERN_ERR "cciss: Unable to remove device \n"); return; } tmp_ptr = pci_get_drvdata(pdev); i = tmp_ptr->ctlr; if (hba[i] == NULL) { printk(KERN_ERR "cciss: device appears to " "already be removed \n"); return; } /* Turn board interrupts off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); free_irq(hba[i]->intr, hba[i]); pci_set_drvdata(pdev, NULL); iounmap((void*)hba[i]->vaddr); unregister_blkdev(MAJOR_NR+i, hba[i]->devname); remove_proc_entry(hba[i]->devname, proc_cciss); /* remove it from the disk list */ del_gendisk(&(hba[i]->gendisk)); pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle); pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); kfree(hba[i]->cmd_pool_bits); free_hba(i);} static struct pci_driver cciss_pci_driver = { name: "cciss", probe: cciss_init_one, remove: __devexit_p(cciss_remove_one), id_table: cciss_pci_device_id, /* id_table */};/** This is it. Register the PCI driver information for the cards we control* the OS will call our registered routines when it finds one of our cards. */int __init cciss_init(void){ printk(KERN_INFO DRIVER_NAME "\n"); /* Register for out PCI devices */ if (pci_register_driver(&cciss_pci_driver) > 0 ) return 0; else return -ENODEV; }EXPORT_NO_SYMBOLS;static int __init init_cciss_module(void){ return ( cciss_init());}static void __exit cleanup_cciss_module(void){ int i; pci_unregister_driver(&cciss_pci_driver); /* double check that all controller entrys have been removed */ for (i=0; i< MAX_CTLR; i++) { if (hba[i] != NULL) { printk(KERN_WARNING "cciss: had to remove" " controller %d\n", i); cciss_remove_one(hba[i]->pdev); } } remove_proc_entry("cciss", proc_root_driver);}module_init(init_cciss_module);module_exit(cleanup_cciss_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -