2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
3 * Copyright (c) 2004-2005 Mellanox Technologies Ltd. All rights reserved.
\r
5 * This software is available to you under the OpenIB.org BSD license
\r
8 * Redistribution and use in source and binary forms, with or
\r
9 * without modification, are permitted provided that the following
\r
10 * conditions are met:
\r
12 * - Redistributions of source code must retain the above
\r
13 * copyright notice, this list of conditions and the following
\r
16 * - Redistributions in binary form must reproduce the above
\r
17 * copyright notice, this list of conditions and the following
\r
18 * disclaimer in the documentation and/or other materials
\r
19 * provided with the distribution.
\r
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
25 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
26 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
37 #include <mtl_common.h>
\r
40 #include "mosal_util.h"
\r
41 #include <vapi_common.h>
\r
44 ////////////////////////////////////////////////////////////////////////////
\r
46 ////////////////////////////////////////////////////////////////////////////
\r
49 * Maximal device name length
\r
51 #define MD_MAX_DEV_NAME_LEN 255
\r
54 * Maximal device params length
\r
56 #define MD_MAX_DEV_PARAMS_LEN 255
\r
59 * Device name DB size
\r
61 #define MD_MAX_DEV_DB_SIZE 1024
\r
66 #define PCI_HDR_SIZE 64
\r
68 ////////////////////////////////////////////////////////////////////////////
\r
70 ////////////////////////////////////////////////////////////////////////////
\r
71 #define MD_DFLT_CONF_ADDR 88
\r
72 #define MD_DFLT_CONF_DATA 92
\r
73 #define MD_DFLT_DDR_OFFSET 0
\r
74 #define MD_DFLT_DDR_SIZE 0x10000000
\r
77 ////////////////////////////////////////////////////////////////////////////
\r
79 ////////////////////////////////////////////////////////////////////////////
\r
82 * Driver control device name
\r
84 #define MD_CTL_DEVICE_NAME "MDCTL"
\r
85 #define MLX_VENDOR_ID 0x15B3
\r
87 ////////////////////////////////////////////////////////////////////////////
\r
89 ////////////////////////////////////////////////////////////////////////////
\r
94 MD_DEV_ID_TAVOR=23108,
\r
95 MD_DEV_ID_TAVOR_BD=23109,
\r
96 MD_DEV_ID_TAVOR_SD=23130,
\r
97 MD_DEV_ID_ARBEL_TM=25208 /* ARBEL in TAvor mode */
\r
104 MD_DEV_IX_TAVOR_BD,
\r
105 MD_DEV_IX_TAVOR_SD,
\r
106 MD_DEV_IX_ARBEL_TM, /* ARBEL in TAvor mode */
\r
111 ////////////////////////////////////////////////////////////////////////////
\r
113 ////////////////////////////////////////////////////////////////////////////
\r
117 * Work with CR_SPACE
\r
119 #define MD_CR_DWORD_WRITE(dev,addr,value) \
\r
120 if (dev->m_fUsePorts) ? WRITE_PORT_ULONG((addr),(value)) : WRITE_REGISTER_ULONG((addr),(value))
\r
121 #define MD_CR_DWORD_READ(dev,addr,value) \
\r
122 value = (dev->m_fUsePorts) ? READ_PORT_ULONG((addr)) : READ_REGISTER_ULONG((addr))
\r
125 #define PRE_LOCK_IT KIRQL l_OldIrql
\r
126 #define INIT_LOCK_IT(a) KeInitializeSpinLock(a)
\r
127 #define LOCK_IT(a) KeAcquireSpinLock((a),&l_OldIrql)
\r
128 #define UNLOCK_IT(a) KeReleaseSpinLock((a),l_OldIrql)
\r
131 #define KMUTEX_INIT(a) KeInitializeMutex(a,0)
\r
132 #define KMUTEX_ACQ(a) KeWaitForMutexObject( a, Executive, KernelMode, FALSE, NULL )
\r
133 #define KMUTEX_REL(a) KeReleaseMutex(a, FALSE)
\r
135 #define FMUTEX_INIT(a) ExInitializeFastMutex(a)
\r
136 #define FMUTEX_ACQ(a) ExAcquireFastMutex(a)
\r
137 #define FMUTEX_REL(a) ExReleaseFastMutex(a)
\r
140 #define KSEM_INIT(a) KeInitializeSemaphore(a,1,1)
\r
141 #define KSEM_ACQ(a) KeWaitForSingleObject( a, Executive, KernelMode, FALSE, NULL )
\r
142 #define KSEM_REL(a) KeReleaseSemaphore(a, 0, 1, FALSE)
\r
146 ////////////////////////////////////////////////////////////////////////////
\r
148 ////////////////////////////////////////////////////////////////////////////
\r
153 typedef struct MD_HAL_DEV_PARAMS_S {
\r
155 /* buffer for DevId string */
\r
156 WCHAR m_DevIdWstr[5];
\r
157 // format string for building internal name
\r
159 // format string for building exported name
\r
161 // Device ID (in PCI configuration)
\r
162 MD_DEV_ID_E m_DevId;
\r
163 // Device IX (in PCI configuration)
\r
164 MD_DEV_IX_E m_DevIx;
\r
167 // BAR sizes (approximately)
\r
171 // the device clock frequency
\r
172 u_int32_t m_ClockFreq;
\r
173 // number of bits per device word
\r
174 u_int8_t m_WordSize;
\r
175 // 1 means opposite to platform endianess
\r
176 u_int8_t m_Endianess;
\r
178 } MD_HAL_DEV_PARAMS_T, *PMD_HAL_DEV_PARAMS_T;
\r
181 typedef struct MD_DEV_CONTEXT_S *PMD_DEV_CONTEXT_T;
\r
183 typedef PFILE_OBJECT PCS_HANDLE_T;
\r
186 // Process context - saved in PFILE_OBJECT->FsContext
\r
188 typedef struct MD_PCS_CONTEXT_S {
\r
190 // TAVOR (VIPKL) info
\r
191 // IB_MGT resource tracking
\r
193 // VIPKL resource tracking
\r
208 // SANITY CHECK info
\r
212 } MD_PCS_CONTEXT_T, *PMD_PCS_CONTEXT_T;
\r
214 #define MAKE_PCS(a) ((PMD_PCS_CONTEXT_T)(a))
\r
220 typedef struct MD_DRV_CONTEXT_S {
\r
223 PDRIVER_OBJECT m_pDrvObject;
\r
225 // Debug Print Level
\r
226 ULONG m_nDebugPrintLevel;
\r
228 // FIFO queue of devices, added (for debug purposes)
\r
229 LIST_ENTRY m_DevQue;
\r
231 // current number of devices
\r
234 // current number of adapters
\r
238 /* control device context */
\r
239 PMD_DEV_CONTEXT_T m_pCtlDevContext;
\r
241 /* device name DB */
\r
242 ULONG m_DevNamesDbSize;
\r
243 ULONG m_DevNamesDbCnt;
\r
244 char m_DevNamesDb[MD_MAX_DEV_DB_SIZE];
\r
247 KSPIN_LOCK m_SpinLock;
\r
249 /* various features support */
\r
250 ULONG m_ThhLegacySqp;
\r
251 BOOLEAN m_fSupportIbMgt;
\r
252 BOOLEAN m_fSupportTavor;
\r
253 ULONG m_AvInHostMem; /* AV in host memory (and not in DDR) */
\r
254 ULONG m_InfiniteCmdTimeout; /* when 1 we use inifinite timeouts on commands completion */
\r
255 ULONG m_NumCmdsOuts; /* max number of outstanding commands */
\r
256 ULONG m_FatalDelayHalt;
\r
257 ULONG m_AsyncEqSize;
\r
258 ULONG m_CmdifUseUar0;
\r
259 ULONG m_IgnoreSubsystemId;
\r
261 int m_IbMgtQp0Only; /* for IB_MGT: use QP0 only */
\r
263 } MD_DRV_CONTEXT_T, *PMD_DRV_CONTEXT_T;
\r
266 // Control device context
\r
268 typedef struct MD_CTL_DEV_CONTEXT_S {
\r
270 } MD_CTL_DEV_CONTEXT_T, *PMD_CTL_DEV_CONTEXT_T;
\r
272 typedef struct MD_IB_DEV_TAVOR_S {
\r
273 VAPI_hca_hndl_t m_hHca;
\r
274 HH_hca_hndl_t m_hHhHca;
\r
275 } MD_IB_DEV_TAVOR_T, *PMD_IB_DEV_TAVOR_T;
\r
277 typedef struct MD_IB_DEV_TAVOR_BD_S {
\r
278 int m_DummyTavorBd;
\r
279 } MD_IB_DEV_TAVOR_BD_T, *PMD_IB_DEV_TAVOR_BD_T;
\r
281 typedef struct MD_IB_DEV_TAVOR_SD_S {
\r
282 PMD_DEV_CONTEXT_T m_pBdDevContext;
\r
283 } MD_IB_DEV_TAVOR_SD_T, *PMD_IB_DEV_TAVOR_SD_T;
\r
288 typedef struct MD_PCI_HDR_S {
\r
289 ULONG m_Hdr[PCI_HDR_SIZE];
\r
292 } MD_PCI_HDR_T, *PMD_PCI_HDR_T;
\r
295 // IB device context
\r
297 typedef struct MD_IB_DEV_CONTEXT_S {
\r
300 ////////////////////////////////////////////////////////////////////////////
\r
301 // Device stack information
\r
302 ////////////////////////////////////////////////////////////////////////////
\r
304 // next-lower driver's device object, representing the target device
\r
305 PDEVICE_OBJECT m_pLdo;
\r
307 // The bus driver object
\r
308 PDEVICE_OBJECT m_pPdo;
\r
310 /* buffer for ASCII device name */
\r
311 char m_AsciiDevName[MD_MAX_DEV_NAME_LEN + 1];
\r
316 ////////////////////////////////////////////////////////////////////////////
\r
317 // Device configuration information
\r
318 ////////////////////////////////////////////////////////////////////////////
\r
326 ULONG m_ulIntVector;
\r
327 KIRQL m_ulIntLevel;
\r
328 KAFFINITY m_Affinity;
\r
329 BOOLEAN m_fIntShared;
\r
330 KINTERRUPT_MODE m_IntMode;
\r
335 // UAR-space region
\r
340 ULONG m_ulDdrMapOffset;
\r
341 ULONG m_ulDdrMapSize;
\r
343 // register offsets
\r
344 ULONG m_ulAddrOffset;
\r
345 ULONG m_ulDataOffset;
\r
348 BOOLEAN m_fMayReset;
\r
349 MD_PCI_HDR_T m_MyHdr;
\r
350 MD_PCI_HDR_T m_HcaHdr;
\r
351 MD_PCI_HDR_T m_BridgeHdr;
\r
352 ULONG m_PerformReset;
\r
354 ////////////////////////////////////////////////////////////////////////////
\r
355 // Power management
\r
356 ////////////////////////////////////////////////////////////////////////////
\r
358 // current device power state
\r
359 DEVICE_POWER_STATE m_CurrentDevicePowerState;
\r
361 //Bus drivers set the appropriate values in this structure in response
\r
362 //to an IRP_MN_QUERY_CAPABILITIES IRP. Function and filter drivers might
\r
363 //alter the capabilities set by the bus driver.
\r
364 DEVICE_CAPABILITIES m_DeviceCapabilities;
\r
366 // used to save the currently-being-handled system-requested power irp request
\r
369 // set to signal driver-generated power request is finished
\r
370 KEVENT m_SelfRequestedPowerIrpEvent;
\r
372 // flag set when IRP_MN_WAIT_WAKE is received and we're in a power state
\r
373 // where we can signal a wait
\r
374 BOOLEAN m_EnabledForWakeup;
\r
376 // used to flag that we're currently handling a self-generated power request
\r
377 BOOLEAN m_SelfPowerIrp;
\r
379 // default power state to power down to on self-suspend
\r
380 ULONG m_PowerDownLevel;
\r
382 ////////////////////////////////////////////////////////////////////////////
\r
384 ////////////////////////////////////////////////////////////////////////////
\r
386 //flag set when processing IRP_MN_REMOVE_DEVICE
\r
387 BOOLEAN m_DeviceRemoved;
\r
389 // flag set when driver has answered success to IRP_MN_QUERY_REMOVE_DEVICE
\r
390 BOOLEAN m_RemoveDeviceRequested;
\r
392 // flag set when driver has answered success to IRP_MN_QUERY_STOP_DEVICE
\r
393 BOOLEAN m_StopDeviceRequested;
\r
395 // MOSAL device handle
\r
396 MOSAL_dev_handle_t m_hMosal;
\r
398 // pointer to device parameters
\r
399 PMD_HAL_DEV_PARAMS_T m_pMdhalParams;
\r
401 /* DEVICE SPECIFIC PART */
\r
404 MD_IB_DEV_TAVOR_BD_T;
\r
405 MD_IB_DEV_TAVOR_SD_T;
\r
408 } MD_IB_DEV_CONTEXT_T, *PMD_IB_DEV_CONTEXT_T;
\r
411 // A structure representing the instance information associated with
\r
412 // this particular device.
\r
415 typedef struct MD_DEV_CONTEXT_S {
\r
417 // FIFO queue of devices
\r
421 PMD_DRV_CONTEXT_T m_pDrvContext;
\r
424 MD_DEV_IX_E m_eDevType;
\r
426 // NT device handle
\r
427 PDEVICE_OBJECT m_pFdo;
\r
429 /* NT device name */
\r
430 UNICODE_STRING m_usNtDeviceName;
\r
432 /* DOS device name */
\r
433 UNICODE_STRING m_usDosDeviceName;
\r
435 /* device level spinlock */
\r
436 KSPIN_LOCK m_SpinLock;
\r
438 /* signature - for checking the handle */
\r
441 // spinlock used to protect inc/dec iocount logic
\r
442 KSPIN_LOCK m_IoCntSpinLock;
\r
444 /* pending IRP count */
\r
445 int m_nPendingIoCnt;
\r
447 // set when PendingIoCount goes to 0; flags device can be removed
\r
448 KEVENT m_RemoveEvent;
\r
450 // set when PendingIoCount goes to 1 ( 1st increment was on add device )
\r
451 // this indicates no IO requests outstanding, either user, system, or self-staged
\r
452 KEVENT m_NoPendingIoEvent;
\r
454 // flag set when device has been successfully started
\r
455 BOOLEAN m_DeviceStarted;
\r
458 LIST_ENTRY m_PcsQue;
\r
461 BOOLEAN m_fDeletePending;
\r
469 // number of OPENs for this device
\r
472 // interface for r/w to PCI config space
\r
473 BUS_INTERFACE_STANDARD m_Interface;
\r
475 /* DEVICE SPECIFIC PART */
\r
477 MD_CTL_DEV_CONTEXT_T;
\r
478 MD_IB_DEV_CONTEXT_T;
\r
481 } MD_DEV_CONTEXT_T, *PMD_DEV_CONTEXT_T;
\r
484 ////////////////////////////////////////////////////////////////////////////
\r
485 // GLOBAL VARIABLES
\r
486 ////////////////////////////////////////////////////////////////////////////
\r
489 PMD_DRV_CONTEXT_T g_pDrvContext = NULL;
\r
490 MD_HAL_DEV_PARAMS_T g_DevParams[MD_DEV_IX_LAST] = {
\r
492 { L"0000", "", "", MD_DEV_ID_CTRL, MD_DEV_IX_CTRL, FALSE, 0,0,0, 0, 0, 0 },
\r
494 { L"5A44", "InfiniHost%d", "InfiniHost%d", MD_DEV_ID_TAVOR, MD_DEV_IX_TAVOR, TRUE, 0x00100000, 0x01000000, 0x00000000, 167000000, 4, 0 },
\r
496 { L"5A45","mt%d_pciconf%d", "mt%d_pciconf%d", MD_DEV_ID_TAVOR_BD, MD_DEV_IX_TAVOR_BD, TRUE, 0x00000000, 0x00000000, 0x00000000, 167000000, 4, 0 },
\r
498 { L"5A5A", "mt%d_pci%d", "mt%d_pci%d", MD_DEV_ID_TAVOR_SD, MD_DEV_IX_TAVOR_SD, TRUE, 0x00100000, 0x01000000, 0x00000000, 167000000, 4, 0 },
\r
500 { L"6278", "InfiniHost%d", "InfiniHosA%d", MD_DEV_ID_ARBEL_TM, MD_DEV_IX_ARBEL_TM, TRUE, 0x00100000, 0x01000000, 0x00000000, 167000000, 4, 0 },
\r
504 extern PMD_DRV_CONTEXT_T g_pDrvContext;
\r
505 extern MD_HAL_DEV_PARAMS_T g_DevParams[MD_DEV_IX_LAST];
\r
508 ////////////////////////////////////////////////////////////////////////////
\r
509 // function prototypes
\r
510 ////////////////////////////////////////////////////////////////////////////
\r
514 IN PDEVICE_OBJECT DeviceObject,
\r
519 MdProcessSysControlIrp(
\r
520 IN PDEVICE_OBJECT DeviceObject,
\r
526 IN PDRIVER_OBJECT DriverObject
\r
531 IN PDEVICE_OBJECT pi_pFdo,
\r
537 IN PDEVICE_OBJECT DeviceObject
\r
542 IN PDEVICE_OBJECT DeviceObject
\r
547 IN PDRIVER_OBJECT DriverObject,
\r
548 IN PDEVICE_OBJECT pi_pPdo
\r
552 MdCreateDeviceObject(
\r
553 IN PDRIVER_OBJECT DriverObject,
\r
554 IN PDEVICE_OBJECT pi_pPdo,
\r
555 IN PDEVICE_OBJECT *DeviceObject
\r
560 IN PDEVICE_OBJECT DeviceObject
\r
564 MdIrpCompletionRoutine(
\r
565 IN PDEVICE_OBJECT DeviceObject,
\r
571 MdPoRequestCompletion(
\r
572 IN PDEVICE_OBJECT DeviceObject,
\r
573 IN UCHAR MinorFunction,
\r
574 IN POWER_STATE PowerState,
\r
576 IN PIO_STATUS_BLOCK IoStatus
\r
580 MdPoSelfRequestCompletion(
\r
581 IN PDEVICE_OBJECT DeviceObject,
\r
582 IN UCHAR MinorFunction,
\r
583 IN POWER_STATE PowerState,
\r
585 IN PIO_STATUS_BLOCK IoStatus
\r
590 IN PDEVICE_OBJECT DeviceObject,
\r
591 IN PULONG PortStatus
\r
596 IN IN PDEVICE_OBJECT DeviceObject
\r
600 MdSelfRequestPowerIrp(
\r
601 IN PDEVICE_OBJECT DeviceObject,
\r
602 IN POWER_STATE PowerState
\r
606 MdSetDevicePowerState(
\r
607 IN PDEVICE_OBJECT DeviceObject,
\r
608 IN DEVICE_POWER_STATE DeviceState
\r
612 MdAsyncReadWrite_Complete(
\r
613 IN PDEVICE_OBJECT DeviceObject,
\r
619 MdSimpleReadWrite_Complete(
\r
620 IN PDEVICE_OBJECT DeviceObject,
\r
627 MdPowerIrp_Complete(
\r
628 IN PDEVICE_OBJECT NullDeviceObject,
\r
634 MdQueryCapabilities(
\r
635 IN PDEVICE_OBJECT pi_pLowerDevObject,
\r
636 OUT PDEVICE_CAPABILITIES po_pDeviceCapabilities
\r
642 IN PDEVICE_OBJECT DeviceObject,
\r
648 IN PDEVICE_OBJECT DeviceObject,
\r
655 IN PDEVICE_OBJECT DeviceObject,
\r
662 IN PDEVICE_OBJECT DeviceObject
\r
668 IN PDEVICE_OBJECT DeviceObject,
\r
675 IN PDEVICE_OBJECT DeviceObject
\r
680 IN PDEVICE_OBJECT DeviceObject,
\r
686 MdIncrementIoCount(
\r
687 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
691 MdDecrementIoCount(
\r
692 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
698 IN PDEVICE_OBJECT DeviceObject,
\r
705 IN PDEVICE_OBJECT DeviceObject,
\r
711 MdSelfSuspendOrActivate(
\r
712 IN PDEVICE_OBJECT DeviceObject,
\r
713 IN BOOLEAN fSuspend
\r
718 IN PDEVICE_OBJECT DeviceObject,
\r
719 IN OUT PUNICODE_STRING deviceLinkUnicodeString
\r
725 IN PDEVICE_OBJECT DeviceObject
\r
729 MdCanAcceptIoRequests(
\r
730 IN PDEVICE_OBJECT DeviceObject
\r
733 #endif // already included
\r
736 * Interface GUID - defined outside of conditional include statement on purpose.
\r
738 // {4FAD14C1-D7D3-40bc-9C83-88498FE114F3}
\r
739 DEFINE_GUID(GUID_MD_INTERFACE,
\r
740 0x4fad14c1, 0xd7d3, 0x40bc, 0x9c, 0x83, 0x88, 0x49, 0x8f, 0xe1, 0x14, 0xf3);
\r