|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: mtaccess.c
9:
10: Abstract:
11:
12: interface functions to lower level driver.
13:
14: Revision History:
15:
16:
17:
18:
19: --*/
20:
21: //
22: // include files
23: //
24:
25: #include <ntddk.h>
26: #include <ntddtape.h>
27: #include "common.h"
28: #include "q117.h"
29: #include "protos.h"
30:
31: #define PAGES_TO_SECTORS(pages) (((pages)*PAGE_SIZE)/BYTES_PER_SECTOR)
32:
33: #define MIN(a,b) ((a)>(b)?(b):(a))
34:
35: STATUS
36: q117ReqIO(
37: IN PIO_REQUEST IoRequest,
38: IN PSEGMENT_BUFFER BufferInfo,
39: IN PQ117_CONTEXT Context
40: )
41:
42: /*++
43:
44: Routine Description:
45:
46: Form an IRP to send to the lower level driver, and send it.
47: For MIPS, allocate sub-requests and break the request into
48: smaller chunks to allow for the 4K DMA limitation of the MIPS
49: box.
50:
51:
52: Arguments:
53:
54: IoRequest - Original request
55:
56: BufferInfo - If a DMA is involved, this contains information about the
57: associated memory for DMA.
58:
59: Context - Context of the driver.
60:
61: Return Value:
62:
63: --*/
64:
65: {
66: PIO_STACK_LOCATION irpStack;
67: PIRP irp;
68: #ifdef BUFFER_SPLIT
69: BOOLEAN secondary = FALSE;
70: PVOID address;
71: PIO_REQUEST subRequest;
72: IO_REQUEST requestCopy;
73: PKEVENT pevent;
74: ULONG mask;
75: ULONG numberOfPagesInTransfer;
76: BOOLEAN needToSplit;
77: ULONG sectorsToTransfer;
78: ULONG maxSplits;
79: #endif
80:
81:
82: IoRequest->BufferInfo = BufferInfo;
83:
84: #ifdef BUFFER_SPLIT
85:
86: needToSplit = FALSE;
87:
88: if (BufferInfo) {
89: numberOfPagesInTransfer = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
90: IoRequest->Data,
91: IoRequest->Number * BYTES_PER_SECTOR );
92:
93: if ( numberOfPagesInTransfer >
94: Context->AdapterInfo->NumberOfMapRegisters ) {
95:
96: needToSplit = TRUE;
97: maxSplits =
98: (numberOfPagesInTransfer /
99: Context->AdapterInfo->NumberOfMapRegisters) + 1;
100:
101: }
102: }
103:
104: #endif
105:
106:
107: #if DBG
108: if (BufferInfo) {
109: //
110: // Check to make sure the buffer information is for the data pointer
111: // we recieved.
112: // If not, then there is a real problem with the calling function.
113: // We need to check this so we don't page fault the system when a bug
114: // occurs.
115: //
116: if (BufferInfo->logical < IoRequest->Data ||
117: ((PUCHAR)(IoRequest->Data) + (IoRequest->Number * BYTES_PER_SECTOR)) >
118: ((PUCHAR)(BufferInfo->logical) + BYTES_PER_SEGMENT) ) {
119:
120: CheckedDump(QIC117DBGP,("Buffer pointer out of range\n"));
121:
122: return FCodeErr;
123:
124: }
125: }
126: #endif
127:
128:
129: #ifdef BUFFER_SPLIT
130:
131: //
132: // For MIPS we must split the request into 4K DMA requests because
133: // the MIPS will not transfer more than 4K at a time.
134: //
135:
136: if (BufferInfo && IoRequest->Command != DFmt && needToSplit) {
137:
138: address = IoRequest->Data;
139:
140: //
141: // Split request into chunks
142: //
143: subRequest = ExAllocatePool(NonPagedPool,
144: sizeof(*IoRequest)*maxSplits);
145:
146: CheckedDump(QIC117INFO,("q117ReqIO: Allocating %d subreqs\n", maxSplits));
147:
148: IoRequest->Next = subRequest;
149: IoRequest->Status = SplitRequests;
150:
151: requestCopy = *IoRequest;
152:
153: #if DBG
154: CheckedDump(QIC117SHOWTD,("*************************", requestCopy.Block ));
155: CheckedDump(QIC117SHOWTD,("IoRequest->Block %x\n", requestCopy.Block ));
156: CheckedDump(QIC117SHOWTD,("IoRequest->Number %x\n", requestCopy.Number ));
157: CheckedDump(QIC117SHOWTD,("IoRequest->Data %x\n", requestCopy.Data ));
158: CheckedDump(QIC117SHOWTD,("IoRequest->BadList %x\n", requestCopy.BadList ));
159: CheckedDump(QIC117SHOWTD,("IoRequest->RetryList %x\n", requestCopy.RetryList ));
160: CheckedDump(QIC117SHOWTD,("IoRequest->Command %x\n\n", requestCopy.Command ));
161: #endif
162:
163: while (requestCopy.Number) {
164:
165: //
166: // Make a copy of the current request
167: //
168: *subRequest = requestCopy;
169:
170: //
171: // there aren't enough map registers to handle the whole
172: // transfer so cap the transfer at the number of map registers
173: // we have
174: //
175:
176: sectorsToTransfer =
177: PAGES_TO_SECTORS(Context->AdapterInfo->NumberOfMapRegisters);
178:
179: //
180: // Perform the lesser of the two for this request
181: //
182: subRequest->Number = (UCHAR)
183: MIN(sectorsToTransfer, (ULONG)subRequest->Number);
184:
185: CheckedDump(QIC117SHOWTD,("Split at %d sectors\n", subRequest->Number));
186:
187: //
188: // Adjust the current request to be the remainder of request
189: //
190: (PCHAR)requestCopy.Data += subRequest->Number * BYTES_PER_SECTOR;
191: requestCopy.Block += subRequest->Number;
192: requestCopy.Number -= subRequest->Number;
193: requestCopy.BadList >>= subRequest->Number;
194: requestCopy.RetryList >>= subRequest->Number;
195:
196: mask = ~(0xffffffff << subRequest->Number);
197: requestCopy.BadList &= mask;
198: requestCopy.RetryList &= mask;
199:
200:
201: //
202: // use IoRequest.DoneEvent on last request so that all requests
203: // up to the last one are done before event is set
204: //
205: pevent = requestCopy.Number ?
206: &subRequest->DoneEvent : &IoRequest->DoneEvent;
207:
208: KeInitializeEvent(
209: pevent,
210: NotificationEvent,
211: FALSE);
212:
213:
214: irp = IoBuildDeviceIoControlRequest(
215: IOCTL_QIC117_DRIVE_REQUEST,
216: Context->q117iDeviceObject,
217: NULL,
218: 0,
219: NULL,
220: 0,
221: TRUE,
222: pevent,
223: &subRequest->IoStatus
224: );
225:
226:
227: if (irp == NULL) {
228:
229: CheckedDump(QIC117DBGP,("q117ReqIO: Can't allocate Irp\n"));
230:
231: //
232: // If an Irp can't be allocated, then this call will
233: // simply return. This will leave the queue frozen for
234: // this device, which means it can no longer be accessed.
235: //
236:
237: return FCodeErr;
238: }
239:
240:
241:
242: //
243: // Build mdl
244: //
245: irp->MdlAddress = IoAllocateMdl(
246: address,
247: subRequest->Number * BYTES_PER_SECTOR,
248: secondary,
249: FALSE, // no charge of quota
250: NULL // no irp
251: );
252:
253: (PCHAR)address += subRequest->Number * BYTES_PER_SECTOR;
254: secondary = TRUE;
255:
256: if (irp->MdlAddress == NULL) {
257:
258: CheckedDump(QIC117DBGP,("q117ReqIO: Can't allocate MDL\n"));
259:
260: //
261: // If a MDL can't be allocated, then this call will
262: // simply return. This will leave the queue frozen for
263: // this device, which means it can no longer be accessed.
264: //
265:
266: IoFreeIrp(irp);
267:
268: return FCodeErr;
269: }
270:
271: MmBuildMdlForNonPagedPool(irp->MdlAddress);
272:
273: //
274: // Get Q117I's stack location and store IoRequest for it's use
275: //
276:
277: irpStack = IoGetNextIrpStackLocation(irp);
278: irpStack->Parameters.DeviceIoControl.Type3InputBuffer = subRequest;
279:
280: #if DBG
281: CheckedDump(QIC117SHOWTD,("subRequest->Block %x\n", subRequest->Block ));
282: CheckedDump(QIC117SHOWTD,("subRequest->Number %x\n", subRequest->Number ));
283: CheckedDump(QIC117SHOWTD,("subRequest->Data %x\n", subRequest->Data ));
284: CheckedDump(QIC117SHOWTD,("subRequest->BadList %x\n", subRequest->BadList ));
285: CheckedDump(QIC117SHOWTD,("subRequest->RetryList %x\n", subRequest->RetryList ));
286: CheckedDump(QIC117SHOWTD,("subRequest->Command %x\n\n", subRequest->Command ));
287: #endif
288: (VOID)IoCallDriver(Context->q117iDeviceObject, irp);
289:
290: CheckedDump(QIC117INFO,("q117ReqIO: Sending subreq\n"));
291:
292: //
293: // point to the next sub-request to make
294: //
295: ++subRequest;
296: }
297:
298: } else {
299:
300: #endif // BUFFER_SPLIT
301:
302: IoRequest->Status = InQue;
303:
304: KeInitializeEvent(
305: &IoRequest->DoneEvent,
306: NotificationEvent,
307: FALSE);
308:
309: irp = IoBuildDeviceIoControlRequest(
310: IOCTL_QIC117_DRIVE_REQUEST,
311: Context->q117iDeviceObject,
312: NULL,
313: 0,
314: NULL,
315: 0,
316: TRUE,
317: &IoRequest->DoneEvent,
318: &IoRequest->IoStatus
319: );
320:
321:
322: if (irp == NULL) {
323:
324: CheckedDump(QIC117DBGP,("q117ReqIO: Can't allocate Irp\n"));
325:
326: //
327: // If an Irp can't be allocated, then this call will
328: // simply return. This will leave the queue frozen for
329: // this device, which means it can no longer be accessed.
330: //
331:
332: return FCodeErr;
333: }
334:
335:
336:
337: //
338: // If we have buffer information
339: //
340: if (BufferInfo) {
341:
342: irp->MdlAddress = IoAllocateMdl(
343: IoRequest->Data,
344: IoRequest->Number * BYTES_PER_SECTOR,
345: FALSE, // not a secondary buffer
346: FALSE, // no charge of quota
347: NULL // no irp
348: );
349:
350: if (irp->MdlAddress == NULL) {
351:
352: CheckedDump(QIC117DBGP,("q117ReqIO: Can't allocate MDL\n"));
353:
354: //
355: // If a MDL can't be allocated, then this call will
356: // simply return. This will leave the queue frozen for
357: // this device, which means it can no longer be accessed.
358: //
359:
360: IoFreeIrp(irp);
361:
362: return FCodeErr;
363: }
364: MmBuildMdlForNonPagedPool(irp->MdlAddress);
365: }
366:
367:
368:
369: //
370: // Get Q117I's stack location and store IoRequest for it's use
371: //
372:
373: irpStack = IoGetNextIrpStackLocation(irp);
374: irpStack->Parameters.DeviceIoControl.Type3InputBuffer = IoRequest;
375:
376: IoCallDriver(Context->q117iDeviceObject, irp);
377:
378: #ifdef BUFFER_SPLIT
379: }
380: #endif // BUFFER_SPLIT
381:
382: return NoErr;
383:
384: }
385:
386: STATUS
387: q117WaitIO(
388: IN PIO_REQUEST IoRequest,
389: IN PQ117_CONTEXT Context
390: )
391:
392: /*++
393:
394: Routine Description:
395:
396: Wait for an I/O request to complete. If a MIPS machine,
397: coalesce the sub-requests into the original request.
398:
399: Arguments:
400:
401: IoRequest -
402:
403: Return Value:
404:
405: --*/
406:
407: {
408: CheckedDump(QIC117INFO,("WaitIO(%x,%x,%x) ... ", IoRequest->Command,IoRequest->Block,IoRequest->Status));
409:
410: KeWaitForSingleObject(
411: &IoRequest->DoneEvent,
412: Suspended,
413: KernelMode,
414: FALSE,
415: NULL);
416:
417: #ifdef BUFFER_SPLIT
418:
419: if (IoRequest->Status == SplitRequests) {
420: PIO_REQUEST subRequest;
421: ULONG blocksLeft,mask,slot;
422:
423: CheckedDump(QIC117INFO,("Got split request\n"));
424:
425: subRequest = IoRequest->Next;
426: blocksLeft = IoRequest->Number;
427:
428: //
429: // Zero accumulating fields
430: //
431:
432: IoRequest->BadList = IoRequest->RetryList = 0;
433: IoRequest->Status = NoErr;
434:
435: //
436: // Loop through all sub-requests and build the resultant request
437: //
438: while (blocksLeft) {
439:
440: #if DBG
441: CheckedDump(QIC117SHOWTD,("subRequest(%x)\n",subRequest));
442: CheckedDump(QIC117SHOWTD,("subRequest->Block %x\n", subRequest->Block ));
443: CheckedDump(QIC117SHOWTD,("subRequest->Number %x\n", subRequest->Number ));
444: CheckedDump(QIC117SHOWTD,("subRequest->Data %x\n", subRequest->Data ));
445: CheckedDump(QIC117SHOWTD,("subRequest->BadList %x\n", subRequest->BadList ));
446: CheckedDump(QIC117SHOWTD,("subRequest->RetryList %x\n", subRequest->RetryList ));
447: CheckedDump(QIC117SHOWTD,("subRequest->Command %x\n", subRequest->Command ));
448: CheckedDump(QIC117SHOWTD,("subRequest->Status %x\n", subRequest->Status ));
449: #endif
450:
451: //
452: // Create mask and calculate bit shift (slot) for each
453: // sub-request
454: //
455: mask = ~(0xffffffff << subRequest->Number);
456: slot = subRequest->Block - IoRequest->Block;
457:
458: CheckedDump(QIC117SHOWTD,("mask=%08lx slot=%x\n",mask,slot));
459:
460: //
461: // Coalesce the bad sector and retry bitfields
462: //
463: IoRequest->BadList |= (subRequest->BadList & mask) << slot;
464: IoRequest->RetryList |= (subRequest->RetryList & mask) << slot;
465:
466: if (subRequest->Status == NewCart) {
467: //
468: // Saw new cart, so set need loaded flag
469: //
470: Context->CurrentTape.State = NeedInfoLoaded;
471: CheckedDump(QIC117SHOWTD,("New Cart Detected\n"));
472:
473: }
474:
475: //
476: // Ignore BadBlk errors (but report them)
477: //
478: if (subRequest->Status == BadBlk) {
479:
480: IoRequest->Status = subRequest->Status;
481: subRequest->Status = NoErr;
482:
483: }
484:
485: if (subRequest->Status != NoErr) {
486:
487: blocksLeft = 0;
488: IoRequest->Status = subRequest->Status;
489:
490: } else {
491:
492: blocksLeft -= subRequest->Number;
493:
494: }
495:
496: //
497: // point to the next sub-request to process
498: //
499: ++subRequest;
500: }
501:
502: //
503: // Free the sub-requests for this I/O request
504: //
505: ExFreePool(IoRequest->Next);
506:
507: #if DBG
508: CheckedDump(QIC117SHOWTD,("IoRequest->Status %x\n", IoRequest->Status ));
509: CheckedDump(QIC117SHOWTD,("IoRequest->Block %x\n", IoRequest->Block ));
510: CheckedDump(QIC117SHOWTD,("IoRequest->Number %x\n", IoRequest->Number ));
511: CheckedDump(QIC117SHOWTD,("IoRequest->Data %x\n", IoRequest->Data ));
512: CheckedDump(QIC117SHOWTD,("IoRequest->BadList %x\n", IoRequest->BadList ));
513: CheckedDump(QIC117SHOWTD,("IoRequest->RetryList %x\n", IoRequest->RetryList ));
514: CheckedDump(QIC117SHOWTD,("IoRequest->Command %x\n", IoRequest->Command ));
515: #endif
516: }
517:
518: if (IoRequest->Status == NewCart) {
519: //
520: // Saw new cart, so set need loaded flag
521: //
522: Context->CurrentTape.State = NeedInfoLoaded;
523: CheckedDump(QIC117SHOWTD,("New Cart Detected\n"));
524:
525: }
526:
527: #endif // BUFFER_SPLIT
528:
529: #if DBG
530: if (IoRequest->Status == BadBlk) {
531: CheckedDump(QIC117INFO,("bbm: %x ", IoRequest->BadList));
532: }
533: #endif
534: CheckedDump(QIC117INFO,("waitio status %x\n", IoRequest->Status));
535:
536: return NoErr;
537: }
538:
539: STATUS
540: q117DoIO(
541: IN PIO_REQUEST IoRequest,
542: IN PSEGMENT_BUFFER BufferInfo,
543: IN PQ117_CONTEXT Context
544: )
545:
546: /*++
547:
548: Routine Description:
549:
550:
551: Arguments:
552:
553: IoRequest -
554:
555: BufferInfo -
556:
557: Context -
558:
559: Return Value:
560:
561: --*/
562:
563: {
564: STATUS ret;
565:
566: CheckedDump(QIC117INFO,("DoIO called (%x)\n", IoRequest->Command));
567:
568: ret = q117ReqIO(IoRequest, BufferInfo, Context);
569: if (!ret) {
570: ret = q117WaitIO(IoRequest, Context);
571: }
572: return ret;
573: }
574:
575: STATUS
576: q117AbortIo(
577: IN PQ117_CONTEXT Context,
578: IN PKEVENT DoneEvent,
579: IN PIO_STATUS_BLOCK IoStatus
580: )
581:
582: /*++
583:
584: Routine Description:
585:
586:
587: Arguments:
588:
589: Context -
590:
591: DoneEvent -
592:
593: IoStatus -
594:
595: Return Value:
596:
597: --*/
598:
599: {
600: PIRP irp;
601:
602:
603: CheckedDump(QIC117INFO,("ClearIO Called\n"));
604:
605: KeInitializeEvent(
606: DoneEvent,
607: NotificationEvent,
608: FALSE);
609:
610: irp = IoBuildDeviceIoControlRequest(
611: IOCTL_QIC117_CLEAR_QUEUE,
612: Context->q117iDeviceObject,
613: NULL,
614: 0,
615: NULL,
616: 0,
617: TRUE,
618: DoneEvent,
619: IoStatus
620: );
621:
622:
623: if (irp == NULL) {
624:
625: CheckedDump(QIC117DBGP,("q117ClearIO: Can't allocate Irp\n"));
626:
627: //
628: // If an Irp can't be allocated, then this call will
629: // simply return. This will leave the queue frozen for
630: // this device, which means it can no longer be accessed.
631: //
632:
633: return FCodeErr;
634: }
635:
636:
637: (VOID)IoCallDriver(Context->q117iDeviceObject, irp);
638:
639: return NoErr;
640: }
641:
642: STATUS
643: q117AbortIoDone(
644: IN PQ117_CONTEXT Context,
645: IN PKEVENT DoneEvent
646: )
647:
648: /*++
649:
650: Routine Description:
651:
652:
653: Arguments:
654:
655: Context -
656:
657: DoneEvent -
658:
659: Return Value:
660:
661: --*/
662:
663: {
664:
665: //
666: // wait for the driver to complete request
667: //
668:
669: KeWaitForSingleObject(
670: DoneEvent,
671: Suspended,
672:
673: KernelMode,
674: FALSE,
675: NULL);
676:
677: return NoErr;
678: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.