2 * Copyright (c) 2004-2005 Mellanox Technologies Ltd. All rights reserved.
\r
4 * This software is available to you under the OpenIB.org BSD license
\r
7 * Redistribution and use in source and binary forms, with or
\r
8 * without modification, are permitted provided that the following
\r
9 * conditions are met:
\r
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\r
15 * - Redistributions in binary form must reproduce the above
\r
16 * copyright notice, this list of conditions and the following
\r
17 * disclaimer in the documentation and/or other materials
\r
18 * provided with the distribution.
\r
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
34 /*------------------------------------------------------------------------------------------------------*/
\r
40 ULONG pi_UniqueErrorCode,
\r
41 ULONG pi_FinalStatus,
\r
42 ULONG pi_nDataItems,
\r
47 Routine Description:
\r
48 Writes an event log entry to the event log.
\r
52 pi_pIoObject......... The IO object ( driver object or device object ).
\r
53 pi_ErrorCode......... The error code.
\r
54 pi_UniqueErrorCode... A specific error code.
\r
55 pi_FinalStatus....... The final status.
\r
56 pi_nDataItems........ Number of data items.
\r
66 { /* WriteEventLogEntry */
\r
68 /* Variable argument list */
\r
70 /* Pointer to an error log entry */
\r
71 PIO_ERROR_LOG_PACKET l_pErrorLogEntry;
\r
73 /* Init the variable argument list */
\r
74 va_start(l_Argptr, pi_nDataItems);
\r
76 /* Allocate an error log entry */
\r
78 (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
\r
80 (UCHAR)(sizeof(IO_ERROR_LOG_PACKET)+pi_nDataItems*sizeof(ULONG))
\r
82 /* Check allocation */
\r
83 if ( l_pErrorLogEntry != NULL)
\r
86 /* Data item index */
\r
87 USHORT l_nDataItem ;
\r
89 /* Set the error log entry header */
\r
90 l_pErrorLogEntry->ErrorCode = pi_ErrorCode;
\r
91 l_pErrorLogEntry->DumpDataSize = (USHORT) (pi_nDataItems*sizeof(ULONG));
\r
92 l_pErrorLogEntry->SequenceNumber = 0;
\r
93 l_pErrorLogEntry->MajorFunctionCode = 0;
\r
94 l_pErrorLogEntry->IoControlCode = 0;
\r
95 l_pErrorLogEntry->RetryCount = 0;
\r
96 l_pErrorLogEntry->UniqueErrorValue = pi_UniqueErrorCode;
\r
97 l_pErrorLogEntry->FinalStatus = pi_FinalStatus;
\r
99 /* Insert the data items */
\r
100 for (l_nDataItem = 0; l_nDataItem < pi_nDataItems; l_nDataItem++)
\r
101 { /* Inset a data item */
\r
103 /* Current data item */
\r
104 int l_CurDataItem ;
\r
106 /* Get next data item */
\r
107 l_CurDataItem = va_arg( l_Argptr, int);
\r
109 /* Put it into the data array */
\r
110 l_pErrorLogEntry->DumpData[l_nDataItem] = l_CurDataItem ;
\r
112 } /* Inset a data item */
\r
114 /* Write the packet */
\r
115 IoWriteErrorLogEntry(l_pErrorLogEntry);
\r
119 /* Term the variable argument list */
\r
122 } /* WriteEventLogEntry */
\r
124 /*------------------------------------------------------------------------------------------------------*/
\r
129 IN PDRIVER_OBJECT pi_pDriverObject,
\r
130 IN PUNICODE_STRING pi_pNtDeviceName,
\r
131 IN PUNICODE_STRING pi_pWin32DeviceName,
\r
132 IN int pi_nExtSize,
\r
133 OUT PMD_DEV_CONTEXT_T * po_ppMdDevContext
\r
137 Routine Description:
\r
138 This routine creates a device object, the symbolic link in \DosDevices and allocates device extension
\r
140 A symbolic link must be created between the device name and an entry
\r
141 in \DosDevices in order to allow Win32 applications to open the device.
\r
146 pi_pDriverObject........ pointer to driver object
\r
147 pi_pNtDeviceName........ NT device name
\r
148 pi_pWin32DeviceName..... Win32 device name
\r
149 pi_nExtSize............. Device xontext size
\r
150 po_ppMdDevContext....... The device context
\r
154 STATUS_SUCCESS if the device and link are created correctly, otherwise
\r
155 an error indicating the reason for failure.
\r
158 { /* MdAddDevice */
\r
160 /* Status of utility calls */
\r
162 /* The address of the new created device object */
\r
163 PDEVICE_OBJECT l_pFdo = NULL;
\r
164 /* The Md device context ( l_pDeviceObject extension ) */
\r
165 PMD_DEV_CONTEXT_T l_pMdDevContext;
\r
168 /* Create a new device */
\r
169 l_Status = IoCreateDevice(
\r
173 FILE_DEVICE_UNKNOWN,
\r
175 FALSE, /* Not Exclusive */
\r
179 /* If device creation failed return the error code */
\r
180 if ( !NT_SUCCESS(l_Status) )
\r
181 { /* Device creation failed */
\r
183 /* Return error code */
\r
186 } /* Device creation failed */
\r
189 * Create the symbolic link.
\r
191 l_Status = IoCreateSymbolicLink( pi_pWin32DeviceName, pi_pNtDeviceName );
\r
194 * If we we couldn't create the link then
\r
195 * abort installation... delete the created device
\r
197 if ( !NT_SUCCESS( l_Status ) )
\r
198 { /* Create symbolic link failed */
\r
200 /* Delete the created device */
\r
201 IoDeleteDevice( l_pFdo );
\r
205 } /* Create symbolic link failed */
\r
208 * Set up the rest of the device info :
\r
211 /* Use direct IO */
\r
213 /* These are used for IRP_MJ_READ and IRP_MJ_WRITE which. */
\r
214 l_pFdo->Flags |= DO_DIRECT_IO ;
\r
215 l_pFdo->Flags &= ~DO_DEVICE_INITIALIZING;
\r
217 /* Word alignment */
\r
218 l_pFdo->AlignmentRequirement = FILE_BYTE_ALIGNMENT;
\r
221 * Set up some device context fields
\r
224 /* get device context */
\r
225 l_pMdDevContext = (PMD_DEV_CONTEXT_T)l_pFdo->DeviceExtension;
\r
227 /* zero the context */
\r
228 RtlZeroMemory(l_pFdo->DeviceExtension, pi_nExtSize);
\r
230 /* store handle to device */
\r
231 l_pMdDevContext->m_pFdo = l_pFdo;
\r
233 /* Copy the Win32 device name */
\r
235 UCopyString( &l_pMdDevContext->m_usDosDeviceName, pi_pWin32DeviceName, TRUE );
\r
236 MdExFreePool( pi_pWin32DeviceName->Buffer );
\r
238 l_pMdDevContext->m_usDosDeviceName.Length = pi_pWin32DeviceName->Length;
\r
239 l_pMdDevContext->m_usDosDeviceName.MaximumLength = pi_pWin32DeviceName->MaximumLength;
\r
240 l_pMdDevContext->m_usDosDeviceName.Buffer = pi_pWin32DeviceName->Buffer;
\r
242 pi_pWin32DeviceName->Buffer = NULL;
\r
244 /* Copy the Nt device name */
\r
246 UCopyString( &l_pMdDevContext->m_usNtDeviceName, pi_pNtDeviceName, TRUE );
\r
247 MdExFreePool( pi_pNtDeviceName->Buffer );
\r
249 l_pMdDevContext->m_usNtDeviceName.Length = pi_pNtDeviceName->Length;
\r
250 l_pMdDevContext->m_usNtDeviceName.MaximumLength = pi_pNtDeviceName->MaximumLength;
\r
251 l_pMdDevContext->m_usNtDeviceName.Buffer = pi_pNtDeviceName->Buffer;
\r
253 pi_pNtDeviceName->Buffer = NULL;
\r
255 /* store the result */
\r
256 *po_ppMdDevContext = l_pMdDevContext;
\r
258 return STATUS_SUCCESS;
\r
260 } /* MdAddDevice */
\r
262 /*------------------------------------------------------------------------------------------------------*/
\r
266 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
270 Routine Description:
\r
271 This routine is called to remove the device.
\r
276 pi_pMdDevContext...... The device context
\r
280 STATUS_SUCCESS if the device and link are created correctly, otherwise
\r
281 an error indicating the reason for failure.
\r
284 { /* MdDelDevice */
\r
286 /* Delete the symbolic link */
\r
287 IoDeleteSymbolicLink(&pi_pMdDevContext->m_usDosDeviceName);
\r
289 /* Free the DOS device names string buffer */
\r
290 if (pi_pMdDevContext->m_usDosDeviceName.Buffer != NULL)
\r
292 PUSHORT l_pBuf = pi_pMdDevContext->m_usDosDeviceName.Buffer;
\r
293 pi_pMdDevContext->m_usDosDeviceName.Buffer = NULL;
\r
294 MdExFreePool( l_pBuf );
\r
297 /* Free the NT device names string buffer */
\r
298 if (pi_pMdDevContext->m_usNtDeviceName.Buffer != NULL)
\r
300 PUSHORT l_pBuf = pi_pMdDevContext->m_usNtDeviceName.Buffer;
\r
301 pi_pMdDevContext->m_usNtDeviceName.Buffer = NULL;
\r
302 MdExFreePool( l_pBuf );
\r
305 /* Delete the created device */
\r
306 if (pi_pMdDevContext->m_pFdo)
\r
308 PDEVICE_OBJECT l_pFdo = pi_pMdDevContext->m_pFdo;
\r
309 pi_pMdDevContext->m_pFdo = NULL;
\r
310 IoDeleteDevice( l_pFdo );
\r
313 } /* MdDelDevice */
\r
315 /*------------------------------------------------------------------------------------------------------*/
\r
317 static void GetRegistryDword(
\r
318 IN PWCHAR pi_ParamName,
\r
319 IN ULONG pi_DfltValue,
\r
320 OUT PLONG po_Result
\r
323 ULONG l_uValue = 0;
\r
325 // read parameter the registry
\r
326 MdGetRegistryDword( MD_REGISTRY_PARAMETERS_PATH, //absolute registry path
\r
327 pi_ParamName, // REG_DWORD ValueName
\r
328 &l_uValue ); // Value receiver
\r
331 { /* no Registry value - set default */
\r
332 *po_Result = pi_DfltValue;
\r
333 } /* no Registry value - set default */
\r
335 { /* store Registry value */
\r
336 *po_Result = l_uValue;
\r
337 } /* store Registry value */
\r
340 /*------------------------------------------------------------------------------------------------------*/
\r
343 MdCreateDevContext(
\r
344 IN PDRIVER_OBJECT pi_pDriverObject,
\r
345 IN MD_DEV_IX_E pi_eDevType,
\r
346 IN PUNICODE_STRING pi_pNtDeviceName,
\r
347 IN PUNICODE_STRING pi_pWin32DeviceName,
\r
348 IN OUT PVOID* pio_ppDevContext
\r
352 Routine Description:
\r
353 This routine creates the device extension
\r
358 pi_pDriverObject........ pointer to driver object
\r
359 pi_eDevType............. The device type.
\r
360 pi_pNtDeviceName........ The \Device\????\ name
\r
361 pi_pWin32DeviceName..... The \DosDevices\????\ name
\r
362 pio_ppDevContext........ Pointer to created device context.
\r
366 STATUS_SUCCESS if the device extension was created correctly, otherwise
\r
367 an error indicating the reason for failure.
\r
370 { /* MdCreateDevContext */
\r
372 /* Status of utility calls */
\r
373 NTSTATUS l_Status = STATUS_SUCCESS;
\r
374 /* The Md device context ( l_pDeviceObject extension ) */
\r
375 PMD_DEV_CONTEXT_T l_pMdDevContext;
\r
378 * Initialize the device context with the template device context
\r
381 /* Create the device */
\r
382 l_Status = MdAddDevice(
\r
385 pi_pWin32DeviceName,
\r
386 sizeof(MD_DEV_CONTEXT_T),
\r
390 /* Check if device create ok */
\r
391 if ( !NT_SUCCESS(l_Status) )
\r
392 { /* Device creation failed */
\r
394 /* Set the device context to 0 */
\r
395 *pio_ppDevContext = NULL;
\r
397 /* Return error code */
\r
400 } /* Device creation failed */
\r
402 /* Save device type/channel */
\r
403 l_pMdDevContext->m_eDevType = pi_eDevType;
\r
406 * Init the rest fields of the driver context
\r
410 INIT_LOCK_IT( &l_pMdDevContext->m_SpinLock );
\r
412 // spinlock used to protect inc/dec iocount logic
\r
413 KeInitializeSpinLock (&l_pMdDevContext->m_IoCntSpinLock);
\r
416 KeInitializeEvent(&l_pMdDevContext->m_RemoveEvent, NotificationEvent, FALSE);
\r
417 KeInitializeEvent(&l_pMdDevContext->m_NoPendingIoEvent, NotificationEvent, FALSE);
\r
418 KeSetEvent(&l_pMdDevContext->m_NoPendingIoEvent, 1, FALSE);
\r
420 // init queue header
\r
421 InitializeListHead( &l_pMdDevContext->m_PcsQue );
\r
424 KSEM_INIT( &l_pMdDevContext->m_Sem );
\r
427 KMUTEX_INIT( &l_pMdDevContext->m_Mutex );
\r
430 l_pMdDevContext->m_fDeletePending = FALSE;
\r
432 switch (l_pMdDevContext->m_eDevType)
\r
433 { /* device-specific init */
\r
435 case MD_DEV_IX_TAVOR_BD:
\r
436 GetRegistryDword( L"ConfAddr", MD_DFLT_CONF_ADDR, &l_pMdDevContext->m_ulAddrOffset );
\r
437 GetRegistryDword( L"ConfData", MD_DFLT_CONF_DATA, &l_pMdDevContext->m_ulDataOffset );
\r
438 l_pMdDevContext->m_nPendingIoCnt = 0;
\r
441 case MD_DEV_IX_TAVOR_SD:
\r
442 GetRegistryDword( L"ConfAddr", MD_DFLT_CONF_ADDR, &l_pMdDevContext->m_ulAddrOffset );
\r
443 GetRegistryDword( L"ConfData", MD_DFLT_CONF_DATA, &l_pMdDevContext->m_ulDataOffset );
\r
444 GetRegistryDword( L"DdrMapOffset", MD_DFLT_CONF_DATA, &l_pMdDevContext->m_ulDdrMapOffset );
\r
445 GetRegistryDword( L"DdrMapSize", MD_DFLT_CONF_DATA, &l_pMdDevContext->m_ulDdrMapSize );
\r
446 l_pMdDevContext->m_nPendingIoCnt = 0;
\r
449 case MD_DEV_IX_TAVOR:
\r
450 GetRegistryDword( L"DdrMapOffset", MD_DFLT_CONF_DATA, &l_pMdDevContext->m_ulDdrMapOffset );
\r
451 GetRegistryDword( L"DdrMapSize", MD_DFLT_CONF_DATA, &l_pMdDevContext->m_ulDdrMapSize );
\r
452 GetRegistryDword( L"ResetCard", MD_DFLT_CONF_DATA, &l_pMdDevContext->m_PerformReset );
\r
453 l_pMdDevContext->m_nPendingIoCnt = 0;
\r
454 l_pMdDevContext->m_hHhHca = NULL;
\r
457 case MD_DEV_IX_CTRL:
\r
458 { /* specific Control device initialization */
\r
459 /* pending IO requests: setting 1 here for "adding" the Control device ('cause OS won't call to AddDevice) */
\r
460 l_pMdDevContext->m_nPendingIoCnt = 1;
\r
462 /* Device open counter */
\r
463 l_pMdDevContext->m_nOpenCount = 0;
\r
465 // mark device started
\r
466 l_pMdDevContext->m_DeviceStarted = TRUE;
\r
469 } /* specific Control device initialization */
\r
471 } /* device-specific init */
\r
473 /* Return the new created extension */
\r
474 *pio_ppDevContext = l_pMdDevContext;
\r
478 } /* MdCreateDevContext */
\r
480 /*------------------------------------------------------------------------------------------------------*/
\r
483 MdRemoveDevContext (
\r
484 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
488 Routine Description:
\r
489 This routine releases the device context resources and remove the device
\r
494 pi_pMdDevContext........ Pointer to the device context.
\r
498 STATUS_SUCCESS if the device extension was created correctly, otherwise
\r
499 an error indicating the reason for failure.
\r
502 { /* MdRemoveDevContext */
\r
505 if (pi_pMdDevContext != NULL)
\r
507 /* close direct PCI interface */
\r
508 if (pi_pMdDevContext->m_eDevType != MD_DEV_IX_CTRL)
\r
509 PciIfClose( &pi_pMdDevContext->m_Interface );
\r
511 /* Remove the device */
\r
512 MdDelDevice( pi_pMdDevContext );
\r
514 /* remove device context */
\r
515 /* NO NEED, BECAUSE IT WAS RELEASED ON IoDeleteDevice() !
\r
516 MdExFreePool( pi_pMdDevContext );
\r
520 return STATUS_SUCCESS;
\r
522 } /* MdRemoveDevContext */
\r
524 /*------------------------------------------------------------------------------------------------------*/
\r
528 IN PMD_DRV_CONTEXT_T pi_pDrvContext,
\r
529 IN MD_DEV_IX_E pi_eDevType,
\r
530 IN PUNICODE_STRING pi_pNtDeviceName,
\r
531 IN PUNICODE_STRING pi_pWin32DeviceName,
\r
532 IN OUT PVOID* pio_ppDevContext
\r
536 Routine Description:
\r
537 This routine creates the device and connect to the driver context
\r
542 pi_pDrvContext.......... Driver context
\r
543 pi_eDevType............. Device type.
\r
544 pi_pNtDeviceName........ The \Device\????\ name
\r
545 pi_pWin32DeviceName..... The \DosDevices\????\ name
\r
546 pio_ppDevContext........ The device extension ofthe created object
\r
550 STATUS_SUCCESS on success, otherwise an error indicating the reason for failure.
\r
555 /* Local status variable */
\r
557 /* Default debug ON/OFF flag */
\r
558 ULONG l_nDfltDebugPrintLevel = FALSE ;
\r
559 /* Device context */
\r
560 PMD_DEV_CONTEXT_T l_pMdDevContext;
\r
562 MdKdPrint( DBGLVL_MINIMUM ,("(MdDevInit) init device '%ws'\n", pi_pWin32DeviceName->Buffer ));
\r
565 * Create the device and the device context
\r
567 l_Status = MdCreateDevContext(
\r
568 pi_pDrvContext->m_pDrvObject,
\r
571 pi_pWin32DeviceName,
\r
575 /* Check creation status */
\r
576 if ( NT_SUCCESS(l_Status) )
\r
580 MdKdPrint( DBGLVL_DEFAULT ,("(MdDeviceInit) Device successfuly initialized\n"));
\r
582 /* Store the device context */
\r
583 *pio_ppDevContext = l_pMdDevContext;
\r
585 /* Add the device context to the driver list */
\r
586 LOCK_IT( &pi_pDrvContext->m_SpinLock);
\r
587 InsertTailList( &pi_pDrvContext->m_DevQue, &l_pMdDevContext->m_Link );
\r
588 UNLOCK_IT( &pi_pDrvContext->m_SpinLock);
\r
590 /* connect device to driver */
\r
591 l_pMdDevContext->m_pDrvContext = pi_pDrvContext;
\r
593 /* Update number of device instances */
\r
594 InterlockedIncrement( &pi_pDrvContext->m_uDevNo );
\r
596 // increment the number of cards
\r
598 int l_ix = (int)l_pMdDevContext->m_eDevType;
\r
599 PMD_HAL_DEV_PARAMS_T l_pDev = &g_DevParams[l_ix];
\r
600 if (l_pDev->m_fExpose)
\r
601 InterlockedIncrement( &g_pDrvContext->m_uCardNo );
\r
609 /*------------------------------------------------------------------------------------------------------*/
\r
612 ReleasePendingRequests(
\r
613 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
617 Routine Description:
\r
619 Release pending requests of the Control Device
\r
623 pi_pMdDevContext - pointer to the Control Device
\r
628 { /* ReleasePendingRequests */
\r
629 MdKdPrint( DBGLVL_MINIMUM ,("(ReleasePendingRequests) Enter \n" ));
\r
630 } /* ReleasePendingRequests */
\r
633 /*------------------------------------------------------------------------------------------------------*/
\r
637 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
641 Routine Description:
\r
642 This routine DeInitialize the device setting and context
\r
647 pi_pMdDevContext........The device context
\r
653 { /* MdDevDeInit */
\r
654 /* Current device object */
\r
655 PDEVICE_OBJECT l_pFdo ;
\r
656 /* The Driver context */
\r
657 PMD_DRV_CONTEXT_T l_pMdDrvContext;
\r
661 MdKdPrint( DBGLVL_MINIMUM ,("(MdDevDeInit) Unloading device '%ws' \n", pi_pMdDevContext->m_usDosDeviceName.Buffer));
\r
663 /* Parameter validation*/
\r
664 if ( pi_pMdDevContext == NULL )
\r
665 { /* no device context */
\r
666 return STATUS_UNSUCCESSFUL;
\r
667 } /* no device context */
\r
669 /* Get the first device object */
\r
670 l_pFdo = pi_pMdDevContext->m_pFdo;
\r
672 /* Check if driver has any device */
\r
673 if ( l_pFdo == NULL )
\r
674 { /* no NT device object */
\r
675 return STATUS_UNSUCCESSFUL;
\r
676 } /* no NT device object */
\r
678 /* get driver context */
\r
679 l_pMdDrvContext = pi_pMdDevContext->m_pDrvContext;
\r
682 * Remove the device from the Driver device list
\r
685 // acquire access to the critical section
\r
686 LOCK_IT( &pi_pMdDevContext->m_SpinLock );
\r
688 // disconnect the global context with device one
\r
689 RemoveEntryList( &pi_pMdDevContext->m_Link );
\r
691 // release access to the critical section
\r
692 UNLOCK_IT( &pi_pMdDevContext->m_SpinLock );
\r
694 // decrement the number of created devices
\r
695 LOCK_IT( &l_pMdDrvContext->m_SpinLock);
\r
696 if ( l_pMdDrvContext->m_uDevNo > 0)
\r
697 InterlockedDecrement( &l_pMdDrvContext->m_uDevNo );
\r
698 UNLOCK_IT( &l_pMdDrvContext->m_SpinLock);
\r
700 // decrement the number of cards
\r
702 int l_ix = (int)pi_pMdDevContext->m_eDevType;
\r
703 PMD_HAL_DEV_PARAMS_T l_pDev = &g_DevParams[l_ix];
\r
704 if (l_pDev->m_fExpose && l_pMdDrvContext->m_uCardNo > 0)
\r
705 InterlockedDecrement( &l_pMdDrvContext->m_uCardNo );
\r
707 /* Free the Device context */
\r
708 return MdRemoveDevContext( pi_pMdDevContext );
\r
710 } /* MdDevDeInit */
\r
714 IN PDEVICE_OBJECT pi_pPdo,
\r
715 IN ULONG * pi_pBus,
\r
716 IN ULONG * pi_pSlot,
\r
717 IN ULONG * pi_pFunction
\r
720 ULONG l_BusNumber, l_DevNumber, l_Function, l_ResultLength = 0;
\r
721 WCHAR l_Buffer[40], *l_pEnd, *l_pBuf = l_Buffer, *l_pBufEnd = l_Buffer + sizeof(l_Buffer);
\r
723 UNICODE_STRING l_UnicodeNumber;
\r
726 l_ResultLength = 0;
\r
727 RtlZeroMemory( l_Buffer, sizeof(l_Buffer) );
\r
729 /* Get the device number */
\r
730 l_Status = IoGetDeviceProperty(pi_pPdo,
\r
731 DevicePropertyLocationInformation, sizeof(l_Buffer), &l_Buffer, &l_ResultLength);
\r
733 /* Verify if the function was successful */
\r
734 if ( !NT_SUCCESS(l_Status) || !l_ResultLength ) {
\r
735 MdKdPrint( DBGLVL_DEFAULT ,("(MdInitPciCfgCard) Unable to get device number: Status 0x%x, ResultSize %d \n",
\r
736 l_Status, l_ResultLength ));
\r
740 // ALL THE BELOW CRAP WE DO INSTEAD OF
\r
741 // sscanf(l_Buffer, "PCI bus %d, device %d, function %d", &l_BusNumber, &l_DevNumber, &l_Function );
\r
743 /* take bus number */
\r
744 l_pBuf = WcharFindChar( l_pBuf, l_pBufEnd, L'0', L'9' );
\r
745 if (l_pBuf == NULL) goto err;
\r
746 l_pEnd = WcharFindChar( l_pBuf, l_pBufEnd, L',', L',' );
\r
747 if (l_pEnd == NULL) goto err;
\r
748 l_UnicodeNumber.Length = l_UnicodeNumber.MaximumLength = (USHORT)((PCHAR)l_pEnd - (PCHAR)l_pBuf);
\r
749 l_UnicodeNumber.Buffer = l_pBuf; l_pBuf = l_pEnd;
\r
750 RtlUnicodeStringToInteger( &l_UnicodeNumber, 10, &l_BusNumber);
\r
752 /* take slot number */
\r
753 l_pBuf = WcharFindChar( l_pBuf, l_pBufEnd, L'0', L'9' );
\r
754 if (l_pBuf == NULL) goto err;
\r
755 l_pEnd = WcharFindChar( l_pBuf, l_pBufEnd, L',', L',' );
\r
756 if (l_pEnd == NULL) goto err;
\r
757 l_UnicodeNumber.Length = l_UnicodeNumber.MaximumLength = (USHORT)((PCHAR)l_pEnd - (PCHAR)l_pBuf);
\r
758 l_UnicodeNumber.Buffer = l_pBuf; l_pBuf = l_pEnd;
\r
759 RtlUnicodeStringToInteger( &l_UnicodeNumber, 10, &l_DevNumber);
\r
761 /* take function number */
\r
762 *(l_Buffer + (l_ResultLength>>1)) = 0; /* set end of string */
\r
763 l_pBuf = WcharFindChar( l_pBuf, l_pBufEnd, L'0', L'9' );
\r
764 if (l_pBuf == NULL) goto err;
\r
765 l_pEnd = WcharFindChar( l_pBuf, l_pBufEnd, 0, 0 );
\r
766 if (l_pEnd == NULL) goto err;
\r
767 l_UnicodeNumber.Length = l_UnicodeNumber.MaximumLength = (USHORT)((PCHAR)l_pEnd - (PCHAR)l_pBuf);
\r
768 l_UnicodeNumber.Buffer = l_pBuf; l_pBuf = l_pEnd;
\r
769 RtlUnicodeStringToInteger( &l_UnicodeNumber, 10, &l_Function);
\r
771 /* return the results */
\r
772 *pi_pBus = l_BusNumber;
\r
773 *pi_pSlot = l_DevNumber;
\r
774 *pi_pFunction = l_Function;
\r
779 l_Status = STATUS_UNSUCCESSFUL;
\r
784 /*------------------------------------------------------------------------------------------------------*/
\r
788 IN PMD_DEV_CONTEXT_T pi_pMdDevContext,
\r
789 IN PCM_RESOURCE_LIST pi_pRawResources,
\r
790 IN PCM_RESOURCE_LIST pi_pTranslatedResources
\r
794 Routine Description:
\r
796 This routine prepares the Driver to the work with a PCI card:
\r
797 - gets card resources from IRP;
\r
798 - store them on the device context;
\r
799 - translate physical address into virtual;
\r
800 - connect interrupt;
\r
804 pi_pMdDevContext....... My device context
\r
805 pi_pRawResources....... Card raw resources
\r
806 pi_pTranslatedResources Card translated resources
\r
813 { /* MdInitPciCfgCard */
\r
815 /* full resource descriptor */
\r
816 PCM_FULL_RESOURCE_DESCRIPTOR l_pFullResDesc;
\r
817 /* partial resource list */
\r
818 PCM_PARTIAL_RESOURCE_LIST l_pPartResList;
\r
819 /* partial resource descriptor */
\r
820 PCM_PARTIAL_RESOURCE_DESCRIPTOR l_pPartResDesc;
\r
821 /* number of resources */
\r
823 /* current resource number */
\r
824 ULONG l_nCurResNum;
\r
825 /* temporary address */
\r
826 PUCHAR l_pPortAddr = NULL;
\r
829 // Device IX (in PCI configuration)
\r
830 MD_DEV_IX_E l_DevIx = pi_pMdDevContext->m_eDevType;
\r
832 PMD_HAL_DEV_PARAMS_T l_pDev = &g_DevParams[l_DevIx];
\r
833 // current BAR descriptor
\r
838 MdKdPrint( DBGLVL_DEFAULT ,("(MdInitPciCfgCard) Enter \n" ));
\r
840 /* zero the fields */
\r
841 #define ZEROF(field) pi_pMdDevContext->field = 0;
\r
842 ZEROF(m_BusNumber);
\r
843 ZEROF(m_DevNumber);
\r
845 ZEROF(m_ulIntVector);
\r
846 ZEROF(m_ulIntLevel);
\r
848 ZEROF(m_fIntShared);
\r
850 RtlZeroMemory( (void*)&pi_pMdDevContext->m_Cr, sizeof(MD_BAR_T));
\r
851 RtlZeroMemory( (void*)&pi_pMdDevContext->m_Uar, sizeof(MD_BAR_T));
\r
852 RtlZeroMemory( (void*)&pi_pMdDevContext->m_Ddr, sizeof(MD_BAR_T));
\r
854 if (l_DevIx == MD_DEV_IX_TAVOR_SD)
\r
855 { /* get BARs via PCI configuration header */
\r
857 l_Status = ReadBars( pi_pMdDevContext );
\r
858 if (!NT_SUCCESS(l_Status))
\r
861 } /* get BARs via PCI configuration header */
\r
864 { /* get resources from resource descriptors */
\r
866 /* validate parameters */
\r
867 if (pi_pTranslatedResources == NULL) {
\r
868 MdKdPrint( DBGLVL_LOW ,("(MdInitPciCfgCard) No resources ! \n" ));
\r
869 return STATUS_SUCCESS;
\r
872 /* prepare for getting resources */
\r
873 l_pFullResDesc = &pi_pTranslatedResources->List[0];
\r
874 l_pPartResList = &l_pFullResDesc->PartialResourceList;
\r
875 l_pPartResDesc = &l_pPartResList->PartialDescriptors[0];
\r
876 l_nResCnt = l_pPartResList->Count;
\r
878 /* store other parameters */
\r
879 for (l_nCurResNum = 0; l_nCurResNum < l_nResCnt; ++l_nCurResNum, ++l_pPartResDesc)
\r
881 switch (l_pPartResDesc->Type)
\r
883 case CmResourceTypeBusNumber:
\r
884 /* Store IB card bus number */
\r
885 //MDASSERT( pi_pMdDevContext->m_ulBusNumber == l_pPartResDesc->u.BusNumber.Start );
\r
886 pi_pMdDevContext->m_BusNumber = l_pPartResDesc->u.BusNumber.Start;
\r
889 case CmResourceTypeInterrupt:
\r
890 pi_pMdDevContext->m_ulIntVector = l_pPartResDesc->u.Interrupt.Vector;
\r
891 pi_pMdDevContext->m_ulIntLevel = (KIRQL)l_pPartResDesc->u.Interrupt.Level;
\r
892 pi_pMdDevContext->m_Affinity = (KAFFINITY)l_pPartResDesc->u.Interrupt.Affinity;
\r
893 pi_pMdDevContext->m_fIntShared = l_pPartResDesc->ShareDisposition == CmResourceShareShared;
\r
894 pi_pMdDevContext->m_IntMode = (l_pPartResDesc->Flags == CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
\r
895 MdKdPrint( DBGLVL_LOW ,("(MdInitPciCfgCard) Dev %d Interrupt: Vector %d, Level %d, Affinity %d, Shared %d, Mode %d\n",
\r
896 l_pDev->m_DevId, pi_pMdDevContext->m_ulIntVector, pi_pMdDevContext->m_ulIntLevel,
\r
897 pi_pMdDevContext->m_Affinity, pi_pMdDevContext->m_fIntShared, pi_pMdDevContext->m_IntMode ));
\r
900 case CmResourceTypeMemory:
\r
903 LARGE_INTEGER l_Offset = { 0,0 };
\r
905 /* decide, what BAR is it about */
\r
906 if (l_pDev->m_SizeBar0 >= l_pPartResDesc->u.Memory.Length) {
\r
907 l_pBar = &pi_pMdDevContext->m_Cr; l_BarName = "CR"; l_BarNum = 0; }
\r
909 if (l_pDev->m_SizeBar1 >= l_pPartResDesc->u.Memory.Length) {
\r
910 l_pBar = &pi_pMdDevContext->m_Uar; l_BarName = "UAR"; l_BarNum = 1; }
\r
912 l_pBar = &pi_pMdDevContext->m_Ddr; l_BarName = "DDR"; l_BarNum = 2; }
\r
914 /* store BAR parameters */
\r
915 l_pBar->m_MemPhysAddr = l_pPartResDesc->u.Memory.Start;
\r
916 l_pBar->m_ulMemSize = l_pPartResDesc->u.Memory.Length;
\r
917 l_pBar->m_usMemFlags = l_pPartResDesc->Flags;
\r
918 l_pBar->m_ulKernelSize = l_pBar->m_ulMemSize;
\r
919 l_pBar->m_ulKernelOffset = 0;
\r
921 /* recalculate boundaries of mapped mempry for DDR */
\r
922 if (l_BarNum == 2 && pi_pMdDevContext->m_ulDdrMapSize != -1) {
\r
923 l_pBar->m_ulKernelSize = pi_pMdDevContext->m_ulDdrMapSize;
\r
924 l_pBar->m_ulKernelOffset = pi_pMdDevContext->m_ulDdrMapOffset;
\r
925 l_Offset.LowPart = pi_pMdDevContext->m_ulDdrMapOffset;
\r
926 } /* for DDR - map some subset of memory */
\r
928 /* map physical address into virtual kernel one */
\r
929 if (l_pBar->m_ulKernelSize) {
\r
930 l_Offset.QuadPart += l_pBar->m_MemPhysAddr.QuadPart;
\r
931 l_pBar->m_pKernelAddr = (PUCHAR) MmMapIoSpace(
\r
933 l_pBar->m_ulKernelSize, MmNonCached);
\r
935 if (!l_pBar->m_pKernelAddr) return STATUS_NO_MEMORY;
\r
938 MdKdPrint( DBGLVL_LOW ,("(MdInitPciCfgCard) Dev %d %s: Phys 0x%I64x Size 0x%x, Virt 0x%x Size 0x%x \n",
\r
939 l_pDev->m_DevId, l_BarName, l_pBar->m_MemPhysAddr, l_pBar->m_ulMemSize,
\r
940 l_pBar->m_pKernelAddr, l_pBar->m_ulKernelSize ));
\r
945 MdKdPrint( DBGLVL_DEFAULT ,("(MdInitPciCfgCard) Unsupported resource type 0x%x \n", l_pPartResDesc->Type ));
\r
950 } /* get resources from resource descriptors */
\r
953 // get the device location information
\r
956 ULONG l_BusNumber, l_DevNumber, l_Function;
\r
958 l_Status = MdGetDevLocation( pi_pMdDevContext->m_pPdo, &l_BusNumber, &l_DevNumber, &l_Function );
\r
960 if ( !NT_SUCCESS(l_Status) )
\r
961 { // fill default values
\r
962 l_BusNumber = g_pDrvContext->m_uDevNo;
\r
963 l_DevNumber = g_pDrvContext->m_uDevNo;
\r
967 /* store the slot number */
\r
968 pi_pMdDevContext->m_BusNumber = l_BusNumber;
\r
969 pi_pMdDevContext->m_DevNumber = l_DevNumber;
\r
970 pi_pMdDevContext->m_Function = l_Function;
\r
972 MdKdPrint( DBGLVL_LOW ,("(MdInitPciCfgCard) Dev %d location is %d:%d:%d) \n",
\r
973 l_pDev->m_DevId, l_BusNumber, l_DevNumber, l_Function ));
\r
977 return STATUS_SUCCESS;
\r
979 } /* MdInitPciCfgCard */
\r
981 /*------------------------------------------------------------------------------------------------------*/
\r
984 MdDeInitPciCfgCard(
\r
985 IN PMD_DEV_CONTEXT_T pi_pMdDevContext
\r
989 Routine Description:
\r
991 This routine releases OS resources, allocaetd for the work with a PCI card:
\r
992 - disconnect the interrupt;
\r
993 - unmap virtual address of the CR-space;
\r
998 pi_pMdDevContext....... My device context
\r
1005 { /* MdDeInitPciCfgCard */
\r
1007 // current BAR descriptor
\r
1008 PMD_BAR_T l_pBar;
\r
1009 // CR space address
\r
1013 l_pBar = &pi_pMdDevContext->m_Cr;
\r
1014 l_pAddr = l_pBar->m_pKernelAddr;
\r
1015 l_pBar->m_pKernelAddr = NULL;
\r
1017 MmUnmapIoSpace(l_pAddr, l_pBar->m_ulKernelSize);
\r
1019 // unmap UAR-space
\r
1020 l_pBar = &pi_pMdDevContext->m_Uar;
\r
1021 l_pAddr = l_pBar->m_pKernelAddr;
\r
1022 l_pBar->m_pKernelAddr = NULL;
\r
1024 MmUnmapIoSpace(l_pAddr, l_pBar->m_ulKernelSize);
\r
1026 // unmap DDR-space
\r
1027 l_pBar = &pi_pMdDevContext->m_Ddr;
\r
1028 l_pAddr = l_pBar->m_pKernelAddr;
\r
1029 l_pBar->m_pKernelAddr = NULL;
\r
1031 MmUnmapIoSpace(l_pAddr, l_pBar->m_ulKernelSize);
\r
1033 } /* MdDeInitPciCfgCard */
\r
1035 /*------------------------------------------------------------------------------------------------------*/
\r
1038 /*------------------------------------------------------------------------------------------------------*/
\r
1042 OUT PUCHAR pi_TargetString,
\r
1043 IN const USHORT * pi_SourceString,
\r
1048 Routine Description:
\r
1049 Converts wide-character string into ASCII
\r
1053 pi_TargetString...... result string
\r
1054 pi_SourceString...... source string
\r
1055 pi_Size.............. size of the source string
\r
1059 The result stringbytes.
\r
1062 { /* WcharToAscii */
\r
1063 int i, size = (pi_Size + 1) >> 1;
\r
1064 PCHAR l_pResult = pi_TargetString;
\r
1066 for (i=0; i<size; i++)
\r
1068 if (*pi_SourceString == 0)
\r
1070 *l_pResult++ = (char)*pi_SourceString++;
\r
1072 *l_pResult = '\0';
\r
1074 return pi_TargetString;
\r
1076 } /* WcharToAscii */
\r
1080 IN PWCHAR pi_BufStart,
\r
1081 IN PWCHAR pi_BufEnd,
\r
1082 IN WCHAR pi_FromPattern,
\r
1083 IN WCHAR pi_ToPattern
\r
1087 Routine Description:
\r
1088 Converts wide-character string into ASCII
\r
1092 pi_BufStart.......... start of the source string
\r
1093 pi_BufEnd............ end of the source string
\r
1094 pi_FromPattern....... start of pattern range to find
\r
1095 pi_ToPattern......... end of pattern range to find
\r
1099 pointer to the first pattern found or NULL (when reached the end)
\r
1102 { /* WcharFindChar */
\r
1104 PWCHAR l_pResult = pi_BufStart;
\r
1106 while (l_pResult < pi_BufEnd )
\r
1108 if (*l_pResult >= pi_FromPattern && *l_pResult <= pi_ToPattern)
\r
1115 } /* WcharFindChar */
\r
1117 /*------------------------------------------------------------------------------------------------------*/
\r
1121 PUNICODE_STRING pi_puTargetString,
\r
1122 PUCHAR pi_szFormat,
\r
1127 Routine Description:
\r
1128 Writes a formatted ( printf like ) string to into a uniocde string.
\r
1132 pi_nDbgLogLevel...... Level of debugging log.
\r
1133 pi_szFormat.......... The format of the log.
\r
1137 The formatted string length in bytes.
\r
1140 { /* AsciiToUnicode */
\r
1142 /* Auxilary scratch buffer */
\r
1143 static UCHAR s_vScratchBuff[1024];
\r
1145 /* Variable argument list */
\r
1147 /* Length of the formated string in bytes */
\r
1148 int l_nStrLenBytes ;
\r
1150 USHORT l_nCharNo ;
\r
1151 /* Maximum lemgth */
\r
1152 USHORT l_nMaxLength;
\r
1154 /* Init the variable argument list */
\r
1155 va_start(l_Argptr, pi_szFormat);
\r
1157 /* Build the formatted string */
\r
1158 l_nStrLenBytes = vsprintf(&s_vScratchBuff[0] , pi_szFormat , l_Argptr);
\r
1160 /* Check if we need to allocate buffer */
\r
1161 if ( pi_puTargetString->Buffer == NULL )
\r
1162 { /* Need to allocate buffer */
\r
1164 /* Allocate the UNICODE string buffer */
\r
1165 pi_puTargetString->Buffer =
\r
1166 (PWCHAR)MdExAllocatePool(NonPagedPool,(l_nStrLenBytes+1)*sizeof(WCHAR));
\r
1168 /* If allocation failed return */
\r
1169 if ( pi_puTargetString->Buffer == NULL ) return 0;
\r
1171 /* Set the UNICODE string new parameters */
\r
1172 pi_puTargetString->MaximumLength = (USHORT)((l_nStrLenBytes+1)*sizeof(WCHAR)) ;
\r
1174 } /* Need to allocate buffer */
\r
1176 /* Reset the string actual length */
\r
1177 pi_puTargetString->Length = 0;
\r
1179 /* Calc max length */
\r
1180 l_nMaxLength = MT_MIN((pi_puTargetString->MaximumLength/sizeof(WCHAR) - 1),(USHORT)l_nStrLenBytes);
\r
1182 /* Convert to UNICODE */
\r
1183 for ( l_nCharNo=0; l_nCharNo<l_nMaxLength; l_nCharNo++ )
\r
1184 { /* Convert a CHAR to WCHAR */
\r
1187 pi_puTargetString->Buffer[ l_nCharNo ] = (WCHAR)s_vScratchBuff[l_nCharNo] ;
\r
1189 /* Update actual length */
\r
1190 pi_puTargetString->Length += sizeof(WCHAR) ;
\r
1192 } /* Convert a CHAR to WCHAR */
\r
1194 /* NULL terminate */
\r
1195 pi_puTargetString->Buffer[ l_nCharNo ] = (WCHAR)'\0';
\r
1197 /* Term the variable argument list */
\r
1200 return pi_puTargetString->Length ;
\r
1202 } /* AsciiToUnicode */
\r
1204 /*------------------------------------------------------------------------------------------------------*/
\r
1207 MdCanAcceptIoRequests(
\r
1208 IN PDEVICE_OBJECT DeviceObject
\r
1212 Routine Description:
\r
1214 Check device extension status flags;
\r
1216 Can't accept a new io request if device:
\r
1218 2) has never been started,
\r
1220 4) has a remove request pending, or
\r
1221 5) has a stop device pending
\r
1226 DeviceObject - pointer to the device object for this instance of the 82930
\r
1232 return TRUE if can accept new io requests, else FALSE
\r
1236 PMD_DEV_CONTEXT_T l_pMdDevContext = (PMD_DEV_CONTEXT_T)DeviceObject->DeviceExtension;
\r
1237 BOOLEAN l_fCan = FALSE;
\r
1240 //flag set when processing IRP_MN_REMOVE_DEVICE
\r
1241 if ( !l_pMdDevContext->m_DeviceRemoved &&
\r
1242 // device must be started( enabled )
\r
1243 l_pMdDevContext->m_DeviceStarted &&
\r
1244 // flag set when driver has answered success to IRP_MN_QUERY_REMOVE_DEVICE
\r
1245 !l_pMdDevContext->m_RemoveDeviceRequested &&
\r
1246 // flag set when driver has answered success to IRP_MN_QUERY_STOP_DEVICE
\r
1247 !l_pMdDevContext->m_StopDeviceRequested &&
\r
1248 // control device (MDCTL) marked for deleting)
\r
1249 !l_pMdDevContext->m_fDeletePending) {
\r
1253 MdKdPrintCond( DBGLVL_MAXIMUM, !l_fCan, ("**** FALSE return from MdCanAcceptIoRequests()!\n"));
\r
1258 /*------------------------------------------------------------------------------------------------------*/
\r
1261 MdCreateDeviceNames(
\r
1262 IN PCHAR pi_pDevName,
\r
1263 OUT PUNICODE_STRING po_pNtName,
\r
1264 OUT PUNICODE_STRING po_pDosName
\r
1268 Routine Description:
\r
1270 Creates Nt and Dos names of the device;
\r
1271 Convert them into Unicode format and put the results into given Unicode strings
\r
1272 Allocates buffers for the Unicode strings from non-paged pool
\r
1276 pi_pDevName - ASCII name of the device without path.
\r
1277 po_pNtName - pointer to Unicode string descriptor for NT device name
\r
1278 po_pDosName - pointer to Unicode string descriptor for DOS device name
\r
1283 return TRUE if succeeded to create strings, else FALSE
\r
1286 { /* MdCreateDeviceNames */
\r
1288 /* buffer for ASCII device name */
\r
1289 char l_DevName[MD_MAX_DEV_NAME_LEN + 1];
\r
1290 /* Unicode string length */
\r
1291 int l_nUnicodeNameLen;
\r
1293 /* build NT name */
\r
1294 strcpy( l_DevName, "\\Device\\" );
\r
1295 strcat( l_DevName, pi_pDevName );
\r
1297 /* get the length */
\r
1298 l_nUnicodeNameLen = (int)((strlen(l_DevName) + 1) * sizeof(WCHAR));
\r
1301 * Init the NT device name
\r
1303 /* Allocate buffers for the NT device name */
\r
1304 po_pNtName->Buffer = MdExAllocatePool(NonPagedPool, l_nUnicodeNameLen);
\r
1306 /* Verify allocation */
\r
1307 if ( po_pNtName->Buffer == NULL )
\r
1308 { /* Allocation failed */
\r
1312 } /* Allocation failed */
\r
1314 /* store lengths */
\r
1315 po_pNtName->Length = (USHORT)(l_nUnicodeNameLen - sizeof(WCHAR));
\r
1316 po_pNtName->MaximumLength = (unsigned short)l_nUnicodeNameLen;
\r
1318 /* Build Unicode NT device name */
\r
1324 /* build DOS name */
\r
1325 strcpy( l_DevName, "\\DosDevices\\" );
\r
1326 strcat( l_DevName, pi_pDevName );
\r
1328 /* get the length */
\r
1329 l_nUnicodeNameLen = (int)((strlen(l_DevName) + 1) * sizeof(WCHAR));
\r
1331 /* Allocate buffers for the DOS device name */
\r
1332 po_pDosName->Buffer = MdExAllocatePool(NonPagedPool, l_nUnicodeNameLen);
\r
1334 /* Verify allocation */
\r
1335 if ( po_pDosName->Buffer == NULL )
\r
1336 { /* Allocation failed */
\r
1338 /* Free the NT device name path buffer */
\r
1339 MdExFreePool(po_pNtName->Buffer);
\r
1343 } /* Allocation failed */
\r
1345 /* store lengths */
\r
1346 po_pDosName->Length = (USHORT)(l_nUnicodeNameLen - sizeof(WCHAR));
\r
1347 po_pDosName->MaximumLength = (unsigned short)l_nUnicodeNameLen;
\r
1349 /* Build the NT device name */
\r
1357 } /* MdCreateDeviceNames */
\r
1359 /*------------------------------------------------------------------------------------------------------*/
\r
1361 /**********************************
\r
1362 * Device name DB handling *
\r
1363 **********************************/
\r
1364 int AddDevNameToDb(char *pi_DevName)
\r
1366 ULONG l_Size = (ULONG)strlen(pi_DevName) + 1;
\r
1367 ULONG l_DbSize = g_pDrvContext->m_DevNamesDbSize;
\r
1369 if ( l_DbSize + l_Size <= sizeof(g_pDrvContext->m_DevNamesDb))
\r
1371 RtlCopyMemory( &g_pDrvContext->m_DevNamesDb[l_DbSize], pi_DevName, l_Size);
\r
1372 g_pDrvContext->m_DevNamesDbCnt++;
\r
1373 g_pDrvContext->m_DevNamesDbSize += l_Size;
\r
1382 /*------------------------------------------------------------------------------------------------------*/
\r
1383 /*------------------------------------------------------------------------------------------------------*/
\r
1384 /*------------------------------------------------------------------------------------------------------*/
\r
1385 /*------------------------------------------------------------------------------------------------------*/
\r
1387 NTSTATUS CreateOneDevice(
\r
1388 IN int pi_DevIx, /* index device BD info */
\r
1389 UNICODE_STRING * pi_pusNtDeviceName, /* NT name */
\r
1390 UNICODE_STRING * pi_pusDosDeviceName, /* Win32 name */
\r
1391 OUT PMD_DEV_CONTEXT_T * pi_ppMdDevContext /* context of created device */
\r
1395 NTSTATUS l_Status = STATUS_SUCCESS;
\r
1396 /* our context to this device */
\r
1397 PMD_DEV_CONTEXT_T l_pMdDevContext;
\r
1398 /* device object we create for the added device */
\r
1399 PDEVICE_OBJECT l_pFdo = NULL;
\r
1401 PMD_HAL_DEV_PARAMS_T l_pDevInfo; /* device BD info */
\r
1402 /* buffer for ASCII device name */
\r
1403 char l_DevName[MD_MAX_DEV_NAME_LEN + 1];
\r
1405 /* create and keep the exposed the name */
\r
1406 l_pDevInfo = &g_DevParams[pi_DevIx];
\r
1407 if (l_pDevInfo->m_DevId == MD_DEV_ID_TAVOR || l_pDevInfo->m_DevId == MD_DEV_ID_ARBEL_TM)
\r
1408 sprintf( l_DevName, l_pDevInfo->m_ExFormat, g_pDrvContext->m_uCardNo );
\r
1410 sprintf( l_DevName, l_pDevInfo->m_ExFormat, l_pDevInfo->m_DevId, g_pDrvContext->m_uCardNo );
\r
1411 if (l_pDevInfo->m_fExpose) {
\r
1412 if (AddDevNameToDb(l_DevName))
\r
1413 return STATUS_INSUFFICIENT_RESOURCES;
\r
1416 /* create Control Device names */
\r
1417 /* !!! from now on work with ARBEL_TM as with TAVOR */
\r
1418 l_pDevInfo = (pi_DevIx == (int)MD_DEV_IX_ARBEL_TM) ? &g_DevParams[MD_DEV_IX_TAVOR] : &g_DevParams[pi_DevIx];
\r
1419 if (l_pDevInfo->m_DevId == MD_DEV_ID_TAVOR)
\r
1420 sprintf( l_DevName, l_pDevInfo->m_Format, g_pDrvContext->m_uCardNo );
\r
1422 sprintf( l_DevName, l_pDevInfo->m_Format, l_pDevInfo->m_DevId, g_pDrvContext->m_uCardNo );
\r
1424 if (!MdCreateDeviceNames(l_DevName, pi_pusNtDeviceName, pi_pusDosDeviceName))
\r
1425 return STATUS_INSUFFICIENT_RESOURCES ;
\r
1427 /* build NT name */
\r
1428 MdKdPrint( DBGLVL_LOW,("(CreateOneDevice) Generated device name %s \n", l_DevName));
\r
1430 /* create functional device object (FDO) */
\r
1431 l_Status = MdDevInit( g_pDrvContext, l_pDevInfo->m_DevIx, pi_pusNtDeviceName, pi_pusDosDeviceName, &l_pMdDevContext);
\r
1433 if (!NT_SUCCESS(l_Status))
\r
1434 { /* device creation failed */
\r
1436 /* Free the NT device name path buffer */
\r
1437 if (pi_pusNtDeviceName->Buffer)
\r
1438 MdExFreePool(pi_pusNtDeviceName->Buffer);
\r
1440 /* Free the Dos device name path buffer */
\r
1441 if (pi_pusDosDeviceName->Buffer)
\r
1442 MdExFreePool(pi_pusDosDeviceName->Buffer);
\r
1445 } /* device creation failed */
\r
1447 /* save ASCII name */
\r
1448 strcpy ( l_pMdDevContext->m_AsciiDevName, l_DevName );
\r
1450 /* get FDO handle */
\r
1451 l_pFdo = l_pMdDevContext->m_pFdo;
\r
1453 //Set this flag causes the driver to not receive a IRP_MN_STOP_DEVICE
\r
1454 //during suspend and also not get an IRP_MN_START_DEVICE during resume.
\r
1455 l_pFdo->Flags |= DO_POWER_PAGABLE;
\r
1457 *pi_ppMdDevContext = l_pMdDevContext;
\r
1458 return STATUS_SUCCESS;
\r
1461 /*------------------------------------------------------------------------------------------------------*/
\r
1464 MdGetRegistryDword(
\r
1465 IN PWCHAR RegPath,
\r
1466 IN PWCHAR ValueName,
\r
1467 IN OUT PULONG Value
\r
1472 Routine Description:
\r
1474 Obtain a Dword value from the registry
\r
1479 RegPath -- supplies absolute registry path
\r
1480 ValueName - Supplies the Value Name.
\r
1481 Value - receives the REG_DWORD value.
\r
1485 TRUE if successfull, FALSE on fail.
\r
1490 UNICODE_STRING path;
\r
1491 RTL_QUERY_REGISTRY_TABLE paramTable[2]; //zero'd second table terminates parms
\r
1492 ULONG lDef = *Value; // default
\r
1495 WCHAR wbuf[ MAXIMUM_FILENAME_LENGTH ];
\r
1497 MdKdPrint( DBGLVL_HIGH,("Enter MdGetRegistryDword() RegPath = %ws\n ValueName =%ws\n", RegPath, ValueName));
\r
1499 path.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof( WCHAR ); // MAXIMUM_FILENAME_LENGTH defined in wdm.h
\r
1500 path.Buffer = wbuf;
\r
1503 RtlZeroMemory(path.Buffer, path.MaximumLength);
\r
1504 RtlMoveMemory(path.Buffer, RegPath, wcslen( RegPath) * sizeof( WCHAR ));
\r
1506 MdKdPrint( DBGLVL_HIGH,("MdGetRegistryDword() path= %ws\n", path.Buffer ));
\r
1508 RtlZeroMemory(paramTable, sizeof(paramTable));
\r
1510 paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
1512 paramTable[0].Name = ValueName;
\r
1514 paramTable[0].EntryContext = Value;
\r
1515 paramTable[0].DefaultType = REG_DWORD;
\r
1516 paramTable[0].DefaultData = &lDef;
\r
1517 paramTable[0].DefaultLength = sizeof(ULONG);
\r
1520 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
\r
1521 path.Buffer, paramTable, NULL, NULL);
\r
1523 if (NT_SUCCESS(status)) {
\r
1524 MdKdPrint( DBGLVL_MEDIUM,("Exit MdGetRegistryDWord() SUCCESS, value = decimal %d 0x%x\n", *Value, *Value));
\r
1529 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_INVALID_PARAMETER) ,("MdGetRegistryDWord() STATUS_INVALID_PARAMETER\n"));
\r
1531 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_OBJECT_NAME_NOT_FOUND) ,("MdGetRegistryDWord() STATUS_OBJECT_NAME_NOT_FOUND\n"));
\r
1540 /*------------------------------------------------------------------------------------------------------*/
\r
1543 MdGetRegistryString(
\r
1544 IN PWCHAR RegPath,
\r
1545 IN PWCHAR ValueName,
\r
1546 IN PUNICODE_STRING DfltValue,
\r
1547 IN OUT PUNICODE_STRING Value
\r
1552 Routine Description:
\r
1554 Obtain a string value from the registry
\r
1559 RegPath -- supplies absolute registry path
\r
1560 ValueName - Supplies the Value Name.
\r
1561 Value - receives the REG_DWORD value.
\r
1565 TRUE if successfull, FALSE on fail.
\r
1570 UNICODE_STRING path;
\r
1571 RTL_QUERY_REGISTRY_TABLE paramTable[2]; //zero'd second table terminates parms
\r
1574 WCHAR wbuf[ MAXIMUM_FILENAME_LENGTH ];
\r
1576 MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString(Enter) RegPath = %ws\n ValueName =%ws\n", RegPath, ValueName));
\r
1578 path.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof( WCHAR ); // MAXIMUM_FILENAME_LENGTH defined in wdm.h
\r
1579 path.Buffer = wbuf;
\r
1582 RtlZeroMemory(path.Buffer, path.MaximumLength);
\r
1583 RtlMoveMemory(path.Buffer, RegPath, wcslen( RegPath) * sizeof( WCHAR ));
\r
1585 MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString() path= %ws\n", path.Buffer ));
\r
1587 RtlZeroMemory(paramTable, sizeof(paramTable));
\r
1589 paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
\r
1590 paramTable[0].Name = ValueName;
\r
1591 paramTable[0].EntryContext = Value;
\r
1592 paramTable[0].DefaultType = REG_SZ;
\r
1593 paramTable[0].DefaultData = DfltValue;
\r
1594 paramTable[0].DefaultLength = DfltValue->MaximumLength;
\r
1597 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
\r
1598 path.Buffer, ¶mTable[0], NULL, NULL);
\r
1600 if (NT_SUCCESS(status)) {
\r
1601 MdKdPrint( DBGLVL_MEDIUM,("MdGetRegistryString(Exit) SUCCESS, value = %ws \n", Value));
\r
1606 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_INVALID_PARAMETER) ,("MdGetRegistryString(Exit) STATUS_INVALID_PARAMETER\n"));
\r
1608 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_OBJECT_NAME_NOT_FOUND) ,("MdGetRegistryString(Exit) STATUS_OBJECT_NAME_NOT_FOUND\n"));
\r
1617 /*------------------------------------------------------------------------------------------------------*/
\r
1620 RegistryMultiSzCallBack(
\r
1621 IN PWSTR ValueName,
\r
1622 IN ULONG ValueType,
\r
1623 IN PVOID ValueData,
\r
1624 IN ULONG ValueLength,
\r
1626 IN PVOID EntryContext
\r
1630 Routine Description:
\r
1632 This callback for a registry SZ or MULTI_SZ is called once for each
\r
1633 SZ in the value. It will attempt to match the data with the
\r
1634 UNICODE_STRING passed in as Context, and modify EntryContext if a
\r
1635 match is found. Written for ClasspCheckRegistryForMediaChangeCompletion
\r
1639 ValueName - name of the key that was opened
\r
1640 ValueType - type of data stored in the value (REG_SZ for this routine)
\r
1641 ValueData - data in the registry, in this case a wide string
\r
1642 ValueLength - length of the data including the terminating null
\r
1643 Context - unicode string to compare against ValueData
\r
1644 EntryContext - should be initialized to 0, will be set to 1 if match found
\r
1649 EntryContext will be 1 if found
\r
1653 UNICODE_STRING uStr;
\r
1657 UNREFERENCED_PARAMETER(ValueName);
\r
1658 UNREFERENCED_PARAMETER(ValueLength);
\r
1659 UNREFERENCED_PARAMETER(EntryContext);
\r
1661 // if the data is not a terminated string, exit
\r
1662 if (ValueType != REG_SZ) return STATUS_SUCCESS;
\r
1664 // convert wide string to ASCII
\r
1665 RtlInitUnicodeString( &uStr, ValueData );
\r
1666 RtlInitAnsiString( &aStr, NULL );
\r
1667 RtlUnicodeStringToAnsiString( &aStr, &uStr, TRUE ); \
\r
1669 // call user routine
\r
1670 ((RegUserCallback_t)Context)(&aStr);
\r
1673 RtlFreeAnsiString( &aStr );
\r
1675 return STATUS_SUCCESS;
\r
1679 MdGetRegistryMultiString(
\r
1680 IN PWCHAR RegPath,
\r
1681 IN PWCHAR ValueName,
\r
1682 IN PVOID DfltValue,
\r
1683 IN ULONG DfltValueSize,
\r
1684 IN RegUserCallback_t Func
\r
1689 Routine Description:
\r
1691 Obtain a string value from the registry
\r
1696 RegPath -- supplies absolute registry path
\r
1697 ValueName - Supplies the Value Name.
\r
1698 Value - receives the REG_DWORD value.
\r
1702 TRUE if successfull, FALSE on fail.
\r
1707 UNICODE_STRING path;
\r
1708 RTL_QUERY_REGISTRY_TABLE paramTable[2]; //zero'd second table terminates parms
\r
1711 WCHAR wbuf[ MAXIMUM_FILENAME_LENGTH ];
\r
1714 MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString(Enter) RegPath = %ws\n ValueName =%ws\n", RegPath, ValueName));
\r
1716 path.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof( WCHAR ); // MAXIMUM_FILENAME_LENGTH defined in wdm.h
\r
1717 path.Buffer = wbuf;
\r
1720 RtlZeroMemory(path.Buffer, path.MaximumLength);
\r
1721 RtlMoveMemory(path.Buffer, RegPath, wcslen( RegPath) * sizeof( WCHAR ));
\r
1723 MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString() path= %ws\n", path.Buffer ));
\r
1725 RtlZeroMemory(paramTable, sizeof(paramTable));
\r
1727 paramTable[0].QueryRoutine = RegistryMultiSzCallBack;
\r
1728 paramTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
\r
1729 paramTable[0].Name = ValueName;
\r
1730 paramTable[0].EntryContext = &ulDummy;
\r
1731 paramTable[0].DefaultType = REG_MULTI_SZ;
\r
1732 paramTable[0].DefaultData = DfltValue;
\r
1733 paramTable[0].DefaultLength = DfltValueSize;
\r
1736 status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
\r
1737 path.Buffer, ¶mTable[0], Func, NULL);
\r
1739 if (NT_SUCCESS(status)) {
\r
1744 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_INVALID_PARAMETER) ,("MdGetRegistryString(Exit) STATUS_INVALID_PARAMETER\n"));
\r
1746 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_OBJECT_NAME_NOT_FOUND) ,("MdGetRegistryString(Exit) STATUS_OBJECT_NAME_NOT_FOUND\n"));
\r