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
34 #include "MdConfPriv.h"
\r
35 #include "MdIoctlSpec.h"
\r
36 #include <initguid.h>
\r
37 #include <wdmguid.h>
\r
39 // select implementation of PciHdrWrite
\r
40 //#define USE_HalSetBusData 1
\r
41 //#define USE_HalSetBusDataByOffset 1
\r
42 #define USE_ReadWritePciConfig 1
\r
45 #define NOT_USE_MDNTDDK 1
\r
46 //#ifdef NOT_USE_MDNTDDK
\r
47 ///* from ntddk.h */
\r
49 //// Define types of bus information.
\r
52 //typedef enum _BUS_DATA_TYPE {
\r
53 // ConfigurationSpaceUndefined = -1,
\r
55 // EisaConfiguration,
\r
57 // CbusConfiguration,
\r
58 // PCIConfiguration,
\r
59 // VMEConfiguration,
\r
60 // NuBusConfiguration,
\r
61 // PCMCIAConfiguration,
\r
62 // MPIConfiguration,
\r
63 // MPSAConfiguration,
\r
64 // PNPISAConfiguration,
\r
65 // SgiInternalConfiguration,
\r
66 // MaximumBusDataType
\r
67 //} BUS_DATA_TYPE, *PBUS_DATA_TYPE;
\r
72 // IN BUS_DATA_TYPE BusDataType,
\r
73 // IN ULONG BusNumber,
\r
74 // IN ULONG SlotNumber,
\r
81 //HalGetBusDataByOffset(
\r
82 // IN BUS_DATA_TYPE BusDataType,
\r
83 // IN ULONG BusNumber,
\r
84 // IN ULONG SlotNumber,
\r
93 // IN BUS_DATA_TYPE BusDataType,
\r
94 // IN ULONG BusNumber,
\r
95 // IN ULONG SlotNumber,
\r
102 //HalSetBusDataByOffset(
\r
103 // IN BUS_DATA_TYPE BusDataType,
\r
104 // IN ULONG BusNumber,
\r
105 // IN ULONG SlotNumber,
\r
106 // IN PVOID Buffer,
\r
107 // IN ULONG Offset,
\r
114 /******************************************************************************
\r
116 * SendAwaitIrpCompletion
\r
119 * IRP completion routine
\r
124 * pointer to the entry on SUCCESS
\r
127 ******************************************************************************/
\r
129 SendAwaitIrpCompletion (
\r
130 IN PDEVICE_OBJECT DeviceObject,
\r
135 UNREFERENCED_PARAMETER (DeviceObject);
\r
136 KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
\r
137 return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
\r
140 /******************************************************************************
\r
145 * Create and send IRP stack down the stack and wait for the response (Blocking Mode)
\r
148 * pi_pDeviceExt.......... ointer to USB device extension
\r
149 * pi_MajorCode........... IRP major code
\r
150 * pi_MinorCode........... IRP minor code
\r
151 * pi_pBuffer............. parameter buffer
\r
152 * pi_nSize............... size of the buffer
\r
155 * pointer to the entry on SUCCESS
\r
158 ******************************************************************************/
\r
161 IN PDEVICE_OBJECT pi_pFdo,
\r
162 IN PDEVICE_OBJECT pi_pLdo,
\r
163 IN ULONG pi_MajorCode,
\r
164 IN ULONG pi_MinorCode,
\r
165 IN PVOID pi_pBuffer,
\r
170 Routine Description:
\r
172 Create and send IRP stack down the stack and wait for the response (
\r
177 pi_pFdo................ our device
\r
178 pi_pLdo................ lower device
\r
179 pi_MajorCode........... IRP major code
\r
180 pi_MinorCode........... IRP minor code
\r
181 pi_pBuffer............. parameter buffer
\r
182 pi_nSize............... size of the buffer
\r
186 standard NTSTATUS return codes.
\r
191 { /* SendAwaitIrp */
\r
197 PIO_STACK_LOCATION l_pStackLocation;
\r
202 if(KeGetCurrentIrql() != PASSIVE_LEVEL)
\r
203 return STATUS_SUCCESS;
\r
206 KeInitializeEvent(&l_hEvent, NotificationEvent, FALSE);
\r
208 // build IRP request to USBD driver
\r
209 l_pIrp = IoAllocateIrp( pi_pFdo->StackSize, FALSE );
\r
211 // validate request
\r
214 //MdKdPrint( DBGLVL_MAXIMUM, ("(SendAwaitIrp) Unable to allocate IRP !\n"));
\r
215 return STATUS_INSUFFICIENT_RESOURCES;
\r
219 l_pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
\r
221 // set completion routine
\r
222 IoSetCompletionRoutine(l_pIrp,SendAwaitIrpCompletion, &l_hEvent, TRUE, TRUE, TRUE);
\r
224 // fill stack location
\r
225 l_pStackLocation = IoGetNextIrpStackLocation(l_pIrp);
\r
226 l_pStackLocation->MajorFunction= (UCHAR)pi_MajorCode;
\r
227 l_pStackLocation->MinorFunction= (UCHAR)pi_MinorCode;
\r
228 RtlCopyMemory( &l_pStackLocation->Parameters, pi_pBuffer, pi_nSize );
\r
230 // Call lower driver perform request
\r
231 l_Status = IoCallDriver( pi_pLdo, l_pIrp );
\r
233 // if the request not performed --> wait
\r
234 if (l_Status == STATUS_PENDING)
\r
236 // Wait until the IRP will be complete
\r
237 KeWaitForSingleObject(
\r
238 &l_hEvent, // event to wait for
\r
239 Executive, // thread type (to wait into its context)
\r
240 KernelMode, // mode of work
\r
241 FALSE, // alertable
\r
244 l_Status = l_pIrp->IoStatus.Status;
\r
251 } /* SendAwaitIrp */
\r
256 /******************************************************************************
\r
258 * DrvReadWritePciConfig
\r
261 * Create and send IRP stack down the stack and wait for the response (Blocking Mode)
\r
266 * pointer to the entry on SUCCESS
\r
269 ******************************************************************************/
\r
271 DrvReadWritePciConfig(
\r
272 IN PMD_DEV_CONTEXT_T pi_pMdDevContext,
\r
273 IN PVOID pi_pDataBuffer,
\r
274 IN ULONG pi_nPciSpaceOffset,
\r
275 IN ULONG pi_nDataLength,
\r
276 IN BOOLEAN pi_fReadConfig
\r
279 { /* DrvReadWritePciConfig */
\r
281 // parameter buffer for the request
\r
282 DrvReadWriteConfig_t l_RwParams;
\r
285 // parameter validation
\r
286 //MDASSERT(pi_pDataBuffer);
\r
287 //MDASSERT(pi_nDataLength);
\r
289 // try to do it directly
\r
290 if (pi_fReadConfig && pi_pMdDevContext->m_Interface.GetBusData) {
\r
291 l_nBytes = pi_pMdDevContext->m_Interface.GetBusData(
\r
292 pi_pMdDevContext->m_Interface.Context,
\r
293 PCI_WHICHSPACE_CONFIG,
\r
295 pi_nPciSpaceOffset,
\r
298 return (l_nBytes != pi_nDataLength) ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS;
\r
301 if (!pi_fReadConfig && pi_pMdDevContext->m_Interface.SetBusData) {
\r
302 pi_pMdDevContext->m_Interface.SetBusData(
\r
303 pi_pMdDevContext->m_Interface.Context,
\r
304 PCI_WHICHSPACE_CONFIG,
\r
306 pi_nPciSpaceOffset,
\r
309 return STATUS_SUCCESS;
\r
312 // fill request parameters
\r
313 l_RwParams.Buffer = pi_pDataBuffer;
\r
314 l_RwParams.Length = pi_nDataLength;
\r
315 l_RwParams.Offset = pi_nPciSpaceOffset;
\r
316 l_RwParams.WhichSpace = PCI_WHICHSPACE_CONFIG;
\r
318 return SendAwaitIrp( pi_pMdDevContext->m_pFdo, pi_pMdDevContext->m_pLdo, IRP_MJ_PNP,
\r
319 pi_fReadConfig ? IRP_MN_READ_CONFIG : IRP_MN_WRITE_CONFIG, &l_RwParams, sizeof(DrvReadWriteConfig_t));
\r
322 } /* DrvReadWritePciConfig */
\r
323 /*------------------------------------------------------------------------------------------------------*/
\r
327 IN PDEVICE_OBJECT pi_pFdo,
\r
328 IN PDEVICE_OBJECT pi_pLdo,
\r
329 IN PBUS_INTERFACE_STANDARD pi_pInterface
\r
332 { /* GetDirectPciInterface */
\r
334 // parameter buffer for the request
\r
335 IO_STACK_LOCATION l_Stack;
\r
337 // clean interface data
\r
338 RtlZeroMemory( (PCHAR)pi_pInterface, sizeof(BUS_INTERFACE_STANDARD) );
\r
340 // fill request parameters
\r
341 l_Stack.Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;
\r
342 l_Stack.Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
\r
343 l_Stack.Parameters.QueryInterface.Version = 1;
\r
344 l_Stack.Parameters.QueryInterface.Interface = (PINTERFACE)pi_pInterface;
\r
345 l_Stack.Parameters.QueryInterface.InterfaceSpecificData = NULL;
\r
347 return SendAwaitIrp( pi_pFdo, pi_pLdo, IRP_MJ_PNP,
\r
348 IRP_MN_QUERY_INTERFACE, &l_Stack.Parameters, sizeof(l_Stack.Parameters));
\r
350 } /* GetDirectPciInterface */
\r
353 IN PBUS_INTERFACE_STANDARD pi_pInterface
\r
356 if (pi_pInterface->InterfaceDereference)
\r
357 pi_pInterface->InterfaceDereference((PVOID)pi_pInterface->Context);
\r
360 #ifdef NOT_USE_MDNTDDK
\r
362 /*------------------------------------------------------------------------------------------------------*/
\r
365 typedef struct _PCI_SLOT_NUMBER {
\r
368 ULONG DeviceNumber:5;
\r
369 ULONG FunctionNumber:3;
\r
374 } PCI_SLOT_NUMBER, *PPCI_SLOT_NUMBER;
\r
378 BOOLEAN PciFindDeviceByBusAndId(
\r
379 IN ULONG pi_MyBus,
\r
380 IN ULONG pi_DevId,
\r
381 IN OUT PULONG po_pSlot )
\r
388 for (l_Slot = *po_pSlot; l_Slot < N_SLOTS; l_Slot++ ) {
\r
389 #pragma warning( push )
\r
390 #pragma warning( disable:4996 )
\r
391 l_Bytes = HalGetBusDataByOffset(
\r
399 #pragma warning( pop )
\r
400 if (l_Bytes != sizeof(ULONG))
\r
401 continue; /* as if - "not found" */
\r
402 if (l_DevId == pi_DevId)
\r
406 if (l_DevId == pi_DevId) {
\r
407 *po_pSlot = l_Slot;
\r
414 BOOLEAN PciFindDeviceById(
\r
415 IN ULONG pi_DevId,
\r
416 IN OUT PULONG po_pBus,
\r
417 IN OUT PULONG po_pSlot )
\r
421 ULONG l_Slot = *po_pSlot;
\r
423 for (l_Bus= *po_pBus; l_Bus < N_BUSES; l_Bus++, l_Slot=0) {
\r
424 if (PciFindDeviceByBusAndId(l_Bus, pi_DevId, &l_Slot))
\r
427 if (l_Bus >= N_BUSES)
\r
430 *po_pSlot = l_Slot;
\r
434 BOOLEAN PciFindBridgeByBus(
\r
435 IN ULONG pi_SecBus,
\r
436 OUT PULONG po_pBus,
\r
437 OUT PULONG po_pSlot )
\r
441 ULONG l_Slot=0, l_Bus=0;
\r
442 ULONG l_DevId = ((int)(23110) << 16) | MLX_VENDOR_ID;
\r
443 ULONG l_SecBus, l_tmp, l_Bytes;
\r
445 for (l_CardNo= 0; l_CardNo < N_CARDS; l_CardNo++, l_Slot=0, l_Bus++) {
\r
446 if (PciFindDeviceById(l_DevId, &l_Bus, &l_Slot)) {
\r
447 /* found a bridge */
\r
448 #pragma warning( push )
\r
449 #pragma warning( disable:4996 )
\r
450 l_Bytes = HalGetBusDataByOffset(
\r
455 24, /* 24 - PrimaryBus, 25 - SecondaryBus, 26 - SubordinateBus */
\r
458 #pragma warning( pop )
\r
459 if (l_Bytes != sizeof(ULONG))
\r
460 continue; /* as if - "not found" */
\r
461 l_SecBus = (l_tmp >> 16) & 255;
\r
462 if ( l_SecBus == pi_SecBus )
\r
463 break; /* found !!! */
\r
466 if (l_CardNo >= N_CARDS)
\r
469 *po_pSlot = l_Slot;
\r
474 BOOLEAN PciFindPdoByPdoAndLocation(
\r
475 IN PDEVICE_OBJECT pi_pPdo,
\r
478 IN ULONG pi_Function,
\r
479 OUT PDEVICE_OBJECT * po_pPdo )
\r
481 PDRIVER_OBJECT l_pDrv;
\r
482 PDEVICE_OBJECT l_pPdo;
\r
484 ULONG l_Slot, l_Bus, l_Function;
\r
486 // get to the PCI driver
\r
487 l_pDrv = pi_pPdo->DriverObject;
\r
489 // loop over all the PCI driver devices
\r
490 for ( l_pPdo = l_pDrv->DeviceObject; l_pPdo; l_pPdo = l_pPdo->NextDevice ) {
\r
491 // if it's not PDO - skip it
\r
492 if (!(l_pPdo->Flags & DO_BUS_ENUMERATED_DEVICE))
\r
494 // get the location of the device of that PDO
\r
495 l_Status = MdGetDevLocation( l_pPdo, &l_Bus, &l_Slot, &l_Function );
\r
496 if (l_Status != STATUS_SUCCESS)
\r
498 // check, whether it's our device
\r
499 if (l_Bus == pi_Bus && l_Slot == pi_Slot && l_Function == pi_Function)
\r
503 // check whether we found the PDO
\r
510 /*------------------------------------------------------------------------------------------------------*/
\r
515 IN PVOID pi_pBuffer,
\r
522 #pragma warning( push )
\r
523 #pragma warning( disable:4996 )
\r
524 l_Bytes = HalGetBusData(
\r
531 #pragma warning( pop )
\r
532 if (l_Bytes != PCI_HDR_SIZE<<2) {
\r
533 return STATUS_UNSUCCESSFUL;
\r
536 return STATUS_SUCCESS;
\r
539 /*------------------------------------------------------------------------------------------------------*/
\r
542 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
545 PDEVICE_OBJECT l_pLdo = pi_pMdDevContext->m_pLdo; /* Shrimp's PDO */
\r
546 BUS_INTERFACE_STANDARD l_Interface, *l_pInterface = &l_Interface;
\r
547 ULONG l_Value, l_NewValue;
\r
548 NTSTATUS l_Status = STATUS_SUCCESS;
\r
549 PDEVICE_OBJECT l_pFdo;
\r
551 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_SD)
\r
552 { /* fix HCA command register from SHRIMP */
\r
554 /* get the PDO of Bridge */
\r
555 if (!PciFindPdoByPdoAndLocation( l_pLdo,
\r
556 pi_pMdDevContext->m_BridgeHdr.m_Bus,
\r
557 pi_pMdDevContext->m_BridgeHdr.m_Slot,
\r
559 MdKdPrint( DBGLVL_LOW,("(PciHdrWrite) Not found bridge PDO - can't restore the PCI header \n" ));
\r
560 return STATUS_UNSUCCESSFUL;
\r
562 l_pFdo = l_pLdo->AttachedDevice;
\r
564 // open interface to PCI driver
\r
565 l_Status = PciIfOpen( l_pFdo, l_pLdo, l_pInterface );
\r
566 if (!NT_SUCCESS(l_Status)) {
\r
567 MdKdPrint( DBGLVL_LOW,("(PciFixCmdReg) PciIfOpen failed (0x%x) \n", l_Status ));
\r
572 if (l_pInterface->GetBusData)
\r
573 l_pInterface->GetBusData( l_pInterface->Context, PCI_WHICHSPACE_CONFIG,
\r
574 (PVOID)&l_Value, 4, sizeof(ULONG) );
\r
577 l_NewValue = l_Value | 7;
\r
580 if (l_pInterface->SetBusData)
\r
581 l_pInterface->SetBusData( l_pInterface->Context, PCI_WHICHSPACE_CONFIG,
\r
582 (PVOID)&l_NewValue, 4, sizeof(ULONG) );
\r
585 PciIfClose( l_pInterface );
\r
587 } /* fix HCA command register from SHRIMP */
\r
589 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR )
\r
590 { /* fix command register for TAVOR */
\r
592 l_pInterface = &pi_pMdDevContext->m_Interface;
\r
594 if (l_pInterface->GetBusData)
\r
595 l_pInterface->GetBusData( l_pInterface->Context, PCI_WHICHSPACE_CONFIG,
\r
596 (PVOID)&l_Value, 4, sizeof(ULONG) );
\r
599 l_NewValue = l_Value | 7;
\r
602 if (l_pInterface->SetBusData)
\r
603 l_pInterface->SetBusData( l_pInterface->Context, PCI_WHICHSPACE_CONFIG,
\r
604 (PVOID)&l_NewValue, 4, sizeof(ULONG) );
\r
606 } /* fix command register for TAVOR */
\r
608 MdKdPrint( DBGLVL_LOW,("(PciFixCmdReg) Cmd register: Old 0x%x New 0x%x \n",
\r
609 l_Value, l_NewValue ));
\r
611 return STATUS_SUCCESS;
\r
614 /*------------------------------------------------------------------------------------------------------*/
\r
617 typedef enum { WRITE_WITH_SET_BUS, WRITE_WITH_SET_BUS_BY_OFFSET, WRITE_WITH_PCI_CONFIG } PCI_WRITE_T;
\r
621 IN PMD_DEV_CONTEXT_T pi_pMdDevContext,
\r
622 IN PCHAR pi_pBuffer,
\r
625 IN PCI_WRITE_T pi_Technique
\r
628 if (pi_Technique == WRITE_WITH_PCI_CONFIG) {
\r
629 NTSTATUS l_Status = STATUS_SUCCESS;
\r
630 PDEVICE_OBJECT l_pLdo = pi_pMdDevContext->m_pLdo; /* Shrimp's PDO */
\r
631 BUS_INTERFACE_STANDARD l_Interface;
\r
632 PDEVICE_OBJECT l_pFdo;
\r
634 /* the following algorithm sutes only for SD */
\r
635 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_SD) {
\r
638 KSEM_ACQ(&pi_pMdDevContext->m_Sem);
\r
640 /* get the PDO of Bridge */
\r
641 if (!PciFindPdoByPdoAndLocation( l_pLdo,
\r
642 pi_pMdDevContext->m_BridgeHdr.m_Bus,
\r
643 pi_pMdDevContext->m_BridgeHdr.m_Slot,
\r
645 MdKdPrint( DBGLVL_LOW,("(PciHdrWrite) Not found bridge PDO - can't restore the PCI header \n" ));
\r
646 return STATUS_UNSUCCESSFUL;
\r
648 l_pFdo = l_pLdo->AttachedDevice;
\r
650 // open interface to PCI driver
\r
651 l_Status = PciIfOpen( l_pFdo, l_pLdo, &l_Interface );
\r
652 if (!NT_SUCCESS(l_Status)) {
\r
653 MdKdPrint( DBGLVL_LOW,("(PciHdrWrite) PciIfOpen failed (0x%x) \n", l_Status ));
\r
658 if (l_Interface.SetBusData) {
\r
659 l_Interface.SetBusData( l_Interface.Context, PCI_WHICHSPACE_CONFIG,
\r
660 pi_pBuffer + 0x08, 0x08, PCI_HDR_SIZE - 0x08 );
\r
663 // write some fields once more
\r
664 if (l_Interface.SetBusData) {
\r
665 /* Bridge Control Register */
\r
666 l_Interface.SetBusData( l_Interface.Context, PCI_WHICHSPACE_CONFIG,
\r
667 pi_pBuffer + 0x3c, 0x3c, 4 );
\r
668 /* The rest of header, including PCIX command register */
\r
669 l_Interface.SetBusData( l_Interface.Context, PCI_WHICHSPACE_CONFIG,
\r
670 pi_pBuffer + PCI_HDR_SIZE, PCI_HDR_SIZE, (PCI_HDR_SIZE<<2) - PCI_HDR_SIZE );
\r
671 /* Command Register */
\r
672 l_Interface.SetBusData( l_Interface.Context, PCI_WHICHSPACE_CONFIG,
\r
673 pi_pBuffer + 0x04, 0x04, 4 );
\r
677 PciIfClose( &l_Interface );
\r
679 KSEM_REL(&pi_pMdDevContext->m_Sem);
\r
683 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR) {
\r
686 KSEM_ACQ(&pi_pMdDevContext->m_Sem);
\r
688 /* get the PDO of Bridge */
\r
689 if (!PciFindPdoByPdoAndLocation( l_pLdo,
\r
690 pi_pMdDevContext->m_BridgeHdr.m_Bus,
\r
691 pi_pMdDevContext->m_BridgeHdr.m_Slot,
\r
693 MdKdPrint( DBGLVL_LOW,("(PciHdrWrite) Not found bridge PDO - can't restore the PCI header \n" ));
\r
694 return STATUS_UNSUCCESSFUL;
\r
696 l_pFdo = l_pLdo->AttachedDevice;
\r
698 // open interface to PCI driver
\r
699 l_Status = PciIfOpen( l_pFdo, l_pLdo, &l_Interface );
\r
700 if (!NT_SUCCESS(l_Status)) {
\r
701 MdKdPrint( DBGLVL_LOW,("(PciHdrWrite) PciIfOpen failed (0x%x) \n", l_Status ));
\r
706 if (l_Interface.SetBusData) {
\r
707 l_Interface.SetBusData( l_Interface.Context, PCI_WHICHSPACE_CONFIG,
\r
708 pi_pBuffer + 0x08, 0x08, PCI_HDR_SIZE - 0x08 );
\r
711 // write some fields once more
\r
712 if (l_Interface.SetBusData) {
\r
713 /* Bridge Control Register */
\r
714 l_Interface.SetBusData( l_Interface.Context, PCI_WHICHSPACE_CONFIG,
\r
715 pi_pBuffer + 0x3c, 0x3c, 4 );
\r
716 /* The rest of header, including PCIX command register */
\r
717 l_Interface.SetBusData( l_Interface.Context, PCI_WHICHSPACE_CONFIG,
\r
718 pi_pBuffer + PCI_HDR_SIZE, PCI_HDR_SIZE, (PCI_HDR_SIZE<<2) - PCI_HDR_SIZE );
\r
719 /* Command Register */
\r
720 l_Interface.SetBusData( l_Interface.Context, PCI_WHICHSPACE_CONFIG,
\r
721 pi_pBuffer + 0x04, 0x04, 4 );
\r
725 PciIfClose( &l_Interface );
\r
726 KSEM_REL(&pi_pMdDevContext->m_Sem);
\r
730 return STATUS_UNSUCCESSFUL;
\r
736 if (pi_Technique == WRITE_WITH_SET_BUS) {
\r
739 #pragma warning( push )
\r
740 #pragma warning( disable:4996 )
\r
741 l_Bytes = HalSetBusData(
\r
748 #pragma warning( pop )
\r
749 return STATUS_SUCCESS;
\r
754 if (pi_Technique == WRITE_WITH_SET_BUS_BY_OFFSET) {
\r
758 PULONG l_pBuf = (PULONG)pi_pBuffer;
\r
760 for (i = 0; i < PCI_HDR_SIZE; i++) {
\r
761 #pragma warning( push )
\r
762 #pragma warning( disable:4996 )
\r
763 l_Bytes = HalSetBusDataByOffset(
\r
771 #pragma warning( pop )
\r
773 return STATUS_SUCCESS;
\r
777 return STATUS_UNSUCCESSFUL;
\r
779 /*------------------------------------------------------------------------------------------------------*/
\r
783 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
786 ULONG l_MyBus = pi_pMdDevContext->m_BusNumber;
\r
787 ULONG l_Slot, l_SecBus;
\r
789 NTSTATUS l_Status = STATUS_SUCCESS;
\r
791 /* prevent RESET if header not saved */
\r
792 pi_pMdDevContext->m_fMayReset = FALSE;
\r
794 /* NB: functionality supported only for MD_DEV_IX_TAVOR_SD and MD_DEV_IX_TAVOR_BD */
\r
795 if ((pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_SD) ||
\r
796 (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_BD)) {
\r
801 l_DevId = (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_BD) ?
\r
802 (((int)(MD_DEV_ID_TAVOR_BD) << 16) | MLX_VENDOR_ID) :
\r
803 (((int)(MD_DEV_ID_TAVOR_SD) << 16) | MLX_VENDOR_ID);
\r
805 if (PciFindDeviceByBusAndId( l_MyBus, l_DevId, &l_Slot )) {
\r
806 l_Status = PciHdrRead( &pi_pMdDevContext->m_MyHdr.m_Hdr[0], l_MyBus, l_Slot);
\r
807 if (l_Status != STATUS_SUCCESS)
\r
810 else { /* not found my device */
\r
811 return STATUS_UNSUCCESSFUL;
\r
813 pi_pMdDevContext->m_MyHdr.m_Bus = l_MyBus;
\r
814 pi_pMdDevContext->m_MyHdr.m_Slot = l_Slot;
\r
820 l_DevId = ((int)(MD_DEV_ID_TAVOR) << 16) | MLX_VENDOR_ID;
\r
822 if (PciFindDeviceByBusAndId( l_MyBus, l_DevId, &l_Slot )) {
\r
823 l_Status = PciHdrRead( &pi_pMdDevContext->m_HcaHdr.m_Hdr[0], l_MyBus, l_Slot);
\r
824 if (l_Status != STATUS_SUCCESS)
\r
827 else { /* not found HCA device */
\r
828 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_SD)
\r
829 return STATUS_UNSUCCESSFUL;
\r
830 pi_pMdDevContext->m_HcaHdr.m_Hdr[0] = 0; /* mark, that PCI header was not saved */
\r
832 pi_pMdDevContext->m_HcaHdr.m_Bus = l_MyBus;
\r
833 pi_pMdDevContext->m_HcaHdr.m_Slot = l_Slot;
\r
838 l_SecBus = l_MyBus;
\r
839 if (PciFindBridgeByBus( l_SecBus, &l_MyBus, &l_Slot )) {
\r
840 l_Status = PciHdrRead( &pi_pMdDevContext->m_BridgeHdr.m_Hdr[0], l_MyBus, l_Slot);
\r
841 if (l_Status != STATUS_SUCCESS)
\r
844 else { /* not found Bridge device */
\r
845 return STATUS_UNSUCCESSFUL;
\r
847 pi_pMdDevContext->m_BridgeHdr.m_Bus = l_MyBus;
\r
848 pi_pMdDevContext->m_BridgeHdr.m_Slot = l_Slot;
\r
852 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR ) {
\r
857 l_DevId = ((int)(MD_DEV_ID_TAVOR) << 16) | MLX_VENDOR_ID;
\r
858 pi_pMdDevContext->m_HcaHdr.m_Hdr[0] = 0; /* mark, that PCI header was not saved */
\r
860 if (PciFindDeviceByBusAndId( l_MyBus, l_DevId, &l_Slot )) {
\r
861 l_Status = PciHdrRead( &pi_pMdDevContext->m_HcaHdr.m_Hdr[0], l_MyBus, l_Slot);
\r
862 if (l_Status != STATUS_SUCCESS)
\r
865 else { /* not found HCA device */
\r
866 return STATUS_UNSUCCESSFUL;
\r
868 pi_pMdDevContext->m_HcaHdr.m_Bus = l_MyBus;
\r
869 pi_pMdDevContext->m_HcaHdr.m_Slot = l_Slot;
\r
874 l_SecBus = l_MyBus;
\r
875 if (PciFindBridgeByBus( l_SecBus, &l_MyBus, &l_Slot )) {
\r
876 l_Status = PciHdrRead( &pi_pMdDevContext->m_BridgeHdr.m_Hdr[0], l_MyBus, l_Slot);
\r
877 if (l_Status != STATUS_SUCCESS)
\r
880 else { /* not found Bridge device */
\r
881 return STATUS_UNSUCCESSFUL;
\r
883 pi_pMdDevContext->m_BridgeHdr.m_Bus = l_MyBus;
\r
884 pi_pMdDevContext->m_BridgeHdr.m_Slot = l_Slot;
\r
887 return STATUS_UNSUCCESSFUL;
\r
890 pi_pMdDevContext->m_fMayReset = TRUE;
\r
892 return STATUS_SUCCESS;
\r
895 /*------------------------------------------------------------------------------------------------------*/
\r
899 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
903 if (((pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_SD) ||
\r
904 (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_BD))) {
\r
908 if (pi_pMdDevContext->m_BridgeHdr.m_Hdr[0]) {
\r
909 PciHdrWrite( pi_pMdDevContext,
\r
910 (PCHAR)&pi_pMdDevContext->m_BridgeHdr.m_Hdr[0],
\r
911 pi_pMdDevContext->m_BridgeHdr.m_Bus,
\r
912 pi_pMdDevContext->m_BridgeHdr.m_Slot,
\r
913 WRITE_WITH_PCI_CONFIG);
\r
919 if (pi_pMdDevContext->m_MyHdr.m_Hdr[0]) {
\r
920 PciHdrWrite( pi_pMdDevContext,
\r
921 (PCHAR)&pi_pMdDevContext->m_MyHdr.m_Hdr[0],
\r
922 pi_pMdDevContext->m_MyHdr.m_Bus,
\r
923 pi_pMdDevContext->m_MyHdr.m_Slot,
\r
924 WRITE_WITH_SET_BUS);
\r
930 if (pi_pMdDevContext->m_HcaHdr.m_Hdr[0]) {
\r
931 PciHdrWrite( pi_pMdDevContext,
\r
932 (PCHAR)&pi_pMdDevContext->m_HcaHdr.m_Hdr[0],
\r
933 pi_pMdDevContext->m_HcaHdr.m_Bus,
\r
934 pi_pMdDevContext->m_HcaHdr.m_Slot,
\r
935 WRITE_WITH_SET_BUS);
\r
939 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR ) {
\r
944 if (pi_pMdDevContext->m_BridgeHdr.m_Hdr[0]) {
\r
945 PciHdrWrite( pi_pMdDevContext,
\r
946 (PCHAR)&pi_pMdDevContext->m_BridgeHdr.m_Hdr[0],
\r
947 pi_pMdDevContext->m_BridgeHdr.m_Bus,
\r
948 pi_pMdDevContext->m_BridgeHdr.m_Slot,
\r
949 WRITE_WITH_PCI_CONFIG);
\r
955 if (pi_pMdDevContext->m_HcaHdr.m_Hdr[0]) {
\r
956 PciHdrWrite( pi_pMdDevContext,
\r
957 (PCHAR)&pi_pMdDevContext->m_HcaHdr.m_Hdr[0],
\r
958 pi_pMdDevContext->m_HcaHdr.m_Bus,
\r
959 pi_pMdDevContext->m_HcaHdr.m_Slot,
\r
960 WRITE_WITH_SET_BUS);
\r
964 return STATUS_UNSUCCESSFUL;
\r
966 return STATUS_SUCCESS;
\r
969 /*------------------------------------------------------------------------------------------------------*/
\r
973 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
976 ULONG l_ResetOffset = 0x0f0010;
\r
977 ULONG l_ResetValue = 0x01000000; /* 1 in BigEndian */
\r
983 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_BD) { /* we are burner device */
\r
984 PCICONF_WRITE( pi_pMdDevContext,
\r
990 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR) { /* we are Tavor device */
\r
991 l_Status = PciDevReset(pi_pMdDevContext, l_ResetOffset, l_ResetValue );
\r
994 if (pi_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR_SD) { /* we are service device */
\r
995 l_Status = PciDevReset(pi_pMdDevContext, l_ResetOffset, l_ResetValue );
\r
997 else { /* other devices not supported */
\r
998 l_Status = STATUS_UNSUCCESSFUL;
\r
1002 * wait for RESET end
\r
1005 #define TIMEOUT_IN_USECS 1500000 /* 1.5 sec */
\r
1006 LARGE_INTEGER timeout;
\r
1007 timeout.QuadPart = - 10 * TIMEOUT_IN_USECS;
\r
1008 KeDelayExecutionThread( KernelMode, FALSE, &timeout );
\r
1014 l_Status = PciHdrRestore( pi_pMdDevContext );
\r
1023 /*------------------------------------------------------------------------------------------------------*/
\r
1025 NTSTATUS ReadBarInfo(
\r
1026 PMD_DEV_CONTEXT_T pi_pMdDevContext,
\r
1027 ULONG pi_LowOffset,
\r
1028 ULONG pi_HighOffset,
\r
1029 ULONG pi_SizeOffset,
\r
1030 PMD_BAR_T pi_pBar,
\r
1036 Routine Description:
\r
1038 This routine reads BAR inforamtion from CR-space and stores it to device context
\r
1042 pi_pMdDevContext....... My device context
\r
1043 pi_LowOffset........... offset of low part of BAR address
\r
1044 pi_HighOffset.......... offset of high part of BAR address
\r
1045 pi_SizeOffset.......... offset of BAR size
\r
1046 pi_pBar ............... pointer to BAR descriptor
\r
1047 pi_BarName............. BAR name for debug print
\r
1048 pi_BarNum.............. BAR number
\r
1055 { /* ReadBarInfo */
\r
1057 ULONG l_LowPart, l_HighPart, l_Size;
\r
1058 NTSTATUS l_Status;
\r
1059 LARGE_INTEGER l_Offset = { 0,0 };
\r
1065 /* read CR-space */
\r
1066 PCICONF_READ( pi_pMdDevContext, pi_LowOffset, &l_LowPart, l_Status );
\r
1067 if (!NT_SUCCESS(l_Status))
\r
1069 PCICONF_READ( pi_pMdDevContext, pi_HighOffset, &l_HighPart, l_Status );
\r
1070 if (!NT_SUCCESS(l_Status))
\r
1072 PCICONF_READ( pi_pMdDevContext, pi_SizeOffset, &l_Size, l_Status );
\r
1073 if (!NT_SUCCESS(l_Status))
\r
1076 /* store BAR parameters */
\r
1077 pi_pBar->m_MemPhysAddr.LowPart = l_LowPart & 0xfff00000;
\r
1078 pi_pBar->m_MemPhysAddr.HighPart = l_HighPart;
\r
1079 pi_pBar->m_ulMemSize = 1 << ((l_Size & 63) + 20); /* l_size is 6 bit field */
\r
1080 pi_pBar->m_usMemFlags = 0;
\r
1081 pi_pBar->m_ulKernelSize = pi_pBar->m_ulMemSize;
\r
1082 pi_pBar->m_ulKernelOffset = 0;
\r
1084 /* recalculate boudaries of mapped memory for DDR */
\r
1085 if (pi_BarNum == 2 && pi_pMdDevContext->m_ulDdrMapSize != -1) {
\r
1086 pi_pBar->m_ulKernelSize = pi_pMdDevContext->m_ulDdrMapSize;
\r
1087 pi_pBar->m_ulKernelOffset = pi_pMdDevContext->m_ulDdrMapOffset;
\r
1088 l_Offset.LowPart = pi_pMdDevContext->m_ulDdrMapOffset;
\r
1089 } /* for DDR - map some subset of memory */
\r
1091 /* map physical address into virtual kernel one */
\r
1092 l_Offset.QuadPart += pi_pBar->m_MemPhysAddr.QuadPart;
\r
1093 pi_pBar->m_pKernelAddr = (PUCHAR) MmMapIoSpace(
\r
1094 l_Offset, pi_pBar->m_ulKernelSize, MmNonCached);
\r
1095 if (!pi_pBar->m_pKernelAddr) return STATUS_NO_MEMORY;
\r
1098 MdKdPrint( DBGLVL_LOW ,("(ReadBarInfo) Dev %d %s: Phys 0x%I64x Size 0x%x, Virt 0x%x Size 0x%x \n",
\r
1099 g_DevParams[pi_pMdDevContext->m_eDevType].m_DevId,
\r
1100 pi_BarName, pi_pBar->m_MemPhysAddr, pi_pBar->m_ulMemSize,
\r
1101 pi_pBar->m_pKernelAddr, pi_pBar->m_ulKernelSize ));
\r
1103 return STATUS_SUCCESS;
\r
1106 NTSTATUS ReadBars(PMD_DEV_CONTEXT_T pi_pMdDevContext)
\r
1108 NTSTATUS l_Status;
\r
1109 PMD_BAR_T l_pBar;
\r
1112 l_pBar = &pi_pMdDevContext->m_Cr;
\r
1113 l_Status = ReadBarInfo( pi_pMdDevContext,
\r
1114 BYTE_OFFSET_A(Tavor->pcu0.pcu_address_decoder.hca_bar_0_lsbs),
\r
1115 BYTE_OFFSET_A(Tavor->pcu0.pcu_address_decoder.hca_bar_0_msbs),
\r
1116 BYTE_OFFSET_A(Tavor->pcu0.pcu_address_decoder.hca_bar_size_0),
\r
1117 l_pBar, "CR", 0 );
\r
1118 if (!NT_SUCCESS(l_Status))
\r
1122 l_pBar = &pi_pMdDevContext->m_Uar;
\r
1123 l_Status = ReadBarInfo( pi_pMdDevContext,
\r
1124 BYTE_OFFSET_A(Tavor->pcu0.pcu_address_decoder.hca_bar_1_lsbs),
\r
1125 BYTE_OFFSET_A(Tavor->pcu0.pcu_address_decoder.hca_bar_1_msbs),
\r
1126 BYTE_OFFSET_A(Tavor->pcu0.pcu_address_decoder.hca_bar_size_1),
\r
1127 l_pBar, "UAR", 1 );
\r
1128 if (!NT_SUCCESS(l_Status))
\r
1132 l_pBar = &pi_pMdDevContext->m_Ddr;
\r
1133 l_Status = ReadBarInfo( pi_pMdDevContext,
\r
1134 BYTE_OFFSET_A(Tavor->pcu0.pcu_address_decoder.dmu_bar_0_lsbs),
\r
1135 BYTE_OFFSET_A(Tavor->pcu0.pcu_address_decoder.dmu_bar_0_msbs),
\r
1136 BYTE_OFFSET_A(Tavor->pcu0.pcu_address_decoder.dmu_bar_size_0),
\r
1137 l_pBar, "DDR", 2 );
\r
1138 if (!NT_SUCCESS(l_Status))
\r
1141 return STATUS_SUCCESS;
\r
1144 NTSTATUS ConfIoctl(
\r
1145 IN PMD_DEV_CONTEXT_T pi_pMdDevContext,
\r
1146 IN PMD_PCS_CONTEXT_T pi_pPcsContext,
\r
1147 IN ULONG pi_nIoControlCode,
\r
1148 IN PVOID pi_pInBuffer,
\r
1149 IN ULONG pi_nInBufLength,
\r
1150 IN PVOID pi_pOutBuffer,
\r
1151 IN ULONG pi_nOutBufLength,
\r
1152 OUT PULONG po_pnBytes
\r
1155 NTSTATUS l_Status;
\r
1157 PULONG l_pData, l_Data;
\r
1158 PPCICONF_MODIFY_T pm;
\r
1159 PPCICONF_WRITE4_T pw;
\r
1163 switch (pi_nIoControlCode)
\r
1164 { /* handle Ioctls */
\r
1166 case UDLL_MAKE_IOCTL(WIN_PCICONF_READ4):
\r
1167 /* call_result_t PciConfRead4( HANDLE h, DWORD offset, DWORD * p_data ) */
\r
1168 l_pOffset = (PULONG)pi_pInBuffer;
\r
1169 l_pData = (PULONG)pi_pOutBuffer;
\r
1170 PCICONF_READ( pi_pMdDevContext, *l_pOffset, l_pData, l_Status );
\r
1171 if (!NT_SUCCESS(l_Status)) *po_pnBytes = sizeof(ULONG);
\r
1174 case UDLL_MAKE_IOCTL(WIN_PCICONF_WRITE4):
\r
1175 /* call_result_t PciConfWrite4( HANDLE h, PPCICONF_WRITE4_T params ) */
\r
1176 pw =(PPCICONF_WRITE4_T)pi_pInBuffer;
\r
1177 PCICONF_WRITE( pi_pMdDevContext, pw->offset, pw->data, l_Status );
\r
1180 case UDLL_MAKE_IOCTL(WIN_PCICONF_MODIFY):
\r
1181 /* call_result_t PciConfModify( HANDLE h, PPCICONF_MODIFY_T params, DWORD * p_old_data ) */
\r
1182 pm = (PPCICONF_MODIFY_T)pi_pInBuffer;
\r
1183 l_pData = (PULONG)pi_pOutBuffer;
\r
1185 PCICONF_READ( pi_pMdDevContext, pm->offset, &l_Data, l_Status );
\r
1186 if (!NT_SUCCESS(l_Status)) break;
\r
1187 *l_Data = (*l_Data & ~pm->mask) | (pm->data & pm->mask);
\r
1188 l_Status = PCICONF_DATA_WRITE(pi_pMdDevContext, l_Data );
\r
1189 if (!NT_SUCCESS(l_Status)) *po_pnBytes = sizeof(ULONG);
\r
1192 case UDLL_MAKE_IOCTL(WIN_SOFT_RESET):
\r
1194 l_Status = PciReset( pi_pMdDevContext );
\r
1199 MdKdPrint( DBGLVL_DEFAULT,("(ConfIoctl) Unsupported Ioctl 0x%x\n", pi_nIoControlCode));
\r
1200 l_Status = STATUS_NOT_IMPLEMENTED;
\r
1203 } /* handle Ioctls */
\r
1210 IN PMD_DEV_CONTEXT_T pi_pMdDevContext,
\r
1214 NTSTATUS l_Status;
\r
1215 PIO_STACK_LOCATION l_pIrpStack;
\r
1217 /* get pointer to IRP stack */
\r
1218 l_pIrpStack = IoGetCurrentIrpStackLocation (pi_pIrp);
\r
1220 switch (l_pIrpStack->Parameters.DeviceIoControl.IoControlCode)
\r
1221 { /* handle Ioctls */
\r
1223 case UDLL_MAKE_IOCTL_BUF(WIN_PCICONF_READ4):
\r
1224 /* call_result_t PciConfRead4( HANDLE h, DWORD offset, DWORD * p_data ) */
\r
1225 PCICONF_READ( pi_pMdDevContext,
\r
1226 *(PULONG)pi_pIrp->AssociatedIrp.SystemBuffer,
\r
1227 (PULONG)pi_pIrp->AssociatedIrp.SystemBuffer,
\r
1229 if (NT_SUCCESS(l_Status))
\r
1230 pi_pIrp->IoStatus.Information = sizeof(ULONG);
\r
1232 pi_pIrp->IoStatus.Information = 0;
\r
1235 case UDLL_MAKE_IOCTL_BUF(WIN_PCICONF_WRITE4):
\r
1236 /* call_result_t PciConfWrite4( HANDLE h, PPCICONF_WRITE4_T params ) */
\r
1237 PCICONF_WRITE( pi_pMdDevContext,
\r
1238 *((PULONG)pi_pIrp->AssociatedIrp.SystemBuffer + 0),
\r
1239 *((PULONG)pi_pIrp->AssociatedIrp.SystemBuffer + 1),
\r
1241 pi_pIrp->IoStatus.Information = 0;
\r
1244 case UDLL_MAKE_IOCTL(WIN_SOFT_RESET):
\r
1246 l_Status = PciReset( pi_pMdDevContext );
\r
1248 pi_pIrp->IoStatus.Information = 0;
\r
1252 MdKdPrint( DBGLVL_DEFAULT,("(ConfIoctl) Unsupported Ioctl 0x%x\n",
\r
1253 l_pIrpStack->Parameters.DeviceIoControl.IoControlCode));
\r
1254 pi_pIrp->IoStatus.Information = 0;
\r
1255 l_Status = STATUS_NOT_IMPLEMENTED;
\r
1258 } /* handle Ioctls */
\r
1263 void SetPciMasterBit(
\r
1264 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
1268 ULONG l_Offset = 4;
\r
1270 PCICONF_DWORD_READ( pi_pMdDevContext, &l_Data, l_Offset );
\r
1271 MdKdPrint( DBGLVL_LOW,("(SetPciMasterBit) CmdStatus Reg 0x%x\n",l_Data));
\r
1273 PCICONF_DWORD_WRITE( pi_pMdDevContext, l_Data, l_Offset );
\r
1274 PCICONF_DWORD_READ( pi_pMdDevContext, &l_Data, l_Offset );
\r
1275 MdKdPrint( DBGLVL_LOW,("(SetPciMasterBit) CmdStatus Reg 0x%x\n",l_Data));
\r
1278 NTSTATUS MdMosalHelper(
\r
1279 IN PMD_DEV_CONTEXT_T pi_pMdDevContext,
\r
1283 NTSTATUS l_Status = STATUS_NOT_IMPLEMENTED;
\r
1285 case MD_HELPER_CARD_RESET:
\r
1287 //l_Status = PciReset( pi_pMdDevContext );
\r