[CMAKE]
[reactos.git] / media / doc / notes
1 *** This file contains messages I've culled off the net as well
2 as previous discussions all of which have useful info on fixes
3 that need to be added to ReactOS. messages are between five
4 dashes on a line by themselves. If you implement the fix
5 reffered to in a message, feel free to delete it from the file.
6 Rex ***
7 -----
8 Subject: [ros-kernel] Inside the Boot Process
9 Date: Mon, 22 Mar 1999 22:05:47 +0100
10 From: Emanuele Aliberti <ea@iol.it>
11
12 For those working on the boot loader: in WinNt Magazine november 1998
13 issue (http://www.winntmag.com/) there is a detailed description, by
14 Mark Russinovich, of the rĂ´le the MBR, NTLDR, boot.ini, ntdetect.com...
15 play in the boot process ("Inside the Boot Process, Part 1").
16 -----
17 Yes with DPCs, KeDrainDpcQueue should go to HIGH_LEVEL because
18 it needs to synchronize with KeInsertDpcQueue. Also the idle thread
19 should run at DISPATCH_LEVEL and regularly drain the dpc queue, that
20 way if an irq happens and the dpc can't be executed immediately it
21 will be executed as soon as the processor is idle rather than
22 waiting for the next timer tick
23 -----
24 About the console driver, I think it might be quite useful to have a simple
25 way for apps to print to the screen for debugging. But when the kernel is more
26 stable, console handling should be moved to user level because console printing
27 needs to know about windows and so on which can only be done at user level.
28 -----
29 Subject: Re: IMSAMP-how to avoid rebooting?
30 Date: 9 Nov 1998 00:40:32 -0000
31 From: Charles Bryant <n51190709.ch@chch.demon.co.uk>
32 Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
33 References: 1, 2 , 3 , 4
34
35 In article <un264wzle.fsf@xxx.yyy.zzz>, David C. <qqqq@xxx.yyy.zzz> wrote:
36 >The reason it won't unload when something is bound to it is the same
37 >reason you can't unload any other driver that has an open client. If
38 >you install any driver, and have a user program (or another driver) open
39 >a handle to it, and then give the "net stop" command to unload it,
40 >you'll find that the unload will be delayed until the user program
41 >closes its handle.
42
43 When developing a driver I found this to be a considerable nuisance.
44 Frequently a bug would leave an IRP stuck in the driver and I
45 couldn't unload and reload a fixed version. While reading NTDDK.H I
46 found a suspicious constant and discovered that the Flags field in
47 the device (the one which you OR in DO_BUFFERED_IO or DO_DIRECT_IO)
48 has a bit called DO_UNLOAD_PENDING. By experiment I confirmed that
49 this bit is set when you do 'net stop', so a driver can check it
50 periodically (e.g. from a timer DPC every ten seconds) and cancel all
51 queued IRPs if it is found to be set.
52
53 Since this is not documented anywhere that I can find, it might be
54 unwise to rely on it for production code, but it is very useful for
55 debugging. Maybe someone with internals knowledge can comment on the
56 reliability of it.
57 -----
58 Subject: Re: Kernel bugs
59 Date: Fri, 23 Oct 1998 12:08:36 -0700
60 From: rex <rex@lvcablemodem.com>
61 To: Jason Filby <jasonfilby@yahoo.com>
62 References: 1
63
64 Jason Filby wrote:
65
66 > Hi,
67 >
68 > Ok -- here's most of what I get when I press a key:
69 >
70 > Page fault detected at address 1fd4 with eip c042f794
71 > Recursive page fault detected
72 > Exception 14(2)
73 > CS:EIP 20:c042f794
74 >
75 > Rex -- do you know of anyway to find out which function in what file
76 > is causing the exception? I know that for problems in the kernel, you
77 > just look in the ntoskrnl\kernel.sym file and find the EIP value which
78 > matches the one given in the exception debug text. But what about
79 > modules? How can we track exceptions that occur in functions in modules?
80 >
81
82 I know this is a little belated, but I thought I'd take astab at answering
83 this anyway. add an option to the
84 makefile for the module to generate a listing file with
85 symbol information. Then, on a boot test, note the
86 address that the module is loaded at, and subtract
87 this from the EIP value. add any offset used in the
88 module link specification (I dont think there currently
89 is one), and look for the last symbol with a lower
90 address offset.
91
92 Brian, I have an idea on how to make this exception
93 dump information a little more useful. We should
94 have the load information for the load modules
95 in memory somewhere. Perhaps the exception
96 dump could check offending addresses to see if
97 they lie in the kernel or in a module, and if they
98 lie in a module the proper offset could be subtracted
99 and this number could be displayed seperately. If
100 I get a chance today, I'll make this change and send
101 it to ya.
102
103 Rex.
104 -----
105 Subject: Re: Question on "Sending buffers on the stack to asynchronous DeviceIoControl with buffered I/O"
106 Date: Mon, 16 Nov 1998 11:24:57 -0800
107 From: "-Paul" <paulsan@microsoftSPAM.com>
108 Organization: Microsoft Corp.
109 Newsgroups: microsoft.public.win32.programmer.kernel, comp.os.ms-windows.programmer.nt.kernel-mode
110 References: 1
111
112 Radu, I post the following information occassionally for questions such as
113 yours. I hope it helps.
114
115 -Paul
116
117 Here is an explanation of buffers and DeviceIoControl.
118
119 First, here are the parameters,
120
121 BOOL DeviceIoControl(
122 HANDLE hDevice, // handle to device of interest
123 DWORD dwIoControlCode, // control code of operation to perform
124 LPVOID lpInBuffer, // pointer to buffer to supply input data
125 DWORD nInBufferSize, // size of input buffer
126 LPVOID lpOutBuffer, // pointer to buffer to receive output data
127 DWORD nOutBufferSize, // size of output buffer
128 LPDWORD lpBytesReturned, // pointer to variable to receive output byte
129 count
130 LPOVERLAPPED lpOverlapped // pointer to overlapped structure for
131 asynchronous operation
132 );
133
134 METHOD_BUFFERED
135
136 user-mode perspective
137
138 lpInBuffer - optional, contains data that is written to the driver
139 lpOutBuffer - optional, contains data that is read from the driver after
140 the call has completed
141
142 lpInBuffer and lpOutBuffer can be two buffers or a single shared buffer.
143 If a shared buffer, lpInBuffer is overwritten by lpOutBuffer.
144
145
146 I/O Manager perspective
147
148 examines nInBufferSize and nOutBufferSize. Allocates memory from non-paged
149 pool and puts the address of this pool in Irp->AssociatedIrp.SystemBuffer.
150 The size of this buffer is equal to the size of the larger of the two
151 bufferes. This buffer is accessible at any IRQL.
152
153 copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
154 copies nOutBufferSize to
155 irpSp->Parameters.DeviceIoControl.OutputBufferLength
156 copies contents of lpInBuffer to SystemBuffer allocated above
157 calls your driver
158
159
160
161 Device Driver perspective
162
163 you have one buffer, Irp->AssociatedIrp.SystemBuffer. You read input data
164 from this buffer and you write output data to the same buffer, overwriting
165 the input data.
166
167 Before calling IoCompleteRequest, you must
168 - set IoStatus.Status to an approriate NtStatus
169 - if IoStatus.Status == STATUS_SUCCESS
170 set IoStatus.Information to the
171 number of bytes you want copied
172 from the SystemBuffer back into
173 lpOutBuffer.
174
175
176 I/O Manager Completion Routine perspective
177
178 looks at IoStatus block, if IoStatus.Status = STATUS_SUCCESS, copies the
179 number of bytes specified by IoStatus.Information from
180 Irp->AssociatedIrp.SystemBuffer into lpOutBuffer
181 completes the request
182
183
184
185
186
187
188 METHOD_IN_DIRECT
189
190 user-mode perspective
191
192 lpInBuffer - optional, contains data that is written to the driver. This
193 buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
194 confusion, mentally rename this buffer to lpControlBuffer. This is
195 typically a small, optional buffer that might contain a control structure
196 with useful information for the device driver. This buffer is smal and is
197 double buffered.
198
199 lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is read by
200 the driver. To avoid confusion, mentally rename this buffer to
201 lpDataTransferBuffer. This is physically the same buffer that the device
202 driver will read from. There is no double buffering. Technically, this
203 buffer is still optional, but since you are using this buffering method,
204 what would be the point???
205
206 I/O Manager perspective
207
208 If lpInBuffer exists, allocates memory from non-paged pool and puts the
209 address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
210 accessible at any IRQL.
211
212 copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
213 copies nOutBufferSize to
214 irpSp->Parameters.DeviceIoControl.OutputBufferLength
215 copies contents of lpInBuffer to SystemBuffer allocated above
216 So far this is completely identical to METHOD_BUFFERED. Most likely
217 lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
218
219 For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
220 allocated. lpOutBuffer is probed and locked into memory. Then, the user
221 buffer virtual addresses are checked to be sure they are readable in the
222 caller's access mode.
223
224 The MDL is address is stored in Irp->MdlAddress.
225 Your driver is called.
226
227
228 Device Driver perspective
229
230 The device driver can read the copy of lpOutBuffer via
231 Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
232 this buffer is lost. The I/O Manager does not copy any data back to the
233 user-mode buffers as it did in the completion routine for METHOD_BUFFERED.
234 Art Baker's book is wrong in this respect (page 168, "data going from the
235 driver back to the caller is passed through an intermediate system-space
236 buffer" and page 177, "When the IOCTL IRP is completed, the contents of the
237 system buffer will be copied back into the callers original output buffer".
238
239 The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
240 The driver uses whatever Mdl API's to read the buffer. Usually, this
241 buffer is to be written to some mass storage media or some similar
242 operation. Since this is a large data transfer, assume a completion
243 routine is required.
244
245 mark the Irp pending
246 queue it
247 return status pending
248
249
250
251
252 Device Driver Completion Routine perspective
253
254 standard completion routine operations
255 set IoStatus.Status to an approriate NtStatus
256 IoStatus.Information is not needed
257 completete the request
258
259
260
261
262 I/O Manager Completion Routine perspective
263
264 standard I/O Manager completion routine operations
265 unmap the pages
266 deallocate the Mdl
267 complete the request
268
269
270
271
272
273 METHOD_OUT_DIRECT
274
275 user-mode perspective
276
277 lpInBuffer - optional, contains data that is written to the driver. This
278 buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
279 confusion, mentally rename this buffer to lpControlBuffer. This is
280 typically a small, optional buffer that might contain a control structure
281 with useful information for the device driver. This buffer is smal and is
282 double buffered.
283
284 lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is written
285 by the driver and read by the wer-mode application when the request is
286 completed. To avoid confusion, mentally rename this buffer to
287 lpDataTransferBuffer. This is physically the same buffer that the device
288 driver will write to. There is no double buffering. Technically, this
289 buffer is still optional, but since you are using this buffering method,
290 what would be the point???
291
292 I/O Manager perspective
293
294 If lpInBuffer exists, allocates memory from non-paged pool and puts the
295 address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
296 accessible at any IRQL.
297
298 copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
299 copies nOutBufferSize to
300 irpSp->Parameters.DeviceIoControl.OutputBufferLength
301 copies contents of lpInBuffer to SystemBuffer allocated above
302 So far this is completely identical to METHOD_BUFFERED. Most likely
303 lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
304
305 For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
306 allocated. lpOutBuffer is probed and locked into memory. Then the user
307 buffer's addresses are checked to make sure the caller could write to them
308 in the caller's access mode.
309
310 The MDL is address is stored in Irp->MdlAddress.
311 Your driver is called.
312
313
314 Device Driver perspective
315
316 The device driver can read the copy of lpOutBuffer via
317 Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
318 this buffer is lost.
319
320 The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
321 The driver uses whatever Mdl API's to write data to the buffer. Usually,
322 this buffer is to be read from some mass storage media or some similar
323 operation. Since this is a large data transfer, assume a completion
324 routine is required.
325
326 mark the Irp pending
327 queue it
328 return status pending
329
330
331
332
333 Device Driver Completion Routine perspective
334
335 standard completion routine operations
336 set IoStatus.Status to an approriate NtStatus
337 IoStatus.Information is not needed
338 completete the request
339
340
341
342
343 I/O Manager Completion Routine perspective
344
345 standard I/O Manager completion routine operations
346 unmap the pages
347 deallocate the Mdl
348 complete the request
349
350
351
352
353 METHOD_NEITHER
354
355 I/O Manager perspective
356
357 Irp->UserBuffer = lpOutputBuffer;
358 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = lpInputBuffer;
359
360 No comments here. Don't use METHOD_DIRECT unless you know what you are
361 doing. Simple rule.
362
363 If your IOCtl involves no data transfer buffers, then METHOD_NEITHER is the
364 fastest path through the I/O Manager that involves an Irp.
365
366
367
368
369 Final Comment
370
371 Don't touch Irp->UserBuffer. This is a bookmark for the I/O Manager. Two
372 major problems can occur. 1 - page fault at high IRQL, or 2 - you write
373 something to Irp->UserBuffer and the I/O Manager overwrites you in its
374 completion routine. File systems access Irp->UserBuffer, but FSD writers
375 know all of the above and know when it is safe to touch Irp->UserBuffer.
376
377
378
379 Radu Woinaroski wrote in message <364F8F6E.2434B010@scitec.com.au>...
380 >Hello,
381 >
382 >I have a kernel-mode device driver that accepts a number of IoControl
383 >commands that use buffered data transfer (METHOD_BUFFERED).
384 >
385 >A user mode API provides a higher level access then the DeviceIoControl
386 >function.
387 >
388 >The function is implemented like that
389 >
390 >BOOL
391 Something(
392 > HANDLE hDevice ,
393 > int param1,
394 > int param2,
395 > DWORD * pReturn,
396 > LPOVERLAPPED pOverlapped)
397 >{
398 > // here a data buffer on the stack sent to asynchronous DeviceIoControl
399 >call
400 > int aDataIn[2];
401 > aDataIn[0] = param1;
402 > aDataIn[1] = param2;
403 >
404 > return DeviceIoControl(
405 > hDevice,
406 > DO_SOMETHING_IO,
407 > aDataIn,
408 > sizeof(int)*2,
409 > pReturn,
410 > sizeof(DWORD),
411 > pOverlapped);
412 >}
413 >
414 >The aDataIn buffer will not exist after DeviceIoControl returns (and
415 >when the I/O operation terminates). I know that for buffered IO the
416 >input data buffer is copyed by de IOManager to a nonpaged-pool area
417 >before passing the request to driver dispatch routine (DeviceControl).
418 >At the point of calling the dispatch routine (DeviceControl) the driver
419 >runs in the context of the calling thread so DeviceIoControl hasn't
420 >returned yet (?? or so I think) so aDataI
421 n will still be valid at the
422 >time IOManager copyes it to its buffer. So, this apears to work ok (at
423 >least in my opinion).
424 >
425 >Does I/O Manager use the Input buffer from the call to the Win32
426 >DeviceIoControl any where else after the first copy ?
427 >
428 >Is there any reason why this approach (passing a buffer on the stack to
429 >a asynchronous DeviceIoControl that uses buffered I/O) wouldn't work ?
430 >
431 >Allocating buffers from heap and deleting them on IO completion while
432 >managing asynchronous IO seems too much work ;-) .
433 >
434 >Thanks in advance for your opinions
435 >Radu W.
436 >
437 >--
438 >Radu Woinaroski
439 >Scitec
440 >Sydney, Australia
441 >Radu.Woinaroski@scitec.com.au
442 -----
443 Subject: Re: PCI ISR problem
444 Date: Fri, 20 Nov 1998 18:04:48 GMT
445 From: jeh@cmkrnl.com (Jamie Hanrahan)
446 Organization: Kernel Mode Systems, San Diego, CA
447 Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
448 References: 1
449
450 On Thu, 19 Nov 1998 15:46:13 -0600, Eric Gardiner
451 <eric.gardiner@natinst.com> wrote:
452
453 >I'm having problems with NT4 not hooking the interrupt line indicated by
454 >a PCI device. Here's what I'm doing:
455 >
456 >1) Enumerating the PCI buses on the system (using HalGetBusData) until
457 >I find my device.
458 >2) Once my device is found, I read the "Interrupt Line Register" in the
459 >device's PCI config space to determine what interrupt level to pass to
460 >HalGetInterruptVector.
461
462 Whups! No. Call HalAssignSlotResources and look at the returned
463 CM_RESOURCE_LIST to find the vector, level, port addresses, etc., for
464 your device. (Then pass the returned CM_RESOURCE_LIST to ExFreePool.)
465
466
467 See Knowledge Base article Q152044.
468
469 --- Jamie Hanrahan, Kernel Mode Systems, San Diego CA (jeh@cmkrnl.com)
470 Drivers, internals, networks, applications, and training for VMS and Windows NT
471 NT kernel driver FAQ, links, and other information: http://www.cmkrnl.com/
472
473 Please post replies, followups, questions, etc., in news, not via e-mail.
474 -----
475 Subject: Re: IRP canceling
476 Date: Mon, 23 Nov 1998 09:05:47 -0500
477 From: Walter Oney <waltoney@oneysoft.com>
478 Organization: Walter Oney Software
479 Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
480 References: 1
481
482 Seol,Keun Seok wrote:
483 > But, if the IRP was the CurrentIrp of the Device Object,
484 > the Driver's Start I/O routine will try to process the IRP.
485 > In the DDK help, the Start I/O routine MUST check the current IRP's
486 > Cancel bit.
487 > If set, Start I/O routine must just return.
488 >
489 > But I think that the IRP already completed should not be accessed.
490
491 You're absolutely right. I recommend the following code in a standard
492 StartIo routine to avoid the problem you point out:
493
494 VOID StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
495 {
496 KIRQL oldirql;
497 IoAcquireCancelSpinLock(&oldirql);
498 if (Irp != DeviceObject->CurrentIrp || Irp->Cancel)
499 {
500 IoReleaseCancelSpinLock(oldirql);
501 return;
502 }
503 else
504 {
505 IoSetCancelRoutine(Irp, NULL);
506 IoReleaseCancelSpinLock(oldirql);
507 }
508 . . .
509 }
510
511 This dovetails with a standard cancel routine:
512
513 VOID CancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp)
514 {
515 if (DeviceObject->CurrentIrp == Irp)
516 {
517 IoReleaseCancelSpinLock(Irp->CancelIrql);
518 IoStartNextPacket(DeviceObject, TRUE);
519 }
520 else
521 {
522 KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,
523 &Irp->Tail.Overlay.DeviceQueueEntry);
524 IoReleaseCancelSpinLock(Irp->CancelIrql);
525 }
526 Irp->IoStatus.Status = STATUS_CANCELLED;
527 Irp->IoStatus.Information = 0;
528 IoCompleteRequest(Irp, IO_NO_INCREMENT);
529 }
530
531 You need to remember that the C language specification requires that
532 evaluation of boolean operators short circuit when the result is known.
533 So, if StartIo discovers that the Irp it got as an argument is not the
534 same as CurrentIrp, it will not attempt to evaulate Irp->Cancel.
535
536 Now, as to why this works: StartIo gets called either by IoStartPacket
537 or IoStartNextPacket. Each of them will grab the cancel spin lock and
538 set CurrentIrp, then release the spin lock and call StartIo. If someone
539 should sneak in on another CPU and cancel this very same IRP, your
540 cancel routine will immediately release the spin lock and call
541 IoStartNextPacket. One of two things will then happen. IoStartNextPacket
542 may succeed in getting the cancel spin lock, whereupon it will nullify
543 the CurrentIrp pointer. If another IRP is on the queue, it will remove
544 it from the queue, set CurrentIrp to point to this *new* IRP, release
545 the spin lock, and call StartIo. [You now have two instances of StartIo
546 running on two different CPUs for two different IRPs, but it's not a
547 problem because they won't be able to interfere with each other.]
548 Meanwhile, your original instance of StartIo gets the cancel spin lock
549 and sees that CurrentIrp is not equal to the IRP pointer it got as an
550 argument, so it gives up.
551
552 The second way this could play out is that StartIo gets the cancel lock
553 before IoStartNextPacket does. In this case, CurrentIrp is still
554 pointing to the IRP that's in the process of being cancelled and that
555 StartIo got as an argument. But this IRP hasn't been completed yet (the
556 CPU that's running your cancel routine is spinning inside
557 IoStartNextPacket and therefore hasn't gotten to calling
558 IoCompleteRequest yet), so no-one will have been able to call IoFreeIrp
559 to make your pointer invalid.
560
561 People may tell you that you should be using your own queues for IRPs so
562 you can avoid bottlenecking the system on the global cancel spin lock.
563 That's true enough, but doing it correctly with Plug and Play and Power
564 management things in the way is gigantically complicated. There's a
565 sample in the NT 5 beta-2 DDK called CANCEL that shows how to manage
566 your own queue if you don't worry about PNP and POWER. I hear tell of an
567 upcoming MSJ article by a Microsoft developer that may solve the
568 complete problem.
569 -----
570 The END.