|
|
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.