diff options
| author | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
| commit | 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch) | |
| tree | 46f3701832d70b420eb0fc0eb93261f9da45db3f /tools/sdv/samples/SDV-FailDriver-STORPORT/driver | |
| parent | ef1905bf1e8825bb31120dfb27e0daf3154d859a (diff) | |
Initial publish
Diffstat (limited to 'tools/sdv/samples/SDV-FailDriver-STORPORT/driver')
14 files changed, 11105 insertions, 0 deletions
diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/MAKEFILE.ddk b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/MAKEFILE.ddk new file mode 100644 index 00000000..fd6ff2a2 --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/MAKEFILE.ddk @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +MINIMUM_NT_TARGET_VERSION=0x502 +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/SCR_U3M.H b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/SCR_U3M.H new file mode 100644 index 00000000..8bb6c618 --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/SCR_U3M.H @@ -0,0 +1,514 @@ +/*++ + +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +PARTICULAR PURPOSE. + +Copyright (c) Microsoft Corporation. All rights reserved + +Module Name: + + scr_u3m.h + +Abstract: + + Private header file for lsi_u3.sys modules. This contains private + structure and function declarations as well as constant values which do + not need to be exported. + +Environment: + + kernel mode only + +Notes: + + +Revision History: + +--*/ + + +/* +************************************************************************* +* * +* Copyright 1994-2008 LSI Corporation. All rights reserved. * +* * +************************************************************************/ + + +typedef unsigned long ULONG; + +ULONG SCRIPT[] = { + 0x808CF800L, 0x000004B4L, + 0x808CF803L, 0x00000234L, + 0x808CF802L, 0x0000078CL, + 0x808CF804L, 0x000008D0L, + 0x80880000L, 0x00000494L, + 0x7C027F00L, 0x00000000L, + 0x60000040L, 0x00000000L, + 0xE2DC0004L, 0x00000970L, + 0x725F0080L, 0x00000000L, + 0x808C0002L, 0x000001E4L, + 0xE1100004L, 0x000000B8L, + 0x72140000L, 0x00000000L, + 0x8084FB04L, 0x00000048L, + 0xF11C0004L, 0x00000000L, + 0x721C0000L, 0x00000000L, + 0x80840000L, 0xFFFFFFE8L, + 0x721D0000L, 0x00000000L, + 0x80840000L, 0xFFFFFFD8L, + 0x721E0000L, 0x00000000L, + 0x80840000L, 0xFFFFFFC8L, + 0x721F0000L, 0x00000000L, + 0x80840000L, 0xFFFFFFB8L, + 0xC1000008L, 0x0000096CL, 0x00000000L, + 0x98180000L, 0x00000000L, + 0xF11C0004L, 0x00000008L, + 0xE21C0004L, 0x000000B8L, + 0x48000000L, 0x00000000L, + 0x80880000L, 0x000003D8L, + 0x48000000L, 0x00000000L, + 0xC100000CL, 0x00000000L, 0x00000960L, + 0xE1100004L, 0x00000960L, + 0x72100000L, 0x00000000L, + 0x8084F801L, 0xFFFFFEF0L, + 0x7C10F800L, 0x00000000L, + 0xC0000004L, 0x00000964L, 0x00000134L, + 0xE0100004L, 0x00000138L, + 0xE1100004L, 0x0000013CL, + 0xC1000004L, 0x00000000L, 0x00000978L, + 0xC1000004L, 0x00000978L, 0x0000096CL, + 0x47000008L, 0x00000370L, + 0xE1100004L, 0x000000F0L, + 0xF25C0004L, 0x00000000L, + 0xC1000004L, 0x00000968L, 0x000000F0L, + 0xE1100004L, 0x0000013CL, + 0xE1DC0004L, 0x0000093CL, + 0x1E000000L, 0x00000018L, + 0x828B0000L, 0x00000018L, + 0x838A0000L, 0x00000084L, + 0x878A0000L, 0x00000104L, + 0x80880000L, 0x0000053CL, + 0x1A000000L, 0x00000010L, + 0x818B0000L, 0x00000040L, + 0x808A0000L, 0x00000038L, + 0x87820000L, 0x00000018L, + 0x0F000001L, 0x00000020L, + 0x808C0004L, 0x000006D8L, + 0x80880000L, 0x000000CCL, + 0x838A0000L, 0x00000034L, + 0x80880000L, 0x000004F4L, + 0x7A3C0C80L, 0x00000000L, + 0xC0000004L, 0x000009C4L, 0x00000210L, + 0x80000000L, 0x00000000L, + 0x88080000L, 0x00000930L, + 0x83830000L, 0x00000008L, + 0x0B000001L, 0x000000DFL, + 0x878B0000L, 0x00000078L, + 0x80880000L, 0x000004B0L, + 0x48000000L, 0x00000000L, + 0x98080000L, 0x0000FF12L, + 0x7C10F800L, 0x00000000L, + 0xE0100004L, 0x00000268L, + 0x72100000L, 0x00000000L, + 0xE1100004L, 0x0000026CL, + 0xC1000004L, 0x00000000L, 0x00000978L, + 0xC1000004L, 0x00000978L, 0x0000096CL, + 0x47000008L, 0x00000240L, + 0xE1100004L, 0x000000F0L, + 0x6A1C0200L, 0x00000000L, + 0xF21C0001L, 0x00000000L, + 0x80880000L, 0xFFFFFEC0L, + 0x0F000001L, 0x00000020L, + 0x808C0000L, 0xFFFFFD74L, + 0x808C0004L, 0x00000068L, + 0x808C0002L, 0x00000040L, + 0x808C0003L, 0x00000350L, + 0x808C0001L, 0x00000058L, + 0x808C0023L, 0x00000110L, + 0x808C0007L, 0x00000180L, + 0x80840F80L, 0x00000120L, + 0x60000040L, 0x00000000L, + 0x878B0000L, 0xFFFFFFA8L, + 0x90080000L, 0x00000000L, + 0x60000040L, 0x00000000L, + 0x9F030000L, 0x0000AA01L, + 0x0F000001L, 0x00000020L, + 0x80840004L, 0x000003C0L, + 0x80880000L, 0x00000558L, + 0x60000040L, 0x00000000L, + 0x87830000L, 0x000003A8L, + 0x0F000001L, 0x00000020L, + 0x808C0006L, 0x00000040L, + 0x808C0003L, 0x00000068L, + 0x80840002L, 0x000000B0L, + 0x60000040L, 0x00000000L, + 0x0F000001L, 0x00000020L, + 0x80840003L, 0x00000098L, + 0x60000040L, 0x00000000L, + 0x0F000001L, 0x00000020L, + 0x98080000L, 0x0000AA1CL, + 0x60000040L, 0x00000000L, + 0x0F000001L, 0x00000020L, + 0x80840004L, 0x00000068L, + 0x60000040L, 0x00000000L, + 0x0F000005L, 0x00000020L, + 0x98080000L, 0x0000AA15L, + 0x60000040L, 0x00000000L, + 0x0F000001L, 0x00000020L, + 0x80840001L, 0x00000038L, + 0x60000040L, 0x00000000L, + 0x0F000002L, 0x00000020L, + 0x98080000L, 0x0000AA0CL, + 0x60000040L, 0x00000000L, + 0x87830000L, 0x000002E8L, + 0x0F000001L, 0x00000020L, + 0x980C0001L, 0x0000AA14L, + 0x58000008L, 0x00000000L, + 0x60000040L, 0x00000000L, + 0x878B0000L, 0x00000020L, + 0x86820000L, 0x000002B8L, + 0x0E000001L, 0x0000094CL, + 0x868B0000L, 0x000002A8L, + 0x80880000L, 0x000001D8L, + 0x0F000001L, 0x00000020L, + 0x60000040L, 0x00000000L, + 0x878B0000L, 0xFFFFFFE8L, + 0x80880000L, 0xFFFFFFC0L, + 0x98080000L, 0x0000FF0EL, + 0x58000008L, 0x00000000L, + 0x60000040L, 0x00000000L, + 0x86830000L, 0x00000260L, + 0x1E000000L, 0x00000018L, + 0x98080000L, 0x0000FF0AL, + 0x58000008L, 0x00000000L, + 0x60000040L, 0x00000000L, + 0x86830000L, 0x00000238L, + 0x1E000000L, 0x00000018L, + 0x80880000L, 0x00000168L, + 0x54000000L, 0x000001F8L, + 0xE1100004L, 0x00000954L, + 0x710A0000L, 0x00000000L, + 0x69080000L, 0x00000000L, + 0x6C103C00L, 0x00000000L, + 0x720A0000L, 0x00000000L, + 0x6A600000L, 0x00000000L, + 0x7A4F2000L, 0x00000000L, + 0xF1030001L, 0x00000003L, + 0x7C4FDF00L, 0x00000000L, + 0xF1060001L, 0x00000002L, + 0xF1050001L, 0x00000001L, + 0xF1BC0001L, 0x00000000L, + 0x0F000001L, 0x00000020L, + 0x60000040L, 0x00000000L, + 0x6C1C1F00L, 0x00000000L, + 0x87830000L, 0x00000118L, + 0x72580000L, 0x00000000L, + 0x80840020L, 0x00000108L, + 0x0F000001L, 0x00000021L, + 0x60000040L, 0x00000000L, + 0x0F000001L, 0x00000022L, + 0x60000040L, 0x00000000L, + 0x6A1C0000L, 0x00000000L, + 0xE1100004L, 0x00000018L, + 0x781D0000L, 0x00000000L, + 0x791C0000L, 0x00000000L, + 0x791D0000L, 0x00000000L, + 0x791C0000L, 0x00000000L, + 0x791D0000L, 0x00000000L, + 0x791C0000L, 0x00000000L, + 0x791D0000L, 0x00000000L, + 0xE21C0002L, 0x000005E8L, + 0xE01C0002L, 0x000005D0L, + 0xF11C0004L, 0x00000000L, + 0xE21C0004L, 0x00000600L, + 0x7E100400L, 0x00000000L, + 0xF11C0004L, 0x00000000L, + 0xE01C0004L, 0x000005FCL, + 0xE1100004L, 0x00000604L, + 0xC1000004L, 0x00000000L, 0x00000978L, + 0xF1DC0004L, 0x00000004L, + 0xC1000004L, 0x00000978L, 0x0000096CL, + 0x60000048L, 0x00000000L, + 0x818B0000L, 0xFFFFFBCCL, + 0x808A0000L, 0xFFFFFBC4L, + 0x828A0000L, 0xFFFFFB6CL, + 0x8F8A0000L, 0xFFFFFC60L, + 0x838A0000L, 0xFFFFFBD0L, + 0x868A0000L, 0xFFFFFE18L, + 0x80880000L, 0x00000088L, + 0x74600F00L, 0x00000000L, + 0x781D0000L, 0x00000000L, + 0x6D080000L, 0x00000000L, + 0x7D1D0000L, 0x00000000L, + 0x791C0000L, 0x00000000L, + 0x791C0000L, 0x00000000L, + 0x791C0000L, 0x00000000L, + 0xE01D0001L, 0x0000069DL, + 0x7A1C0000L, 0x00000000L, + 0x6A1D0000L, 0x00000000L, + 0xE1100004L, 0x0000001CL, + 0x80880000L, 0xFFFFFF00L, + 0x721A0000L, 0x00000000L, + 0xE11C0004L, 0x00000958L, + 0x721C0000L, 0x00000000L, + 0x980C0001L, 0x0000AA05L, + 0x80880000L, 0xFFFFFA08L, + 0x58000008L, 0x00000000L, + 0x60000040L, 0x00000000L, + 0x9E030000L, 0x0000FF08L, + 0x7C027F00L, 0x00000000L, + 0x0E000001L, 0x00000944L, + 0x48000000L, 0x00000000L, + 0x98080000L, 0x0000FF07L, + 0xE11C0004L, 0x00000008L, + 0x741C0100L, 0x00000000L, + 0x80840001L, 0x00000018L, + 0xC1000004L, 0x000000F0L, 0x00000008L, + 0xC1000004L, 0x00000014L, 0x000000F0L, + 0xE1100004L, 0x00000010L, + 0xF11C0004L, 0x00000000L, + 0x721C0000L, 0x00000000L, + 0x8084F802L, 0x00000030L, + 0xE11C0004L, 0x000009BCL, + 0x7A1C0300L, 0x00000000L, + 0xF21C0004L, 0x00000000L, + 0xF11C0004L, 0x00000008L, + 0xE21C0004L, 0x00000010L, + 0x80880000L, 0xFFFFF948L, + 0x98080000L, 0x0000FF13L, + 0xC1000004L, 0x000000F0L, 0x00000014L, + 0xC1000004L, 0x00000008L, 0x000000F0L, + 0x7A1C0100L, 0x00000000L, + 0xE21C0004L, 0x00000008L, + 0x80880000L, 0xFFFFF918L, + 0xE0B40004L, 0x000007ECL, + 0xE0CC0004L, 0x000007E8L, + 0x01000001L, 0x00000000L, 0x00000000L, + 0x80880000L, 0x00000010L, + 0xE0CC0004L, 0x00000804L, + 0x01000001L, 0x00000000L, + 0x7E4C0180L, 0x00000000L, + 0x7F4D0080L, 0x00000000L, + 0x7F4E0080L, 0x00000000L, + 0x7F4F0080L, 0x00000000L, + 0x78570000L, 0x00000000L, + 0x87820000L, 0x000000A8L, + 0x0F000001L, 0x00000020L, + 0x80840002L, 0xFFFFFA64L, + 0x60000040L, 0x00000000L, + 0x87830000L, 0xFFFFFE8CL, + 0x0F000001L, 0x00000020L, + 0x80840004L, 0xFFFFFE7CL, + 0xE0D00004L, 0x00000878L, + 0xC1000008L, 0x000000C8L, 0x00000000L, + 0xF2D00004L, 0x0000004CL, + 0xF2DC0004L, 0x00000004L, + 0xC1000004L, 0x000009BCL, 0x000008ACL, + 0xC0000004L, 0x000009C0L, 0x000008A4L, + 0xC1000004L, 0x00000978L, 0x00000000L, + 0x7C027F00L, 0x00000000L, + 0x60000040L, 0x00000000L, + 0xC0000004L, 0x000009B8L, 0x000008D4L, + 0xC1000008L, 0x000009BCL, 0x00000000L, + 0x80880000L, 0xFFFFF804L, + 0x83820000L, 0xFFFFFDFCL, + 0x80880000L, 0xFFFFF92CL, + 0x7C10F800L, 0x00000000L, + 0xF11C0004L, 0x00000000L, + 0xE21C0004L, 0x0000096CL, + 0xE1100004L, 0x000000F0L, + 0xF25C0004L, 0x00000000L, + 0xE11C0004L, 0x00000968L, + 0xE21C0004L, 0x000000F0L, + 0x98080000L, 0x0000AA09L, + 0x90080000L, 0x00000000L, + 0x98080000L, 0x00000000L, + 0x98080000L, 0x0000000CL, + 0x98080000L, 0x00000007L, + 0x98080000L, 0x00000000L, + 0x80000000L, 0x00000000L, + 0xC0000004L, 0x00000000L, 0x00000000L, + 0xC0000004L, 0x00000000L, 0x00000000L, + 0x80000000L, 0x00000000L + +}; + +ULONG R_base_Used[] = { + 0x00000088L, + 0x0000021DL +}; + +ULONG R_context_Used[] = { + 0x0000023FL +}; + +ULONG R_dataXferParmTable_Used[] = { + 0x00000255L +}; + +ULONG R_vars_Used[] = { + 0x00000073L, + 0x000000AAL, + 0x000000C6L, + 0x000000D0L, + 0x000000DAL, + 0x000000E0L, + 0x000000E6L, + 0x000000ECL, + 0x000000F2L, + 0x000000F8L, + 0x00000100L, + 0x00000112L, + 0x0000014AL, + 0x00000156L, + 0x0000015AL, + 0x00000160L, + 0x000001ACL, + 0x000001C8L, + 0x000001CFL, + 0x000001D1L, + 0x000001D4L, + 0x000001E4L, + 0x000001EBL, + 0x000001EDL, + 0x000001F2L, + 0x0000020FL, + 0x00000217L +}; + +ULONG R_runningCount_Used[] = { + 0x00000183L, + 0x00000222L +}; + +ULONG R_iovPtr_Used[] = { + 0x00000220L +}; + +#define A_ZERO 0x00000000L +#define A_patchValue 0x00000000L +#define A_SVDT_SEM_FREE 0x00000000L +#define A_SCSIMESS_COMMAND_COMPLETE 0x00000000L +#define A_SVDT_SEM_START 0x00000001L +#define A_SCSIMESS_EXTENDED_MESSAGE 0x00000001L +#define A_SCSIMESS_SYNCHRONOUS_DATA_REQ 0x00000001L +#define A_SVDT_SEM_QSEM 0x00000001L +#define A_SCSISTAT_CHECK_CONDITION 0x00000002L +#define A_SVDT_SEM_UNLOCK 0x00000002L +#define A_SCSIMESS_SAVE_DATA_POINTER 0x00000002L +#define A_SCSIMESS_WIDE_DATA_REQUEST 0x00000003L +#define A_SCSIMESS_RESTORE_POINTERS 0x00000003L +#define A_SVDT_SEM_REQ_SNS 0x00000003L +#define A_INTFLY_SET 0x00000004L +#define A_SCSIMESS_DISCONNECT 0x00000004L +#define A_SCSIMESS_PPR_DATA_REQUEST 0x00000004L +#define A_SVDT_SEM_NVCONFIG 0x00000004L +#define A_SCSIMESS_MESSAGE_REJECT 0x00000007L +#define A_SCSIMESS_BUS_DEVICE_RESET 0x0000000CL +#define A_ENID_MASK 0x0000000FL +#define A_LUN_MASK 0x0000001FL +#define A_SCSIMESS_SIMPLE_QUEUE_TAG 0x00000020L +#define A_SCSIMESS_IGNORE_WIDE_RESIDUE 0x00000023L +#define A_SCSIMESS_IDENTIFY 0x00000080L +#define A_SVDT_SEM_MASK_VALUE 0x000000F8L +#define A_INTFLY_MASK 0x000000FBL +#define A_Save_Pointers 0x0000AA01L +#define A_ScriptsAborted 0x0000AA05L +#define A_NVConfigInt 0x0000AA09L +#define A_SynchNegotComp 0x0000AA0CL +#define A_IgnoreWideRes 0x0000AA14L +#define A_PprNegotComp 0x0000AA15L +#define A_WideNegotComp 0x0000AA1CL +#define A_DeviceReset 0x0000FF07L +#define A_ResetFailed 0x0000FF08L +#define A_ParityMessageSent 0x0000FF0AL +#define A_MessageRejected 0x0000FF0EL +#define A_CheckCondition 0x0000FF12L +#define A_CAQueueFull 0x0000FF13L +#define Ent_Add2CaQueue 0x0000071CL +#define Ent_burstRS_PA 0x00000264L +#define Ent_CommandScriptStart 0x000000ECL +#define Ent_ContNegScript 0x00000494L +#define Ent_DQ_entry 0x0000096CL +#define Ent_DataOutJump1 0x000001B8L +#define Ent_DataOutJump2 0x0000062CL +#define Ent_JumpPatch 0x00000048L +#define Ent_NopPatch 0x00000204L +#define Ent_PhaseMisJump1 0x00000828L +#define Ent_PhaseMisJump2 0x000007F8L +#define Ent_PhaseMisJump64 0x000007D4L +#define Ent_postDoneQ 0x000000B0L +#define Ent_RejectMessage 0x0000040CL +#define Ent_RestartScript 0x0000061CL +#define Ent_SendErrorMessage 0x0000046CL +#define Ent_scriptStopFlag 0x00000958L +#define Ent_svdt 0x00000978L + + +ULONG LABELPATCHES[] = { + 0x0000000FL, + 0x00000015L, + 0x0000002DL, + 0x00000034L, + 0x0000003DL, + 0x0000003FL, + 0x00000047L, + 0x00000048L, + 0x0000004AL, + 0x0000004CL, + 0x0000004FL, + 0x00000051L, + 0x00000052L, + 0x00000056L, + 0x0000005AL, + 0x0000005BL, + 0x0000005DL, + 0x0000005FL, + 0x0000007FL, + 0x00000080L, + 0x00000084L, + 0x00000094L, + 0x00000098L, + 0x0000009BL, + 0x0000009DL, + 0x0000009EL, + 0x000000A2L, + 0x0000010CL, + 0x00000132L, + 0x00000170L, + 0x00000172L, + 0x00000176L, + 0x0000017CL, + 0x0000017EL, + 0x00000181L, + 0x00000185L, + 0x00000186L, + 0x000001A6L, + 0x000001B2L, + 0x000001C2L, + 0x000001CEL, + 0x000001D2L, + 0x000001DCL, + 0x000001EAL, + 0x000001EEL, + 0x000001F6L, + 0x000001F8L, + 0x000001FFL, + 0x0000021BL, + 0x00000224L, + 0x00000225L, + 0x00000227L, + 0x00000228L, + 0x0000022AL, + 0x00000231L, + 0x00000232L, + 0x00000234L, + 0x00000241L, + 0x00000243L, + 0x00000247L, + 0x00000249L +}; + +#define INSTRUCTIONS 0x00000124L diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.c b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.c new file mode 100644 index 00000000..786994bf --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.c @@ -0,0 +1,8858 @@ +/*++ + +Module Name: + + lsi_u3.c + +Abstract: + + This is a sample driver that contains intentionally placed + code defects in order to illustrate how Static Driver Verifier + works. This driver is not functional and not intended as a + sample for real driver development projects. + +Environment: + + Kernel mode + +--*/ + + +/* +************************************************************************* +* * +* Copyright 1994-2008 LSI Corporation. All rights reserved. * +* * +************************************************************************/ + +#pragma warning(disable:4127) // conditional expression is constant +#pragma warning(disable:4213) // nonstandard extension used : cast on l-value +#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int +#pragma warning(disable:4701) // potentially uninitialized local variable 'n' used + +/**********************************************************************/ + +#define FORCE_SYNC // this define will default the driver to force sync. +/**********************************************************************/ + +// +// include files used by the Miniport +// +#include "miniport.h" +#include "storport.h" +#include "lsi_u3.h" + +#include "scr_u3m.h" // memory mapped scripts + +#include "lsisiop.h" +#include "lsinvm.h" +#include "lsisvdt.h" +#include "lsiver.h" + +// headers for DMI support +#include "ntddscsi.h" +#include "lsidmi.h" + +// Define the SRB Extension. +// + +typedef struct _SRB_EXTENSION { + UCHAR PhysBreakCount; // physical break count + UCHAR SrbExtFlags; // negot & other flags + UCHAR autoReqSns; // autoReqSns flag + UCHAR trackEntry; // I/O track array entry + PSVARS_DESCRIPTOR_TABLE svdt; // pointer to this svdt + SVARS_DESCRIPTOR_TABLE svarsDescriptorTable; // descriptor table + UCHAR AlignPad[4]; + +}SRB_EXTENSION, *PSRB_EXTENSION; + + +#define SRB_EXT(x) ((PSRB_EXTENSION)(x->SrbExtension)) + + + +// Define the noncached extension. Data items are placed in the noncached +// extension because they are accessed via DMA. + +typedef struct _HW_NONCACHED_EXTENSION { + + ULONG ScsiScripts[ sizeof(SCRIPT) / 4 ]; + SVARS_DESCRIPTOR NegotMsgBufDesc[SYM_MAX_TARGETS]; + NEGOT_BUF NegotMsg[SYM_MAX_TARGETS]; + ULONG dataXferParms[SYM_MAX_TARGETS]; + START_QUEUE_ENTRY startQueue[START_Q_DEPTH]; + START_QUEUE_ENTRY caQueue[CA_Q_DEPTH]; + DONE_QUEUE_ENTRY doneQueue[DONE_Q_DEPTH]; + NEXUS_PTR ITLnexusPtrs[256]; + UCHAR alignPad[4]; + +} HW_NONCACHED_EXTENSION, *PHW_NONCACHED_EXTENSION; + +// +// Define the LSI_U3 Device Extension structure +// + +typedef struct _HW_DEVICE_EXTENSION { + + PHW_NONCACHED_EXTENSION NonCachedExtension; // pointer to noncached + // device extension + PSIOP_REGISTER_BASE SIOPRegisterBase; // 53C1010 SIOP register base. + ULONG SIOPRegisterBasePhys; // physical ptr for patching + + PSVARS svars; // ptr to svarsTable structure + ULONG *dxp; // ptr to data xfer table, all devices + ULONG *dxpSR; // ptr to data xfer table in SRam + ULONG old_dxp; // dxp value at start of req sns negots + + PSTART_QUEUE_ENTRY ioStartQueue; // ptr to scripts start queue + ULONG ioStartQPhys; // physical ptr + PSTART_QUEUE_ENTRY caStartQueue; // ptr to scripts ca queue + ULONG caStartQPhys; // physical ptr + PDONE_QUEUE_ENTRY ioDoneQueue; // ptr to scripts completion queue + ULONG ioDoneQPhys; // physical ptr + ULONG ioStartQIndex; // offset with in start queue + ULONG ioDoneQIndex; // offset with in completion queue + PULONG DQ_entrySR; // ptr to DQ_entry in Scripts RAM + PULONG scriptStopFlag; // ptr to scriptStopFlag in Scripts RAM + + PNEXUS_PTR ITQnexusTable; // ptr to tagged nexus pointer array + ULONG ITQnexusTablePhys; // physical ptr + PNEXUS_PTR ITLnexusTable; // ptr to untagged nexus pointer array + ULONG ITLnexusTablePhys; // physical ptr + + PSVARS_DESCRIPTOR_TABLE localSvdt; // pointer to local svdt in SRam + ULONG localIovPhys; // physical ptr to local iov list + + SVARS_DESCRIPTOR deviceDesc; // template for deviceDescriptor + SVARS_DESCRIPTOR cmdBufDesc; // template for cmdBufDescriptor + SVARS_DESCRIPTOR msgOutDesc; // template for msgOutDescriptor + + USHORT DeviceFlags; // bus specific flags + UCHAR SIOPBusID; // SCSI bus ID in integer form. + +// script physical address entry points follow... + + ULONG RestartScriptPhys; // phys ptr to restart script + ULONG CommandScriptPhys; // phys ptr to cmd start script + ULONG SendIDEScriptPhys; // phys ptr to IDE message script + ULONG RejectScriptPhys; // phys ptr to reject message script + ULONG ContNegScriptPhys; // phys ptr to continue negotiations script + ULONG Add2CaQScriptPhys; // phys ptr to add to auto req sns queue + ULONG PhaseMisJump1Phys; // phys ptr to phase mismatch jump 1 + ULONG PhaseMisJump2Phys; // phys ptr to phase mismatch jump 2 + ULONG PhaseMisJump64Phys; // phys ptr to phase mismatch jump 64 + ULONG DQ_entryPhys; // phys ptr to DQ_entry storage + ULONG DataOutJump1Phys; // phys ptr to DataOutJump1 + +// define pointers to the active logical unit object + + PSCSI_REQUEST_BLOCK ActiveRequest; // pointer to active LU + +// logical unit specific flags and logical unit index + + USHORT LuFlags[SYM_MAX_TARGETS]; // logical unit spec. flags + + USHORT hbaCapability; // HBA capabilities bit-field + UCHAR chip_rev; // chip revision + + UCHAR ClockSpeed; // SIOP clock speed + BOOLEAN IO_blocked; // flag to indicate I/O's are blocked + BOOLEAN StopAdapter; // flag to indicate HBA is shutdown + +// target intiated negotiation values from target + UCHAR tin_rec_period; // requested period + UCHAR tin_rec_offset; // requested offset + UCHAR tin_rec_DT; // requested DT transfers + + ULONG ScriptRamPhys; // start of Scripts RAM (physical) + ULONG_PTR ScriptRamVirt; // start of Scripts RAM (virtual) + ULONG_PTR ScriptStartVirt; // start of Scripts instructions (virtual) + +// extra resources for the nvram/NVS values + DEVICE_TABLE DeviceTable[HW_MAX_DEVICES]; + UINT8 Gpio[5]; // GPIO pin usage table (pin 0 placeholder) + UINT8 HostSCSIId; // HBA initiator ID + USHORT TerminatorState; // SCSI termination state + ULONG BiosCodeSpacePtr; // pointer to BIOS code space (read NVS) + ULONG NVSDataOffset; // offset of first NVS data area + ULONG IoPortAddress; // saved off to identify device in NVS area + ULONG PciBusSlot; // saved PCI bus/slot numbers for NVConfig + +// crash dump indicator + ULONG crash_dump; // flag to indicate memory dump mode + +// reset active flag + ULONG ResetActive; // non-zero indicates a device reset is active + +// queue tag FIFO and pointers + UCHAR QTagFIFO[START_Q_DEPTH]; // FIFO for assigning queue tag values + ULONG QTagFree; // pointer to next free queue tag + ULONG QTagPost; // pointer to next tag re-post entry + +// I/O tracking array and track array FIFO + IO_TRACK_ENTRY IoTrackArray[START_Q_DEPTH]; // I/O tracking array + UCHAR IoTrackFIFO[START_Q_DEPTH]; // FIFO to find next entry + ULONG TrackFree; // pointer to next free + ULONG TrackPost; // pointer to next post + +// data and clock masks for NVRAM access + UCHAR data_mask; // data mask for reading NVRAM + UCHAR clock_mask; // clock mask for reading MVRAM + +// flag for NTLDR context + UCHAR ntldr_flag; // flag indicating NTLDR mode + +// flag for IRQ_not_connected check + BOOLEAN IRQ_received; // flag indicating we have received interrupts + +// DMI data structure + DMI_DATA DmiData; // DMI (CIM) data for IOCTL + +} HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION; + +// predefined message buffers for wide/sync negotiation messages +UCHAR narrow_msg[4] = { 0x01, 0x02, 0x03, 0x00 }; +UCHAR async_msg[5] = { 0x01, 0x03, 0x01, 0x19, 0x00 }; +UCHAR ppr_msg[8] = { 0x01, 0x06, 0x04, 0x19, 0x00, 0x00, 0x00, 0x00 }; + +// version string for DMI +UCHAR driver_version[] = LSI_VERSION_LABEL; // driver version string + +// +// LSI_U3 miniport driver function declarations. +// + +BOOLEAN NvmDetect( PHW_DEVICE_EXTENSION DeviceExtension ); +void NvmSendStop( PHW_DEVICE_EXTENSION DeviceExtension ); +void NvmSendStart( PHW_DEVICE_EXTENSION DeviceExtension ); +UINT NvmSendData( PHW_DEVICE_EXTENSION DeviceExtension, UINT Value ); +UINT8 NvmReadData( PHW_DEVICE_EXTENSION DeviceExtension ); +void NvmSendAck( PHW_DEVICE_EXTENSION DeviceExtension ); +UINT NvmReceiveAck( PHW_DEVICE_EXTENSION DeviceExtension ); +void NvmSendNoAck( PHW_DEVICE_EXTENSION DeviceExtension); +BOOLEAN NVSDetect( PHW_DEVICE_EXTENSION DeviceExtension); +BOOLEAN RetrieveNVSData( PHW_DEVICE_EXTENSION DeviceExtension); +VOID FillNvmData( PHW_DEVICE_EXTENSION DeviceExtension, + PTR_NON_VOLATILE_SETTINGS pNVM); +BOOLEAN ReadNVM( PHW_DEVICE_EXTENSION DeviceExtension, PVOID dataBuf, + PULONG ret_length); +BOOLEAN WriteNVM( PHW_DEVICE_EXTENSION DeviceExtension, _In_reads_bytes_(length) PVOID dataBuf, + _In_range_(1, sizeof(NON_VOLATILE_SETTINGS)) ULONG length); +MEMORY_STATUS HwReadNonVolatileMemory( PHW_DEVICE_EXTENSION DeviceExtension, + UINT8 *Buffer, UINT Offset, UINT Length ); +UINT16 CalculateCheckSum(UINT8 * PNvmData, UINT16 Length); +UINT8 CalculateMfgCheckSum(UINT8 * PNvmData, UINT16 Length); +VOID RetrieveMfgData( PHW_DEVICE_EXTENSION DeviceExtension); +void HwInitGpioPins( PHW_DEVICE_EXTENSION DeviceExtension); +char HwFindGpioPin( PHW_DEVICE_EXTENSION DeviceExtension, char usageCode, + PUCHAR ptrActiveLevel ); +char HwReadGpioPin( PHW_DEVICE_EXTENSION DeviceExtension, char usageCode); +char HwSetGpioPin( PHW_DEVICE_EXTENSION DeviceExtension, char usageCode, + char setting); +BOOLEAN RetrieveNvmData( PHW_DEVICE_EXTENSION DeviceExtension); +void InvalidateNvmData( PHW_DEVICE_EXTENSION DeviceExtension ); +void data_output( PHW_DEVICE_EXTENSION DeviceExtension); +void data_input( PHW_DEVICE_EXTENSION DeviceExtension); +void set_data( PHW_DEVICE_EXTENSION DeviceExtension); +void reset_data( PHW_DEVICE_EXTENSION DeviceExtension); +void set_clock( PHW_DEVICE_EXTENSION DeviceExtension); +void reset_clock( PHW_DEVICE_EXTENSION DeviceExtension); +UCHAR set_1010_clock(PHW_DEVICE_EXTENSION DeviceExtension); +UCHAR set_sync_speed(PHW_DEVICE_EXTENSION DeviceExtension, UCHAR period); +VOID ISR_Service_Next(PHW_DEVICE_EXTENSION DeviceExtension,UCHAR ISRDisposition); +VOID doneQRemove(PHW_DEVICE_EXTENSION DeviceExtension, UCHAR IntStatus); +BOOLEAN EatInts(PHW_DEVICE_EXTENSION DeviceExtension); +void delay_mils( USHORT counter); + +void NvmPageWrite( PHW_DEVICE_EXTENSION DeviceExtension, + UINT8 *Buffer, UINT Offset, UINT Pages ); +void NvmByteWrite( PHW_DEVICE_EXTENSION DeviceExtension, + UINT8 *Buffer, UINT Offset, UINT Length ); +MEMORY_STATUS HwWriteNonVolatileMemory( PHW_DEVICE_EXTENSION DeviceExtension, + UINT8 *Buffer, UINT Offset, UINT Length ); + +VOID +AbortCurrentScript( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +PreAbortScripts( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +BusResetPostProcess( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +CheckSubsysID( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ USHORT SubsystemID + ); + +VOID +ComputeSCSIScriptVectors( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ); + +/*ULONG +DriverEntry( + _In_ PVOID DriverObject, + _In_ PVOID Argument2 + );*/ + +VOID +InitializeSIOP( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +initializeSvdtQueue( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ); + +SCSI_ADAPTER_CONTROL_STATUS +LsiU3AdapterControl( + _In_ PVOID DevExt, + _In_ SCSI_ADAPTER_CONTROL_TYPE ControlType, + _In_ PVOID Parameters + ); + +/*ULONG +LsiU3FindAdapter( + _In_ PVOID Context, + _In_ PVOID Reserved1, + _In_ PVOID Reserved2, + // DDK has argument #4 as a PCHAR + //_In_ PCSTR ArgumentString, + _In_ PCHAR ArgumentString, + _Inout_ PPORT_CONFIGURATION_INFORMATION ConfigInfo, + _In_ PUCHAR Reserved3 + ); + +BOOLEAN +LsiU3HWInitialize( + _In_ PVOID Context + ); + +BOOLEAN +LsiU3ISR( + _In_ PVOID Context + ); + +BOOLEAN +LsiU3Reset( + _In_ PVOID DeviceExtension, + _In_ ULONG PathId + );*/ + +BOOLEAN +SynchronizeReset( + _In_ PVOID Context, + _In_ PVOID ptrPathId + ); + +/*BOOLEAN +LsiU3BuildIo( + _In_ PVOID Context, + _In_ PSCSI_REQUEST_BLOCK Srb + ); + +BOOLEAN +LsiU3StartIo( + _In_ PVOID Context, + _In_ PSCSI_REQUEST_BLOCK Srb + );*/ + +UCHAR +ProcessBadDataDirection( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessBusResetReceived( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessCheckCondition( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +ProcessCommandComplete( + PHW_DEVICE_EXTENSION DeviceExtension, + ULONG statXferLen + ); + +UCHAR +ProcessDeviceResetFailed( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessDeviceResetOccurred( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessDiffSenseChange( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessDMAInterrupt( + PHW_DEVICE_EXTENSION DeviceExtension, + UCHAR DmaStatus + ); + +UCHAR +ProcessErrorMsgSent( + VOID + ); + +UCHAR +ProcessGrossError( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessIgnoreWideResidue( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessIllegalInstruction( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessInvalidReselect( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessNVConfigIoctl( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessParityError( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessPhaseMismatch( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +BOOLEAN +ProcessParseArgumentString( + //_In_ PCSTR String, + _In_ PCHAR String, + //_In_ PCSTR WantedString, + _In_ PCHAR WantedString, + _Out_ PULONG ValueFound + ); + +UCHAR +ProcessPprNegotComplete( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessRejectReceived( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessSaveDataPointers( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessSCSIInterrupt( + PHW_DEVICE_EXTENSION DeviceExtension, + UCHAR ScsiStatus + ); + +UCHAR +ProcessSelectionTimeout( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessSynchNegotComplete( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessNegotNotSupported( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +ProcessUnexpectedDisconnect( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +ScheduleReinit( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +TimerReinit( + _In_ PVOID Context + ); + +BOOLEAN +SynchronizeISRReinit( + _In_ PVOID Context, + _In_ PVOID dummy + ); + +VOID +ResetSCSIBus( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ); + +USHORT +ScatterGatherScriptSetup( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ PSCSI_REQUEST_BLOCK Srb, + _In_ BOOLEAN hostSvdt + ); + +VOID +SetChipModes ( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +SetupLuFlags( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ UCHAR ResetFlag + ); + +VOID +SetupNegotBuf( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ UCHAR target, + _In_ UCHAR negot_type + ); + +UCHAR +ProcessWideNegotComplete( + PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +StartAbortResetRequest( + PSCSI_REQUEST_BLOCK Srb, + PHW_DEVICE_EXTENSION DeviceExtension + ); + +UCHAR +StartNegotiations( + PHW_DEVICE_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK Srb, + UCHAR MessageCount, + _In_ BOOLEAN hostSvdt + ); + +VOID +StartNVConfigRequest( + PSCSI_REQUEST_BLOCK Srb, + PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +StartSCSIRequest( + PSCSI_REQUEST_BLOCK Srb, + PHW_DEVICE_EXTENSION DeviceExtension + ); + +VOID +StartSIOP( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ ULONG ScriptPhysAddr + ); + +VOID +UpdateStartQDesc( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ PSCSI_REQUEST_BLOCK Srb + ); + + +VOID +AbortCurrentScript( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ) + +/*++ + +Routine Description: + + + This routine aborts the scripts to make sure they are NOT running. + +Arguments: + + DeviceExtension - Supplies the device Extension for the SCSI bus adapter. + +Return Value: + + none + +--*/ + +{ + UCHAR IntStat; + UCHAR AbortIteration = 0; + UCHAR i; + + // mask off all interrupts + WRITE_SIOP_UCHAR(SIEN0, 0); + WRITE_SIOP_UCHAR(SIEN1, 0); + WRITE_SIOP_UCHAR(DIEN, 0); + + // try to abort scripts a maximum of ABORT_SCRIPTS_TRIES only + for (i = 0; i < ABORT_SCRIPTS_TRIES; i++) + { + // set abort bit to stop scripts + WRITE_SIOP_UCHAR( ISTAT0, ISTAT_ABORT); + + do { + IntStat = READ_SIOP_UCHAR( ISTAT0); + + // if we are in the second or greater iteration of this loop.. + if (AbortIteration++) { + + // wait a moment + StorPortStallExecution( ABORT_STALL_TIME); + + if (AbortIteration > MAX_ABORT_TRIES) { + + DebugPrint((1, "LsiU3(%2x): AbortCurrentScript timeout - ISTAT0 = %x\n", + DeviceExtension->SIOPRegisterBase, IntStat)); + + // If can't get DMA_INT to set, assume abort worked and + // break to check DSTAT below. If not set, will loop again. + break; + + } // if + } // if + } while ( !( IntStat & ( ISTAT_SCSI_INT | ISTAT_DMA_INT))); + + if ( IntStat & ISTAT_SCSI_INT) { + + // read SCSI interrupts to clear ISTAT. + + READ_SIOP_UCHAR(SIST0); + READ_SIOP_UCHAR(SIST1); + + // retry aborting of scripts + continue; + } // if + + // A DMA interrupt has occured. + WRITE_SIOP_UCHAR( ISTAT0, 0); + + // if interrupt was an ABORT, we're done so just break out of loop. + if ( READ_SIOP_UCHAR( DSTAT) & DSTAT_ABORTED) + break; + + } // for + +} // AbortCurrentScript + + +VOID +PreAbortScripts( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ) + +/*++ + +Routine Description: + + This routine attempts to stop the Scripts via a flag in Scripts RAM, tested + after issuing a SIGP. This is to prevent doing an Abort via ISTAT0 while + the Scripts are executing. This is called prior to AbortCurrentScript. + +Arguments: + + DeviceExtension - Supplies a pointer to device extension. + +Return Value: + + None. + +--*/ + +{ + UCHAR IntStat; + int i; + + // mask off all interrupts + WRITE_SIOP_UCHAR(SIEN0, 0); + WRITE_SIOP_UCHAR(SIEN1, 0); + WRITE_SIOP_UCHAR(DIEN, 0); + + // write the scriptsStopFlag + StorPortWriteRegisterUlong( DeviceExtension, + DeviceExtension->scriptStopFlag, 1); + // write SIGP + WRITE_SIOP_UCHAR(ISTAT0, ISTAT_SIGP); + // wait for an interrupt (anything but an INT_FLY) + for (i = 0; i < 2000; i++) + { + StorPortStallExecution(999); + IntStat = READ_SIOP_UCHAR( ISTAT0); + // check for INT_FLY + if ( IntStat & ISTAT_INTF ) + { + // clear the INT_FLY interrupt + WRITE_SIOP_UCHAR(ISTAT0, IntStat); + } + else if ( IntStat & (ISTAT_SCSI_INT | ISTAT_DMA_INT) ) + { + // we have a hard interrupt, Scripts are stopped + break; + } + } + + // clear the SIGP just in case + WRITE_SIOP_UCHAR( ISTAT0, 0); + + // clear the scriptsStopFlag +#ifdef AMD64 + StorPortWriteRegisterUlong64( DeviceExtension, + NULL, + MAXULONG64); +#else + StorPortWriteRegisterUlong( DeviceExtension, + DeviceExtension->scriptStopFlag, + 0); +#endif + + // if we didn't get an interrupt either Scripts aren't running or we're + // hung on the bus. In either case, just return and allow the Abort to + // happen because there is no DMA occurring. + + return; + +} // PreAbortScripts + + +VOID +BusResetPostProcess( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ) + +/*++ + +Routine Description: + + This routine aborts any pending requests after a bus reset is received. + It also resets the LuFlags and re-initializes all the svdt queues. + +Arguments: + + DeviceExtension - Supplies a pointer to device extension for the bus that + was reset. + +Return Value: + + None. + +--*/ + +{ + SetupLuFlags(DeviceExtension,1); + + initializeSvdtQueue(DeviceExtension); + + DeviceExtension->ActiveRequest = NULL; + +//*********************************************************************************************** +//* +//* WARNING: Do not use StorPortCompleteRequest in your own miniport. +//* +//* As discussed at the 2008 Microsoft Windows Driver Developer Conference, using +//* StorPortCompleteRequest will lead to race conditions that could result in +//* double-completions and never-completions. The recommended approach to handling +//* resets is to loop through all requests currently owned by the miniport and complete +//* each one using StorPortNotification( RequestComplete ). +//* +//*********************************************************************************************** + + //_____________________________________________________________________ + // Defect injection for: StorPortDeprecated.slic + // (this call was already in the driver) + // Part B, see part A in LsiU3ISR. + StorPortCompleteRequest(DeviceExtension, + 0, + SP_UNTAGGED, + SP_UNTAGGED, + SRB_STATUS_BUS_RESET + ); + //_____________________________________________________________________ + + StorPortStallExecution(POST_RESET_STALL_TIME); + + return; + +} // BusResetPostProcess + + +VOID +CheckSubsysID( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ USHORT SubsystemID + ) +/*++ + +Routine Description: + + This procedure decodes the PCI Subsystem ID bits to determine selected + features and operation of the 1010 device and sets the appropriate bits + in DeviceFlags. + +Arguments: + + DeviceExtension - Pointer to the device extension for this adapter. + + SubsystemID - PCI Subsystem ID value retrieved from PCI config space. + +Return Value: + + None + +--*/ + +{ + union _subsysID { + struct { + USHORT Features : 7; + USHORT SubType : 3; + USHORT AdapType : 2; + USHORT ConfigType : 3; + USHORT ExcludeFlag : 1; + } b; + USHORT ssid; + } subsysID; + UCHAR cfg_typ; + UCHAR adap_typ; + UCHAR sub_typ; + UCHAR feat; + + // move PCI Subsystem ID into local structure and variables + subsysID.ssid = SubsystemID; + cfg_typ = (UCHAR)subsysID.b.ConfigType; + adap_typ = (UCHAR)subsysID.b.AdapType; + sub_typ = (UCHAR)subsysID.b.SubType; + feat = (UCHAR)subsysID.b.Features; + + // we don't look at the exclude flag since the miniport cannot exclude + // a device once it is called. + + // check configuration type for non-supported values + if ( !(cfg_typ == 1 || cfg_typ > 5) ) + return; + + // check adapter type for non-supported values + if ( adap_typ > 1 || (adap_typ == 1 && sub_typ > 0) ) + return; + + // check for swapped NVM clock/data lines + if ( cfg_typ == 7 ) + DeviceExtension->DeviceFlags |= DFLAGS_SWAP_NVM_LINES; + + // check adapter features common to all supported configurations + // check for narrow only mode + if ( feat & 1 ) + DeviceExtension->DeviceFlags |= DFLAGS_FORCE_NARROW; + // check for forcing of half speed + if ( feat & 2 ) + DeviceExtension->DeviceFlags |= DFLAGS_HALF_SPEED; + // check for flag to not use NVM (non-LSI) + if ( feat & 4 ) + DeviceExtension->DeviceFlags |= DFLAGS_NO_NVM_ACCESS; + + return; +} // CheckSubsysID + + +VOID +ComputeSCSIScriptVectors( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine computes 53C1010 script physical addresses, and fills in + device extension fields used by scripts. It also patches labels and + variables into the scripts, and moves the scripts to scripts RAM if + available. Note that all patching is done in the SCRIPTS array, then + they are moved to the aligned scripts location or scripts RAM. + +Arguments: + + PHW_DEVICE_EXTENSION DeviceExtension + +Return Value: + + None. + +--*/ + +{ + ULONG SegmentLength; // receives length of physical memory segment + PHW_NONCACHED_EXTENSION NonCachedExtPtr = + DeviceExtension->NonCachedExtension; + PULONG ScriptArrayPtr, srcPtr, dstPtr; + ULONG svdtPhys, svdtIovOffset, ScriptRegPtr; + ULONG ScriptPhys, SvarsPhys, dxpPhys, SRamPhys; + ULONG NegotBufDescPhys, NegotMsgPhys; + ULONG_PTR SRamVirt, ScriptVirt; + USHORT i; + + // Non-cached extension is always allocated on a 4 byte boundary, so + // alignment is not necessary. The svars and ITQnexus tables are located + // in Scripts RAM and are not part of the non-cached extension. + + ScriptArrayPtr = (PULONG)DeviceExtension->NonCachedExtension->ScsiScripts; + ScriptPhys = StorPortConvertPhysicalAddressToUlong( + StorPortGetPhysicalAddress(DeviceExtension, NULL, + (PVOID)DeviceExtension->NonCachedExtension, + &SegmentLength)); + + // move scripts to NonCachedExtension for patching + StorPortMoveMemory( ScriptArrayPtr, SCRIPT, sizeof(SCRIPT) ); + + // set NegotMsgBufDesc array & MegotMsg array phys pointers + NegotBufDescPhys = ScriptPhys + sizeof(SCRIPT); + NegotMsgPhys = NegotBufDescPhys + sizeof(NonCachedExtPtr->NegotMsgBufDesc); + + // get non cached extension pointers into device extension + DeviceExtension->dxp = NonCachedExtPtr->dataXferParms; + DeviceExtension->ioStartQueue = NonCachedExtPtr->startQueue; + DeviceExtension->caStartQueue = NonCachedExtPtr->caQueue; + DeviceExtension->ioDoneQueue = NonCachedExtPtr->doneQueue; + DeviceExtension->ITLnexusTable = NonCachedExtPtr->ITLnexusPtrs; + + // get physical pointers for use by scripts. + DeviceExtension->ioStartQPhys = ScriptPhys + + FIELD_OFFSET(HW_NONCACHED_EXTENSION, startQueue); + DeviceExtension->caStartQPhys = ScriptPhys + + FIELD_OFFSET(HW_NONCACHED_EXTENSION, caQueue); + DeviceExtension->ioDoneQPhys = ScriptPhys + + FIELD_OFFSET(HW_NONCACHED_EXTENSION, doneQueue); + DeviceExtension->ITLnexusTablePhys = ScriptPhys + + FIELD_OFFSET(HW_NONCACHED_EXTENSION, ITLnexusPtrs); + + // align ITLnexusTable on 8 byte boundary (scripts efficiency) + if (DeviceExtension->ITLnexusTablePhys & 0x00000007) + { + DeviceExtension->ITLnexusTablePhys += 4; + DeviceExtension->ITLnexusTable = + (PNEXUS_PTR)((ULONG_PTR)(DeviceExtension->ITLnexusTable) + 4); + } + + // initialize the negotiation buffer table descriptor physical addresses + for (i = 0; i < SYM_MAX_TARGETS; i++) + { + NonCachedExtPtr->NegotMsgBufDesc[i].paddr = + NegotMsgPhys + (i * sizeof(NEGOT_BUF)); + } + + // set virtual/physical pointers to top of Scripts RAM + SRamPhys = DeviceExtension->ScriptRamPhys; + SRamVirt = DeviceExtension->ScriptRamVirt; + // put ITQnexusTable at top of Scripts RAM + // (ITQ and ITL tables are the same size) + DeviceExtension->ITQnexusTable = (PNEXUS_PTR)SRamVirt; + DeviceExtension->ITQnexusTablePhys = SRamPhys; + SRamVirt += sizeof(NonCachedExtPtr->ITLnexusPtrs); + SRamPhys += sizeof(NonCachedExtPtr->ITLnexusPtrs); + // put dxp table after ITQnexusTable (insures 256 byte alignment) + DeviceExtension->dxpSR = (PULONG)SRamVirt; + dxpPhys = SRamPhys; + SRamVirt += sizeof(NonCachedExtPtr->dataXferParms); + SRamPhys += sizeof(NonCachedExtPtr->dataXferParms); + // put svars table after the dxp table + DeviceExtension->svars = (PSVARS)SRamVirt; + SvarsPhys = SRamPhys; + SRamVirt += sizeof(SVARS); + SRamPhys += sizeof(SVARS); + // set area for scripts below previous elements, update saved values + ScriptVirt = SRamVirt; + ScriptPhys = SRamPhys; + DeviceExtension->ScriptStartVirt = ScriptVirt; + // calculate virtual/physical address of local (SRam) svdt + DeviceExtension->localSvdt = + (PSVARS_DESCRIPTOR_TABLE)(ScriptVirt + Ent_svdt); + svdtPhys = ScriptPhys + Ent_svdt; + // calculate virtual address of local (SRam) DQ_entry + DeviceExtension->DQ_entrySR = (PULONG)(ScriptVirt + Ent_DQ_entry); + // calculate virtual address of local (SRam) scriptStopFlag + DeviceExtension->scriptStopFlag = (PULONG)(ScriptVirt + Ent_scriptStopFlag); + + // calcuate physical address of local iov list + svdtIovOffset = FIELD_OFFSET(SVARS_DESCRIPTOR_TABLE, iovList); + DeviceExtension->localIovPhys = svdtPhys + svdtIovOffset; + + // fill in template table descriptor physical addresses + DeviceExtension->deviceDesc.paddr = 0; // NULL for deviceDesc + DeviceExtension->cmdBufDesc.paddr = svdtPhys + + FIELD_OFFSET(SVARS_DESCRIPTOR_TABLE, Cdb); + DeviceExtension->msgOutDesc.paddr = svdtPhys + + FIELD_OFFSET(SVARS_DESCRIPTOR_TABLE, msgOutBuf); + + // the following code computes physical addresses of script entry points. + + DeviceExtension->CommandScriptPhys = ScriptPhys + Ent_CommandScriptStart; + DeviceExtension->RestartScriptPhys = ScriptPhys + Ent_RestartScript; + DeviceExtension->RejectScriptPhys = ScriptPhys + Ent_RejectMessage; + DeviceExtension->SendIDEScriptPhys = ScriptPhys + Ent_SendErrorMessage; + DeviceExtension->ContNegScriptPhys = ScriptPhys + Ent_ContNegScript; + DeviceExtension->Add2CaQScriptPhys = ScriptPhys + Ent_Add2CaQueue; + DeviceExtension->PhaseMisJump1Phys = ScriptPhys + Ent_PhaseMisJump1; + DeviceExtension->PhaseMisJump2Phys = ScriptPhys + Ent_PhaseMisJump2; + DeviceExtension->PhaseMisJump64Phys = ScriptPhys + Ent_PhaseMisJump64; + DeviceExtension->DQ_entryPhys = ScriptPhys + Ent_DQ_entry; + DeviceExtension->DataOutJump1Phys = ScriptPhys + Ent_DataOutJump1; + + // Use memory mapped base address + ScriptRegPtr = DeviceExtension->SIOPRegisterBasePhys; + + // patches for scripts in system memory + + for (i = 0; i < sizeof(LABELPATCHES) / 4; i++) + { + ScriptArrayPtr[(int)LABELPATCHES[(int)i]] = ScriptPhys + + SCRIPT[(int)LABELPATCHES[(int)i]]; + } + + for ( i = 0; i < sizeof(R_vars_Used) /4; i++ ) + { + ScriptArrayPtr[(int)R_vars_Used[(int)i]] = SvarsPhys + + SCRIPT[(int)R_vars_Used[(int)i]]; + } + + for ( i = 0; i < sizeof(R_base_Used) /4; i++ ) + { + ScriptArrayPtr[(int)R_base_Used[i]] = ScriptRegPtr + + SCRIPT[(int)R_base_Used[(int)i]]; + } + + for ( i = 0; i < sizeof(R_dataXferParmTable_Used) /4; i++ ) + { + ScriptArrayPtr[(int)R_dataXferParmTable_Used[i]] = dxpPhys + + SCRIPT[(int)R_dataXferParmTable_Used[i]]; + } + + ScriptArrayPtr[(int)(Ent_burstRS_PA / 4)] = MEMORY_MOVE_CMD + + svdtIovOffset + 36; + + // if in NTLDR context, patch jump instruction to force all I/O's to + // interrupt at completion + if (DeviceExtension->ntldr_flag) + ScriptArrayPtr[(int)(Ent_JumpPatch / 4)] = JUMP_REL_SCRIPT; + + // if using 64-bit addresses, patch nop to set bit 1 in CCNTL1 + if ( DeviceExtension->DeviceFlags & DFLAGS_64BIT_ADDRESS ) + ScriptArrayPtr[(int)(Ent_NopPatch / 4)] = ENABLE_64BITS; + + // For 1010-66 patch 2 jump instructions to jump to the previous instruction + // (this previous instruction is the SCNTL4 settings instruction) + if ( (DeviceExtension->hbaCapability & HBA_CAPABILITY_1010_66) && + (DeviceExtension->chip_rev == 0) ) + { + ScriptArrayPtr[(int)(Ent_DataOutJump1 / 4) + 1] -= SCRIPT_INS_SIZE; + ScriptArrayPtr[(int)(Ent_DataOutJump2 / 4) + 1] -= SCRIPT_INS_SIZE; + } + + // a for loop is used here due to errata on the device. + // Systems with "CPU to PCI Posted Write" enabled will not + // work with a StorPortWriteRegisterBuffer command + srcPtr = ScriptArrayPtr; + dstPtr = (PULONG)ScriptVirt; + for (i = 0; i < (sizeof(SCRIPT)/4); i++) + { + StorPortWriteRegisterUlong( DeviceExtension, dstPtr++, *(srcPtr++)); + } + +} // ComputeSCSIScriptVectors + + +ULONG +DriverEntry( + _In_ PVOID DriverObject, + _In_ PVOID Argument2 + ) + +/*++ + +Routine Description: + + Initial entry point for LSI_U3 miniport driver. + +Arguments: + + Driver Object + +Return Value: + + Status indicating whether adapter(s) were found and initialized. + +--*/ + +{ + HW_INITIALIZATION_DATA hwInitializationData; + ULONG i, Status; + + DebugPrint((1, "\nLSI Ultra160 SCSI Miniport Driver.\n\n")); + + // Initialize the hardware initialization data structure. + for ( i = 0; i < sizeof( HW_INITIALIZATION_DATA); i++) + { + ((PUCHAR)&hwInitializationData)[i] = 0; + } + + // Set size of hardware initialization structure. + hwInitializationData.HwInitializationDataSize = + sizeof(HW_INITIALIZATION_DATA); + + // Identify required miniport entry point routines. + hwInitializationData.HwInitialize = LsiU3HWInitialize; + hwInitializationData.HwStartIo = LsiU3StartIo; + hwInitializationData.HwInterrupt = LsiU3ISR; + hwInitializationData.HwFindAdapter = LsiU3FindAdapter; + hwInitializationData.HwResetBus = LsiU3Reset; + hwInitializationData.HwAdapterControl = LsiU3AdapterControl; + hwInitializationData.HwBuildIo = LsiU3BuildIo; + + // Specifiy adapter specific information. + hwInitializationData.AutoRequestSense = TRUE; + hwInitializationData.NeedPhysicalAddresses = TRUE; + hwInitializationData.NumberOfAccessRanges = 3; + hwInitializationData.AdapterInterfaceType = PCIBus; + hwInitializationData.MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS; + hwInitializationData.TaggedQueuing = TRUE; + hwInitializationData.MultipleRequestPerLu = TRUE; + + // Set required extension sizes. + hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); + hwInitializationData.SrbExtensionSize = sizeof(SRB_EXTENSION); + + // call StorPort to register our HW init data + Status = StorPortInitialize( DriverObject, + Argument2, + &hwInitializationData, + NULL); + + return(Status); + +} // end DriverEntry() + + +VOID +InitializeSIOP( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This function initializes the LSI SCSI adapter chip. It sets up all + registers, clocks, and chip features. + +Arguments: + + DeviceExtension - Pointer to the specific device extension for this SCSI + bus. + +Return Value: + + NONE + +--*/ + +{ + UCHAR HbaId = 0; + UCHAR scntl3Value; + UCHAR sst0, sst1, dst; + UCHAR sig_type = STEST4_SNGL_ENDED; + USHORT i, termState; + ULONG jumpAddr; + PULONG srcPtr, dstPtr, selAddr; + + DebugPrint((3, "LsiU3(%2x): Reinitializing chip now... \n", + DeviceExtension->SIOPRegisterBase )); + + WRITE_SIOP_UCHAR( ISTAT0, 0x40 ); + + for ( i = 0; i < MAX_CLEAR_FIFO_LOOP; i++ ) { + + StorPortStallExecution( POST_RESET_STALL_TIME ); + WRITE_SIOP_UCHAR( ISTAT0, 0 ); + if ( !(READ_SIOP_UCHAR( ISTAT0 ) & 0x40) ) + break; + } + + // Insure that Flush DMA FIFO, Clear DMA FIFO, and Fetch Pin Mode + // bits are all cleared. + WRITE_SIOP_UCHAR( CTEST3, 0x00); + + // Set DMA control values: + WRITE_SIOP_UCHAR (DCNTL, 0x81); + WRITE_SIOP_UCHAR (DMODE, 0x02); + + // Set chip modes according to chip revisions and registry settings + SetChipModes(DeviceExtension); + + // set SCSI Control Register 0 bits + WRITE_SIOP_UCHAR( SCNTL0, SCNTL0_ARB_MODE_1 + SCNTL0_ARB_MODE_0 + + SCNTL0_ENA_PARITY_CHK + SCNTL0_ASSERT_ATN_PAR ); + + // set SCSI clock frequency + scntl3Value = set_1010_clock (DeviceExtension); + + // initialize data transfer parameter table in table indirect format + // (dxp) points to table in system memory + for (i = 0; i < SYM_MAX_TARGETS; i++) + { + // ID in byte lane 2 + DeviceExtension->dxp[(int)i] = (ULONG)(i << 16); + // SCNTL3 value in byte lane 3 + DeviceExtension->dxp[(int)i] |= ((ULONG)scntl3Value << 24); + } + // copy initizlied table to dxp table in Scripts RAM + srcPtr = DeviceExtension->dxp; + dstPtr = DeviceExtension->dxpSR; + for (i = 0; i < 16; i++) + StorPortWriteRegisterUlong( DeviceExtension, dstPtr++, *(srcPtr++)); + + // Enable data phase mismatch processing internal to 1010 + WRITE_SIOP_UCHAR( CCNTL0, CCNTL0_DISABLE_PIPE_REQ + CCNTL0_ENA_PM_JUMP); + // Disable 64-bit slave cycles + WRITE_SIOP_UCHAR( CCNTL1, 0x10); + // Set phase mismatch jump registers + WRITE_SIOP_ULONG( PMJAD1, DeviceExtension->PhaseMisJump1Phys); + // select correct WSR jump routine based on 32 or 64 bit + if ( DeviceExtension->DeviceFlags & DFLAGS_64BIT_ADDRESS ) + jumpAddr = DeviceExtension->PhaseMisJump64Phys; + else + jumpAddr = DeviceExtension->PhaseMisJump2Phys; + WRITE_SIOP_ULONG( PMJAD2, jumpAddr); + + // Clear all 64-bit Scripts selectors (in case EFI BIOS set them) + selAddr = &(DeviceExtension->SIOPRegisterBase)->MMRS; + for ( i = 0; i < 6; i++ ) + StorPortWriteRegisterUlong( DeviceExtension, selAddr++, 0); + + // clear the scriptsStopFlag + StorPortWriteRegisterUlong( DeviceExtension, + DeviceExtension->scriptStopFlag, 0); + + // set SCSI bus SCSI ID - enable response to reselections + WRITE_SIOP_UCHAR( SCID, (UCHAR)(DeviceExtension->SIOPBusID + 0x40 )); + + // set reselection ID + if ( DeviceExtension->SIOPBusID < 0x08 ) { + WRITE_SIOP_UCHAR( RESPID0, (UCHAR) (1 << DeviceExtension->SIOPBusID )); + } else { + HbaId = DeviceExtension->SIOPBusID - 8; + WRITE_SIOP_UCHAR( RESPID1, (UCHAR) (1 << HbaId )); + } + + // on 1010-66, disable AIP (on by default) + if ( DeviceExtension->hbaCapability & HBA_CAPABILITY_1010_66 ) + WRITE_SIOP_UCHAR( AIPCNTL1, 0x08); + + // Clear all interrupt status registers. Diffsense interrupt (and others) + for ( i = 0; i < 100; i++ ) + { + sst0 = READ_SIOP_UCHAR(SIST0); + sst1 = READ_SIOP_UCHAR(SIST1); + dst = READ_SIOP_UCHAR(DSTAT) & 0x7F; // mask off DMA FIFO full + if ( !(sst0 || sst1 || dst) ) + break; + } + + // Enable appropriate SCSI interrupts + WRITE_SIOP_UCHAR( SIEN0, SIEN0_PHASE_MISMATCH + + SIEN0_SCSI_GROSS_ERROR + + SIEN0_UNEXPECTED_DISCON + + SIEN0_RST_RECEIVED + + SIEN0_PARITY_ERROR + ); + + // enable appropriate DMA interrupts + WRITE_SIOP_UCHAR( DIEN, DIEN_ENA_ABRT_INT + + DIEN_BUS_FAULT + + DIEN_ENABLE_INT_RCVD + + DIEN_ENABLE_ILL_INST + ); + + // Enable additional SCSI interrupts + // Selection or relection time-out & LDVS difsense interrupts + WRITE_SIOP_UCHAR( SIEN1, SIEN1_SEL_RESEL_TIMEOUT + + SIEN1_BUS_MODE_CHANGE + ); + + // set ScratchB register to 0 for use by scripts + WRITE_SIOP_ULONG( SCRATCHB, 0 ); + + // Set the SCSI timer values + WRITE_SIOP_UCHAR( STIME0, 0x0c ); + + // Enable TolerANT + WRITE_SIOP_UCHAR( STEST3, 0x80 ); + + // Initialize input/output settings of GPIO pins + HwInitGpioPins( DeviceExtension); + + // see if termination should be programmed ON or OFF + termState = DeviceExtension->TerminatorState; + if ( termState != TS_CANT_PROGRAM ) + { + if ( termState == TS_ENABLED ) + // turn on termination + HwSetGpioPin( DeviceExtension, GPIO_TERMINATION, GPIO_ON); + else if ( termState == TS_DISABLED ) + // turn off termination + HwSetGpioPin( DeviceExtension, GPIO_TERMINATION, GPIO_OFF); + } + + // see if in LVDS mode + if (DeviceExtension->DeviceFlags & DFLAGS_LVDS_MODE) + sig_type = STEST4_LOWV_DIFF; + // put signal type into DMI structure + DeviceExtension->DmiData.SignalType = sig_type >> 6; + + // enable internal connected signal on GPIO0 to be LED activity signal + WRITE_SIOP_UCHAR(GPCNTL,(UCHAR)(READ_SIOP_UCHAR(GPCNTL) | GPCNTL_LED_CNTL)); + +} // InitializeSIOP + + +VOID +initializeSvdtQueue ( + _In_ PHW_DEVICE_EXTENSION DeviceExtension) +/*++ + +Routine Description: + + This routine initializes the scripts queues and variables. + +Arguments: + + DeviceExtension - Supplies the device Extension for the SCSI bus adapter. + +Return Value: + + None. + +--*/ +{ + ULONG i, linkPtr; + PULONG tmp_ptr; + PSVARS pS = DeviceExtension->svars; + PIO_TRACK_ENTRY pEntry; + + // initialize queue ptrs in svars (located in Scripts RAM) + StorPortWriteRegisterUlong( DeviceExtension, + DeviceExtension->DQ_entrySR, 0); + tmp_ptr = + (PULONG)(DeviceExtension->ScriptStartVirt + Ent_CommandScriptStart + 4); + StorPortWriteRegisterUlong( DeviceExtension, + tmp_ptr, DeviceExtension->ioStartQPhys); + StorPortWriteRegisterUlong( DeviceExtension, &pS->lockedQPhysPtr, 1); + tmp_ptr = (PULONG)(DeviceExtension->ScriptStartVirt + Ent_postDoneQ + 8); + StorPortWriteRegisterUlong( DeviceExtension, + tmp_ptr, DeviceExtension->ioDoneQPhys); + StorPortWriteRegisterUlong( DeviceExtension, &pS->caPutQPhysPtr, + DeviceExtension->caStartQPhys); + StorPortWriteRegisterUlong( DeviceExtension, &pS->caStartQPhysPtr, + DeviceExtension->caStartQPhys); + StorPortWriteRegisterUlong( DeviceExtension, &pS->ITQnexusTablePhysPtr, + DeviceExtension->ITQnexusTablePhys); + StorPortWriteRegisterUlong( DeviceExtension, &pS->ITLnexusTablePhysPtr, + DeviceExtension->ITLnexusTablePhys); + + // initialize start queue + DeviceExtension->ioStartQIndex = 0; + linkPtr = DeviceExtension->ioStartQPhys + 12; + for (i = 0; i < (START_Q_DEPTH-1); i++) + { + DeviceExtension->ioStartQueue[i].svdtPhysSem = 0; + DeviceExtension->ioStartQueue[i].linkPhys = linkPtr; + linkPtr += 12; + } + // link last element in queue back to start + DeviceExtension->ioStartQueue[START_Q_DEPTH-1].svdtPhysSem = 0; + DeviceExtension->ioStartQueue[START_Q_DEPTH-1].linkPhys = + DeviceExtension->ioStartQPhys; + + // initialize completion queue + DeviceExtension->ioDoneQIndex = 0; + linkPtr = DeviceExtension->ioDoneQPhys + 12; + for (i = 0; i < (DONE_Q_DEPTH-1); i++) + { + DeviceExtension->ioDoneQueue[i].context = 0; + DeviceExtension->ioDoneQueue[i].linkPhys = linkPtr; + linkPtr += 12; + } + // link last element in queue back to start + DeviceExtension->ioDoneQueue[DONE_Q_DEPTH-1].context = 0; + DeviceExtension->ioDoneQueue[DONE_Q_DEPTH-1].linkPhys = + DeviceExtension->ioDoneQPhys; + + // initialize ca queue + linkPtr = DeviceExtension->caStartQPhys + 12; + for (i = 0; i < (CA_Q_DEPTH-1); i++) + { + DeviceExtension->caStartQueue[i].svdtPhysSem = SVDT_SEM_UNLOCK; + DeviceExtension->caStartQueue[i].linkPhys = linkPtr; + linkPtr += 12; + } + // link last element in queue back to start + DeviceExtension->caStartQueue[CA_Q_DEPTH-1].svdtPhysSem = SVDT_SEM_UNLOCK; + DeviceExtension->caStartQueue[CA_Q_DEPTH-1].linkPhys = + DeviceExtension->caStartQPhys; + + // initialize the queue tag FIFO + DeviceExtension->QTagFree = 0; + DeviceExtension->QTagPost = 0; + for (i = 0; i < START_Q_DEPTH; i++) + { + DeviceExtension->QTagFIFO[i] = (UCHAR)i; + } + + // initialize the I/O tracking array (set all SRB addresses to NULL) + pEntry = DeviceExtension->IoTrackArray; + for (i = 0; i < START_Q_DEPTH; i++) + { + pEntry->Srb = NULL; + pEntry++; + } + + // initialize I/O track array FIFO and pointers + DeviceExtension->TrackFree = 0; + DeviceExtension->TrackPost = 0; + for (i = 0; i < START_Q_DEPTH; i++) + { + DeviceExtension->IoTrackFIFO[i] = (UCHAR)i; + } + +} // initializeSvdtQueue + + +VOID ISR_Service_Next(PHW_DEVICE_EXTENSION DeviceExtension,UCHAR ISRDisposition) +/*++ + +Routine Description: + + This routine handles the return value from various ISR service procedures + and restarts the scripts processor as required. + +Arguments: + + DeviceExtension - Supplies the device Extension for the SCSI bus adapter. + ISRDisposition - Method needed for restarting the scripts + +Return Value: + + None. + +--*/ + +{ + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + + DebugPrint((3, "LsiU3: Entering ISR_Service_Next... \n")); + + if ( ISRDisposition != ISR_EXIT ) + { + if ( ISRDisposition == ISR_START_SCRIPT ) + { + if (!DeviceExtension->ntldr_flag) // restart if not NTLDR context + StartSIOP( DeviceExtension, DeviceExtension->CommandScriptPhys); + } + else + { + if ( ISRDisposition == ISR_RELOAD_SCRIPT ) + { + WRITE_SIOP_UCHAR(SCNTL3, + (UCHAR)(DeviceExtension->dxp[Srb->TargetId] >> 24)); + WRITE_SIOP_UCHAR(SXFER, + (UCHAR)(DeviceExtension->dxp[Srb->TargetId] >> 8)); + WRITE_SIOP_UCHAR(SCNTL4, + (UCHAR)(DeviceExtension->dxp[Srb->TargetId])); + } + StartSIOP( DeviceExtension, DeviceExtension->RestartScriptPhys); + } + } + +} //isr_service_next + + +SCSI_ADAPTER_CONTROL_STATUS +LsiU3AdapterControl( + _In_ PVOID DevExt, + _In_ SCSI_ADAPTER_CONTROL_TYPE ControlType, + _In_ PVOID Parameters + ) +/*++ + +Routine Description: + + This is a generic routine to allow for special adapter control routines + to be implemented without changing the HW_INITIALIZATION_DATA structure. + Currently, it contains the StopAdapter routine and the ScsiRestartAdapter + routine which replaces FindAdapter and HwInitialize for adapters going + through a power management cycle. Since the DeviceExtension is maintained + through the power cycle, it is not necessary to use ScsiSetRunningConfig + to access system memory. + +Arguments: + + DevExt - Pointer to the device extension for this SCSI bus. + + ControlType - Specifies the type of call being made through this routine. + + Parameters - Pointer to parameters needed for this control type (optional). + +Return Value: + + SCSI_ADAPTER_CONTROL_STATUS - currently either: + ScsiAdapterControlSuccess (= 0) + ScsiAdapterControlUnsuccessful (= 1) + (additional status codes can be added with new control codes) + +--*/ + +{ + PHW_DEVICE_EXTENSION DeviceExtension = DevExt; + PSCSI_SUPPORTED_CONTROL_TYPE_LIST pCtlTypList; + + // do a switch on the ControlType + switch (ControlType) + { + // determine which control types (routines) are supported + case ScsiQuerySupportedControlTypes: + // get pointer to control type list + pCtlTypList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters; + + // Mark the types that we support. Note that we must take precautions + // to not overrun the type list buffer. + if (ScsiQuerySupportedControlTypes < pCtlTypList->MaxControlType) { + pCtlTypList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE; + } + if (ScsiStopAdapter < pCtlTypList->MaxControlType) { + pCtlTypList->SupportedTypeList[ScsiStopAdapter] = TRUE; + } + if (ScsiRestartAdapter < pCtlTypList->MaxControlType) { + pCtlTypList->SupportedTypeList[ScsiRestartAdapter] = TRUE; + } + break; + + + // StopAdapter routine called just before power down of adapter + case ScsiStopAdapter: + // if StopAdapter flag is already set, we did out shutdown via + // the SRB_FUNCTION_POWER request, just return + if ( DeviceExtension->StopAdapter ) + break; + // make sure device is still accessable (not already removed) + if ( READ_SIOP_UCHAR(ISTAT0) != 0xFF ) + { + // just call routine to abort scripts running since this + // routine first turns off all interrupts. + AbortCurrentScript(DeviceExtension); + + // get rid of any interrupts that may be pending on the adapter + // no need to test return, adapter being powered off anyway + EatInts(DeviceExtension); + } + // set StopAdapter flag + DeviceExtension->StopAdapter = TRUE; + break; + + // routine to reinitialize adapter while system in running. Since + // the adapter DeviceExtension is maintained through a power management + // cycle, we can just restore the scripts and reinitialize the chip. + case ScsiRestartAdapter: + // clear StopAdapter flag + DeviceExtension->StopAdapter = FALSE; + // reinitialize H/W + ComputeSCSIScriptVectors( DeviceExtension ); // setup scripts + InitializeSIOP( DeviceExtension ); + + if ( !EatInts( DeviceExtension )) // eat any pending interrupts + { + // if clearing interrupts fails, try resetting the bus + // and reinitializing the chip one time only. StorPort is + // notified of reset through this call. + ResetSCSIBus( DeviceExtension); + InitializeSIOP( DeviceExtension); + // ignore return this time to prevent infinite loop + EatInts( DeviceExtension); + } + + SetupLuFlags( DeviceExtension, 1 ); // init all LU flags + initializeSvdtQueue( DeviceExtension ); // init shared queues + // restart the scripts + StartSIOP( DeviceExtension, DeviceExtension->CommandScriptPhys); + // 2 second delay to allow some drives to become ready before + // I/O's start + delay_mils(2000); + break; + + } // end of switch + + //_____________________________________________________________________ + // Defect injection for: StorPortAdapterControl.slic + return ScsiAdapterControlUnsuccessful; + //_____________________________________________________________________ + +} // LsiU3AdapterControl + + +ULONG LsiU3FindAdapter( + _In_ PVOID Context, + _In_ PVOID Reserved1, + _In_ PVOID Reserved2, + _In_z_ PCHAR ArgumentString, + _Inout_ PPORT_CONFIGURATION_INFORMATION ConfigInfo, + _In_ PBOOLEAN Reserved3 + ) +/*++ + +Routine Description: + + This function fills in the configuration information structure + +Arguments: + + Context - Supplies a pointer to the device extension. + + Reserved1 - Unused. + + Reserved2 - Unused. + + ArgumentString - DriverParameter string. + + ConfigInfo - Pointer to the configuration information structure to be + filled in. + + Reserved3 - Unused. + +Return Value: + + Returns status based upon results of adapter parameter acquisition. + +--*/ + +{ + PHW_DEVICE_EXTENSION DeviceExtension = Context; + PACCESS_RANGE AccessRange, SAccessRange, MM_Range, IO_Range; + PPCI_COMMON_CONFIG pPciConf = NULL; + PUCHAR ptr; +#ifndef FORCE_SYNC + ULONG force_sync; +#endif + ULONG pci_cfg_len, loop; + ULONG load_context; + UCHAR pci_cfg_buf[48], reqId, i, hbaDeviceID; + USHORT hbaCap = 0; + BOOLEAN foundNVM; + BOOLEAN found_SymNVM = FALSE; + ULONG crash_dump = 0; + PDMI_DATA pDmi = &DeviceExtension->DmiData; + + PSTORPORT_EXTENDED_FUNCTIONS pExtFuncTable = NULL; // defect injection + BOOLEAN validateRange; // defect injection + + UNREFERENCED_PARAMETER( Reserved1 ); + UNREFERENCED_PARAMETER( Reserved2 ); + UNREFERENCED_PARAMETER( Reserved3 ); + + RtlZeroMemory(&pci_cfg_buf, 48); + + //_____________________________________________________________________ + // Defect injection for: StorPortNotification2.slic + StorPortNotification(GetExtendedFunctionTable, DeviceExtension, &pExtFuncTable); + //_____________________________________________________________________ + + // see if the DeviceExtension has not been zeroed out + if ( DeviceExtension->NonCachedExtension ) + { + // no, zero it out + ptr = (PUCHAR)DeviceExtension; + for ( loop = 0; loop < sizeof(HW_DEVICE_EXTENSION); loop++ ) + *ptr++ = 0; + } + + //_____________________________________________________________________ + // Defect injection for: StorPortDeprecated.slic + validateRange = StorPortValidateRange( + DeviceExtension, + ConfigInfo->AdapterInterfaceType, + ConfigInfo->SystemIoBusNumber, + (*ConfigInfo->AccessRanges)[0].RangeStart, + (*ConfigInfo->AccessRanges)[0].RangeLength, + (*ConfigInfo->AccessRanges)[0].RangeInMemory ); + //_____________________________________________________________________ + + // get memory-mapped and port I/O access range info. + MM_Range = IO_Range = NULL; + for ( i = 0; i < 2; i++ ) // scan ranges 0 & 1 + { + AccessRange = &((*(ConfigInfo->AccessRanges))[i]); + if ( !(AccessRange->RangeLength) ) // check for NULL entry + continue; + if ( AccessRange->RangeInMemory ) // memory-mapped or port I/O + MM_Range = AccessRange; + else + IO_Range = AccessRange; + } + + AccessRange = MM_Range; + + //_____________________________________________________________________ + // Defect injection for: StorPortVirtualDevice.slic + ConfigInfo->VirtualDevice = TRUE; + //_____________________________________________________________________ + + if (!AccessRange) // if desired access range is not available + { + return (SP_RETURN_NOT_FOUND); + } + + DeviceExtension->SIOPRegisterBase = + (PSIOP_REGISTER_BASE)StorPortGetDeviceBase(DeviceExtension, + ConfigInfo->AdapterInterfaceType, + ConfigInfo->SystemIoBusNumber, + AccessRange->RangeStart, + AccessRange->RangeLength, + (BOOLEAN)!AccessRange->RangeInMemory); + DeviceExtension->SIOPRegisterBasePhys = AccessRange->RangeStart.LowPart; + + // check for error in mapping adapter registers to a virtual address + if (!DeviceExtension->SIOPRegisterBase) + { + DebugPrint((3,"LsiU3(%2x) LsiU3FindAdapter: StorPortGetDeviceBase (reg) Failed\n")); + return (SP_RETURN_NOT_FOUND); + } + + // Save off I/O Post Address for this device for NVS detection + DeviceExtension->IoPortAddress = 0x00; + if (IO_Range) // save it if we have an IO range + DeviceExtension->IoPortAddress = IO_Range->RangeStart.LowPart; + + + + // get PCI config space header for future use + pci_cfg_len = StorPortGetBusData ( DeviceExtension, PCIConfiguration, + ConfigInfo->SystemIoBusNumber, + (ULONG)ConfigInfo->SlotNumber, + (PVOID)pci_cfg_buf, (ULONG)0x30 ); + + // if chip is not accessable, return not found status + if ( READ_SIOP_UCHAR(ISTAT0) == 0xFF ) + { + return (SP_RETURN_NOT_FOUND); + } + + // set pointer if we got valid PCI config data + if (pci_cfg_len == 0x30) + { + pPciConf = (PPCI_COMMON_CONFIG)pci_cfg_buf; + // save chip revision from PCI config space + DeviceExtension->chip_rev = pPciConf->RevisionID; + } + + + // check Subsystem ID settings + if (pPciConf) + CheckSubsysID( DeviceExtension, pPciConf->u.type0.SubSystemID); + + // get PCI device ID from config space, if no config info default to 1010 + hbaDeviceID = pPciConf ? (UCHAR)pPciConf->DeviceID : 0x20; + + // use device ID to set proper HBA capabilities + switch (hbaDeviceID) + { + case 0x20: // 53C1010-33 + hbaCap = HBA_CAPABILITY_WIDE + HBA_CAPABILITY_64_BITS + + HBA_CAPABILITY_8K_SCR_RAM + HBA_CAPABILITY_SCRIPT_RAM; + break; + + case 0x21: // 53C1010-66 + hbaCap = HBA_CAPABILITY_WIDE + HBA_CAPABILITY_64_BITS + + HBA_CAPABILITY_8K_SCR_RAM + HBA_CAPABILITY_SCRIPT_RAM + + HBA_CAPABILITY_1010_66; + break; + } + + DeviceExtension->ScriptRamPhys = 0; + if (hbaCap & HBA_CAPABILITY_SCRIPT_RAM) + { + SAccessRange = &((*(ConfigInfo->AccessRanges))[2]); + if ( SAccessRange->RangeLength ) + { + // just map the Script Ram area here + // save the needed address into ScriptRamPhys + DeviceExtension->ScriptRamVirt = + (ULONG_PTR)StorPortGetDeviceBase(DeviceExtension, + ConfigInfo->AdapterInterfaceType, + ConfigInfo->SystemIoBusNumber, + SAccessRange->RangeStart, + SAccessRange->RangeLength, + (BOOLEAN)!SAccessRange->RangeInMemory); + DeviceExtension->ScriptRamPhys = SAccessRange->RangeStart.LowPart; + } + + // if no Scripts RAM access range or if mapping of Scripts RAM to a + // virtual address fails, we can't run - return failure + if (!DeviceExtension->ScriptRamPhys || !DeviceExtension->ScriptRamVirt) + { + DebugPrint((3,"LsiU3(%2x) LsiU3FindAdapter: StorPortGetDeviceBase (SR) Failed\n")); + return (SP_RETURN_NOT_FOUND); + } + } + + // if Subsystem ID is forcing narrow, turn off wide capability + if (DeviceExtension->DeviceFlags & DFLAGS_FORCE_NARROW) + hbaCap &= ~HBA_CAPABILITY_WIDE; + + // set hbaCapability + DeviceExtension->hbaCapability = hbaCap; + + if (ArgumentString != NULL) + { + // check if doing crash dump + if (ProcessParseArgumentString(ArgumentString,"dump", &crash_dump)) + DeviceExtension->crash_dump = crash_dump; + +#ifndef FORCE_SYNC + // check for force sync registry entry + if (ProcessParseArgumentString(ArgumentString,"forcesync", + &force_sync)) + { + if (force_sync) + { + DeviceExtension->DeviceFlags |= DFLAGS_FORCE_SYNC; + } + } +#endif + + // check if in NTLDR context + if (ProcessParseArgumentString(ArgumentString,"ntldr", &load_context)) + DeviceExtension->ntldr_flag = (UCHAR)load_context; + } + +#ifdef FORCE_SYNC + // set force sync flag to ignore disable_sync + // (if not in crash dump context) + if (!crash_dump) + DeviceExtension->DeviceFlags |= DFLAGS_FORCE_SYNC; +#endif + + // make sure scripts aren't running (from a reboot) + AbortCurrentScript(DeviceExtension); + + // initialize data & clock mask values for NVM detection + DeviceExtension->data_mask = 0x01; + DeviceExtension->clock_mask = 0x02; + + // look for NVM image in NVM and NVS + foundNVM = FALSE; // set flag to invalidate NVM + if (NvmDetect(DeviceExtension) == SUCCESS) + { + found_SymNVM = TRUE; + foundNVM = RetrieveNvmData(DeviceExtension); + if (foundNVM) + { + DeviceExtension->DeviceFlags |= DFLAGS_NVM_FOUND; + // get GPIO pin usage data from Mfg data area + RetrieveMfgData(DeviceExtension); + } + } +#ifdef _X86_ + // do this only on X86 platforms + else if (NVSDetect(DeviceExtension) == SUCCESS) + { + foundNVM = RetrieveNVSData(DeviceExtension); + } +#endif + if (!foundNVM) // if NVM image not found, use default values + InvalidateNvmData(DeviceExtension); + + // Set SCSI ID obtained from NVRAM (or defaulted to 7) + DeviceExtension->SIOPBusID = (UCHAR)DeviceExtension->HostSCSIId; + + // device has clock quadrupler (40Mhz * 4 = 160Mhz) + DeviceExtension->ClockSpeed = 160; + + //_____________________________________________________________________ + // Defect injection for: StorPortFindAdapter.slic + // commenting out following line so value stays at SP_UNINITIALIZED_VALUE + // ConfigInfo->MaximumTransferLength = MAX_XFER_LENGTH; + //_____________________________________________________________________ + + // if doing crash dump we only support 64K SG list to minimize + // non-paged pool usage (needs to be < 32K) + if (crash_dump) + ConfigInfo->NumberOfPhysicalBreaks = 0x11; + else + // use compiled default (256K) + ConfigInfo->NumberOfPhysicalBreaks = MAX_SG_ELEMENTS; + + if (hbaCap & HBA_CAPABILITY_WIDE) + ConfigInfo->MaximumNumberOfTargets = SYM_MAX_TARGETS; + else + ConfigInfo->MaximumNumberOfTargets = SYM_NARROW_MAX_TARGETS; + + ConfigInfo->NumberOfBuses = 1; + ConfigInfo->ScatterGather = TRUE; + + //_____________________________________________________________________ + // Defect injection for: StorPortMSILock.slic + // See LsiU3StartIo for part B of this defect. + ConfigInfo->InterruptSynchronizationMode = InterruptSynchronizeAll; + //_____________________________________________________________________ + + + + // see if user asked for specific host ID + // if not, InitiatorBusId[0] == SP_UNINITIALIED_VALUE (0xFF) + // by checking against highest valid ID, can get both cases + // and validate users requested ID + reqId = ConfigInfo->InitiatorBusId[0]; + if ( reqId > ConfigInfo->MaximumNumberOfTargets - 1 ) + // either uninitialized or outside valid range, use our default + ConfigInfo->InitiatorBusId[0] = DeviceExtension->SIOPBusID; + else + // requested ID is good, store it + DeviceExtension->SIOPBusID = reqId; + + // set ResetTargetSupported and increase number of LUNs supported to 16. + ConfigInfo->ResetTargetSupported = TRUE; + ConfigInfo->MaximumNumberOfLogicalUnits = 16; + // set driver to run in full duplex mode + ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex; + + // if system and adapter support 64-bit addressing, set ConfigInfo, + // local flag, and adjust SrbExtension size for 64-bit move commands. + if ((ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED) && + (hbaCap & HBA_CAPABILITY_64_BITS)) + { + ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED; + DeviceExtension->DeviceFlags |= DFLAGS_64BIT_ADDRESS; + // increase size of SrbExtension to accomodate 64-bit move commands + // and 1 extra Scripts instruction (turn off 64-bit mode) + ConfigInfo->SrbExtensionSize += + (ULONG)((ConfigInfo->NumberOfPhysicalBreaks + 2) * 4); + } + + DeviceExtension->NonCachedExtension = StorPortGetUncachedExtension( + DeviceExtension, + ConfigInfo, + sizeof(HW_NONCACHED_EXTENSION) ); + + if (DeviceExtension->NonCachedExtension == NULL) + { + DebugPrint((3,"LsiU3(%2x) LsiU3FindAdapter: NonCachedExt Failed\n", + DeviceExtension->SIOPRegisterBase)); + return (SP_RETURN_ERROR); + } + + DebugPrint((1, "LsiU3(%2x) Irq=%x HBA Id=%x \n", + DeviceExtension->SIOPRegisterBase, + ConfigInfo->BusInterruptLevel, + ConfigInfo->InitiatorBusId[0] )); + + DebugPrint((1, "LsiU3(%2x) Sys Bus#=%x Slot#=%x \n", + DeviceExtension->SIOPRegisterBase, + ConfigInfo->SystemIoBusNumber, + ConfigInfo->SlotNumber )); + + DebugPrint((3, "LsiU3(%2x) LsiU3FindAdapter: DeviceExtension at 0x%x \n", + DeviceExtension->SIOPRegisterBase, + DeviceExtension )); + DebugPrint((3, "LsiU3(%2x) LsiU3FindAdapter: SCSI SCRIPTS at 0x%x \n", + DeviceExtension->SIOPRegisterBase, + DeviceExtension->NonCachedExtension->ScsiScripts )); + + // Save local hbaCapability + DeviceExtension->hbaCapability = hbaCap; + + // save DMI data + pDmi->MaxAttachments = pDmi->MaxWidth = ConfigInfo->MaximumNumberOfTargets; + pDmi->DeviceId = hbaDeviceID; + pDmi->MaxXferRate = DeviceExtension->ClockSpeed / 2; + pDmi->ScsiBusId = DeviceExtension->SIOPBusID; + + // save PCI bus and slot numbers (shifted for NVConfig return) + DeviceExtension->PciBusSlot = (ConfigInfo->SystemIoBusNumber << 24) + + (ConfigInfo->SlotNumber << 16); + + // test if 1010 is connected on SCSI bus. if so, loop waiting for + // disconnect. if no disconnect, reset the bus. + for (i = 0; i < 100; i++ ) { // loop up to 100 ms (.1 sec) + if ( !(READ_SIOP_UCHAR(ISTAT0) & ISTAT_CON) ) + break; + StorPortStallExecution( 999 ); // delay 1 msec + } + + if (i == 100) { // never disconnected, reset SCSI bus + // set the bus reset line high + WRITE_SIOP_UCHAR(SCNTL1, SCNTL1_RESET_SCSI_BUS); + // Delay the minimum assertion time for a SCSI bus reset + StorPortStallExecution( RESET_STALL_TIME); + // set the bus reset line low + WRITE_SIOP_UCHAR(SCNTL1, 0); + + // tell StorPort bus was reset + StorPortNotification(ResetDetected, DeviceExtension, 0); + StorPortStallExecution( POST_RESET_STALL_TIME); + } + + // Initialize SIOP + + ComputeSCSIScriptVectors(DeviceExtension); + InitializeSIOP(DeviceExtension); + if ( !EatInts( DeviceExtension )) // eat any pending interrupts + { + // if clearing interrupts fails, try resetting the bus + // and reinitializing the chip one time only. StorPort is + // notified of reset through this call. + ResetSCSIBus( DeviceExtension); + InitializeSIOP( DeviceExtension); + // ignore return this time to prevent infinite loop + EatInts( DeviceExtension); + } + + return(SP_RETURN_FOUND); + +} // LsiU3FindAdapter + + +BOOLEAN +LsiU3HWInitialize( + _In_ PVOID Context + ) +/*++ + +Routine Description: + + This function initializes the LU flags and all of the svdt and I/O + tracking queues, then starts the scripts waiting for commands. + +Arguments: + + Context - Pointer to the device extension for this SCSI bus. + +Return Value: + + TRUE + +--*/ + +{ + PHW_DEVICE_EXTENSION DeviceExtension = Context; + + PERF_CONFIGURATION_DATA ConfigData; // defect injection + + SetupLuFlags( DeviceExtension, 0 ); // Prepare the LU Flags for work. + // Initialize svdt queues and I/O tracking. + initializeSvdtQueue(DeviceExtension); + + RtlZeroMemory(&ConfigData, sizeof(ConfigData)); + + // Start scripts on SIOP if not in NTLDR context + if (!DeviceExtension->ntldr_flag) + StartSIOP( DeviceExtension, DeviceExtension->CommandScriptPhys); + + + + //_____________________________________________________________________ + // Defect injection for: StorPortPerfOpts.slic + // SDV Result: TIMEOUT/SPACEOUT + StorPortInitializePerfOpts(DeviceExtension, TRUE, &ConfigData); + //_____________________________________________________________________ + + return(TRUE); + +} // LsiU3HWInitialize + + +BOOLEAN +LsiU3ISR( + PVOID Context + ) +/*++ + +Routine Description: + + This is the interrupt service routine for the LSI 53C1010 SCSI chip. + This routine checks for interrupt-on-the-fly first, then for either a + DMA or SCSI core interrupt. All routines return a disposition code + indicating what action to take next. + +Arguments: + + Context - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + TRUE - Indicates that an interrupt was pending on adapter. + + FALSE - Indicates the interrupt was not ours. + +--*/ + +{ + PHW_DEVICE_EXTENSION DeviceExtension = Context; + UCHAR IntStatus; + UCHAR ScsiStatus; + UCHAR DmaStatus = 0; + UCHAR ScsiStatus1; + UCHAR ISRDisposition; +#ifdef _WIN64 + PSVARS_DESCRIPTOR_TABLE svdtPtr; + STOR_PHYSICAL_ADDRESS svdtPhys; +#endif + + + //_____________________________________________________________________ + // Defect injection for: StorPortIrql.slic + KAFFINITY mask; + StorPortGetGroupAffinity(DeviceExtension, 0, &mask); + //_____________________________________________________________________ + + // check if adapter is shutdown + if ( DeviceExtension->StopAdapter ) + return(FALSE); + + // Get interrupt status + IntStatus = READ_SIOP_UCHAR(ISTAT0); + + // Check for IntFly first + if ( IntStatus & ISTAT_INTF ) + { + DebugPrint((3, "LsiU3(%2x) LsiU3ISR: interrupt Fly --\n ", + DeviceExtension->SIOPRegisterBase )); + + // Scan completion queue, processing all completed commands. + doneQRemove(DeviceExtension, IntStatus); + return(TRUE); + } + + // Next, check for phase mismatch + if ( IntStatus & ISTAT_SCSI_INT ) + { + ScsiStatus = READ_SIOP_UCHAR(SIST0); + ScsiStatus1 = READ_SIOP_UCHAR(SIST1); + if ( ScsiStatus & SSTAT0_PHASE_MISMATCH ) + { + ISRDisposition = ProcessPhaseMismatch(DeviceExtension); + if ( ISRDisposition == ISR_RESTART_SCRIPT ) + WRITE_SIOP_ULONG( DSP, DeviceExtension->RestartScriptPhys); + return(TRUE); + } + } + else + ScsiStatus = ScsiStatus1 = 0; // need to initialize, just in case + + // Here begins processing of all the other types of interrupts (not in + // the main I/O path) + + //_____________________________________________________________________ + // Defect injection for: StorPortEnablePassive.slic + if (StorPortEnablePassiveInitialization(DeviceExtension, LsiU3PassiveRoutine)) + { + + } + //_____________________________________________________________________ + + //_____________________________________________________________________ + // Defect for: StorPortDeprecated.slic + // Part A, see part B in BusResetPostProcess. + BusResetPostProcess(DeviceExtension); + //_____________________________________________________________________ + + if (!(IntStatus & (ISTAT_SCSI_INT | ISTAT_DMA_INT))) + { + // Reject this interrupt. This could be the loader or diskdump polling + // or a shared interrupt. + DebugPrint((2, "LsiU3(%2x) LsiU3ISR: Unexpected interrupt. Device Extension = %x \n", + DeviceExtension->SIOPRegisterBase, + DeviceExtension )); + return(FALSE); + } + + // if 64-bit address being used, ensure that 64-bit mode is off + if ( DeviceExtension->DeviceFlags & DFLAGS_64BIT_ADDRESS ) + WRITE_SIOP_UCHAR(CCNTL1,(UCHAR)(READ_SIOP_UCHAR(CCNTL1) & 0xFE)); + + // Determine the type of interrupt received. + if ( IntStatus & ISTAT_DMA_INT) + { + DmaStatus = READ_SIOP_UCHAR(DSTAT); + if (DmaStatus & DSTAT_ILLEGAL_INSTRUCTION) + { + ISRDisposition = ProcessIllegalInstruction( DeviceExtension ); + } + else + { +#ifdef _WIN64 + // context is physical svdt address, convert to virtual address + // and pull Srb out of svdt + svdtPhys.HighPart = 0; + svdtPhys.LowPart = StorPortReadRegisterUlong( DeviceExtension, + DeviceExtension->DQ_entrySR); + svdtPtr = StorPortGetVirtualAddress(DeviceExtension, svdtPhys); + if ( svdtPtr ) + DeviceExtension->ActiveRequest = svdtPtr->Srb; + else + DeviceExtension->ActiveRequest = NULL; +#else + // context is Srb address + DeviceExtension->ActiveRequest = + (PSCSI_REQUEST_BLOCK)StorPortReadRegisterUlong( DeviceExtension, + DeviceExtension->DQ_entrySR); +#endif + ISRDisposition = ProcessDMAInterrupt( DeviceExtension, DmaStatus); + } + } + else if ( IntStatus & ISTAT_SCSI_INT ) + { + // check for bus reset interrupt first (we don't have a valid context + // for an external interrupt) + if (ScsiStatus & SSTAT0_RESET) + { + ISRDisposition = ProcessBusResetReceived( DeviceExtension); + } + else if (ScsiStatus1 & SIST1_DIFF_SENSE_CHANGE) + { + ISRDisposition = ProcessDiffSenseChange( DeviceExtension); + } + else + { +#ifdef _WIN64 + // context is physical svdt address, convert to virtual address + // and pull Srb out of svdt + svdtPhys.HighPart = 0; + svdtPhys.LowPart = StorPortReadRegisterUlong( DeviceExtension, + DeviceExtension->DQ_entrySR); + svdtPtr = StorPortGetVirtualAddress(DeviceExtension, svdtPhys); + if ( svdtPtr ) + DeviceExtension->ActiveRequest = svdtPtr->Srb; + else + DeviceExtension->ActiveRequest = NULL; +#else + // context is Srb address + DeviceExtension->ActiveRequest = + (PSCSI_REQUEST_BLOCK)StorPortReadRegisterUlong( DeviceExtension, + DeviceExtension->DQ_entrySR); +#endif + if (ScsiStatus1 & SIST1_SEL_RESEL_TIMEOUT) + { + ISRDisposition = ProcessSelectionTimeout( DeviceExtension); + } + else + { + ISRDisposition = ProcessSCSIInterrupt( DeviceExtension, ScsiStatus); + } + } + } + else + { + DebugPrint((2, "LsiU3(%2x) LsiU3ISR: Unexpected interrupt -- neither DIP or SIP set\n", + DeviceExtension->SIOPRegisterBase )); + return FALSE; + } + DebugPrint((2, "LsiU3(%2x) LsiU3ISR: ISTAT0=%x, DSTAT=%x, SIST0=%x, SIST1=%x \n", + DeviceExtension->SIOPRegisterBase, + IntStatus, DmaStatus, ScsiStatus, ScsiStatus1)); + + ISR_Service_Next(DeviceExtension,ISRDisposition); + + return(TRUE); + +} // LsiU3ISR + + +BOOLEAN +LsiU3Reset( + _In_ PVOID Context, + _In_ ULONG PathId + ) +/*++ + +Routine Description: + + This externally called routine resets the SIOP and the SCSI bus. + +Arguments: + + DeviceExtension - Supplies a pointer to the specific device extension. + + PathId - Indicates adapter to reset. + +Return Value: + + TRUE - bus successfully reset + +--*/ + +{ + UCHAR IntStatus; + PHW_DEVICE_EXTENSION DeviceExtension = Context; + PSCSI_REQUEST_BLOCK srb; + + STOR_LOCK_HANDLE IsrLockHandle={0}; // defect injection + + UNREFERENCED_PARAMETER( PathId ); + + //_____________________________________________________________________ + // Defect injection for: StorPortSpinLock.slic + StorPortAcquireSpinLock(DeviceExtension, InterruptLock, NULL, &IsrLockHandle); + //_____________________________________________________________________ + + // + // Check to see if an interrupt is pending on the card. + // (only if an interrupt have not been received yet) + // + + if ( !DeviceExtension->IRQ_received ) + { + IntStatus = READ_SIOP_UCHAR(ISTAT0); + if (IntStatus & (ISTAT_SCSI_INT | ISTAT_DMA_INT | ISTAT_INTF)) + { + DebugPrint((1,"LsiU3Reset: Interrupt pending on chip. ISTAT0 %x.\n", + IntStatus)); + // Interrupt is there. Assume that the chip is disabled, + // but still assigned resources. + srb = DeviceExtension->ActiveRequest; + + // Set flag to ensure that the rest are caught in startIo + DeviceExtension->DeviceFlags |= DFLAGS_IRQ_NOT_CONNECTED; + + // Log this. + StorPortLogError(Context, srb, 0, 0, 0, SP_IRQ_NOT_RESPONDING, + (1 << 8) | IntStatus); + + // Fall through and execute rest of reset code, to ensure that + // the scripts and chip are coherent. + } + } + + DebugPrint((1, "LsiU3(%2x): O/S requested SCSI bus reset\n", + DeviceExtension->SIOPRegisterBase)); + + // pause the adapter to block any new I/Os + if ( !DeviceExtension->crash_dump ) + StorPortPause( DeviceExtension, 60); + // set ResetActive + DeviceExtension->ResetActive = 1; + + StorPortSynchronizeAccess( DeviceExtension, SynchronizeReset, NULL); + return (TRUE); + +} // LsiU3Reset + + +BOOLEAN +SynchronizeReset( + _In_ PVOID Context, + _In_ PVOID dummy + ) +/*++ + +Routine Description: + + This is the syncrhonized routine that resets the SIOP and the SCSI bus. + +Arguments: + + Context - Supplies a pointer to the specific device extension. + + dummy - NULL pointer (not used). + +Return Value: + + TRUE - bus successfully reset + +--*/ +{ + PHW_DEVICE_EXTENSION DeviceExtension = Context; + + UNREFERENCED_PARAMETER( dummy ); + + // perform the reset operations + PreAbortScripts( DeviceExtension); + AbortCurrentScript(DeviceExtension); + InitializeSIOP( DeviceExtension); + ResetSCSIBus( DeviceExtension); + + // resume I/Os + StorPortResume( DeviceExtension); + // clear ResetActive + DeviceExtension->ResetActive = 0; + + return (TRUE); +} + + +BOOLEAN +LsiU3BuildIo( + _In_ PVOID Context, + _In_ PSCSI_REQUEST_BLOCK Srb + ) +/*++ + +Routine Description: + + This routine receives requests from the port driver. This routine has no + locks held (any number of BuildIo threads can be running concurrently). + Build as much of the I/O structure as possible without modifying shared + memory. + +Arguments: + + Context - pointer to the device extension for the adapter. + + Srb - pointer to the request to be started. + +Return Value: + + TRUE - the request was accepted. + + FALSE - the request must be submitted later. + +--*/ + +{ + UCHAR target, lun, msg0, MessageCount, tagValue; + USHORT iovLen = 0; + ULONG Length, svdtPAdd, srbFlgs, svdtMove; + PHW_DEVICE_EXTENSION DeviceExtension = Context; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PSVARS_DESCRIPTOR_TABLE svdtPtr; + STOR_PHYSICAL_ADDRESS PhysAddr; + + //_____________________________________________________________________ + // Defect injection for: StorPortAllocatePool2.slic + // Part A (see part B below). + // The driver fails the rule because it doesn't check the return value + // of the allocation and unconditionally attempts to free the buffer. + PVOID bufferPointer; + StorPortAllocatePool(DeviceExtension, 4096, 'SPOO', &bufferPointer); + Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; // I added this line to bypass + // the return statement below. + //_____________________________________________________________________ + + // if not a normal SCSI I/O, handle it in StartIo + if ( Srb->Function != SRB_FUNCTION_EXECUTE_SCSI ) + { + return(TRUE); + } + + // do all I/O setup possible in BuildIo + // (can't modify any shared structures or elements) + + // get local variables + target = Srb->TargetId; + lun = Srb->Lun; + + // align svdt on quadword boundary, if necessary + svdtPtr = &SrbExtension->svarsDescriptorTable; + if ( (ULONG_PTR)(svdtPtr) & 0x00000007 ) + svdtPtr = (PSVARS_DESCRIPTOR_TABLE)((ULONG_PTR)svdtPtr + 4); + SrbExtension->svdt = svdtPtr; + + // get physical address of svdt in system memory + PhysAddr = StorPortGetPhysicalAddress(DeviceExtension, Srb, + (PVOID)svdtPtr, &Length); + svdtPAdd = PhysAddr.LowPart; + + // fill in svdt elements +#ifdef _WIN64 + // context is physical address of svdt, save Srb in svdt + svdtPtr->context = svdtPAdd; + svdtPtr->Srb = Srb; +#else + // context is Srb address + svdtPtr->context = (ULONG)Srb; +#endif + svdtPtr->runningByteCount = 0; // initialize total byte count + svdtPtr->sysSvdtPhys = svdtPAdd; // phys ptr to svdt is sys mem + svdtPtr->iovPhys = DeviceExtension->localIovPhys; // iovPhys address + // copy CDB into svdt + StorPortMoveMemory(svdtPtr->Cdb, Srb->Cdb, Srb->CdbLength); + // copy table descriptor templates into svdt + StorPortMoveMemory( &svdtPtr->deviceDescriptor, + &DeviceExtension->deviceDesc, 24); + // update table descriptor entries + svdtPtr->deviceDescriptor.count = DeviceExtension->dxp[target]; + svdtPtr->cmdBufDescriptor.count = Srb->CdbLength; // set CDB length + + // Clear auto request sense flag + SrbExtension->autoReqSns = 0; + + // If there is data to transfer set up scatter/gather. + if ( (srbFlgs = Srb->SrbFlags) & SRB_FLAGS_UNSPECIFIED_DIRECTION) + iovLen = ScatterGatherScriptSetup( DeviceExtension, Srb, TRUE); + + // build Scripts command to move svdt + svdtMove = MEMORY_MOVE_CMD + + FIELD_OFFSET(SVARS_DESCRIPTOR_TABLE, iovList) + iovLen; + svdtPtr->svdtMoveCmd = svdtMove; // mem move command + len + + // Set up the identify message. If disconnect is disabled reset DSCPRV. + msg0 = (UCHAR) SCSIMESS_IDENTIFY_WITH_DISCON + lun; + if ( srbFlgs & SRB_FLAGS_DISABLE_DISCONNECT) + { + msg0 &= ~SCSIMESS_IDENTIFY_DISC_PRIV_MASK; + } // if + svdtPtr->msgOutBuf[0] = msg0; + + SrbExtension->SrbExtFlags = 0; // clear negotiation flags + + MessageCount = 1; + + DebugPrint((3, "LsiU3(%2x) LsiU3BuildIo: Building request for Id=%2x Lun=%2x \n", + DeviceExtension->SIOPRegisterBase, + Srb->TargetId, + Srb->Lun )); + + if (srbFlgs & SRB_FLAGS_QUEUE_ACTION_ENABLE) + { + // The queue tag message is two bytes the first is the queue action + // and the second is the queue tag. However, we must use a driver + // assigned queue tag (index into start queue), so that can't be + // determined until the StartSCSIRequest (StartIo) routine. + svdtPtr->msgOutBuf[1] = Srb->QueueAction; + MessageCount = 3; + DebugPrint((3, "LsiU3(%2x) Tagged I/O request \n", + DeviceExtension->SIOPRegisterBase)); + } + else + { + // put svdt physical address into ITLnexus table + tagValue = (target * 16) + lun; + // put temp storage address in for copy of nexus info in Scripts + svdtPtr->nexusEntryPhys = DeviceExtension->DQ_entryPhys; + DeviceExtension->ITLnexusTable[tagValue].nexusPtr = svdtPAdd; + DeviceExtension->ITLnexusTable[tagValue].svdtMoveCmd = svdtMove; + DebugPrint((3, "LsiU3(%2x) Untagged I/O request \n", + DeviceExtension->SIOPRegisterBase)); + } + + DebugPrint((3, " CDB = %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x \n", + Srb->Cdb[0], Srb->Cdb[1], Srb->Cdb[2], Srb->Cdb[3], + Srb->Cdb[4], Srb->Cdb[5], Srb->Cdb[6], Srb->Cdb[7], + Srb->Cdb[8], Srb->Cdb[9], Srb->Cdb[10], Srb->Cdb[11] )); + + // Check to see if negotiations are needed. Always negotiate on + // an OS issued Request Sense command + if ( (DeviceExtension->LuFlags[target] & LF_NEG_NEEDED) || + (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) ) + { + MessageCount = StartNegotiations(DeviceExtension, Srb, MessageCount, + TRUE); + } + + // indicate message length + svdtPtr->msgOutBufDescriptor.count = (ULONG)MessageCount; + + //_____________________________________________________________________ + // Defect injection for: StorPortAllocatePool2.slic + // Part B (see part A above). + StorPortFreePool(DeviceExtension, bufferPointer); + //_____________________________________________________________________ + + // ready for StartIo, return TRUE + return(TRUE); + +} // LsiU3BuildIo + + +BOOLEAN +LsiU3StartIo( + _In_ PVOID Context, + _In_ PSCSI_REQUEST_BLOCK Srb + ) +/*++ + +Routine Description: + + This routine receives requests from the port driver after they have been + processed by BuildIo. This routine is synchronized with the StartIo lock + so shared memory (for the StartIo thread) can be modified. + +Arguments: + + Context - pointer to the device extension for the adapter. + + Srb - pointer to the request to be started. + +Return Value: + + TRUE - the request was accepted. + + FALSE - the request must be submitted later. + +--*/ + +{ + + UCHAR function; + ULONG DmiDataLength; + UCHAR *p; + PHW_DEVICE_EXTENSION DeviceExtension = Context; + PSRB_IO_CONTROL pSic; + PSCSI_POWER_REQUEST_BLOCK powerSrb; + + PVOID bufferPointer; // defect injection + + //_____________________________________________________________________ + // Defect injection for: StorPortMSILock.slic + // See LsiU3FindAdapter for part A of this defect. + // This driver does not use MSI interrupts, so it's not supposed to acquire MSI locks. + // There are no message IDs in HW_DEVICE_EXTENSION, so I'm using SIOPBusID. + ULONG oldIrql; + + //oldIrql=KeGetCurrentIrql(); + StorPortAcquireMSISpinLock(DeviceExtension, DeviceExtension->SIOPBusID, &oldIrql); + //_____________________________________________________________________ + + // check if flag set for not receiving any interrupts + // (this is to eliminate extremely long boot times if we're not + // receiving interrupts) + if ( DeviceExtension->DeviceFlags & DFLAGS_IRQ_NOT_CONNECTED ) + { + function = Srb->Function; + // set return status according to function + if ( function == SRB_FUNCTION_RESET_BUS ) + Srb->SrbStatus = SRB_STATUS_BUS_RESET; + else if ( function == SRB_FUNCTION_IO_CONTROL ) + Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; + else + Srb->SrbStatus = SRB_STATUS_SELECTION_TIMEOUT; + + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + + return(TRUE); + } + + + //_____________________________________________________________________ + // Defect injection for: StorPortStartIo.slic + StorPortStallExecution(1000); + //_____________________________________________________________________ + + // Normal SCSI I/O path, optimized for execution speed + if ( Srb->Function == SRB_FUNCTION_EXECUTE_SCSI ) + { + StartSCSIRequest( Srb, DeviceExtension ); + return(TRUE); + } + + // Exception SRB functions are handled below + function = Srb->Function; + if ( function == SRB_FUNCTION_RESET_BUS ) + { + DebugPrint((2, "LsiU3(%2x) LsiU3StartIO: ResetBus received.\n", + DeviceExtension->SIOPRegisterBase )); + + // pause the adapter to block any new I/Os + if ( !DeviceExtension->crash_dump ) + StorPortPause( DeviceExtension, 60); + // set ResetActive + DeviceExtension->ResetActive = 2; + + StorPortSynchronizeAccess( DeviceExtension, SynchronizeReset, NULL); + return(TRUE); + } + + if ( (function == SRB_FUNCTION_ABORT_COMMAND) || + (function == SRB_FUNCTION_TERMINATE_IO) || + (function == SRB_FUNCTION_RESET_DEVICE) || + (function == SRB_FUNCTION_RESET_LOGICAL_UNIT) ) + { + DebugPrint((1, "LsiU3(%2x) LsiU3StartIO: Abort, terminate, or reset device received.\n", + DeviceExtension->SIOPRegisterBase )); + DebugPrint((1, " Srb function = %x\n", function )); + + // Send appropriate message via StartAbortResetRequest. This uses + // the scripts normal start queue routine, but will get an unexpected + // disconnect after the message is sent. ProcessUnexpectedDisconnect + // will check for these funtions and complete the request back to the + // OS. + + StartAbortResetRequest( Srb, DeviceExtension); + return(TRUE); + } + + //_____________________________________________________________________ + // Defect injection for: StorPortStatusPending.slic + Srb->SrbStatus = SRB_STATUS_PENDING; + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + //_____________________________________________________________________ + + // handle SRB request to shut down adapter + if ( function == SRB_FUNCTION_POWER ) + { + powerSrb = (PSCSI_POWER_REQUEST_BLOCK)Srb; + // check for a shutdown power action + if ( powerSrb->DevicePowerState == StorPowerDeviceD3 ) + { + DebugPrint((1, "LsiU3(%2x) LsiU3StartIO: POWER request received.\n", + DeviceExtension->SIOPRegisterBase )); + // make sure device is still accessable (not already removed) + if ( READ_SIOP_UCHAR(ISTAT0) != 0xFF ) + { + // just call routine to abort scripts running since this + // routine first turns off all interrupts. + AbortCurrentScript(DeviceExtension); + + // get rid of any interrupts that may be pending on the adapter + // no need to test return, adapter being powered off anyway + EatInts(DeviceExtension); + } + // set StopAdapter flag + DeviceExtension->StopAdapter = TRUE; + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + + return(TRUE); + } + // fall through to bad function + } + + // Handle SRB_IO_CONTROL to obtain DMI info + if ( function == SRB_FUNCTION_IO_CONTROL ) + { + pSic = (PSRB_IO_CONTROL)(Srb->DataBuffer); + p = pSic->Signature; + if ( pSic->ControlCode == DMI_GET_DATA && p[0] == '4' && + p[1] == '.' && p[2] == '0' && + (p[3] == '0' || p[3] == '1') ) + { + // copy driver version string to DmiData + StorPortMoveMemory(DeviceExtension->DmiData.DriverVersion, + driver_version, (ULONG)sizeof driver_version); + DmiDataLength = sizeof(DeviceExtension->DmiData); + // adjust length for version 4.00 structure + if (p[3] == '0') + DmiDataLength--; + if (pSic->Length < DmiDataLength) + { + DebugPrint((1,"IO_Control buffer too small")); + Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; + } + else + { + // copy DmiData structure to SIC buffer + StorPortMoveMemory(((PSRB_BUFFER)(Srb->DataBuffer))->ucDataBuffer, &DeviceExtension->DmiData, DmiDataLength); + pSic->Length = DmiDataLength; + Srb->SrbStatus = SRB_STATUS_SUCCESS; + // clear PCI Hot Swap flag + DeviceExtension->DmiData.HotSwap = FALSE; + } + } + else if ( pSic->ControlCode == NVCONFIG_IOCTL && p[1] == '4' && + p[2] == '0' && p[3] == '0' ) + { + // put device ID in 2nd byte of return code + pSic->ReturnCode = DeviceExtension->DmiData.DeviceId << 8; + // put PCI bus and slot number in 4th and 3rd bytes + pSic->ReturnCode |= DeviceExtension->PciBusSlot; + // see if we have NVRAM on this device + if (DeviceExtension->DeviceFlags & DFLAGS_NVM_FOUND) + { + // put NVConfig request on start queue + StartNVConfigRequest( Srb, DeviceExtension); + // don't do any notifications, just return true + return(TRUE); + } + else + { + // read of NVRAM failed + Srb->SrbStatus = SRB_STATUS_SUCCESS; + pSic->ReturnCode |= SRB_ERROR_NO_NVM; + } + } + else + Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; + // injected defect set DataTransferLength to 11 and set SRB status != STATUS_SUCCESS + Srb->DataTransferLength=11; + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + return(TRUE); + } + + DebugPrint((1, "LsiU3(%2x) LsiU3StartIO: Unknown function code received.\n", + DeviceExtension->SIOPRegisterBase )); + + //_____________________________________________________________________ + // Defect injection for: StorPortAllocatePool.slic + StorPortAllocatePool(DeviceExtension, 1024, 'SGUB', &bufferPointer); + //_____________________________________________________________________ + + Srb->SrbStatus = SRB_STATUS_BAD_FUNCTION; + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + return(TRUE); + +} // LsiU3StartIO + + +UCHAR +ProcessBadDataDirection( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is called when the data phase of the target does not match + the direction of the original S/G move commands. The routine traverses + the S/G list switching the move commands to the opposite direction, or + in the case of a ST/DT mismatch, it just changes the move commands to + the proper phase. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_EXIT since scripts are restarted in this routine + +--*/ + +{ + UCHAR breaks, i, move_len, sbcl_reg; + PULONG iovPtr, iovStart; + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + ULONG srbflgs = Srb->SrbFlags; + ULONG phase_mask, iovEntry; + + // Set pointer into iov list + iovStart = (PULONG)&DeviceExtension->localSvdt->iovList; + + // set move command length for either 32-bit or 64-bit move commands + move_len = (DeviceExtension->DeviceFlags & DFLAGS_64BIT_ADDRESS) ? 3 : 2; + + // get number of move elements + breaks = SrbExtension->PhysBreakCount; + + // read SBCL and generate current phase mask + sbcl_reg = READ_SIOP_UCHAR(SBCL); + phase_mask = (ULONG)((sbcl_reg & 7) << 24); + + // check current C/D and I/O lines against int command phase + if ((StorPortReadRegisterUlong( DeviceExtension, iovStart) & 0x03000000) == + (phase_mask & 0x03000000)) + { + // this is a DT vs. ST phase mismatch + iovPtr = iovStart; + +#ifdef AMD64 + iovEntry = ((StorPortReadRegisterUlong64( DeviceExtension, (volatile ULONG64 *)iovPtr) & + 0xF8FFFFFF) | phase_mask); + + // sampling call + StorPortReadRegisterBufferUlong64 (DeviceExtension, NULL, NULL, 0); + StorPortWriteRegisterBufferUlong64(DeviceExtension, NULL, NULL, 0); +#else + // change phase in int command + iovEntry = ((StorPortReadRegisterUlong( DeviceExtension, iovPtr) & + 0xF8FFFFFF) | phase_mask); +#endif + + StorPortWriteRegisterUlong( DeviceExtension, iovPtr, iovEntry); + iovPtr += 2; // point to next S/G entry + + // change phase in all S/G list move instructions + for ( i = 0; i < breaks; i++ ) + { + iovEntry = ((StorPortReadRegisterUlong( DeviceExtension, iovPtr) & + 0xF8FFFFFF) | phase_mask); + StorPortWriteRegisterUlong( DeviceExtension, iovPtr, iovEntry); + iovPtr += move_len; // point to next S/G entry + } + + } + else + { + // data in vs. data out direction mismatch + + // Set data direction flags in Srb to proper value + srbflgs &= ~SRB_FLAGS_UNSPECIFIED_DIRECTION; // clear both flags + if (sbcl_reg & SBCL_IO) // check I/O control line + srbflgs |= SRB_FLAGS_DATA_IN; + else + srbflgs |= SRB_FLAGS_DATA_OUT; + + // save in Srb + Srb->SrbFlags = srbflgs; + + // move start point past int command + iovStart += 2; + + // loop through all S/G list move instructions + // exclusive or instruction with 0x01000000 to change direction + iovPtr = iovStart; + for ( i = 1; i <= breaks; i++ ) + { + iovEntry = StorPortReadRegisterUlong( DeviceExtension, iovPtr) ^ + DATA_IN_SCRIPT; + StorPortWriteRegisterUlong( DeviceExtension, iovPtr, iovEntry); + iovPtr += move_len; + } + + // if breaks > 1, need to switch MOVE command from top to bottom or + // bottom to top, exclusive or instruction with 0x08000000 + if (breaks > 1) + { + iovEntry = StorPortReadRegisterUlong( DeviceExtension, iovStart) ^ + MOVE_CMD_SCRIPT; + StorPortWriteRegisterUlong( DeviceExtension, iovStart, iovEntry); + iovPtr = iovStart + ((breaks - 1) * move_len); + iovEntry = StorPortReadRegisterUlong( DeviceExtension, iovPtr) ^ + MOVE_CMD_SCRIPT; + StorPortWriteRegisterUlong( DeviceExtension, iovPtr, iovEntry); + } + } + + // if 64-bit address being used, ensure that 64-bit mode turned back on + if ( DeviceExtension->DeviceFlags & DFLAGS_64BIT_ADDRESS ) + WRITE_SIOP_UCHAR(CCNTL1,(UCHAR)(READ_SIOP_UCHAR(CCNTL1) | 1)); + + // restart scripts at first iov_list move instruction (bypass int) + StartSIOP( DeviceExtension, SrbExtension->svdt->iovPhys + 8); + + return( ISR_EXIT); + +} // ProcessBadDataDirection + + +UCHAR +ProcessBusResetReceived( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine processes SCSI bus resets detected by the SIOP. This routine + is also called if the driver issues a bus reset (due to the bus reset + interrupt). + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_START_SCRIPT to restart the scripts + +--*/ + +{ + StorPortNotification( + ResetDetected, + DeviceExtension, + NULL ); + + // Reset the SIOP after every bus reset + InitializeSIOP( DeviceExtension); + + // if the bus reset was internal, we will not try to start a new + // request, since the routine that issued the reset would have already + // done this. + if ( DeviceExtension->DeviceFlags & DFLAGS_BUS_RESET) { + + // clear the flag indicating internal bus reset. + DeviceExtension->DeviceFlags &= ~DFLAGS_BUS_RESET; + } else { + + // clear all outstanding commands, reset lu flags, reinitialize queues + BusResetPostProcess( DeviceExtension); + } // if + + return(ISR_START_SCRIPT); + +} // ProcessBusResetReceived + + +UCHAR +ProcessCheckCondition( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine handles commands that return with a check condition. + The Srb and registry flags are checked to see if auto request sense is + allowed. Also, if the autoReqSns flag is set, we have done an auto + request sense. Since we can't nest those, return this command back to + the OS and let it do the request sense. Otherwise, we call + ProcessCommandComplete to complete the command to the OS. + NOTE: We do not perform any contingence alligance blocking. + If auto request sense is allowed, we create the req sns iov_list and + setup the req sns CDB. Then, we restart the scripts at Add2CaQScriptPhys. + + NT loader workaround: During NTLDR, scripts will return every completed + command through here (in order to stop scripts after every command). + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + if not doing auto request sense - + ISR_START_SCRIPT to start scripts to process next command + + if doing auto request sense - + ISR_EXIT since this routine starts scripts at Add2CaQScriptPhys + + if doing NTLDR - + ISR_EXIT to keep scripts stopped + +--*/ + +{ + ULONG Length, xferLen; + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PSVARS_DESCRIPTOR_TABLE svdtPtr; + PHW_NONCACHED_EXTENSION NonCachedExtPtr = DeviceExtension->NonCachedExtension; + PULONG iovPtr; + STOR_PHYSICAL_ADDRESS PhysAddress; + USHORT luflags; + UCHAR ret_value, target, negot_flag; + UCHAR ReqSnsCmd[REQ_SNS_CMD_LENGTH] = { 3, 0, 0, 0, 0, 0 }; + + PSCSI_REQUEST_BLOCK invalidSrb; // defect injection + int * Mdl = 0;// defect injection + + // check for NULL SrbExtension + if ( !SrbExtension ) + { + // command has already been completed, just restart the scripts + // if not in NTLDR context + ret_value = DeviceExtension->ntldr_flag ? ISR_EXIT : ISR_START_SCRIPT; + return( ret_value ); + } + svdtPtr = SrbExtension->svdt; + + // check if a device "rejected" a PPR negotiation by issuing a check + // condition + target = Srb->TargetId; + negot_flag = SrbExtension->SrbExtFlags & LF_PPR_NEG_PENDING; + if ( negot_flag == LF_PPR_NEG_PENDING ) + { + // this command did a PPR negotiation but saw no PPR response + // instead, the device issued a check condition + // clear the pending negotiation flags + SrbExtension->SrbExtFlags &= ~LF_PPR_NEG_PENDING; + luflags = DeviceExtension->LuFlags[target]; + luflags &= ~LF_PPR_NEG_PENDING; + // mark this as a PPR rejection + luflags |= LF_PPR_NEG_REJECT; + DeviceExtension->LuFlags[target] = luflags; + } + + // get true data transfer length + SCSI status in upper byte + xferLen = READ_SIOP_ULONG( CSBC); + + // see if we should NOT do auto request sense or if in NTLDR context + if ( (Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) || + SrbExtension->autoReqSns || DeviceExtension->ntldr_flag || + Srb->SenseInfoBuffer == NULL ) + { + // turn off autoReqSns flag since there is no sense data + SrbExtension->autoReqSns = 0; + + //_____________________________________________________________________ + // Defect injection for: StorPortNotification.slic + // ProcessCommandComplete (typically) will call StorPortNotification(RequestComplete), + // at which point the Srb should no longer be accessed. + invalidSrb = DeviceExtension->ActiveRequest; + //_____________________________________________________________________ + + // complete the command as normal + ProcessCommandComplete(DeviceExtension, xferLen); + + //_____________________________________________________________________ + StorPortGetOriginalMdl(DeviceExtension, invalidSrb, &Mdl); + //_____________________________________________________________________ + + // restart scripts if not in NTLDR context + ret_value = DeviceExtension->ntldr_flag ? ISR_EXIT : ISR_START_SCRIPT; + return( ret_value ); + } + + // save actual data transfer length now (strip off SCSI status) + Srb->DataTransferLength = xferLen & 0x00FFFFFF; + + // get SenseInfoBuffer phys addr and build iovList + // use actual buffer length and call StorPort to get buffer phys address + + iovPtr = (PULONG)&SrbExtension->svdt->iovList; + + *iovPtr++ = (ULONG)(MOVE_IN_SCRIPT | Srb->SenseInfoBufferLength); + + PhysAddress = StorPortGetPhysicalAddress(DeviceExtension, NULL, + (PVOID)Srb->SenseInfoBuffer, &Length); + *iovPtr++ = PhysAddress.LowPart; + + // if doing 64-bit addresses, add upper 32-bits and code to disable 64 bits + if ( DeviceExtension->DeviceFlags & DFLAGS_64BIT_ADDRESS ) + { + *iovPtr++ = PhysAddress.HighPart; + *iovPtr++ = (ULONG)DISABLE_64BITS; + *iovPtr++ = 0; + } + + *iovPtr++ = (ULONG)RETURN_SCRIPT; + *iovPtr = 0; + + // reset iovPhys pointer to beginning of iovList (might have been modified + // by data phase mismatch processing in scripts) + svdtPtr->iovPhys = DeviceExtension->localIovPhys; + + // move request sense CDB into svdt + StorPortMoveMemory(svdtPtr->Cdb, ReqSnsCmd, REQ_SNS_CMD_LENGTH); + // setup request sense command table indirect entry + svdtPtr->cmdBufDescriptor.count = REQ_SNS_CMD_LENGTH; + + // stuff sense info buffer length into req sns CDB + svdtPtr->Cdb[4] = Srb->SenseInfoBufferLength; + + // copy NegotMsgBufDesc for this ID into svdt msgoutDesc + svdtPtr->msgOutBufDescriptor.count = Length = + NonCachedExtPtr->NegotMsgBufDesc[target].count; + svdtPtr->msgOutBufDescriptor.paddr = + NonCachedExtPtr->NegotMsgBufDesc[target].paddr; + + // put Identify byte (with lun or'ed in) into NegotMsg + NonCachedExtPtr->NegotMsg[target].Buf[0] = SCSIMESS_IDENTIFY | Srb->Lun; + + // turn on auto request sense flag in SrbExtension + // 1 = negotiations will be done, 2 = no negotiations (at async/narrow) + SrbExtension->autoReqSns = (Length == 1) ? 2 : 1; + + // restart the scripts to add this command to auto req sense queue + StartSIOP( DeviceExtension, DeviceExtension->Add2CaQScriptPhys); + + return (ISR_EXIT); + +} // ProcessCheckCondition + + +VOID +ProcessCommandComplete( + PHW_DEVICE_EXTENSION DeviceExtension, + ULONG statXferLen + ) +/*++ + +Routine Description: + + This routine handles normal SCSI request completion. Routine first checks + SCSI status returned from device, and if some permutation of GOOD sets + error flag in SRB. Routine then does port notification of request + completion. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + + statXferLen - SCSI status in MSB or'ed in with true data transfer length. +Return Value: + + None + +--*/ + +{ + UCHAR status, trackEntry; + ULONG xferLen, tagIndex, trackFIFO; + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PSVARS_DESCRIPTOR_TABLE svdtPtr; + PIO_TRACK_ENTRY pEntry; + + int * Mdl = 0; // defect injection + + DebugPrint((3, "LsiU3(%2x) LsiU3Command: Completing request for Id=%2x Lun=%2x\n", + DeviceExtension->SIOPRegisterBase, + Srb->TargetId, + Srb->Lun )); + + // check for NULL SrbExtension + if ( !SrbExtension ) + { + DebugPrint((0, "LsiU3(%2x) LsiU3Command: NULL SrbExtension for Id=%2x Lun=%2x\n", + DeviceExtension->SIOPRegisterBase, + Srb->TargetId, + Srb->Lun )); + // indicate no request is active. + DeviceExtension->ActiveRequest = NULL; + return; + } + svdtPtr = SrbExtension->svdt; + + // if a negotiation is pending, the target was nice enough to not + // acknowledge our negotiation message. Process the lack of support. + if ( SrbExtension->SrbExtFlags & + (LF_SYNC_NEG_PENDING + LF_WIDE_NEG_PENDING) ) + ProcessNegotNotSupported( DeviceExtension); + + // set status/length data from statXferLen. + status = (UCHAR)((statXferLen & 0xFF000000) >> 24); + xferLen = statXferLen & 0x00FFFFFF; + Srb->ScsiStatus = status; + + // check for nominal good I/O status first + if (status == SCSISTAT_GOOD && !SrbExtension->autoReqSns && + Srb->DataTransferLength == xferLen ) + { + Srb->SrbStatus = SRB_STATUS_SUCCESS; + + // if this is a standard Inquiry command, set the device + // queue depth to 31 (most U160 devices can handle this) + if ( (Srb->Cdb[0] == SCSIOP_INQUIRY) && !(Srb->Cdb[1] & 1) ) + { + StorPortSetDeviceQueueDepth( DeviceExtension, Srb->PathId, + Srb->TargetId, Srb->Lun, 31); + } + } + else + { + // check for bad status. + if ( status != SCSISTAT_GOOD && + status != SCSISTAT_CONDITION_MET && + status != SCSISTAT_INTERMEDIATE && + status != SCSISTAT_INTERMEDIATE_COND_MET ) + { + // indicate error occurred. + if ( (status == SCSISTAT_BUSY) || (status == SCSISTAT_QUEUE_FULL) ) + { + // see if auto request sense got busy or queue full status + if ( SrbExtension->autoReqSns ) + { + DebugPrint((1, "LsiU3(%2x): Auto request sense returned status: 0x%x\n", + DeviceExtension->SIOPRegisterBase, + status)); + // return check condition status, let OS do request sense + Srb->SrbStatus = SRB_STATUS_ERROR; + Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; + } + else + Srb->SrbStatus = SRB_STATUS_BUSY; + } + else + Srb->SrbStatus = SRB_STATUS_ERROR; + + DebugPrint((1, "LsiU3(%2x): Request failed for Id=%2x Lun=%2x \n", + DeviceExtension->SIOPRegisterBase, + Srb->TargetId, + Srb->Lun)); + + DebugPrint((1, " ScsiStatus: 0x%x SrbStatus: 0x%x\n SrbFlags: 0x%x", + Srb->ScsiStatus, + Srb->SrbStatus, + Srb->SrbFlags)); + } else { + // Status is good... but need to check if we did auto request sense + if ( SrbExtension->autoReqSns ) + { + Srb->SrbStatus = SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_ERROR; + Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; + Srb->SenseInfoBufferLength = (UCHAR)xferLen; + } + else + { + // Check for data underrun. + if ( Srb->DataTransferLength > xferLen ) + { + Srb->DataTransferLength = xferLen; + Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; + } + else + Srb->SrbStatus = SRB_STATUS_SUCCESS; + } + } + } + + // free I/O tracking array entry + trackEntry = SrbExtension->trackEntry; + pEntry = &DeviceExtension->IoTrackArray[trackEntry]; + if ( !(pEntry->Srb) ) + { + DebugPrint((3, "LsiU3(%2x): ProcessCommandComplete - SRB is NULL!!\n", + DeviceExtension->SIOPRegisterBase)); + // this may have been completed already by a LUN or target reset + // indicate no request is active. + DeviceExtension->ActiveRequest = NULL; + return; + } + // reset Srb address + pEntry->Srb = NULL; + // get I/O tracking entry post index + trackFIFO = DeviceExtension->TrackPost; + DeviceExtension->IoTrackFIFO[trackFIFO++] = trackEntry; + // check for index wrap + if ( trackFIFO == START_Q_DEPTH ) + trackFIFO = 0; + // save index + DeviceExtension->TrackPost = trackFIFO; + + // post queue tag value back to FIFO + if ( Srb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE ) + { + tagIndex = DeviceExtension->QTagPost; + DeviceExtension->QTagFIFO[tagIndex++] = pEntry->queueTag; + // check for index wrap + if ( tagIndex == START_Q_DEPTH ) + tagIndex = 0; + // save index + DeviceExtension->QTagPost = tagIndex; + } + + // indicate no request is active. + DeviceExtension->ActiveRequest = NULL; + + // indicate request completed to port driver. + StorPortNotification( + RequestComplete, + DeviceExtension, + Srb ); + + //_____________________________________________________________________ + // Defect injection for: StorPortNotification.slic + StorPortGetOriginalMdl(DeviceExtension, Srb, &Mdl); + //_____________________________________________________________________ + +} // ProcessCommandComplete + + +UCHAR +ProcessDeviceResetFailed( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is called when scripts try to reset a wayward device, but + cannot. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_EXIT - no restart of scripts needed (BusResetPostProcess will restart) + +--*/ + +{ + DebugPrint((1, "LsiU3(%2x) Bus Device Reset or Abort failed \n", + DeviceExtension->SIOPRegisterBase)); + + // set ResetActive + DeviceExtension->ResetActive = 3; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT ); + +} // ProcessDeviceResetFailed + + +UCHAR +ProcessDeviceResetOccurred( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is called when scripts sucessfully sent a Bus Device + Reset message to a device. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_START_SCRIPT to restart the scripts + +--*/ + +{ + UCHAR function, lun, target; + ULONG index, trackFIFO, tagIndex; + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PIO_TRACK_ENTRY pEntry; + + target = Srb->TargetId; + function = Srb->Function; + + if ( function == SRB_FUNCTION_RESET_LOGICAL_UNIT ) + { + lun = Srb->Lun; + DebugPrint((1, "LsiU3(%2x) LUN Reset occurred on ID %d, LUN %d\n", + DeviceExtension->SIOPRegisterBase, target, lun)); + } + else + { + DebugPrint((1, "LsiU3(%2x) Bus Device Reset occurred on ID %d\n", + DeviceExtension->SIOPRegisterBase, target)); + } + + // scan I/O tracking array to complete all outstanding I/Os to this + // target or LUN back to the port driver + pEntry = DeviceExtension->IoTrackArray; + for ( index = 0; index < START_Q_DEPTH; index++ ) + { + Srb = pEntry->Srb; + if ( Srb ) + { + if ( ((function == SRB_FUNCTION_RESET_LOGICAL_UNIT) && + (pEntry->target == target) && (pEntry->lun == lun)) || + (pEntry->target == target) ) + { + pEntry->Srb = NULL; + // get I/O tracking entry post index + trackFIFO = DeviceExtension->TrackPost; + DeviceExtension->IoTrackFIFO[trackFIFO++] = (UCHAR)index; + // check for index wrap + if ( trackFIFO == START_Q_DEPTH ) + trackFIFO = 0; + // save index + DeviceExtension->TrackPost = trackFIFO; + + // post queue tag value back to FIFO + if ( Srb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE ) + { + tagIndex = DeviceExtension->QTagPost; + DeviceExtension->QTagFIFO[tagIndex++] = pEntry->queueTag; + // check for index wrap + if ( tagIndex == START_Q_DEPTH ) + tagIndex = 0; + // save index + DeviceExtension->QTagPost = tagIndex; + } + // complete the Srb back with reset status + Srb->SrbStatus = SRB_STATUS_BUS_RESET; + StorPortNotification( RequestComplete, DeviceExtension, Srb); + } + } + pEntry++; + } + + // complete the reset request (if there was one) + if ( (function == SRB_FUNCTION_RESET_LOGICAL_UNIT) || + (function == SRB_FUNCTION_RESET_DEVICE) ) + { + Srb = DeviceExtension->ActiveRequest; + // complete the lun/target reset Srb + Srb->SrbStatus = SRB_STATUS_SUCCESS; + StorPortNotification( RequestComplete, DeviceExtension, Srb); + } + + // reset active request + DeviceExtension->ActiveRequest = NULL; + + return( ISR_START_SCRIPT ); +} // ProcessDeviceResetOccurred + + +UCHAR +ProcessDiffSenseChange( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is called when the 1010 chip generates an interrupt due + to a change in the SCSI bus mode between SE and LVDS. We keep a + flag to indicate if we're in LVDS mode or not, and another flag + to indicate that be dropped back from LVDS to SE. + + NOTE: This routine assumes mode changes of LVDS to SE and SE to LVDS + only. No change from or to HV differential is handled. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_EXIT - SCSI bus reset will cause scripts to restart + +--*/ + +{ + // see if we're in LVDS mode and set flag accordingly + if ((READ_SIOP_UCHAR(STEST4) & STEST4_BUS_TYPE_MASK) == STEST4_LOWV_DIFF) + { + DeviceExtension->DeviceFlags |= DFLAGS_LVDS_MODE; + DeviceExtension->DeviceFlags &= ~DFLAGS_LVDS_DROPBACK; + } + else + { + DeviceExtension->DeviceFlags &= ~DFLAGS_LVDS_MODE; + DeviceExtension->DeviceFlags |= DFLAGS_LVDS_DROPBACK; + } + + // set ResetActive + DeviceExtension->ResetActive = 4; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); +} + + +UCHAR +ProcessDMAInterrupt( + PHW_DEVICE_EXTENSION DeviceExtension, + UCHAR DmaStatus + ) +/*++ + +Routine Description: + + The routine processes interrupts from the DMA core of the 53C1010 SIOP. + +Arguments: + + Context - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + An ISR_ return value for ISR_Service_Next to restart the scripts. + +--*/ + +{ + ULONG i; + UCHAR ScriptIntOpcode; + + if ( DmaStatus & DSTAT_SCRPTINT) { + + // Check for residual data in the C1010 DMA FIFO and + // flush it as neccessary. + if (!(DmaStatus & 0x80)) { + WRITE_SIOP_UCHAR( CTEST3, (UCHAR)(READ_SIOP_UCHAR(CTEST3) | + CTEST3_FLUSH_FIFO)); + for (i=0; i < 1000; i++) { + if (READ_SIOP_UCHAR(DSTAT) & 0x80) { + break; + } + StorPortStallExecution(5); + } + + if (i >= 1000) { + // set ResetActive + DeviceExtension->ResetActive = 5; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); + } + WRITE_SIOP_UCHAR( CTEST3, (UCHAR)(READ_SIOP_UCHAR(CTEST3) & 0x01)); + } + + // read the register that contains the script interrupt opcode. + ScriptIntOpcode = READ_SIOP_UCHAR( DSPS[0]); + + // The following DMA interrupts should only occur when we have an + // active SRB. To be safe, we check for one. If there is not an + // active SRB, the hardware has interrupted inappropriately, + // so reset everything. + + if ( DeviceExtension->ActiveRequest == NULL ) { + + DebugPrint((1, "LsiU3(%2x) ProcessDMAInterrupt unknown request\n", + DeviceExtension->SIOPRegisterBase)); + DebugPrint((1, " ActiveRequest: %lx DmaStatus: %x\n", + DeviceExtension->ActiveRequest, DmaStatus)); + DebugPrint((1, " DSPS[0]: %x\n", + ScriptIntOpcode)); + + // set ResetActive + DeviceExtension->ResetActive = 6; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); + }; + + DebugPrint((3, "LsiU3(%2x) ProcessDMAInterrupt ...ScriptIntOpcode=%x\n", + DeviceExtension->SIOPRegisterBase, ScriptIntOpcode)); + + switch( ScriptIntOpcode) { + + // call appropriate routine to process script interrupt. + + case SCRIPT_INT_SYNC_NEGOT_COMP: + + // process SCRIPT_INT_SYNC_NEGOT_COMP script interrupt. + // return disposition code to ISR. + return( ProcessSynchNegotComplete( DeviceExtension)); + + case SCRIPT_INT_WIDE_NEGOT_COMP: + + // process SCRIPT_INT_WIDE_NEGOT_COMP script interrupt. + // return disposition code to ISR. + return( ProcessWideNegotComplete( DeviceExtension)); + + case SCRIPT_INT_CHECK_CONDITION: + + // process SCRIPT_INT_CHECK_CONDITION script interrupt. + // return disposition code to ISR. + return( ProcessCheckCondition( DeviceExtension)); + + case SCRIPT_INT_PPR_NEGOT_COMP: + + // process SCRIPT_INT_PPR_NEGOT_COMP script interrupt. + // return disposition code to ISR. + return( ProcessPprNegotComplete( DeviceExtension)); + + case SCRIPT_INT_REJECT_MSG_RECEIVED: + + // process SCRIPT_INT_REJECT_MSG_RECEIVED script interrupt. + // return disposition code to ISR. + return( ProcessRejectReceived( DeviceExtension)); + + case SCRIPT_INT_SAVE_DATA_PTRS: + + // most of the time, a SAVE DATA POINTERS is followed + // by a DISCONNECT message. The scripts already handle + // this, saving us a second interrupt for the disconnect. + return( ProcessSaveDataPointers( DeviceExtension)); + + case SCRIPT_INT_DEV_RESET_OCCURRED: + + // process SCRIPT_INT_DEV_RESET_OCCURRED script interrupt. return + // disposition code to ISR. + return( ProcessDeviceResetOccurred( DeviceExtension)); + + case SCRIPT_INT_DEV_RESET_FAILED: + case SCRIPT_INT_ABORT_FAILED: + + // process SCRIPT_INT_DEV_RESET_FAILED script interrupt. return + // disposition code to ISR. + return( ProcessDeviceResetFailed( DeviceExtension)); + + case SCRIPT_INT_IDE_MSG_SENT: + + // process SCRIPT_INT_IDE_MSG_SENT script interrupt. return + // disposition code to ISR. + return( ProcessErrorMsgSent( )); + + case SCRIPT_INT_INVALID_RESELECT: + case SCRIPT_INT_INVALID_TAG_MESSAGE: + + // process SCRIPT_INT_INVALID_RESELECT script interrupt. + // return disposition code to ISR. + return( ProcessInvalidReselect( DeviceExtension) ); + + case SCRIPT_INT_BAD_XFER_DIRECTION: + + // S/G move commands are wrong direction. Switch commands + // to opposite direction and restart scripts at S/G moves. + return( ProcessBadDataDirection( DeviceExtension) ); + + case SCRIPT_INT_IGNORE_WIDE_RESIDUE: + + // process SCRIPT_INT_IGNORE_WIDE_RESIDUE script interrupt. + // return disposition code to ISR. + return( ProcessIgnoreWideResidue( DeviceExtension) ); + + case SCRIPT_INT_NVCONFIG_IOCTL: + + // process request to read or write NVRAM. + return( ProcessNVConfigIoctl( DeviceExtension) ); + + case SCRIPT_INT_CA_QUEUE_FULL: + + // The CA queue is full and no more req sns commands can + // be issued. We're hosed, so we need to reset the bus. + + DebugPrint((1, "LsiU3(%2x): CA Queue Full... Reset Bus.\n", + DeviceExtension->SIOPRegisterBase)); + // fall through to reset SCSI bus + + default: + + // something went really wrong. + // perform drastic error recovery. + // set ResetActive + DeviceExtension->ResetActive = 7; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); + } // switch ( SCRIPT_INT_OPCODE) + } // if + + // all other cases indicate that things are really wrong, since we mask + // off all other types of DMA interrupts. perform drastic error recovery. + // set ResetActive + DeviceExtension->ResetActive = 8; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); + +} // ProcessDMAInterrupt + + +UCHAR +ProcessErrorMsgSent( + VOID + ) +/*++ + +Routine Description: + + This routine is called when scripts sucessfully sent an IDE or MPE + message to a device. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_RESTART_SCRIPT to restart the scripts. + +--*/ + +{ + // Target devices should either: + // a) return CHECK CONDITION status after receiving an IDE message, or + // + // b) resend the entire message in the case of an MPE message. + // + // Therefore, we simply restart the script state machine. + // + // tell ISR to restart the script + return( ISR_RESTART_SCRIPT); +} // ProcessErrorMsgSent + + +UCHAR +ProcessGrossError( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine processes gross scsi errors. See 53C1010 data manual for + a description of gross errors. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_EXIT - no restart of scripts needed (BusResetPostProcess will restart) + +--*/ + +{ + UCHAR cso, ct4; + ULONG logValue, sh_st0, sh_st1; + + DebugPrint((3, "LsiU3(%2x) SCSI Gross Error occurred \n", + DeviceExtension->SIOPRegisterBase)); + // A gross error implies the hardware or SCSI device is in an unknown + // state. We reset the chip and SCSI bus in hopes that the problem will + // not recur. + // reset SIOP + // + + // 1010 Errata - writing SCNTL3 can cause a spurious Residual Data in SCSI + // FIFO gross error. If this is the SGE, just read/write the DSP to + // restart Scripts and continue. Otherwise, log the error. + + // read current inbound SCSI offset register + cso = READ_SIOP_UCHAR(CSO); + // turn on shadow register test mode bit in CTEST4 + ct4 = READ_SIOP_UCHAR(CTEST4); + WRITE_SIOP_UCHAR( CTEST4, (UCHAR)(ct4 | CTEST4_SHADOW_REG_MODE)); + // read shadowed SIST0 and SIST1 registers + sh_st0 = (ULONG)READ_SIOP_UCHAR(SIST0); + sh_st1 = (ULONG)READ_SIOP_UCHAR(SIST1); + // turn off shadow register test mode bit in CTEST4 + WRITE_SIOP_UCHAR( CTEST4, ct4); + // check for 1010 residual data errata + if ( (sh_st0 == (ULONG)SGEST0_RD) && !sh_st1 && !cso ) + { + // spurious SGE interrupt, read/write DSP + WRITE_SIOP_ULONG( DSP, READ_SIOP_ULONG(DSP)); + } + else + { + // build the value to log + // (sh_st0, sh_st1, 0x101 for SCSI gross error) + logValue = (sh_st0 << 24) + (sh_st1 << 16) + 0x101; + // log the error (can't rely on having an Srb) + StorPortLogError(DeviceExtension, NULL, 0, 0, 0, + SP_INTERNAL_ADAPTER_ERROR, logValue); + // set ResetActive + DeviceExtension->ResetActive = 9; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + } + + return( ISR_EXIT); +} // ProcessGrossError + + +UCHAR +ProcessIgnoreWideResidue( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is called when scripts receive an Ignore Wide Residue message. + It will decrement the data length by 1, due to the ignore wide residue + message, and build a new scatter/gather list. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_RESTART_SCRIPT to restart the scripts. + +--*/ + +{ + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PSVARS_DESCRIPTOR_TABLE svdtPtr = SrbExtension->svdt; + ULONG count, dataLength; + PVOID dataBuf; + USHORT Flgs, dispose; + + // get device flags for this target + Flgs = DeviceExtension->LuFlags[Srb->TargetId]; + + // send message reject if not in wide mode + if ( Flgs & LF_WIDE_NEG_FAILED || !(Flgs & LF_WIDE_NEG_DONE) ) + { + StartSIOP( DeviceExtension, DeviceExtension->RejectScriptPhys); + return( ISR_EXIT); + } + + // get cummulative byte count, decrement + count = READ_SIOP_ULONG( CSBC); + count--; + + // store updated byte count in CSBC register and svdt + WRITE_SIOP_ULONG( CSBC, count); + svdtPtr->runningByteCount = count; + + // check if all data transferred. If so, just restart scripts. + if ( count == Srb->DataTransferLength ) + return( ISR_RESTART_SCRIPT); + + // save original Srb values, adjust for data transferred so far + dataBuf = Srb->DataBuffer; + dataLength = Srb->DataTransferLength; + (ULONG_PTR)Srb->DataBuffer += count; + Srb->DataTransferLength -= count; + + // generate new scatter/gather list for rest of transfer + dispose = ScatterGatherScriptSetup(DeviceExtension, Srb, FALSE); + + // restore original Srb values + Srb->DataBuffer = dataBuf; + Srb->DataTransferLength = dataLength; + + return( ISR_RESTART_SCRIPT); +} // ProcessIgnoreWideResidue + + + +UCHAR +ProcessIllegalInstruction( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is called when illegal script instruction is fetched by + the 53C1010 or if REQ is received while executing a WAIT DISCONNECT. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_EXIT - scripts either already started or will be by BusResetPostProcess + +--*/ + +{ + ULONG ScriptPhysAddr; + + DebugPrint((1, "LsiU3(%2x) LsiU3DMAInterrupt: Illegal script instruction \n", + DeviceExtension->SIOPRegisterBase)); + // if a WAIT DISCONNECT has generated an ILLEGAL INSTRUCTION interrupt, + // meaning that we have been reselected before the WAIT DISCONNECT could + // be fetched and processed, we just restart the scripts at the next + // instruction. + + if ( READ_SIOP_UCHAR( DCMD) == DCMD_WAIT_DISCONNECT) { + DebugPrint((1, "LsiU3(%2x) LsiU3DMAInterrupt: Illegal WAIT DISCONNECT \n", + DeviceExtension->SIOPRegisterBase)); + + // get the physical address of the next script instruction. + ScriptPhysAddr = READ_SIOP_ULONG(DSP); + + // start the script instruction. + StartSIOP( DeviceExtension, ScriptPhysAddr); + return( ISR_EXIT); + } + + // if we reach here, either scripts have been corrupted in memory or the + // hardware is hosed. since we can't do anything about the former case, + // we will assume the latter and reset everything. + + // log the error (can't rely on having an Srb) + StorPortLogError(DeviceExtension, NULL, 0, 0, 0, + SP_INTERNAL_ADAPTER_ERROR, 0x102); + // set ResetActive + DeviceExtension->ResetActive = 10; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); + +} // ProcessIllegalInstruction + + +UCHAR +ProcessInvalidReselect( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is called when a device reselects that did not disconnect. + Since something is really broken at this point, we just reset everything + we can, and hope for the best. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_EXIT - no restart of scripts needed (BusResetPostProcess will restart) + +--*/ + +{ + DebugPrint((1, "LsiU3(%2x) LsiU3DMAInterrupt: Invalid Reselect \n", + DeviceExtension->SIOPRegisterBase)); + + // set ResetActive + DeviceExtension->ResetActive = 11; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); + +} // ProcessInvalidReselect + + +UCHAR +ProcessNVConfigIoctl( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + Perform either a read or write of NVRAM, as requested by the IOCTL + structure in the Srb. Read/write to/from the data buffer pointed + to by the structure. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_START_SCRIPT - Restart scripts to check for next I/O to process + +--*/ + +{ + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PSRB_IO_CONTROL pSic; + ULONG nvLength, ret_code; + + pSic = (PSRB_IO_CONTROL)(Srb->DataBuffer); + if( pSic->Signature[0] != 'W' ) + { + // set return code to error + ret_code = SRB_ERROR_ON_READ; + // read NVM data + if ( ReadNVM( DeviceExtension, + ((PSRB_BUFFER)(Srb->DataBuffer))->ucDataBuffer, + &nvLength) ) + { + // set return code and length + ret_code = SRB_GOOD_ACCESS; + pSic->Length = nvLength; + } + } + else // writing NVRAM + { + // set return code to errpr + ret_code = SRB_ERROR_ON_WRITE; + // get length of NvmData + nvLength = pSic->Length; + // write NVM data + if ( WriteNVM( DeviceExtension, + ((PSRB_BUFFER)(Srb->DataBuffer))->ucDataBuffer, + nvLength) ) + { + ret_code = SRB_GOOD_ACCESS; + } + } + + // set return code + pSic->ReturnCode |= ret_code; + // set Srb status + Srb->SrbStatus = SRB_STATUS_SUCCESS; + + // now do notification + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + + return( ISR_START_SCRIPT); +} + + +UCHAR +ProcessParityError( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine processes parity errors detected on the SCSI bus by the + host adapter. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_EXIT - Scripts already restarted by StartSIOP. + +--*/ + +{ + UCHAR msgChar; + PSVARS_DESCRIPTOR_TABLE svdtPtr = DeviceExtension->localSvdt; + + // we must determine if we are in message in phase, or some other phase, + // since we must send a different message for each case. + DebugPrint((1, "LsiU3(%2x) ProcessParityError: Parity error detected \n", + DeviceExtension->SIOPRegisterBase)); + + // check if SCSI bus message and C/D lines are high. if so, send MESSAGE + // PARITY message, and if not, send INITIATOR DETECTED ERROR message. + if ((READ_SIOP_UCHAR(SOCL) & (SBCL_MSG + SBCL_CD)) == (SBCL_MSG + SBCL_CD)) + msgChar = SCSIMESS_MESS_PARITY_ERROR; + else + msgChar = SCSIMESS_INIT_DETECTED_ERROR; + StorPortWriteRegisterUchar( DeviceExtension, svdtPtr->msgOutBuf, msgChar); + StorPortWriteRegisterUlong( DeviceExtension, + &svdtPtr->msgOutBufDescriptor.count, 1); + + StartSIOP( DeviceExtension, DeviceExtension->SendIDEScriptPhys); + + return( ISR_EXIT); + +} // ProcessParityError + + +UCHAR +ProcessPhaseMismatch( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is called when a phase mismatch occurs during a non-data + transfer. This normally occurs during message out phases. Data phase + mismatches are handled totally by the 1010 Scripts. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + An ISR_ return value for ISR_Service_Next to restart the scripts. + +--*/ + +{ + DebugPrint((3, "LsiU3(%2x) ProcessPhaseMismatch: Mismatch Occurred \n", + DeviceExtension->SIOPRegisterBase)); + + // the phase mismatch did not occur during a data phase. + // this will happen in cases such as a phase change during an + // extended message. clear the FIFO's and restart the scripts. + WRITE_SIOP_UCHAR( CTEST3, (UCHAR)(READ_SIOP_UCHAR(CTEST3) | CTEST3_CLEAR_FIFO)); + + return(ISR_RESTART_SCRIPT); + +} // ProcessPhaseMismatch + + +char +Lowercase( char c ) +{ + // + // If character is uppercase, lowercase it + // + if (c >= 'A' && c <= 'Z') { + c -= ('a' - 'A'); + } + + return c; +} + + +BOOLEAN +ProcessParseArgumentString( + //_In_ PCSTR String, + _In_ PCHAR String, + //_In_ PCSTR WantedString, + _In_ PCHAR WantedString, + _Out_ PULONG ValueFound + ) + +/*++ + +Routine Description: + + This routine will parse the string for a match on the wanted string, then + calculate the value for the wanted string and return it to the caller. + + Each character of the argument string is converted to lowercase before comparison, + though the original string is unmodified. + +Arguments: + + String - The ASCII string to parse. + WantedString - The keyword for the value desired (case-sensitive). + ValueFound - address where the value found is placed + +Return Values: + + TRUE if WantedString found, FALSE if not + ValueFound converted from ASCII to binary. + +--*/ + +{ + //PCSTR cptr; + //PCSTR kptr; + PCHAR cptr; + PCHAR kptr; + ULONG stringLength = 0; + ULONG WantedStringLength = 0; + ULONG index; + + RtlZeroMemory(&ValueFound, sizeof(ULONG)); + + // Calculate the string length. + cptr = String; + while (*cptr) + { + cptr++; + stringLength++; + } + + // Calculate the wanted strings length. + cptr = WantedString; + while (*cptr) + { + cptr++; + WantedStringLength++; + } + + if (WantedStringLength > stringLength) + // Can't possibly have a match. + return FALSE; + + // Now setup and start the compare. + cptr = String; + +ContinueSearch: + + // The input string may start with white space. Skip it. + while (*cptr == ' ' || *cptr == '\t') + cptr++; + + if (*cptr == '\0') + // end of string. + return FALSE; + + kptr = WantedString; + + while (Lowercase( *cptr++ ) == *kptr++) + { + if (*(cptr - 1) == '\0') + // end of string + return FALSE; + } + + if (*(kptr - 1) == '\0') + { + // May have a match backup and check for blank or equals. + cptr--; + while (*cptr == ' ' || *cptr == '\t') + cptr++; + + // Found a match. Make sure there is an equals. + if (*cptr != '=') + { + // Not a match so move to the next semicolon. + while (*cptr) + { + if (*cptr++ == ';') + goto ContinueSearch; + } + return FALSE; + } + + // Skip the equals sign. + cptr++; + + // Skip white space. + while ((*cptr == ' ') || (*cptr == '\t')) + cptr++; + + if (*cptr == '\0') + // Early end of string, return not found + return FALSE; + + if (*cptr == ';') + { + // This isn't it either. + cptr++; + goto ContinueSearch; + } + + *ValueFound = 0; + if ((*cptr == '0') && (Lowercase( *(cptr + 1) ) == 'x')) + { + // Value is in Hex. Skip the "0x" + cptr += 2; + for (index = 0; *(cptr + index); index++) + { + if (*(cptr + index) == ' ' || + *(cptr + index) == '\t' || + *(cptr + index) == ';') + break; + + if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) + *ValueFound = (16 * (*ValueFound)) + (*(cptr + index) - '0'); + else + { + if ((Lowercase( *(cptr + index) ) >= 'a') && (Lowercase( *(cptr + index) ) <= 'f')) + *ValueFound = (16 * (*ValueFound)) + (Lowercase( *(cptr + index) ) - 'a' + 10); + else + // Syntax error, return not found. + return FALSE; + } + } + } + else + { + // Value is in Decimal. + for (index = 0; *(cptr + index); index++) + { + if (*(cptr + index) == ' ' || + *(cptr + index) == '\t' || + *(cptr + index) == ';') + break; + if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) + *ValueFound = (10 * (*ValueFound)) + (*(cptr + index) - '0'); + else + // Syntax error return not found. + return FALSE; + } + } + return TRUE; + } + else + { + // Not a match check for ';' to continue search. + while (*cptr) + { + if (*cptr++ == ';') + goto ContinueSearch; + } + } + return FALSE; +} // ProcessParseArgumentString + + +UCHAR +ProcessPprNegotComplete( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine handles successful PPR negotiation, as well as + target initiated negotiation. The routine first retrieves the + PPR period, offset, and width from the message in buffer, then massages + the parameters into a form the SIOP can use. It also sets up the PPR + message to be sent by a request sense command. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + An ISR_ return value for ISR_Service_Next to restart the scripts. + +--*/ + +{ + UCHAR RecvdSynchPeriod, RecvdSynchOffset, RecvdWideWidth, RecvdDT_flag; + UCHAR SynchPeriod = 0, SynchOffset = 0, i; + UCHAR Scntl3Value, scf; + UCHAR MaxOffset, MinPeriod; + UCHAR negot_flag, target; + PUCHAR msgPtr; + USHORT luflags; + ULONG dxp_value, script_addr; + BOOLEAN dis_sync = FALSE; + BOOLEAN AutoReqSns = FALSE; + BOOLEAN reject_flag = FALSE; + BOOLEAN tin_flag = FALSE; + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PDMI_DATA pDmi = &DeviceExtension->DmiData; + UCHAR sync_values[5] = { 0x09, 0x0A, 0x0C, 0x19, 0x32}; + UCHAR scf_values[5] = { 0x10, 0x10, 0x30, 0x50, 0x70}; + + target = Srb->TargetId; + luflags = DeviceExtension->LuFlags[target]; + dxp_value = DeviceExtension->dxp[target]; + // if doing OS issued request sense, process like auto request sense + if (SrbExtension->autoReqSns || (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)) + AutoReqSns = TRUE; + + if (!((SrbExtension->SrbExtFlags & LF_PPR_NEG_PENDING) == + LF_PPR_NEG_PENDING) && !AutoReqSns ) + { + tin_flag = TRUE; + SrbExtension->SrbExtFlags |= LF_TIN_PPR_PENDING; + DebugPrint((1, "LsiU3(%2x) ProcessPprNegotComplete: Target initiated PPR negotiation\n", + DeviceExtension->SIOPRegisterBase)); + } + else + { + luflags &= ~LF_PPR_NEG_PENDING; + SrbExtension->SrbExtFlags &= ~LF_PPR_NEG_PENDING; + } + + if ( AutoReqSns || tin_flag ) + // save dxp to check for changes + DeviceExtension->old_dxp = dxp_value; + + if ( SrbExtension->SrbExtFlags & LF_DISABLE_SYNC ) + dis_sync = TRUE; + + // pick up period, offset, width, and DT flag from Script message buffer + msgPtr = DeviceExtension->svars->msgInBuf; + RecvdSynchPeriod = StorPortReadRegisterUchar( DeviceExtension, msgPtr); + RecvdSynchOffset = StorPortReadRegisterUchar( DeviceExtension, &msgPtr[2]); + RecvdWideWidth = StorPortReadRegisterUchar( DeviceExtension, &msgPtr[3]); + RecvdDT_flag = StorPortReadRegisterUchar( DeviceExtension, &msgPtr[4]); + + DebugPrint((1, "LsiU3(%2x) PPR Negotiation Received - Id=%2x \n", + DeviceExtension->SIOPRegisterBase, + target + )); + DebugPrint((1, " Period: %x Offset: %x Width: %x DT_flag %x\n", + RecvdSynchPeriod, RecvdSynchOffset, RecvdWideWidth, RecvdDT_flag)); + + MaxOffset = MAX_1010_ST_OFFSET; + + if (RecvdSynchOffset == 0) + MinPeriod = 0; + else + { + // start with minimum period for Ultra160 + MinPeriod = 0x09; + // can do Ultra160 only if wide + if ( RecvdSynchPeriod == 0x09 && RecvdWideWidth != 1) + { + MinPeriod = 0x0A; // reset to Ultra 2 + DebugPrint((1, "LsiU3(%2x) Can't do Ultra160 if narrow - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + // can do Ultra160 only if DT on + if ( RecvdSynchPeriod == 0x09 && RecvdDT_flag != 2) + { + MinPeriod = 0x0A; + DebugPrint((1, "LsiU3(%2x) Can't do Ultra160 in ST mode - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + // check for LVDS_DROPBACK and half speed mode + MinPeriod = set_sync_speed( DeviceExtension, MinPeriod); + } + + // if doing TIN, limit the requested sync period and offset to our device + // maximums, if necessary + if ( tin_flag ) + { + if (RecvdSynchOffset > MaxOffset) + RecvdSynchOffset = MaxOffset; + if (RecvdSynchPeriod < MinPeriod) + RecvdSynchPeriod = MinPeriod; + } + + // WIDE negotiation part of PPR + if (RecvdWideWidth == 0) // target agreed only to narrow + { + dxp_value &= DISABLE_WIDE; + if (dis_sync || AutoReqSns || tin_flag) + { + // we wanted narrow, negotiation ok + luflags |= LF_NARROW_NEG_DONE; + DebugPrint((1, "LsiU3(%2x) NarrowNegotiation Agreed - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else // we wanted wide, negotiation failed + { + luflags |= LF_WIDE_NEG_DONE + LF_WIDE_NEG_FAILED; + DebugPrint((1, "LsiU3(%2x) Wide Disabled - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + } + else // target agreed with wide + { + // if not doing TIN or sync not disabled, and we have wide capability + if ( (!tin_flag || !dis_sync) && !(luflags & LF_WIDE_NEG_FAILED) ) + { + dxp_value |= ENABLE_WIDE; + luflags |= LF_WIDE_NEG_DONE; + DebugPrint((1, "LsiU3(%2x) WideNegotiation Agreed - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else // doing TIN and sync is disabled, or no wide capability + { + dxp_value &= DISABLE_WIDE; + DebugPrint((1, "LsiU3(%2x) Returned Narrow Negotiation- Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + } + + // set DMI device width field according to new width + RecvdWideWidth = 8; + if (dxp_value & ENABLE_WIDE) + RecvdWideWidth = 16; + pDmi->DevWidth[target] = RecvdWideWidth; + + // SYNC negotiation part of PPR + + if ( RecvdSynchOffset == 0 ) // target agreed only to async + { + dxp_value &= CLEAR_OFFSET_VALUES; + // set DMI device speed to async + pDmi->DevSpeed[target] = SYNC_NONE; + // need to set the sync failed flag in either case since it's used + // to see if we check sstat1_orf on phase mismatches + luflags |= LF_SYNC_NEG_FAILED; + + if ( dis_sync || AutoReqSns ) // we wanted async, negotiation ok + { + luflags |= LF_ASYNC_NEG_DONE; + DebugPrint((1, "LsiU3(%2x) AsynNegotiation Received - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else // we want sync, negotiation failed + { + luflags |= LF_SYNC_NEG_DONE; + DebugPrint((1, "LsiU3(%2x) Synchronous Disabled - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + } + else // target agreed to sync + { + if ( dis_sync && !AutoReqSns ) + { + // we wanted async, negotiation falied + // need to ignore dis_sync on auto request sense + dxp_value &= CLEAR_OFFSET_VALUES; + // set DMI device speed to async + pDmi->DevSpeed[target] = SYNC_NONE; + + if ( tin_flag ) // doing TIN, will send async response + { + DebugPrint((1, "LsiU3(%2x) Returned Async Negotiation- Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else // not doing TIN, send message reject + { + luflags |= LF_ASYNC_NEG_DONE + LF_SYNC_NEG_FAILED; + DebugPrint((1, "LsiU3(%2x) Rejecting SDTR message. Asynch failed\n", + DeviceExtension->SIOPRegisterBase)); + reject_flag = TRUE; // set flag to send reject message + } + } + else // we got sync, check on values + { + + // we negotiated for sync, target has responded with sync params + + luflags |= LF_SYNC_NEG_DONE; + Scntl3Value = (UCHAR)(dxp_value >> 24) & 0x0F; + dxp_value &= CLEAR_OFFSET_VALUES; + SynchPeriod = RecvdSynchPeriod; + SynchOffset = RecvdSynchOffset; + + // set DMI sevice speed to sync value (4 * received value) + pDmi->DevSpeed[target] = RecvdSynchPeriod << 2; + + // normalize received period to 10Mb or 5Mb periods + // between Fast-10 and Ultra, use Fast-10 + if (SynchPeriod > 0x0C && SynchPeriod <= 0x19) + SynchPeriod = 0x19; + // between Fast-5 and Fast-10, use Fast-5 + if (SynchPeriod > 0x19 && SynchPeriod <= 0x32) + SynchPeriod = 0x32; + // slower than Fast-5, use async + if (SynchPeriod > 0x32) + SynchOffset = 0; + + // find SCF value in table + for ( i = 0; i < 5; i++ ) + { + if ( SynchPeriod == sync_values[i]) + { + scf = scf_values[i]; + // if doing DT xfers below 80MT/sec, need to use the + // next lower scf value + if ((SynchPeriod > 0x09) && (RecvdDT_flag == 2) && (i < 4)) + scf = scf_values[i+1]; + Scntl3Value |= scf; + dxp_value |= RecvdSynchOffset << 8; + break; + } + } + + // turn on U3EN for DT transfers, set DT offset + if ( RecvdDT_flag == 2 ) + { + dxp_value |= 0x00000080; + MaxOffset = MAX_1010_DT_OFFSET; + } + + // put new sync period value in dxp_value + dxp_value &= CLEAR_PERIOD_VALUES; + dxp_value |= (ULONG)(Scntl3Value) << 24; + + // check for valid values, reject target if not OK + if ( (RecvdSynchOffset > MaxOffset) || + (RecvdSynchPeriod < MinPeriod) || + (SynchOffset == 0) ) + { + SynchPeriod = 0x19; // default value for async + dxp_value &= CLEAR_OFFSET_VALUES; + // set DMI device speed to async + pDmi->DevSpeed[target] = SYNC_NONE; + + if ( tin_flag ) + { + DebugPrint((1, "LsiU3(%2x) Returned async negotiation. Rate too slow\n", + DeviceExtension->SIOPRegisterBase)); + } + else + { + DebugPrint((1, "LsiU3(%2x) Rejecting SDTR message. Rate too slow\n", + DeviceExtension->SIOPRegisterBase)); + luflags |= LF_SYNC_NEG_FAILED; + reject_flag = TRUE; // set flag to send reject message + } + } + } + } + + // store updated dxp_value + DeviceExtension->dxp[target] = dxp_value; + + // store updated luflags, if not doing auto request sense or TIN + if (!AutoReqSns && !tin_flag) + { + DeviceExtension->LuFlags[target] = luflags; + } + + if ( !tin_flag ) // if not doing TIN + { + // setup negotiation buffer for next auto request sense negotiation + negot_flag = SETUP_PPR_FIRST; + } + else // doing TIN + { + // if negotiation is OK, turn on sync_neg_done flag if no sync + // negotiation is currently pending or disable sync flag is not set. + // Reset sync reject and sync failed flags. + if (!reject_flag && !(luflags & LF_SYNC_NEG_PENDING) && !dis_sync) + { + DeviceExtension->LuFlags[target] |= LF_SYNC_NEG_DONE; + DeviceExtension->LuFlags[target] &= + ~(LF_SYNC_NEG_REJECT + LF_SYNC_NEG_FAILED); + } + // save asked for period, offset, and DT flag + DeviceExtension->tin_rec_period = SynchPeriod; + DeviceExtension->tin_rec_offset = SynchOffset; + DeviceExtension->tin_rec_DT = RecvdDT_flag; + // setup msgBufOut for TIN response + negot_flag = SETUP_PPR_TIN; + } + SetupNegotBuf( DeviceExtension, target, negot_flag); + + // see if we need to update device descriptors for all outstanding commands + if (!AutoReqSns || (DeviceExtension->old_dxp != dxp_value)) + UpdateStartQDesc( DeviceExtension, Srb); + + // copy updated dxp entry to Scripts RAM dxp + StorPortWriteRegisterUlong( DeviceExtension, + &DeviceExtension->dxpSR[target], + DeviceExtension->dxp[target]); + + // if negotiation truly failed, send reject message or if doing TIN + // restart scripts at ContNegScript + if ( reject_flag || tin_flag ) + { + // reset wide/sync parameters, send a message reject + WRITE_SIOP_UCHAR(SCNTL3, (UCHAR)(dxp_value >> 24)); + WRITE_SIOP_UCHAR(SXFER, (UCHAR)(dxp_value >> 8)); + WRITE_SIOP_UCHAR(SCNTL4, (UCHAR)dxp_value); + script_addr = (tin_flag) ? DeviceExtension->ContNegScriptPhys : + DeviceExtension->RejectScriptPhys; + StartSIOP( DeviceExtension, script_addr); + return( ISR_EXIT ); + } + + return( ISR_RELOAD_SCRIPT); + +} // ProcessPprNegotComplete + + +UCHAR +ProcessRejectReceived( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is called when a device rejects a message sent in scripts. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_RESTART_SCRIPT to restart the scripts. + +--*/ + +{ + UCHAR function; + PSCSI_REQUEST_BLOCK Srb; + PSRB_EXTENSION SrbExtension; + + DebugPrint((1, "LsiU3(%2x) ProcessDMAInterrupt: Message reject received \n", + DeviceExtension->SIOPRegisterBase)); + + Srb = DeviceExtension->ActiveRequest; + SrbExtension = Srb->SrbExtension; + + // process a negotiation not supported if any negotiations are pending + // or if doing auto request sense or if OS issued request sense + if ( SrbExtension->SrbExtFlags & + (LF_WIDE_NEG_PENDING + LF_SYNC_NEG_PENDING + + LF_TIN_WIDE_PENDING + LF_TIN_SYNC_PENDING) || + SrbExtension->autoReqSns || (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) ) + return( ProcessNegotNotSupported( DeviceExtension)); + + function = Srb->Function; + if ( (function == SRB_FUNCTION_RESET_LOGICAL_UNIT) || + (function == SRB_FUNCTION_RESET_DEVICE) ) + { + // reset message byte was rejected, fail reset Srb + Srb->SrbStatus = SRB_STATUS_ERROR; + StorPortNotification( RequestComplete, DeviceExtension, Srb); + } + + return( ISR_RESTART_SCRIPT ); + +} // ProcessRejectReceived + + +UCHAR +ProcessSaveDataPointers( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine is essentially a NOP, since we save the data pointers as + part of the phase mismatch handling in scripts. We just restart the + scripts engine. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_RESTART_SCRIPT to restart the scripts. + +--*/ + +{ +#if DBG + DebugPrint((3, "LsiU3(%2x) Save Data Pointers\n",DeviceExtension->SIOPRegisterBase)); +#else + UNREFERENCED_PARAMETER( DeviceExtension ); +#endif + + return( ISR_RESTART_SCRIPT); + +} // ProcessSaveDataPointers + + +UCHAR +ProcessSCSIInterrupt( + PHW_DEVICE_EXTENSION DeviceExtension, + UCHAR ScsiStatus + ) +/*++ + +Routine Description: + + This routine processes interrupts from the SCSI core of the 53C1010 SIOP. + +Arguments: + + Context - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + TRUE + +--*/ + +{ + // The following SCSI interrupts should only occur when we have an + // active SRB. To be safe, we check for one. If there is not an + // active SRB, the hardware has interrupted inappropriately, + // so reset everything. + + if (DeviceExtension->ActiveRequest == NULL) + { + DebugPrint((1, "LsiU3(%2x) ProcessSCSIInterrupt unknown request\n", + DeviceExtension->SIOPRegisterBase)); + DebugPrint((1, " ActiveRequest: %lx ScsiStatus: %x\n", + DeviceExtension->ActiveRequest, ScsiStatus)); + + // set ResetActive + DeviceExtension->ResetActive = 12; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); + } + + // if a SCSI gross error occurred call routine to process, and return + // disposition code to ISR. + if ( ScsiStatus & SSTAT0_GROSS_ERROR) + return( ProcessGrossError( DeviceExtension)); + + // if an unexpected disconnect occurred call routine to process, and + // return disposition code to ISR. + if ( ScsiStatus & SSTAT0_UNEXPECTED_DISCONNECT) + return( ProcessUnexpectedDisconnect( DeviceExtension)); + + // if a parity error was detected call routine to process, and return + // disposition code to ISR. + if ( ScsiStatus & SSTAT0_PARITY_ERROR) + return( ProcessParityError( DeviceExtension)); + + // if none of the above, the hardware is in an unknown state. Perform + // drastic error recovery. + // set ResetActive + DeviceExtension->ResetActive = 13; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); + +} // ProcessSCSIInterrupt + + +UCHAR +ProcessSelectionTimeout( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine processes selection timeouts. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_RESTART_SCRIPT to restart the scripts. + +--*/ + +{ + UCHAR target, trackEntry; + USHORT lflags; + ULONG tagIndex, trackFIFO; + PSCSI_REQUEST_BLOCK Srb; + PSRB_EXTENSION SrbExtension; + PIO_TRACK_ENTRY pEntry; + + // clear DMA FIFO to eliminate residual data if interrupted during + // a table indirect move + WRITE_SIOP_UCHAR( CTEST3, (UCHAR)(READ_SIOP_UCHAR(CTEST3) | CTEST3_CLEAR_FIFO)); + + // set IRQ received flag + DeviceExtension->IRQ_received = TRUE; + + // the 53C1010 SIOP generates an UNEXPECTED DISCONNECT interrupt along + // with SELECTION TIMEOUT. We check the SCSI STATUS0 register to see if + // one has been stacked. If so, read SCSI STATUS1 register also to clear + // it. This is safe since no additional SCSI interrupt should have + // been generated at this time. + + if (READ_SIOP_UCHAR(SIST0) == SSTAT0_UNEXPECTED_DISCONNECT) + READ_SIOP_UCHAR(SIST1); + + // get the logical unit extension and SRB for the request that timed out. + Srb = DeviceExtension->ActiveRequest; + + if (!Srb) { + return (ISR_START_SCRIPT); + } + + target = Srb->TargetId; + DebugPrint((1, "LsiU3(%2x) SelectionTimeout: Timeout for Id=%2x \n", + DeviceExtension->SIOPRegisterBase, + target)); + + // restore LuFlags for this device to initial state (to prepare for a + // future device arrival) + lflags = LF_SYNC_NEG_FAILED + LF_NEG_NEEDED; // these need to be set + // check if wide should be disabled + if ( !(DeviceExtension->hbaCapability & HBA_CAPABILITY_WIDE) || + DeviceExtension->DeviceTable[target].WideDataBits == WIDE_NONE ) + lflags |= LF_NARROW_NEG_DONE + LF_WIDE_NEG_DONE + + LF_WIDE_NEG_FAILED; + // if sync should be turned off, set sync negotiation done flag + if ( DeviceExtension->DeviceTable[target].SyncPeriodNs == SYNC_NONE ) + lflags |= LF_SYNC_NEG_DONE; + // save local lflags value + DeviceExtension->LuFlags[target] = lflags; + + + // free I/O tracking array entry + SrbExtension = Srb->SrbExtension; + if ( !SrbExtension ) + { + DebugPrint((3, "LsiU3(%2x): ProcessSelectionTimeout - SrbExtension is NULL!!\n", + DeviceExtension->SIOPRegisterBase)); + // this may have been completed already by a LUN or target reset + // indicate no request is active. + DeviceExtension->ActiveRequest = NULL; + return (ISR_START_SCRIPT); + } + trackEntry = SrbExtension->trackEntry; + pEntry = &DeviceExtension->IoTrackArray[trackEntry]; + if ( !(pEntry->Srb) ) + { + DebugPrint((3, "LsiU3(%2x): ProcessSelectionTimeout - SRB is NULL!!\n", + DeviceExtension->SIOPRegisterBase)); + // this may have been completed already by a LUN or target reset + // indicate no request is active. + DeviceExtension->ActiveRequest = NULL; + return (ISR_START_SCRIPT); + } + pEntry->Srb = NULL; + // get I/O tracking entry post index + trackFIFO = DeviceExtension->TrackPost; + DeviceExtension->IoTrackFIFO[trackFIFO++] = trackEntry; + // check for index wrap + if ( trackFIFO == START_Q_DEPTH ) + trackFIFO = 0; + // save index + DeviceExtension->TrackPost = trackFIFO; + + // post queue tag value back to FIFO + if ( Srb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE ) + { + tagIndex = DeviceExtension->QTagPost; + DeviceExtension->QTagFIFO[tagIndex++] = pEntry->queueTag; + // check for index wrap + if ( tagIndex == START_Q_DEPTH ) + tagIndex = 0; + // save index + DeviceExtension->QTagPost = tagIndex; + } + + // indicate this request is no longer active. + DeviceExtension->ActiveRequest = NULL; + + // indicate selection timeout occurred and notify port driver. + + Srb->SrbStatus = SRB_STATUS_SELECTION_TIMEOUT; + + StorPortNotification( + RequestComplete, + DeviceExtension, + Srb); + + // tell ISR to start new request. + + return( ISR_START_SCRIPT); + +} // ProcessSelectionTimeout + + +UCHAR +ProcessSynchNegotComplete( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine handles successful async/sync negotiation, as well as + target initiated negotiation. The routine first retrieves the + synchronous period and offset from the message in buffer, then massages + the parameters into a form the SIOP can use. It also sets up the wide + (if doing wide) or sync message to be sent first by a request sense + command. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + An ISR_ return value for ISR_Service_Next to restart the scripts. + +--*/ + +{ + UCHAR RecvdSynchPeriod, RecvdSynchOffset; + UCHAR SynchPeriod = 0, SynchOffset = 0, i; + UCHAR Scntl3Value; + UCHAR MaxOffset, MinPeriod; + UCHAR negot_flag, target; + USHORT luflags, hbaCap; + ULONG dxp_value, script_addr; + BOOLEAN dis_sync = FALSE; + BOOLEAN AutoReqSns = FALSE; + BOOLEAN reject_flag = FALSE; + BOOLEAN tin_flag = FALSE; + PUCHAR msgPtr; + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PDMI_DATA pDmi = &DeviceExtension->DmiData; + UCHAR sync_values[5] = { 0x09, 0x0A, 0x0C, 0x19, 0x32}; + UCHAR scf_values[5] = { 0x10, 0x10, 0x30, 0x50, 0x70}; + + target = Srb->TargetId; + luflags = DeviceExtension->LuFlags[target]; + hbaCap = DeviceExtension->hbaCapability; + + // set IRQ received flag + DeviceExtension->IRQ_received = TRUE; + + // if doing OS issued request sense, process like auto request sense + if ((SrbExtension->autoReqSns || (Srb->Cdb[0] == SCSIOP_REQUEST_SENSE)) && + (SrbExtension->autoReqSns != 2)) + { + AutoReqSns = TRUE; + if ( luflags & LF_WIDE_NEG_FAILED ) + DeviceExtension->old_dxp = DeviceExtension->dxp[target]; + } + + if ( !(SrbExtension->SrbExtFlags & LF_SYNC_NEG_PENDING) && !AutoReqSns ) + { + tin_flag = TRUE; + SrbExtension->SrbExtFlags |= LF_TIN_SYNC_PENDING; + DebugPrint((1, "LsiU3(%2x) ProcessSynchNegotComplete: Target initiated sync negotiation\n", + DeviceExtension->SIOPRegisterBase)); + } + else + { + luflags &= ~LF_SYNC_NEG_PENDING; + SrbExtension->SrbExtFlags &= ~LF_SYNC_NEG_PENDING; + } + + if ( SrbExtension->SrbExtFlags & LF_DISABLE_SYNC ) + dis_sync = TRUE; + + // Clear the failed negotiation flag. If needed, it will be set on failure. + // if we have done sync. values, now need to check sstat1_orf + luflags &= ~LF_SYNC_NEG_FAILED; + + // pick up synch period and offset from Script message buffer + msgPtr = DeviceExtension->svars->msgInBuf; + RecvdSynchPeriod = StorPortReadRegisterUchar( DeviceExtension, msgPtr); + RecvdSynchOffset = StorPortReadRegisterUchar( DeviceExtension, &msgPtr[1]); + + MaxOffset = MAX_1010_ST_OFFSET; + + if (RecvdSynchOffset == 0) + MinPeriod = 0; + else + { + MinPeriod = 0x0A; // FAST40 + // check for LVDS_DROPBACK and half speed mode + MinPeriod = set_sync_speed( DeviceExtension, MinPeriod); + } + + DebugPrint((1, "LsiU3(%2x) SynchronousNegotiation Received - Id=%2x \n", + DeviceExtension->SIOPRegisterBase, + target + )); + DebugPrint((1, " Period: %x Offset: %x\n", + RecvdSynchPeriod, RecvdSynchOffset)); + + // if doing TIN, limit the requested sync period and offset to our device + // maximums, if necessary + if ( tin_flag ) + { + if (RecvdSynchOffset > MaxOffset) + RecvdSynchOffset = MaxOffset; + if (RecvdSynchPeriod < MinPeriod) + RecvdSynchPeriod = MinPeriod; + } + + if ( RecvdSynchOffset == 0 ) // target agreed only to async + { + DeviceExtension->dxp[target] &= CLEAR_OFFSET_VALUES; + // set DMI device speed to async + pDmi->DevSpeed[target] = SYNC_NONE; + // need to set the sync failed flag in either case since it's used + // to see if we check sstat1_orf on phase mismatches + luflags |= LF_SYNC_NEG_FAILED; + + if ( dis_sync || AutoReqSns ) // we wanted async, negotiation ok + { + luflags |= LF_ASYNC_NEG_DONE; + DebugPrint((1, "LsiU3(%2x) AsynNegotiation Received - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else // we want sync, negotiation failed + { + luflags |= LF_SYNC_NEG_DONE; + DebugPrint((1, "LsiU3(%2x) Synchronous Disabled - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + } + else // target agreed to sync + { + if ( dis_sync && !AutoReqSns ) + { + // we wanted async, negotiation falied + // need to ignore dis_sync on auto request sense + DeviceExtension->dxp[target] &= CLEAR_OFFSET_VALUES; + // set DMI device speed to async + pDmi->DevSpeed[target] = SYNC_NONE; + + if ( tin_flag ) // doing TIN, will send async response + { + DebugPrint((1, "LsiU3(%2x) Returned Async Negotiation- Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else // not doing TIN, send message reject + { + luflags |= LF_ASYNC_NEG_DONE + LF_SYNC_NEG_FAILED; + DebugPrint((1, "LsiU3(%2x) Rejecting SDTR message. Asynch failed\n", + DeviceExtension->SIOPRegisterBase)); + reject_flag = TRUE; // set flag to send reject message + } + } + else // we got sync, check on values + { + + // we negotiated for sync, target has responded with sync params + + luflags |= LF_SYNC_NEG_DONE; + dxp_value = DeviceExtension->dxp[target]; + Scntl3Value = (UCHAR)(dxp_value >> 24) & 0x0F; + dxp_value &= CLEAR_OFFSET_VALUES; + SynchPeriod = RecvdSynchPeriod; + SynchOffset = RecvdSynchOffset; + + // set DMI sevice speed to sync value (4 * received value) + pDmi->DevSpeed[target] = RecvdSynchPeriod << 2; + + // normalize received period to 10Mb or 5Mb periods + // between Fast-10 and Ultra, use Fast-10 + if (SynchPeriod > 0x0C && SynchPeriod <= 0x19) + SynchPeriod = 0x19; + // between Fast-5 and Fast-10, use Fast-5 + if (SynchPeriod > 0x19 && SynchPeriod <= 0x32) + SynchPeriod = 0x32; + // slower than Fast-5, use async + if (SynchPeriod > 0x32) + SynchOffset = 0; + + // find SCF value in table + for ( i = 0; i < 5; i++ ) + { + if ( SynchPeriod == sync_values[i]) + { + Scntl3Value = (UCHAR)(Scntl3Value | scf_values[i]); + dxp_value |= RecvdSynchOffset << 8; + break; + } + } + + // put new sync period value in dxp_value + dxp_value &= CLEAR_PERIOD_VALUES; + dxp_value |= (ULONG)(Scntl3Value) << 24; + + // check for valid values, reject target if not OK + // workaround for 1010-66 errata at Fast-10 + // don't allow Fast-10 rate, drop back to async + if ( (RecvdSynchOffset > MaxOffset) || + (RecvdSynchPeriod < MinPeriod) || + (SynchOffset == 0) || + ((hbaCap & HBA_CAPABILITY_1010_66) && (SynchPeriod >= 0x19)) ) + { + dxp_value &= CLEAR_OFFSET_VALUES; + // set DMI device speed to async + pDmi->DevSpeed[target] = SYNC_NONE; + + if ( tin_flag ) + { + DebugPrint((1, "LsiU3(%2x) Returned async negotiation. Rate too slow\n", + DeviceExtension->SIOPRegisterBase)); + } + else + { + DebugPrint((1, "LsiU3(%2x) Rejecting SDTR message. Rate too slow\n", + DeviceExtension->SIOPRegisterBase)); + DeviceExtension->LuFlags[target] = luflags + LF_SYNC_NEG_FAILED; + reject_flag = TRUE; // set flag to send reject message + } + } + + // store updated dxp_value + DeviceExtension->dxp[target] = dxp_value; + } + } + + // store updated luflags, if not doing auto request sense or TIN + if (!AutoReqSns && !tin_flag) + { + DeviceExtension->LuFlags[target] = luflags; + } + + if ( !tin_flag ) // if not doing TIN + { + // setup negotiation buffer for next auto request sense negotiation + negot_flag = (luflags & LF_WIDE_NEG_FAILED) ? + SETUP_SYNC_FIRST : SETUP_WIDE_FIRST; + } + else // doing TIN + { + // if negotiation is OK, turn on sync_neg_done flag if no sync + // negotiation is currently pending or disable sync flag is not set. + // Reset sync reject and sync failed flags. + if (!reject_flag && !(luflags & LF_SYNC_NEG_PENDING) && !dis_sync) + { + DeviceExtension->LuFlags[target] |= LF_SYNC_NEG_DONE; + DeviceExtension->LuFlags[target] &= + ~(LF_SYNC_NEG_REJECT + LF_SYNC_NEG_FAILED); + } + // save asked for period and offset + DeviceExtension->tin_rec_period = SynchPeriod; + DeviceExtension->tin_rec_offset = SynchOffset; + // setup msgBufOut for TIN response + negot_flag = SETUP_SYNC_TIN; + } + SetupNegotBuf( DeviceExtension, target, negot_flag); + + // see if we need to update device descriptors for all outstanding commands + if (!AutoReqSns || (DeviceExtension->old_dxp != DeviceExtension->dxp[target])) + UpdateStartQDesc( DeviceExtension, Srb); + + // copy updated dxp entry to Scripts RAM dxp + StorPortWriteRegisterUlong( DeviceExtension, + &DeviceExtension->dxpSR[target], + DeviceExtension->dxp[target]); + + // if negotiation truly failed, send reject message or if doing TIN + // restart scripts at ContNegScript + if ( reject_flag || tin_flag ) + { + // reset sync parameters in sxfer, send a message reject + WRITE_SIOP_UCHAR(SXFER, (UCHAR)(DeviceExtension->dxp[target] >> 8)); + script_addr = (tin_flag) ? DeviceExtension->ContNegScriptPhys : + DeviceExtension->RejectScriptPhys; + StartSIOP( DeviceExtension, script_addr); + return( ISR_EXIT ); + } + + return( ISR_RELOAD_SCRIPT); + +} // ProcessSynchNegotComplete + + +UCHAR +ProcessNegotNotSupported( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine handles unsuccessful negotiations (sync, wide, & PPR). + For WDTR or SDTR, this routine sets the synchronous parameters to + asynchronous, or wide parameters to narrow, and sets the appropriate flags. + For a PPR rejection, the routine will setup to perform wide negotiations. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_RELOAD_SCRIPT to reload dxp parameters and restart script + +--*/ + +{ + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PSVARS_DESCRIPTOR_TABLE svdtPtr = DeviceExtension->localSvdt; + UCHAR target, MessageCount, negot_flag; + UCHAR neg_flags = SrbExtension->SrbExtFlags; + USHORT luflags; + BOOLEAN dis_sync = FALSE; + BOOLEAN sync_reject = FALSE; + BOOLEAN autoSnsWide = FALSE; + BOOLEAN OSRS_Wide = FALSE; + BOOLEAN contNeg = FALSE; + PDMI_DATA pDmi = &DeviceExtension->DmiData; + + target = Srb->TargetId; + luflags = DeviceExtension->LuFlags[target]; + if ( neg_flags & LF_DISABLE_SYNC ) + dis_sync = TRUE; + + // set IRQ received flag + DeviceExtension->IRQ_received = TRUE; + + // check for host initiated or target initiated PPR negotiations + negot_flag = neg_flags & (LF_PPR_NEG_PENDING | LF_TIN_PPR_PENDING); + if ( (negot_flag == LF_PPR_NEG_PENDING) || + (negot_flag == LF_TIN_PPR_PENDING) ) + { + luflags &= ~LF_PPR_NEG_PENDING; + SrbExtension->SrbExtFlags &= + ~(LF_PPR_NEG_PENDING + LF_TIN_PPR_PENDING); + if ( neg_flags & LF_PPR_NEG_PENDING ) + { + // host initiated PPR negotiation, but was rejected + // set flags to never try PPR negotiation again + luflags |= LF_PPR_NEG_REJECT; + DeviceExtension->LuFlags[target] = luflags; + DebugPrint((1, "LsiU3(%2x) PPR negotiation failed, Id=%x \n", + DeviceExtension->SIOPRegisterBase, + target)); + // setup negotiations again, this time with WDTR/SDTR + MessageCount = 0; + MessageCount = StartNegotiations(DeviceExtension, Srb, + MessageCount, FALSE); + // if MessageCount = 0, then no wide/sync negotiations are needed + if (MessageCount) + { + StorPortWriteRegisterUlong( DeviceExtension, + &svdtPtr->msgOutBufDescriptor.count, + (ULONG)MessageCount); + contNeg = TRUE; + } + } + else + { + // target initiated PPR negotiation, but rejected our response + DebugPrint((1, "LsiU3(%2x) Target initiated PPR negotiation rejected, Id=%x \n", + DeviceExtension->SIOPRegisterBase, + target)); + // probably need something here to get to common parameters + } + } + else // not a PPR negotiation + { + // check if doing a wide negotiation during auto request sense + // (3rd byte of NegotMsg buffer = 2 if doing wide negotiation) + if ( SrbExtension->autoReqSns ) + { + if (DeviceExtension->NonCachedExtension->NegotMsg[target].Buf[2] == 2) + autoSnsWide = TRUE; + else + sync_reject = TRUE; + } + + // check if doing a wide negotiation during OS issued request sense + // (3rd byte of msgOutBuf = 2 if doing wide negotiation) + if ( Srb->Cdb[0] == SCSIOP_REQUEST_SENSE ) + { + if ( SrbExtension->svdt->msgOutBuf[2] == 2 ) + OSRS_Wide = TRUE; + else + sync_reject = TRUE; + } + + // if doing sync negotiations during either auto or OS issued request + // sense, set flags to never try sync negotiations again and setup + // NegotBuf for next request sense command + if ( sync_reject ) + { + // set flags to never try sync negotiation again + DeviceExtension->LuFlags[target] |= LF_ASYNC_NEG_DONE + + LF_SYNC_NEG_DONE + LF_SYNC_NEG_FAILED + LF_SYNC_NEG_REJECT; + // need to setup NegotBuf in preparation for next req sns cmd + // don't do wide if previous wide negotation has failed + negot_flag = (luflags & LF_WIDE_NEG_FAILED) ? + SETUP_SYNC_FIRST : SETUP_WIDE_FIRST; + SetupNegotBuf( DeviceExtension, target, negot_flag); + // set DMI device speed to async + pDmi->DevSpeed[target] = SYNC_NONE; + return(ISR_RESTART_SCRIPT); + } + + // if host initiated or target initiated sync negotiation + if (neg_flags & (LF_SYNC_NEG_PENDING + LF_TIN_SYNC_PENDING) ) + { + luflags &= ~LF_SYNC_NEG_PENDING; + // need to set sync failed for either async or sync, used as a flag + // to check sstat1_orf in phase mismatch + luflags |= LF_SYNC_NEG_FAILED; + SrbExtension->SrbExtFlags &= + ~(LF_SYNC_NEG_PENDING + LF_TIN_SYNC_PENDING); + DeviceExtension->dxp[target] &= CLEAR_OFFSET_VALUES; + // set DMI device speed to async + pDmi->DevSpeed[target] = SYNC_NONE; + + if ( neg_flags & LF_SYNC_NEG_PENDING ) + { + // host initiated sync negotiation, but was rejected + // set flags to never try sync negotiation again + luflags |= LF_ASYNC_NEG_DONE + LF_SYNC_NEG_DONE + + LF_SYNC_NEG_REJECT; + DeviceExtension->LuFlags[target] = luflags; + // need to setup NegotBuf in preparation for next req sns cmd + // don't do wide if previous wide negotation has failed + negot_flag = (luflags & LF_WIDE_NEG_FAILED) ? + SETUP_SYNC_FIRST : SETUP_WIDE_FIRST; + SetupNegotBuf( DeviceExtension, target, negot_flag); + DebugPrint((1, "LsiU3(%2x) Sync/Async negotiation failed, Id=%x \n", + DeviceExtension->SIOPRegisterBase, + target)); + } + else + { + // target initiated sync negotiation, but rejected our response + DebugPrint((1, "LsiU3(%2x) Target initiated sync negotiation rejected, Id=%x \n", + DeviceExtension->SIOPRegisterBase, + target)); + } + } + else // wide negotiation (possibly during auto request sense) + { + luflags &= ~LF_WIDE_NEG_PENDING; + // if we get a reject on a narrow or wide negotiation, set both + // done along with the failed flag, so we won't try wide again + luflags |= LF_NARROW_NEG_DONE + LF_WIDE_NEG_DONE + + LF_WIDE_NEG_FAILED; + SrbExtension->SrbExtFlags &= + ~(LF_WIDE_NEG_PENDING + LF_TIN_WIDE_PENDING); + DeviceExtension->dxp[target] &= DISABLE_WIDE; + // set DMI device width to narrow + pDmi->DevWidth[target] = 8; + + // if host initiated wide negotiation or during auto request sense + // or during OS issued request sense + if ((neg_flags & LF_WIDE_NEG_PENDING) || autoSnsWide || OSRS_Wide) + { + DeviceExtension->LuFlags[target] = luflags; + + DebugPrint((1, "LsiU3(%2x) Narrow/wide negotiation failed, Id=%x \n", + DeviceExtension->SIOPRegisterBase, + target)); + + // although wide negotiation was rejected, continue with + // synchronous negotiation on this same I/O + // check if doing auto request sense or not + if (!autoSnsWide) + { + MessageCount = 0; + MessageCount = StartNegotiations(DeviceExtension, Srb, + MessageCount, FALSE); + if (MessageCount) + StorPortWriteRegisterUlong( DeviceExtension, + &svdtPtr->msgOutBufDescriptor.count, + (ULONG)MessageCount); + } + else + { + SetupNegotBuf( DeviceExtension, target, SETUP_SYNC_CONT); + MessageCount = 1; // needed for next test + } + // if MessageCount = 0, then no sync negotiations are needed + if (MessageCount) + contNeg = TRUE; + } + else + { + // target initiated wide negotiation, but rejected our response + DebugPrint((1, "LsiU3(%2x) Target initiated wide negotiation rejected, Id=%x \n", + DeviceExtension->SIOPRegisterBase, + target)); + } + } + + // copy updated dxp entry to Scripts RAM dxp + StorPortWriteRegisterUlong( DeviceExtension, + &DeviceExtension->dxpSR[target], + DeviceExtension->dxp[target]); + } // end of non PPR negotiation + + // see if we need to continue negotiations + if ( contNeg ) + { + StartSIOP( DeviceExtension, DeviceExtension->ContNegScriptPhys); + return( ISR_EXIT); + } + return( ISR_RELOAD_SCRIPT); + +} // ProcessNegotNotSupported + + + +UCHAR +ProcessWideNegotComplete( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine handles successful narrow/wide negotiation, as well as + responding to target initiated negotiation. The routine first retrieves + the wide width from the message in buffer, then massages the parameters + into a form the SIOP can use. It also sets up the continuation of + sync negotiations if doing auto request sense. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + An ISR_ return value for ISR_Service_Next to restart the scripts. + +--*/ + +{ + UCHAR RecvdWideWidth, target, MessageCount, negot_type; + USHORT luflags; + BOOLEAN dis_sync = FALSE; + BOOLEAN AutoReqSns = FALSE; + BOOLEAN OS_ReqSns = FALSE; + BOOLEAN tin_flag = FALSE; + PSCSI_REQUEST_BLOCK Srb = DeviceExtension->ActiveRequest; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + + target = Srb->TargetId; + luflags = DeviceExtension->LuFlags[target]; + + // set IRQ received flag + DeviceExtension->IRQ_received = TRUE; + + // see if doing auto request sense + if ( SrbExtension->autoReqSns == 1 ) + AutoReqSns = TRUE; + + // is OS doing request sense? + if ((Srb->Cdb[0] == SCSIOP_REQUEST_SENSE) && + (SrbExtension->autoReqSns != 2) ) + OS_ReqSns = TRUE; + + if ( !(SrbExtension->SrbExtFlags & LF_WIDE_NEG_PENDING) && + !AutoReqSns && !OS_ReqSns ) + { + tin_flag = TRUE; + SrbExtension->SrbExtFlags |= LF_TIN_WIDE_PENDING; + // since we're doing wide negotiation, reset sync params to async + // set sync not done and negotiations needed + DeviceExtension->dxp[target] &= CLEAR_OFFSET_VALUES; + luflags &= ~(LF_SYNC_NEG_DONE + LF_SYNC_NEG_REJECT + + LF_WIDE_NEG_FAILED); + DeviceExtension->LuFlags[target] = + luflags | (LF_NEG_NEEDED + LF_SYNC_NEG_FAILED); + DebugPrint((1, "LsiU3(%2x) ProcessWideNegotComplete: Target initiated wide negotiation\n", + DeviceExtension->SIOPRegisterBase)); + } + else + { + luflags &= ~LF_WIDE_NEG_PENDING; + SrbExtension->SrbExtFlags &= ~LF_WIDE_NEG_PENDING; + DebugPrint((1, "LsiU3(%2x) WideNegotiation Received - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + + if ( AutoReqSns || OS_ReqSns || tin_flag ) + // save dxp to check for changes + DeviceExtension->old_dxp = DeviceExtension->dxp[target]; + + if ( SrbExtension->SrbExtFlags & LF_DISABLE_SYNC ) + dis_sync = TRUE; + + RecvdWideWidth = StorPortReadRegisterUchar( DeviceExtension, + DeviceExtension->svars->msgInBuf); + + if (RecvdWideWidth == 0) // target agreed only to narrow + { + DeviceExtension->dxp[target] &= DISABLE_WIDE; + if (dis_sync || AutoReqSns || OS_ReqSns || tin_flag) + { + // we wanted narrow, negotiation ok + luflags |= LF_NARROW_NEG_DONE; + DebugPrint((1, "LsiU3(%2x) NarrowNegotiation Agreed - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else // we wanted wide, negotiation failed + { + luflags |= LF_WIDE_NEG_DONE + LF_WIDE_NEG_FAILED; + DebugPrint((1, "LsiU3(%2x) Wide Disabled - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + } + else // target agreed with wide + { + // if not doing TIN or sync not disabled, and we have wide capability + if ( (!tin_flag || !dis_sync) && !(luflags & LF_WIDE_NEG_FAILED) ) + { + DeviceExtension->dxp[target] |= ENABLE_WIDE; + luflags |= LF_WIDE_NEG_DONE; + DebugPrint((1, "LsiU3(%2x) WideNegotiation Agreed - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else // doing TIN and sync is disabled, or no wide capability + { + DeviceExtension->dxp[target] &= DISABLE_WIDE; + DebugPrint((1, "LsiU3(%2x) Returned Narrow Negotiation- Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + } + + if (!AutoReqSns && !tin_flag) // if not doing auto request sense or TIN + { + // update LuFlags from local variable if not doing OS issued req sns + if ( !OS_ReqSns ) + DeviceExtension->LuFlags[target] = luflags; + + // setup to continue sync negotiations on this I/O + MessageCount = 0; + MessageCount = StartNegotiations( DeviceExtension, Srb, MessageCount, + FALSE); + // if MessageCount = 0, don't need to do sync negotiation + if (MessageCount) + StorPortWriteRegisterUlong( DeviceExtension, + &DeviceExtension->localSvdt->msgOutBufDescriptor.count, + (ULONG)MessageCount); + else + // won't do sync, so update message buffer now + SetupNegotBuf( DeviceExtension, target, SETUP_WIDE_FIRST); + } + else // if doing auto request sense or TIN + { + // setup message buffer to continue with sync neg for auto req sns + // or to respond to wide TIN + negot_type = (tin_flag) ? SETUP_WIDE_TIN : SETUP_SYNC_CONT; + SetupNegotBuf( DeviceExtension, target, negot_type); + MessageCount = 1; // need non-zero value as flag for later + } + + // see if we need to update device descriptors in the start queue + if ( tin_flag && (DeviceExtension->old_dxp != DeviceExtension->dxp[target])) + UpdateStartQDesc( DeviceExtension, Srb); + + // copy updated dxp entry to Scripts RAM dxp + StorPortWriteRegisterUlong( DeviceExtension, + &DeviceExtension->dxpSR[target], + DeviceExtension->dxp[target]); + + // set DMI device width field according to new width + RecvdWideWidth = 8; + if (DeviceExtension->dxp[target] & ENABLE_WIDE) + RecvdWideWidth = 16; + DeviceExtension->DmiData.DevWidth[target] = RecvdWideWidth; + + // restart scripts to continue negotiations if sync negotiation is needed, + // or to restart scripts to continue this I/O + if (MessageCount) + { + // restart to continue negotiations + StartSIOP( DeviceExtension, DeviceExtension->ContNegScriptPhys); + return (ISR_EXIT); + } + else + { + // restart to continue I/O + return (ISR_RELOAD_SCRIPT); + } + +} // ProcessWideNegotComplete + + +UCHAR +ProcessUnexpectedDisconnect( + PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine processes unexpected disconnects. An unexpected disconnect + is defined as a disconnect occurring before a disconnect message is + received. The SCSI bus is reset since we can't reliably determine which + I/O failed due to the unexpected disconnect. + +Arguments: + + DeviceContext - Supplies a pointer to the device extension for the + interrupting adapter. + +Return Value: + + ISR_START_SCRIPT to restart the scripts. + +--*/ + +{ + UCHAR function, id; + ULONG ScriptPhysAddr; + PSCSI_REQUEST_BLOCK Srb; + + // clear DMA FIFO to eliminate residual data if interrupted during + // a table indirect move + WRITE_SIOP_UCHAR( CTEST3, (UCHAR)(READ_SIOP_UCHAR(CTEST3) | CTEST3_CLEAR_FIFO)); + + // need to check validity of our context pointer before using it + // get current Scripts pointer + ScriptPhysAddr = READ_SIOP_ULONG(DSP); + // test for script address in area of valid context + if ( (ScriptPhysAddr > DeviceExtension->CommandScriptPhys) && + (ScriptPhysAddr < DeviceExtension->DataOutJump1Phys) ) + { + // set Srb and function + Srb = DeviceExtension->ActiveRequest; + function = Srb->Function; + + if ( (function == SRB_FUNCTION_RESET_DEVICE) || + (function == SRB_FUNCTION_RESET_LOGICAL_UNIT) ) + return( ProcessDeviceResetOccurred( DeviceExtension)); + + if ( (function == SRB_FUNCTION_ABORT_COMMAND) || + (function == SRB_FUNCTION_TERMINATE_IO) ) + { + Srb->SrbStatus = SRB_STATUS_SUCCESS; + StorPortNotification( RequestComplete, DeviceExtension, Srb); + DeviceExtension->ActiveRequest = NULL; + return( ISR_START_SCRIPT); + } + } + + // reset the active request + DeviceExtension->ActiveRequest = NULL; + // log unexpected disconnect + id = READ_SIOP_UCHAR(SSID) & 0x0F; // get id that reselected + StorPortLogError(DeviceExtension, NULL, 0, id, 0, + SP_UNEXPECTED_DISCONNECT, 0); + // reinitialize SIOP (can't determine reliably which I/O disconnected) + // set ResetActive + DeviceExtension->ResetActive = 14; + // call routine to schedule reinitialization of the SIOP + ScheduleReinit( DeviceExtension); + return( ISR_EXIT); + +} // ProcessUnexpectedDisconnected + + +VOID +ScheduleReinit( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ) +/*++ + +Routine Description: + + This routine prepares to reinitialize the SIOP. It pauses the adapter to + block new I/O's, then does a timer routine call to a TimerReinit routine + which calls SynchronizeAccess to a SyncrhonizeISRReinit routine that does + the actual reinitialization. This is necessary because we need to + synchronize our StartIo and ISR threads during the reinitialization, and + a SynchronizeAccess call cannot be done from the ISR thread. + +Arguments: + + DeviceExtension - Supplies a pointer to the specific device extension. + +Return Value: + + None + +--*/ +{ + // pause the adapter to block any new I/Os + StorPortPause( DeviceExtension, 60); + + // request a timer call to the TimerReinit routine in 100 msec + StorPortNotification( RequestTimerCall, DeviceExtension, + TimerReinit, (ULONG)100000); +} + +VOID +TimerReinit( + _In_ PVOID Context + ) +/*++ + +Routine Description: + + This routine is called via a RequestTimerCall from an ISR thread to + perform a SynchronizeAccess call to SynchronizeISRReinit. This routine + will reinitialize the SIOP with both StartIo and ISR threads syncrhonized. + +Arguments: + + Context - Supplies a pointer to the specific adapter device extension. + +Return Value: + + None + +--*/ +{ + PHW_DEVICE_EXTENSION DeviceExtension = Context; + + // call SyncrhonizeISRReinit via a SyncrhonizeAccess call + StorPortSynchronizeAccess( DeviceExtension, + SynchronizeISRReinit, + NULL); +} + +BOOLEAN +SynchronizeISRReinit( + _In_ PVOID Context, + _In_ PVOID dummy + ) +/*++ + +Routine Description: + + This routine will reinitialize the SIOP with both StartIo and ISR threads + syncrhonized. The ResetSCSIBus routine will perform a bus reset. This + will generate an interrupt which will be processed after leaving this + routine. The processing of the bus reset interrupt will cause the Scripts + to be restarted. + +Arguments: + + Context - Supplies a pointer to the specific adapter device extension. + + dummy - Pointer value supplied via SyncrhonizeAccess (not used) + +Return Value: + + TRUE (not used) + +--*/ +{ + PHW_DEVICE_EXTENSION DeviceExtension = Context; + + UNREFERENCED_PARAMETER( dummy ); + + // reinitialize the SIOP + InitializeSIOP( DeviceExtension); + // reset the SCSI bus + ResetSCSIBus( DeviceExtension); + + // resume I/Os + StorPortResume( DeviceExtension); + // clear ResetActive + DeviceExtension->ResetActive = 0; + + return (TRUE); +} + + +VOID +ResetSCSIBus( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ) + +/*++ + +Routine Description: + + This routine resets the SCSI bus and calls the bus reset postprocess + routine. + + Note that since the 53C1010 generates a bus reset interrupt when we reset + the bus, we set a flag indicating we have reset the bus so the reset + postprocess routine will not be called twice. + +Arguments: + + DeviceExtension - Supplies a pointer to the specific device extension. + +Return Value: + + None + +--*/ + +{ + DebugPrint((1, "LsiU3(%2x) ResetSCSIBus\n", + DeviceExtension->SIOPRegisterBase)); + + // set the bus reset line high + WRITE_SIOP_UCHAR(SCNTL1, (UCHAR) ( READ_SIOP_UCHAR(SCNTL1) + | (UCHAR) SCNTL1_RESET_SCSI_BUS)); + + // Delay the minimum assertion time for a SCSI bus reset to make sure a + // valid reset signal is sent. + + StorPortStallExecution( RESET_STALL_TIME); + + WRITE_SIOP_UCHAR(SCNTL1, (UCHAR) ( READ_SIOP_UCHAR(SCNTL1) + & (UCHAR) ~SCNTL1_RESET_SCSI_BUS)); + + // indicate that we reset the bus locally. + DeviceExtension->DeviceFlags |= DFLAGS_BUS_RESET; + + BusResetPostProcess(DeviceExtension); + +} // ResetSCSIBus + + +USHORT +ScatterGatherScriptSetup( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ PSCSI_REQUEST_BLOCK Srb, + _In_ BOOLEAN hostSvdt + ) +/*++ + +Routine Description: + + This routine calculates physical break pointers and transfer lengths to + create move instructions (scripts) for each S/G element. + + NOTE: The first instruction in the S/G list is an int 0x20 when data + [in|out] to test for a wrong transfer direction. This handles cases + where the data direction flags in SrbFlags are wrong or unspecified. + +Arguments: + + DeviceExtension - Supplies the device Extension for the SCSI bus adapter. + + Srb - Supplies the Srb pointer for this I/O. + + hostSvdt - Flag to determine which svdt structure to use: + TRUE = use svdt located in SrbExtension (host memory) + FALSE = use svdt located in Scripts RAM (adapter memory) + +Return Value: + + Length of total IOV list in bytes. + +--*/ + +{ + BOOLEAN dataIn, do64bit; + USHORT iovLen, i; + ULONG scriptCmd, numElements, loop; + ULONG ElementLength; + ULONG_PTR iovStart; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PULONG iovPtr, iovSR; + PSTOR_SCATTER_GATHER_LIST pSpSGStruct; + PSTOR_SCATTER_GATHER_ELEMENT pSpSGL; + + // set flag if we should do 64 bit addressing + do64bit = (DeviceExtension->DeviceFlags & DFLAGS_64BIT_ADDRESS) ? + TRUE : FALSE; + + if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) + { + dataIn = TRUE; + scriptCmd = DATA_IN_SCRIPT; + } + else + { + dataIn = FALSE; + scriptCmd = DATA_OUT_SCRIPT; + } + + // Set pointer into Srbextension iov list + // if iovList needs to be in Scripts RAM, we'll copy it later + iovPtr = (PULONG)&SrbExtension->svdt->iovList; + + // save starting address for later length calculation + iovStart = (ULONG_PTR)iovPtr; + + // build int instruction to test data phase direction in first element + *iovPtr++ = scriptCmd | INT_CMD_MASK; + *iovPtr++ = SCRIPT_INT_BAD_XFER_DIRECTION; + + // get pointer to StorPort scatter/gather list + pSpSGStruct = StorPortGetScatterGatherList( DeviceExtension, Srb); + numElements = pSpSGStruct->NumberOfElements; + pSpSGL = pSpSGStruct->List; + + // build the SG move instructions + for ( loop = 1; loop <= numElements; loop++ ) + { + ElementLength = pSpSGL->Length; + // for data out, last element needs to be a MOVE instead of a CHMOV + // for data in, all elements must be a CHMOV (1010 errata) + if ( (loop == numElements) && !dataIn ) + { + *iovPtr++ = scriptCmd | MOVE_CMD_SCRIPT | ElementLength; + } + else + { + *iovPtr++ = scriptCmd | ElementLength; + } + + // next dword is low 32-bits of physical address + *iovPtr++ = pSpSGL->PhysicalAddress.LowPart; + + // if using 64-bit addresses, next dword is high 32-bits + if (do64bit) + *iovPtr++ = pSpSGL->PhysicalAddress.HighPart; + + // bump SGL pointer + pSpSGL++; + } + + // if using 64-bit addresses, insert instruction to turn off 64-bit mode + if (do64bit) + { + *iovPtr++ = (ULONG)DISABLE_64BITS; + *iovPtr++ = 0; + } + + // finish up SG list with return instruction + *iovPtr++ = (ULONG)RETURN_SCRIPT; + *iovPtr++ = 0; + + SrbExtension->PhysBreakCount = (UCHAR)numElements; + + iovLen = (USHORT)((ULONG_PTR)iovPtr - iovStart); + + // if hostSvdt flag is false, move the new iovList to Scripts RAM + if (!hostSvdt) + { + iovPtr = (PULONG)&SrbExtension->svdt->iovList; + iovSR = (PULONG)&DeviceExtension->localSvdt->iovList; + for ( i = 0; i < (iovLen / 4); i++) + StorPortWriteRegisterUlong( DeviceExtension, iovSR++, *(iovPtr++)); + } + + DebugPrint((3, "LsiU3(%2x) LsiU3ScatterGather: Phys breaks = %2x, total size = %8x \n", + DeviceExtension->SIOPRegisterBase, + numElements, + Srb->DataTransferLength)); + + return(iovLen); + +} // ScatterGatherScriptSetup + + +VOID +SetChipModes ( + _In_ PHW_DEVICE_EXTENSION DeviceExtension + ) +/******************************************************************************** + +Routine Description: + + This routine sets the appropriate chip options for the 1010 chip. These + chip options are: Burst Size, Read Line Enable, Read Multiple Enable, + Prefetch Enable, and Write & Invalidate Enable. + +Arguments: + + DeviceExtension - Supplies a pointer to device extension for the bus that + is being initialized. + +Return Value: + + none. + +--*/ +{ + // save chip revision in DMI data + DeviceExtension->DmiData.HW_Revision = DeviceExtension->chip_rev; + + // Prefetch Enable + WRITE_SIOP_UCHAR(DCNTL, (UCHAR)(READ_SIOP_UCHAR(DCNTL) | + (DCNTL_PREFETCH_FLUSH + DCNTL_PREFETCH_ENABLE))); + + // Write & Invalidate Enable + WRITE_SIOP_UCHAR(CTEST3, (UCHAR)(READ_SIOP_UCHAR(CTEST3) | + CTEST3_WRITE_INVALIDATE)); + + // enable Read Line & Read Multiple, set burst size (along with CTEST5) + WRITE_SIOP_UCHAR(DMODE, (UCHAR)(READ_SIOP_UCHAR(DMODE) | + (DMODE_BURST_0 + DMODE_ENA_READ_LINE + DMODE_ENA_READ_MULT))); + + // enable 64-transfer burst + WRITE_SIOP_UCHAR(CTEST5, (UCHAR)(READ_SIOP_UCHAR(CTEST5) | CTEST5_BURST)); + +} // SetChipModes + + +VOID +SetupLuFlags( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ UCHAR ResetFlag + ) +/*++ + +Routine Description: + + This routine sets up the LU flags which hold information such as whether + a peripheral device supports wide or synchronous. It also sets up initial + values for the NegotMsg buffers for negotiation on request sense. + +Arguments: + + PHW_DEVICE_EXTENSION DeviceExtension + + UCHAR ResetFlag - 0 = called during initialization, 1 = called after reset + +Return Value: + + None. + +--*/ + +{ + PHW_NONCACHED_EXTENSION NonCachedExtPtr = DeviceExtension->NonCachedExtension; + UCHAR target; + UCHAR max_targets; + UCHAR *msgptr; + UINT8 wide_bits; + USHORT lflags, save_lflags; + ULONG length; + BOOLEAN wide = TRUE; + PNEGOT_BUF bufPtr = NonCachedExtPtr->NegotMsg; + PSVARS_DESCRIPTOR negotDescPtr = NonCachedExtPtr->NegotMsgBufDesc; + PDMI_DATA pDmi = &DeviceExtension->DmiData; + + // + // Indicate that no negotiations have been done. However, if the chip + // can't do wide or the NVRAM is set for narrow only, mark wide + // negotiations as being done so we won't keep checking. If bus has + // been reset, mark narrow & async negotiations as done. + // + if ( DeviceExtension->hbaCapability & HBA_CAPABILITY_WIDE) + { + max_targets = SYM_MAX_TARGETS; + } + else + { + max_targets = SYM_NARROW_MAX_TARGETS; + wide = FALSE; + } + + for (target = 0; target < max_targets; target++) { + + lflags = save_lflags = DeviceExtension->LuFlags[target]; + wide_bits = DeviceExtension->DeviceTable[target].WideDataBits; + if ( ResetFlag ) + { + // set negotiation flags after a bus reset, save wide failed status + if ( !wide || (save_lflags & LF_WIDE_NEG_FAILED) || + (wide_bits == WIDE_NONE) ) + { + lflags = LF_NARROW_NEG_DONE + LF_WIDE_NEG_DONE + + LF_WIDE_NEG_FAILED; + } + else + { + lflags = 0; + } + + lflags |= LF_ASYNC_NEG_DONE + LF_NARROW_NEG_DONE; + // if sync has been rejected before, set flags to not negotiate + if ( save_lflags & LF_SYNC_NEG_REJECT ) + lflags |= LF_SYNC_NEG_DONE + LF_SYNC_NEG_REJECT; + + // if PPR has been rejected before, set flag + if ( save_lflags & LF_PPR_NEG_REJECT ) + lflags |= LF_PPR_NEG_REJECT; + } + else + { + // set negotiation flags during driver initialization + if ( !wide || (wide_bits == WIDE_NONE) ) + lflags = LF_NARROW_NEG_DONE + LF_WIDE_NEG_DONE + + LF_WIDE_NEG_FAILED; + else + lflags = 0; + } + + // check NVRAM setting to see if sync is turned off. if so, + // set sync negotiation done and reject flags + if ( DeviceExtension->DeviceTable[target].SyncPeriodNs == SYNC_NONE ) + lflags |= LF_SYNC_NEG_DONE + LF_SYNC_NEG_REJECT + + LF_PPR_NEG_REJECT; + + // needed as a check so we only look at sstat1_orf when we are sync + // set failed bit as a check to see when we actually get to go sync. + lflags |= LF_SYNC_NEG_FAILED; + + // if both wide & sync haven't been rejected, set neg_needed flag + // for quick check to call start negotiation. + if ( !(lflags & LF_WIDE_NEG_FAILED) || !(lflags & LF_SYNC_NEG_REJECT) ) + lflags |= LF_NEG_NEEDED; + + // save local lflags value + DeviceExtension->LuFlags[target] = lflags; + + // Setup NegotMsg buffers for negotiations on request sense commands. + // If PPR has not been rejected before, beging with PPR negotiation. + // If adapter can do wide, will default to negotiate narrow (unless + // this ID has failed a wide negotiation in the past). Otherwise, + // will setup for async negotiation. + + if ( !(lflags & LF_PPR_NEG_REJECT) ) + { + length = (ULONG)(sizeof ppr_msg); + msgptr = ppr_msg; + } + else if ( lflags & LF_WIDE_NEG_FAILED ) + { + length = (ULONG)(sizeof async_msg); + msgptr = async_msg; + if (lflags & LF_SYNC_NEG_REJECT) // do no negotiations + length = 0; // only identify byte + } + else + { + length = (ULONG)(sizeof narrow_msg); + msgptr = narrow_msg; + } + negotDescPtr[target].count = length + 1; // add 1 for identify byte + // leave room for identify byte during move + if (length) + StorPortMoveMemory( &bufPtr[target].Buf[1], msgptr, length); + } + + // at initialization set all DMI device speeds to FF, not negotiated, + // and all device widths to 8. + if (!ResetFlag) + for (target = 0; target < SYM_MAX_TARGETS; target++) + { + pDmi->DevSpeed[target] = 0xFF; + pDmi->DevWidth[target] = 8; + } + +} // SetupLuFlags + + +VOID +SetupNegotBuf( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ UCHAR target, + _In_ UCHAR negot_type + ) +/*++ + +Routine Description: + + This routine sets up the negotiation buffer used during auto request sense + negotiations or responding to target initiated negotiation (TIN) for a + particular target. + + Note: When responding to TIN, use the SrbExtension msgOutBuf in order to + keep the NegotMsgBuf array intact for any future request sense commands. + +Arguments: + + PHW_DEVICE_EXTENSION DeviceExtension + + UCHAR target - SCSI ID for this particular device + + UCHAR negot_type - SETUP_WIDE_FIRST - 1st negotiation of wide + SETUP_WIDE_TIN - wide TIN response + SETUP_SYNC_FIRST - 1st negotiation of sync + SETUP_SYNC_CONT - sync negotiation after wide + SETUP_SYNC_TIN - sync TIN response + SETUP_PPR_FIRST - 1st negotiation of PPR + SETUP_PPR_TIN - PPR TIN response + +Return Value: + + None. + +--*/ + +{ + PHW_NONCACHED_EXTENSION NonCachedExtPtr = DeviceExtension->NonCachedExtension; + UCHAR period, nv_period, offset, ptr, DT_flag, i; + UCHAR tmpBuf[8]; + ULONG length; + BOOLEAN wide = FALSE; + PUCHAR msgPtr; + PNEGOT_BUF bufPtr = NonCachedExtPtr->NegotMsg; + PSVARS_DESCRIPTOR negotDescPtr = NonCachedExtPtr->NegotMsgBufDesc; + PSVARS_DESCRIPTOR_TABLE svdtPtr = DeviceExtension->localSvdt; + + RtlZeroMemory(&tmpBuf, 8*sizeof(UCHAR)); + + // get period NVRAM setting + nv_period = (UCHAR)DeviceExtension->DeviceTable[target].SyncPeriodNs / 4; + + // check if wide (16 bits) is enabled, + if ( DeviceExtension->dxp[target] & ENABLE_WIDE ) + wide = TRUE; // set to negotiate 16 bits + + // check for setting up PPR negotiations first + if ( negot_type >= SETUP_PPR_FIRST ) + { + // if not doing TIN, setup for our maximums + if ( negot_type != SETUP_PPR_TIN ) + { + // set sync period to NVRAM setting, check LVDS_DROPBACK/half speed + period = nv_period; + // Initialize sync offset to maximum + offset = MAX_1010_DT_OFFSET; + DT_flag = 2; + } + else + { + // doing TIN, so setup to what was asked for (if values are out of our + // range, the next test for async will reset offset and period). + + // limit period to max set in NVRAM + period = (DeviceExtension->tin_rec_period < nv_period) + ? nv_period : DeviceExtension->tin_rec_period; + offset = DeviceExtension->tin_rec_offset; + DT_flag = DeviceExtension->tin_rec_DT; + } + + // see if we are currently in async (this means params not accepted) + if ( !(DeviceExtension->dxp[target] & PERIOD_MASK) ) + { + // set period and offset for async + period = 25; // use non-zero period when negotiating async + offset = 0; + } + + // check for LVDS_DROPBACK and half speed mode + period = set_sync_speed( DeviceExtension, period); + // can do Ultra160 only if wide + if (period == 0x09 && !wide) + period = 0x0A; + // can do Ultra160 only if DT on + if ( period == 0x09 && DT_flag != 2) + period = 0x0A; + // if not doing Ultra160 don't use DT + if ( period > 0x09 ) + DT_flag = 0; + // if not doing DT, use ST offset + if ( !DT_flag ) + offset = MAX_1010_ST_OFFSET; + + // move wide negotiation bytes and set count in descriptor + length = (ULONG)(sizeof ppr_msg); + + if ( negot_type == SETUP_PPR_TIN ) + // setup PPR TIN response in msgOutBuf + { + StorPortMoveMemory( tmpBuf, ppr_msg, length); + tmpBuf[3] = period; + tmpBuf[5] = offset; + if (wide) // set to 16 bits if doing wide + tmpBuf[6] = 1; + tmpBuf[7] = DT_flag; + msgPtr = svdtPtr->msgOutBuf; + for ( i = 0; i < length; i++) + StorPortWriteRegisterUchar( DeviceExtension, msgPtr++, + tmpBuf[i]); + StorPortWriteRegisterUlong( DeviceExtension, + &svdtPtr->msgOutBufDescriptor.count, + length); + } + + // setup NegotMsg buffer for PPR if doing either PPR_FIRST or + // PPR_TIN (do for PPR_TIN also since PPR params may have changed) + msgPtr = bufPtr[target].Buf; + StorPortMoveMemory( &msgPtr[1], ppr_msg, length); + negotDescPtr[target].count = length + 1; // add 1, identify byte + msgPtr[4] = period; + msgPtr[6] = offset; + if (wide) // set to 16 bits if doing wide + msgPtr[7] = 1; + msgPtr[8] = DT_flag; + + return; + } // end of PPR negotiations + + else + { + // check for setting up wide negotiations + if ( negot_type <= SETUP_WIDE_TIN ) + { + // move wide negotiation bytes and set count in descriptor + length = (ULONG)(sizeof narrow_msg); + + if ( negot_type == SETUP_WIDE_TIN) + // setup wide TIN response in msgOutBuf + { + StorPortMoveMemory( tmpBuf, narrow_msg, length); + if (wide) // set to 16 bits if doing wide + tmpBuf[3] = 1; + msgPtr = svdtPtr->msgOutBuf; + for ( i = 0; i < length; i++) + StorPortWriteRegisterUchar( DeviceExtension, msgPtr++, + tmpBuf[i]); + StorPortWriteRegisterUlong( DeviceExtension, + &svdtPtr->msgOutBufDescriptor.count, + length); + StorPortWriteRegisterUlong( DeviceExtension, + &svdtPtr->msgOutBufDescriptor.paddr, + DeviceExtension->msgOutDesc.paddr); + } + + // setup NegotMsg buffer for wide if doing either WIDE_FIRST or + // WIDE_TIN (do for WIDE_TIN also since wide param may have changed) + StorPortMoveMemory( &bufPtr[target].Buf[1], narrow_msg, length); + negotDescPtr[target].count = length + 1; // add 1, identify byte + if (wide) // set to 16 bits if doing wide + bufPtr[target].Buf[4] = 1; + + return; + } + + // setup for synchronous negotiations + + // check if doing only sync and sync has been rejected + if ( (negot_type == SETUP_SYNC_FIRST) && + (DeviceExtension->LuFlags[target] & LF_SYNC_NEG_REJECT) ) + { + // don't do any more sync negotiations, just send identify byte + negotDescPtr[target].count = 1; // 1 for just identify byte + return; + } + + // if not doing TIN, setup for our maximums + if ( negot_type != SETUP_SYNC_TIN ) + { + // set sync period to NVRAM setting, check LVDS_DROPBACK/half speed + period = set_sync_speed( DeviceExtension, nv_period); + // can't use period of 9 for SDTR + if ( period == 0x09 ) + period = 0x0A; + // Initialize sync offset to maximum + offset = MAX_1010_ST_OFFSET; + } + else + { + // doing TIN, so setup to what was asked for (if values are out of our + // range, the next test for async will reset offset and period). + + // limit period to max set in NVRAM + period = (DeviceExtension->tin_rec_period < nv_period) + ? nv_period : DeviceExtension->tin_rec_period; + // check LVDS and half speed modes + period = set_sync_speed( DeviceExtension, period); + offset = DeviceExtension->tin_rec_offset; + } + + // see if we are currently in async (this means params not accepted) + if ( !(DeviceExtension->dxp[target] & PERIOD_MASK) ) + { + // set period and offset for async + period = 25; // use non-zero period when negotiating async + offset = 0; + } + + // set sync negotiation message byte length + length = (ULONG)(sizeof async_msg); + + ptr = 0; // use this as a flag to patch period and offset + if ( negot_type == SETUP_SYNC_CONT ) + { + // setup continuing negotiations in NegotMsg buffer, but beware that + // the length needs to be placed in the svdt msgOutBufDesciptor + // because the descriptor in the NegotMsgBufDesc array has already + // been copied into the svdt. + StorPortMoveMemory( &bufPtr[target], async_msg, length); + StorPortWriteRegisterUlong( DeviceExtension, + &svdtPtr->msgOutBufDescriptor.count, + length); + ptr = 3; + } + + if ( negot_type == SETUP_SYNC_FIRST || ( negot_type == SETUP_SYNC_TIN && + (DeviceExtension->LuFlags[target] & LF_WIDE_NEG_FAILED) ) ) + { + // setup NegotMsg buffer if doing SYNC_FIRST or if doing SYNC_TIN and + // wide negotiation has failed. (need to do this for SYNC_TIN since + // the sync params may have changed) + StorPortMoveMemory( &bufPtr[target].Buf[1], async_msg, length); + negotDescPtr[target].count = length + 1; // add 1 for identify byte + ptr = 4; // point to 4th element for patching + } + + // if necessary, patch proper period and offset into buffer + if ( ptr ) + { + bufPtr[target].Buf[ptr++] = period; + bufPtr[target].Buf[ptr] = offset; + } + + if ( negot_type == SETUP_SYNC_TIN ) + // setup sync TIN response in msgOutBuf + { + StorPortMoveMemory( tmpBuf, async_msg, length); + tmpBuf[3] = period; + tmpBuf[4] = offset; + msgPtr = svdtPtr->msgOutBuf; + for ( i = 0; i < length; i++) + StorPortWriteRegisterUchar( DeviceExtension, msgPtr++, + tmpBuf[i]); + StorPortWriteRegisterUlong( DeviceExtension, + &svdtPtr->msgOutBufDescriptor.count, + length); + StorPortWriteRegisterUlong( DeviceExtension, + &svdtPtr->msgOutBufDescriptor.paddr, + DeviceExtension->msgOutDesc.paddr); + } + } // end of WDTR/SDTR negotiations + +} // SetupNegotBuf + + +VOID +StartAbortResetRequest( + PSCSI_REQUEST_BLOCK Srb, + PHW_DEVICE_EXTENSION DeviceExtension + ) + +/*++ + +Routine Description: + + This procedure starts an abort, terminate, bus device reset or LUN reset + request using the same start queue method. This is a subset of the + StartSCSIRequest procedure, but is cloned here to keep the overhead for + normal I/O processing as low as possible. + +Arguments: + + Srb - Pointer to the request to be started. + + DeviceExtension - Pointer to the device extension for this adapter. + +Return Value: + + None + +--*/ + +{ + ULONG Length, srbFlgs; + ULONG svdtPAdd; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PSVARS_DESCRIPTOR_TABLE svdtPtr; + ULONG index, svdtMove; + UCHAR function, target, lun, msg0, msg1, count; + UCHAR turCdb[] = { 0, 0, 0, 0, 0, 0 }; + + // make sure start queue isn't full + index = DeviceExtension->ioStartQIndex; + if (DeviceExtension->ioStartQueue[index].svdtPhysSem & SVDT_SEM_MASK) + { + DebugPrint((3,"StartAbortResetRequest: Start Queue Full... \n")); + Srb->SrbStatus = SRB_STATUS_BUSY; + // notify port driver of adapter busy status + // resume IO's after 20 requests have completed + StorPortBusy( DeviceExtension, 20); + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + return; + } + + // get local variables + lun = msg0 = 0; // initialize just in case + count = 0; + function = Srb->Function; + srbFlgs = Srb->SrbFlags; + target = Srb->TargetId; + svdtMove = MEMORY_MOVE_CMD + + FIELD_OFFSET(SVARS_DESCRIPTOR_TABLE, iovList); + if (function != SRB_FUNCTION_RESET_DEVICE) + lun = Srb->Lun; + + SrbExtension->SrbExtFlags = 0; // clear negotiation flags + + // align svdt on quadword boundary, if necessary + svdtPtr = &SrbExtension->svarsDescriptorTable; + if ( (ULONG_PTR)(svdtPtr) & 0x00000007 ) + svdtPtr = (PSVARS_DESCRIPTOR_TABLE)((ULONG_PTR)svdtPtr + 4); + SrbExtension->svdt = svdtPtr; + + // get physical address of svdt in system memory + svdtPAdd = StorPortConvertPhysicalAddressToUlong( + StorPortGetPhysicalAddress(DeviceExtension, NULL, + (PVOID)svdtPtr, &Length)); + + // context and deviceDescriptor entries need no physical addresses +#ifdef _WIN64 + // context is physical address of svdt, save Srb in svdt + svdtPtr->context = svdtPAdd; + svdtPtr->Srb = Srb; +#else + // context is Srb address + svdtPtr->context = (ULONG)Srb; +#endif + svdtPtr->sysSvdtPhys = svdtPAdd; // phys ptr to svdt is sys mem + svdtPtr->svdtMoveCmd = svdtMove; // mem move command + len + // copy CDB into svdt + StorPortMoveMemory(svdtPtr->Cdb, turCdb, 6); + // copy table descriptor templates into svdt + StorPortMoveMemory( &svdtPtr->deviceDescriptor, + &DeviceExtension->deviceDesc, 24); + // update table descriptor entries + svdtPtr->deviceDescriptor.count = DeviceExtension->dxp[target]; + svdtPtr->cmdBufDescriptor.count = 6; // set CDB length + + // Clear auto request sense flag + SrbExtension->autoReqSns = 0; + + // check for LUN reset + if ( function == SRB_FUNCTION_RESET_LOGICAL_UNIT ) + { + msg0 = (UCHAR)SCSIMESS_IDENTIFY_WITH_DISCON + lun; + msg1 = SCSIMESS_LOGICAL_UNIT_RESET; + count = 2; + } + else + { + // set proper message byte for this function + switch (function) + { + case SRB_FUNCTION_ABORT_COMMAND: + // see if trying to abort a tagged command + if (srbFlgs & SRB_FLAGS_QUEUE_ACTION_ENABLE) + msg0 = SCSIMESS_ABORT_WITH_TAG; + else + msg0 = SCSIMESS_ABORT; + break; + + case SRB_FUNCTION_TERMINATE_IO: + msg0 = SCSIMESS_TERMINATE_IO_PROCESS; + break; + + case SRB_FUNCTION_RESET_DEVICE: + msg0 = SCSIMESS_BUS_DEVICE_RESET; + break; + } + count = 1; + } + + svdtPtr->msgOutBuf[0] = msg0; + if ( count == 2) + svdtPtr->msgOutBuf[1] = msg1; + + // indicate message length + svdtPtr->msgOutBufDescriptor.count = count; + + DebugPrint((3, "LsiU3(%2x) StartAbortResetRequest: Starting request for Id=%2x\n", + DeviceExtension->SIOPRegisterBase, + Srb->TargetId )); + + // insert this command into the start queue + + DeviceExtension->ioStartQueue[index].svdtMoveCmd = svdtMove; + // write of svdtPhysSem must be done last + DeviceExtension->ioStartQueue[index].svdtPhysSem = svdtPAdd | SVDT_SEM_START; + + WRITE_SIOP_UCHAR(ISTAT0, ISTAT_SIGP); + + index++; + if (index == START_Q_DEPTH) + { + index = 0; + } + DeviceExtension->ioStartQIndex = index; + +} // StartAbortResetRequest + + +UCHAR +StartNegotiations( + PHW_DEVICE_EXTENSION DeviceExtension, + PSCSI_REQUEST_BLOCK Srb, + UCHAR MessageCount, + _In_ BOOLEAN hostSvdt + ) + +/*++ + +Routine Description: + + This procedure checks to see if negotiations need to be done and + sets up the message buffer if they are. + +Arguments: + + DeviceExtension - Pointer to the device extension for this adapter. + + Srb - Pointer to I/O request + + MessageCount - Message count variable for msgOut bytes + + hostSvdt - TRUE if message is built in host memory, FALSE if message + is to be copied to Scripts RAM + +Return Value: + + MessageCount - Updated value of message count + +--*/ + +{ + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PUCHAR msgOutBufPtr, msgOutBufSR; + USHORT luFlgs, hbaCap; + UCHAR period, offset, target, width, wide_bits, initCount, i; + BOOLEAN do_PPR, PPRwideSync; + BOOLEAN dis_sync = FALSE; + BOOLEAN OS_ReqSns = FALSE; + BOOLEAN wide_OSRS = FALSE; + BOOLEAN sync_OSRS = FALSE; + BOOLEAN ppr_OSRS = FALSE; + + // Setup local variables + + initCount = MessageCount; + hbaCap = DeviceExtension->hbaCapability; + target = Srb->TargetId; + luFlgs = DeviceExtension->LuFlags[target]; + wide_bits = DeviceExtension->DeviceTable[target].WideDataBits; + // set sync period to NVRAM setting + period = (UCHAR)DeviceExtension->DeviceTable[target].SyncPeriodNs / 4; + // modify sync speed for LVDS or half speed mode + period = set_sync_speed( DeviceExtension, period); + // see if we should do PPR negotiations (never do for async negotiations, + // if in narrow mode, or if period not 80MB/s) + do_PPR = !(luFlgs & LF_PPR_NEG_REJECT) && (luFlgs & LF_ASYNC_NEG_DONE) && + (wide_bits == WIDE_16) && (period == 9); + + // set message out buffer pointer to SrbExtension svdt + // if needed in local svdt, we'll move it later + msgOutBufPtr = SrbExtension->svdt->msgOutBuf; + + // are we doing an OS issued Request Sense command? + // if so, setup flags for PPR, or wide and sync + if ( Srb->Cdb[0] == SCSIOP_REQUEST_SENSE ) + { + OS_ReqSns = TRUE; + if ( do_PPR ) + { + ppr_OSRS = TRUE; + } + else + { + if ( !(luFlgs & LF_WIDE_NEG_FAILED) && + !(SrbExtension->SrbExtFlags & LF_OSRS_WIDE_DONE) ) + wide_OSRS = TRUE; + if ( !(luFlgs & LF_SYNC_NEG_REJECT) ) + sync_OSRS = TRUE; + } + } + + // If async, sync, and wide have been done, clear negotiations needed flag + // and return + if ( (luFlgs & LF_WIDE_NEG_DONE) && (luFlgs & LF_ASYNC_NEG_DONE) && + (luFlgs & LF_SYNC_NEG_DONE) && !OS_ReqSns ) + { + DeviceExtension->LuFlags[target] &= ~LF_NEG_NEEDED; + return (MessageCount); + } + + // see if force sync flag is set and async negotiations have been done + if (!((DeviceExtension->DeviceFlags & DFLAGS_FORCE_SYNC) && + (luFlgs & LF_ASYNC_NEG_DONE)) ) + { + // if not, set local disable wide/sync transfer flag + if ( Srb->SrbFlags & SRB_FLAGS_DISABLE_SYNCH_TRANSFER ) + { + SrbExtension->SrbExtFlags |= LF_DISABLE_SYNC; + dis_sync = TRUE; + } + } + + // check for doing PPR negotiations + if ( do_PPR ) + { + // make flag for PPR wide/sync done + PPRwideSync = ((luFlgs & (LF_WIDE_NEG_DONE | LF_SYNC_NEG_DONE)) == + (LF_WIDE_NEG_DONE | LF_SYNC_NEG_DONE)); + // Decide if PPR negotiations are needed + if ( (!OS_ReqSns && ((!(luFlgs & LF_ASYNC_NEG_DONE) && dis_sync) || + (!PPRwideSync && !dis_sync))) || ppr_OSRS ) + { + // fill in the parameters for PPR extended message + msgOutBufPtr[MessageCount++] = SCSIMESS_EXTENDED_MESSAGE; + msgOutBufPtr[MessageCount++] = 6; // 6 message bytes + msgOutBufPtr[MessageCount++] = 4; // PPR message + + width = 0; // default to narrow + + // Initialize sync offset to maximum for ST + offset = MAX_1010_ST_OFFSET; + + // setup for async/sync and narrow/wide depending on dis_sync flag + // or current transfer parameters if doing OS issued request sense + if ( OS_ReqSns ) + { + if ( !(DeviceExtension->dxp[target] & PERIOD_MASK) ) + offset = 0; // currently in async, set offset for async + // see if we are already in wide, if so negot wide + if ( DeviceExtension->dxp[target] & ENABLE_WIDE ) + width = 1; + } + else // normal I/O, set pending flags & check dis_sync flag + { + // indicate PPR negotiation is pending + DeviceExtension->LuFlags[target] |= LF_PPR_NEG_PENDING; + // set PPR pending flag for this I/O + SrbExtension->SrbExtFlags |= LF_PPR_NEG_PENDING; + // check for disable sync or sync rate of 0 + if ( dis_sync || period == 0 ) + { + period = 25; + offset = 0; + } + // setup for narrow/disable_sync or wide + if ( !dis_sync && (wide_bits != WIDE_NONE) ) + width = 1; + } + + // 80 MT/sec speed requires wide, if narrow set to 40MT/sec + if ( !width && (period == 9) ) + period = 10; + + // if 80MT/sec & offset not 0, set offset to DT maximum + if ( period == 9 && offset ) + offset = MAX_1010_DT_OFFSET; + + msgOutBufPtr[MessageCount++] = period; + msgOutBufPtr[MessageCount++] = 0; // reserved byte + msgOutBufPtr[MessageCount++] = offset; + msgOutBufPtr[MessageCount++] = width; + + // set DT transfers only for 80MT/sec + msgOutBufPtr[MessageCount++] = (period == 9) ? 2 : 0; + } + } + else // not doing PPR, do WDTR and SDTR + { + // Decide if narrow/wide negotiations are needed + if ( (!OS_ReqSns && (((!(luFlgs & LF_NARROW_NEG_DONE) && dis_sync) || + (!(luFlgs & LF_WIDE_NEG_DONE) && !dis_sync)) && + !(luFlgs & LF_WIDE_NEG_PENDING))) || wide_OSRS ) + { + // fill in the parameters for WDTR extended message + msgOutBufPtr[MessageCount++] = SCSIMESS_EXTENDED_MESSAGE; + msgOutBufPtr[MessageCount++] = 2; // 2 message bytes + msgOutBufPtr[MessageCount++] = SCSIMESS_WIDE_DATA_REQUEST; + + width = 0; // initialize to narrow + + if ( OS_ReqSns ) // doing OS issued request sense + { + // set flag to indicate wide negotiation done + SrbExtension->SrbExtFlags |= LF_OSRS_WIDE_DONE; + // see if we are already in wide, if so negot wide + if ( DeviceExtension->dxp[target] & ENABLE_WIDE ) + width = 1; + } + else // normal negotiations + { + // indicate narrow or wide negotiation is pending + DeviceExtension->LuFlags[target] |= LF_WIDE_NEG_PENDING; + // set narrow or wide pending flag for this I/O + SrbExtension->SrbExtFlags |= LF_WIDE_NEG_PENDING; + + // setup for narrow or wide depending on dis_sync flag & NVRAM + if ( dis_sync || wide_bits == WIDE_NONE ) + { + DebugPrint((1, "LsiU3(%2x): NarrowNegotiation Requested - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else if (wide_bits == WIDE_16) + { + width = 1; + DebugPrint((1, "LsiU3(%2x): WideNegotiation Requested - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + } + + msgOutBufPtr[MessageCount++] = width; + } + + // else, check on async/sync negotiations + else if ( (((!(luFlgs & LF_ASYNC_NEG_DONE) && dis_sync) || + (!(luFlgs & LF_SYNC_NEG_DONE) && !dis_sync)) && + !(luFlgs & (LF_WIDE_NEG_PENDING + LF_SYNC_NEG_PENDING))) || + sync_OSRS ) + { + // fill in the parameters for SDTR extended message + msgOutBufPtr[MessageCount++] = SCSIMESS_EXTENDED_MESSAGE; + msgOutBufPtr[MessageCount++] = 3; // 3 message bytes + msgOutBufPtr[MessageCount++] = SCSIMESS_SYNCHRONOUS_DATA_REQ; + + // if period is 9, set it to 10 (can't use 9 with SDTR) + if ( period == 9 ) + period = 10; + + // Initialize sync offset to ST maximum + offset = MAX_1010_ST_OFFSET; + + // setup for async or sync depending on dis_sync flag + // or current transfer parameters if doing OS issued request sense + if ( OS_ReqSns ) + { + if ( !(DeviceExtension->dxp[target] & PERIOD_MASK) ) + offset = 0; // currently in async, set offset for async + } + else // normal I/O, set pending flags & check dis_sync flag + { + // indicate async or sync negotiation is pending + DeviceExtension->LuFlags[target] |= LF_SYNC_NEG_PENDING; + // set async or sync pending flag for this I/O + SrbExtension->SrbExtFlags |= LF_SYNC_NEG_PENDING; + // check for disable_sync or async NVRAM setting + if ( dis_sync || period == 0 ) + { + period = 25; // some devices need a non-zero period + offset = 0; + DebugPrint((1, "LsiU3(%2x): AsynchronousNegotiation Requested - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + else + { + DebugPrint((1, "LsiU3(%2x): SynchronousNegotiation Requested - Target: %x\n", + DeviceExtension->SIOPRegisterBase, target)); + } + } + + msgOutBufPtr[MessageCount++] = period; + msgOutBufPtr[MessageCount++] = offset; + } + } // end of if do_PPR + + // move buffer to Scripts RAM if hostSvdt is false + if ( !hostSvdt && (MessageCount > initCount) ) + { + msgOutBufPtr = &SrbExtension->svdt->msgOutBuf[initCount]; + msgOutBufSR = &DeviceExtension->localSvdt->msgOutBuf[initCount]; + for ( i = initCount; i < MessageCount; i++) + StorPortWriteRegisterUchar( DeviceExtension, msgOutBufSR++, + *(msgOutBufPtr++)); + } + + return (MessageCount); +} // StartNegotiations + + +VOID +StartNVConfigRequest( + PSCSI_REQUEST_BLOCK Srb, + PHW_DEVICE_EXTENSION DeviceExtension + ) + +/*++ + +Routine Description: + + This procedure puts an entry on the start queue to perform an NVConfig + IOCTL task (either read or write NVRAM). ProcessNVConfigIoctl is the + companion routine that performs the task. + +Arguments: + + Srb - Pointer to the request to be started. + + DeviceExtension - Pointer to the device extension for this adapter. + +Return Value: + + None + +--*/ + +{ + ULONG Length; + ULONG svdtPAdd; + ULONG index, svdtMove; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PSVARS_DESCRIPTOR_TABLE svdtPtr; + + // make sure start queue isn't full + index = DeviceExtension->ioStartQIndex; + if (DeviceExtension->ioStartQueue[index].svdtPhysSem & SVDT_SEM_MASK) + { + DebugPrint((3,"StartNVConfigRequest: Start Queue Full... \n")); + Srb->SrbStatus = SRB_STATUS_BUSY; + // notify port driver of adapter busy status + // resume IO's after 20 requests have completed + StorPortBusy( DeviceExtension, 20); + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + return; + } + svdtMove = MEMORY_MOVE_CMD + + FIELD_OFFSET(SVARS_DESCRIPTOR_TABLE, iovList); + + // align svdt on quadword boundary, if necessary + svdtPtr = &SrbExtension->svarsDescriptorTable; + if ( (ULONG_PTR)(svdtPtr) & 0x00000007 ) + svdtPtr = (PSVARS_DESCRIPTOR_TABLE)((ULONG_PTR)svdtPtr + 4); + SrbExtension->svdt = svdtPtr; + + // get physical address of svdt in system memory + svdtPAdd = StorPortConvertPhysicalAddressToUlong( + StorPortGetPhysicalAddress(DeviceExtension, NULL, + (PVOID)svdtPtr, &Length)); + +#ifdef _WIN64 + // context is physical address of svdt, save Srb in svdt + svdtPtr->context = svdtPAdd; + svdtPtr->Srb = Srb; +#else + // context is Srb address + svdtPtr->context = (ULONG)Srb; +#endif + + DebugPrint((3, "LsiU3(%2x) StartNVConfigRequest: Starting NVConfig IOCTL request\n", + DeviceExtension->SIOPRegisterBase )); + + // insert this command into the start queue + + index = DeviceExtension->ioStartQIndex; + DeviceExtension->ioStartQueue[index].svdtMoveCmd = svdtMove; + // write of svdtPhysSem must be done last + DeviceExtension->ioStartQueue[index].svdtPhysSem = svdtPAdd | SVDT_SEM_NVCONFIG; + + WRITE_SIOP_UCHAR(ISTAT0, ISTAT_SIGP); + + index++; + if (index == START_Q_DEPTH) + { + index = 0; + } + DeviceExtension->ioStartQIndex = index; + +} // StartNVConfigRequest + + +VOID +StartSCSIRequest( + PSCSI_REQUEST_BLOCK Srb, + PHW_DEVICE_EXTENSION DeviceExtension + ) + +/*++ + +Routine Description: + + This procedure starts a request if possible, and also checks if + negotiations need to be started. This routine is called by StartIo and + most of the I/O processing has already been done previously in BuildIo. + +Arguments: + + Srb - Pointer to the request to be started. + + DeviceExtension - Pointer to the device extension for this adapter. + +Return Value: + + None + +--*/ + +{ + UCHAR qTag, trackEntry; + ULONG svdtPAdd, index, svdtMove, tagIndex, trackFIFO; + PSRB_EXTENSION SrbExtension = Srb->SrbExtension; + PSVARS_DESCRIPTOR_TABLE svdtPtr; + PIO_TRACK_ENTRY pEntry; + + // check for ResetActive + if ( DeviceExtension->ResetActive ) + { + // return the I/O with Busy status + DebugPrint((3,"StartSCSIRequest: ResetActive, returning Busy... \n")); + Srb->SrbStatus = SRB_STATUS_BUSY; + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + return; + } + + // make sure start queue isn't full + index = DeviceExtension->ioStartQIndex; + if (DeviceExtension->ioStartQueue[index].svdtPhysSem & SVDT_SEM_MASK) + { + DebugPrint((3,"StartSCSIRequest: Start Queue Full... \n")); + // return the I/O with Busy status + Srb->SrbStatus = SRB_STATUS_BUSY; + // notify port driver of adapter busy status + // resume IO's after 20 requests have completed + StorPortBusy( DeviceExtension, 20); + StorPortNotification( RequestComplete, DeviceExtension, Srb ); + return; + } + + // get svdtMove command and svdt physical address from svdt + svdtPtr = SrbExtension->svdt; + svdtMove = svdtPtr->svdtMoveCmd; + svdtPAdd = svdtPtr->sysSvdtPhys; + + // get next free I/O tracking entry index + trackFIFO = DeviceExtension->TrackFree; + trackEntry = DeviceExtension->IoTrackFIFO[trackFIFO++]; + // check for index wrap + if ( trackFIFO == START_Q_DEPTH ) + trackFIFO = 0; + // save index + DeviceExtension->TrackFree = trackFIFO; + // put this I/O into the tracking array + pEntry = &DeviceExtension->IoTrackArray[trackEntry]; +#if DBG + if ( pEntry->Srb ) + DebugPrint((3, "LsiU3(%2x) SRB is not NULL - SRB: %x\n", + DeviceExtension->SIOPRegisterBase, pEntry->Srb)); + +#endif + pEntry->Srb = Srb; + pEntry->target = Srb->TargetId; + pEntry->lun = Srb->Lun; + // save entry index in SrbExtension + SrbExtension->trackEntry = trackEntry; + + // assign driver determined queue tag value (if queue action enabled) + if ( Srb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE ) + { + // get next free queue tag value + tagIndex = DeviceExtension->QTagFree; + qTag = DeviceExtension->QTagFIFO[tagIndex++]; + // check for index wrap + if ( tagIndex == START_Q_DEPTH ) + tagIndex = 0; + // save index + DeviceExtension->QTagFree = tagIndex; + // put queue tag value in message bytes and save in SrbExtension + svdtPtr->msgOutBuf[2] = qTag; + // put nexus entry address into svdt + svdtPtr->nexusEntryPhys = DeviceExtension->ITQnexusTablePhys + + (qTag * 8); + // save queue tag in tracking array + pEntry->queueTag = qTag; + } + + // insert this command into the start queue + DeviceExtension->ioStartQueue[index].svdtMoveCmd = svdtMove; + // NOTE: write of address/semaphore must be done last + DeviceExtension->ioStartQueue[index].svdtPhysSem = svdtPAdd | SVDT_SEM_START; + + WRITE_SIOP_UCHAR(ISTAT0, ISTAT_SIGP); + + index++; + if (index == START_Q_DEPTH) + { + index = 0; + } + DeviceExtension->ioStartQIndex = index; + +} // StartSCSIRequest + + +VOID +StartSIOP( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ ULONG ScriptPhysAddr + ) +/*++ + +Routine Description: + + This routine starts the scripts at the instruction whose physical + address is passed to it. + +Arguments: + + DeviceExtension - Supplies the device Extension for the SCSI bus adapter. + ScriptPhysAddr - Supplies the address of the script routine to start. + +Return Value: + + None + +--*/ + +{ + WRITE_SIOP_ULONG( DSP, ScriptPhysAddr); + +} // StartSIOP + + +VOID +doneQRemove( + PHW_DEVICE_EXTENSION DeviceExtension, + UCHAR IntStatus + ) +/*++ + +Routine Description: + + This function removes a descriptor table pointer from the completion queue + and processes the completed command. + +Arguments: + + DeviceExtension - Pointer to the device extension for this adapter. + + IntStatus - Value of ISTAT0 when ISR was entered. + +Return Value: + + none + +--*/ + +{ + ULONG index, statLen; +#ifdef _WIN64 + STOR_PHYSICAL_ADDRESS svdtPhys; + PSVARS_DESCRIPTOR_TABLE svdtPtr; +#else + PSCSI_REQUEST_BLOCK Srb; +#endif + + // NOTE: Do NOT clear IntFly until processing all entries on the done + // queue. Scripts test IntFly and will post one entry without checking + // that the entry is empty. + + // Load local copy of ioDoneQIndex + index = DeviceExtension->ioDoneQIndex; + + // we loop on completing commands until the done_queue is empty + do { + +#ifdef _WIN64 + while ((svdtPhys.LowPart = DeviceExtension->ioDoneQueue[index].context) != 0) { + + // get virtual svdt address + svdtPhys.HighPart = 0; + svdtPtr = StorPortGetVirtualAddress(DeviceExtension, svdtPhys); + if ( svdtPtr ) + { + // get active request from svdt and complete the command + DeviceExtension->ActiveRequest = svdtPtr->Srb; + // get the status/true transfer length from the done queue entry + statLen = DeviceExtension->ioDoneQueue[index].statXferLen; + ProcessCommandComplete(DeviceExtension, statLen); + } + else + { + // bad svdt virtual address, log controller error, don't complete + StorPortLogError(DeviceExtension, NULL, 0, 0, 0, + SP_INTERNAL_ADAPTER_ERROR, 0); + } +#else + while ((Srb = (PSCSI_REQUEST_BLOCK)DeviceExtension->ioDoneQueue[index].context) != NULL) { + + // get the status/true transfer length from the done queue entry + statLen = DeviceExtension->ioDoneQueue[index].statXferLen; + + // set active pointers + DeviceExtension->ActiveRequest = Srb; + + ProcessCommandComplete(DeviceExtension, statLen); +#endif + + // clear queue entry + DeviceExtension->ioDoneQueue[index].context = 0; + + index++; + if (index == DONE_Q_DEPTH) + { + index = 0; + } + + } //while + + // clear INT FLY after removing all items from the queue + WRITE_SIOP_UCHAR(ISTAT0, IntStatus); + + // check the current queue entry to see if scripts posted to it after + // we were done checking. Need to do this in case scripts post an + // entry just before we clear IntFly. If we don't check, we could + // leave an entry sitting on the queue with no IntFly. + } while (DeviceExtension->ioDoneQueue[index].context); + + // Save local copy of index into ioDoneQIndex + DeviceExtension->ioDoneQIndex = index; + +} // doneQRemove + + +VOID +UpdateStartQDesc( + _In_ PHW_DEVICE_EXTENSION DeviceExtension, + _In_ PSCSI_REQUEST_BLOCK Srb + ) +/*++ + +Routine Description: + + This routine updates the device descriptors for all oustanding + commands in the start queue for this device id. This is necessary + to make sure commands queued after a command which does negotiations + all have the proper dxp data. + +Arguments: + + DeviceExtension - Supplies a pointer to the device extension for the + interrupting adapter. + + Srb - Pointer to the current Scsi request block + +Return Value: + + None + +--*/ + +{ + UCHAR id, target; + ULONG i, svdtPhys, new_dxp; + PSVARS_DESCRIPTOR_TABLE svdt; + STOR_PHYSICAL_ADDRESS svdtScsiPhys; + + // setup local variables + target = Srb->TargetId; + new_dxp = DeviceExtension->dxp[target]; + svdtScsiPhys.HighPart = 0; // setup for getting virtual addresses + + // search through start queue looking at all active I/O's which + // are for this device id + for (i = 0; i < START_Q_DEPTH; i++) + { + // get svdt physical address + semaphore, check for start semaphore + svdtPhys = DeviceExtension->ioStartQueue[i].svdtPhysSem; + if ( svdtPhys & SVDT_SEM_START ) + { + // mask off semaphore, store in scsi_physical_address structure + svdtScsiPhys.LowPart = svdtPhys & SVDT_PHYS_MASK; + + // convert physical svdt addres to virtual + svdt = (PSVARS_DESCRIPTOR_TABLE) + StorPortGetVirtualAddress(DeviceExtension, svdtScsiPhys); + + // check for valid virtual address + if ( svdt ) + { + // extract device id from current dxp + id = (UCHAR)(svdt->deviceDescriptor.count >> 16); + + // check if I/O is for this target + if ( id == target ) + { + // update device descriptor with new dxp parameters + svdt->deviceDescriptor.count = new_dxp; + } + } + } + } // for + +} // UpdateStartQDesc + + +// start of NVRAM useage code +// NVRAM_CODE +/* The following procedures are used to simplify reading of the nvram code. + * + * data_mask - This is the GPREG bit used as a data line. + * clock_mask - This is the GPREG bit used as a clock line. + */ + +void data_output( PHW_DEVICE_EXTENSION DeviceExtension) +{ + WRITE_SIOP_UCHAR( GPCNTL, (UCHAR)(READ_SIOP_UCHAR( GPCNTL ) + & (~DeviceExtension->data_mask)) ) +} + +void data_input( PHW_DEVICE_EXTENSION DeviceExtension) +{ + WRITE_SIOP_UCHAR( GPCNTL, (UCHAR)(READ_SIOP_UCHAR( GPCNTL ) + | DeviceExtension->data_mask) ) +} + +void set_data( PHW_DEVICE_EXTENSION DeviceExtension) +{ + WRITE_SIOP_UCHAR( GPREG, (UCHAR)(READ_SIOP_UCHAR( GPREG ) + | DeviceExtension->data_mask) ) +} + +void reset_data( PHW_DEVICE_EXTENSION DeviceExtension) +{ + WRITE_SIOP_UCHAR( GPREG, (UCHAR)(READ_SIOP_UCHAR( GPREG ) + & (~DeviceExtension->data_mask)) ) +} + +void set_clock( PHW_DEVICE_EXTENSION DeviceExtension) +{ + WRITE_SIOP_UCHAR( GPREG, (UCHAR)(READ_SIOP_UCHAR( GPREG ) + | DeviceExtension->clock_mask) ) +} + +void reset_clock( PHW_DEVICE_EXTENSION DeviceExtension) +{ + WRITE_SIOP_UCHAR( GPREG, (UCHAR)(READ_SIOP_UCHAR( GPREG ) + & (~DeviceExtension->clock_mask)) ) +} + +/* BOOLEAN NvmDetect( PHW_DEVICE_EXTENSION DeviceExtension ) + * + * Input: + * + * DeviceExtension - Pointer to the device extension for this adapter. + * + * Returns: + * + * BOOLEAN - SUCCESS if NVM was detected + * FAILURE if NVM was not detected + * + * Purpose: + * + * This routine is used to test the adapter to see if NVM is installed on + * the GPIO pins of the 1010 chip. + */ + + +BOOLEAN NvmDetect( PHW_DEVICE_EXTENSION DeviceExtension ) +{ + UINT flag; + UINT retries; + UCHAR dmask = DeviceExtension->data_mask; + UCHAR cmask = DeviceExtension->clock_mask; + + /* Check for no NVM access flag (set via PCI Subsystem ID). + * If set, return with FAILURE. + */ + + if (DeviceExtension->DeviceFlags & DFLAGS_NO_NVM_ACCESS) + return( FAILURE ); + + /* Turn the data & clock lines into outputs and turn off H/W LED, + * then send a stop signal to the I2C chip to reset it to a known state. + */ + + WRITE_SIOP_UCHAR( GPCNTL, (UCHAR)(READ_SIOP_UCHAR(GPCNTL) & + (~(dmask | cmask | GPCNTL_LED_CNTL))) ); + NvmSendStop(DeviceExtension); /* Reset the I2C chip */ + + /* Attempt to issue a read for retries number of times. If the ACK is not + * received, then return that the I2C chip is not present or not + * functional. + */ + + flag = 1; + retries = 100; + + do + { + NvmSendStart(DeviceExtension); + /* Send a dummy write 1010 | A2 A1 A0 | Write */ + } while ( --retries && (NvmSendData( DeviceExtension, 0xA0 | 0x00 | 0x00 ) != 0x00) ); + + if (retries != 0) + { + flag = NvmSendData( DeviceExtension, 0x00 ); /* Address zero */ + NvmSendStart(DeviceExtension); + /* 1010 | A2 A1 A0 | Read */ + flag += NvmSendData( DeviceExtension, 0xA0 | 0x00 | 0x01 ); /* read */ + (void)NvmReadData(DeviceExtension); + NvmSendNoAck(DeviceExtension); /* Also sends stop */ + } + + /* Turn the clock back into an input signal so that the I2C won't + * recognize our LED line (same as the data line) toggling. + * Re-enable the H/W control of the LED. + */ + + WRITE_SIOP_UCHAR( GPCNTL, (UCHAR)((READ_SIOP_UCHAR( GPCNTL ) + & (~dmask)) | (cmask | GPCNTL_LED_CNTL) )); + + return( (flag == 0) ? SUCCESS : FAILURE ); +} + +/* void NvmSendStop( PHW_DEVICE_EXTENSION ) + * + * Input: + * + * DATA line is an output + * CLOCK line is an output + * + * Output: + * + * An I2C 'stop' signal is sent. + * DATA line is asserted + * CLOCK line is deasserted + * + * Returns + * + * NONE + * + * Purpose: + * + * This routine is used to send an I2C stop signal. + */ + +void NvmSendStop( PHW_DEVICE_EXTENSION DeviceExtension ) +{ + reset_data(DeviceExtension); + StorPortStallExecution(10L); + set_clock(DeviceExtension); + StorPortStallExecution(10L); + set_data(DeviceExtension); + StorPortStallExecution(10L); + reset_clock(DeviceExtension); +} + + +/* void NvmSendStart( PHW_DEVICE_EXTENSION ) + * + * Input: + * + * DATA line is an output + * CLOCK line is an output + * + * Output: + * + * An I2C 'start' signal is sent. + * DATA line is deasserted + * CLOCK line is deasserted + * + * Returns + * + * NONE + * + * Purpose: + * + * This routine is used to send an I2C start signal. + */ + +void NvmSendStart( PHW_DEVICE_EXTENSION DeviceExtension ) +{ + set_data(DeviceExtension); + StorPortStallExecution(10L); + set_clock(DeviceExtension); + StorPortStallExecution(10L); + reset_data(DeviceExtension); + StorPortStallExecution(10L); + reset_clock(DeviceExtension); +} + +/* UINT NvmSendData( PHW_DEVICE_EXTENSION, UINT Value ) + * + * Input: + * + * UINT Value - This is the data value to send (lower 8 bits only) + * + * ??? + * + * Output: + * + * ??? + * + * Returns + * + * UINT - == 0 if no acknowledge signal is present. + * != 0 if an acknowledge signal is present. + * + * Purpose: + * + * This routine is used to send a single data byte to the I2C interface. + */ + +UINT NvmSendData( PHW_DEVICE_EXTENSION DeviceExtension, UINT Value ) +{ + UINT i; + UINT8 bit; + + + for (i = 0, bit = 0x80; i < 8; i++, bit >>= 1) + { + if (Value & bit) + { + set_data(DeviceExtension); + } + else + { + reset_data(DeviceExtension); + } + + StorPortStallExecution(10L); + set_clock(DeviceExtension); + StorPortStallExecution(10L); + reset_clock(DeviceExtension); + } + return( NvmReceiveAck(DeviceExtension) ); +} + +/* UINT8 NvmReadData( PHW_DEVICE_EXTENSION ) + * + * Input: + * + * ??? + * + * Output: + * + * ??? + * + * Returns + * + * UINT8 - The data byte read from the I2C interface. + * + * Purpose: + * + * This routine is used to read a single data byte from the I2C interface. + */ + +UINT8 NvmReadData( PHW_DEVICE_EXTENSION DeviceExtension ) +{ + UINT i; + UINT8 value, bit; + UCHAR dmask = DeviceExtension->data_mask; + + value = 0; + data_input(DeviceExtension); + for (i = 0; i < 8; i++) + { + StorPortStallExecution(10L); + set_clock(DeviceExtension); + StorPortStallExecution(10L); + + /* Read in the next bit and shift it into place. + * + * NOTE: Need to check which line is data_mask. If not bit 1, then + * we need to shift the data bit to bit 1 before or'ing it in. + */ + + bit = READ_SIOP_UCHAR( GPREG ) & dmask; + if (dmask == 0x02) // if data in bit 2 need to shift right 1 + bit >>= 1; + value = (UINT8)(value << 1) | bit; + reset_clock(DeviceExtension); + } + data_output(DeviceExtension); + return( value ); +} + +/* void NvmSendAck( PHW_DEVICE_EXTENSION ) + * + * Input: + * + * ??? + * + * Output: + * + * ??? + * + * Returns + * + * NONE + * + * Purpose: + * + * This routine is used to send an acknowledge signal to the I2C part. + */ + +void NvmSendAck( PHW_DEVICE_EXTENSION DeviceExtension ) +{ + StorPortStallExecution(10L); + reset_data(DeviceExtension); + set_clock(DeviceExtension); + StorPortStallExecution(10L); + reset_clock(DeviceExtension); + reset_data(DeviceExtension); +} + +/* UINT NvmReceiveAck( PHW_DEVICE_EXTENSION ) + * + * Input: + * + * ??? + * + * Output: + * + * ??? + * + * Returns + * + * UINT - == 0 if no acknowledge signal is present. + * != 0 if an acknowledge signal is present. + * + * Purpose: + * + * This routine is used to check for an acknowledge signal from the I2C + * part. + */ + +UINT NvmReceiveAck( PHW_DEVICE_EXTENSION DeviceExtension ) +{ + UINT status; + + + data_input(DeviceExtension); + StorPortStallExecution(10L); + set_clock(DeviceExtension); + status = READ_SIOP_UCHAR( GPREG ) & DeviceExtension->data_mask; + StorPortStallExecution(10L); + reset_clock(DeviceExtension); + data_output(DeviceExtension); + return( status ); +} + +/* void NvmSendNoAck( PHW_DEVICE_EXTENSION ) + * + * Input: + * + * ??? + * + * Output: + * + * ??? + * + * Returns + * + * NONE + * + * Purpose: + * + * This routine is used to send a 'no acknowledge' signal to the I2C part. + */ + +void NvmSendNoAck( PHW_DEVICE_EXTENSION DeviceExtension) +{ + StorPortStallExecution(10L); + set_data(DeviceExtension); + set_clock(DeviceExtension); + StorPortStallExecution(10L); + reset_clock(DeviceExtension); + reset_data(DeviceExtension); + NvmSendStop(DeviceExtension); +} + + +/* MEMORY_STATUS HwReadNonVolatileMemory( PHW_DEVICE_EXTENSION DeviceExtension, + * UINT8 *Buffer, UINT Offset, + * UINT Length ) + * + * Input: + * + * PHW_DEVICE_EXTENSION DevcieExtesnion - The adapter whose NVM is being read. If + * the ACF_NO_NON_VOLATILE_MEMORY bit in the Public.ControlFlags field + * is set, then it is illegal to call this routine. + * + * UINT8 far *Buffer - The data buffer in which to store the data being + * accessed. This buffer must be Length UINT8 elements in size. + * + * UINT Offset - The non-volatile memory offset to start reading at. + * + * UINT Length - The number of UINT8 elements to read from the NVM. + * + * Output: + * + * UINT8 far *Buffer - If this routine returns MS_GOOD, then this buffer + * is filled with Length UINT8 elements from the NVM. + * + * Returns: + * + * MS_GOOD - If the operation completed successfully. + * + * Another MEMORY_STATUS - If the operation failed for some reason. + * + * Purpose: + * + * This routine is used to read the non-volatile memory of a particular + * adapter. + */ + +MEMORY_STATUS HwReadNonVolatileMemory( PHW_DEVICE_EXTENSION DeviceExtension, + UINT8 *Buffer, UINT Offset, UINT Length ) +{ + UINT i; + UINT nvmAddress; + UCHAR dmask = DeviceExtension->data_mask; + UCHAR cmask = DeviceExtension->clock_mask; + + + /* Make sure that the requested addresses are in range */ + + if (Offset + Length > 2048) + { + return( MS_ILLEGAL_ADDRESS ); + } + + + /* Turn the data & clock lines into outputs and turn off H/W LED, + * then send a stop signal to the I2C chip to reset it to a known state. + */ + + WRITE_SIOP_UCHAR( GPCNTL, (UCHAR)(READ_SIOP_UCHAR(GPCNTL) & + (~(dmask | cmask | GPCNTL_LED_CNTL))) ); + NvmSendStop(DeviceExtension); // Reset the I2C chip + + /* Now read in all of the requested data */ + + nvmAddress = 0xA0 | ((Offset & 0x700) >> 7); + do + { + NvmSendStart(DeviceExtension); + } while ( NvmSendData( DeviceExtension, nvmAddress | 0x00 ) != 0x00 ); // dummy write + + (void)NvmSendData( DeviceExtension, Offset & 0x00FF ); // address + NvmSendStart(DeviceExtension); + (void)NvmSendData( DeviceExtension, nvmAddress | 0x01 ); // read + + *Buffer = NvmReadData(DeviceExtension); + for (i = 1; i < Length; i++) + { + NvmSendAck(DeviceExtension); + Buffer++; + *Buffer = NvmReadData(DeviceExtension); + } + NvmSendNoAck(DeviceExtension); // Also sends Stop + + /* Turn the clock back into an input signal so that the I2C won't + * recognize our LED line (same as the data line) toggling. + * Re-enable the H/W control of the LED. + */ + + WRITE_SIOP_UCHAR( GPCNTL, (UCHAR)((READ_SIOP_UCHAR( GPCNTL ) + & (~dmask)) | (cmask | GPCNTL_LED_CNTL) )); + + return( MS_GOOD ); +} + + +/* void InvalidateNvmData(PHW_DEVICE_EXTENSION DeviceExtension) + * + * Input: + * + * PHW_DEVICE_EXTENSION DevcieExtesnion - The adapter whose NVM is being used. + * + * Returns: + * None + * + * Purpose: + * + * This routine is used to set defaults the nv ram fields so the rest + * of the driver can still use them. + */ +void InvalidateNvmData( PHW_DEVICE_EXTENSION DeviceExtension ) +{ + UINT8 WideBits, OffsetValue, i; + UINT16 SyncValue; + USHORT hbaCap = DeviceExtension->hbaCapability; + + if ( hbaCap & HBA_CAPABILITY_WIDE ) + WideBits = WIDE_16; + else + WideBits = WIDE_NONE; + + // Initialize sync period to maximum supported + SyncValue = SYNC_80; + + // Initialize sync offset to DT maximum + OffsetValue = MAX_1010_DT_OFFSET; + + for (i=0; i < HW_MAX_DEVICES; i++) + { + DeviceExtension->DeviceTable[i].SyncPeriodNs = SyncValue; + DeviceExtension->DeviceTable[i].SyncOffset = OffsetValue; + DeviceExtension->DeviceTable[i].WideDataBits = WideBits; + } + + DeviceExtension->HostSCSIId = 0x07; + + DeviceExtension->TerminatorState = TS_CANT_PROGRAM; +} + +/* BOOLEAN RetrieveNvmData( PHW_DEVICE_EXTENSION) + * + * Input: + * + * PHW_DEVICE_EXTENSION DevcieExtesnion - The adapter whose NVM is being read. + * + * + * Returns: + * + * BOOLEAN + * SUCCESS if nvram data is of correct type, correct sumcheck and correct major\minor numbers + * FAILURE if any flaws are found. + * + * + * Purpose: + * + * This routine is used to read the non-volatile memory of a particular + * adapter, verify it as valid and to fill the DeviceExtension fields housed within the + * nvram structure. + */ + BOOLEAN RetrieveNvmData( PHW_DEVICE_EXTENSION DeviceExtension) + { + NVM_HEADER NvmHeader; + NON_VOLATILE_SETTINGS NvmData; + BOOLEAN Status = FAILURE; + + if (HwReadNonVolatileMemory(DeviceExtension, (UINT8 *)&NvmHeader, + (0 + NVMDATAOFFSET), sizeof(NvmHeader)) == MS_GOOD) + { + if (NvmHeader.Type == HT_BOOT_ROM) + { + if (HwReadNonVolatileMemory(DeviceExtension, (UINT8 *)&NvmData, + (sizeof(NvmHeader) + NVMDATAOFFSET), sizeof(NvmData)) == MS_GOOD) + { + if (CalculateCheckSum((UINT8 *)&NvmData, NvmHeader.Length) == NvmHeader.CheckSum) + { + if ( (NvmData.VersionMajor == NVS_VERSION_MAJOR) && + (NvmData.VersionMinor == NVS_VERSION_MINOR) ) + { + // fill host structures with NVM data + FillNvmData( DeviceExtension, &NvmData); + Status = SUCCESS; + } + } + } + } + } + return (Status); +} + +/* UINT16 CalculateCheckSum( UINT8 * PNvmData, UINT16 Length) + * + * Input: + * + * UINT8 * PNvmData Pointer to the NVRAM data just read + * UINT16 Length length of the data to calculate sum check against + * + * + * Returns: + * + * UINT16 returns the 16 bit sum of NVRAM data ( read as all 8 bit members) + * + * + * Purpose: + * + * This routine is used calculate the sum check of the nvram data area to insure + * it is valid before its use. + */ + +UINT16 CalculateCheckSum(UINT8 * PNvmData, UINT16 Length) +{ + UINT16 i; + UINT16 CheckSum = 0; + + for ( i = 0; i < Length; i++, PNvmData++) + CheckSum += *PNvmData; + + return ( CheckSum); + +} + +/* UINT8 CalculateMfgCheckSum( UINT8 * PNvmData, UINT16 Length) + * + * Input: + * + * UINT8 * PNvmData Pointer to the NVRAM data just read + * UINT16 Length length of the data to calculate sum check against + * + * Returns: + * + * UINT8 returns the 16 bit sum of Mfg data (read as all 8 bit members) + * + * Purpose: + * + * This routine is used calculate the sum check of the Mfg data area to + * insure it is valid before its use. + */ + +UINT8 CalculateMfgCheckSum(UINT8 * PNvmData, UINT16 Length) +{ + UINT16 i; + UINT8 CheckSum = 0x55; + + for ( i = 0; i < Length; i++, PNvmData++) + CheckSum += *PNvmData; + + return ( (UINT8)(~CheckSum + 1) ); +} + +/* GPIO Pin Usage Routines - Allow OEM's to tailor the use of GPIO pins via + the Mfg data area in NVRAM */ + +/* VOID RetrieveMfgData( PHW_DEVICE_EXTENSION) + * + * Input: + * + * PHW_DEVICE_EXTENSION DevcieExtesnion - The adapter whose NVM Mfg data + * is being read. + * + * Returns: + * None + * + * Purpose: + * + * This routine is used to read the Mfg data from non-volatile memory of a + * particular adapter, verify it as valid and to fill the DeviceExtension + * GPIO pin usage array. If not found, default GPIO pin settings are + * used. This routine is called only if NVRAM is found. + */ +VOID RetrieveMfgData( PHW_DEVICE_EXTENSION DeviceExtension) +{ + UINT8 MfgDataBuffer[sizeof(NVM_MFG_DATA)]; + PTR_NVM_MFG_DATA ptrMfgData = (PTR_NVM_MFG_DATA)MfgDataBuffer; + UINT8 *ptrGpio = DeviceExtension->Gpio; + + // read mfg data + if (HwReadNonVolatileMemory(DeviceExtension, (UINT8 *)ptrMfgData, + (NVM_OFFSET_MFG_DATA), sizeof(NVM_MFG_DATA)) == MS_GOOD) + { + // read was good, check table length (larger is OK as it may be + // a later version of the table) + if (ptrMfgData->Table.TableLen >= sizeof(ptrMfgData->Table) ) + { + // check mfg data checksum + if (CalculateMfgCheckSum((UINT8 *)&ptrMfgData->Table, + (sizeof(NVM_MFG_DATA) - sizeof(ptrMfgData->Checksum))) == + ptrMfgData->Checksum) + { + // we have good mfg data, fill in the GPIO array + StorPortMoveMemory(ptrGpio, &ptrMfgData->Table, 5); + return; + } + } + } + + // if we get here, we couldn't get the mfg data for some reason + // just use defaults. + ptrGpio[1] = GPIO_UNUSED; // Active n/a + ptrGpio[2] = GPIO_UNUSED; // Active n/a + ptrGpio[3] = GPIO_HVD_SENSE; // Active Low + ptrGpio[4] = GPIO_FLASH_PROGRAM | 0x80; // Active High +} + +/* setup GPIO pins as inputs or outputs based on their usage */ +void HwInitGpioPins( PHW_DEVICE_EXTENSION DeviceExtension) +{ + UCHAR i, setMask, usage; + PUCHAR pGpio = DeviceExtension->Gpio; + + setMask = 0; // calculate mask for GPCNTL register + for (i = 1; i < 5; i++) + { + usage = pGpio[i] & GPIO_USAGE_MASK; // get usage code + // check for function requiring input pin + if ( !(usage == GPIO_FLASH_PROGRAM || usage == GPIO_TERMINATION) ) + setMask |= 1<<i; + } + + // Write GPCNTL with setMask to enable pins as input/output as appropriate + WRITE_SIOP_UCHAR(GPCNTL, setMask ); +} + +/* find GPIO assigned for a particular usage code */ +char HwFindGpioPin( PHW_DEVICE_EXTENSION DeviceExtension, char usageCode, + PUCHAR ptrActiveLevel ) +{ + char i; + char pin = 0; + UCHAR activeLevel = 0; + PUCHAR pGpio = DeviceExtension->Gpio; + + // Determine which GPIO pin has been defined for the specified usageCode. + // If a match isn't found, return -1 + for (i = 1; i < 5; i++) + { + if ( (pGpio[i] & GPIO_USAGE_MASK) == usageCode ) + { + pin = 1<<i; + activeLevel = pGpio[i] & GPIO_LEVEL_MASK; + break; + } + } + + if (i == 5) + return( -1 ); // No pin is defined for usageCode + + // return activeLevel if supplied pointer is not NULL + if ( ptrActiveLevel != NULL ) + *ptrActiveLevel = activeLevel; + + return( pin ); // return the GPIO pin mask +} + +/* read GPIO pin for a particular usage code */ +char HwReadGpioPin( PHW_DEVICE_EXTENSION DeviceExtension, char usageCode) +{ + char readPin, setting; + UCHAR activeLevel; + + // find the GPIO pin defined for this function + if ( (readPin = HwFindGpioPin( DeviceExtension, usageCode, &activeLevel)) + == -1 ) + return( -1 ); // no pin defined for usageCode + + setting = (READ_SIOP_UCHAR(GPREG) & readPin) ? GPIO_ON : GPIO_OFF; + + // if active level is low, need to reverse value of setting + if (!activeLevel) + setting ^= 1; // xor with 1 reverses setting + + return( setting ); +} + +/* set GPIO pin for a particular usage code to specified value */ +char HwSetGpioPin( PHW_DEVICE_EXTENSION DeviceExtension, char usageCode, + char setting) +{ + char setPin, currentReg; + UCHAR activeLevel; + + // find the GPIO pin defined for this function + if ( (setPin = HwFindGpioPin( DeviceExtension, usageCode, &activeLevel)) + == -1 ) + return( -1 ); // no pin defined for usageCode + + if (!activeLevel) // active low, reverse setting + setting ^= 1; + + currentReg = READ_SIOP_UCHAR(GPREG); // get current GPREG value + if (setting) // if setting is GPIO_ON (true) + currentReg |= setPin; // OR in pin value + else // else (if GPIO_OFF) + currentReg &= ~setPin; // AND off pin value + + WRITE_SIOP_UCHAR(GPREG, currentReg); // write new value to GPREG + + return( 0 ); +} +/* end of GPIO usage routines */ + +/* void NvmPageWrite( PHW_DEVICE_EXTENSION DeviceExtension, + * UINT8 *Buffer, UINT Offset, UINT Pages ) + * + * Input: + * + * PHW_DEVICE_EXTENSION DeviceExtension - The adapter whose NVM is + * being written. + * + * UINT8 *Buffer - This references the data to write. + * + * UINT Offset - This references the offset in the I2C part to start + * writing data at. It must be on a page boundary. + * + * UINT Pages - This is the number of pages to write to the I2C. + * + * Output: + * + * The data is written to the I2C part. + * + * Returns: + * + * NONE + * + * Purpose: + * + * This routine is used to perform an I2C page write with a page size of + * 16 bytes. + */ + +void NvmPageWrite( PHW_DEVICE_EXTENSION DeviceExtension, + UINT8 *Buffer, UINT Offset, UINT Pages ) +{ + UINT pageNum; // Current page + UINT byteNum; // Current byte within the page + UINT nvmAddress; + + for (pageNum = 0; pageNum < Pages; pageNum++) + { + nvmAddress = 0xA0 | ((Offset & 0x700) >> 7); + do + { + NvmSendStart(DeviceExtension); + // Send write and check for an acknowledge + } while ( NvmSendData( DeviceExtension, nvmAddress | 0x00 ) != 0x00 ); + + (void)NvmSendData( DeviceExtension, Offset & 0x00FF ); // address + + for (byteNum = 0; byteNum < 16; byteNum++) + { + (void)NvmSendData( DeviceExtension, *Buffer ); + Buffer++; + } + Offset += 16; + NvmSendStop(DeviceExtension); + } +} + +/* void NvmByteWrite( PHW_DEVICE_EXTENSION DeviceExtension, + * UINT8 *Buffer, UINT Offset, UINT Length ) + * + * Input: + * + * PHW_DEVICE_EXTENSION DeviceExtension - The adapter whose NVM is + * being written. + * + * UINT8 *Buffer - This references the data to write. + * + * UINT Offset - This references the offset in the I2C part to start + * writing data at. + * + * UINT Length - This is the number of bytes to write to the I2C. + * + * Output: + * + * The data is written to the I2C part. + * + * Returns: + * + * NONE + * + * Purpose: + * + * This routine is used to perform an I2C byte write. + */ + +void NvmByteWrite( PHW_DEVICE_EXTENSION DeviceExtension, + UINT8 *Buffer, UINT Offset, UINT Length ) +{ + UINT byteNum; // Current byte number + UINT nvmAddress; + + for (byteNum = 0; byteNum < Length; byteNum++) + { + nvmAddress = 0xA0 | ((Offset & 0x700) >> 7); + do + { + NvmSendStart(DeviceExtension); + // Send write and check for an acknowledge + } while ( NvmSendData( DeviceExtension, nvmAddress | 0x00 ) != 0x00 ); + + (void)NvmSendData( DeviceExtension, Offset & 0x00FF ); // address + (void)NvmSendData( DeviceExtension, *Buffer ); // Data byte + Buffer++; + Offset++; + NvmSendStop(DeviceExtension); + } +} + +/* MEMORY_STATUS HwWriteNonVolatileMemory(PHW_DEVICE_EXTENSION DeviceExtension, + * UINT8 *Buffer, UINT Offset, + * UINT Length ) + * + * Input: + * + * PHW_DEVICE_EXTENSION DeviceExtension - The adapter whose NVM is + * being written. + * + * UINT8 *Buffer - The data buffer from which to write data. This + * buffer must be Length UINT8 elements in size. + * + * UINT Offset - The non-volatile memory offset to start writing at. + * + * UINT Length - The number of UINT8 elements to write to the NVM. + * + * Output: + * + * UINT8 *Buffer - If this routine returns MS_GOOD, then this + * buffer has been written to the NVM. + * + * Returns: + * + * MS_GOOD - If the operation completed successfully. + * + * Another MEMORY_STATUS - If the operation failed for some reason. + * + * Purpose: + * + * This routine is used to write the non-volatile memory of a particular + * adapter. + */ + +MEMORY_STATUS HwWriteNonVolatileMemory( PHW_DEVICE_EXTENSION DeviceExtension, + UINT8 *Buffer, UINT Offset, UINT Length ) +{ + UINT index; + UINT segmentLength; + UCHAR dmask = DeviceExtension->data_mask; + UCHAR cmask = DeviceExtension->clock_mask; + + + /* Make sure that the requested addresses are in range */ + + if ( Offset + Length > 2048) + { + return( MS_ILLEGAL_ADDRESS ); + } + + /* Turn the data & clock lines into outputs and turn off H/W LED, + * then send a stop signal to the I2C chip to reset it to a known state. + */ + + WRITE_SIOP_UCHAR( GPCNTL, (UCHAR)(READ_SIOP_UCHAR(GPCNTL) & + (~(dmask | cmask | GPCNTL_LED_CNTL))) ); + NvmSendStop(DeviceExtension); // Reset the I2C chip + + index = 0; + segmentLength = 16 - (Offset % 16); + if (segmentLength != 16) + { + if (segmentLength > Length) + { + segmentLength = Length; + } + Length -= segmentLength; + + NvmByteWrite(DeviceExtension, &Buffer[index], Offset, segmentLength); + Offset += segmentLength; + index += segmentLength; + } + + if (Length >= 16) + { + NvmPageWrite(DeviceExtension, &Buffer[index], Offset, Length / 16 ); + Offset += Length - (Length % 16); + index += Length - (Length % 16); + Length %= 16; + } + + if (Length != 0) + { + NvmByteWrite(DeviceExtension, &Buffer[index], Offset, Length ); + } + + /* Turn the clock back into an input signal so that the I2C won't + * recognize our LED line (same as the data line) toggling. + * Re-enable the H/W control of the LED. + */ + + WRITE_SIOP_UCHAR( GPCNTL, (UCHAR)((READ_SIOP_UCHAR( GPCNTL ) + & (~dmask)) | (cmask | GPCNTL_LED_CNTL) )); + + return( MS_GOOD ); +} + +// +// +// start of NVS usage code +// +/* BOOLEAN NVSDetect( PHW_DEVICE_EXTENSION DeviceExtension ) + * + * Input: + * + * DeviceExtension - Pointer to the device extension for this adapter. + * + * Returns: + * + * BOOLEAN - SUCCESS if NVS was detected + * FAILURE if NVS was not detected + * + * Purpose: + * + * This routine is used to search through ROM Bios area (C0000-FF000) + * to determine if there is NVS data (copy of our NVRAM data) available. + */ +BOOLEAN NVSDetect( PHW_DEVICE_EXTENSION DeviceExtension ) +{ + UINT offset; + ULONG rawadrs; + UCHAR *tmp; + PUCHAR BiosCodeSpace; + + rawadrs = 0x000C0000; // Start the search at this address. + do + { + // Get a mapped system address to the physical address of a BIOS code + // space area. We'll look through it 2k chunks at a time unless a ROM + // signature is found and it's not ours. + + BiosCodeSpace = (PUCHAR)StorPortGetDeviceBase(DeviceExtension, + Internal, + 0, // must use bus 0 for system memory + StorPortConvertUlongToPhysicalAddress(rawadrs), + 0x800, // BIOS space mapped on 2k boundries + FALSE ); // not in I/O space + + tmp = BiosCodeSpace; + if ( (tmp) && ((tmp[0] == 0x55) && (tmp[1] == 0xaa) && + (tmp[2] != 0x00)) ) + { + // Found a ROM signature at least, is it ours? + // check for 3.X BIOS + if (tmp[12] == 'P' && tmp[13] == 'C') + { + // it has no NVS support + break; + } + + // check for 4.X BIOS + if (tmp[12] == 'P' && tmp[13] == 'X') + { + // Seems to be... 'PX' at offsets 12 & 13 + // figure offset to the PCI Data Struct + offset = (((UINT) tmp[25]) << 8) + tmp[24]; + tmp = BiosCodeSpace + offset; + + // bump offset past the PCI Data Struct & past the + // 2nd pair code ver. nums + offset += 0x1a; + + // offset now is the total offset from the start of this BIOS + // image to the pointer to the 1st of the NVS information + // structures. The ptr/offset stored here & added to the raw + // address we have currently mapped is what we want to keep. + + tmp = BiosCodeSpace + offset; + if ((tmp[0] == 0) && (tmp[1] == 0)) + { + // the pointer/offset is null; No NVS on this platform + break; + } + else + { + // save pointers to start of Bios area and offset to NVS + DeviceExtension->BiosCodeSpacePtr = rawadrs; + DeviceExtension->NVSDataOffset = + ((((ULONG)tmp[1]) << 8) + tmp[0]); + StorPortFreeDeviceBase(DeviceExtension, BiosCodeSpace); + return (SUCCESS); + } + + } + + // did not find our signature, advance to next option ROM + // and continue search. + rawadrs += (ULONG)(BiosCodeSpace[2] * 0x200); + } + else // no option ROM header detected + { + // if not at a 16K boundary, keep checking every 512 bytes + + // For an unknown reason, the call to StorPortGetDeviceBase() + // fails on 0xC0000. However, the below IF will let us continue. + + if ( (rawadrs <= 0xC8000) || (rawadrs & 0x00003FFF) ) + { + rawadrs += 512; + } + else + { + // no option rom at 16K boundary, quit + break; + } + } + + // free current mapping + StorPortFreeDeviceBase( DeviceExtension, (PVOID) BiosCodeSpace ); + + } while (rawadrs < 0x000ff000); + + DeviceExtension->BiosCodeSpacePtr = 0L; + DeviceExtension->NVSDataOffset = 0L; + StorPortFreeDeviceBase(DeviceExtension, BiosCodeSpace); + return (FAILURE); +} + +/* BOOLEAN RetrieveNVSData( PHW_DEVICE_EXTENSION DeviceExtension ) + * + * Input: + * + * DevcieExtesnion - The adapter whose NVM data is to be setup. + * + * + * Returns: + * + * BOOLEAN + * SUCCESS if nvram data is of correct type, correct sumcheck and + * correct major\minor numbers + * FAILURE if any flaws are found. + * + * + * Purpose: + * + * This routine is used to retrieve the copy of non-volatile memory data + * of a particular adapter out of the BIOS code space and to fill the + * DeviceExtension fields housed within the nvram structure. + */ + BOOLEAN RetrieveNVSData( PHW_DEVICE_EXTENSION DeviceExtension ) + { + BOOLEAN Status = FAILURE; + PTR_SINGLE_HBA_NVS pNVS; + UCHAR *tmp; + ULONG offset; + + if ( !(DeviceExtension->NVSDataOffset) ) // if NULL, return FAILURE + return (Status); + + offset = DeviceExtension->NVSDataOffset; // offset to NVS data struct. + + // Get a mapped system address to the BIOS code area found earlier. + // Map the BIOS code + while(TRUE) + { + tmp = (UCHAR *) StorPortGetDeviceBase( DeviceExtension, + Internal, + 0, // must use bus 0 for system memory + StorPortConvertUlongToPhysicalAddress(DeviceExtension->BiosCodeSpacePtr + offset), + (sizeof(SINGLE_HBA_NVS)), + FALSE ); // not in I/O space + + if ( !tmp ) // if it comes back a NULL pointer, exit w/FAILURE + break; + + pNVS = (PTR_SINGLE_HBA_NVS) tmp; // point to NVS data segment + if (pNVS->header1.Type == HT_BOOT_ROM) + { + if ((pNVS->settings.VersionMajor == NVS_VERSION_MAJOR) && + (pNVS->settings.VersionMinor == NVS_VERSION_MINOR)) + { + // this NVS data for this board?? + if (pNVS->IoPort == DeviceExtension->IoPortAddress) + { + // fill host data structures with NVS data + FillNvmData( DeviceExtension, &pNVS->settings); + Status = SUCCESS; + break; + } + else + { + // advance to the next NVS data struct if present. + if ( pNVS->NextHBANVS ) + { + offset = (ULONG)pNVS->NextHBANVS; + StorPortFreeDeviceBase( DeviceExtension, tmp ); + } + else + { + break; + } + } + } + else // not correct major & minor version number + { + break; + } + } + else // not our Boot ROM + { + break; + } + } // end while(TRUE) + if(tmp!=NULL) + { + StorPortFreeDeviceBase( DeviceExtension, (PVOID) tmp ); + } + return (Status); +} + +/* VOID FillNvmData( PHW_DEVICE_EXTENSION, PTR_NON_VOLATILE_SETTINGS) + * + * Input: + * + * PHW_DEVICE_EXTENSION DevcieExtesnion - The adapter whose NVM or NVS + * data is being read. + * + * PTR_NON_VOLATILE_SETTINGS pNVM - Pointer to the NVM or NVS structure. + * + * Returns: + * + * None. + * + * Purpose: + * + * This routine fills in the DeviceExtension fields from the NVRAM or + * NVS data structures. + */ + VOID FillNvmData( PHW_DEVICE_EXTENSION DeviceExtension, + PTR_NON_VOLATILE_SETTINGS pNVM) +{ + USHORT maxid = (SYM_NARROW_MAX_TARGETS - 1); + PVOID SrcBuffer,DestBuffer; + + // get termination state + DeviceExtension->TerminatorState = pNVM->TerminatorState; + // get host SCSI ID, check against board limits + DeviceExtension->HostSCSIId = pNVM->HostScsiId; + if ( DeviceExtension->hbaCapability & HBA_CAPABILITY_WIDE ) + maxid = (SYM_MAX_TARGETS - 1); + if ((DeviceExtension->HostSCSIId > maxid)) + DeviceExtension->HostSCSIId = 0x07; + // move DeviceTable info into DeviceExtension storage + DestBuffer = (PVOID)DeviceExtension->DeviceTable; + SrcBuffer = (PVOID)pNVM->DeviceTable; + StorPortMoveMemory (DestBuffer, SrcBuffer, + (ULONG)sizeof(DeviceExtension->DeviceTable)); +} + + +/* BOOLEAN ReadNVM( PHW_DEVICE_EXTENSION, PVOID, PULONG) + * + * Input: + * + * PHW_DEVICE_EXTENSION DevcieExtesnion - The adapter whose NVM or NVS + * data is being read. + * + * PVOID - Pointer to the receiving data buffer. + * + * PULONG - Pointer to a ULONG to store length of NVM data read. + * + * Returns: + * + * TRUE is successful, FALSE if not. + * + * Purpose: + * + * This routine reads the NVM data into a buffer. + */ + BOOLEAN ReadNVM( PHW_DEVICE_EXTENSION DeviceExtension, PVOID dataBuf, + PULONG ret_length) +{ + NVM_HEADER NvmHeader; + NON_VOLATILE_SETTINGS NvmData; + ULONG length; + + // read NVM header to obtain length + if (HwReadNonVolatileMemory(DeviceExtension, (UINT8 *)&NvmHeader, + NVMDATAOFFSET, sizeof(NvmHeader)) == MS_GOOD) + { + *ret_length = length = NvmHeader.Length; + // read NVRAM into data buffer + if (HwReadNonVolatileMemory(DeviceExtension, (UINT8 *)&NvmData, + (sizeof(NvmHeader) + NVMDATAOFFSET), length) == MS_GOOD) + { + // copy NVM data into IOCTL buffer + StorPortMoveMemory(dataBuf, &NvmData, length); + return(TRUE); + } + } + + return(FALSE); +} + + +/* BOOLEAN WriteNVM( PHW_DEVICE_EXTENSION, PVOID, ULONG) + * + * Input: + * + * PHW_DEVICE_EXTENSION DevcieExtesnion - The adapter whose NVM or NVS + * data is being written. + * + * PVOID - Pointer to the source data buffer. + * + * ULONG - Length of NVM data to write. + * + * Returns: + * + * TRUE is successful, FALSE if not. + * + * Purpose: + * + * This routine writes the NVM data from a buffer. + */ + BOOLEAN WriteNVM( PHW_DEVICE_EXTENSION DeviceExtension, _In_reads_bytes_(length) PVOID dataBuf, + _In_range_(1, sizeof(NON_VOLATILE_SETTINGS)) ULONG length) +{ + NVM_HEADER NvmHeader; + NON_VOLATILE_SETTINGS NvmData; + USHORT checksum; + + + RtlZeroMemory(&NvmData, sizeof(NON_VOLATILE_SETTINGS)); + // move data buffer into NvmData structure + StorPortMoveMemory( &NvmData, dataBuf, length); + // calculate checksum + checksum = CalculateCheckSum((UINT8 *)&NvmData, (USHORT)length); + // write checksum bytes only to NVRAM + if (HwWriteNonVolatileMemory(DeviceExtension, (UINT8 *)&checksum, + FIELD_OFFSET(NVM_HEADER, CheckSum) + NVMDATAOFFSET, + sizeof(checksum)) == MS_GOOD) + { + // write NVRAM data + if (HwWriteNonVolatileMemory(DeviceExtension, (UINT8 *)&NvmData, + (sizeof(NvmHeader) + NVMDATAOFFSET), length) == MS_GOOD) + { + return(TRUE); + } + } + + return(FALSE); +} + + +/******************************************************* +** ** +** set_sync_speed ** +** ** +*******************************************************/ + +UCHAR set_sync_speed(PHW_DEVICE_EXTENSION DeviceExtension, UCHAR period) +{ + USHORT dFlgs; + + dFlgs = DeviceExtension->DeviceFlags; + + // if async (0 period), just return + if ( !period ) + return (period); + + // check for half speed set + if ( (dFlgs & DFLAGS_HALF_SPEED) && (period == 9) ) + period = 10; + + // if not in LVDS mode, period is limited to 20 MB/sec + if ( !(dFlgs & DFLAGS_LVDS_MODE) && (period < 12) ) + period = 12; + + // if we've dropped back from LVDS mode, then limit is 10MB/sec + // (and LVD cable plant may not support Ultra speeds) + if ( (dFlgs & DFLAGS_LVDS_DROPBACK) && (period < 25) ) + period = 25; + + // workaround for 1010-66 errata at Fast-10 + // don't allow Fast-10 rate, drop back to async + if ( (DeviceExtension->hbaCapability & HBA_CAPABILITY_1010_66) && + (period >= 25) ) + period = 0; + + return (period); +} + +/******************************************************* +** ** +** set_1010_clock ** +** ** +*******************************************************/ + +UCHAR set_1010_clock(PHW_DEVICE_EXTENSION DeviceExtension) +{ + UCHAR scntl3Value; + + DeviceExtension->DeviceFlags &= ~DFLAGS_LVDS_MODE; // not using LVDS + + WRITE_SIOP_UCHAR( STEST1, + (UCHAR)(READ_SIOP_UCHAR(STEST1) | STEST1_DOUBLER_ENABLE)); + + // wait at least 100 usec to allow quadruler frequency to lock + StorPortStallExecution(125); + + WRITE_SIOP_UCHAR( STEST3, + (UCHAR)(READ_SIOP_UCHAR(STEST3) | STEST3_HALT_CLOCK)); + + if ((READ_SIOP_UCHAR(STEST4) & STEST4_BUS_TYPE_MASK) == + STEST4_LOWV_DIFF) + { + DeviceExtension->DeviceFlags |= DFLAGS_LVDS_MODE; // use LVDS + } + scntl3Value = 0x70; + + WRITE_SIOP_UCHAR( SCNTL3, scntl3Value ); + + WRITE_SIOP_UCHAR( STEST1, + (UCHAR)(READ_SIOP_UCHAR(STEST1) | STEST1_DOUBLER_SELECT)); + + WRITE_SIOP_UCHAR( STEST3, + (UCHAR)(READ_SIOP_UCHAR(STEST3) & ~STEST3_HALT_CLOCK)); + + return (scntl3Value); +} + + +/******************************************************/ +/* This routine eats any interrupts pending. */ +/******************************************************/ + +BOOLEAN EatInts(PHW_DEVICE_EXTENSION DeviceExtension) +{ + UCHAR dispose; + UCHAR istat; + UCHAR sist0; + UCHAR retries = 100; + +#define DIP 0x01 +#define SIP 0x02 + + istat=READ_SIOP_UCHAR(ISTAT0); + sist0=READ_SIOP_UCHAR(SIST0); + + /* Spin until no DMA or SCSI interrupts left */ + while ( ((istat & (DIP + SIP)) || (sist0 & 0x02)) && retries ) + { + retries--; // decrement retries + + if (sist0 & 0x02) + { + dispose=READ_SIOP_UCHAR(SIST0); + dispose=READ_SIOP_UCHAR(SIST1); + } + + if (istat & SIP) + { + dispose=READ_SIOP_UCHAR(SIST0); + dispose=READ_SIOP_UCHAR(SIST1); + } + + if (istat & DIP) + { + dispose=READ_SIOP_UCHAR(DSTAT); + } + + delay_mils(5); + istat=READ_SIOP_UCHAR(ISTAT0); + sist0=READ_SIOP_UCHAR(SIST0); + } + return(retries ? TRUE : FALSE); +} + +/*****************************************************************************/ +/* delay_mils is used to delay code X amount of milliseconds by +** using the system call of storportstallexecution +** +******************************************************************************/ +void delay_mils( USHORT counter) +{ + USHORT i; + + for ( i = counter; i > 0; i--) + StorPortStallExecution(999); +} + +/* + This routine is part of the defect injection for the StorPortEnablePassive.slic rule. +*/ +BOOLEAN +LsiU3PassiveRoutine( + _In_ PVOID DeviceExtension) +{ + UNREFERENCED_PARAMETER(DeviceExtension); + return TRUE; +} diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.h b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.h new file mode 100644 index 00000000..e5c9a25e --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.h @@ -0,0 +1,194 @@ +/*++ + +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +PARTICULAR PURPOSE. + +Copyright (c) Microsoft Corporation. All rights reserved + +Module Name: + + lsi_u3.h + +Abstract: + + Private header file for lsi_u3.sys modules. This contains private + structure and function declarations as well as constant values which do + not need to be exported. + +Environment: + + kernel mode only + +Notes: + + +Revision History: + + Aug-2010: Added defect injections for StorPort rules, + checked in as fail driver. + +--*/ + + +/* +************************************************************************* +* * +* Copyright 1994-2008 LSI Corporation. All rights reserved. * +* * +************************************************************************/ + + +#ifndef _LSI_U3_ +#define _LSI_U3_ + +#pragma warning(disable: 26165) +#pragma warning(disable: 28159) +#pragma warning(disable: 28183) +#pragma warning(disable: 6001) +#pragma warning(disable: 6262) +#pragma warning(disable: 26006) +#pragma warning(disable: 26007) +#pragma warning(disable: 26045) +#pragma warning(disable: 28930) +#pragma warning(disable: 28931) +#pragma warning(disable: 4152) // nonstandard extension, function/data pointer conversion in expression this is the same issue in all storport Miniport note this feature is supported by Microsoft compiler by not by the ansi compiler + +// SDV role types: +typedef +ULONG +sp_DRIVER_INITIALIZE ( + _In_ PVOID DriverObject, + _In_ PVOID RegistryPath + ); +typedef sp_DRIVER_INITIALIZE *sp_PDRIVER_INITIALIZE; + +sp_DRIVER_INITIALIZE DriverEntry; +HW_INITIALIZE LsiU3HWInitialize; +HW_STARTIO LsiU3StartIo; +HW_INTERRUPT LsiU3ISR; +HW_FIND_ADAPTER LsiU3FindAdapter; +HW_RESET_BUS LsiU3Reset; +HW_ADAPTER_CONTROL LsiU3AdapterControl; +HW_BUILDIO LsiU3BuildIo; +HW_PASSIVE_INITIALIZE_ROUTINE LsiU3PassiveRoutine; // added as part of a defect injection +// ----------------------------------------------------- + +// +// 53C1010 SIOP I/O registers. +// + +typedef struct _SIOP_REGISTER_BASE { + UCHAR SCNTL0; // 00 SCSI control 0 + UCHAR SCNTL1; // 01 SCSI control 1 + UCHAR SCNTL2; // 02 SCSI control 2 + UCHAR SCNTL3; // 03 SCSI control 3 + UCHAR SCID; // 04 SCSI chip ID + UCHAR SXFER; // 05 SCSI transfer + UCHAR SDID; // 06 SCSI destination ID + UCHAR GPREG; // 07 general purpose bits + UCHAR SFBR; // 08 SCSI first byte received + UCHAR SOCL; // 09 SCSI output control latch + UCHAR SSID; // 0a SCSI selector id + UCHAR SBCL; // 0b SCSI bus control lines + UCHAR DSTAT; // 0c DMA status + UCHAR SSTAT0; // 0d SCSI status 0 + UCHAR SSTAT1; // 0e SCSI status 1 + UCHAR SSTAT2; // 0f SCSI status 2 + ULONG DSA; // 10-13 data structure address + UCHAR ISTAT0; // 14 interrupt status 0 + UCHAR ISTAT1; // 15 interrupt status 1 + UCHAR MBOX0; // 16 mail box 0 + UCHAR MBOX1; // 17 mail box 1 + UCHAR CTEST0; // 18 chip test 0 + UCHAR CTEST1; // 19 chip test 1 + UCHAR CTEST2; // 1a chip test 2 + UCHAR CTEST3; // 1b chip test 3 + ULONG TEMP; // 1c-1f temporary stack + UCHAR RESERVED1; // 20 + UCHAR CTEST4; // 21 chip test 4 + UCHAR CTEST5; // 22 chip test 5 + UCHAR CTEST6; // 23 chip test 6 + UCHAR DBC[3]; // 24-26 DMA byte counter + UCHAR DCMD; // 27 DMA command + ULONG DNAD; // 28-2b DMA next address for data + ULONG DSP; // 2c-2f DMA scripts pointer + UCHAR DSPS[4]; // 30-33 DMA scripts pointer save + UCHAR SCRATCHA[4]; // 34-37 general purpose scratch pad A + UCHAR DMODE; // 38 DMA mode + UCHAR DIEN; // 39 DMA interrupt enable + UCHAR SBR; // 3a scratch byte register + UCHAR DCNTL; // 3b DMA control + ULONG ADDER; // 3c-3f sum output of internal adder + UCHAR SIEN0; // 40 SCSI interrupt enable 0 + UCHAR SIEN1; // 41 SCSI interrupt enable 1 + UCHAR SIST0; // 42 SCSI interrupt status 0 + UCHAR SIST1; // 43 SCSI interrupt status 1 + UCHAR RESERVED2; // 44 + UCHAR SWIDE; // 45 SCSI wide residue + UCHAR RESERVED3; // 46 + UCHAR GPCNTL; // 47 general purpose control + UCHAR STIME0; // 48 SCSI timer 0 + UCHAR STIME1; // 49 SCSI timer 1 + UCHAR RESPID0; // 4a response ID low-byte + UCHAR RESPID1; // 4b response ID high-byte + UCHAR STEST0; // 4c SCSI test 0 + UCHAR STEST1; // 4d SCSI test 1 + UCHAR STEST2; // 4e SCSI test 2 + UCHAR STEST3; // 4f SCSI test 3 + UCHAR SIDL[2]; // 50-51 SCSI input data latch + UCHAR STEST4; // 52 SCSI test 4 + UCHAR CSO; // 53 current inbound SCSI offset + UCHAR SODL; // 54-55 SCSI output data latch + UCHAR SODL_LOWER; + UCHAR CCNTL0; // 56 chip control 0 + UCHAR CCNTL1; // 57 chip control 1 + UCHAR SBDL; // 58-59 SCSI bus data lines + UCHAR SBDL_LOWER; + UCHAR CCNTL2; // 5a chip control 2 + UCHAR CCNTL3; // 5b chip control 3 + ULONG SCRATCHB; // 5c-5f general purpose scratch pad B + ULONG SCRATCHC; // 60-63 general purpose scratch pad C + ULONG SCRATCHD; // 64-67 general purpose scratch pad D + ULONG SCRATCHE; // 68-6b general purpose scratch pad E + ULONG SCRATCHF; // 6c-6f general purpose scratch pad F + ULONG SCRATCHG; // 70-73 general purpose scratch pad G + ULONG SCRATCHH; // 74-77 general purpose scratch pad H + ULONG SCRATCHI; // 78-7b general purpose scratch pad I + ULONG SCRATCHJ; // 7c-7f general purpose scratch pad J + ULONG SCRATCHK; // 80-83 general purpose scratch pad K + ULONG SCRATCHL; // 84-87 general purpose scratch pad L + ULONG SCRATCHM; // 88-8b general purpose scratch pad M + ULONG SCRATCHN; // 8c-8f general purpose scratch pad N + ULONG SCRATCHO; // 90-93 general purpose scratch pad O + ULONG SCRATCHP; // 94-97 general purpose scratch pad P + ULONG SCRATCHQ; // 98-9b general purpose scratch pad Q + ULONG SCRATCHR; // 9c-9f general purpose scratch pad R + ULONG MMRS; // a0-a3 memory move read selector + ULONG MMWS; // a4-a7 memory move write selector + ULONG SFS; // a8-ab script fetch selector + ULONG DRS; // ac-af DSA relative selector + ULONG SBMS; // b0-b3 static block move selector + ULONG DBMS; // b4-b7 dynamic block move selector + ULONG DNAD64; // b8-bb DMA next address 64 + UCHAR SCNTL4; // bc SCSI control 4 + UCHAR RESERVED4; // bd + UCHAR AIPCNTL0; // be AIP control 0 + UCHAR AIPCNTL1; // bf AIP control 1 + ULONG PMJAD1; // c0-c3 phase mismatch jump address 1 + ULONG PMJAD2; // c4-c7 phase mismatch jump address 2 + ULONG RBC; // c8-cb remaining byte count + ULONG UA; // cc-cf updated address + ULONG ESA; // d0-d3 entry storage address + ULONG IA; // d4-d7 instruction address + UCHAR SBC[3]; // d8-da SCSI byte count + UCHAR RESERVED5; // db + ULONG CSBC; // dc-df cumulative SCSI byte count + USHORT CRCPAD; // e0-e1 CRC pad byte value + UCHAR CRCCNTL0; // e2 CRC control 0 + UCHAR CRCCNTL1; // e3 CRC control 1 + ULONG CRCDATA; // e4-e7 CRC data +} SIOP_REGISTER_BASE, *PSIOP_REGISTER_BASE; + +#endif diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.rc b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.rc new file mode 100644 index 00000000..c4de704f --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.rc @@ -0,0 +1,60 @@ +/* ------------------------------------------------------------------------- * + * * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF * + * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO * + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A * + * PARTICULAR PURPOSE. * + * * + * Copyright (c) Microsoft Corporation. All rights reserved * + * * + * Module Name : lsi_u3.rc * + * * + * Abstract : Resource script for lsi_u3.sys * + * * + * ------------------------------------------------------------------------- */ + +/* +************************************************************************* +* * +* Copyright 1994-2008 LSI Corporation. All rights reserved. * +* * +************************************************************************/ + +#include <winver.h> + +#include <ntverp.h> + +#include "lsiver.h" + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "LSI Ultra160 SCSI Miniport Driver" + + +#ifdef IA64 +#define VER_INTERNALNAME_STR LSI_VERSION_LABEL " (Windows 7 IA64)" +#elif defined AMD64 +#define VER_INTERNALNAME_STR LSI_VERSION_LABEL " (Windows 7 x64)" +#else +#define VER_INTERNALNAME_STR LSI_VERSION_LABEL " (Windows 7 x86)" +#endif + +#define VER_ORIGINALFILENAME_STR "LSI_U3.SYS" + +#undef VER_COMPANYNAME_STR +#define VER_COMPANYNAME_STR "LSI Corporation" +#define VER_LEGALCOPYRIGHT_YEARS "2008" +#define VER_LEGALCOPYRIGHT_STR "Copyright \251 LSI Corporation " VER_LEGALCOPYRIGHT_YEARS + +#define VER_FILEVERSION LSI_VERSION_MAJOR,LSI_VERSION_MINOR,LSI_VERSION_BUILD,LSI_VERSION_REV +#define VER_FILEVERSION_STR LSI_CMN_VERSION_NUMBER + +// Comment out these next 4 lines for the source base delivered to Microsoft +// for bundling our driver +//#undef VER_PRODUCTNAME_STR +//#define VER_PRODUCTNAME_STR "LSI Ultra160 SCSI Miniport Driver" +//#undef VER_PRODUCTVERSION_STR +//#define VER_PRODUCTVERSION_STR LSI_CMN_VERSION_NUMBER + +#include "common.ver" + diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj new file mode 100644 index 00000000..d1b9a392 --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj @@ -0,0 +1,181 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{85233D28-0D55-441F-A21F-A75655270EC1}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <SupportsPackaging>false</SupportsPackaging> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{BBF416EE-8943-42D0-A5F3-DAAF62F3FDCB}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>Miniport</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>Miniport</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>Miniport</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>Miniport</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>lsi_u3</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>lsi_u3</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>lsi_u3</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>lsi_u3</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\storport.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\storport.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\storport.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);..\inc</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\storport.lib;$(DDK_LIB_PATH)\ntoskrnl.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="lsi_u3.c" /> + <ResourceCompile Include="lsi_u3.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj.Filters b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj.Filters new file mode 100644 index 00000000..51d43f8f --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3.vcxproj.Filters @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{FE117081-70E1-41C8-A729-F3496F4F366B}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{3EBD2AE7-1F95-4C6A-A853-80039B1D5035}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{36D30486-2B2A-473B-86B6-D83356FA1642}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{C2632345-EC91-400B-8AAF-CB7AEA1EE30C}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="lsi_u3.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="lsi_u3.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3_inf.txt b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3_inf.txt Binary files differnew file mode 100644 index 00000000..c8562c36 --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsi_u3_inf.txt diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsidmi.h b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsidmi.h new file mode 100644 index 00000000..567fee1c --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsidmi.h @@ -0,0 +1,80 @@ +/*++ + +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +PARTICULAR PURPOSE. + +Copyright (c) Microsoft Corporation. All rights reserved + +Module Name: + + lsidmi.h + +Abstract: + + Private header file for lsi_u3.sys modules. This contains private + structure and function declarations as well as constant values which do + not need to be exported. + +Environment: + + kernel mode only + +Notes: + + +Revision History: + +--*/ + + +/* +************************************************************************* +* * +* Copyright 1994-2008 LSI Corporation. All rights reserved. * +* * +************************************************************************/ + + +#ifndef _LSIDMI_ +#define _LSIDMI_ + + +// IO Control Codes +// bit 31 of this code must be on to denote it is a user-defined code +#define DMI_GET_DATA 0x80444D49 // last 3 bytes are 'DMI' +#define NVCONFIG_IOCTL 0x804E5643 // last 3 bytes are 'NVC' + +// DMI data structure for retrieval by IOCTL function +// Original structure is version 4.00 (IOCTL Signature) +typedef struct _DMI_DATA +{ + UCHAR DevSpeed[SYM_MAX_TARGETS]; // sync speed as in SYMNVM.H + UCHAR DevWidth[SYM_MAX_TARGETS]; // width in bits + UCHAR MaxAttachments; + UCHAR MaxXferRate; // sync speed as in SYMNVM.H + UCHAR MaxWidth; // width in bits + UCHAR DeviceId; // PCI device ID + UCHAR HW_Revision; // bits 7-4 of CTEST3 >> 4 + UCHAR ScsiBusId; // adapter SCSI ID + UCHAR SignalType; // bits 7-6 of STEST4 >> 6 + UCHAR DriverVersion[80]; // version string as in .rc file +// Version 4.01 adds boolean (uchar) flag for PCI Hot Swap +// Set when power cycle occurs, cleared when IOCTL call reads data + BOOLEAN HotSwap; // TRUE if hot swap has occurred +} DMI_DATA, *PDMI_DATA; + +// SrbBuffer structure to handle IO_Control call +typedef struct { + SRB_IO_CONTROL sic; + UCHAR ucDataBuffer[512]; +} SRB_BUFFER, *PSRB_BUFFER; + +#endif + +// return codes for NVConfig utility +#define SRB_GOOD_ACCESS 0x00000000 +#define SRB_ERROR_NO_NVM 0x00000001 +#define SRB_ERROR_ON_READ 0x00000002 +#define SRB_ERROR_ON_WRITE 0x00000003 diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsinvm.h b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsinvm.h new file mode 100644 index 00000000..0064b03b --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsinvm.h @@ -0,0 +1,429 @@ +/*++ + +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +PARTICULAR PURPOSE. + +Copyright (c) Microsoft Corporation. All rights reserved + +Module Name: + + lsinvm.h + +Abstract: + + Private header file for lsi_u3.sys modules. This contains private + structure and function declarations as well as constant values which do + not need to be exported. + +Environment: + + kernel mode only + +Notes: + + +Revision History: + +--*/ + + +/* +************************************************************************* +* * +* Copyright 1994-2008 LSI Corporation. All rights reserved. * +* * +************************************************************************/ + + +/* + * This include file contains the definitions for the NT driver to read user + * set values in the nvram chip. The driver looks at the HBA ID and scam ID values. + * The structure version number for this code is major -0x00 minor -0x21. + * To get the definitions of the fields look at the SDMS4.0 bootrom include files + * ROMTYPES.H + * ROMPUBLC.H + * ROMSTRUC.H + * ROMSCAM.H + * ROMHW.H + * ROMBIOS.H + */ + +/* If this header file has not been included yet */ +#if !defined LSINVM_H +#define LSINVM_H + +/* Since all data structures must be byte aligned throughout this file, we + * issue the commands to perform that alignment once, and then restore the + * compilers default alignment at the end of this file. + */ + +#pragma pack(1) /* Force byte alignment, MS-C, WATCOM */ + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * Non Volatile Memory types + *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + */ + +/* NVS_VERSION_MAJOR and NVS_VERSION_MINOR are #defined to the revision of the + * main data structure (NON_VOLATILE_SETTINGS) in this document. + */ + +#define NVS_VERSION_MAJOR (0x00) +#define NVS_VERSION_MINOR (0x30) + +#define BI_MAX_HBA 4 +#define HW_MAX_DEVICES 16 +#define HW_MAX_SCAM_DEVICES 4 +#define NVMDATAOFFSET 0x100 + +#define FAILURE (0) +#define SUCCESS (1) + +typedef enum _HEADER_TYPE +{ + HT_BOOT_ROM = 0, + HT_DOS_ASPI = 1, + HT_WINDOWS_ASPI = 2, + HT_NETWARE = 3, + HT_UNIXWARE = 4, + HT_SCO_UNIX = 5, + HT_WINDOWS_NT = 6, + HT_WINDOWS95 = 7, + HT_OS_2 = 8, + HT_SOLARIS = 9, + HT_INTERACTIVE = 10, + HT_NEXTSTEP = 11, + HT_END_MEMORY_BLOCK = 0xFEFE +} HEADER_TYPE; + +typedef unsigned int UINT; +typedef unsigned char UINT8; +typedef unsigned short UINT16; +// need to define UINT32 for NT 4.0 +#if _WIN32_WINNT == 0x0400 +typedef unsigned long UINT32; +#endif + +#define WIDE_NONE (8) +#define WIDE_16 (16) +#define WIDE_32 (32) +#define WIDE_NO_CHANGE (0xFF) + +/* Synchronous speed macros are used to declare a synchronous period for + * an adapter or a device. The values of the macros used are in units of + * nano-seconds, the names of the macros are in mega-transfers per second. + * + * SYNC_NO_CHANGE ==> Defines a SCSI synchronous period entry for no changes in + * the current device synchronous selection. + * + * SYNC_NONE ==> Defines a SCSI synchronous period entry for asynchronous + * operation. + * + * SYNC_5 ==> Defines a SCSI synchronous period entry for 5 + * mega-transfers per second. + * + * SYNC_10 ==> Defines a SCSI synchronous period entry for 10 + * mega-transfers per second. + * + * SYNC_20 ==> Defines a SCSI synchronous period entry for 20 + * mega-transfers per second. + * + * SYNC_40 ==> Defines a SCSI synchronous period entry for 40 + * mega-transfers per second. + * + * SYNC_80 ==> Defines a SCSI synchronous period entry for 80 + * mega-transfers per second. + */ + +#define SYNC_NO_CHANGE (0xFFFF) +#define SYNC_NONE ( 0) +#define SYNC_5 ( 200) +#define SYNC_10 ( 100) +#define SYNC_20 ( 48) +#define SYNC_40 ( 40) +#define SYNC_80 ( 36) + +typedef UINT8 WIDE_PARAMETERS; +typedef USHORT IO_ADDRESS; +typedef UINT32 PHYS_ADDRESS; + +typedef USHORT HBA_FLAGS; +#define HF_SCAM_ENABLED (0x0001) +#define HF_PARITY_ENABLED (0x0002) +#define HF_DISPLAY_VERBOSE_ENABLED (0x0004) +#define HF_NO_NON_VOLATILE_MEMORY (0x0008) + +typedef UINT8 DEVICE_FLAGS; +#define DF_DISCONNECT_ENABLED (0x01) +#define DF_SCAN_ENABLED (0x02) +#define DF_LUNS_ENABLED (0x04) +#define DF_QT_ENABLED (0x08) +#define DF_ALL_FEATURES_ENABLED (DF_DISCONNECT_ENABLED | DF_SCAN_ENABLED | \ + DF_LUNS_ENABLED | DF_QT_ENABLED) + +typedef enum MEMORY_STATUS +{ + MS_GOOD = 0, + MS_ILLEGAL_ADDRESS, + MS_GENERAL_ERROR +} MEMORY_STATUS; + +typedef enum _TERMINATION_STATE +{ + TS_CANT_PROGRAM = 0, + TS_ENABLED = 1, + TS_DISABLED = 2 +} TERMINATION_STATE; + +typedef enum _ADAPTER_TYPE +{ + AT_UNKNOWN = 0, + AT_400A = 1, + AT_406A = 2, + AT_416 = 3, + AT_8XX = 4 +} ADAPTER_TYPE; + +typedef struct _ADAPTER_IO_INFO +{ + USHORT RangeSize; + IO_ADDRESS IoBasePort; +} ADAPTER_IO_INFO, * PTR_ADAPTER_IO_INFO; + +typedef struct _ADAPTER_MEMORY_INFO +{ + PHYS_ADDRESS PhyMemoryBase; + UINT8 *VirtMemoryBase; +} ADAPTER_MEMORY_INFO, * PTR_ADAPTER_MEMORY_INFO; + +typedef struct _ADAPTER_416_INFO +{ + UINT32 DeviceId; + UINT32 SerialNumber; +} ADAPTER_416_INFO, * PTR_ADAPTER_416_INFO; + +typedef struct _ADAPTER_8XX_INFO +{ + USHORT DeviceId; + USHORT VendorId; + UINT8 BusNumber; + UINT8 BusIndex; +} ADAPTER_8XX_INFO, * PTR_ADAPTER_8XX_INFO; + +typedef union _ADAPTER_INFO +{ + ADAPTER_416_INFO Hba416; + ADAPTER_8XX_INFO Hba8xx; + ADAPTER_IO_INFO HbaIo; +/* Can't have the following structure as part of this union: + ADAPTER_MEMORY_INFO HbaMemory; + This is due to it having a pointer address, which becomes 8 bytes + long with a 64-bit OS, causing the compiler offsets to be wrong + compared with the data stored in NVM. It's not used in this driver. +*/ +} ADAPTER_INFO, * PTR_ADAPTER_INFO; + +typedef enum _SCAN_ORDER +{ + SO_LOW_TO_HIGH = 0, + SO_HIGH_TO_LOW = 1 +} SCAN_ORDER; + +typedef enum _REMOVABLE_MEDIA +{ + RM_NO_SUPPORT = 0, + RM_BOOT_DEVICE_ONLY = 1, + RM_MEDIA_INSTALLED_ONLY = 2 +} REMOVABLE_MEDIA; + +typedef struct _HBA_INIT +{ + USHORT Type; + ADAPTER_INFO HbaInfo; + USHORT InitStatus; + IO_ADDRESS IoPort; +} HBA_INIT, * PTR_HBA_INIT; + +typedef struct _DEVICE_TABLE +{ + UINT8 Flags; // 8 bits + UINT8 Reserved; + WIDE_PARAMETERS WideDataBits; // 8 bits + UINT8 SyncOffset; + USHORT SyncPeriodNs; + USHORT Timeout; +} DEVICE_TABLE, * PTR_DEVICE_TABLE; + +typedef struct _SCAM_IDENTIFIER +{ + UINT8 DeviceType[ 2 ]; + char VendorId[ 8 ]; + char VendorSpecific[ 21 ]; + UINT8 Reserved; +} SCAM_IDENTIFIER, * PTR_SCAM_IDENTIFIER; + +typedef enum _SCAM_ID_METHOD +{ + SIM_DEFAULT_METHOD = 0, + SIM_DONT_ASSIGN = 1, + SIM_SET_SPECIFIC_ID = 2, + SIM_USE_ORDER_GIVEN = 3 +} SCAM_ID_METHOD; + +typedef enum _SCAM_STATUS +{ + SS_UNKNOWN = 0, + SS_DEVICE_NOT_FOUND = 1, + SS_ID_NOT_SET = 2, + SS_ID_VALID = 3 +} SCAM_STATUS; + +typedef struct _SCAM_TABLE +{ + USHORT ScamId; + USHORT HowToSetId; + USHORT ScamStatus; + UINT8 ScamTargetId; + UINT8 Reserved; +} SCAM_TABLE, * PTR_SCAM_TABLE; + +typedef struct _NVM_HEADER +{ + USHORT Type; + USHORT Length; + USHORT CheckSum; +} NVM_HEADER, * PTR_NVM_HEADER; + +typedef SCAM_TABLE NVM_SCAM_DATA; +typedef PTR_SCAM_TABLE PTR_NVM_SCAM_DATA; + +typedef struct _NON_VOLATILE_SETTINGS +{ + UINT8 VersionMajor; + UINT8 VersionMinor; + UINT32 BootCrc; + USHORT HbaFlags; + USHORT ScanOrder; + USHORT TerminatorState; + USHORT RemovableMediaSetting; + UINT8 HostScsiId; + UINT8 NumHba; + UINT8 NumDevices; + UINT8 MaxScamDevices; + UINT8 NumValidScamDevices; + UINT8 Reserved; + HBA_INIT HbaInit[ BI_MAX_HBA ]; + DEVICE_TABLE DeviceTable[ HW_MAX_DEVICES ]; + NVM_SCAM_DATA ScamTable[ HW_MAX_SCAM_DEVICES ]; + UINT8 freespace[1024]; // this added by NT so we can read past end + // of the NVRAM structure to get all data + // used for checksum +} NON_VOLATILE_SETTINGS, * PTR_NON_VOLATILE_SETTINGS; + +typedef struct _SINGLE_HBA_NVS +{ + UINT16 NextHBANVS; // offset of next struct in code segment + IO_ADDRESS IoPort; + UINT16 DeviceId; + UINT16 VendorId; + UINT16 BusNumber; + UINT16 BusIndex; + NVM_HEADER header1; + NON_VOLATILE_SETTINGS settings; + NVM_HEADER header2; + +} SINGLE_HBA_NVS, * PTR_SINGLE_HBA_NVS; + + +/* NVM Manufacturing data table definition. This is used for + * GPIO pin usage information. + */ +#define NVM_OFFSET_MFG_DATA (0x40) +#define NVM_LENGTH_MFG_DATA (0x80) + +typedef struct _NVM_MFG_DATA_TABLE +{ + UINT8 TableLen; /* for this structure, TableLen == 5 */ + UINT8 Gpio1; + UINT8 Gpio2; + UINT8 Gpio3; + UINT8 Gpio4; +} NVM_MFG_DATA_TABLE, *PTR_NVM_MFG_DATA_TABLE; + +typedef struct _NVM_MFG_DATA +{ + UINT8 Checksum; + NVM_MFG_DATA_TABLE Table; + /* Manufacturing data table begins at 0x40 and ends at 0xbf + * we calculate the number of bytes that are unused and allocate + * storage for them since they are read and are part of the + * checksum calculation. This structure is normally only used + * during driver initialization. + */ + UINT8 Unused[NVM_LENGTH_MFG_DATA - + sizeof( struct _NVM_MFG_DATA_TABLE ) - + sizeof( UINT8 /* Checksum */ )]; +} NVM_MFG_DATA, *PTR_NVM_MFG_DATA; + +/* Masks for GPIO pin definition byte */ +#define GPIO_USAGE_MASK 0x3f /* Bits 0-5 holds usage code */ + /* Bit 6 is reserved */ +#define GPIO_LEVEL_MASK 0x80 /* Bit 7 active signal level */ +/* Note: The bit that denotes the active signal level is set to 1 + * when the manufacture uses a high signal on the GPIO pin to indicate + * a TRUE or ON condition, whereas the bit is set to 0 if the GPIO pin + * uses a low signal on the GPIO pin to indicate a TRUE or ON condition */ + +/* Defines for the known usage codes for GPIO pins */ +#define GPIO_UNUSED 0 +#define GPIO_FLASH_PROGRAM 1 +#define GPIO_HVD_SENSE 2 +#define GPIO_TERMINATION 3 +#define GPIO_CABLE_SENSE_A 4 +#define GPIO_CABLE_SENSE_B 5 +#define GPIO_TERMINATION_SENSE 6 + +/* Defines for GPIO pins on and off */ +#define GPIO_ON 1 +#define GPIO_OFF 0 + +/* Define some macros to access the offsets of particular portions of this + * data structure. These macros are then used to allow the code to more + * easily program only those parts of non-volatile memory which might have + * changed when the user issues a set NVM call. + */ + +#define NVS_ADAPTER_BEGIN (offsetof(struct _NON_VOLATILE_SETTINGS, HbaFlags)) +#define NVS_ADAPTER_END (offsetof(struct _NON_VOLATILE_SETTINGS, \ + DeviceTable[ 0 ])) +#define NVS_ADAPTER_LENGTH (NVS_ADAPTER_END - NVS_ADAPTER_BEGIN) + +#define NVS_DEVICE_BEGIN(x) (offsetof(struct _NON_VOLATILE_SETTINGS, \ + DeviceTable[(x)])) +#define NVS_DEVICE_END(x) (offsetof(struct _NON_VOLATILE_SETTINGS, \ + DeviceTable[(x)+1])) +#define NVS_DEVICE_LENGTH (sizeof( DEVICE_TABLE )) + +#if HW_MAX_SCAM_DEVICES != 0 + #define NVS_SCAM_BEGIN (offsetof(struct _NON_VOLATILE_SETTINGS, \ + ScamTable[0])) + #define NVS_SCAM_END (sizeof(NON_VOLATILE_SETTINGS)) + #define NVS_SCAM_LENGTH (NVS_SCAM_END - NVS_SCAM_BEGIN) +#endif + +/* NVM_DATA_SIZE defines the number of bytes of data we need to access the + * NVM header structure and the NVM data structure for our ROM. + */ + +#define NVM_DATA_SIZE (sizeof(NVM_HEADER) + sizeof(NON_VOLATILE_SETTINGS)) + +/* We are now done with the requirement of forcing byte alignment on all + * elements so restore the compilers default structure alignment. + */ + +#pragma pack() /* Restore default alignment, MS-C, WATCOM */ + +#endif /* End of if LSINVM_H */ + diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsisiop.h b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsisiop.h new file mode 100644 index 00000000..4dc4521e --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsisiop.h @@ -0,0 +1,415 @@ +/*++ + +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +PARTICULAR PURPOSE. + +Copyright (c) Microsoft Corporation. All rights reserved + +Module Name: + + lsisiop.h + +Abstract: + + Private header file for lsi_u3.sys modules. This contains private + structure and function declarations as well as constant values which do + not need to be exported. + +Environment: + + kernel mode only + +Notes: + + +Revision History: + +--*/ + + +/* +************************************************************************* +* * +* Copyright 1994-2008 LSI Corporation. All rights reserved. * +* * +************************************************************************/ + + + +#ifndef _SYMSIOP_ +#define _SYMSIOP_ + +// +// Define miniport constants. +// + +// Set the next entry to the maximum block size supported (in Kbytes) +#define SYM_MAX_BLOCK_SIZE 256 // max block size in Kbytes + +#define MAX_SYNCH_TABLE_ENTRY 8 // # of entries in synch period array +#define ASYNCHRONOUS_MODE_PARAMS 0x00 // asychronous xfer mode +#define MAX_SG_ELEMENTS ((SYM_MAX_BLOCK_SIZE / 4) + 1) // # SG entries +#define MAX_ABORT_TRIES 100 // max times we will try to abort script +#define ABORT_SCRIPTS_TRIES 5 // overall loop count to aboart scripts +#define ABORT_STALL_TIME 3 // stall time between script abort tries +#define MAX_1010_DT_OFFSET 0x3E // 1010 DT offset - 62 +#define MAX_1010_ST_OFFSET 0x1F // 1010 ST offset - 31 +#define MESSAGE_BUFFER_SIZE 8 // maximum message size +#define RESET_STALL_TIME 30 // length of time bus reset line high +#define POST_RESET_STALL_TIME 1000 // drive recovery time after reset +#define CLEAR_FIFO_STALL_TIME 500 // Time to clear SCSI and DMA fifos +#define MAX_CLEAR_FIFO_LOOP 10 // Number of times in clear loop +#define SYM_MAX_TARGETS 16 +#define SYM_NARROW_MAX_TARGETS 8 +#define MAX_STALL 50000 +#define MAX_XFER_LENGTH 0x00FFFFFF // maximum transfer length per request + +// SCSI message byte for Logical Unit Reset (not in storport.h) +#define SCSIMESS_LOGICAL_UNIT_RESET 0x17 + +// define request sense command length +#define REQ_SNS_CMD_LENGTH 6 + +// define SetupNegotBuf constants +#define SETUP_WIDE_FIRST 0 +#define SETUP_WIDE_TIN 1 +#define SETUP_SYNC_FIRST 2 +#define SETUP_SYNC_CONT 3 +#define SETUP_SYNC_TIN 4 +#define SETUP_PPR_FIRST 5 +#define SETUP_PPR_TIN 6 + +// some more defines for the Performanced enhanced version +#define CLEAR_PERIOD_VALUES 0x00FFFFFF +#define CLEAR_OFFSET_VALUES 0xFFFF0000 +#define DISABLE_WIDE 0xF7FFFFFF +#define ENABLE_WIDE 0x08000000 +#define PERIOD_MASK 0x0000FF00 +// +// SCSI equates and flags not included in SCSI.H +// TODO: Rework code to omit these +// + +#define SCSIMESS_IDENTIFY_DISC_PRIV_MASK 0x40 + +#define CTEST3_WRITE_INVALIDATE 0x01 +#define CTEST3_CLEAR_FIFO 0x04 +#define CTEST3_FLUSH_FIFO 0x08 +#define CTEST4_SHADOW_REG_MODE 0x10 +#define CTEST5_USE_LARGE_FIFO 0x20 +#define CTEST5_BURST 0x04 +#define SGEST0_RD 0x20 + +#define DCMD_WAIT_DISCONNECT 0x48 +#define SSTAT1_ORF 0x40 +#define SSTAT1_OLF 0x20 +#define SSTAT2_ORF 0x40 +#define SSTAT2_OLF 0x20 +#define SBCL_MSG 0x04 +#define SBCL_CD 0x02 +#define SBCL_IO 0x01 +#define DFIFO_LOW_SEVEN 0x7F + +// +// LSI_U3 script interrupt definitions. These values are returned in the +// DSPS register when a script routine completes. +// + +#define SCRIPT_INT_COMMAND_COMPLETE 0x00 // SCSI command complete +#define SCRIPT_INT_SAVE_DATA_PTRS 0x01 // save data ptrs +#define SCRIPT_INT_SAVE_WITH_DISCONNECT 0x02 // combination SDP & disconnect +#define SCRIPT_INT_DISCONNECT 0x03 // disconnect from SCSI bus +#define SCRIPT_INT_RESTORE_POINTERS 0x04 // restore data pointers +#define SCRIPT_INT_SCRIPT_ABORTED 0x05 // SCSI script aborted +#define SCRIPT_INT_TAG_RECEIVED 0x06 // Queue tag message recieved +#define SCRIPT_INT_DEV_RESET_OCCURRED 0x07 // indicates device was reset + // due to wierd phase +#define SCRIPT_INT_DEV_RESET_FAILED 0x08 // indicates above effort + // failed +#define SCRIPT_INT_NVCONFIG_IOCTL 0x09 // NVRAM Config operation +#define SCRIPT_INT_IDE_MSG_SENT 0x0A // initiator detected error +#define SCRIPT_INT_SYNC_NOT_SUPP 0x0B // synchronous not supported +#define SCRIPT_INT_SYNC_NEGOT_COMP 0x0C // synchronous neg complete +#define SCRIPT_INT_IGNORE_WIDE_RESIDUE 0x14 // ignore wide residue received +#define SCRIPT_INT_PPR_NEGOT_COMP 0x15 // PPR neg complete +#define SCRIPT_INT_WIDE_NOT_SUPP 0x1B // wide not supported +#define SCRIPT_INT_WIDE_NEGOT_COMP 0x1C // wide neg complete +#define SCRIPT_INT_INVALID_RESELECT 0x0D // reselecting device returned + // invalid SCSI id. +#define SCRIPT_INT_REJECT_MSG_RECEIVED 0x0E // message reject msg received +#define SCRIPT_INT_INVALID_TAG_MESSAGE 0x0F // target did not send tag +#define SCRIPT_INT_ABORT_OCCURRED 0x10 +#define SCRIPT_INT_ABORT_FAILED 0x11 +#define SCRIPT_INT_CHECK_CONDITION 0x12 // target returned check cond +#define SCRIPT_INT_CA_QUEUE_FULL 0x13 // queue for req sns full +#define SCRIPT_INT_BAD_XFER_DIRECTION 0x20 // data xfer is other direction + + +// +// define LSI_U3 SCSI Script instruction size +// + +#define SCRIPT_INS_SIZE 8 // size of a script instruction + +// +// ISR disposition codes. these codes are returned by ISR subroutines to +// indicate what should be done next. +// + +#define ISR_START_SCRIPT 0x00 // indicates bus is free for new req. +#define ISR_RESTART_SCRIPT 0x01 // indicates script restart necessary +#define ISR_RELOAD_SCRIPT 0x02 // indicates script restart necessary + // with reload of dxp parameters +#define ISR_EXIT 0x03 // indicates no action needed + +// +// Device Extension driver flags. +// + +#define DFLAGS_BUS_RESET 0x0001 // indicates bus was reset internally +#define DFLAGS_IRQ_NOT_CONNECTED 0x0002 // Indicates chip is 'disabled' but + // resources were still assigned. + // (Omniplex problem) +#define DFLAGS_LVDS_MODE 0x0004 // indicates using LVDS signaling + // allowing 40MB/sec transfers +#define DFLAGS_LVDS_DROPBACK 0x0008 // indicates SCSI bus was in LVDS, but + // changed mode due to a SE device + // being added to the bus +#define DFLAGS_SWAP_NVM_LINES 0x0010 // GPIO0 - clock, GPIO1 - data +#define DFLAGS_NO_FLASH_PROG 0x0020 // do not program flash memory +#define DFLAGS_FORCE_NARROW 0x0040 // do not negotiate wide, narrow only +#define DFLAGS_HALF_SPEED 0x0080 // run @ half speed (if Ultra capable + // use 10 Mb/s, if LVDS use 20 Mb/s) +#define DFLAGS_NO_NVM_ACCESS 0x0100 // SSID indicates NVM should not be + // accessed +#define DFLAGS_NVM_FOUND 0x0200 // NVM is present on this device +#define DFLAGS_FORCE_SYNC 0x0400 // ignore DISABLE_SYNC flag when set +#define DFLAGS_64BIT_ADDRESS 0x0800 // use 64-bit DMA addresses, scripts + +// +// Logical Unit flags (track negotiation status) +// + +// this first section is to flag pending negotiations +#define LF_TIN_SYNC_PENDING 0x0001 // sync TIN pending +#define LF_TIN_WIDE_PENDING 0x0002 // wide TIN pending +#define LF_TIN_PPR_PENDING 0x0003 // PPR TIN pending (both sync/wide) +#define LF_SYNC_NEG_PENDING 0x0004 // sync/async negotiation pending +#define LF_WIDE_NEG_PENDING 0x0008 // wide/narrow negotiation pending +#define LF_PPR_NEG_PENDING 0x000C // PPR negot pending (both sync/wide) + +#define LF_ASYNC_NEG_DONE 0x0010 // async negotiation done +#define LF_SYNC_NEG_DONE 0x0020 // sync negotiation done +#define LF_SYNC_NEG_FAILED 0x0040 // sync not supported + +#define LF_NARROW_NEG_DONE 0x0080 // narrow negotiation done +#define LF_WIDE_NEG_DONE 0x0100 // wide negotiation done +#define LF_WIDE_NEG_FAILED 0x0200 // wide not supported + +#define LF_NEG_NEEDED 0x0400 // need to check for negotiations +#define LF_SYNC_NEG_REJECT 0x0800 // sync rejected, never do again +#define LF_PPR_NEG_REJECT 0x1000 // PPR rejected, use WDTR/SDTR +#define LF_DT_XFERS_ON 0x2000 // use dual transition transfers + +// Next 2 flags are used only in SrbExtFlags +#define LF_OSRS_WIDE_DONE 0x0010 // set when OS_RS wide negot is done +#define LF_DISABLE_SYNC 0x0020 // set to disable sync on this I/O + +// +// HBA Capability Flags +// + +#define HBA_CAPABILITY_WIDE 0x0001 +#define HBA_CAPABILITY_DIFFERENTIAL 0x0002 +#define HBA_CAPABILITY_SCRIPT_RAM 0x0004 +#define HBA_CAPABILITY_64_BITS 0x0010 +#define HBA_CAPABILITY_8K_SCR_RAM 0x0020 +#define HBA_CAPABILITY_NO_DOM_VAL 0x0040 +#define HBA_CAPABILITY_1010_66 0x0080 + +// +// SCSI Protocol Chip Definitions. +// + +// +// Define the SCSI Control Register 0 bit equates +// + +#define SCNTL0_ARB_MODE_1 0x80 +#define SCNTL0_ARB_MODE_0 0x40 +#define SCNTL0_ENA_PARITY_CHK 0x08 + +#define SCNTL0_ASSERT_ATN_PAR 0x02 +#define SCNTL0_TAR 0x01 + +// +// Define the SCSI Control Register 1 bit equates +// + +#define SCNTL1_EXT_CLK_CYC 0x80 +#define SCNTL1_SODLTOSCSI 0x40 + +#define SCNTL1_CONNECTED 0x10 +#define SCNTL1_RESET_SCSI_BUS 0x08 + +// +// Define the SCSI Control Register 2 bit equates +// + +#define SCNTL2_WSS 0x08 +#define SCNTL2_WSR 0x01 + +// +// Define the SCSI Interrupt Enable register bit equates +// + +#define SIEN0_PHASE_MISMATCH 0x80 +#define SIEN0_FUNCTION_COMP 0x40 + +#define SIEN0_RESELECT 0x10 +#define SIEN0_SCSI_GROSS_ERROR 0x08 +#define SIEN0_UNEXPECTED_DISCON 0x04 +#define SIEN0_RST_RECEIVED 0x02 +#define SIEN0_PARITY_ERROR 0x01 + +#define SIEN1_SEL_RESEL_TIMEOUT 0x04 +#define SIEN1_BUS_MODE_CHANGE 0x10 +// +// Define the DMA Status Register bit equates +// + +#define DSTAT_ILLEGAL_INSTRUCTION 0x01 +#define DSTAT_ABORTED 0x10 +#define DSTAT_SCRPTINT 0x04 + +// +// Define the SCSI Status Register 0 bit equates +// + +#define SSTAT0_PHASE_MISMATCH 0x80 +#define SSTAT0_RESELECTED 0x10 +#define SSTAT0_GROSS_ERROR 0x08 +#define SSTAT0_UNEXPECTED_DISCONNECT 0x04 +#define SSTAT0_RESET 0x02 +#define SSTAT0_PARITY_ERROR 0x01 + +// +// Define the Interrupt Status Register bit equates +// + +#define ISTAT_ABORT 0x80 +#define ISTAT_RESET 0x40 +#define ISTAT_SIGP 0x20 +#define ISTAT_SEM 0x10 +#define ISTAT_CON 0x08 +#define ISTAT_INTF 0x04 +#define ISTAT_SCSI_INT 0x02 +#define ISTAT_DMA_INT 0x01 + +// +// Define the DMA Mode Register bit equates +// + +#define DMODE_BURST_1 0x80 +#define DMODE_BURST_0 0x40 +#define DMODE_ENA_READ_MULT 0x04 +#define DMODE_ENA_READ_LINE 0x08 + +// +// Define the DMA Interrupt Enable Register bit equates +// +#define DIEN_BUS_FAULT 0x20 +#define DIEN_ENA_ABRT_INT 0x10 +#define DIEN_ENA_SNGL_STP_INT 0x08 +#define DIEN_ENABLE_INT_RCVD 0x04 +#define DIEN_ENABLE_ILL_INST 0x01 + +// +// Define the DMA Control Register bit equates +// + +#define DCNTL_PREFETCH_FLUSH 0x40 +#define DCNTL_PREFETCH_ENABLE 0x20 + +// +// Define the SIST1 equates. SCSI Interrupt Status 1. +// + +#define SIST1_SEL_RESEL_TIMEOUT 0x04 +#define SIST1_DIFF_SENSE_CHANGE 0x10 + +// +// Define STEST1 equates +// + +#define STEST1_DOUBLER_SELECT 0x04 +#define STEST1_DOUBLER_ENABLE 0x08 + +// +// Define STEST2 equates +// + +#define STEST2_DIFF_MODE 0x20 + +// +// Define STEST3 equates +// + +#define STEST3_CLEAR_FIFO 0x02 +#define STEST3_HALT_CLOCK 0x20 + +// +// Define STEST4 equates +// + +#define STEST4_FREQ_LOCK 0x20 +#define STEST4_OLD_DIFF 0x40 +#define STEST4_SNGL_ENDED 0x80 +#define STEST4_LOWV_DIFF 0xC0 +#define STEST4_BUS_TYPE_MASK 0xC0 + +// +// Define GPCNTL equates +// + +#define GPCNTL_LED_CNTL 0x20 + +// +// Define CCNTL equates +// + +#define CCNTL0_DISABLE_PIPE_REQ 0x01 +#define CCNTL0_ENA_PM_JUMP 0x80 +#define CCNTL3_ENA_REQACK_SKEW 0x10 + +// +// LSI SIOP I/O macros. +// + +#define READ_SIOP_UCHAR(RegisterOffset) \ + (StorPortReadRegisterUchar( DeviceExtension, \ + &(DeviceExtension->SIOPRegisterBase)->RegisterOffset)) \ + + +#define WRITE_SIOP_UCHAR(RegisterOffset, BitMask) \ +{ \ + StorPortWriteRegisterUchar( DeviceExtension, \ + &(DeviceExtension->SIOPRegisterBase)->RegisterOffset, \ + BitMask); \ +} + +#define READ_SIOP_ULONG(RegisterOffset) \ + (StorPortReadRegisterUlong( DeviceExtension, \ + &(DeviceExtension->SIOPRegisterBase)->RegisterOffset)) \ + + +#define WRITE_SIOP_ULONG(RegisterOffset, BitMask) \ +{ \ + StorPortWriteRegisterUlong( DeviceExtension, \ + &(DeviceExtension->SIOPRegisterBase)->RegisterOffset, \ + BitMask); \ +} + +#endif diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsisvdt.h b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsisvdt.h new file mode 100644 index 00000000..4fcd5c89 --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsisvdt.h @@ -0,0 +1,274 @@ +/*++ + +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +PARTICULAR PURPOSE. + +Copyright (c) Microsoft Corporation. All rights reserved + +Module Name: + + lsisvdt.h + +Abstract: + + Private header file for lsi_u3.sys modules. This contains private + structure and function declarations as well as constant values which do + not need to be exported. + +Environment: + + kernel mode only + +Notes: + + +Revision History: + +--*/ + + +/* +************************************************************************* +* * +* Copyright 1994-2008 LSI Corporation. All rights reserved. * +* * +************************************************************************/ + + + +#ifndef _SYMSVDT_ +#define _SYMSVDT_ + +/* SCRIPTS structure definitions */ + +/* It is required that both DATA_IN and DATA_OUT support the same + * number of MOVE FRAGMENTS for this core. + */ + +#define START_Q_DEPTH 256 /* number of start queue entries */ +#define DONE_Q_DEPTH 10 /* number of done queue entries */ +#define CA_Q_DEPTH 32 /* number of ca queue entries */ + + +/* script instruction values */ +#define DATA_IN_SCRIPT 0x01000000L // chmov for data in +#define DATA_OUT_SCRIPT 0x00000000L // chmov for data out +#define OR_IN_DT_DATA 0x04000000L // or in to change to DT data +#define MOVE_CMD_SCRIPT 0x08000000L // or in to change chmov to move +#define MOVE_IN_SCRIPT 0x09000000L // move for data in (for req sns) +#define RETURN_SCRIPT 0x90080000L // return command +#define OPCODE_SCRIPT 0xff000000L // mask for chmov/move opcode +#define COUNT_SCRIPT 0x00ffffffL // mask for chmov/move byte count +#define INT_CMD_MASK 0x98020000L // mask for int, bad xfer direction +#define JUMP_REL_SCRIPT 0x80880000L // jump rel command +#define ENABLE_64BITS 0x7a570100L // move CCNTL1 | 0x01 to CCNTL1 +#define DISABLE_64BITS 0x7c57fe00L // move CCNTL1 & 0xFE to CCNTL1 +#define MEMORY_MOVE_CMD 0xC0000000L // memory move command +#define SCNTL4_1010_66 0x7A3C0C80L // move SCNTL4 | 0x0C to SCNTL4 + + + /* scripts variable descriptor table semaphore definitions */ + +#define SVDT_SEM_FREE 0x00000000L /* semaphore not set */ +#define SVDT_SEM_START 0x00000001L /* set to start i/o */ +#define SVDT_SEM_UNLOCK 0x00000002L /* unlock original queue */ +#define SVDT_SEM_REQ_SNS 0x00000003L /* set to start req sns */ +#define SVDT_SEM_NVCONFIG 0x00000004L /* set to do nvconfig ioctl */ +#define SVDT_SEM_MASK_VALUE 0x000000F8L +#define SVDT_SEM_MASK 0x00000007L +#define SVDT_SEM_PTR_MASK 0x000000F8L +#define SVDT_PHYS_MASK 0xFFFFFFF8L /* mask off semaphore */ + + +/* I/O tracking array entry definition */ + +typedef struct _IO_TRACK_ENTRY +{ + PSCSI_REQUEST_BLOCK Srb; /* saved SRB address of active I/O */ + UCHAR target; /* target ID of this I/O */ + UCHAR lun; /* logical unit number of this I/O */ + UCHAR queueTag; /* queue tag value for this I/O */ + UCHAR reserved1; /* padding */ +#ifdef _WIN64 + ULONG reserved2; /* alignment padding if 64-bit */ +#endif +} IO_TRACK_ENTRY, *PIO_TRACK_ENTRY; + +/* I/O start queue entry definition */ + +typedef struct _START_QUEUE_ENTRY +{ + ULONG svdtPhysSem; /* combined svdt pointer and semaphore */ + ULONG svdtMoveCmd; /* move memory command with svdt length */ + ULONG linkPhys; /* physical pointer to next entry */ + +} START_QUEUE_ENTRY, *PSTART_QUEUE_ENTRY; + +/* I/O completion queue entry definition */ + +typedef struct _DONE_QUEUE_ENTRY +{ + ULONG context; /* Srb address (32), svdtPhys (64) */ + ULONG statXferLen; /* SCSI status and length of transfer */ + ULONG linkPhys; /* physical pointer to next entry */ + +} DONE_QUEUE_ENTRY, *PDONE_QUEUE_ENTRY; + +/* ITQ and ITL nexus pointers & svdt length */ + +typedef struct _NEXUS_PTR +{ + ULONG nexusPtr; /* physical address of sys mem svdt */ + ULONG svdtMoveCmd; /* mem move command with svdt length */ +} NEXUS_PTR, *PNEXUS_PTR; + +/* I/O vector list entry definition */ + +typedef struct _IOV_ENTRY +{ + ULONG scriptWord0; + ULONG scriptWord1; +} IOV_ENTRY; + +/* -- I/O vector list -- + * The I/O vector list contains scripts block move instructions. + * The first instruction is an int 0x20 when data[in|out] to test + * for a wrong data transfer direction specified in SrbFlags. + * There is one instruction for each element of a simple scatter/ + * gather list. The list will be called by the main scripts, and + * must be termintated with a return instruction. + */ + +typedef struct _IOV_LIST +{ + IOV_ENTRY iovEntry[MAX_SG_ELEMENTS+2]; +} IOV_LIST, *PIOV_LIST; + + +/* NegotMsg structure holds the msg out buffers for each target ID. + * Pointed to by the NegotMsgBufDesc array of table indirect entries. + * Used during auto request sense to do renegotiation of wide/sync parameters. + */ + +typedef struct _NEGOT_BUF +{ + UCHAR Buf[12]; +} NEGOT_BUF, *PNEGOT_BUF; + + +/* svdt entry */ + +typedef struct _SVARS_DESCRIPTOR +{ + ULONG count; + ULONG paddr; +} SVARS_DESCRIPTOR, *PSVARS_DESCRIPTOR; + + /* -- svars -- + * The scripts variables structure is a global data area that + * is shared with the scripts. The fields are defined as follows: + * + * - currentContext - + * Context pointer from the active descriptor table. This field is + * set by the scripts for each SCSI bus connection and is used by the + * driver while servicing SCSI and DMA interrupts. + * Initialization requirements: none. + * - startQPhysPtr - + * Physical pointer used by the scripts to maintain start queue position. + * Initialization requirements: must be set to point to the head of the + * start queue during driver initialization and after resets. + * - lockedQPhysPtr - + * This field is used by the scripts to store the current start queue + * position when doing auto request sense. The scripts automatically + * restores the current position when all CA conditions are cleared. + * Initialization requirements: none. + * - doneQPhysPtr - + * Physical pointer used by the scripts to maintain done queue position. + * Initialization requirements: must be set to point to the head of the + * done queue during driver initialization and after resets. + * - caPutQPhysPtr - + * Physical pointer used by the scripts to maintain ca queue position + * for inserting commands that returned with check conditions. + * Initialization requirements: must be set to point to the head of the + * ca queue during driver initialization and after resets. + * - caStartQPhysPtr - + * Physical pointer used by the scripts to maintain ca queue position + * for starting request sense commands to clear check conditions. + * Initialization requirements: must be set to point to the head of the + * ca queue during driver initialization and after resets. + * - ITQnexusTablePhysPtr - + * Physical pointer used by scripts to obtain base address of nexus + * pointer lookup table for tagged commmands. + * Initialization requirements: must be set during driver initialization. + * - ITLnexusTablePhysPtr - + * Physical pionter used by scripts to obtain base address of nexus + * pointer lookup table for non-tagged commands. + * Initialization requirements: must be set during driver initialization. + * - msgInBuf - + * This field is used as a scratch area by the scripts to store + * message bytes received from the target device. If the driver + * needs to examine message bytes, the data is stored here, as well. + * Initialization requirements: none. + * + * NOTE: Any changes to this table must be matched in scripts. + */ + typedef struct _SVARS + { + /* this area is commonly defined between the driver and scripts */ + + ULONG currentContext; /* 0x00 */ + ULONG startQPhysPtr; /* 0x04 */ + ULONG lockedQPhysPtr; /* 0x08 */ + ULONG doneQPhysPtr; /* 0x0C */ + ULONG caPutQPhysPtr; /* 0x10 */ + ULONG caStartQPhysPtr; /* 0x14 */ + ULONG ITQnexusTablePhysPtr; /* 0x18 */ + ULONG ITLnexusTablePhysPtr; /* 0x1C */ + UCHAR msgInBuf[ 8 ]; /* 0x20 */ + /* end of common scripts/driver definition */ + + } SVARS, *PSVARS; + + + /* -- svdt -- + * The scripts variable descriptor table is a data structure that is + * used to pass I/O specific information to the scripts. Each svdt + * contains pointers to other data structures formatted for table + * indirect scripts addressing. The SCSI I/O Processor requires + * each entry in the descriptor table to be 8 bytes long. The first + * four bytes must contain a 24-bit byte count, followed by a 32-bit + * physical address. This structure also contains data elements that + * is not acccessed by table indirect operations. Table indirect + * fields are defined as the type SVARS_DESCRIPTOR. + * + * In order to support simplified scripts calculations, the table size + * must be aligned on 16 byte boundaries. + * + * NOTE: Any changes to this table must be matched in scripts. + */ + + typedef struct _SVARS_DESCRIPTOR_TABLE + { + /* this area is commonly defined between the driver and scripts */ + ULONG context; /* 0x00 context */ + ULONG runningByteCount; /* 0x04 total bytes xfered */ + SVARS_DESCRIPTOR deviceDescriptor; /* 0x08 selection parms */ + SVARS_DESCRIPTOR cmdBufDescriptor; /* 0x10 scsi cdb */ + SVARS_DESCRIPTOR msgOutBufDescriptor; /* 0x18 scsi messages */ + UCHAR Cdb[16]; /* 0x20 SCSI CDB */ + UCHAR msgOutBuf[16]; /* 0x30 message out buffer */ + ULONG nexusEntryPhys; /* 0x40 ptr to nexus entry */ + ULONG sysSvdtPhys; /* 0x44 ptr to sys mem svdt */ + ULONG svdtMoveCmd; /* 0x48 svdt move & length */ + ULONG iovPhys; /* 0x4c io vector pointer */ +#ifdef _WIN64 + PSCSI_REQUEST_BLOCK Srb; /* 0x50 Srb pointer */ +#endif + IOV_LIST iovList; /* 0x50 scatter/gather list */ + /* 0x58 if WIN64 */ + /* end of common scripts/driver definition */ + } SVARS_DESCRIPTOR_TABLE, *PSVARS_DESCRIPTOR_TABLE; + +#endif diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsiver.h b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsiver.h new file mode 100644 index 00000000..d52ddedc --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/lsiver.h @@ -0,0 +1,55 @@ +/*++ + +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +PARTICULAR PURPOSE. + +Copyright (c) Microsoft Corporation. All rights reserved + +Module Name: + + lsiver.h + +Abstract: + + Private header file for lsi_u3.sys modules. This contains private + structure and function declarations as well as constant values which do + not need to be exported. + +Environment: + + kernel mode only + +Notes: + + +Revision History: + +--*/ + + +/* +************************************************************************* +* * +* Copyright 1994-2008 LSI Corporation. All rights reserved. * +* * +************************************************************************/ + + +#ifndef _LSIVER_ +#define _LSIVER_ + + +// version numbers for VER_FILEVERSION, keep in sync with version string +#define LSI_VERSION_MAJOR 5 +#define LSI_VERSION_MINOR 9 +#define LSI_VERSION_BUILD 10 +#define LSI_VERSION_REV 5 + +#define LSI_CMN_VERSION_NUMBER "5.09.10.05" + +#define LSI_VERSION_LABEL "LSI_U3-" LSI_CMN_VERSION_NUMBER + +#endif + diff --git a/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/sdv-user.sdv b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/sdv-user.sdv new file mode 100644 index 00000000..5c2bd095 --- /dev/null +++ b/tools/sdv/samples/SDV-FailDriver-STORPORT/driver/sdv-user.sdv @@ -0,0 +1,7 @@ +StorPortAllocatePool2 +StorPortDeprecated +StorPortEnablePassive +StorPortNotification2 +StorPortSpinLock +StorPortStartIo +StorPortStatusPending |
