Ticket #252: patch.diff
File patch.diff, 11.6 KB (added by , 12 years ago) |
---|
-
os_linux.cpp
65 65 #include <stddef.h> // for offsetof() 66 66 #include <sys/uio.h> 67 67 #include <sys/types.h> 68 #include <dirent.h> 68 69 #ifndef makedev // old versions of types.h do not include sysmacros.h 69 70 #include <sys/sysmacros.h> 70 71 #endif … … 122 123 int get_fd() const 123 124 { return m_fd; } 124 125 126 void set_fd(int fd) 127 { m_fd = fd; } 128 125 129 private: 126 130 int m_fd; ///< filedesc, -1 if not open. 127 131 int m_flags; ///< Flags for ::open() … … 901 905 m_fd(-1), pt_cmd(0) 902 906 { 903 907 set_info().info_name = strprintf("%s [megaraid_disk_%02d]", dev_name, m_disknum); 908 set_info().dev_type = strprintf("megaraid,%d", tgt); 904 909 } 905 910 906 911 linux_megaraid_device::~linux_megaraid_device() throw() … … 944 949 ata_device * newdev = smi()->autodetect_sat_device(this, req_buff, len); 945 950 if (newdev) { 946 951 // NOTE: 'this' is now owned by '*newdev' 947 newdev->close();948 newdev->set_err(ENOSYS, "SATA device detected,\n"949 "MegaRAID SAT layer is reportedly buggy, use '-d sat+megaraid,N' to try anyhow");950 952 return newdev; 951 953 } 952 954 } … … 963 965 FILE *fp; 964 966 int report = scsi_debugmode; 965 967 966 if (!linux_smart_device::open()) 967 return false; 968 969 /* Get device HBA */ 970 struct sg_scsi_id sgid; 971 if (ioctl(get_fd(), SG_GET_SCSI_ID, &sgid) == 0) { 972 m_hba = sgid.host_no; 973 } 974 else if (ioctl(get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &m_hba) != 0) { 975 int err = errno; 968 if(sscanf(get_dev_name(),"/dev/bus/%d", &m_hba) == 0) { 969 if (!linux_smart_device::open()) 970 return false; 971 /* Get device HBA */ 972 struct sg_scsi_id sgid; 973 if (ioctl(get_fd(), SG_GET_SCSI_ID, &sgid) == 0) { 974 m_hba = sgid.host_no; 975 } 976 else if (ioctl(get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &m_hba) != 0) { 977 int err = errno; 978 linux_smart_device::close(); 979 return set_err(err, "can't get bus number"); 980 } // we dont need this device anymore 976 981 linux_smart_device::close(); 977 return set_err(err, "can't get bus number");978 982 } 979 980 983 /* Perform mknod of device ioctl node */ 981 984 fp = fopen("/proc/devices", "r"); 982 985 while (fgets(line, sizeof(line), fp) != NULL) { 983 986 n1=0; 984 987 if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) { 985 986 987 988 988 n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0)); 989 if(report > 0) 990 pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno); 991 if (n1 >= 0 || errno == EEXIST) 989 992 break; 990 }991 else if (sscanf(line, "%d megadev%n", &mjr, &n1) == 1 && n1 == 11) {992 993 994 995 993 } 994 else if (sscanf(line, "%d megadev%n", &mjr, &n1) == 1 && n1 == 11) { 995 n1=mknod("/dev/megadev0", S_IFCHR, makedev(mjr, 0)); 996 if(report > 0) 997 pout("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno); 998 if (n1 >= 0 || errno == EEXIST) 996 999 break; 997 }1000 } 998 1001 } 999 1002 fclose(fp); 1000 1003 … … 1010 1013 linux_smart_device::close(); 1011 1014 return set_err(err, "cannot open /dev/megaraid_sas_ioctl_node or /dev/megadev0"); 1012 1015 } 1013 1016 set_fd(m_fd); 1014 1017 return true; 1015 1018 } 1016 1019 1020 1017 1021 bool linux_megaraid_device::close() 1018 1022 { 1019 1023 if (m_fd >= 0) 1020 1024 ::close(m_fd); 1021 1025 m_fd = -1; m_hba = 0; pt_cmd = 0; 1022 return linux_smart_device::close(); 1026 set_fd(m_fd); 1027 return true; 1023 1028 } 1024 1029 1025 1030 bool linux_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop) … … 2313 2318 2314 2319 // DELL? 2315 2320 if (!memcmp(req_buff + 8, "DELL PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8) 2316 || !memcmp(req_buff + 16, "PERC H700", 9) 2321 || !memcmp(req_buff + 16, "PERC H700", 9) || !memcmp(req_buff + 8, "LSI\0",4) 2317 2322 ) { 2318 2323 close(); 2319 2324 set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'"); … … 2433 2438 private: 2434 2439 bool get_dev_list(smart_device_list & devlist, const char * pattern, 2435 2440 bool scan_ata, bool scan_scsi, const char * req_type, bool autodetect); 2436 2441 bool get_dev_megasas(smart_device_list & devlist); 2437 2442 smart_device * missing_option(const char * opt); 2443 int megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf, 2444 size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp); 2445 int megasas_pd_add_list(int bus_no, smart_device_list & devlist); 2438 2446 }; 2439 2447 2440 2448 std::string linux_smart_interface::get_os_version_str() … … 2547 2555 devlist.push_back(dev); 2548 2556 } 2549 2557 } 2550 2558 2551 2559 // free memory 2552 2560 globfree(&globbuf); 2561 return true; 2562 } 2553 2563 2564 // getting devices from LSI SAS MegaRaid, if available 2565 bool linux_smart_interface::get_dev_megasas(smart_device_list & devlist) 2566 { 2567 /* Scanning of disks on MegaRaid device */ 2568 /* Perform mknod of device ioctl node */ 2569 int mjr, n1; 2570 FILE *fp; 2571 char line[128]; 2572 bool scan_megasas = false; 2573 fp = fopen("/proc/devices", "r"); 2574 while (fgets(line, sizeof(line), fp) != NULL) { 2575 n1=0; 2576 if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) { 2577 scan_megasas = true; 2578 n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0)); 2579 if(scsi_debugmode > 0) 2580 pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno); 2581 if (n1 >= 0 || errno == EEXIST) 2582 break; 2583 } 2584 } 2585 fclose(fp); 2586 2587 if(!scan_megasas) 2588 return false; 2589 2590 // getting bus numbers with megasas devices 2591 DIR *dp; 2592 struct dirent *ep; 2593 unsigned int host_no = 0, i; 2594 char sysfsdir[256]; 2595 2596 /* we are using sysfs to get list of all scsi hosts */ 2597 dp = opendir ("/sys/class/scsi_host/"); 2598 if (dp != NULL) 2599 { 2600 while ((ep = readdir (dp)) != NULL) { 2601 if (!sscanf(ep->d_name, "host%d", &host_no)) 2602 continue; 2603 /* proc_name should be megaraid_sas */ 2604 snprintf(sysfsdir, sizeof(sysfsdir) - 1, 2605 "/sys/class/scsi_host/host%d/proc_name", host_no); 2606 if((fp = fopen(sysfsdir, "r")) == NULL) 2607 continue; 2608 if(fgets(line, sizeof(line), fp) != NULL && !strncmp(line,"megaraid_sas",12)) { 2609 megasas_pd_add_list(host_no, devlist); 2610 } 2611 fclose(fp); 2612 2613 } 2614 (void) closedir (dp); 2615 } else { /* sysfs not mounted ? */ 2616 for(i = 0; i <=16; i++) // trying to add devices on first 16 buses 2617 megasas_pd_add_list(i, devlist); 2618 } 2554 2619 return true; 2555 2620 } 2556 2621 … … 2578 2643 get_dev_list(devlist, "/dev/sd[a-z]", false, true, type, autodetect); 2579 2644 // Support up to 104 devices 2580 2645 get_dev_list(devlist, "/dev/sd[a-c][a-z]", false, true, type, autodetect); 2646 // get device list from the megaraid device 2647 get_dev_megasas(devlist); 2581 2648 } 2582 2649 2583 2650 // if we found traditional links, we are done … … 2605 2672 return 0; 2606 2673 } 2607 2674 2675 int 2676 linux_smart_interface::megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf, 2677 size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp) 2678 { 2679 struct megasas_iocpacket ioc; 2680 struct megasas_dcmd_frame *dcmd; 2681 int r; 2682 2683 if ((mbox != NULL && (mboxlen == 0 || mboxlen > MFI_MBOX_SIZE)) || 2684 (mbox == NULL && mboxlen != 0)) 2685 { 2686 errno = EINVAL; 2687 return (-1); 2688 } 2689 2690 bzero(&ioc, sizeof(ioc)); 2691 dcmd = &ioc.frame.dcmd; 2692 ioc.host_no = bus_no; 2693 if (mbox) 2694 bcopy(mbox, dcmd->mbox.w, mboxlen); 2695 dcmd->cmd = MFI_CMD_DCMD; 2696 dcmd->timeout = 0; 2697 dcmd->flags = 0; 2698 dcmd->data_xfer_len = bufsize; 2699 dcmd->opcode = opcode; 2700 2701 if (bufsize > 0) { 2702 dcmd->sge_count = 1; 2703 dcmd->data_xfer_len = bufsize; 2704 dcmd->sgl.sge32[0].phys_addr = (intptr_t)buf; 2705 dcmd->sgl.sge32[0].length = (uint32_t)bufsize; 2706 } 2707 2708 if (bufsize > 0) { 2709 ioc.sge_count = 1; 2710 ioc.sgl_off = offsetof(struct megasas_dcmd_frame, sgl); 2711 ioc.sgl[0].iov_base = buf; 2712 ioc.sgl[0].iov_len = bufsize; 2713 } 2714 int fd; 2715 if ((fd = ::open("/dev/megaraid_sas_ioctl_node", O_RDWR)) <= 0) { 2716 return (errno); 2717 } 2718 2719 r = ioctl(fd, MEGASAS_IOC_FIRMWARE, &ioc); 2720 if (r < 0) { 2721 return (r); 2722 } 2723 2724 if (statusp != NULL) 2725 *statusp = dcmd->cmd_status; 2726 else if (dcmd->cmd_status != MFI_STAT_OK) { 2727 fprintf(stderr, "command %x returned error status %x\n", 2728 opcode, dcmd->cmd_status); 2729 errno = EIO; 2730 return (-1); 2731 } 2732 return (0); 2733 } 2734 2735 int 2736 linux_smart_interface::megasas_pd_add_list(int bus_no, smart_device_list & devlist) 2737 { 2738 struct megasas_pd_list *list; 2739 uint32_t list_size; 2740 unsigned int i; 2741 char line[128]; 2742 smart_device * dev; 2743 2744 /* 2745 * Keep fetching the list in a loop until we have a large enough 2746 * buffer to hold the entire list. 2747 */ 2748 list = NULL; 2749 list_size = 1024; 2750 fetch: 2751 list = (megasas_pd_list *)realloc(list, list_size); 2752 if (list == NULL) 2753 return (-1); 2754 bzero(list, list_size); 2755 if (megasas_dcmd_cmd(bus_no, MFI_DCMD_PD_GET_LIST, list, list_size, NULL, 0, 2756 NULL) < 0) 2757 { 2758 free(list); 2759 return (-1); 2760 } 2761 if (list->size > list_size) { 2762 list_size = list->size; 2763 goto fetch; 2764 } 2765 // adding new to devlist devices 2766 // adding all SCSI devices 2767 for (i = 0; i < list->count; i++) { 2768 if(list->addr[i].scsi_dev_type) 2769 continue; /* non disk device found */ 2770 snprintf(line, sizeof(line) - 1, "/dev/bus/%d", bus_no); 2771 dev = new linux_megaraid_device(this, line, 0, list->addr[i].device_id); 2772 if (dev) 2773 devlist.push_back(dev); 2774 } 2775 free(list); 2776 return (0); 2777 } 2778 2608 2779 // Return kernel release as integer ("2.6.31" -> 206031) 2609 2780 static unsigned get_kernel_release() 2610 2781 { -
megaraid.h
107 107 #define MEGASAS_IOC_FIRMWARE _IOWR(MEGASAS_MAGIC, 1, struct megasas_iocpacket) 108 108 109 109 #define MFI_CMD_PD_SCSI_IO 0x04 110 #define MFI_CMD_DCMD 0x05 110 111 #define MFI_FRAME_SGL64 0x02 111 #define MFI_FRAME_DIR_READ 0x10 112 #define MFI_FRAME_DIR_READ 0x10 113 #define MFI_STAT_OK 0x00 114 #define MFI_DCMD_PD_GET_LIST 0x02010000 115 /* 116 * Number of mailbox bytes in DCMD message frame 117 */ 118 #define MFI_MBOX_SIZE 12 119 #define MAX_IOCTL_SGE 16 112 120 113 #define MAX_ IOCTL_SGE 16121 #define MAX_SYS_PDS 240 114 122 115 123 struct megasas_sge32 { 116 124 … … 220 228 u8 raw[128]; 221 229 struct megasas_header hdr; 222 230 struct megasas_pthru_frame pthru; 231 struct megasas_dcmd_frame dcmd; 223 232 } frame; 224 233 225 234 struct iovec sgl[MAX_IOCTL_SGE]; 235 } __attribute__ ((packed)); 226 236 237 struct megasas_pd_address { 238 u16 device_id; 239 u16 encl_device_id; 240 u8 encl_index; 241 u8 slot_number; 242 u8 scsi_dev_type; /* 0 = disk */ 243 u8 connect_port_bitmap; 244 u64 sas_addr[2]; 245 } __attribute__ ((packed)); 246 247 struct megasas_pd_list { 248 u32 size; 249 u32 count; 250 struct megasas_pd_address addr[MAX_SYS_PDS]; 227 251 } __attribute__ ((packed)); 228 252 229 253 #undef u8 -
scsiata.cpp
141 141 hide_ata(); // Start as SCSI, switch to ATA in autodetect_open() 142 142 else 143 143 hide_scsi(); // ATA always 144 145 if (strcmp(scsidev->get_dev_type(),"scsi")) // RAID devices 146 set_info().dev_type = strprintf("sat+%s", scsidev->get_dev_type()); 144 147 145 148 set_info().info_name = strprintf("%s [%sSAT]", scsidev->get_info_name(), 146 149 (enable_auto ? "SCSI/" : ""));