Thursday, November 19, 2015

Issue SATA commands directly through IOCTL

Directly write to SATA interface to perform simple read and write operation on a storage device.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <scsi/sg.h>
#include <scsi/scsi.h>
main()
{
 int fd;
 unsigned char buffer[512];

 fd=open("/dev/sda", O_RDWR );

 ReadSector(fd, 0, 1, buffer);
 WriteSector(fd, 0, 1, buffer);
}


// return 0 on fail
// return 1 on success
int ReadSector(int fd, int sector, int nsec, unsigned char *pbuffer)
{
 int res;
 int t_length;
 sg_io_hdr_t io_hdr;
 unsigned char sense_b[SG_MAX_SENSE];
 unsigned char rdCmdBlk6[6];

 t_length = 512;              // 512 bytes transferred per sec

// Prepare SCSI READ (6) command
 rdCmdBlk6[0]  = READ_6;           // COMMAND
 rdCmdBlk6[1]  = (sector & 0xFF0000 ) >> 16;           // LBA
 rdCmdBlk6[2]  = (sector & 0xff00) >> 8;         // LBA
 rdCmdBlk6[3]  = sector & 0xff;  // LBA
 rdCmdBlk6[4]  = nsec;
 rdCmdBlk6[5]  = 0x00;

// Prepare the sg_io_hdr_t structure
 memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
 io_hdr.interface_id = 'S';                  // Always set to 'S' for sg driver
 io_hdr.cmd_len = sizeof(rdCmdBlk6);         // Size of SCSI command
 io_hdr.mx_sb_len  = sizeof(sense_b);        // Max sense buffer size(for error)
 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; // Data transfer direction(no data)
 io_hdr.dxfer_len = nsec*t_length;                // Data transfer length(512)
 io_hdr.dxferp = pbuffer;                       // Data transfer buffer(none)
 io_hdr.cmdp = rdCmdBlk6;                    // SCSI command buffer
 io_hdr.sbp = sense_b;                       // Sense buffer
 io_hdr.timeout = 5000;                      // Timeout(5s)

// Sends the command to device
 if ((res = ioctl(fd, SG_IO, &io_hdr)) < 0) {
   return 0;
 }

// Error processing
 if ( ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) || // check info
      (io_hdr.masked_status != 0x00) ||                  // check status(0 if ioctl success)
      (io_hdr.msg_status != 0x00) ||                     // check message status
      (io_hdr.host_status != 0x00) ||                    // check host status
      (io_hdr.driver_status != 0x00) )                   // check driver status
 {
   return 0;
 } else {
   return 1;
 }
}

int WriteSector(int fd, int sector, int nsec, unsigned char *pbuffer)
{
 int res;
 int t_length;
 sg_io_hdr_t io_hdr;
 unsigned char sense_b[SG_MAX_SENSE];
 unsigned char rdCmdBlk6[6] ;
 t_length = 512;              // 512 bytes transferred per sec

// Prepare SCSI WRITE (6) command
 rdCmdBlk6[0]  = WRITE_6;           // COMMAND
 rdCmdBlk6[1]  = (sector & 0xFF0000 ) >> 16;           // LBA
 rdCmdBlk6[2]  = (sector & 0xff00) >> 8;         // LBA
 rdCmdBlk6[3]  = sector & 0xff;  // LBA
 rdCmdBlk6[4]  = nsec;
 rdCmdBlk6[5]  = 0x00;

// Prepare the sg_io_hdr_t structure
 memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
 io_hdr.interface_id = 'S';                  // Always set to 'S' for sg driver
 io_hdr.cmd_len = sizeof(rdCmdBlk6);         // Size of SCSI command
 io_hdr.mx_sb_len  = sizeof(sense_b);        // Max sense buffer size(for error)
 io_hdr.dxfer_direction = SG_DXFER_TO_DEV; // Data transfer direction(no data)
 io_hdr.dxfer_len = nsec*t_length;                // Data transfer length(512)
 io_hdr.dxferp = pbuffer;                       // Data transfer buffer(none)
 io_hdr.cmdp = rdCmdBlk6;                    // SCSI command buffer
 io_hdr.sbp = sense_b;                       // Sense buffer
 io_hdr.timeout = 5000;                      // Timeout(5s)

// Sends the command to device
 if ((res = ioctl(fd, SG_IO, &io_hdr)) < 0) {
   return 0;
 }

// Error processing
 if ( ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) || // check info
      (io_hdr.masked_status != 0x00) ||                  // check status(0 if ioctl success)
      (io_hdr.msg_status != 0x00) ||                     // check message status
      (io_hdr.host_status != 0x00) ||                    // check host status
      (io_hdr.driver_status != 0x00) )                   // check driver status
 {
   return 0;
 } else {
   return 1;
 }
}

Tuesday, November 17, 2015

Intel xHCI drivers

xHCI

https://downloadcenter.intel.com/download/21129/USB-3-0-Driver-Intel-USB-3-0-eXtensible-Host-Controller-Driver-for-Intel-7-Series-C216-Chipset-Family

https://downloadcenter.intel.com/download/22824/USB-3-0-Driver-Intel-USB-3-0-eXtensible-Host-Controller-Driver-for-Intel-8-9-100-Series-and-C220-C610-Chipset-Family

CentOS 7 32 bit VirtualBox client

Officially, CentOS 7 only has x86_64.  The first version 7.0 was released in 2014.

Not until 10/13/2015, AltArch SIG released a CentOS 7 32 bit for IOT x86 boards.
Release note: https://wiki.centos.org/SpecialInterestGroup/AltArch/i386
Release images: http://mirror.centos.org/altarch/7/isos/i386/

Not like the x86_64 version, the 32 bit version is not typically available on CentOS mirror sites.

At this moment, AltArch CentOS 7 32 bit version meets our need of creating USB token now with a catch.
- The two required RPM packages are from CentOS 6.7.  Luckily, they are working.

So far, I believe that it would be in the best interests of normal institution to consider taking CentOS 7 x86_64 instead of 32bit (i386/i686) version.  With x86_64, there is definitely less worry for future.


Note for getting the task done.

2 VirtualBox
2.1 Required VirtualBox components
Both VirtualBox installer and extension pack are required.  They can be found on the URL
http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html

2.2 Virtual Machine Creation
2.2.1 VirtualBox options
System->Motherboard->Base Memory must be >= 512MB
System->Processor->Extended Features check Enable PAE/NX
Network->Adapter 1 -> Advanced ->Adapter Type Intel PRO/1000 MT Desktop (8254OEM)
USB -> Enable USB Controller -> USB 3.0 (xHCI) Controller

Note that xHCI driver should be from vendors, Intel etc.

3 Install CentOS
3.1 Required CentOS 7 components
CentOS 7 ISO image
http://mirror.centos.org/altarch/7/isos/i386/CentOS-7-i386-Minimal-1503.iso
vim filesystem RPM package
ftp://fr2.rpmfind.net/linux/centos/6.7/os/i386/Packages/vim-filesystem-7.4.629-5.el6.i686.rpm
vim common RPM package
ftp://fr2.rpmfind.net/linux/centos/6.7/os/i386/Packages/vim-common-7.4.629-5.el6.i686.rpm

Friday, November 13, 2015

CentOS 7 32 bit virtualbox client

32bit CentOS 7 was released on 10/15/2015

The download is available here
http://mirror.centos.org/altarch/7/isos/i386/

When creating virtualbox client, the default configurations are not sufficient.

Create Virtual Machine:
- Linex and Other Linux(32-bit)

Settings
- System->Processor->Enable PAE/NX
- Network->Advanced->Adapter Type: Intel PRO/1000 MT Desktop (8254OEM)

CentOS 7 i386 by default won't recognize the default virtualbox network device.  This is from the 3.10 kernel taken by CentOS 7
https://www.centos.org/forums/viewtopic.php?f=47&t=47724

For development on CentOS, the following line will install compiler/linker packages.
yum groupinstall 'Development Tools'

Friday, October 30, 2015

Ubuntu 12.04 random crash and Intel i915 DRM video driver + Sandy Bridge

12/15/2012:
http://ubuntuforums.org/showthread.php?t=2094859

Investigation:

12/28/2011: Intel disable RC6 for Linux 3.2
http://www.phoronix.com/scan.php?page=news_item&px=MTAzNDg

Ubuntu official messages on the issue.
02/18/2012: Official notice of testing new kernel fix for RC6 related hang.
https://lists.ubuntu.com/archives/ubuntu-devel/2012-February/034782.html

04/11/2012: Official announcement of disabling RC6 and updated testing results of testing
https://wiki.ubuntu.com/Kernel/PowerManagementRC6

10/02/2015: Official announcement of reenabling RC6
https://wiki.ubuntu.com/Kernel/PowerManagement/PowerSavingTweaks
NOTE: If you are running 12.04 LTS ("Precise"), this is already enabled by default.

The Intel i915 RC6 feature allows the Graphics Processing Unit (GPU) to enter a lower power state during GPU idle. The i915 RC6 feature applies to Intel Sandybridge and later processors. RC6 was switched between enabled and disabled earlier in the Ubuntu 12.04 Precise LTS development cycle, but eventually all problems were fixed and it is now enabled by default.

Source code (Kernel 3.14):

/drivers/gpu/drm/i915/intel_pm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
{
        if (IS_GEN6(dev))
                DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");

        if (IS_HASWELL(dev))
                DRM_DEBUG_DRIVER("Haswell: only RC6 available\n");

        DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
                        (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off",
                        (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off",
                        (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off");
}

int intel_enable_rc6(const struct drm_device *dev)
{
        /* No RC6 before Ironlake */
        if (INTEL_INFO(dev)->gen < 5)
                return 0;

        /* Respect the kernel parameter if it is set */
        if (i915_enable_rc6 >= 0)
                return i915_enable_rc6;

        /* Disable RC6 on Ironlake */
        if (INTEL_INFO(dev)->gen == 5)
                return 0;

        if (IS_HASWELL(dev))
                return INTEL_RC6_ENABLE;

        /* snb/ivb have more than one rc6 state. */
        if (INTEL_INFO(dev)->gen == 6)
                return INTEL_RC6_ENABLE;

        return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
}


Since kernel version 3.6, Intel disabled their i915 driver pushing “deep sleep” on all Sandy Bridge devices.  However, the corresponding source code files are varying in different versions.

The video device on ATOM E6xx is GMA 600, a PowerVR SGX 535 based device.  Consequently, Ubuntu 12.04 running on E6xx is immune to the issue by nature.