Fixed Id keyword in source files
[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                         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
455                         break;\r
456                         \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
461 \r
462                         /* Device open counter */\r
463                         l_pMdDevContext->m_nOpenCount = 0;\r
464         \r
465                         // mark device started\r
466                         l_pMdDevContext->m_DeviceStarted = TRUE;\r
467                         \r
468                         break;\r
469                 } /* specific Control device initialization */\r
470 \r
471         } /* device-specific init */\r
472 \r
473         /* Return the new created extension */\r
474         *pio_ppDevContext       = l_pMdDevContext;\r
475 \r
476     return l_Status;\r
477 \r
478 } /* MdCreateDevContext */\r
479 \r
480 /*------------------------------------------------------------------------------------------------------*/\r
481 \r
482 NTSTATUS\r
483 MdRemoveDevContext (\r
484     IN  PMD_DEV_CONTEXT_T               pi_pMdDevContext\r
485     )\r
486 /*++\r
487 \r
488 Routine Description:\r
489     This routine releases the device context resources and remove the device\r
490 \r
491 \r
492 Arguments:\r
493 \r
494     pi_pMdDevContext........ Pointer to the device context.\r
495 \r
496 Return Value:\r
497 \r
498     STATUS_SUCCESS if the device extension was created correctly, otherwise\r
499     an error indicating the reason for failure.\r
500 \r
501 --*/\r
502 { /* MdRemoveDevContext */\r
503 \r
504         \r
505         if (pi_pMdDevContext != NULL)\r
506         {\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
510                 \r
511                 /* Remove the device */\r
512                 MdDelDevice( pi_pMdDevContext );\r
513                 \r
514                 /* remove device context */\r
515                 /* NO NEED, BECAUSE IT WAS RELEASED ON IoDeleteDevice() ! \r
516                 MdExFreePool( pi_pMdDevContext );\r
517                 */\r
518         }\r
519 \r
520         return STATUS_SUCCESS;\r
521 \r
522 } /* MdRemoveDevContext */\r
523 \r
524 /*------------------------------------------------------------------------------------------------------*/\r
525 \r
526 NTSTATUS \r
527 MdDevInit(\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
533         )\r
534 /*++\r
535 \r
536 Routine Description:\r
537     This routine creates the device and connect to the driver context\r
538 \r
539 \r
540 Arguments:\r
541 \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
547 \r
548 Return Value:\r
549 \r
550     STATUS_SUCCESS on success, otherwise an error indicating the reason for failure.\r
551 \r
552 --*/\r
553 { /* MdDevInit */\r
554 \r
555         /* Local status variable */\r
556     NTSTATUS                                    l_Status;\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
561 \r
562     MdKdPrint( DBGLVL_MINIMUM ,("(MdDevInit) init device '%ws'\n", pi_pWin32DeviceName->Buffer ));\r
563 \r
564         /*\r
565          * Create the device and the device context\r
566          */\r
567         l_Status = MdCreateDevContext(\r
568                                                 pi_pDrvContext->m_pDrvObject,\r
569                                                 pi_eDevType,\r
570                                                 pi_pNtDeviceName,\r
571                                                 pi_pWin32DeviceName,\r
572                                                 &l_pMdDevContext\r
573                                                 );\r
574 \r
575         /* Check creation status */\r
576         if ( NT_SUCCESS(l_Status) )\r
577         { /* Loaded OK */\r
578                 PRE_LOCK_IT;\r
579 \r
580                 MdKdPrint( DBGLVL_DEFAULT ,("(MdDeviceInit) Device successfuly initialized\n"));\r
581 \r
582                 /* Store the device context */\r
583                 *pio_ppDevContext = l_pMdDevContext;\r
584 \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
589                 \r
590                 /* connect device to driver */\r
591                 l_pMdDevContext->m_pDrvContext = pi_pDrvContext;\r
592 \r
593                 /* Update number of device instances */\r
594                 InterlockedIncrement( &pi_pDrvContext->m_uDevNo );\r
595 \r
596                 // increment the number of cards\r
597                 {\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
602                 }\r
603         } /* Loaded OK */\r
604 \r
605         return l_Status ;\r
606 \r
607 } /* MdDevInit */\r
608 \r
609 /*------------------------------------------------------------------------------------------------------*/\r
610 \r
611 void\r
612 ReleasePendingRequests(\r
613     IN PMD_DEV_CONTEXT_T        pi_pMdDevContext\r
614     )\r
615 /*++\r
616 \r
617 Routine Description:\r
618 \r
619     Release pending requests of the Control Device \r
620 \r
621 Arguments:\r
622 \r
623     pi_pMdDevContext - pointer to the Control Device\r
624 \r
625 Return Value:\r
626 \r
627 --*/\r
628 { /* ReleasePendingRequests */\r
629         MdKdPrint( DBGLVL_MINIMUM ,("(ReleasePendingRequests) Enter \n" ));\r
630 } /* ReleasePendingRequests */\r
631 \r
632 \r
633 /*------------------------------------------------------------------------------------------------------*/\r
634 \r
635 NTSTATUS \r
636 MdDevDeInit(\r
637         IN PMD_DEV_CONTEXT_T                    pi_pMdDevContext        \r
638         )\r
639 /*++\r
640 \r
641 Routine Description:\r
642     This routine DeInitialize the device setting and context\r
643 \r
644 \r
645 Arguments:\r
646 \r
647         pi_pMdDevContext........The device context\r
648 Return Value:\r
649 \r
650     None.\r
651 \r
652 --*/\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
658         // prepare lock\r
659         PRE_LOCK_IT;\r
660 \r
661         MdKdPrint( DBGLVL_MINIMUM ,("(MdDevDeInit) Unloading device '%ws' \n", pi_pMdDevContext->m_usDosDeviceName.Buffer));\r
662 \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
668 \r
669     /* Get the first device object */\r
670     l_pFdo = pi_pMdDevContext->m_pFdo;\r
671 \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
677 \r
678         /* get driver context */\r
679         l_pMdDrvContext = pi_pMdDevContext->m_pDrvContext;\r
680 \r
681         /*\r
682          * Remove the device from the Driver device list\r
683          */\r
684 \r
685         // acquire access to the critical section\r
686         LOCK_IT( &pi_pMdDevContext->m_SpinLock );\r
687 \r
688         // disconnect the global context with device one\r
689         RemoveEntryList( &pi_pMdDevContext->m_Link );\r
690 \r
691         // release access to the critical section\r
692         UNLOCK_IT( &pi_pMdDevContext->m_SpinLock );\r
693 \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
699 \r
700         // decrement the number of cards\r
701         {\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
706         }\r
707         /* Free the Device context */\r
708         return MdRemoveDevContext( pi_pMdDevContext );\r
709 \r
710 } /* MdDevDeInit */\r
711 \r
712 NTSTATUS \r
713 MdGetDevLocation(\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
718         )\r
719 {\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
722         NTSTATUS        l_Status;\r
723         UNICODE_STRING  l_UnicodeNumber;\r
724 \r
725         /* prepare */\r
726         l_ResultLength = 0;\r
727         RtlZeroMemory( l_Buffer, sizeof(l_Buffer) );\r
728 \r
729         /* Get the device number  */\r
730         l_Status = IoGetDeviceProperty(pi_pPdo,\r
731                 DevicePropertyLocationInformation, sizeof(l_Buffer), &l_Buffer, &l_ResultLength);\r
732 \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
737                 goto exit;      \r
738         }\r
739 \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
742 \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
751 \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
760 \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
770 \r
771         /* return the results */\r
772         *pi_pBus                = l_BusNumber;\r
773         *pi_pSlot               = l_DevNumber;\r
774         *pi_pFunction   = l_Function;\r
775         \r
776         goto exit;\r
777 \r
778 err:\r
779         l_Status = STATUS_UNSUCCESSFUL;\r
780 exit:\r
781         return l_Status;\r
782 }\r
783 \r
784 /*------------------------------------------------------------------------------------------------------*/\r
785 \r
786 NTSTATUS \r
787 MdInitPciCfgCard(\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
791         )\r
792 /*++\r
793 \r
794 Routine Description:\r
795 \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
801 \r
802 Arguments:\r
803 \r
804         pi_pMdDevContext....... My device context\r
805         pi_pRawResources....... Card raw resources\r
806         pi_pTranslatedResources Card translated resources\r
807 \r
808 Return Value:\r
809 \r
810     None.\r
811 \r
812 --*/\r
813 { /* MdInitPciCfgCard */\r
814 \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
822         ULONG                                                           l_nResCnt;\r
823         /* current resource number */\r
824         ULONG                                                           l_nCurResNum;\r
825         /* temporary address */\r
826         PUCHAR                                                          l_pPortAddr = NULL;\r
827         /* status */\r
828         NTSTATUS                                                        l_Status;\r
829         // Device IX  (in PCI configuration)                            \r
830     MD_DEV_IX_E                                                 l_DevIx = pi_pMdDevContext->m_eDevType; \r
831     // Device BD\r
832     PMD_HAL_DEV_PARAMS_T                                l_pDev = &g_DevParams[l_DevIx];\r
833     // current BAR descriptor \r
834         PMD_BAR_T       l_pBar;                                         \r
835         // for Debug \r
836         char *          l_BarName;                                      \r
837         \r
838         MdKdPrint( DBGLVL_DEFAULT ,("(MdInitPciCfgCard) Enter \n" ));\r
839 \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
844         ZEROF(m_Function);\r
845         ZEROF(m_ulIntVector);\r
846         ZEROF(m_ulIntLevel);\r
847         ZEROF(m_Affinity);\r
848         ZEROF(m_fIntShared);\r
849         ZEROF(m_IntMode);\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
853 \r
854         if (l_DevIx == MD_DEV_IX_TAVOR_SD)\r
855         { /* get BARs via PCI configuration header */\r
856 \r
857                 l_Status = ReadBars( pi_pMdDevContext ); \r
858             if (!NT_SUCCESS(l_Status))\r
859                 return l_Status;\r
860 \r
861         } /* get BARs via PCI configuration header */\r
862         \r
863         else\r
864         { /* get resources from resource descriptors */\r
865         \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
870                 }\r
871         \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
877 \r
878                 /* store other parameters */\r
879                 for (l_nCurResNum = 0; l_nCurResNum < l_nResCnt; ++l_nCurResNum, ++l_pPartResDesc)\r
880             {\r
881                         switch (l_pPartResDesc->Type)\r
882                         {\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
887                                         break;\r
888 \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
898                                 break;\r
899         \r
900                                 case CmResourceTypeMemory:\r
901                                         {\r
902                                                 ULONG l_BarNum;\r
903                                                 LARGE_INTEGER   l_Offset = { 0,0 };\r
904                                         \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
908                                                 else    \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
911                                                 else {\r
912                                                         l_pBar = &pi_pMdDevContext->m_Ddr; l_BarName = "DDR"; l_BarNum = 2; }\r
913                                                                 \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
920                                                 \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
927                                                         \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
932                                                         l_Offset, \r
933                                                         l_pBar->m_ulKernelSize, MmNonCached);\r
934                                                 }\r
935                                                 if (!l_pBar->m_pKernelAddr)     return STATUS_NO_MEMORY;\r
936         \r
937                                                 /* debug print */\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
941                                         } \r
942                                         break;\r
943         \r
944                                 default:\r
945                                         MdKdPrint( DBGLVL_DEFAULT ,("(MdInitPciCfgCard) Unsupported resource type 0x%x \n", l_pPartResDesc->Type ));\r
946                                         break;\r
947                         }\r
948                 }\r
949 \r
950         } /* get resources from resource descriptors */\r
951         \r
952         //\r
953         // get the device location information\r
954         //\r
955         { \r
956                 ULONG   l_BusNumber, l_DevNumber, l_Function;\r
957                 \r
958                 l_Status = MdGetDevLocation(    pi_pMdDevContext->m_pPdo, &l_BusNumber, &l_DevNumber, &l_Function );\r
959 \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
964                         l_Function      = 0;\r
965                 }\r
966 \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
971 \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
974         }\r
975 \r
976 \r
977         return STATUS_SUCCESS;\r
978 \r
979 } /* MdInitPciCfgCard */\r
980 \r
981 /*------------------------------------------------------------------------------------------------------*/\r
982 \r
983 VOID \r
984 MdDeInitPciCfgCard(\r
985         IN      PMD_DEV_CONTEXT_T               pi_pMdDevContext\r
986         )\r
987 /*++\r
988 \r
989 Routine Description:\r
990 \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
994 \r
995 \r
996 Arguments:\r
997 \r
998         pi_pMdDevContext....... My device context\r
999 \r
1000 Return Value:\r
1001 \r
1002     None.\r
1003 \r
1004 --*/\r
1005 { /* MdDeInitPciCfgCard */\r
1006 \r
1007     // current BAR descriptor \r
1008         PMD_BAR_T       l_pBar;                                         \r
1009         // CR space address \r
1010         PUCHAR                          l_pAddr;\r
1011 \r
1012         // unmap CR-space\r
1013         l_pBar = &pi_pMdDevContext->m_Cr;\r
1014         l_pAddr = l_pBar->m_pKernelAddr;\r
1015         l_pBar->m_pKernelAddr = NULL;\r
1016         if (l_pAddr)\r
1017                 MmUnmapIoSpace(l_pAddr, l_pBar->m_ulKernelSize);\r
1018 \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
1023         if (l_pAddr)\r
1024                 MmUnmapIoSpace(l_pAddr, l_pBar->m_ulKernelSize);\r
1025 \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
1030         if (l_pAddr)\r
1031                 MmUnmapIoSpace(l_pAddr, l_pBar->m_ulKernelSize);\r
1032 \r
1033 } /* MdDeInitPciCfgCard */\r
1034 \r
1035 /*------------------------------------------------------------------------------------------------------*/\r
1036 \r
1037 \r
1038 /*------------------------------------------------------------------------------------------------------*/\r
1039 \r
1040 PCHAR\r
1041 WcharToAscii(\r
1042         OUT     PUCHAR                  pi_TargetString,\r
1043         IN      const USHORT *  pi_SourceString,\r
1044         IN      ULONG                   pi_Size\r
1045         )\r
1046 /*++\r
1047 \r
1048 Routine Description:\r
1049     Converts wide-character string into ASCII\r
1050 \r
1051 Arguments:\r
1052 \r
1053         pi_TargetString...... result string\r
1054         pi_SourceString...... source string\r
1055         pi_Size.............. size of the source string\r
1056 \r
1057 Return Value:\r
1058 \r
1059         The result stringbytes.\r
1060 \r
1061 --*/\r
1062 { /* WcharToAscii */\r
1063         int             i, size         = (pi_Size + 1) >> 1;\r
1064         PCHAR   l_pResult       = pi_TargetString;\r
1065 \r
1066         for (i=0; i<size; i++)\r
1067         {\r
1068                 if (*pi_SourceString == 0)\r
1069                         break;\r
1070                 *l_pResult++ = (char)*pi_SourceString++;\r
1071         }\r
1072         *l_pResult = '\0';\r
1073 \r
1074         return pi_TargetString;\r
1075 \r
1076 } /* WcharToAscii */\r
1077 \r
1078 PWCHAR \r
1079 WcharFindChar(\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
1084         )\r
1085 /*++\r
1086 \r
1087 Routine Description:\r
1088     Converts wide-character string into ASCII\r
1089 \r
1090 Arguments:\r
1091 \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
1096 \r
1097 Return Value:\r
1098 \r
1099         pointer to the first pattern found or NULL (when reached the end)\r
1100 \r
1101 --*/\r
1102 { /* WcharFindChar */\r
1103 \r
1104         PWCHAR  l_pResult       = pi_BufStart;\r
1105 \r
1106         while (l_pResult < pi_BufEnd )\r
1107         {\r
1108                 if (*l_pResult >= pi_FromPattern && *l_pResult <= pi_ToPattern)\r
1109                         return l_pResult;\r
1110                 l_pResult++;\r
1111         }\r
1112 \r
1113         return NULL;\r
1114 \r
1115 } /* WcharFindChar */\r
1116 \r
1117 /*------------------------------------------------------------------------------------------------------*/\r
1118 \r
1119 USHORT \r
1120 AsciiToUnicode(\r
1121         PUNICODE_STRING pi_puTargetString,\r
1122         PUCHAR                  pi_szFormat,\r
1123         ...\r
1124         )\r
1125 /*++\r
1126 \r
1127 Routine Description:\r
1128     Writes a formatted ( printf like ) string to into a uniocde string.\r
1129 \r
1130 Arguments:\r
1131 \r
1132         pi_nDbgLogLevel...... Level of debugging log.\r
1133         pi_szFormat.......... The format of the log.\r
1134 \r
1135 Return Value:\r
1136 \r
1137         The formatted string length in bytes.\r
1138 \r
1139 --*/\r
1140 { /* AsciiToUnicode */\r
1141 \r
1142         /* Auxilary scratch buffer */\r
1143         static UCHAR    s_vScratchBuff[1024];\r
1144 \r
1145         /* Variable argument list */    \r
1146         va_list l_Argptr;\r
1147         /* Length of the formated string in bytes */\r
1148         int             l_nStrLenBytes ;\r
1149         /* Char index */\r
1150         USHORT  l_nCharNo ;\r
1151         /* Maximum lemgth */\r
1152         USHORT  l_nMaxLength;\r
1153 \r
1154         /* Init the variable argument list */   \r
1155         va_start(l_Argptr, pi_szFormat);\r
1156 \r
1157         /* Build the formatted string */\r
1158         l_nStrLenBytes = vsprintf(&s_vScratchBuff[0] , pi_szFormat , l_Argptr);\r
1159 \r
1160         /* Check if we need to allocate buffer */\r
1161         if ( pi_puTargetString->Buffer == NULL )\r
1162         { /* Need to allocate buffer */\r
1163 \r
1164                 /* Allocate the UNICODE string buffer */\r
1165                 pi_puTargetString->Buffer = \r
1166                         (PWCHAR)MdExAllocatePool(NonPagedPool,(l_nStrLenBytes+1)*sizeof(WCHAR));\r
1167 \r
1168                 /* If allocation failed return */\r
1169                 if ( pi_puTargetString->Buffer == NULL ) return 0;\r
1170 \r
1171                 /* Set the UNICODE string new parameters */\r
1172                 pi_puTargetString->MaximumLength = (USHORT)((l_nStrLenBytes+1)*sizeof(WCHAR)) ;\r
1173 \r
1174         } /* Need to allocate buffer */\r
1175 \r
1176         /* Reset the string actual length */\r
1177         pi_puTargetString->Length = 0;\r
1178 \r
1179         /* Calc max length */\r
1180         l_nMaxLength = MT_MIN((pi_puTargetString->MaximumLength/sizeof(WCHAR) - 1),(USHORT)l_nStrLenBytes);\r
1181 \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
1185 \r
1186                 /* Convert... */\r
1187                 pi_puTargetString->Buffer[ l_nCharNo ] = (WCHAR)s_vScratchBuff[l_nCharNo] ;\r
1188 \r
1189                 /* Update actual length */\r
1190                 pi_puTargetString->Length += sizeof(WCHAR) ;\r
1191 \r
1192         } /* Convert a CHAR to WCHAR */\r
1193 \r
1194         /* NULL terminate */\r
1195         pi_puTargetString->Buffer[ l_nCharNo ] = (WCHAR)'\0';\r
1196 \r
1197         /* Term the variable argument list */   \r
1198         va_end(l_Argptr);\r
1199 \r
1200         return pi_puTargetString->Length ;\r
1201 \r
1202 } /* AsciiToUnicode */\r
1203 \r
1204 /*------------------------------------------------------------------------------------------------------*/\r
1205 \r
1206 BOOLEAN\r
1207 MdCanAcceptIoRequests(\r
1208     IN PDEVICE_OBJECT DeviceObject\r
1209     )\r
1210 /*++\r
1211 \r
1212 Routine Description:\r
1213 \r
1214   Check device extension status flags; \r
1215 \r
1216      Can't accept a new io request if device:\r
1217       1) is removed, \r
1218       2) has never been started, \r
1219       3) is stopped,\r
1220       4) has a remove request pending, or\r
1221       5) has a stop device pending\r
1222 \r
1223 \r
1224 Arguments:\r
1225 \r
1226     DeviceObject - pointer to the device object for this instance of the 82930\r
1227                     device.\r
1228 \r
1229 \r
1230 Return Value:\r
1231 \r
1232     return TRUE if can accept new io requests, else FALSE\r
1233 \r
1234 --*/\r
1235 {\r
1236     PMD_DEV_CONTEXT_T   l_pMdDevContext = (PMD_DEV_CONTEXT_T)DeviceObject->DeviceExtension;\r
1237         BOOLEAN                         l_fCan = FALSE;\r
1238 \r
1239 \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
1250                         l_fCan = TRUE;\r
1251         }\r
1252 \r
1253     MdKdPrintCond( DBGLVL_MAXIMUM, !l_fCan, ("**** FALSE return from MdCanAcceptIoRequests()!\n"));\r
1254 \r
1255         return l_fCan;\r
1256 }\r
1257 \r
1258 /*------------------------------------------------------------------------------------------------------*/\r
1259 \r
1260 BOOLEAN\r
1261 MdCreateDeviceNames(\r
1262         IN      PCHAR                           pi_pDevName,\r
1263         OUT     PUNICODE_STRING         po_pNtName,\r
1264         OUT     PUNICODE_STRING         po_pDosName\r
1265         )\r
1266 /*++\r
1267 \r
1268 Routine Description:\r
1269 \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
1273 \r
1274 Arguments:\r
1275 \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
1279 \r
1280 \r
1281 Return Value:\r
1282 \r
1283     return TRUE if succeeded to create strings, else FALSE\r
1284 \r
1285 --*/\r
1286 { /* MdCreateDeviceNames */\r
1287 \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
1292 \r
1293         /* build NT name */\r
1294         strcpy( l_DevName, "\\Device\\" );\r
1295         strcat( l_DevName, pi_pDevName );\r
1296 \r
1297         /* get the length */\r
1298         l_nUnicodeNameLen = (int)((strlen(l_DevName) + 1) * sizeof(WCHAR));\r
1299 \r
1300         /*\r
1301          * Init the NT device name\r
1302          */\r
1303         /* Allocate buffers for the NT device name */\r
1304         po_pNtName->Buffer = MdExAllocatePool(NonPagedPool, l_nUnicodeNameLen);\r
1305 \r
1306         /* Verify allocation */\r
1307         if ( po_pNtName->Buffer == NULL )\r
1308         { /* Allocation failed */\r
1309 \r
1310                 return FALSE;\r
1311 \r
1312         } /* Allocation failed */\r
1313 \r
1314         /* store lengths */\r
1315         po_pNtName->Length                      = (USHORT)(l_nUnicodeNameLen - sizeof(WCHAR));\r
1316         po_pNtName->MaximumLength       = (unsigned short)l_nUnicodeNameLen;\r
1317 \r
1318         /* Build Unicode NT device name */\r
1319         AsciiToUnicode( \r
1320                 po_pNtName,\r
1321                 l_DevName\r
1322                 );\r
1323 \r
1324         /* build DOS name */\r
1325         strcpy( l_DevName, "\\DosDevices\\" );\r
1326         strcat( l_DevName, pi_pDevName );\r
1327 \r
1328         /* get the length */\r
1329         l_nUnicodeNameLen = (int)((strlen(l_DevName) + 1) * sizeof(WCHAR));\r
1330 \r
1331         /* Allocate buffers for the DOS device name */\r
1332         po_pDosName->Buffer = MdExAllocatePool(NonPagedPool, l_nUnicodeNameLen);\r
1333 \r
1334         /* Verify allocation */\r
1335         if ( po_pDosName->Buffer == NULL )\r
1336         { /* Allocation failed */\r
1337 \r
1338                 /* Free the NT device name path buffer */\r
1339                 MdExFreePool(po_pNtName->Buffer);\r
1340 \r
1341                 return FALSE;\r
1342 \r
1343         } /* Allocation failed */\r
1344 \r
1345         /* store lengths */\r
1346         po_pDosName->Length                     = (USHORT)(l_nUnicodeNameLen - sizeof(WCHAR));\r
1347         po_pDosName->MaximumLength      = (unsigned short)l_nUnicodeNameLen;\r
1348 \r
1349         /* Build the NT device name */\r
1350         AsciiToUnicode( \r
1351                 po_pDosName,\r
1352                 l_DevName\r
1353                 );\r
1354 \r
1355         return TRUE;\r
1356 \r
1357 } /* MdCreateDeviceNames */\r
1358 \r
1359 /*------------------------------------------------------------------------------------------------------*/\r
1360 \r
1361 /**********************************\r
1362  * Device name DB handling        *\r
1363  **********************************/\r
1364 int AddDevNameToDb(char *pi_DevName)\r
1365  {\r
1366         ULONG l_Size    = (ULONG)strlen(pi_DevName) + 1;\r
1367         ULONG l_DbSize  = g_pDrvContext->m_DevNamesDbSize;\r
1368 \r
1369         if ( l_DbSize + l_Size <= sizeof(g_pDrvContext->m_DevNamesDb))\r
1370         {\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
1374                 return 0;\r
1375         }\r
1376         else\r
1377         {       \r
1378                 return 1;\r
1379         }\r
1380  }\r
1381 \r
1382 /*------------------------------------------------------------------------------------------------------*/\r
1383 /*------------------------------------------------------------------------------------------------------*/\r
1384 /*------------------------------------------------------------------------------------------------------*/\r
1385 /*------------------------------------------------------------------------------------------------------*/\r
1386 \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
1392 )\r
1393 {\r
1394         /* status */\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
1400         /* dev info */\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
1404     \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
1409         else\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
1414         }\r
1415 \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
1421         else\r
1422                 sprintf( l_DevName, l_pDevInfo->m_Format, l_pDevInfo->m_DevId, g_pDrvContext->m_uCardNo );\r
1423 \r
1424         if (!MdCreateDeviceNames(l_DevName, pi_pusNtDeviceName, pi_pusDosDeviceName))\r
1425                 return STATUS_INSUFFICIENT_RESOURCES ;\r
1426         \r
1427         /* build NT name */\r
1428     MdKdPrint( DBGLVL_LOW,("(CreateOneDevice) Generated device name %s \n", l_DevName));\r
1429 \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
1432 \r
1433     if (!NT_SUCCESS(l_Status))  \r
1434         { /* device creation failed */\r
1435 \r
1436                 /* Free the NT device name path buffer */\r
1437                 if (pi_pusNtDeviceName->Buffer)\r
1438                         MdExFreePool(pi_pusNtDeviceName->Buffer);\r
1439 \r
1440                 /* Free the Dos device name path buffer */\r
1441                 if (pi_pusDosDeviceName->Buffer)\r
1442                         MdExFreePool(pi_pusDosDeviceName->Buffer);\r
1443 \r
1444                 return l_Status;\r
1445         } /* device creation failed */\r
1446 \r
1447         /* save ASCII name */\r
1448         strcpy ( l_pMdDevContext->m_AsciiDevName, l_DevName );\r
1449 \r
1450         /* get FDO handle */\r
1451         l_pFdo = l_pMdDevContext->m_pFdo;\r
1452 \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
1456 \r
1457         *pi_ppMdDevContext = l_pMdDevContext;\r
1458     return STATUS_SUCCESS;\r
1459 }\r
1460 \r
1461 /*------------------------------------------------------------------------------------------------------*/\r
1462 \r
1463 BOOLEAN\r
1464 MdGetRegistryDword(\r
1465     IN      PWCHAR    RegPath,\r
1466     IN      PWCHAR    ValueName,\r
1467     IN OUT  PULONG    Value\r
1468     )\r
1469 \r
1470 /*++\r
1471 \r
1472 Routine Description:\r
1473 \r
1474         Obtain a Dword value from the registry\r
1475 \r
1476 \r
1477 Arguments:\r
1478 \r
1479     RegPath  -- supplies absolute registry path\r
1480     ValueName    - Supplies the Value Name.\r
1481     Value      - receives the REG_DWORD value.\r
1482 \r
1483 Return Value:\r
1484 \r
1485     TRUE if successfull, FALSE on fail.\r
1486 \r
1487 --*/\r
1488 \r
1489 {\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
1493     NTSTATUS status;\r
1494     BOOLEAN fres;\r
1495         WCHAR wbuf[ MAXIMUM_FILENAME_LENGTH ];\r
1496 \r
1497     MdKdPrint( DBGLVL_HIGH,("Enter MdGetRegistryDword() RegPath = %ws\n   ValueName =%ws\n", RegPath, ValueName));\r
1498     path.Length = 0;\r
1499     path.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof( WCHAR );  // MAXIMUM_FILENAME_LENGTH defined in wdm.h\r
1500     path.Buffer = wbuf;\r
1501 \r
1502 \r
1503     RtlZeroMemory(path.Buffer, path.MaximumLength);\r
1504     RtlMoveMemory(path.Buffer, RegPath, wcslen( RegPath) * sizeof( WCHAR ));\r
1505 \r
1506     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryDword() path= %ws\n", path.Buffer ));\r
1507 \r
1508     RtlZeroMemory(paramTable, sizeof(paramTable));\r
1509 \r
1510     paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
1511 \r
1512     paramTable[0].Name = ValueName;\r
1513 \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
1518 \r
1519 \r
1520     status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,\r
1521                                     path.Buffer, paramTable, NULL, NULL);\r
1522 \r
1523     if (NT_SUCCESS(status)) {\r
1524         MdKdPrint( DBGLVL_MEDIUM,("Exit MdGetRegistryDWord() SUCCESS, value = decimal %d 0x%x\n", *Value, *Value));\r
1525         fres = TRUE;\r
1526 \r
1527     } else {\r
1528 \r
1529         MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_INVALID_PARAMETER) ,("MdGetRegistryDWord() STATUS_INVALID_PARAMETER\n"));\r
1530  \r
1531                 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_OBJECT_NAME_NOT_FOUND) ,("MdGetRegistryDWord() STATUS_OBJECT_NAME_NOT_FOUND\n"));\r
1532 \r
1533         fres = FALSE;\r
1534 \r
1535     }\r
1536 \r
1537     return fres;\r
1538 }\r
1539 \r
1540 /*------------------------------------------------------------------------------------------------------*/\r
1541 \r
1542 BOOLEAN\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
1548     )\r
1549 \r
1550 /*++\r
1551 \r
1552 Routine Description:\r
1553 \r
1554         Obtain a string value from the registry\r
1555 \r
1556 \r
1557 Arguments:\r
1558 \r
1559     RegPath  -- supplies absolute registry path\r
1560     ValueName    - Supplies the Value Name.\r
1561     Value      - receives the REG_DWORD value.\r
1562 \r
1563 Return Value:\r
1564 \r
1565     TRUE if successfull, FALSE on fail.\r
1566 \r
1567 --*/\r
1568 \r
1569 {\r
1570     UNICODE_STRING path;\r
1571     RTL_QUERY_REGISTRY_TABLE paramTable[2];  //zero'd second table terminates parms\r
1572     NTSTATUS status;\r
1573     BOOLEAN fres;\r
1574         WCHAR wbuf[ MAXIMUM_FILENAME_LENGTH ];\r
1575 \r
1576     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString(Enter) RegPath = %ws\n   ValueName =%ws\n", RegPath, ValueName));\r
1577     path.Length = 0;\r
1578     path.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof( WCHAR );  // MAXIMUM_FILENAME_LENGTH defined in wdm.h\r
1579     path.Buffer = wbuf;\r
1580 \r
1581 \r
1582     RtlZeroMemory(path.Buffer, path.MaximumLength);\r
1583     RtlMoveMemory(path.Buffer, RegPath, wcslen( RegPath) * sizeof( WCHAR ));\r
1584 \r
1585     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString() path= %ws\n", path.Buffer ));\r
1586 \r
1587     RtlZeroMemory(paramTable, sizeof(paramTable));\r
1588 \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
1595 \r
1596 \r
1597     status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,\r
1598                                     path.Buffer, &paramTable[0], NULL, NULL);\r
1599 \r
1600     if (NT_SUCCESS(status)) {\r
1601         MdKdPrint( DBGLVL_MEDIUM,("MdGetRegistryString(Exit) SUCCESS, value = %ws \n", Value));\r
1602         fres = TRUE;\r
1603 \r
1604     } else {\r
1605 \r
1606         MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_INVALID_PARAMETER) ,("MdGetRegistryString(Exit) STATUS_INVALID_PARAMETER\n"));\r
1607  \r
1608                 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_OBJECT_NAME_NOT_FOUND) ,("MdGetRegistryString(Exit) STATUS_OBJECT_NAME_NOT_FOUND\n"));\r
1609 \r
1610         fres = FALSE;\r
1611 \r
1612     }\r
1613 \r
1614     return fres;\r
1615 }\r
1616 \r
1617 /*------------------------------------------------------------------------------------------------------*/\r
1618 \r
1619 NTSTATUS\r
1620 RegistryMultiSzCallBack(\r
1621     IN PWSTR ValueName,\r
1622     IN ULONG ValueType,\r
1623     IN PVOID ValueData,\r
1624     IN ULONG ValueLength,\r
1625     IN PVOID Context,\r
1626     IN PVOID EntryContext\r
1627     )\r
1628 /*++\r
1629 \r
1630 Routine Description:\r
1631 \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
1636 \r
1637 Arguments:\r
1638 \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
1645 \r
1646 Return Value:\r
1647 \r
1648     STATUS_SUCCESS\r
1649     EntryContext will be 1 if found\r
1650 \r
1651 --*/\r
1652 {\r
1653     UNICODE_STRING uStr;\r
1654     ANSI_STRING aStr;\r
1655 \r
1656     PAGED_CODE();\r
1657     UNREFERENCED_PARAMETER(ValueName);\r
1658     UNREFERENCED_PARAMETER(ValueLength);\r
1659     UNREFERENCED_PARAMETER(EntryContext);\r
1660 \r
1661     // if the data is not a terminated string, exit\r
1662     if (ValueType != REG_SZ) return STATUS_SUCCESS;\r
1663 \r
1664     // convert wide string to ASCII\r
1665     RtlInitUnicodeString( &uStr, ValueData );\r
1666     RtlInitAnsiString( &aStr, NULL );\r
1667     RtlUnicodeStringToAnsiString( &aStr, &uStr, TRUE ); \\r
1668 \r
1669     // call user routine\r
1670     ((RegUserCallback_t)Context)(&aStr);\r
1671     \r
1672     // free resources\r
1673     RtlFreeAnsiString( &aStr );\r
1674     \r
1675     return STATUS_SUCCESS;\r
1676 }\r
1677 \r
1678 BOOLEAN\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
1685     )\r
1686 \r
1687 /*++\r
1688 \r
1689 Routine Description:\r
1690 \r
1691         Obtain a string value from the registry\r
1692 \r
1693 \r
1694 Arguments:\r
1695 \r
1696     RegPath  -- supplies absolute registry path\r
1697     ValueName    - Supplies the Value Name.\r
1698     Value      - receives the REG_DWORD value.\r
1699 \r
1700 Return Value:\r
1701 \r
1702     TRUE if successfull, FALSE on fail.\r
1703 \r
1704 --*/\r
1705 \r
1706 {\r
1707     UNICODE_STRING path;\r
1708     RTL_QUERY_REGISTRY_TABLE paramTable[2];  //zero'd second table terminates parms\r
1709     NTSTATUS status;\r
1710     BOOLEAN fres;\r
1711         WCHAR wbuf[ MAXIMUM_FILENAME_LENGTH ];\r
1712     ULONG           ulDummy;\r
1713     \r
1714     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString(Enter) RegPath = %ws\n   ValueName =%ws\n", RegPath, ValueName));\r
1715     path.Length = 0;\r
1716     path.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof( WCHAR );  // MAXIMUM_FILENAME_LENGTH defined in wdm.h\r
1717     path.Buffer = wbuf;\r
1718 \r
1719 \r
1720     RtlZeroMemory(path.Buffer, path.MaximumLength);\r
1721     RtlMoveMemory(path.Buffer, RegPath, wcslen( RegPath) * sizeof( WCHAR ));\r
1722 \r
1723     MdKdPrint( DBGLVL_HIGH,("MdGetRegistryString() path= %ws\n", path.Buffer ));\r
1724 \r
1725     RtlZeroMemory(paramTable, sizeof(paramTable));\r
1726 \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
1734 \r
1735 \r
1736     status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,\r
1737                                     path.Buffer, &paramTable[0], Func, NULL);\r
1738 \r
1739     if (NT_SUCCESS(status)) {\r
1740         fres = TRUE;\r
1741 \r
1742     } else {\r
1743 \r
1744         MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_INVALID_PARAMETER) ,("MdGetRegistryString(Exit) STATUS_INVALID_PARAMETER\n"));\r
1745  \r
1746                 MdKdPrintCond( DBGLVL_MEDIUM, (status == STATUS_OBJECT_NAME_NOT_FOUND) ,("MdGetRegistryString(Exit) STATUS_OBJECT_NAME_NOT_FOUND\n"));\r
1747 \r
1748         fres = FALSE;\r
1749 \r
1750     }\r
1751 \r
1752     return fres;\r
1753 }\r
1754 \r
1755 \r