[HCA] Distinguish between Tavor and Arbel HCAs, report correct device ID
[mirror/winof/.git] / hw / mt23108 / vapi / mlxsys / os_dep / win / tdriver / MdUtil.c
1 /*\r
2  * Copyright (c) 2004-2005 Mellanox Technologies Ltd.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\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
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\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
19  *\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
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 #include "MdGen.h" \r
33 \r
34 /*------------------------------------------------------------------------------------------------------*/\r
35 \r
36 VOID\r
37 WriteEventLogEntry(\r
38         PVOID   pi_pIoObject,\r
39         ULONG   pi_ErrorCode,\r
40         ULONG   pi_UniqueErrorCode,\r
41         ULONG   pi_FinalStatus,\r
42         ULONG   pi_nDataItems,\r
43         ...\r
44         )\r
45 /*++\r
46 \r
47 Routine Description:\r
48     Writes an event log entry to the event log.\r
49 \r
50 Arguments:\r
51 \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
57         .\r
58         . data items values\r
59         .\r
60 \r
61 Return Value:\r
62 \r
63         None .\r
64 \r
65 --*/\r
66 { /* WriteEventLogEntry */\r
67 \r
68         /* Variable argument list */    \r
69         va_list                                 l_Argptr;\r
70         /* Pointer to an error log entry */\r
71         PIO_ERROR_LOG_PACKET    l_pErrorLogEntry; \r
72 \r
73         /* Init the variable argument list */   \r
74         va_start(l_Argptr, pi_nDataItems);\r
75 \r
76         /* Allocate an error log entry */ \r
77     l_pErrorLogEntry = \r
78         (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(\r
79                                                                 pi_pIoObject,\r
80                                                                 (UCHAR)(sizeof(IO_ERROR_LOG_PACKET)+pi_nDataItems*sizeof(ULONG))\r
81                                                                 ); \r
82         /* Check allocation */\r
83     if ( l_pErrorLogEntry != NULL) \r
84         { /* OK */\r
85 \r
86                 /* Data item index */\r
87                 USHORT l_nDataItem ;\r
88 \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
98 \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
102 \r
103                         /* Current data item */\r
104                         int l_CurDataItem ;\r
105                                 \r
106                         /* Get next data item */\r
107                         l_CurDataItem = va_arg( l_Argptr, int);\r
108 \r
109             /* Put it into the data array */\r
110                         l_pErrorLogEntry->DumpData[l_nDataItem] = l_CurDataItem ;\r
111 \r
112                 } /* Inset a data item */\r
113 \r
114         /* Write the packet */\r
115                 IoWriteErrorLogEntry(l_pErrorLogEntry);\r
116 \r
117     } /* OK */\r
118 \r
119         /* Term the variable argument list */   \r
120         va_end(l_Argptr);\r
121 \r
122 } /* WriteEventLogEntry */\r
123 \r
124 /*------------------------------------------------------------------------------------------------------*/\r
125 \r
126 \r
127 NTSTATUS\r
128 MdAddDevice(\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
134     )\r
135 /*++\r
136 \r
137 Routine Description:\r
138     This routine creates a device object, the symbolic link in \DosDevices and allocates device extension\r
139 \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
142 \r
143 \r
144 Arguments:\r
145 \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
151 \r
152 Return Value:\r
153 \r
154     STATUS_SUCCESS if the device and link are created correctly, otherwise\r
155     an error indicating the reason for failure.\r
156 \r
157 --*/\r
158 { /* MdAddDevice */\r
159 \r
160         /* Status of utility calls */\r
161     NTSTATUS                            l_Status;\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
166 \r
167         \r
168         /* Create a new device */\r
169     l_Status = IoCreateDevice(\r
170                                     pi_pDriverObject,\r
171                                     pi_nExtSize,\r
172                                     pi_pNtDeviceName,\r
173                                     FILE_DEVICE_UNKNOWN,\r
174                                     0,\r
175                                     FALSE, /* Not Exclusive */\r
176                                     &l_pFdo\r
177                                     );\r
178 \r
179         /* If device creation failed return the error code */\r
180     if ( !NT_SUCCESS(l_Status) )\r
181         { /* Device creation failed */\r
182 \r
183                 /* Return error code */\r
184         return l_Status;\r
185 \r
186         } /* Device creation failed */\r
187 \r
188         /*\r
189          * Create the symbolic link.\r
190          */\r
191     l_Status = IoCreateSymbolicLink( pi_pWin32DeviceName, pi_pNtDeviceName );\r
192 \r
193         /*\r
194          * If we we couldn't create the link then\r
195          * abort installation... delete the created device\r
196          */\r
197     if ( !NT_SUCCESS( l_Status ) )\r
198     { /* Create symbolic link failed */\r
199 \r
200                 /* Delete the created device */\r
201         IoDeleteDevice( l_pFdo );\r
202 \r
203         return l_Status;\r
204 \r
205     } /* Create symbolic link failed */\r
206 \r
207     /*\r
208          * Set up the rest of the device info :\r
209      */\r
210 \r
211         /* Use direct IO */\r
212 \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
216 \r
217         /* Word alignment */\r
218     l_pFdo->AlignmentRequirement = FILE_BYTE_ALIGNMENT;\r
219 \r
220     /*\r
221          * Set up some device context fields\r
222      */\r
223 \r
224         /* get device context */\r
225         l_pMdDevContext = (PMD_DEV_CONTEXT_T)l_pFdo->DeviceExtension;\r
226 \r
227         /* zero the context */\r
228         RtlZeroMemory(l_pFdo->DeviceExtension, pi_nExtSize);\r
229 \r
230         /* store handle to device */\r
231         l_pMdDevContext->m_pFdo = l_pFdo;\r
232 \r
233         /* Copy the Win32 device name */\r
234         #if 0\r
235         UCopyString( &l_pMdDevContext->m_usDosDeviceName, pi_pWin32DeviceName, TRUE );\r
236         MdExFreePool( pi_pWin32DeviceName->Buffer );\r
237         #else\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
241         #endif\r
242         pi_pWin32DeviceName->Buffer = NULL;\r
243 \r
244         /* Copy the Nt device name */\r
245         #if 0\r
246         UCopyString( &l_pMdDevContext->m_usNtDeviceName, pi_pNtDeviceName, TRUE );\r
247         MdExFreePool( pi_pNtDeviceName->Buffer );\r
248         #else\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
252         #endif\r
253         pi_pNtDeviceName->Buffer = NULL;\r
254 \r
255         /* store the result */\r
256         *po_ppMdDevContext = l_pMdDevContext;\r
257         \r
258     return STATUS_SUCCESS;\r
259 \r
260 } /* MdAddDevice */\r
261 \r
262 /*------------------------------------------------------------------------------------------------------*/\r
263 \r
264 VOID\r
265 MdDelDevice(\r
266         IN      PMD_DEV_CONTEXT_T       pi_pMdDevContext\r
267     )\r
268 /*++\r
269 \r
270 Routine Description:\r
271         This routine is called to remove the device.\r
272 \r
273 \r
274 Arguments:\r
275 \r
276         pi_pMdDevContext...... The device context\r
277 \r
278 Return Value:\r
279 \r
280     STATUS_SUCCESS if the device and link are created correctly, otherwise\r
281     an error indicating the reason for failure.\r
282 \r
283 --*/\r
284 { /* MdDelDevice */\r
285 \r
286         /* Delete the symbolic link */\r
287         IoDeleteSymbolicLink(&pi_pMdDevContext->m_usDosDeviceName);\r
288 \r
289         /* Free the DOS device names string buffer */\r
290         if (pi_pMdDevContext->m_usDosDeviceName.Buffer != NULL)\r
291         {\r
292                 PUSHORT l_pBuf = pi_pMdDevContext->m_usDosDeviceName.Buffer;\r
293                 pi_pMdDevContext->m_usDosDeviceName.Buffer = NULL;\r
294                 MdExFreePool( l_pBuf );\r
295         }\r
296 \r
297         /* Free the NT device names string buffer */\r
298         if (pi_pMdDevContext->m_usNtDeviceName.Buffer != NULL)\r
299         {\r
300                 PUSHORT l_pBuf = pi_pMdDevContext->m_usNtDeviceName.Buffer;\r
301                 pi_pMdDevContext->m_usNtDeviceName.Buffer = NULL;\r
302                 MdExFreePool( l_pBuf );\r
303         }\r
304 \r
305         /* Delete the created device */\r
306         if (pi_pMdDevContext->m_pFdo)\r
307         {\r
308                 PDEVICE_OBJECT  l_pFdo = pi_pMdDevContext->m_pFdo;\r
309                 pi_pMdDevContext->m_pFdo = NULL;\r
310                 IoDeleteDevice( l_pFdo );\r
311         }\r
312 \r
313 } /* MdDelDevice */\r
314 \r
315 /*------------------------------------------------------------------------------------------------------*/\r
316 \r
317 static void GetRegistryDword(\r
318         IN      PWCHAR  pi_ParamName,\r
319         IN      ULONG   pi_DfltValue,\r
320         OUT     PLONG   po_Result\r
321 )       \r
322 {\r
323         ULONG l_uValue = 0;\r
324                 \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
329                         \r
330         if (!l_uValue)\r
331         { /* no Registry value - set default */\r
332                 *po_Result = pi_DfltValue;\r
333         } /* no Registry value - set default */\r
334         else\r
335         { /* store Registry value */\r
336                 *po_Result = l_uValue;\r
337         } /* store Registry value */\r
338 }\r
339 \r
340 /*------------------------------------------------------------------------------------------------------*/\r
341 \r
342 NTSTATUS\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
349     )\r
350 /*++\r
351 \r
352 Routine Description:\r
353     This routine creates the device extension\r
354 \r
355 \r
356 Arguments:\r
357 \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
363 \r
364 Return Value:\r
365 \r
366     STATUS_SUCCESS if the device extension was created correctly, otherwise\r
367     an error indicating the reason for failure.\r
368 \r
369 --*/\r
370 { /* MdCreateDevContext */\r
371 \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
376 \r
377         /*\r
378          * Initialize the device context with the template device context\r
379          */\r
380 \r
381         /* Create the device */\r
382         l_Status = MdAddDevice(\r
383                 pi_pDriverObject,\r
384                 pi_pNtDeviceName,\r
385                 pi_pWin32DeviceName,\r
386                 sizeof(MD_DEV_CONTEXT_T),\r
387                 &l_pMdDevContext\r
388                 );\r
389 \r
390         /* Check if device create ok */\r
391         if ( !NT_SUCCESS(l_Status) )\r
392         { /* Device creation failed */\r
393 \r
394                 /* Set the device context to 0 */\r
395                 *pio_ppDevContext = NULL;\r
396 \r
397                 /* Return error code */\r
398                 return l_Status;\r
399 \r
400         } /* Device creation failed */\r
401 \r
402         /* Save device type/channel */\r
403         l_pMdDevContext->m_eDevType = pi_eDevType;\r
404 \r
405         /*\r
406          * Init the rest fields of the driver context\r
407          */ \r
408 \r
409         /* spinlock */\r
410         INIT_LOCK_IT( &l_pMdDevContext->m_SpinLock );\r
411 \r
412         // spinlock used to protect inc/dec iocount logic\r
413         KeInitializeSpinLock (&l_pMdDevContext->m_IoCntSpinLock);\r
414 \r
415     // init events\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
419 \r
420         // init queue header\r
421         InitializeListHead( &l_pMdDevContext->m_PcsQue );\r
422         \r
423         // init semaphore\r
424         KSEM_INIT( &l_pMdDevContext->m_Sem );\r
425                         \r
426         // init mutex\r
427         KMUTEX_INIT( &l_pMdDevContext->m_Mutex );\r
428                         \r
429         // set flag\r
430         l_pMdDevContext->m_fDeletePending = FALSE;\r
431 \r
432         switch (l_pMdDevContext->m_eDevType) \r
433         { /* device-specific init */\r
434 \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
439                         break;\r
440                         \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
447                         break;\r
448 \r
449                 case MD_DEV_IX_TAVOR:\r
450                 case MD_DEV_IX_ARBEL_TM:\r
451                         GetRegistryDword( L"DdrMapOffset",      MD_DFLT_CONF_DATA, &l_pMdDevContext->m_ulDdrMapOffset );\r
452                         GetRegistryDword( L"DdrMapSize",        MD_DFLT_CONF_DATA, &l_pMdDevContext->m_ulDdrMapSize );\r
453                         GetRegistryDword( L"ResetCard",         MD_DFLT_CONF_DATA, &l_pMdDevContext->m_PerformReset );\r
454                         l_pMdDevContext->m_nPendingIoCnt = 0;\r
455                         l_pMdDevContext->m_hHhHca = NULL;\r
456                         break;\r
457                         \r
458                 case MD_DEV_IX_CTRL:\r
459                 { /* specific Control device initialization */\r
460                         /* pending IO requests: setting 1 here for "adding" the Control device ('cause OS won't call to AddDevice) */\r
461                         l_pMdDevContext->m_nPendingIoCnt = 1;\r
462 \r
463                         /* Device open counter */\r
464                         l_pMdDevContext->m_nOpenCount = 0;\r
465         \r
466                         // mark device started\r
467                         l_pMdDevContext->m_DeviceStarted = TRUE;\r
468                         \r
469                         break;\r
470                 } /* specific Control device initialization */\r
471 \r
472         } /* device-specific init */\r
473 \r
474         /* Return the new created extension */\r
475         *pio_ppDevContext       = l_pMdDevContext;\r
476 \r
477     return l_Status;\r
478 \r
479 } /* MdCreateDevContext */\r
480 \r
481 /*------------------------------------------------------------------------------------------------------*/\r
482 \r
483 NTSTATUS\r
484 MdRemoveDevContext (\r
485     IN  PMD_DEV_CONTEXT_T               pi_pMdDevContext\r
486     )\r
487 /*++\r
488 \r
489 Routine Description:\r
490     This routine releases the device context resources and remove the device\r
491 \r
492 \r
493 Arguments:\r
494 \r
495     pi_pMdDevContext........ Pointer to the device context.\r
496 \r
497 Return Value:\r
498 \r
499     STATUS_SUCCESS if the device extension was created correctly, otherwise\r
500     an error indicating the reason for failure.\r
501 \r
502 --*/\r
503 { /* MdRemoveDevContext */\r
504 \r
505         \r
506         if (pi_pMdDevContext != NULL)\r
507         {\r
508                 /* close direct PCI interface */\r
509                 if (pi_pMdDevContext->m_eDevType != MD_DEV_IX_CTRL)\r
510                   PciIfClose(  &pi_pMdDevContext->m_Interface );\r
511                 \r
512                 /* Remove the device */\r
513                 MdDelDevice( pi_pMdDevContext );\r
514                 \r
515                 /* remove device context */\r
516                 /* NO NEED, BECAUSE IT WAS RELEASED ON IoDeleteDevice() ! \r
517                 MdExFreePool( pi_pMdDevContext );\r
518                 */\r
519         }\r
520 \r
521         return STATUS_SUCCESS;\r
522 \r
523 } /* MdRemoveDevContext */\r
524 \r
525 /*------------------------------------------------------------------------------------------------------*/\r
526 \r
527 NTSTATUS \r
528 MdDevInit(\r
529         IN              PMD_DRV_CONTEXT_T                               pi_pDrvContext,\r
530         IN              MD_DEV_IX_E                                             pi_eDevType,\r
531         IN              PUNICODE_STRING                                 pi_pNtDeviceName,\r
532         IN              PUNICODE_STRING                                 pi_pWin32DeviceName,\r
533     IN OUT      PVOID*                                                  pio_ppDevContext\r
534         )\r
535 /*++\r
536 \r
537 Routine Description:\r
538     This routine creates the device and connect to the driver context\r
539 \r
540 \r
541 Arguments:\r
542 \r
543         pi_pDrvContext.......... Driver context\r
544         pi_eDevType............. Device type.\r
545         pi_pNtDeviceName........ The \Device\????\ name\r
546         pi_pWin32DeviceName..... The \DosDevices\????\ name\r
547         pio_ppDevContext........ The device extension ofthe created object\r
548 \r
549 Return Value:\r
550 \r
551     STATUS_SUCCESS on success, otherwise an error indicating the reason for failure.\r
552 \r
553 --*/\r
554 { /* MdDevInit */\r
555 \r
556         /* Local status variable */\r
557     NTSTATUS                                    l_Status;\r
558         /* Default debug ON/OFF flag */\r
559         ULONG                                           l_nDfltDebugPrintLevel = FALSE ;\r
560         /* Device context */\r
561         PMD_DEV_CONTEXT_T                       l_pMdDevContext;\r
562 \r
563     MdKdPrint( DBGLVL_MINIMUM ,("(MdDevInit) init device '%ws'\n", pi_pWin32DeviceName->Buffer ));\r
564 \r
565         /*\r
566          * Create the device and the device context\r
567          */\r
568         l_Status = MdCreateDevContext(\r
569                                                 pi_pDrvContext->m_pDrvObject,\r
570                                                 pi_eDevType,\r
571                                                 pi_pNtDeviceName,\r
572                                                 pi_pWin32DeviceName,\r
573                                                 &l_pMdDevContext\r
574                                                 );\r
575 \r
576         /* Check creation status */\r
577         if ( NT_SUCCESS(l_Status) )\r
578         { /* Loaded OK */\r
579                 PRE_LOCK_IT;\r
580 \r
581                 MdKdPrint( DBGLVL_DEFAULT ,("(MdDeviceInit) Device successfuly initialized\n"));\r
582 \r
583                 /* Store the device context */\r
584                 *pio_ppDevContext = l_pMdDevContext;\r
585 \r
586                 /* Add the device context to the driver list */\r
587                 LOCK_IT( &pi_pDrvContext->m_SpinLock);\r
588                 InsertTailList( &pi_pDrvContext->m_DevQue, &l_pMdDevContext->m_Link );\r
589                 UNLOCK_IT( &pi_pDrvContext->m_SpinLock);\r
590                 \r
591                 /* connect device to driver */\r
592                 l_pMdDevContext->m_pDrvContext = pi_pDrvContext;\r
593 \r
594                 /* Update number of device instances */\r
595                 InterlockedIncrement( &pi_pDrvContext->m_uDevNo );\r
596 \r
597                 // increment the number of cards\r
598                 {\r
599                         int l_ix = (int)l_pMdDevContext->m_eDevType;\r
600                         PMD_HAL_DEV_PARAMS_T l_pDev = &g_DevParams[l_ix];\r
601                         if (l_pDev->m_fExpose)\r
602                                 InterlockedIncrement( &g_pDrvContext->m_uCardNo );\r
603                 }\r
604         } /* Loaded OK */\r
605 \r
606         return l_Status ;\r
607 \r
608 } /* MdDevInit */\r
609 \r
610 /*------------------------------------------------------------------------------------------------------*/\r
611 \r
612 void\r
613 ReleasePendingRequests(\r
614     IN PMD_DEV_CONTEXT_T        pi_pMdDevContext\r
615     )\r
616 /*++\r
617 \r
618 Routine Description:\r
619 \r
620     Release pending requests of the Control Device \r
621 \r
622 Arguments:\r
623 \r
624     pi_pMdDevContext - pointer to the Control Device\r
625 \r
626 Return Value:\r
627 \r
628 --*/\r
629 { /* ReleasePendingRequests */\r
630         MdKdPrint( DBGLVL_MINIMUM ,("(ReleasePendingRequests) Enter \n" ));\r
631 } /* ReleasePendingRequests */\r
632 \r
633 \r
634 /*------------------------------------------------------------------------------------------------------*/\r
635 \r
636 NTSTATUS \r
637 MdDevDeInit(\r
638         IN PMD_DEV_CONTEXT_T                    pi_pMdDevContext        \r
639         )\r
640 /*++\r
641 \r
642 Routine Description:\r
643     This routine DeInitialize the device setting and context\r
644 \r
645 \r
646 Arguments:\r
647 \r
648         pi_pMdDevContext........The device context\r
649 Return Value:\r
650 \r
651     None.\r
652 \r
653 --*/\r
654 { /* MdDevDeInit */\r
655         /* Current device object */\r
656         PDEVICE_OBJECT                  l_pFdo ;\r
657         /* The Driver context */\r
658     PMD_DRV_CONTEXT_T           l_pMdDrvContext;\r
659         // prepare lock\r
660         PRE_LOCK_IT;\r
661 \r
662         MdKdPrint( DBGLVL_MINIMUM ,("(MdDevDeInit) Unloading device '%ws' \n", pi_pMdDevContext->m_usDosDeviceName.Buffer));\r
663 \r
664         /* Parameter validation*/\r
665         if ( pi_pMdDevContext == NULL )\r
666         { /* no device context */\r
667                 return STATUS_UNSUCCESSFUL;\r
668         } /* no device context */\r
669 \r
670     /* Get the first device object */\r
671     l_pFdo = pi_pMdDevContext->m_pFdo;\r
672 \r
673         /* Check if driver has any device */\r
674         if ( l_pFdo == NULL ) \r
675         { /* no NT device object */\r
676                 return STATUS_UNSUCCESSFUL;\r
677         } /* no NT device object */\r
678 \r
679         /* get driver context */\r
680         l_pMdDrvContext = pi_pMdDevContext->m_pDrvContext;\r
681 \r
682         /*\r
683          * Remove the device from the Driver device list\r
684          */\r
685 \r
686         // acquire access to the critical section\r
687         LOCK_IT( &pi_pMdDevContext->m_SpinLock );\r
688 \r
689         // disconnect the global context with device one\r
690         RemoveEntryList( &pi_pMdDevContext->m_Link );\r
691 \r
692         // release access to the critical section\r
693         UNLOCK_IT( &pi_pMdDevContext->m_SpinLock );\r
694 \r
695         // decrement the number of created devices\r
696         LOCK_IT( &l_pMdDrvContext->m_SpinLock);\r
697         if ( l_pMdDrvContext->m_uDevNo > 0)\r
698                 InterlockedDecrement( &l_pMdDrvContext->m_uDevNo );\r
699         UNLOCK_IT( &l_pMdDrvContext->m_SpinLock);\r
700 \r
701         // decrement the number of cards\r
702         {\r
703                 int l_ix = (int)pi_pMdDevContext->m_eDevType;\r
704                 PMD_HAL_DEV_PARAMS_T l_pDev = &g_DevParams[l_ix];\r
705                 if (l_pDev->m_fExpose && l_pMdDrvContext->m_uCardNo > 0)\r
706                         InterlockedDecrement( &l_pMdDrvContext->m_uCardNo );\r
707         }\r
708         /* Free the Device context */\r
709         return MdRemoveDevContext( pi_pMdDevContext );\r
710 \r
711 } /* MdDevDeInit */\r
712 \r
713 NTSTATUS \r
714 MdGetDevLocation(\r
715         IN      PDEVICE_OBJECT  pi_pPdo,\r
716         IN      ULONG *                 pi_pBus,\r
717         IN      ULONG *                 pi_pSlot,\r
718         IN      ULONG *                 pi_pFunction\r
719         )\r
720 {\r
721         ULONG   l_BusNumber, l_DevNumber, l_Function, l_ResultLength = 0;\r
722         WCHAR   l_Buffer[40], *l_pEnd, *l_pBuf = l_Buffer, *l_pBufEnd = l_Buffer + sizeof(l_Buffer);\r
723         NTSTATUS        l_Status;\r
724         UNICODE_STRING  l_UnicodeNumber;\r
725 \r
726         /* prepare */\r
727         l_ResultLength = 0;\r
728         RtlZeroMemory( l_Buffer, sizeof(l_Buffer) );\r
729 \r
730         /* Get the device number  */\r
731         l_Status = IoGetDeviceProperty(pi_pPdo,\r
732                 DevicePropertyLocationInformation, sizeof(l_Buffer), &l_Buffer, &l_ResultLength);\r
733 \r
734         /* Verify if the function was successful */\r
735         if ( !NT_SUCCESS(l_Status) || !l_ResultLength ) {\r
736                 MdKdPrint( DBGLVL_DEFAULT ,("(MdInitPciCfgCard) Unable to get device number: Status 0x%x, ResultSize %d \n", \r
737                         l_Status, l_ResultLength  ));\r
738                 goto exit;      \r
739         }\r
740 \r
741         // ALL THE BELOW CRAP WE DO INSTEAD OF \r
742         // sscanf(l_Buffer, "PCI bus %d, device %d, function %d", &l_BusNumber, &l_DevNumber, &l_Function );\r
743 \r
744         /* take bus number */\r
745         l_pBuf  = WcharFindChar( l_pBuf, l_pBufEnd, L'0', L'9' );\r
746         if (l_pBuf == NULL) goto err;\r
747         l_pEnd  = WcharFindChar( l_pBuf, l_pBufEnd, L',', L',' );\r
748         if (l_pEnd == NULL) goto err;\r
749         l_UnicodeNumber.Length = l_UnicodeNumber.MaximumLength = (USHORT)((PCHAR)l_pEnd - (PCHAR)l_pBuf);\r
750         l_UnicodeNumber.Buffer = l_pBuf; l_pBuf = l_pEnd;\r
751         RtlUnicodeStringToInteger( &l_UnicodeNumber, 10, &l_BusNumber);\r
752 \r
753         /* take slot number */\r
754         l_pBuf  = WcharFindChar( l_pBuf, l_pBufEnd, L'0', L'9' );\r
755         if (l_pBuf == NULL) goto err;\r
756         l_pEnd  = WcharFindChar( l_pBuf, l_pBufEnd, L',', L',' );\r
757         if (l_pEnd == NULL) goto err;\r
758         l_UnicodeNumber.Length = l_UnicodeNumber.MaximumLength = (USHORT)((PCHAR)l_pEnd - (PCHAR)l_pBuf);\r
759         l_UnicodeNumber.Buffer = l_pBuf; l_pBuf = l_pEnd;\r
760         RtlUnicodeStringToInteger( &l_UnicodeNumber, 10, &l_DevNumber);\r
761 \r
762         /* take function number */\r
763         *(l_Buffer + (l_ResultLength>>1)) = 0;  /* set end of string */\r
764         l_pBuf  = WcharFindChar( l_pBuf, l_pBufEnd, L'0', L'9' );\r
765         if (l_pBuf == NULL) goto err;\r
766         l_pEnd  = WcharFindChar( l_pBuf, l_pBufEnd, 0, 0 );\r
767         if (l_pEnd == NULL) goto err;\r
768         l_UnicodeNumber.Length = l_UnicodeNumber.MaximumLength = (USHORT)((PCHAR)l_pEnd - (PCHAR)l_pBuf);\r
769         l_UnicodeNumber.Buffer = l_pBuf; l_pBuf = l_pEnd;\r
770         RtlUnicodeStringToInteger( &l_UnicodeNumber, 10, &l_Function);\r
771 \r
772         /* return the results */\r
773         *pi_pBus                = l_BusNumber;\r
774         *pi_pSlot               = l_DevNumber;\r
775         *pi_pFunction   = l_Function;\r
776         \r
777         goto exit;\r
778 \r
779 err:\r
780         l_Status = STATUS_UNSUCCESSFUL;\r
781 exit:\r
782         return l_Status;\r
783 }\r
784 \r
785 /*------------------------------------------------------------------------------------------------------*/\r
786 \r
787 NTSTATUS \r
788 MdInitPciCfgCard(\r
789         IN      PMD_DEV_CONTEXT_T               pi_pMdDevContext,\r
790         IN      PCM_RESOURCE_LIST               pi_pRawResources,\r
791         IN      PCM_RESOURCE_LIST               pi_pTranslatedResources\r
792         )\r
793 /*++\r
794 \r
795 Routine Description:\r
796 \r
797     This routine prepares the Driver to the work with a PCI card:\r
798                 - gets card resources from IRP;\r
799                 - store them on the device context;\r
800                 - translate physical address into virtual;\r
801                 - connect interrupt;\r
802 \r
803 Arguments:\r
804 \r
805         pi_pMdDevContext....... My device context\r
806         pi_pRawResources....... Card raw resources\r
807         pi_pTranslatedResources Card translated resources\r
808 \r
809 Return Value:\r
810 \r
811     None.\r
812 \r
813 --*/\r
814 { /* MdInitPciCfgCard */\r
815 \r
816         /* full resource descriptor */\r
817         PCM_FULL_RESOURCE_DESCRIPTOR            l_pFullResDesc;\r
818         /* partial resource list */\r
819         PCM_PARTIAL_RESOURCE_LIST                       l_pPartResList;\r
820         /* partial resource descriptor */\r
821         PCM_PARTIAL_RESOURCE_DESCRIPTOR         l_pPartResDesc;\r
822         /* number of resources */\r
823         ULONG                                                           l_nResCnt;\r
824         /* current resource number */\r
825         ULONG                                                           l_nCurResNum;\r
826         /* temporary address */\r
827         PUCHAR                                                          l_pPortAddr = NULL;\r
828         /* status */\r
829         NTSTATUS                                                        l_Status;\r
830         // Device IX  (in PCI configuration)                            \r
831     MD_DEV_IX_E                                                 l_DevIx = pi_pMdDevContext->m_eDevType; \r
832     // Device BD\r
833     PMD_HAL_DEV_PARAMS_T                                l_pDev = &g_DevParams[l_DevIx];\r
834     // current BAR descriptor \r
835         PMD_BAR_T       l_pBar;                                         \r
836         // for Debug \r
837         char *          l_BarName;                                      \r
838         \r
839         MdKdPrint( DBGLVL_DEFAULT ,("(MdInitPciCfgCard) Enter \n" ));\r
840 \r
841         /* zero the fields */\r
842 #define ZEROF(field)    pi_pMdDevContext->field = 0;\r
843     ZEROF(m_BusNumber);\r
844         ZEROF(m_DevNumber);\r
845         ZEROF(m_Function);\r
846         ZEROF(m_ulIntVector);\r
847         ZEROF(m_ulIntLevel);\r
848         ZEROF(m_Affinity);\r
849         ZEROF(m_fIntShared);\r
850         ZEROF(m_IntMode);\r
851         RtlZeroMemory( (void*)&pi_pMdDevContext->m_Cr, sizeof(MD_BAR_T));\r
852         RtlZeroMemory( (void*)&pi_pMdDevContext->m_Uar, sizeof(MD_BAR_T));\r
853         RtlZeroMemory( (void*)&pi_pMdDevContext->m_Ddr, sizeof(MD_BAR_T));\r
854 \r
855         if (l_DevIx == MD_DEV_IX_TAVOR_SD)\r
856         { /* get BARs via PCI configuration header */\r
857 \r
858                 l_Status = ReadBars( pi_pMdDevContext ); \r
859             if (!NT_SUCCESS(l_Status))\r
860                 return l_Status;\r
861 \r
862         } /* get BARs via PCI configuration header */\r
863         \r
864         else\r
865         { /* get resources from resource descriptors */\r
866         \r
867                 /* validate parameters */\r
868                 if (pi_pTranslatedResources == NULL) {\r
869                         MdKdPrint( DBGLVL_LOW ,("(MdInitPciCfgCard) No resources ! \n" ));\r
870                         return  STATUS_SUCCESS;\r
871                 }\r
872         \r
873                 /* prepare for getting resources */\r
874                 l_pFullResDesc          = &pi_pTranslatedResources->List[0];\r
875                 l_pPartResList          = &l_pFullResDesc->PartialResourceList;\r
876                 l_pPartResDesc          = &l_pPartResList->PartialDescriptors[0];\r
877                 l_nResCnt                       = l_pPartResList->Count;\r
878 \r
879                 /* store other parameters */\r
880                 for (l_nCurResNum = 0; l_nCurResNum < l_nResCnt; ++l_nCurResNum, ++l_pPartResDesc)\r
881             {\r
882                         switch (l_pPartResDesc->Type)\r
883                         {\r
884                                 case CmResourceTypeBusNumber:\r
885                                         /* Store IB card bus number */\r
886                                         //MDASSERT( pi_pMdDevContext->m_ulBusNumber == l_pPartResDesc->u.BusNumber.Start );\r
887                                         pi_pMdDevContext->m_BusNumber = l_pPartResDesc->u.BusNumber.Start;\r
888                                         break;\r
889 \r
890                                 case CmResourceTypeInterrupt:\r
891                                         pi_pMdDevContext->m_ulIntVector                 = l_pPartResDesc->u.Interrupt.Vector;\r
892                                         pi_pMdDevContext->m_ulIntLevel                  = (KIRQL)l_pPartResDesc->u.Interrupt.Level;\r
893                                         pi_pMdDevContext->m_Affinity                    = (KAFFINITY)l_pPartResDesc->u.Interrupt.Affinity;\r
894                                         pi_pMdDevContext->m_fIntShared                  = l_pPartResDesc->ShareDisposition == CmResourceShareShared;\r
895                                         pi_pMdDevContext->m_IntMode                             = (l_pPartResDesc->Flags == CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;\r
896                                         MdKdPrint( DBGLVL_LOW ,("(MdInitPciCfgCard) Dev %d Interrupt: Vector %d, Level %d, Affinity %d, Shared %d, Mode %d\n", \r
897                                                 l_pDev->m_DevId,  pi_pMdDevContext->m_ulIntVector, pi_pMdDevContext->m_ulIntLevel, \r
898                                                 pi_pMdDevContext->m_Affinity, pi_pMdDevContext->m_fIntShared, pi_pMdDevContext->m_IntMode ));\r
899                                 break;\r
900         \r
901                                 case CmResourceTypeMemory:\r
902                                         {\r
903                                                 ULONG l_BarNum;\r
904                                                 LARGE_INTEGER   l_Offset = { 0,0 };\r
905                                         \r
906                                                 /* decide, what BAR is it about */\r
907                                                 if (l_pDev->m_SizeBar0 >= l_pPartResDesc->u.Memory.Length) {\r
908                                                         l_pBar = &pi_pMdDevContext->m_Cr; l_BarName = "CR"; l_BarNum = 0; }\r
909                                                 else    \r
910                                                 if (l_pDev->m_SizeBar1 >= l_pPartResDesc->u.Memory.Length) {\r
911                                                         l_pBar = &pi_pMdDevContext->m_Uar; l_BarName = "UAR"; l_BarNum = 1; }\r
912                                                 else {\r
913                                                         l_pBar = &pi_pMdDevContext->m_Ddr; l_BarName = "DDR"; l_BarNum = 2; }\r
914                                                                 \r
915                                                 /* store BAR parameters */\r
916                                                 l_pBar->m_MemPhysAddr   = l_pPartResDesc->u.Memory.Start;\r
917                                                 l_pBar->m_ulMemSize             = l_pPartResDesc->u.Memory.Length;\r
918                                                 l_pBar->m_usMemFlags    = l_pPartResDesc->Flags;\r
919                                                 l_pBar->m_ulKernelSize  = l_pBar->m_ulMemSize;\r
920                                                 l_pBar->m_ulKernelOffset = 0;\r
921                                                 \r
922                                                 /* recalculate boundaries of mapped mempry for DDR */\r
923                                                 if (l_BarNum == 2 && pi_pMdDevContext->m_ulDdrMapSize != -1) {\r
924                                                         l_pBar->m_ulKernelSize = pi_pMdDevContext->m_ulDdrMapSize;\r
925                                                         l_pBar->m_ulKernelOffset = pi_pMdDevContext->m_ulDdrMapOffset;\r
926                                                         l_Offset.LowPart = pi_pMdDevContext->m_ulDdrMapOffset;\r
927                                                 } /* for DDR - map some subset of memory */\r
928                                                         \r
929                                                 /* map physical address into virtual kernel one */\r
930                                                 if (l_pBar->m_ulKernelSize) {\r
931                                                         l_Offset.QuadPart += l_pBar->m_MemPhysAddr.QuadPart;\r
932                                                 l_pBar->m_pKernelAddr = (PUCHAR) MmMapIoSpace(\r
933                                                         l_Offset, \r
934                                                         l_pBar->m_ulKernelSize, MmNonCached);\r
935                                                 }\r
936                                                 if (!l_pBar->m_pKernelAddr)     return STATUS_NO_MEMORY;\r
937         \r
938                                                 /* debug print */\r
939                                                 MdKdPrint( DBGLVL_LOW ,("(MdInitPciCfgCard) Dev %d %s: Phys 0x%I64x Size 0x%x, Virt 0x%x Size 0x%x \n", \r
940                                                         l_pDev->m_DevId,  l_BarName, l_pBar->m_MemPhysAddr, l_pBar->m_ulMemSize, \r
941                                                         l_pBar->m_pKernelAddr, l_pBar->m_ulKernelSize ));\r
942                                         } \r
943                                         break;\r
944         \r
945                                 default:\r
946                                         MdKdPrint( DBGLVL_DEFAULT ,("(MdInitPciCfgCard) Unsupported resource type 0x%x \n", l_pPartResDesc->Type ));\r
947                                         break;\r
948                         }\r
949                 }\r
950 \r
951         } /* get resources from resource descriptors */\r
952         \r
953         //\r
954         // get the device location information\r
955         //\r
956         { \r
957                 ULONG   l_BusNumber, l_DevNumber, l_Function;\r
958                 \r
959                 l_Status = MdGetDevLocation(    pi_pMdDevContext->m_pPdo, &l_BusNumber, &l_DevNumber, &l_Function );\r
960 \r
961                 if ( !NT_SUCCESS(l_Status) )\r
962                 { // fill default values \r
963                         l_BusNumber = g_pDrvContext->m_uDevNo;\r
964                         l_DevNumber = g_pDrvContext->m_uDevNo;\r
965                         l_Function      = 0;\r
966                 }\r
967 \r
968                 /* store the slot number */\r
969                 pi_pMdDevContext->m_BusNumber   = l_BusNumber;\r
970                 pi_pMdDevContext->m_DevNumber   = l_DevNumber;\r
971                 pi_pMdDevContext->m_Function    = l_Function;\r
972 \r
973                 MdKdPrint( DBGLVL_LOW ,("(MdInitPciCfgCard) Dev %d location is %d:%d:%d) \n", \r
974                         l_pDev->m_DevId,  l_BusNumber, l_DevNumber, l_Function ));\r
975         }\r
976 \r
977 \r
978         return STATUS_SUCCESS;\r
979 \r
980 } /* MdInitPciCfgCard */\r
981 \r
982 /*------------------------------------------------------------------------------------------------------*/\r
983 \r
984 VOID \r
985 MdDeInitPciCfgCard(\r
986         IN      PMD_DEV_CONTEXT_T               pi_pMdDevContext\r
987         )\r
988 /*++\r
989 \r
990 Routine Description:\r
991 \r
992     This routine releases OS resources, allocaetd for the work with a PCI card:\r
993                 - disconnect the interrupt;\r
994                 - unmap virtual address of the CR-space;\r
995 \r
996 \r
997 Arguments:\r
998 \r
999         pi_pMdDevContext....... My device context\r
1000 \r
1001 Return Value:\r
1002 \r
1003     None.\r
1004 \r
1005 --*/\r
1006 { /* MdDeInitPciCfgCard */\r
1007 \r
1008     // current BAR descriptor \r
1009         PMD_BAR_T       l_pBar;                                         \r
1010         // CR space address \r
1011         PUCHAR                          l_pAddr;\r
1012 \r
1013         // unmap CR-space\r
1014         l_pBar = &pi_pMdDevContext->m_Cr;\r
1015         l_pAddr = l_pBar->m_pKernelAddr;\r
1016         l_pBar->m_pKernelAddr = NULL;\r
1017         if (l_pAddr)\r
1018                 MmUnmapIoSpace(l_pAddr, l_pBar->m_ulKernelSize);\r
1019 \r
1020         // unmap UAR-space\r
1021         l_pBar = &pi_pMdDevContext->m_Uar;\r
1022         l_pAddr = l_pBar->m_pKernelAddr;\r
1023         l_pBar->m_pKernelAddr = NULL;\r
1024         if (l_pAddr)\r
1025                 MmUnmapIoSpace(l_pAddr, l_pBar->m_ulKernelSize);\r
1026 \r
1027         // unmap DDR-space\r
1028         l_pBar = &pi_pMdDevContext->m_Ddr;\r
1029         l_pAddr = l_pBar->m_pKernelAddr;\r
1030         l_pBar->m_pKernelAddr = NULL;\r
1031         if (l_pAddr)\r
1032                 MmUnmapIoSpace(l_pAddr, l_pBar->m_ulKernelSize);\r
1033 \r
1034 } /* MdDeInitPciCfgCard */\r
1035 \r
1036 /*------------------------------------------------------------------------------------------------------*/\r
1037 \r
1038 \r
1039 /*------------------------------------------------------------------------------------------------------*/\r
1040 \r
1041 PCHAR\r
1042 WcharToAscii(\r
1043         OUT     PUCHAR                  pi_TargetString,\r
1044         IN      const USHORT *  pi_SourceString,\r
1045         IN      ULONG                   pi_Size\r
1046         )\r
1047 /*++\r
1048 \r
1049 Routine Description:\r
1050     Converts wide-character string into ASCII\r
1051 \r
1052 Arguments:\r
1053 \r
1054         pi_TargetString...... result string\r
1055         pi_SourceString...... source string\r
1056         pi_Size.............. size of the source string\r
1057 \r
1058 Return Value:\r
1059 \r
1060         The result stringbytes.\r
1061 \r
1062 --*/\r
1063 { /* WcharToAscii */\r
1064         int             i, size         = (pi_Size + 1) >> 1;\r
1065         PCHAR   l_pResult       = pi_TargetString;\r
1066 \r
1067         for (i=0; i<size; i++)\r
1068         {\r
1069                 if (*pi_SourceString == 0)\r
1070                         break;\r
1071                 *l_pResult++ = (char)*pi_SourceString++;\r
1072         }\r
1073         *l_pResult = '\0';\r
1074 \r
1075         return pi_TargetString;\r
1076 \r
1077 } /* WcharToAscii */\r
1078 \r
1079 PWCHAR \r
1080 WcharFindChar(\r
1081         IN      PWCHAR          pi_BufStart,\r
1082         IN      PWCHAR          pi_BufEnd,\r
1083         IN      WCHAR           pi_FromPattern,\r
1084         IN      WCHAR           pi_ToPattern\r
1085         )\r
1086 /*++\r
1087 \r
1088 Routine Description:\r
1089     Converts wide-character string into ASCII\r
1090 \r
1091 Arguments:\r
1092 \r
1093         pi_BufStart.......... start of the source string\r
1094         pi_BufEnd............ end of the source string\r
1095         pi_FromPattern....... start of pattern range to find\r
1096         pi_ToPattern......... end of pattern range to find\r
1097 \r
1098 Return Value:\r
1099 \r
1100         pointer to the first pattern found or NULL (when reached the end)\r
1101 \r
1102 --*/\r
1103 { /* WcharFindChar */\r
1104 \r
1105         PWCHAR  l_pResult       = pi_BufStart;\r
1106 \r
1107         while (l_pResult < pi_BufEnd )\r
1108         {\r
1109                 if (*l_pResult >= pi_FromPattern && *l_pResult <= pi_ToPattern)\r
1110                         return l_pResult;\r
1111                 l_pResult++;\r
1112         }\r
1113 \r
1114         return NULL;\r
1115 \r
1116 } /* WcharFindChar */\r
1117 \r
1118 /*------------------------------------------------------------------------------------------------------*/\r
1119 \r
1120 USHORT \r
1121 AsciiToUnicode(\r
1122         PUNICODE_STRING pi_puTargetString,\r
1123         PUCHAR                  pi_szFormat,\r
1124         ...\r
1125         )\r
1126 /*++\r
1127 \r
1128 Routine Description:\r
1129     Writes a formatted ( printf like ) string to into a uniocde string.\r
1130 \r
1131 Arguments:\r
1132 \r
1133         pi_nDbgLogLevel...... Level of debugging log.\r
1134         pi_szFormat.......... The format of the log.\r
1135 \r
1136 Return Value:\r
1137 \r
1138         The formatted string length in bytes.\r
1139 \r
1140 --*/\r
1141 { /* AsciiToUnicode */\r
1142 \r
1143         /* Auxilary scratch buffer */\r
1144         static UCHAR    s_vScratchBuff[1024];\r
1145 \r
1146         /* Variable argument list */    \r
1147         va_list l_Argptr;\r
1148         /* Length of the formated string in bytes */\r
1149         int             l_nStrLenBytes ;\r
1150         /* Char index */\r
1151         USHORT  l_nCharNo ;\r
1152         /* Maximum lemgth */\r
1153         USHORT  l_nMaxLength;\r
1154 \r
1155         /* Init the variable argument list */   \r
1156         va_start(l_Argptr, pi_szFormat);\r
1157 \r
1158         /* Build the formatted string */\r
1159         l_nStrLenBytes = vsprintf(&s_vScratchBuff[0] , pi_szFormat , l_Argptr);\r
1160 \r
1161         /* Check if we need to allocate buffer */\r
1162         if ( pi_puTargetString->Buffer == NULL )\r
1163         { /* Need to allocate buffer */\r
1164 \r
1165                 /* Allocate the UNICODE string buffer */\r
1166                 pi_puTargetString->Buffer = \r
1167                         (PWCHAR)MdExAllocatePool(NonPagedPool,(l_nStrLenBytes+1)*sizeof(WCHAR));\r
1168 \r
1169                 /* If allocation failed return */\r
1170                 if ( pi_puTargetString->Buffer == NULL ) return 0;\r
1171 \r
1172                 /* Set the UNICODE string new parameters */\r
1173                 pi_puTargetString->MaximumLength = (USHORT)((l_nStrLenBytes+1)*sizeof(WCHAR)) ;\r
1174 \r
1175         } /* Need to allocate buffer */\r
1176 \r
1177         /* Reset the string actual length */\r
1178         pi_puTargetString->Length = 0;\r
1179 \r
1180         /* Calc max length */\r
1181         l_nMaxLength = MT_MIN((pi_puTargetString->MaximumLength/sizeof(WCHAR) - 1),(USHORT)l_nStrLenBytes);\r
1182 \r
1183         /* Convert to UNICODE */\r
1184         for ( l_nCharNo=0; l_nCharNo<l_nMaxLength; l_nCharNo++ )\r
1185         { /* Convert a CHAR to WCHAR */\r
1186 \r
1187                 /* Convert... */\r
1188                 pi_puTargetString->Buffer[ l_nCharNo ] = (WCHAR)s_vScratchBuff[l_nCharNo] ;\r
1189 \r
1190                 /* Update actual length */\r
1191                 pi_puTargetString->Length += sizeof(WCHAR) ;\r
1192 \r
1193         } /* Convert a CHAR to WCHAR */\r
1194 \r
1195         /* NULL terminate */\r
1196         pi_puTargetString->Buffer[ l_nCharNo ] = (WCHAR)'\0';\r
1197 \r
1198         /* Term the variable argument list */   \r
1199         va_end(l_Argptr);\r
1200 \r
1201         return pi_puTargetString->Length ;\r
1202 \r
1203 } /* AsciiToUnicode */\r
1204 \r
1205 /*------------------------------------------------------------------------------------------------------*/\r
1206 \r
1207 BOOLEAN\r
1208 MdCanAcceptIoRequests(\r
1209     IN PDEVICE_OBJECT DeviceObject\r
1210     )\r
1211 /*++\r
1212 \r
1213 Routine Description:\r
1214 \r
1215   Check device extension status flags; \r
1216 \r
1217      Can't accept a new io request if device:\r
1218       1) is removed, \r
1219       2) has never been started, \r
1220       3) is stopped,\r
1221       4) has a remove request pending, or\r
1222       5) has a stop device pending\r
1223 \r
1224 \r
1225 Arguments:\r
1226 \r
1227     DeviceObject - pointer to the device object for this instance of the 82930\r
1228                     device.\r
1229 \r
1230 \r
1231 Return Value:\r
1232 \r
1233     return TRUE if can accept new io requests, else FALSE\r
1234 \r
1235 --*/\r
1236 {\r
1237     PMD_DEV_CONTEXT_T   l_pMdDevContext = (PMD_DEV_CONTEXT_T)DeviceObject->DeviceExtension;\r
1238         BOOLEAN                         l_fCan = FALSE;\r
1239 \r
1240 \r
1241         //flag set when processing IRP_MN_REMOVE_DEVICE\r
1242     if ( !l_pMdDevContext->m_DeviceRemoved &&\r
1243                  // device must be started( enabled )\r
1244                  l_pMdDevContext->m_DeviceStarted &&\r
1245                  // flag set when driver has answered success to IRP_MN_QUERY_REMOVE_DEVICE\r
1246                  !l_pMdDevContext->m_RemoveDeviceRequested &&\r
1247                  // flag set when driver has answered success to IRP_MN_QUERY_STOP_DEVICE\r
1248                  !l_pMdDevContext->m_StopDeviceRequested  &&\r
1249                  // control device (MDCTL) marked for deleting)\r
1250                  !l_pMdDevContext->m_fDeletePending) {\r
1251                         l_fCan = TRUE;\r
1252         }\r
1253 \r
1254     MdKdPrintCond( DBGLVL_MAXIMUM, !l_fCan, ("**** FALSE return from MdCanAcceptIoRequests()!\n"));\r
1255 \r
1256         return l_fCan;\r
1257 }\r
1258 \r
1259 /*------------------------------------------------------------------------------------------------------*/\r
1260 \r
1261 BOOLEAN\r
1262 MdCreateDeviceNames(\r
1263         IN      PCHAR                           pi_pDevName,\r
1264         OUT     PUNICODE_STRING         po_pNtName,\r
1265         OUT     PUNICODE_STRING         po_pDosName\r
1266         )\r
1267 /*++\r
1268 \r
1269 Routine Description:\r
1270 \r
1271         Creates Nt and Dos names of the device;\r
1272         Convert them into Unicode format and put the results into given Unicode strings\r
1273         Allocates buffers for the Unicode strings from non-paged pool\r
1274 \r
1275 Arguments:\r
1276 \r
1277     pi_pDevName         - ASCII name of the device without path.\r
1278         po_pNtName              - pointer to Unicode string descriptor for NT device name\r
1279         po_pDosName             - pointer to Unicode string descriptor for DOS device name\r
1280 \r
1281 \r
1282 Return Value:\r
1283 \r
1284     return TRUE if succeeded to create strings, else FALSE\r
1285 \r
1286 --*/\r
1287 { /* MdCreateDeviceNames */\r
1288 \r
1289         /* buffer for ASCII device name */\r
1290         char    l_DevName[MD_MAX_DEV_NAME_LEN + 1];\r
1291         /* Unicode string length */\r
1292         int             l_nUnicodeNameLen;\r
1293 \r
1294         /* build NT name */\r
1295         strcpy( l_DevName, "\\Device\\" );\r
1296         strcat( l_DevName, pi_pDevName );\r
1297 \r
1298         /* get the length */\r
1299         l_nUnicodeNameLen = (int)((strlen(l_DevName) + 1) * sizeof(WCHAR));\r
1300 \r
1301         /*\r
1302          * Init the NT device name\r
1303          */\r
1304         /* Allocate buffers for the NT device name */\r
1305         po_pNtName->Buffer = MdExAllocatePool(NonPagedPool, l_nUnicodeNameLen);\r
1306 \r
1307         /* Verify allocation */\r
1308         if ( po_pNtName->Buffer == NULL )\r
1309         { /* Allocation failed */\r
1310 \r
1311                 return FALSE;\r
1312 \r
1313         } /* Allocation failed */\r
1314 \r
1315         /* store lengths */\r
1316         po_pNtName->Length                      = (USHORT)(l_nUnicodeNameLen - sizeof(WCHAR));\r
1317         po_pNtName->MaximumLength       = (unsigned short)l_nUnicodeNameLen;\r
1318 \r
1319         /* Build Unicode NT device name */\r
1320         AsciiToUnicode( \r
1321                 po_pNtName,\r
1322                 l_DevName\r
1323                 );\r
1324 \r
1325         /* build DOS name */\r
1326         strcpy( l_DevName, "\\DosDevices\\" );\r
1327         strcat( l_DevName, pi_pDevName );\r
1328 \r
1329         /* get the length */\r
1330         l_nUnicodeNameLen = (int)((strlen(l_DevName) + 1) * sizeof(WCHAR));\r
1331 \r
1332         /* Allocate buffers for the DOS device name */\r
1333         po_pDosName->Buffer = MdExAllocatePool(NonPagedPool, l_nUnicodeNameLen);\r
1334 \r
1335         /* Verify allocation */\r
1336         if ( po_pDosName->Buffer == NULL )\r
1337         { /* Allocation failed */\r
1338 \r
1339                 /* Free the NT device name path buffer */\r
1340                 MdExFreePool(po_pNtName->Buffer);\r
1341 \r
1342                 return FALSE;\r
1343 \r
1344         } /* Allocation failed */\r
1345 \r
1346         /* store lengths */\r
1347         po_pDosName->Length                     = (USHORT)(l_nUnicodeNameLen - sizeof(WCHAR));\r
1348         po_pDosName->MaximumLength      = (unsigned short)l_nUnicodeNameLen;\r
1349 \r
1350         /* Build the NT device name */\r
1351         AsciiToUnicode( \r
1352                 po_pDosName,\r
1353                 l_DevName\r
1354                 );\r
1355 \r
1356         return TRUE;\r
1357 \r
1358 } /* MdCreateDeviceNames */\r
1359 \r
1360 /*------------------------------------------------------------------------------------------------------*/\r
1361 \r
1362 /**********************************\r
1363  * Device name DB handling        *\r
1364  **********************************/\r
1365 int AddDevNameToDb(char *pi_DevName)\r
1366  {\r
1367         ULONG l_Size    = (ULONG)strlen(pi_DevName) + 1;\r
1368         ULONG l_DbSize  = g_pDrvContext->m_DevNamesDbSize;\r
1369 \r
1370         if ( l_DbSize + l_Size <= sizeof(g_pDrvContext->m_DevNamesDb))\r
1371         {\r
1372                 RtlCopyMemory( &g_pDrvContext->m_DevNamesDb[l_DbSize], pi_DevName, l_Size);\r
1373                 g_pDrvContext->m_DevNamesDbCnt++;\r
1374                 g_pDrvContext->m_DevNamesDbSize += l_Size;\r
1375                 return 0;\r
1376         }\r
1377         else\r
1378         {       \r
1379                 return 1;\r
1380         }\r
1381  }\r
1382 \r
1383 /*------------------------------------------------------------------------------------------------------*/\r
1384 /*------------------------------------------------------------------------------------------------------*/\r
1385 /*------------------------------------------------------------------------------------------------------*/\r
1386 /*------------------------------------------------------------------------------------------------------*/\r
1387 \r
1388 NTSTATUS CreateOneDevice(\r
1389         IN      int                                             pi_DevIx,                               /* index device BD info */\r
1390         UNICODE_STRING *                        pi_pusNtDeviceName,     /* NT name */\r
1391         UNICODE_STRING *                        pi_pusDosDeviceName,    /* Win32 name */\r
1392         OUT PMD_DEV_CONTEXT_T   *       pi_ppMdDevContext               /* context of created device */\r
1393 )\r
1394 {\r
1395         /* status */\r
1396     NTSTATUS                l_Status                    = STATUS_SUCCESS;\r
1397         /* our context to this device */\r
1398     PMD_DEV_CONTEXT_T       l_pMdDevContext;\r
1399         /* device object we create for the added device */\r
1400     PDEVICE_OBJECT          l_pFdo                              = NULL;\r
1401         /* dev info */\r
1402         PMD_HAL_DEV_PARAMS_T    l_pDevInfo;                     /* device BD info */\r
1403         /* buffer for ASCII device name */\r
1404         char                                    l_DevName[MD_MAX_DEV_NAME_LEN + 1];\r
1405     \r
1406    /* create and keep the exposed the name */\r
1407         l_pDevInfo = &g_DevParams[pi_DevIx];\r
1408         if (l_pDevInfo->m_DevId == MD_DEV_ID_TAVOR || l_pDevInfo->m_DevId == MD_DEV_ID_ARBEL_TM)\r
1409                 sprintf( l_DevName, l_pDevInfo->m_ExFormat, g_pDrvContext->m_uCardNo );\r
1410         else\r
1411                 sprintf( l_DevName, l_pDevInfo->m_ExFormat, l_pDevInfo->m_DevId, g_pDrvContext->m_uCardNo );\r
1412         if (l_pDevInfo->m_fExpose) {\r
1413                 if (AddDevNameToDb(l_DevName))\r
1414                     return STATUS_INSUFFICIENT_RESOURCES;\r
1415         }\r
1416 \r
1417         /* create Control Device names */\r
1418         /* !!! from now on work with ARBEL_TM as with TAVOR */\r
1419         //l_pDevInfo = (pi_DevIx == (int)MD_DEV_IX_ARBEL_TM) ? &g_DevParams[MD_DEV_IX_TAVOR] : &g_DevParams[pi_DevIx];\r
1420         l_pDevInfo =   &g_DevParams[pi_DevIx];\r
1421         if (l_pDevInfo->m_DevId == MD_DEV_ID_TAVOR || l_pDevInfo->m_DevId == MD_DEV_ID_ARBEL_TM)\r
1422                 sprintf( l_DevName, l_pDevInfo->m_Format, g_pDrvContext->m_uCardNo );\r
1423         else\r
1424                 sprintf( l_DevName, l_pDevInfo->m_Format, l_pDevInfo->m_DevId, g_pDrvContext->m_uCardNo );\r
1425 \r
1426         if (!MdCreateDeviceNames(l_DevName, pi_pusNtDeviceName, pi_pusDosDeviceName))\r
1427                 return STATUS_INSUFFICIENT_RESOURCES ;\r
1428         \r
1429         /* build NT name */\r
1430     MdKdPrint( DBGLVL_LOW,("(CreateOneDevice) Generated device name %s \n", l_DevName));\r
1431 \r
1432         /* create functional device object (FDO) */\r
1433         l_Status = MdDevInit( g_pDrvContext, l_pDevInfo->m_DevIx, pi_pusNtDeviceName, pi_pusDosDeviceName, &l_pMdDevContext); \r
1434 \r
1435     if (!NT_SUCCESS(l_Status))  \r
1436         { /* device creation failed */\r
1437 \r
1438                 /* Free the NT device name path buffer */\r
1439                 if (pi_pusNtDeviceName->Buffer)\r
1440                         MdExFreePool(pi_pusNtDeviceName->Buffer);\r
1441 \r
1442                 /* Free the Dos device name path buffer */\r
1443                 if (pi_pusDosDeviceName->Buffer)\r
1444                         MdExFreePool(pi_pusDosDeviceName->Buffer);\r
1445 \r
1446                 return l_Status;\r
1447         } /* device creation failed */\r
1448 \r
1449         /* save ASCII name */\r
1450         strcpy ( l_pMdDevContext->m_AsciiDevName, l_DevName );\r
1451 \r
1452         /* get FDO handle */\r
1453         l_pFdo = l_pMdDevContext->m_pFdo;\r
1454 \r
1455     //Set this flag causes the driver to not receive a IRP_MN_STOP_DEVICE\r
1456     //during suspend and also not get an IRP_MN_START_DEVICE during resume.\r
1457     l_pFdo->Flags |= DO_POWER_PAGABLE;\r
1458 \r
1459         *pi_ppMdDevContext = l_pMdDevContext;\r
1460     return STATUS_SUCCESS;\r
1461 }\r
1462 \r
1463 /*------------------------------------------------------------------------------------------------------*/\r
1464 \r
1465 BOOLEAN\r
1466 MdGetRegistryDword(\r
1467     IN      PWCHAR    RegPath,\r
1468     IN      PWCHAR    ValueName,\r
1469     IN OUT  PULONG    Value\r
1470     )\r
1471 \r
1472 /*++\r
1473 \r
1474 Routine Description:\r
1475 \r
1476         Obtain a Dword value from the registry\r
1477 \r
1478 \r
1479 Arguments:\r
1480 \r
1481     RegPath  -- supplies absolute registry path\r
1482     ValueName    - Supplies the Value Name.\r
1483     Value      - receives the REG_DWORD value.\r
1484 \r
1485 Return Value:\r
1486 \r
1487     TRUE if successfull, FALSE on fail.\r
1488 \r
1489 --*/\r
1490 \r
1491 {\r
1492     UNICODE_STRING path;\r
1493     RTL_QUERY_REGISTRY_TABLE paramTable[2];  //zero'd second table terminates parms\r
1494     ULONG lDef = *Value;                     // default\r
1495     NTSTATUS status;\r
1496     BOOLEAN fres;\r
1497         WCHAR wbuf[ MAXIMUM_FILENAME_LENGTH ];\r
1498 \r
1499     MdKdPrint( DBGLVL_HIGH,("Enter MdGetRegistryDword() RegPath = %ws\n   ValueName =%ws\n", RegPath, ValueName));\r
1500     path.Length = 0;\r
1501     path.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof( WCHAR );  // MAXIMUM_FILENAME_LENGTH defined in wdm.h\r
1502     path.Buffer = wbuf;\r
1503 \r
1504 \r
1505     RtlZeroMemory(path.Buffer, path.MaximumLength);\r
1506     RtlMoveMemory(path.Buffer, RegPath, wcslen( RegPath) * sizeof( WCHAR ));\r
1507 \r
1508     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryDword() path= %ws\n", path.Buffer ));\r
1509 \r
1510     RtlZeroMemory(paramTable, sizeof(paramTable));\r
1511 \r
1512     paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
1513 \r
1514     paramTable[0].Name = ValueName;\r
1515 \r
1516     paramTable[0].EntryContext = Value;\r
1517     paramTable[0].DefaultType = REG_DWORD;\r
1518     paramTable[0].DefaultData = &lDef;\r
1519     paramTable[0].DefaultLength = sizeof(ULONG);\r
1520 \r
1521 \r
1522     status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,\r
1523                                     path.Buffer, paramTable, NULL, NULL);\r
1524 \r
1525     if (NT_SUCCESS(status)) {\r
1526         MdKdPrint( DBGLVL_MEDIUM,("Exit MdGetRegistryDWord() SUCCESS, value = decimal %d 0x%x\n", *Value, *Value));\r
1527         fres = TRUE;\r
1528 \r
1529     } else {\r
1530 \r
1531         MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_INVALID_PARAMETER) ,("MdGetRegistryDWord() STATUS_INVALID_PARAMETER\n"));\r
1532  \r
1533                 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_OBJECT_NAME_NOT_FOUND) ,("MdGetRegistryDWord() STATUS_OBJECT_NAME_NOT_FOUND\n"));\r
1534 \r
1535         fres = FALSE;\r
1536 \r
1537     }\r
1538 \r
1539     return fres;\r
1540 }\r
1541 \r
1542 /*------------------------------------------------------------------------------------------------------*/\r
1543 \r
1544 BOOLEAN\r
1545 MdGetRegistryString(\r
1546     IN      PWCHAR                              RegPath,\r
1547     IN      PWCHAR                              ValueName,\r
1548     IN      PUNICODE_STRING             DfltValue,\r
1549     IN OUT  PUNICODE_STRING             Value\r
1550     )\r
1551 \r
1552 /*++\r
1553 \r
1554 Routine Description:\r
1555 \r
1556         Obtain a string value from the registry\r
1557 \r
1558 \r
1559 Arguments:\r
1560 \r
1561     RegPath  -- supplies absolute registry path\r
1562     ValueName    - Supplies the Value Name.\r
1563     Value      - receives the REG_DWORD value.\r
1564 \r
1565 Return Value:\r
1566 \r
1567     TRUE if successfull, FALSE on fail.\r
1568 \r
1569 --*/\r
1570 \r
1571 {\r
1572     UNICODE_STRING path;\r
1573     RTL_QUERY_REGISTRY_TABLE paramTable[2];  //zero'd second table terminates parms\r
1574     NTSTATUS status;\r
1575     BOOLEAN fres;\r
1576         WCHAR wbuf[ MAXIMUM_FILENAME_LENGTH ];\r
1577 \r
1578     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString(Enter) RegPath = %ws\n   ValueName =%ws\n", RegPath, ValueName));\r
1579     path.Length = 0;\r
1580     path.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof( WCHAR );  // MAXIMUM_FILENAME_LENGTH defined in wdm.h\r
1581     path.Buffer = wbuf;\r
1582 \r
1583 \r
1584     RtlZeroMemory(path.Buffer, path.MaximumLength);\r
1585     RtlMoveMemory(path.Buffer, RegPath, wcslen( RegPath) * sizeof( WCHAR ));\r
1586 \r
1587     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString() path= %ws\n", path.Buffer ));\r
1588 \r
1589     RtlZeroMemory(paramTable, sizeof(paramTable));\r
1590 \r
1591     paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
1592     paramTable[0].Name = ValueName;\r
1593     paramTable[0].EntryContext = Value;\r
1594     paramTable[0].DefaultType = REG_SZ;\r
1595     paramTable[0].DefaultData = DfltValue;\r
1596     paramTable[0].DefaultLength = DfltValue->MaximumLength;\r
1597 \r
1598 \r
1599     status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,\r
1600                                     path.Buffer, &paramTable[0], NULL, NULL);\r
1601 \r
1602     if (NT_SUCCESS(status)) {\r
1603         MdKdPrint( DBGLVL_MEDIUM,("MdGetRegistryString(Exit) SUCCESS, value = %ws \n", Value));\r
1604         fres = TRUE;\r
1605 \r
1606     } else {\r
1607 \r
1608         MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_INVALID_PARAMETER) ,("MdGetRegistryString(Exit) STATUS_INVALID_PARAMETER\n"));\r
1609  \r
1610                 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_OBJECT_NAME_NOT_FOUND) ,("MdGetRegistryString(Exit) STATUS_OBJECT_NAME_NOT_FOUND\n"));\r
1611 \r
1612         fres = FALSE;\r
1613 \r
1614     }\r
1615 \r
1616     return fres;\r
1617 }\r
1618 \r
1619 /*------------------------------------------------------------------------------------------------------*/\r
1620 \r
1621 NTSTATUS\r
1622 RegistryMultiSzCallBack(\r
1623     IN PWSTR ValueName,\r
1624     IN ULONG ValueType,\r
1625     IN PVOID ValueData,\r
1626     IN ULONG ValueLength,\r
1627     IN PVOID Context,\r
1628     IN PVOID EntryContext\r
1629     )\r
1630 /*++\r
1631 \r
1632 Routine Description:\r
1633 \r
1634     This callback for a registry SZ or MULTI_SZ is called once for each\r
1635     SZ in the value.  It will attempt to match the data with the\r
1636     UNICODE_STRING passed in as Context, and modify EntryContext if a\r
1637     match is found.  Written for ClasspCheckRegistryForMediaChangeCompletion\r
1638 \r
1639 Arguments:\r
1640 \r
1641     ValueName     - name of the key that was opened\r
1642     ValueType     - type of data stored in the value (REG_SZ for this routine)\r
1643     ValueData     - data in the registry, in this case a wide string\r
1644     ValueLength   - length of the data including the terminating null\r
1645     Context       - unicode string to compare against ValueData\r
1646     EntryContext  - should be initialized to 0, will be set to 1 if match found\r
1647 \r
1648 Return Value:\r
1649 \r
1650     STATUS_SUCCESS\r
1651     EntryContext will be 1 if found\r
1652 \r
1653 --*/\r
1654 {\r
1655     UNICODE_STRING uStr;\r
1656     ANSI_STRING aStr;\r
1657 \r
1658     PAGED_CODE();\r
1659     UNREFERENCED_PARAMETER(ValueName);\r
1660     UNREFERENCED_PARAMETER(ValueLength);\r
1661     UNREFERENCED_PARAMETER(EntryContext);\r
1662 \r
1663     // if the data is not a terminated string, exit\r
1664     if (ValueType != REG_SZ) return STATUS_SUCCESS;\r
1665 \r
1666     // convert wide string to ASCII\r
1667     RtlInitUnicodeString( &uStr, ValueData );\r
1668     RtlInitAnsiString( &aStr, NULL );\r
1669     RtlUnicodeStringToAnsiString( &aStr, &uStr, TRUE ); \\r
1670 \r
1671     // call user routine\r
1672     ((RegUserCallback_t)Context)(&aStr);\r
1673     \r
1674     // free resources\r
1675     RtlFreeAnsiString( &aStr );\r
1676     \r
1677     return STATUS_SUCCESS;\r
1678 }\r
1679 \r
1680 BOOLEAN\r
1681 MdGetRegistryMultiString(\r
1682     IN      PWCHAR                              RegPath,\r
1683     IN      PWCHAR                              ValueName,\r
1684     IN      PVOID                   DfltValue,\r
1685     IN      ULONG               DfltValueSize,\r
1686     IN      RegUserCallback_t           Func\r
1687     )\r
1688 \r
1689 /*++\r
1690 \r
1691 Routine Description:\r
1692 \r
1693         Obtain a string value from the registry\r
1694 \r
1695 \r
1696 Arguments:\r
1697 \r
1698     RegPath  -- supplies absolute registry path\r
1699     ValueName    - Supplies the Value Name.\r
1700     Value      - receives the REG_DWORD value.\r
1701 \r
1702 Return Value:\r
1703 \r
1704     TRUE if successfull, FALSE on fail.\r
1705 \r
1706 --*/\r
1707 \r
1708 {\r
1709     UNICODE_STRING path;\r
1710     RTL_QUERY_REGISTRY_TABLE paramTable[2];  //zero'd second table terminates parms\r
1711     NTSTATUS status;\r
1712     BOOLEAN fres;\r
1713         WCHAR wbuf[ MAXIMUM_FILENAME_LENGTH ];\r
1714     ULONG           ulDummy;\r
1715     \r
1716     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString(Enter) RegPath = %ws\n   ValueName =%ws\n", RegPath, ValueName));\r
1717     path.Length = 0;\r
1718     path.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof( WCHAR );  // MAXIMUM_FILENAME_LENGTH defined in wdm.h\r
1719     path.Buffer = wbuf;\r
1720 \r
1721 \r
1722     RtlZeroMemory(path.Buffer, path.MaximumLength);\r
1723     RtlMoveMemory(path.Buffer, RegPath, wcslen( RegPath) * sizeof( WCHAR ));\r
1724 \r
1725     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString() path= %ws\n", path.Buffer ));\r
1726 \r
1727     RtlZeroMemory(paramTable, sizeof(paramTable));\r
1728 \r
1729     paramTable[0].QueryRoutine  = RegistryMultiSzCallBack;\r
1730     paramTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;\r
1731     paramTable[0].Name = ValueName;\r
1732     paramTable[0].EntryContext = &ulDummy;\r
1733     paramTable[0].DefaultType = REG_MULTI_SZ;\r
1734     paramTable[0].DefaultData = DfltValue;\r
1735     paramTable[0].DefaultLength = DfltValueSize;\r
1736 \r
1737 \r
1738     status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,\r
1739                                     path.Buffer, &paramTable[0], Func, NULL);\r
1740 \r
1741     if (NT_SUCCESS(status)) {\r
1742         fres = TRUE;\r
1743 \r
1744     } else {\r
1745 \r
1746         MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_INVALID_PARAMETER) ,("MdGetRegistryString(Exit) STATUS_INVALID_PARAMETER\n"));\r
1747  \r
1748                 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_OBJECT_NAME_NOT_FOUND) ,("MdGetRegistryString(Exit) STATUS_OBJECT_NAME_NOT_FOUND\n"));\r
1749 \r
1750         fres = FALSE;\r
1751 \r
1752     }\r
1753 \r
1754     return fres;\r
1755 }\r
1756 \r
1757 \r