Aspifunc.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. // ----------------------------------------------
  2. // - ASPIFUNC implementation file -
  3. // - Written 1996-1998 by Christoph Schmelnik -
  4. // ----------------------------------------------
  5. // Version 1.40 : 24.02.1998
  6. // Changes:
  7. // Set correct direction flags, to work with NT device IO interface and ATAPI drives
  8. // Added Immediate paremeter for WaitSCSIRequest to allow detection of buffer underruns
  9. #include <stddef.h>
  10. #include "aspifunc.h"
  11. HMODULE hDLL=0;
  12. VOIDPROC GetASPI32SupportInfo;
  13. SRBPROC SendASPI32Command;
  14. int ASPIInstalled;
  15. int RunningNT;
  16. int NumberOfHostAdapters;
  17. //Implementation of base ASPI Functions
  18. BOOL HAInquiry(int HostAdapterNumber,char *ManagerID, char *HAID,THAUnique &HAUnique)
  19. {
  20. SRB_HAInquiry MySRB;
  21. DWORD ASPI_Status;
  22. memset(&MySRB,0,sizeof(SRB_HAInquiry));
  23. MySRB.SRB_Cmd = SC_HA_INQUIRY;
  24. MySRB.SRB_HaId = HostAdapterNumber;
  25. MySRB.SRB_Flags = 0;
  26. MySRB.SRB_Hdr_Rsvd = 0;
  27. ASPI_Status = SendASPI32Command ( (LPSRB) &MySRB );
  28. if (ASPI_Status!=SS_COMP)
  29. return FALSE;
  30. HAUnique=MySRB.HA_Unique;
  31. for (int i=0; i<16; i++)
  32. {
  33. ManagerID[i]=MySRB.HA_ManagerId[i];
  34. HAID[i]=MySRB.HA_Identifier[i];
  35. }
  36. ManagerID[16]=0;
  37. HAID[16]=0;
  38. return TRUE;
  39. }
  40. int GetDeviceType(int HostAdapterNumber,int TargetId,int LUN)
  41. {
  42. SRB_GDEVBlock MySRB;
  43. DWORD ASPI_Status;
  44. memset(&MySRB,0,sizeof(SRB_GDEVBlock));
  45. MySRB.SRB_Cmd = SC_GET_DEV_TYPE;
  46. MySRB.SRB_HaId = HostAdapterNumber;
  47. MySRB.SRB_Flags = 0;
  48. MySRB.SRB_Hdr_Rsvd = 0;
  49. MySRB.SRB_Target = TargetId;
  50. MySRB.SRB_Lun = LUN;
  51. ASPI_Status = SendASPI32Command ((LPSRB)&MySRB);
  52. /***************************************************/
  53. /* If ASPI_Status == SS_COMP, MySRB.SRB_DeviceType */
  54. /* will contain the peripheral device type. */
  55. /***************************************************/
  56. if (ASPI_Status==SS_COMP)
  57. return MySRB.SRB_DeviceType;
  58. return DTYPE_UNKNOWN;
  59. }
  60. BOOL ExecuteSCSIRequest(int HostAdapterNumber,int TargetId,int LUN,int RequestFlags,
  61. TOpcode OpC, BYTE OpCLen,void *DataPtr, int DataLen, HANDLE hDriveEvent)
  62. {
  63. if ((HostAdapterNumber>=NumberOfHostAdapters) &&
  64. RunningNT)
  65. {
  66. DWORD il, ol;
  67. SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sb;
  68. ZeroMemory(&sb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
  69. sb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
  70. sb.sptd.CdbLength = OpCLen;
  71. sb.sptd.DataIn = ((SRB_DIR_IN & RequestFlags) ? 1/*SCSI_IOCTL_DATA_IN*/ : 0/*SCSI_IOCTL_DATA_OUT*/);
  72. sb.sptd.SenseInfoLength = 32;
  73. sb.sptd.DataTransferLength = DataLen;
  74. sb.sptd.TimeOutValue = 2;
  75. sb.sptd.DataBuffer = (unsigned char*) DataPtr;
  76. sb.sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
  77. for (int i=0; i<OpCLen; i++) sb.sptd.Cdb[i]=OpC[i];
  78. il = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
  79. if (DeviceIoControl(hDriveEvent, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sb, il, &sb, il, &ol, FALSE))
  80. {
  81. if (sb.sptd.ScsiStatus==0)
  82. return TRUE;
  83. }
  84. return FALSE;
  85. }
  86. SRB_ExecSCSICmd MySRB;
  87. DWORD ASPI_Status;
  88. DWORD ASPIEventStatus;
  89. memset(&MySRB,0,sizeof(SRB_ExecSCSICmd));
  90. MySRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
  91. MySRB.SRB_HaId = HostAdapterNumber;
  92. MySRB.SRB_Flags = RequestFlags|SRB_EVENT_NOTIFY;
  93. MySRB.SRB_Hdr_Rsvd = 0;
  94. MySRB.SRB_Target = TargetId;
  95. MySRB.SRB_Lun = LUN;
  96. MySRB.SRB_BufPointer = (unsigned char*) DataPtr;
  97. MySRB.SRB_BufLen = DataLen;
  98. MySRB.SRB_CDBLen = OpCLen;
  99. MySRB.SRB_SenseLen = SENSE_LEN;
  100. MySRB.SRB_PostProc = (void(__cdecl *)(void))hDriveEvent;
  101. for (int i=0; i<OpCLen; i++) MySRB.CDBByte[i]=OpC[i];
  102. ResetEvent(hDriveEvent);
  103. ASPI_Status = SendASPI32Command ((LPSRB)&MySRB);
  104. /**************************************************/
  105. /* Block on event till signaled */
  106. /**************************************************/
  107. if ( MySRB.SRB_Status == SS_PENDING )
  108. {
  109. ASPIEventStatus = WaitForSingleObject(hDriveEvent, TIMEOUT);
  110. /**************************************************/
  111. /* Reset event to non-signaled state. */
  112. /**************************************************/
  113. if (ASPIEventStatus == WAIT_OBJECT_0)
  114. ResetEvent(hDriveEvent);
  115. else
  116. {
  117. OutputDebugString(L"Execute Timed out\n");
  118. AbortSCSIRequest(MySRB);
  119. }
  120. }
  121. if (MySRB.SRB_Status==SS_COMP)
  122. return TRUE;
  123. return FALSE;
  124. }
  125. void FillSCSIRequest(int HostAdapterNumber,int TargetId,int LUN,int RequestFlags,
  126. TOpcode OpC, BYTE OpCLen,void *DataPtr, int DataLen,SRB_ExecSCSICmd &MySRB, HANDLE hDriveEvent)
  127. {
  128. memset(&MySRB,0,sizeof(SRB_ExecSCSICmd));
  129. MySRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
  130. MySRB.SRB_HaId = HostAdapterNumber;
  131. if ((HostAdapterNumber>=NumberOfHostAdapters) &&
  132. RunningNT)
  133. {
  134. MySRB.SRB_Flags = RequestFlags;
  135. }
  136. else
  137. {
  138. MySRB.SRB_Flags = RequestFlags|SRB_EVENT_NOTIFY;
  139. MySRB.SRB_Hdr_Rsvd = 0;
  140. MySRB.SRB_PostProc = (void(__cdecl *)(void))hDriveEvent;
  141. }
  142. MySRB.SRB_Target = TargetId;
  143. MySRB.SRB_Lun = LUN;
  144. MySRB.SRB_BufPointer = (unsigned char*) DataPtr;
  145. MySRB.SRB_BufLen = DataLen;
  146. MySRB.SRB_CDBLen = OpCLen;
  147. MySRB.SRB_SenseLen = SENSE_LEN;
  148. for (int i=0; i<OpCLen; i++) MySRB.CDBByte[i]=OpC[i];
  149. }
  150. void ExecuteSCSIRequest(SRB_ExecSCSICmd &MySRB,HANDLE hDriveEvent)
  151. {
  152. if ((MySRB.SRB_HaId>=NumberOfHostAdapters) &&
  153. RunningNT)
  154. {
  155. DWORD il, ol;
  156. SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sb;
  157. ZeroMemory(&sb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
  158. sb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
  159. sb.sptd.PathId = 0;
  160. sb.sptd.TargetId = 1;
  161. sb.sptd.Lun = 0;
  162. sb.sptd.CdbLength = MySRB.SRB_CDBLen;
  163. sb.sptd.DataIn = MySRB.SRB_Flags;
  164. sb.sptd.SenseInfoLength = 32;
  165. sb.sptd.DataTransferLength = MySRB.SRB_BufLen;
  166. sb.sptd.TimeOutValue = TIMEOUT;
  167. sb.sptd.DataBuffer = MySRB.SRB_BufPointer;
  168. sb.sptd.SenseInfoOffset =
  169. offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
  170. for (int i=0; i<MySRB.SRB_CDBLen; i++) sb.sptd.Cdb[i]=MySRB.CDBByte[i];
  171. il = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
  172. if (DeviceIoControl(hDriveEvent, IOCTL_SCSI_PASS_THROUGH_DIRECT,
  173. &sb, il, &sb, il, &ol, NULL))
  174. if (sb.sptd.ScsiStatus==0)
  175. {
  176. MySRB.SRB_Status=SS_COMP;
  177. return;
  178. }
  179. MySRB.SRB_Status=SS_ERR;
  180. return;
  181. }
  182. DWORD ASPI_Status;
  183. ResetEvent(hDriveEvent);
  184. ASPI_Status = SendASPI32Command ((LPSRB)&MySRB);
  185. }
  186. BYTE WaitSCSIRequest(SRB_ExecSCSICmd &MySRB,HANDLE hDriveEvent,BOOL bImmediate)
  187. {
  188. if ((MySRB.SRB_HaId>=NumberOfHostAdapters) &&
  189. RunningNT)
  190. return MySRB.SRB_Status;
  191. if ((MySRB.SRB_Status == SS_PENDING) &&
  192. !bImmediate)
  193. {
  194. DWORD ASPIEventStatus = WaitForSingleObject(hDriveEvent, 100);
  195. if (ASPIEventStatus == WAIT_OBJECT_0)
  196. {
  197. ResetEvent(hDriveEvent);
  198. }
  199. }
  200. return MySRB.SRB_Status;
  201. }
  202. BOOL AbortSCSIRequest(SRB_ExecSCSICmd &StuckSRB)
  203. {
  204. SRB_Abort AbortSRB;
  205. DWORD ASPIStatus;
  206. AbortSRB.SRB_Cmd = SC_ABORT_SRB;
  207. AbortSRB.SRB_HaId = StuckSRB.SRB_HaId;
  208. AbortSRB.SRB_Flags = 0;
  209. AbortSRB.SRB_Hdr_Rsvd = 0;
  210. AbortSRB.SRB_ToAbort = (LPSRB)&StuckSRB;
  211. ASPIStatus = SendASPI32Command ( (LPSRB)&AbortSRB );
  212. return (ASPIStatus==SS_COMP);
  213. }
  214. int GetDeviceInfo(int HostAdapterNumber,int TargetId,int LUN,BYTE &SCSIType,char *VendorID,
  215. char *ProductID,char *ProductRevision,HANDLE hDriveEvent)
  216. {
  217. struct InquireFormat
  218. {
  219. BYTE ConfigPara[8];
  220. char VendorID[8];
  221. char ProductID[16];
  222. char ProductRevision[4];
  223. } DeviceInfo;
  224. TOpcode OpC;
  225. OpC[0]=0x12;
  226. OpC[1]=0;
  227. OpC[2]=0;
  228. OpC[3]=0;
  229. OpC[4]=sizeof(DeviceInfo);
  230. OpC[5]=0;
  231. memset(&DeviceInfo,0,sizeof(DeviceInfo));
  232. BOOL r=ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,6,(void*)&DeviceInfo,sizeof(DeviceInfo),hDriveEvent);
  233. if (r)
  234. {
  235. for (int i=0; i<16; i++)
  236. {
  237. if (i<8) VendorID[i]=DeviceInfo.VendorID[i];
  238. ProductID[i]=DeviceInfo.ProductID[i];
  239. if (i<4) ProductRevision[i]=DeviceInfo.ProductRevision[i];
  240. }
  241. VendorID[8]=0;
  242. ProductID[16]=0;
  243. ProductRevision[4]=0;
  244. SCSIType=DeviceInfo.ConfigPara[2] & 0x0f;
  245. return DeviceInfo.ConfigPara[0];
  246. }
  247. return DTYPE_UNKNOWN;
  248. }
  249. BOOL TestUnitReady(int HostAdapterNumber,int TargetId,int LUN,HANDLE hDriveEvent)
  250. {
  251. TOpcode OpC;
  252. OpC[0]=0;
  253. OpC[1]=0;
  254. OpC[2]=0;
  255. OpC[3]=0;
  256. OpC[4]=0;
  257. OpC[5]=0;
  258. return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,6,NULL,0,hDriveEvent);
  259. }
  260. BOOL ModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,int PageCode,HANDLE hDriveEvent)
  261. {
  262. // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
  263. TOpcode OpC;
  264. OpC[0]=0x1a;
  265. OpC[1]=0x00;
  266. OpC[2]=PageCode;
  267. OpC[3]=0x00;
  268. OpC[4]=Size;
  269. OpC[5]=0x00;
  270. return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,6,(void *)&ModeData,Size,hDriveEvent);
  271. }
  272. BOOL ATAPIModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,int PageCode,HANDLE hDriveEvent)
  273. {
  274. // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
  275. TOpcode OpC;
  276. OpC[0]=0x5a;
  277. OpC[1]=0x00;
  278. OpC[2]=PageCode;
  279. OpC[3]=0x00;
  280. OpC[4]=0x00;
  281. OpC[5]=0x00;
  282. OpC[6]=0x00;
  283. OpC[7]=0x00;
  284. OpC[8]=Size;
  285. OpC[9]=0x00;
  286. OpC[10]=0x00;
  287. OpC[11]=0x00;
  288. return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,12,(void *)&ModeData,Size,hDriveEvent);
  289. }
  290. BOOL addModeSense(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent)
  291. {
  292. // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
  293. TOpcode OpC;
  294. OpC[0]=0xca;
  295. OpC[1]=0x08;
  296. OpC[2]=0x0f;
  297. OpC[3]=0x00;
  298. OpC[4]=0x00;
  299. OpC[5]=0x00;
  300. OpC[6]=0x00;
  301. OpC[7]=0x00;
  302. OpC[8]=Size;
  303. OpC[9]=0x00;
  304. return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_IN,OpC,10,(void *)&ModeData,Size,hDriveEvent);
  305. }
  306. BOOL ModeSelect(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent)
  307. {
  308. // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
  309. TOpcode OpC;
  310. OpC[0]=0x15;
  311. if (Size==12)
  312. OpC[1]=0x00;
  313. else
  314. OpC[1]=0x10;
  315. OpC[2]=0x00;
  316. OpC[3]=0x00;
  317. OpC[4]=Size;
  318. OpC[5]=0x00;
  319. return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_OUT,OpC,6,(void *)&ModeData,Size,hDriveEvent);
  320. }
  321. BOOL addModeSelect(int HostAdapterNumber,int TargetId,int LUN,TDriveMode &ModeData,int Size,HANDLE hDriveEvent)
  322. {
  323. // while (!TestUnitReady(HostAdapterNumber,TargetId,LUN));
  324. TOpcode OpC;
  325. OpC[0]=0xc5;
  326. OpC[1]=0x10;
  327. OpC[2]=0x00;
  328. OpC[3]=0x00;
  329. OpC[4]=0x00;
  330. OpC[5]=0x00;
  331. OpC[6]=0x00;
  332. OpC[7]=0x00;
  333. OpC[8]=Size;
  334. OpC[9]=0x00;
  335. return ExecuteSCSIRequest(HostAdapterNumber,TargetId,LUN,SRB_DIR_OUT,OpC,10,(void *)&ModeData,Size,hDriveEvent);
  336. }
  337. BOOL SCSIMaxBlocks(HANDLE fh, int *mb)
  338. {
  339. DWORD ol;
  340. IO_SCSI_CAPABILITIES ca;
  341. if (DeviceIoControl(fh,IOCTL_SCSI_GET_CAPABILITIES,NULL,0,
  342. &ca,sizeof(IO_SCSI_CAPABILITIES),&ol,NULL))
  343. {
  344. *mb=(int)ca.MaximumTransferLength;
  345. return TRUE;
  346. }
  347. return FALSE;
  348. }