2016年10月8日 星期六

Linux LibUsb

Linux LibUsb


LibUsb for Linux

  Download Source Code: sourceforge
 $ apt-get install libudev-dev
 $ ./configure

 $ make

 Download Example 
   https://github.com/libusb/libusb/tree/master/examples
   
 Download Hot-Plug Example
   CD /libusb-1.0.20/examples/
    # make
    # listdevs
      get usb vendor_id and  product_id


   update hotplugtest.c
    line  75, 78  Update vendor_id and  product_id
    # ./hotplugtest
   http://libusb.sourceforge.net/api-1.0/hotplug.html

但是那個 LIBUSB_HOTPLUG_PRODUCTID_ANY 怎測試都失敗









Linux usbview

Linux usbview


Linux usbview
   Download Source Code: Source code
  Compiler Source Code:
   unpack usbview-2.0.tar.gz
   cd usbview-2.0
   ./configure

   apt-get install libgtk-3-dev

   make

   ./usbview




   

2016年10月4日 星期二

SCSI Bus Rescan

SCSI Bus rescan
但是一些 SCSI Control Card已經是很久以前的
但 SCSI Device ID 變更, Linux 會還是記著, 不會釋放


只能斷電重新開機或是使用 SCSI bus Delete 指令

1:
 #  echo "- - -" > /sys/class/scsi_host/hostX/scan
  hostX:  0 to n

  #  echo "- - -" > /sys/class/scsi_host/host0/scan
  #  echo "- - -" > /sys/class/scsi_host/host6/scan

 # lsscsi

 # cat /proc/scsi/scsi



2:
 # echo "1" > /sys/class/block/sdX/device/rescan
  sdX:  A to n
  # echo "1" > /sys/class/block/sdb/device/rescan
  # echo "1" > /sys/class/block/sdc/device/rescan


3:
  # echo "1" > /sys/class/scsi_device/6:0:1:0/device/rescan
    6:0:1:0  => Host 6,  ID 1


4:
 # apt-get install scsitools
 # rescan-scsi-bus
 # lsscsi


5:  SCSI bus Delete
echo 1 > /sys/bus/scsi/drivers/sd/6\:0\:6\:0/delete



//========================
lsscsi Source Code
 http://sg.danny.cz/scsi/lsscsi.html
 https://github.com/hreinecke/lsscsi





2016年9月20日 星期二

Linux SCSI CDB vs ATA Command

關於 Linux 下直接使用 ATA Command
  Linux ioctl command for bypassing ATA command(Identify) - Sample Code
  這是直接使用 ioctl(device, HDIO_DRIVE_CMD, buf);
  真是方便, 以前在 NIOS 中, 程式寫了一大堆程式才做出來.
  但還是建議使用 Hdparm 的  sgio方式

另一個是請查詢 hdparm 的原始程式
  https://sourceforge.net/projects/hdparm/
  hdparm.c / sgio.c / sgio.h

請注意 hdparm 的 sgio 方式, 無法對 SAS HDD下這種 ATA Command
SAS HDD 請使用 CDB Command  (SPC & SBC)

T10
SCSI Primary Commands - 5 (SPC-5)  spc5r12.pdf
SCSI Block Commands - 4 (SBC-4) sbc4r11.pdf

2016年9月14日 星期三

Linx USB Disk 相關指令

臨時筆記...

lshw
dmesg
sudo fdisk OR sudo fdisk -l
sudo blkid
lsblk
mount
lsusb
usb-devices
df -h
Device hotplug event notification


USB utilities for Linux
    Download Source Code: Source code 

Linux USB Tools




Linux Hotplug
NETLINK_KOBJECT_UEVENT
https://www.google.com.tw/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=NETLINK_KOBJECT_UEVENT

http://nano-chicken.blogspot.tw/2010/01/linux-modules111-sysfs-and-hotplug.html
http://blog.chinaunix.net/uid-24943863-id-3223000.html


2016年9月13日 星期二

Linux + Windows 7 網路芳鄰自動斷線的問題

windows 7 網路芳鄰保持連線, 防止自動斷線, 造成 Linux連線問題
https://support.microsoft.com/zh-tw/kb/297684#LetMeFixItMyselfAlways


如果要關閉自動中斷連線功能,請開啟命令提示字元輸入下列命令,然後按 ENTER 鍵:
net config server /autodisconnect:-1

如果要變更伺服器服務自動中斷連線功能的預設逾時期間,請開啟命令提示字元,輸入下行,然後按 ENTER 鍵
net config server /autodisconnect:number
,其中 number 是您要伺服器中斷對應磁碟機的連線之前必須等待的分鐘數。這個命令的最大值為 65,535。

2016年9月9日 星期五

Ubuntu 14.x 開機自動登入及啟動程式


一: GUI 模式下

Step 1:
 Alt-F2
Step 2:
 gnome-session-properties




二. 文字模式下

1: 要改成文字模式做法是編輯 /etc/default/grub
   將這一行的設定 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
   修改為  GRUB_CMDLINE_LINUX_DEFAULT="text"
2: 修改 /etc/init/tty1.conf
   將這一行的設定 exec /sbin/getty -8 38400 tty1
   修改為  # exec /sbin/getty -8 38400 tty1 -a root
    那個 root 是指登入的帳號名稱 username
    密碼不用輸入, 會自動忽略
3: 修改 /root/.bashrc 檔案
    增加最後一行
     exec /MyDir/MyExecFile

    記得要修改  MyExecFile至這個執行檔的權限
    chmod 777 /MyDir/MyExecFile

4:切換 tty1 和 tty2 使用指者界面
   (換另一個user account 登入)
   使用鍵盤 CTRL-Alt-F2

 

======================
cd /
madir usb
mount /dev/s
mount /dev/sdb1  /usb
cd usb
cp /usb/MyExecFile /MyDir
chmod 777 /MyDir/MyExecFile
unmount /dev/sdb1
reboot


2016年6月29日 星期三

關於 USB Type-C 傳輸線接頭

關於 USB Type-C 傳輸線接頭
現在已有多家同時使用這種傳輸線接頭
也就是說, 一種線材同時被多種協定拿去使用
這和過去一種線材代表一種傳輸協定不同了

下面列出已知 USB Type-C 被使用到的傳輸協定

  傳輸協定              頻寬        速度  
  Thunderbolt 3       40Gbps/s   約 4.768GB/s
  USB 3.1             10Gbps/s   約 1.192GB/s
  USB 3.0              5Gbps/s   約 596MB/s
  USB 2.0             480Mbps/s  約 57.2MB/s

現在市面上手機在用的 USB Type-C 傳輸線接頭, 是使用 USB 2.0傳輸協定.

相信過一陣子一定會看到用USB Type-C 傳輸線做成 PCIe的傳輸線
這個我需要啊! 快點出來.

關於跨平台C++原始程式內含中文字變成亂碼的解決方法


關於C++原始程式跨平台內含中文字解說之方法

同一份 C++程式( .cpp 和 .h)原始程式檔案
如果原始程式檔案( .cpp 和 .h)內含中文字解說
想要在 Windows 和 Linux 中共同使用
這樣中文字就不會變成亂碼


方法如下

Linux 端 Eclipse 設定如下
 將原始程式儲存為 UTF-8  NO BOM
 (Linux G++ 只支援 UTF-8  NO BOM 格式)

如果舊的 .cpp, 可以使用UltraEdit 開啟後, 再另存新檔, 成為 UTF-8  NO BOM



Windows 端 Eclipse 設定如下:
每一個 Project 都要單獨設定一次

如果舊的 .cpp, 可以使用UltraEdit 開啟後, 再另存新檔, 成為 UTF-8  NO BOM
要注意一下 makefile 這檔案, 如果編譯有錯, 請在 Eclipse 開啟/檢查/存檔/編譯

Windows 端 Araxis Merge 設定如下:


Windows 端 Notepad++ 設定如下:



LSI 9211-8I Firmware & BIOS Update

LSI 9211-8I Firmware & BIOS Update

http://www.avagotech.com/products/server-storage/host-bus-adapters/sas-9211-8i#downloads

Firmware  Page
  Download
9211-8i_Package_P20_IR_IT_Firmware_BIOS_for_MSDOS_Windows
Package_P20_Firmware_BIOS_for_MSDOS_WindowsVersion: 20.00.07.00
File Size: 1700 KB
Language: English

Unzip File : 9211-8i_Package_P20_IR_IT_FW_BIOS_for_MSDOS_Windows.zip

File 1:
\sas2flash_win_x64_rel\sas2flash.exe

File 2:
\Firmware\HBA_9211_8i_IR\2118ir.bin
 or
\Firmware\HBA_9211_8i_IR\2118it.bin

File 3:
\sasbios_rel\mptsas2.rom


Update BIOS
> sas2flash.exe -b mptsas2.rom

Update Firmware
> sas2flash.exe -o -f 2118ir.bin



2016年5月24日 星期二

Ubuntu Install Altera Complete Design Suite


未完, 待測試中....

簡單的說, 除非有Altera DFAE的支援,
建議還是在 Windows環境下開發執行quartus, 還比較容易.
不同版本的 quartus, 還得花大量時測試.

//================================================
Insatll Altera Complete Design Suite v13.1 for Windows
Run  Quartus_II_13.1_x64.exe or Quartus_II_13.1_x86.exe
Get File: license.dat
copy license.dat to Linux
Insatll Altera Complete Design Suite v13.0 for Linux
# cd /root/altera/13.1/quartus
# ./quartus
Run quartus, Get Host ID xxxxxxxx, Close quartus
Edit  license.dat, Change Host ID xxxxxxxx
Run quartus, select file license.dat
//================================================

# apt-get install lib32stdc++6
# apt-get install libgtk2.0-0:i386
# apt-get install libxtst6:i386
# apt-get install gtk2-engines-murrine
# apt-get install libcanberra0
# apt-get install libcanberra-gtk-module
# apt-get install libcanberra-gtk-module:i386
# apt-get install libcanberra-gtk3-module
# apt-get install libcanberra-gtk3-module:i386
# apt-get install gtk2-engines-murrine
# apt-get install gtk2-engines-murrine:i386
# apt-get download gtk2-engines-murrine:i386
# dpkg --force-depends -i gtk2-engines-murrine_*_i386.deb
# apt-get download overlay-scrollbar-gtk2:i386
# dpkg --force-depends -i overlay-scrollbar-gtk2_*_i386.deb
# apt-get download unity-gtk2-module:i386
# dpkg --force-depends -i unity-gtk2-module_*_i386.deb

# touch /etc/ld.so.conf.d/gtk-2.0.conf
# touch /etc/ld.so.conf.d/gtk-3.0.conf

Edit File:
 # gedit /etc/ld.so.conf.d/gtk-2.0.conf
 Add path to file
 /usr/lib/x86_64-linux-gnu/gtk-2.0/modules

Edit File:
 # gedit /etc/ld.so.conf.d/gtk-2.0.conf
 Add path to file
 /usr/lib/x86_64-linux-gnu/gtk-2.0/modules

Load Config
 # ldconfig

# cd /altera/13.1/nios2eds/bin
# ./eclipse-nios2

//================================================
Step 1: Download Altera Complete Design Suite v11.0
   11.1_173_quartus_free_linux.sh

Step 2: 
  extract  11.1_173_acds_linux.iso

Step 3:
  Delete file "libpng12.so.0"
  /altera_installer/bin/libpng12.so.0
 # cd 11.1_173_acds_linux
 # cd altera_installer
 # cd bin
 # mv libpng12.so.0



Step 4: 
 # cd 11.1_173_acds_linux
 # chmod 700 setup


Step 5: 
 run setup 
 # bash ./setup


Step 6: 
  extract 11.1_173_acds_devices.iso



apt-get install libxext6:i386
apt-get install libxtst6:i386
apt-get install libxi6:i386



Step 7: 
 Download Altera Complete Design Suite v11.1.259 sp2
11.1sp2_259_quartus_linux.sh






http://www.fpga-dev.com/altera-usb-blaster-with-ubuntu/

2016年5月11日 星期三

Linux pthread priority setting




PTHREAD_SETSCHEDPARAM(3) Linux Programmer's Manual 

pthread優先權的設定範例



About Disk Erase


未完成, 慢慢再寫出來...
因為這幾天都在硬K SAS 規格書, 頭快暈了


HDD 內含 Secure Erase, 其實自己寫程式來做, 比較快.
可以參考另一篇 Linux SCSI Pass Through Interface
如果 Windows 下, 請參考 DDK\src\storage\tools\spti 的範例
只有機械式 HDD 才有提供, SSD 是不包含 Secure Erase 指令.






這有幾篇文章寫的不錯, 值得一讀
國家級標準銷毀儲存媒體資料

What is DoD 5220.22-M?

2016年5月5日 星期四

ubuntu 滑鼠游標消失問題修正

ubuntu 滑鼠游標在開機後, 游標就突然消失不見.
(由其是電腦關機一個晚上後, 第二天重新開機, 常會發生這種怪問題)
但滑鼠還在, 點了畫面也有反應.

這問題在Logitech 上面常發生
(但 Logitech的滑鼠真的比別家的好用)
不然就換另一家的滑鼠試看看囉!

解決方法
  重開進 BIOS, 看滑鼠是否可以動作 (只是為了驗證滑鼠正常, 這問題不多, 就可以省略這步驟)
  再斷電重新開機, 進入 Ubuntu (在開始出現第一個Ubuntu的 GUI LOGO 時, 一定要移動滑鼠)
  再進入Ubuntu的過程中, 就無聊的把滑鼠每幾秒移動一下

(最好是斷電方式重新開機 Power OFF, 不是暖開機喔!)

很多 Linux 系列都有這問題
簡單的說, 斷電重新開機時, 把滑鼠每隔幾秒移動一下, 進入桌面平台
游標就會顯示出來

再不行.把滑鼠重插一個USB 孔, 重新開機


下面是網路上的解決方案
問題是又臭又長, 誰會去背這個,
問題都消失了, 怎找出下面這一大段指令
還是重開機比較快

開啟終端機輸入下面指令
 gsettings set org.gnome.settings-daemon.plugins.cursor active false
完成後,不用重新啟動電腦,滑鼠的游標就會出現。

2016年5月3日 星期二

Linux Thread Stack Size

pthread 的所有 Functoion Example

原則上, 寫程式盡量不要在 Thread中 new 大塊的記憶體
不然光是找出 memory leak 就累斃
大部份都是在 Main Process 都 new好記憶體
放在 struct中, 再傳入Thread 中.
Thread結束後, 統一在 Main Process刪除記憶體


顯示系統預設的 pthread Stack Size 是 8MiB
# ulimit -s
8192


使用 pthread_attr_setstacksize(...) 設定 pthread Stack Size
 pthread_create Example Code


使用 pthread_attr_getstacksize(...) 取得 pthread Stack Size


Linux File Compare Tools

Binary Compare Tools

還沒找到一個和 Hex Workshop 一樣好用的.
只好把檔案移到 Windows 下比對.

1:
 # diff file1.bin file2.bin
 如果是大型檔案, 可以增加 -H 參數
PS: 比對成功後, 也沒有訊息出來, 搞不清處是成功還是失敗.

2:
 # apt-get install diffuse
 # diffuse
PS: 無法處理對大型的bin 檔案

3:
# apt-get install kdiff3
# kdiff3
PS: 無法處理對大型的bin 檔案, 500GiB檔案, 一開啟就當了.

4:
Ultra Compare

About pthread_timedjoin_np Function


範例程式隨便寫的, 別太認真.

關於 pthread_timedjoin_np() 的回傳值
當 Thread 還在執行時, 回傳 nStstus = 110
#define ETIMEDOUT   110 /* Connection timed out */
當 Thread 還在結束時, 回傳 nStstus = 0x00
但只能問到一次是 0x00
再問一次, 就會變成 22
#define EINVAL      22  /* Invalid argument */
這一點會讓寫程式時, 就得立刻記錄 Thread已結束,
不然別的 Thread 就問不到已結束.
pthread_exit((void *)3) 的0x03 是收不到的.

//-----------------------------------------------------------------------------
#include 
//-----------------------------------------------------------------------------
void *thread_start( void *para)
{
 int i = 0;
 printf("pthread (%u) begin (%d).\n", clock(), i);
 for( i= 1; i< 10; i++)
 {
     printf("pthread (%u) - (%d).\n", clock(), i);
     sleep(2); // 2sec
 }
 printf("pthread (%u) pthread_exit()-1.\n", clock());
 pthread_exit((void *)3);
 printf("pthread (%u) pthread_exit()-2.\n", clock());
 sleep(5);
 printf("pthread (%u) return.\n", clock());
 return (void *)2;
}
//-----------------------------------------------------------------------------
int main_ThreadTest()
{
 pthread_t id;
 int i,ret;
 int nStstus;
 struct timespec sWaitTime;
 void *pThreadRet = NULL;

 ret = pthread_create( &id, NULL, thread_start, NULL);
 clock_gettime( CLOCK_REALTIME, &sWaitTime);
 sWaitTime.tv_sec += 1; // wait 1sec
 nStstus = pthread_timedjoin_np( id, &pThreadRet, &sWaitTime);
 nprintf( "pthread_timedjoin_np-2 (%u) Status:%d, pThreadRetSc:%d\n", clock(), nStstus, ret);
 if(ret!=0)
 {
     printf ("Create pthread error!\n");
     exit (1);
 }
 for(i=0 ; i < 1000; i++)
 {
  clock_gettime( CLOCK_REALTIME, &sWaitTime);
  sWaitTime.tv_sec += 1; // wait 1sec
  nStstus = pthread_timedjoin_np( id, &pThreadRet, &sWaitTime);
  nprintf( "pthread_timedjoin_np-2 (%u)Status:%d, pThreadRetSc:%d\n", clock(), nStstus, ret);
  usleep(100);
 }
// #define EBUSY       16  /* Device or resource busy */
// #define EINVAL      22  /* Invalid argument */
// #define ETIMEDOUT   110 /* Connection timed out */
// #define ECONNREFUSED    111 /* Connection refused */
// pthread_join(id,NULL);//等待線程(pthread)結束
 return (0);
}


2016年4月29日 星期五

How To Compiler udev (udevadm)




Linux 初學者, 對這邊核心程式的編譯方式一定會被搞瘋掉
有時間再寫一篇 udevadm 移殖到Eclipse中 Debug的流程

The options used usually look like:


# mkdir udev
# cd udev
# git clone git://git.kernel.org/pub/scm/linux/hotplug/udev.git git





# cd git
# apt-get install gtk-doc-tools
# ./autogen.sh --without-selinux --disable-extras --disable-introspection
# ./configure CFLAGS='-g -O1'  --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --with-selinux --enable-gtk-doc --with-rootprefix= --with-rootlibdir=/lib --bindir=/sbin --libexecdir=/lib --with-systemdsystemunitdir=/lib/systemd/system 

checking for BLKID... no
configure: error: Package requirements (blkid >= 2.20) were not met:
No package 'blkid' found
No blkid, need install libblkid-dev


# apt-get install libblkid-dev

# ./configure CFLAGS='-g -O1'  --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --with-selinux --enable-gtk-doc --with-rootprefix= --with-rootlibdir=/lib --bindir=/sbin --libexecdir=/lib --with-systemdsystemunitdir=/lib/systemd/system 
checking for KMOD... no
configure: error: Package requirements (libkmod >= 5) were not met:

No package 'libkmod' found
No 'libkmod', Need install libkmod-dev

# apt-get install libkmod-dev
# apt-get install libselinux-dev

# apt-get install libglib2.0-dev

# apt-get install libgirepository1.0-dev

# apt-get install gperf

# ./configure CFLAGS='-g -O1'  --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib --with-selinux --enable-gtk-doc --with-rootprefix= --with-rootlibdir=/lib --bindir=/sbin --libexecdir=/lib --with-systemdsystemunitdir=/lib/systemd/system 






configure 完成, 會在目錄下發現一個 makefile 檔案! 

可以開始進行 gcc make 動作


# make


編譯出現錯誤, 原來這個 mq_getattr 很久以前的功能,可以直接作廢.

# gedit /root/udev/git/src/sd-daemon.c
comment it out line 394 & 395 
 //        if (mq_getattr(fd, &attr) < 0)
 //              return -errno;

重新作執行一次 gcc make 動作
# make

 




# ./udevadm --version
182

請參考 Ubuntu udevadm用法
# ./udevadm info -q all -n /dev/sda | grep DEVPATH


可以使用 udevadm監控Hot Plug的狀態

# udevadm monitor





2016年4月25日 星期一

HTML with C++ cpp Code


原文來自
How can I show code (specifically C++) in an HTML page?



<head>
  <link href="css/shCore.css" rel="stylesheet" type="text/css" />
  <link href="css/shThemeDefault.css" rel="stylesheet" type="text/css" />
</head>

<body>
  <pre class='brush: cpp'>
  // my first program in C++
  #include <iostream>
  using namespace std;

  int main ()
  {
    cout << "Hello World!";
    return 0;
  }
  </pre>

  <script src="js/shCore.js"></script>
  <script src="js/shBrushCpp.js"></script>
  <script>
    SyntaxHighlighter.all()
  </script>
</body>

Debugging with GDB


因為在 Eclipse中 Debug 多個 pthread 真的有點痛苦
奇怪的是 Altera Eclipse 版本不會這樣

後來查出原來是其他程式段錯誤
卻造成 Debug thread混亂


但 Linux Eclipse CDT 中 switch thread時卻會卡卡的
只好找找看別的方式來試試看

Debugging with GDB學習記錄(一)

Debugging with GDB學習記錄(二)

Debugging with GDB學習記錄(三)


2016年4月21日 星期四

Linux Memory Leak

Linux Tools Project - Valgrind Support
 https://eclipse.org/linuxtools/projectPages/valgrind/


Eclipse 外掛︰ MAT, Memory Analyzer Tool (JAVA Only)
  http://www.eclipse.org/mat/downloads.php
  http://lp43.blogspot.tw/2011/11/mat.html

valgrind:
使用valgrind檢查C語言memory leak
 # apt-get install valgrind
 # valgrind --leak-check=full --show-leak-kinds=all --verbose ./My-Leaky-Program-Filename


mtrace:

在程式中加入兩行
#include <mcheck.h>

static void Main()
{
 ...
  mtrace();
 ...
}

在終端機模式下
# mtrace ./My-Leaky-Program-Filename  Memory_Leak.txt


2016年4月19日 星期二

Linux Physical Block Size

Linux 這個  physical_block_size 是 File System 的 physical block

> 磁區大小 (邏輯/實體):512 位元組 / 4096 位元組
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
File System 以上, 一個 Block Size是 4096Byte
SCSI Direct IO以下, 一個 Sector Size是 512Byte 
(但有一些少見的裝置其 Sector Size是 1024Byte)

/sys/block/sda/queue/physical_block_size
 4096

/sys/block/sdb/queue/physical_block_size
 512

/sys/block/sdc/queue/physical_block_size
 512



Linux SCSI Pass Through Interface

其實不難, 只是專案必需要知道每一個實體 PHY Port 是連結到 Linux 中那一個 /dev/sgn 中
原來是直接用 /dev/sdN , 但發現這對以逅的專案會有影響, 所以就改用/dev/sgN 方式
而且習慣看 SCSI Sense Code, 除錯也比較容易.

過去十幾年來都在 Windows 和 NIOS-II 下對 Device直接下 SCSI Command
終於換到 Linux 平台來.

Some examples of storage device names of the supported operating systems

 //===========================================
方式一:
   一般都是利用 sg3-utils核心
   # apt-get install sg3-utils

   也就是開啟 "/dev/sgN" 方法
   http://sg3-utils.sourcearchive.com/
    sg3_utils-1.32 Example
 

  參考下面這幾篇
   T10 Working Drafts
   這個 T10很多檔案都已經改為付費購買. 其實只要只知道檔案名稱, 還是在Google搜尋下載得到.

   Seagate SCSI Commands Reference Manual
   Seagate SCSI Commands Reference Manual April 2010
   wiki SCSI command


   http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/
   Appendix C. Programming example

   ioctrl-using-scsi-pass-through

   linux scsi generic howto學習筆記

 
typedef struct sg_io_hdr
{
  int interface_id;           /* [i] 'S' for SCSI generic (required) */
  int dxfer_direction;        /* [i] data transfer direction  */
                                     SG_DXFER_NONE /* e.g. a SCSI Test Unit Ready command */
                                     SG_DXFER_TO_DEV /* e.g. a SCSI WRITE command */
                                     SG_DXFER_FROM_DEV /* e.g. a SCSI READ command */
                                   
                                     TestUnitReady => SG_DXFER_NONE
                                     ReadCapacity10 => SG_DXFER_FROM_DEV
                                     Read10 => SG_DXFER_FROM_DEV
                                     Write10 => SG_DXFER_TO_DEV
 
  unsigned char cmd_len;      /* [i] SCSI command length ( <= 16 bytes) */
                                     ReadCapacity10 => cmd_len = 10
                                     ReadCapacity16 => cmd_len = 16
                                     Read10 => cmd_len = 10
                                     Write10 => cmd_len = 10
                                     Write16 => cmd_len = 16

  ...
} sg_io_hdr_t;
//===========================================

使用 SG_IO 出現 ENOMEM
表示要求傳輸的記憶體太大
經測試只傳輸到 512byte * 9181sector
一呼叫 512byte * 9182sector   就會發生 ENOMEM
經查 Google 這是Linux的核心限制
scsi sg ioctl要求向 blk-mq 取得一塊和要求傳輸大小的記憶體區塊失敗.

對 Storage一次使用大區塊讀取, 並不一定會比較穩定快速
因為不同的 Storage, 其晶片的特性不同
讀取太大塊, 速度反而會變慢, 變錯.
這個數字是多少, 就依賴經驗值, 必竟Storage的種類範圍太廣.


下面只是參考, 別太認真.
void ReadWrite_Test()
{
 int nI, nJ;
 TLBA nReadLba, nWriteLba;
 DWORD nSectorSize, nReadLen, nWriteLen;
 DWORD nReadCrc32, nWriteCrc32, nWriteSectorCrc32;
 DWORD nReadBufLen, nWriteBufLen;
 UCHAR *pReadBuf = new UCHAR[16*1024*1024];
 UCHAR *pWriteBuf = new UCHAR[16*1024*1024];


 nSectorSize = 512;
 nWriteLba = 0;
 nWriteLen = 8192;
 memset( pWriteBuf, 0, 16*1024*1024);
 /* 初始化 Writer Data Buffer */
 for( nI =0; nI < nWriteLen; nI++)
 {
  /* 中間填入 序號Index */
  for( nJ = 4; nJ < nSectorSize-sizeof(DWORD); nJ++)
   pWriteBuf[nI*nSectorSize+nJ] = nJ%255;
  /* 前4個Byte 是 Sector Index */
  pWriteBuf[nI*nSectorSize]   = (UCHAR)((nWriteLba+nI) >> 24); // MSB
  pWriteBuf[nI*nSectorSize+1] = (UCHAR)((nWriteLba+nI) >> 16);
  pWriteBuf[nI*nSectorSize+2] = (UCHAR)((nWriteLba+nI) >> 8);
  pWriteBuf[nI*nSectorSize+3] = (UCHAR)((nWriteLba+nI));            // LSB
  nWriteSectorCrc32 = Get_CRC32( pWriteBuf+(nI*nSectorSize), nSectorSize-sizeof(DWORD));
  /* 後 2個Byte 是 Sector Index */
  pWriteBuf[nI*nSectorSize+nSectorSize-sizeof(DWORD)]    = (UCHAR)(nWriteSectorCrc32 >> 24); // MSB
  pWriteBuf[nI*nSectorSize+nSectorSize-sizeof(DWORD)+1]  = (UCHAR)(nWriteSectorCrc32 >> 16);
  pWriteBuf[nI*nSectorSize+nSectorSize-sizeof(DWORD)+2]  = (UCHAR)(nWriteSectorCrc32 >> 8);
  pWriteBuf[nI*nSectorSize+nSectorSize-sizeof(DWORD)+3]  = (UCHAR)(nWriteSectorCrc32);       // LSB
 }

 nWriteBufLen = nSectorSize*nWriteLen;
 /* 整個 Write Data Buffer 的 CRC-32 */
 nWriteCrc32  = Get_CRC32( pWriteBuf, nWriteBufLen);
 if( Write16( nWriteLba, nSectorSize, nWriteLen, pWriteBuf) == true)
 {
  memset( pReadBuf, 0, 4096);
  memset( pReadBuf, 0, 16*1024*1024);
  nReadLen = nWriteLen;
  nReadLba = nWriteLba;
  nReadBufLen = nSectorSize * nReadLen;
  if( Read16( nReadLba, nSectorSize, nReadLen, pReadBuf))
  {
   /* 驗證讀回來的資料是否正確 */
   nReadCrc32 = Get_CRC32( pReadBuf, nReadBufLen);
   if( nReadCrc32 != nWriteCrc32)
    nprintf( "Read/Write Test CRAC-32 Failed!");
   if( memcmp( pReadBuf, pWriteBuf, nReadBufLen) == 0)
    nprintf( "Read/Write Test Compare Ok!");
   else
    nprintf( "Read/Write Test Compare Failed!");
  }
 }
// Write12( nWriteLba, nSectorSize, nWriteLen, pWriteBuf);
// Write16( nWriteLba, nSectorSize, nWriteLen, pWriteBuf);

if( pReadBuf)
 delete[] pReadBuf;
if( pWriteBuf)
 delete[] pWriteBuf;
}


 //===========================================
# lsscsi
[0:0:0:0]    disk    SEAGATE  ST3500414SS      0006  /dev/sdb
[0:0:1:0]    disk    SEAGATE  ST3500414SS      0006  /dev/sdc
[1:0:0:0]    disk    ATA      ST1000DM003-9YN1 CC4B  /dev/sda

# lsscsi --transport
[6:0:0:0]    disk    sas:0x5000c500418fac39          /dev/sdb
[6:0:1:0]    disk    sas:0x5000c50041ea5265          /dev/sdc

  /sys/class/scsi_generic/sg2/device/block/sdc
  /sys/class/scsi_generic/sg2/device/scsi_device/6:0:1:0
  /sys/class/scsi_generic/sg2/device/scsi_device/6:0:1:0/sas_address

可以交叉驗證, 就可以知道 /dev/sg3 是那一顆HDD
要注意  Hot-Plug 的狀態下, Target 會改變, /sys/class/scsi_generic/sgN的目錄會自動消失, 也會自動出現.

所以用udevadm 來監控 (但監控這幾個目錄也是可以, 而且比較簡單)
How To Compiler udev


 $ apt-get install sg3-utils
 $ sg_scan -i -x

 //===========================================
 sg3_utils-1.32 Example




如果是 SATA HDD交叉驗證, 請看另一篇取得 SATA PHY Port Index 的相關文章

//===========================================
關於超過 2TB 容量的 Device
請使用 ReadCapacity16, Read16, Write16 這幾組指令
ReadCapacity10  有的會直接失敗, 有的 Device會回傳四個 0xFF
這時就轉換為  ReadCapacity16指令

ReadCapacity回傳的 Capacity是最後一個 LBA位置
所以實際容量為 Capacity + 1

還有一種情況是造假的 Capacity, 也就是回傳的 Capacity都是假的
這時要實際的去 Write & Read Last LBA, 進行資料驗證

記得有一次, 遇到一個Device, 一次 Read/Write 16MB, 回傳都是正常
讀寫的資料只有前面 4MB 資料是正確, 後面 12MB資料都是晶片亂編出來.

其實最常見的是, 寫入時, Device回傳 Write OK, 但確沒有真正的寫入.


//===========================================
//===========================================
方式二:
   使用 /dev/bsg/1:0:0:0
http://sg.danny.cz/sg/p/libsgutils2-2_1.42-0.1_i386.deb
http://www.spinics.net/lists/linux-scsi/msg53920.html
sg_tst_context


//===========================================
//===========================================
方式三:
  這方法只適用 LSI  控制卡上的 Device
  Linux LSI SAS 9211-8i Utility
  Source Code中一個 doScsiIo(), doMptCommand()  的函式
  利用 LSI 驅動程式提供的 mpt_ioctl_command
  直接對 LSI CHIP 下達 SCSI Command
  LSI Util 原始程式是一個 SCSI Command就 Open Device Handle一次
  速度會比較慢, 最好要改寫一些程式.

//===========================================
關於 Linux 下直接使用 ATA Command
  Linux ioctl command for bypassing ATA command(Identify) - Sample Code
  這是直接使用 ioctl(device, HDIO_DRIVE_CMD, buf);
  真是方便, 以前在 NIOS 中, 程式寫了一大堆程式才做出來.
  但還是建議使用 Hdparm 的  sgio方式

另一個是請查詢 hdparm 的原始程式
  https://sourceforge.net/projects/hdparm/
  hdparm.c / sgio.c / sgio.h

//===========================================